source: mainline/uspace/lib/ext4/libext4_balloc.c@ b73530a

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

appending fblock to existing extent

  • actually not solved situation, when extent is full !!!
  • Property mode set to 100644
File size: 18.2 KB
RevLine 
[2674db6]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
[b12ca16]33/**
34 * @file libext4_balloc.c
[e63ce679]35 * @brief Physical block allocator.
[b12ca16]36 */
37
[2674db6]38#include <errno.h>
39#include <sys/types.h>
40#include "libext4.h"
41
[b12ca16]42static uint32_t ext4_balloc_blockaddr2_index_in_group(ext4_superblock_t *sb,
43 uint32_t block_addr)
[2674db6]44{
[b12ca16]45 uint32_t blocks_per_group = ext4_superblock_get_blocks_per_group(sb);
46 uint32_t first_block = ext4_superblock_get_first_data_block(sb);
[2674db6]47
[b12ca16]48 // First block == 0 or 1
49 if (first_block == 0) {
50 return block_addr % blocks_per_group;
51 } else {
52 return (block_addr - 1) % blocks_per_group;
53 }
54}
55
56static uint32_t ext4_balloc_index_in_group2blockaddr(ext4_superblock_t *sb,
57 uint32_t index, uint32_t bgid)
58{
59 uint32_t blocks_per_group = ext4_superblock_get_blocks_per_group(sb);
60
61 if (ext4_superblock_get_first_data_block(sb) == 0) {
62 return bgid * blocks_per_group + index;
63 } else {
64 return bgid * blocks_per_group + index + 1;
65 }
66
67}
68
69static uint32_t ext4_balloc_get_bgid_of_block(ext4_superblock_t *sb,
70 uint32_t block_addr)
71{
72 uint32_t blocks_per_group = ext4_superblock_get_blocks_per_group(sb);
73 uint32_t first_block = ext4_superblock_get_first_data_block(sb);
[2674db6]74
75 // First block == 0 or 1
76 if (first_block == 0) {
[b12ca16]77 return block_addr / blocks_per_group;
[2674db6]78 } else {
[b12ca16]79 return (block_addr - 1) / blocks_per_group;
[2674db6]80 }
[b12ca16]81}
82
83
[1ac1ab4]84int ext4_balloc_free_block(ext4_inode_ref_t *inode_ref, uint32_t block_addr)
[b12ca16]85{
86 int rc;
[2674db6]87
[1ac1ab4]88 ext4_filesystem_t *fs = inode_ref->fs;
89 ext4_superblock_t *sb = fs->superblock;
90
91 uint32_t block_group = ext4_balloc_get_bgid_of_block(sb, block_addr);
92 uint32_t index_in_group = ext4_balloc_blockaddr2_index_in_group(sb, block_addr);
[b12ca16]93
94 ext4_block_group_ref_t *bg_ref;
[2674db6]95 rc = ext4_filesystem_get_block_group_ref(fs, block_group, &bg_ref);
96 if (rc != EOK) {
[b12ca16]97 EXT4FS_DBG("error in loading bg_ref \%d", rc);
[2674db6]98 return rc;
99 }
100
[fe27eb4]101 uint32_t bitmap_block_addr = ext4_block_group_get_block_bitmap(
[1ac1ab4]102 bg_ref->block_group, sb);
[b12ca16]103 block_t *bitmap_block;
104 rc = block_get(&bitmap_block, fs->device, bitmap_block_addr, 0);
[2674db6]105 if (rc != EOK) {
[b12ca16]106 EXT4FS_DBG("error in loading bitmap \%d", rc);
[2674db6]107 return rc;
108 }
109
[b12ca16]110 ext4_bitmap_free_bit(bitmap_block->data, index_in_group);
111 bitmap_block->dirty = true;
[2674db6]112
[b12ca16]113 rc = block_put(bitmap_block);
[2674db6]114 if (rc != EOK) {
[b12ca16]115 // Error in saving bitmap
116 ext4_filesystem_put_block_group_ref(bg_ref);
117 EXT4FS_DBG("error in saving bitmap \%d", rc);
[2674db6]118 return rc;
119 }
120
[1ac1ab4]121 uint32_t block_size = ext4_superblock_get_block_size(sb);
[b12ca16]122
[ae3d4f8]123 // Update superblock free blocks count
[1ac1ab4]124 uint32_t sb_free_blocks = ext4_superblock_get_free_blocks_count(sb);
[662bd71]125 sb_free_blocks++;
[1ac1ab4]126 ext4_superblock_set_free_blocks_count(sb, sb_free_blocks);
[ae3d4f8]127
128 // Update inode blocks count
[1ac1ab4]129 uint64_t ino_blocks = ext4_inode_get_blocks_count(sb, inode_ref->inode);
[2674db6]130 ino_blocks -= block_size / EXT4_INODE_BLOCK_SIZE;
[1ac1ab4]131 ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks);
[2674db6]132 inode_ref->dirty = true;
133
[ae3d4f8]134 // Update block group free blocks count
[fe27eb4]135 uint32_t free_blocks = ext4_block_group_get_free_blocks_count(
[1ac1ab4]136 bg_ref->block_group, sb);
[2674db6]137 free_blocks++;
[fe27eb4]138 ext4_block_group_set_free_blocks_count(bg_ref->block_group,
[1ac1ab4]139 sb, free_blocks);
[2674db6]140 bg_ref->dirty = true;
141
142 rc = ext4_filesystem_put_block_group_ref(bg_ref);
143 if (rc != EOK) {
144 EXT4FS_DBG("error in saving bg_ref \%d", rc);
145 return rc;
146 }
147
148 return EOK;
149}
150
[662bd71]151int ext4_balloc_free_blocks(ext4_inode_ref_t *inode_ref,
152 uint32_t first, uint32_t count)
153{
154 int rc;
155
156 ext4_filesystem_t *fs = inode_ref->fs;
157 ext4_superblock_t *sb = fs->superblock;
158
159 uint32_t block_group_first =
160 ext4_balloc_get_bgid_of_block(sb, first);
161 uint32_t block_group_last =
[3e2952b]162 ext4_balloc_get_bgid_of_block(sb, first + count - 1);
[662bd71]163
[3e2952b]164 assert(block_group_first == block_group_last);
[662bd71]165
[c6a44a3]166 ext4_block_group_ref_t *bg_ref;
[662bd71]167 rc = ext4_filesystem_get_block_group_ref(fs, block_group_first, &bg_ref);
168 if (rc != EOK) {
169 EXT4FS_DBG("error in loading bg_ref \%d", rc);
170 return rc;
171 }
172
173 uint32_t index_in_group_first =
174 ext4_balloc_blockaddr2_index_in_group(sb, first);
175
176 uint32_t bitmap_block_addr = ext4_block_group_get_block_bitmap(
177 bg_ref->block_group, sb);
178
179 block_t *bitmap_block;
180 rc = block_get(&bitmap_block, fs->device, bitmap_block_addr, 0);
181 if (rc != EOK) {
182 EXT4FS_DBG("error in loading bitmap \%d", rc);
183 return rc;
184 }
185
186 ext4_bitmap_free_bits(bitmap_block->data, index_in_group_first, count);
187
188 bitmap_block->dirty = true;
189
190 rc = block_put(bitmap_block);
191 if (rc != EOK) {
192 // Error in saving bitmap
193 ext4_filesystem_put_block_group_ref(bg_ref);
194 EXT4FS_DBG("error in saving bitmap \%d", rc);
195 return rc;
196 }
197
198 uint32_t block_size = ext4_superblock_get_block_size(sb);
199
200 // Update superblock free blocks count
201 uint32_t sb_free_blocks = ext4_superblock_get_free_blocks_count(sb);
202 sb_free_blocks += count;
203 ext4_superblock_set_free_blocks_count(sb, sb_free_blocks);
204
205 // Update inode blocks count
206 uint64_t ino_blocks = ext4_inode_get_blocks_count(sb, inode_ref->inode);
207 ino_blocks -= count * (block_size / EXT4_INODE_BLOCK_SIZE);
208 ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks);
209 inode_ref->dirty = true;
210
211 // Update block group free blocks count
212 uint32_t free_blocks = ext4_block_group_get_free_blocks_count(
213 bg_ref->block_group, sb);
214 free_blocks += count;
215 ext4_block_group_set_free_blocks_count(bg_ref->block_group,
216 sb, free_blocks);
217 bg_ref->dirty = true;
218
219 rc = ext4_filesystem_put_block_group_ref(bg_ref);
220 if (rc != EOK) {
221 EXT4FS_DBG("error in saving bg_ref \%d", rc);
222 return rc;
223 }
224
225 return EOK;
226}
227
[b12ca16]228static uint32_t ext4_balloc_get_first_data_block_in_group(
229 ext4_superblock_t *sb, ext4_block_group_t *bg, uint32_t bgid)
230{
231 uint32_t block_group_count = ext4_superblock_get_block_group_count(sb);
[fe27eb4]232 uint32_t inode_table_first_block = ext4_block_group_get_inode_table_first_block(
233 bg, sb);
[b12ca16]234 uint16_t inode_table_item_size = ext4_superblock_get_inode_size(sb);
235 uint32_t inodes_per_group = ext4_superblock_get_inodes_per_group(sb);
236 uint32_t block_size = ext4_superblock_get_block_size(sb);
237 uint32_t inode_table_bytes;
238
239 if (bgid < block_group_count - 1) {
240 inode_table_bytes = inodes_per_group * inode_table_item_size;
241 } else {
242 // last block group could be smaller
243 uint32_t inodes_count_total = ext4_superblock_get_inodes_count(sb);
244 inode_table_bytes =
245 (inodes_count_total - ((block_group_count - 1) * inodes_per_group))
246 * inode_table_item_size;
247 }
248
249 uint32_t inode_table_blocks = inode_table_bytes / block_size;
250
251 if (inode_table_bytes % block_size) {
252 inode_table_blocks++;
253 }
254
255 return inode_table_first_block + inode_table_blocks;
256}
257
[2674db6]258
[1ac1ab4]259static uint32_t ext4_balloc_find_goal(ext4_inode_ref_t *inode_ref)
[2674db6]260{
[b12ca16]261 int rc;
[2674db6]262 uint32_t goal = 0;
263
[1ac1ab4]264 ext4_superblock_t *sb = inode_ref->fs->superblock;
265
266 uint64_t inode_size = ext4_inode_get_size(sb, inode_ref->inode);
267 uint32_t block_size = ext4_superblock_get_block_size(sb);
[2674db6]268 uint32_t inode_block_count = inode_size / block_size;
269
270 if (inode_size % block_size != 0) {
271 inode_block_count++;
272 }
273
274 if (inode_block_count > 0) {
275
[95947d24]276 rc = ext4_filesystem_get_inode_data_block_index(inode_ref, inode_block_count - 1, &goal);
277 if (rc != EOK) {
278 return 0;
279 }
280
281 if (goal != 0) {
282 goal++;
283 return goal;
284 }
[b12ca16]285
[95947d24]286 // if goal == 0, sparse file -> continue
[2674db6]287 }
288
289 // Identify block group of inode
[1ac1ab4]290 uint32_t inodes_per_group = ext4_superblock_get_inodes_per_group(sb);
[2674db6]291 uint32_t block_group = (inode_ref->index - 1) / inodes_per_group;
[1ac1ab4]292 block_size = ext4_superblock_get_block_size(sb);
[2674db6]293
294 ext4_block_group_ref_t *bg_ref;
[1ac1ab4]295 rc = ext4_filesystem_get_block_group_ref(inode_ref->fs, block_group, &bg_ref);
[2674db6]296 if (rc != EOK) {
297 return 0;
298 }
299
[1ac1ab4]300 uint32_t block_group_count = ext4_superblock_get_block_group_count(sb);
[fe27eb4]301 uint32_t inode_table_first_block = ext4_block_group_get_inode_table_first_block(
[1ac1ab4]302 bg_ref->block_group, sb);
303 uint16_t inode_table_item_size = ext4_superblock_get_inode_size(sb);
[b12ca16]304 uint32_t inode_table_bytes;
305
306 if (block_group < block_group_count - 1) {
307 inode_table_bytes = inodes_per_group * inode_table_item_size;
308 } else {
309 // last block group could be smaller
[1ac1ab4]310 uint32_t inodes_count_total = ext4_superblock_get_inodes_count(sb);
[b12ca16]311 inode_table_bytes =
312 (inodes_count_total - ((block_group_count - 1) * inodes_per_group))
313 * inode_table_item_size;
314 }
315
[2674db6]316 uint32_t inode_table_blocks = inode_table_bytes / block_size;
317
318 if (inode_table_bytes % block_size) {
319 inode_table_blocks++;
320 }
321
322 goal = inode_table_first_block + inode_table_blocks;
323
324 ext4_filesystem_put_block_group_ref(bg_ref);
325
326 return goal;
327}
328
[1ac1ab4]329int ext4_balloc_alloc_block(
[412f813]330 ext4_inode_ref_t *inode_ref, uint32_t *fblock)
[2674db6]331{
332 int rc;
[b12ca16]333 uint32_t allocated_block = 0;
334
[528e5b3]335 uint32_t bitmap_block_addr;
336 block_t *bitmap_block;
[2674db6]337 uint32_t rel_block_idx = 0;
338
[b12ca16]339 // Find GOAL
[1ac1ab4]340 uint32_t goal = ext4_balloc_find_goal(inode_ref);
[2674db6]341 if (goal == 0) {
[95947d24]342 // no goal found => partition is full
[2674db6]343 EXT4FS_DBG("ERRORR (goal == 0)");
[b12ca16]344 return ENOSPC;
[2674db6]345 }
346
[1ac1ab4]347 ext4_superblock_t *sb = inode_ref->fs->superblock;
348
[b12ca16]349 // Load block group number for goal and relative index
[1ac1ab4]350 uint32_t block_group = ext4_balloc_get_bgid_of_block(sb, goal);
351 uint32_t index_in_group = ext4_balloc_blockaddr2_index_in_group(sb, goal);
[2674db6]352
353
[b12ca16]354 ext4_block_group_ref_t *bg_ref;
[1ac1ab4]355 rc = ext4_filesystem_get_block_group_ref(inode_ref->fs, block_group, &bg_ref);
[2674db6]356 if (rc != EOK) {
[b12ca16]357 EXT4FS_DBG("initial BG ref not loaded");
[2674db6]358 return rc;
359 }
360
[b12ca16]361 uint32_t first_in_group =
[1ac1ab4]362 ext4_balloc_get_first_data_block_in_group(sb,
[b12ca16]363 bg_ref->block_group, block_group);
364
[528e5b3]365 uint32_t first_in_group_index = ext4_balloc_blockaddr2_index_in_group(
[1ac1ab4]366 sb, first_in_group);
[528e5b3]367
368 if (index_in_group < first_in_group_index) {
369 index_in_group = first_in_group_index;
[b12ca16]370 }
371
[2674db6]372 // Load bitmap
[fe27eb4]373 bitmap_block_addr = ext4_block_group_get_block_bitmap(bg_ref->block_group,
[1ac1ab4]374 sb);
[2674db6]375
[1ac1ab4]376 rc = block_get(&bitmap_block, inode_ref->fs->device, bitmap_block_addr, 0);
[2674db6]377 if (rc != EOK) {
378 ext4_filesystem_put_block_group_ref(bg_ref);
[b12ca16]379 EXT4FS_DBG("initial bitmap not loaded");
[2674db6]380 return rc;
381 }
382
[b12ca16]383 // Check if goal is free
[528e5b3]384 if (ext4_bitmap_is_free_bit(bitmap_block->data, index_in_group)) {
385 ext4_bitmap_set_bit(bitmap_block->data, index_in_group);
386 bitmap_block->dirty = true;
387 rc = block_put(bitmap_block);
[2674db6]388 if (rc != EOK) {
[95947d24]389 EXT4FS_DBG("goal check: error in saving bitmap \%d", rc);
[b12ca16]390 ext4_filesystem_put_block_group_ref(bg_ref);
391 return rc;
[2674db6]392 }
393
394 allocated_block = goal;
[b12ca16]395 goto success;
[2674db6]396
397 }
398
[1ac1ab4]399 uint32_t blocks_in_group = ext4_superblock_get_blocks_in_group(sb, block_group);
[2674db6]400
[b12ca16]401 uint32_t end_idx = (index_in_group + 63) & ~63;
402 if (end_idx > blocks_in_group) {
403 end_idx = blocks_in_group;
404 }
[2674db6]405
[b12ca16]406 // Try to find free block near to goal
407 for (uint32_t tmp_idx = index_in_group + 1; tmp_idx < end_idx; ++tmp_idx) {
[528e5b3]408 if (ext4_bitmap_is_free_bit(bitmap_block->data, tmp_idx)) {
[2674db6]409
[528e5b3]410 ext4_bitmap_set_bit(bitmap_block->data, tmp_idx);
411 bitmap_block->dirty = true;
412 rc = block_put(bitmap_block);
[2674db6]413 if (rc != EOK) {
[b12ca16]414 EXT4FS_DBG("near blocks: error in saving initial bitmap \%d", rc);
[95947d24]415 return rc;
[2674db6]416 }
417
[b12ca16]418 allocated_block = ext4_balloc_index_in_group2blockaddr(
[1ac1ab4]419 sb, tmp_idx, block_group);
[b12ca16]420
421 goto success;
[2674db6]422 }
423
[b12ca16]424 }
[2674db6]425
426 // Find free BYTE in bitmap
[528e5b3]427 rc = ext4_bitmap_find_free_byte_and_set_bit(bitmap_block->data, index_in_group, &rel_block_idx, blocks_in_group);
[2674db6]428 if (rc == EOK) {
[528e5b3]429 bitmap_block->dirty = true;
430 rc = block_put(bitmap_block);
[2674db6]431 if (rc != EOK) {
[b12ca16]432 EXT4FS_DBG("free byte: error in saving initial bitmap \%d", rc);
[95947d24]433 return rc;
[2674db6]434 }
435
[b12ca16]436 allocated_block = ext4_balloc_index_in_group2blockaddr(
[1ac1ab4]437 sb, rel_block_idx, block_group);
[2674db6]438
[b12ca16]439 goto success;
440 }
[2674db6]441
442 // Find free bit in bitmap
[528e5b3]443 rc = ext4_bitmap_find_free_bit_and_set(bitmap_block->data, index_in_group, &rel_block_idx, blocks_in_group);
[2674db6]444 if (rc == EOK) {
[528e5b3]445 bitmap_block->dirty = true;
446 rc = block_put(bitmap_block);
[2674db6]447 if (rc != EOK) {
[b12ca16]448 EXT4FS_DBG("free bit: error in saving initial bitmap \%d", rc);
[95947d24]449 return rc;
[2674db6]450 }
451
[b12ca16]452 allocated_block = ext4_balloc_index_in_group2blockaddr(
[1ac1ab4]453 sb, rel_block_idx, block_group);
[2674db6]454
[b12ca16]455 goto success;
[2674db6]456 }
457
[e63ce679]458 // No free block found yet
[528e5b3]459 block_put(bitmap_block);
[b12ca16]460 ext4_filesystem_put_block_group_ref(bg_ref);
461
462 // Try other block groups
[1ac1ab4]463 uint32_t block_group_count = ext4_superblock_get_block_group_count(sb);
[b12ca16]464
465 uint32_t bgid = (block_group + 1) % block_group_count;
466 uint32_t count = block_group_count;
467
468 while (count > 0) {
[1ac1ab4]469 rc = ext4_filesystem_get_block_group_ref(inode_ref->fs, bgid, &bg_ref);
[b12ca16]470 if (rc != EOK) {
[95947d24]471 EXT4FS_DBG("ERROR: unable to load block group \%u", bgid);
[b12ca16]472 return rc;
473 }
474
475 // Load bitmap
[fe27eb4]476 bitmap_block_addr = ext4_block_group_get_block_bitmap(
[1ac1ab4]477 bg_ref->block_group, sb);
[b12ca16]478
[1ac1ab4]479 rc = block_get(&bitmap_block, inode_ref->fs->device, bitmap_block_addr, 0);
[b12ca16]480 if (rc != EOK) {
481 ext4_filesystem_put_block_group_ref(bg_ref);
[95947d24]482 EXT4FS_DBG("ERROR: unable to load bitmap block");
[b12ca16]483 return rc;
484 }
485
486 first_in_group = ext4_balloc_get_first_data_block_in_group(
[1ac1ab4]487 sb, bg_ref->block_group, bgid);
488 index_in_group = ext4_balloc_blockaddr2_index_in_group(sb,
[b12ca16]489 first_in_group);
[1ac1ab4]490 blocks_in_group = ext4_superblock_get_blocks_in_group(sb, bgid);
[b12ca16]491
[528e5b3]492 first_in_group_index = ext4_balloc_blockaddr2_index_in_group(
[1ac1ab4]493 sb, first_in_group);
[528e5b3]494
495 if (index_in_group < first_in_group_index) {
496 index_in_group = first_in_group_index;
[b12ca16]497 }
498
[528e5b3]499
500 rc = ext4_bitmap_find_free_byte_and_set_bit(bitmap_block->data, index_in_group, &rel_block_idx, blocks_in_group);
[b12ca16]501 if (rc == EOK) {
[528e5b3]502 bitmap_block->dirty = true;
503 rc = block_put(bitmap_block);
[b12ca16]504 if (rc != EOK) {
[95947d24]505 EXT4FS_DBG("ERROR: unable to save bitmap block");
506 return rc;
[b12ca16]507 }
508
509 allocated_block = ext4_balloc_index_in_group2blockaddr(
[1ac1ab4]510 sb, rel_block_idx, bgid);
[b12ca16]511
512 goto success;
513 }
514
515 // Find free bit in bitmap
[528e5b3]516 rc = ext4_bitmap_find_free_bit_and_set(bitmap_block->data, index_in_group, &rel_block_idx, blocks_in_group);
[b12ca16]517 if (rc == EOK) {
[528e5b3]518 bitmap_block->dirty = true;
519 rc = block_put(bitmap_block);
[b12ca16]520 if (rc != EOK) {
[95947d24]521 EXT4FS_DBG("ERROR: unable to save bitmap block");
522 return rc;
[b12ca16]523 }
524
525 allocated_block = ext4_balloc_index_in_group2blockaddr(
[1ac1ab4]526 sb, rel_block_idx, bgid);
[b12ca16]527
528 goto success;
529 }
530
[2674db6]531
[b12ca16]532 // Next group
[528e5b3]533 block_put(bitmap_block);
[b12ca16]534 ext4_filesystem_put_block_group_ref(bg_ref);
535 bgid = (bgid + 1) % block_group_count;
536 count--;
537 }
538
[2674db6]539 return ENOSPC;
540
[b12ca16]541success:
[528e5b3]542 ; // Empty command - because of syntax
543
[1ac1ab4]544 uint32_t block_size = ext4_superblock_get_block_size(sb);
[b12ca16]545
[ae3d4f8]546 // Update superblock free blocks count
[1ac1ab4]547 uint32_t sb_free_blocks = ext4_superblock_get_free_blocks_count(sb);
[ae3d4f8]548 sb_free_blocks--;
[1ac1ab4]549 ext4_superblock_set_free_blocks_count(sb, sb_free_blocks);
[2674db6]550
[ae3d4f8]551 // Update inode blocks (different block size!) count
[412f813]552
[1ac1ab4]553 uint64_t ino_blocks = ext4_inode_get_blocks_count(sb, inode_ref->inode);
[2674db6]554 ino_blocks += block_size / EXT4_INODE_BLOCK_SIZE;
[1ac1ab4]555 ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks);
[2674db6]556 inode_ref->dirty = true;
557
[ae3d4f8]558 // Update block group free blocks count
[fe27eb4]559 uint32_t bg_free_blocks = ext4_block_group_get_free_blocks_count(
[1ac1ab4]560 bg_ref->block_group, sb);
[2674db6]561 bg_free_blocks--;
[1ac1ab4]562 ext4_block_group_set_free_blocks_count(bg_ref->block_group, sb, bg_free_blocks);
[2674db6]563 bg_ref->dirty = true;
564
565 ext4_filesystem_put_block_group_ref(bg_ref);
566
567 *fblock = allocated_block;
568 return EOK;
569}
570
[b73530a]571int ext4_balloc_try_alloc_block(ext4_inode_ref_t *inode_ref, uint32_t fblock)
572{
573 int rc;
574
575 ext4_filesystem_t *fs = inode_ref->fs;
576 ext4_superblock_t *sb = fs->superblock;
577
578 uint32_t block_group = ext4_balloc_get_bgid_of_block(sb, fblock);
579 uint32_t index_in_group = ext4_balloc_blockaddr2_index_in_group(sb, fblock);
580
581 ext4_block_group_ref_t *bg_ref;
582 rc = ext4_filesystem_get_block_group_ref(fs, block_group, &bg_ref);
583 if (rc != EOK) {
584 EXT4FS_DBG("error in loading bg_ref \%d", rc);
585 return rc;
586 }
587
588 uint32_t bitmap_block_addr = ext4_block_group_get_block_bitmap(
589 bg_ref->block_group, sb);
590 block_t *bitmap_block;
591 rc = block_get(&bitmap_block, fs->device, bitmap_block_addr, 0);
592 if (rc != EOK) {
593 EXT4FS_DBG("error in loading bitmap \%d", rc);
594 return rc;
595 }
596
597 bool free = ext4_bitmap_is_free_bit(bitmap_block->data, index_in_group);
598
599 if (free) {
600 ext4_bitmap_set_bit(bitmap_block->data, index_in_group);
601 bitmap_block->dirty = true;
602 }
603
604 rc = block_put(bitmap_block);
605 if (rc != EOK) {
606 // Error in saving bitmap
607 ext4_filesystem_put_block_group_ref(bg_ref);
608 EXT4FS_DBG("error in saving bitmap \%d", rc);
609 return rc;
610 }
611
612 if (!free) {
613 rc = EINVAL;
614 goto terminate;
615 }
616
617 uint32_t block_size = ext4_superblock_get_block_size(sb);
618
619 // Update superblock free blocks count
620 uint32_t sb_free_blocks = ext4_superblock_get_free_blocks_count(sb);
621 sb_free_blocks--;
622 ext4_superblock_set_free_blocks_count(sb, sb_free_blocks);
623
624 // Update inode blocks count
625 uint64_t ino_blocks = ext4_inode_get_blocks_count(sb, inode_ref->inode);
626 ino_blocks += block_size / EXT4_INODE_BLOCK_SIZE;
627 ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks);
628 inode_ref->dirty = true;
629
630 // Update block group free blocks count
631 uint32_t free_blocks = ext4_block_group_get_free_blocks_count(
632 bg_ref->block_group, sb);
633 free_blocks--;
634 ext4_block_group_set_free_blocks_count(bg_ref->block_group,
635 sb, free_blocks);
636 bg_ref->dirty = true;
637
638terminate:
639
640 rc = ext4_filesystem_put_block_group_ref(bg_ref);
641 if (rc != EOK) {
642 EXT4FS_DBG("error in saving bg_ref \%d", rc);
643 return rc;
644 }
645
646 return rc;
647}
[2674db6]648
649/**
650 * @}
651 */
Note: See TracBrowser for help on using the repository browser.