source: mainline/uspace/lib/ext4/src/balloc.c@ f1380b7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f1380b7 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 19.1 KB
Line 
1/*
2 * Copyright (c) 2012 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 * @file balloc.c
34 * @brief Physical block allocator.
35 */
36
37#include <errno.h>
38#include <stdint.h>
39#include "ext4/balloc.h"
40#include "ext4/bitmap.h"
41#include "ext4/block_group.h"
42#include "ext4/filesystem.h"
43#include "ext4/inode.h"
44#include "ext4/superblock.h"
45#include "ext4/types.h"
46
47/** Free block.
48 *
49 * @param inode_ref Inode, where the block is allocated
50 * @param block_addr Absolute block address to free
51 *
52 * @return Error code
53 *
54 */
55errno_t ext4_balloc_free_block(ext4_inode_ref_t *inode_ref, uint32_t block_addr)
56{
57 ext4_filesystem_t *fs = inode_ref->fs;
58 ext4_superblock_t *sb = fs->superblock;
59
60 /* Compute indexes */
61 uint32_t block_group = ext4_filesystem_blockaddr2group(sb, block_addr);
62 uint32_t index_in_group =
63 ext4_filesystem_blockaddr2_index_in_group(sb, block_addr);
64
65 /* Load block group reference */
66 ext4_block_group_ref_t *bg_ref;
67 errno_t rc = ext4_filesystem_get_block_group_ref(fs, block_group, &bg_ref);
68 if (rc != EOK)
69 return rc;
70
71 /* Load block with bitmap */
72 uint32_t bitmap_block_addr =
73 ext4_block_group_get_block_bitmap(bg_ref->block_group, sb);
74 block_t *bitmap_block;
75 rc = block_get(&bitmap_block, fs->device, bitmap_block_addr, 0);
76 if (rc != EOK) {
77 ext4_filesystem_put_block_group_ref(bg_ref);
78 return rc;
79 }
80
81 /* Modify bitmap */
82 ext4_bitmap_free_bit(bitmap_block->data, index_in_group);
83 bitmap_block->dirty = true;
84
85 /* Release block with bitmap */
86 rc = block_put(bitmap_block);
87 if (rc != EOK) {
88 /* Error in saving bitmap */
89 ext4_filesystem_put_block_group_ref(bg_ref);
90 return rc;
91 }
92
93 uint32_t block_size = ext4_superblock_get_block_size(sb);
94
95 /* Update superblock free blocks count */
96 uint32_t sb_free_blocks =
97 ext4_superblock_get_free_blocks_count(sb);
98 sb_free_blocks++;
99 ext4_superblock_set_free_blocks_count(sb, sb_free_blocks);
100
101 /* Update inode blocks count */
102 uint64_t ino_blocks =
103 ext4_inode_get_blocks_count(sb, inode_ref->inode);
104 ino_blocks -= block_size / EXT4_INODE_BLOCK_SIZE;
105 ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks);
106 inode_ref->dirty = true;
107
108 /* Update block group free blocks count */
109 uint32_t free_blocks =
110 ext4_block_group_get_free_blocks_count(bg_ref->block_group, sb);
111 free_blocks++;
112 ext4_block_group_set_free_blocks_count(bg_ref->block_group,
113 sb, free_blocks);
114 bg_ref->dirty = true;
115
116 /* Release block group reference */
117 return ext4_filesystem_put_block_group_ref(bg_ref);
118}
119
120static errno_t ext4_balloc_free_blocks_internal(ext4_inode_ref_t *inode_ref,
121 uint32_t first, uint32_t count)
122{
123 ext4_filesystem_t *fs = inode_ref->fs;
124 ext4_superblock_t *sb = fs->superblock;
125
126 /* Compute indexes */
127 uint32_t block_group_first = ext4_filesystem_blockaddr2group(sb,
128 first);
129 uint32_t block_group_last = ext4_filesystem_blockaddr2group(sb,
130 first + count - 1);
131
132 assert(block_group_first == block_group_last);
133
134 /* Load block group reference */
135 ext4_block_group_ref_t *bg_ref;
136 errno_t rc = ext4_filesystem_get_block_group_ref(fs, block_group_first, &bg_ref);
137 if (rc != EOK)
138 return rc;
139
140 uint32_t index_in_group_first =
141 ext4_filesystem_blockaddr2_index_in_group(sb, first);
142
143 /* Load block with bitmap */
144 uint32_t bitmap_block_addr =
145 ext4_block_group_get_block_bitmap(bg_ref->block_group, sb);
146
147 block_t *bitmap_block;
148 rc = block_get(&bitmap_block, fs->device, bitmap_block_addr, 0);
149 if (rc != EOK) {
150 ext4_filesystem_put_block_group_ref(bg_ref);
151 return rc;
152 }
153
154 /* Modify bitmap */
155 ext4_bitmap_free_bits(bitmap_block->data, index_in_group_first, count);
156 bitmap_block->dirty = true;
157
158 /* Release block with bitmap */
159 rc = block_put(bitmap_block);
160 if (rc != EOK) {
161 /* Error in saving bitmap */
162 ext4_filesystem_put_block_group_ref(bg_ref);
163 return rc;
164 }
165
166 uint32_t block_size = ext4_superblock_get_block_size(sb);
167
168 /* Update superblock free blocks count */
169 uint32_t sb_free_blocks =
170 ext4_superblock_get_free_blocks_count(sb);
171 sb_free_blocks += count;
172 ext4_superblock_set_free_blocks_count(sb, sb_free_blocks);
173
174 /* Update inode blocks count */
175 uint64_t ino_blocks =
176 ext4_inode_get_blocks_count(sb, inode_ref->inode);
177 ino_blocks -= count * (block_size / EXT4_INODE_BLOCK_SIZE);
178 ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks);
179 inode_ref->dirty = true;
180
181 /* Update block group free blocks count */
182 uint32_t free_blocks =
183 ext4_block_group_get_free_blocks_count(bg_ref->block_group, sb);
184 free_blocks += count;
185 ext4_block_group_set_free_blocks_count(bg_ref->block_group,
186 sb, free_blocks);
187 bg_ref->dirty = true;
188
189 /* Release block group reference */
190 return ext4_filesystem_put_block_group_ref(bg_ref);
191}
192
193/** Free continuous set of blocks.
194 *
195 * @param inode_ref Inode, where the blocks are allocated
196 * @param first First block to release
197 * @param count Number of blocks to release
198 *
199 */
200errno_t ext4_balloc_free_blocks(ext4_inode_ref_t *inode_ref,
201 uint32_t first, uint32_t count)
202{
203 errno_t r;
204 uint32_t gid;
205 uint64_t limit;
206 ext4_filesystem_t *fs = inode_ref->fs;
207 ext4_superblock_t *sb = fs->superblock;
208
209 while (count) {
210 gid = ext4_filesystem_blockaddr2group(sb, first);
211 limit = ext4_filesystem_index_in_group2blockaddr(sb, 0,
212 gid + 1);
213
214 if ((first + count) >= limit) {
215 /* This extent spans over 2 or more block groups,
216 * we'll break it into smaller parts.
217 */
218 uint32_t s = limit - first;
219
220 r = ext4_balloc_free_blocks_internal(inode_ref,
221 first, s);
222 if (r != EOK)
223 return r;
224
225 first = limit;
226 count -= s;
227 } else {
228 return ext4_balloc_free_blocks_internal(inode_ref,
229 first, count);
230 }
231 }
232
233 return EOK;
234}
235
236/** Compute first block for data in block group.
237 *
238 * @param sb Pointer to superblock
239 * @param bg Pointer to block group
240 * @param bgid Index of block group
241 *
242 * @return Absolute block index of first block
243 *
244 */
245uint32_t ext4_balloc_get_first_data_block_in_group(ext4_superblock_t *sb,
246 ext4_block_group_ref_t *bg_ref)
247{
248 uint32_t r;
249 uint64_t itable = ext4_block_group_get_inode_table_first_block(
250 bg_ref->block_group, sb);
251 uint32_t itable_sz = ext4_filesystem_bg_get_itable_size(sb, bg_ref);
252
253 if (!ext4_superblock_has_feature_incompatible(sb,
254 EXT4_FEATURE_INCOMPAT_FLEX_BG)) {
255 /* If we are not using FLEX_BG, the first data block
256 * is always after the inode table.
257 */
258 r = itable + itable_sz;
259 return ext4_filesystem_blockaddr2_index_in_group(sb, r);
260 }
261
262 uint64_t bbmap = ext4_block_group_get_block_bitmap(bg_ref->block_group,
263 sb);
264 uint64_t ibmap = ext4_block_group_get_inode_bitmap(bg_ref->block_group,
265 sb);
266
267 r = ext4_filesystem_index_in_group2blockaddr(sb, 0, bg_ref->index);
268 r += ext4_filesystem_bg_get_backup_blocks(bg_ref);
269
270 if (ext4_filesystem_blockaddr2group(sb, bbmap) != bg_ref->index)
271 bbmap = -1; /* Invalid */
272
273 if (ext4_filesystem_blockaddr2group(sb, ibmap) != bg_ref->index)
274 ibmap = -1;
275
276 while (1) {
277 if (r == bbmap || r == ibmap)
278 r++;
279 else if (r >= itable && r < (itable + itable_sz))
280 r = itable + itable_sz;
281 else
282 break;
283 }
284
285 return r;
286}
287
288/** Compute 'goal' for allocation algorithm.
289 *
290 * @param inode_ref Reference to inode, to allocate block for
291 *
292 * @return Goal block number
293 *
294 */
295static errno_t ext4_balloc_find_goal(ext4_inode_ref_t *inode_ref, uint32_t *goal)
296{
297 *goal = 0;
298 ext4_superblock_t *sb = inode_ref->fs->superblock;
299
300 uint64_t inode_size = ext4_inode_get_size(sb, inode_ref->inode);
301 uint32_t block_size = ext4_superblock_get_block_size(sb);
302 uint32_t inode_block_count = inode_size / block_size;
303
304 if (inode_size % block_size != 0)
305 inode_block_count++;
306
307 /* If inode has some blocks, get last block address + 1 */
308 if (inode_block_count > 0) {
309 errno_t rc = ext4_filesystem_get_inode_data_block_index(inode_ref,
310 inode_block_count - 1, goal);
311 if (rc != EOK)
312 return rc;
313
314 if (goal != 0) {
315 (*goal)++;
316 return EOK;
317 }
318 /* If goal == 0, sparse file -> continue */
319 }
320
321 /* Identify block group of inode */
322 uint32_t inodes_per_group = ext4_superblock_get_inodes_per_group(sb);
323 uint32_t block_group = (inode_ref->index - 1) / inodes_per_group;
324
325 /* Load block group reference */
326 ext4_block_group_ref_t *bg_ref;
327 errno_t rc = ext4_filesystem_get_block_group_ref(inode_ref->fs,
328 block_group, &bg_ref);
329 if (rc != EOK)
330 return rc;
331
332 *goal = ext4_balloc_get_first_data_block_in_group(sb, bg_ref);
333
334 return ext4_filesystem_put_block_group_ref(bg_ref);
335}
336
337/** Data block allocation algorithm.
338 *
339 * @param inode_ref Inode to allocate block for
340 * @param fblock Allocated block address
341 *
342 * @return Error code
343 *
344 */
345errno_t ext4_balloc_alloc_block(ext4_inode_ref_t *inode_ref, uint32_t *fblock)
346{
347 uint32_t allocated_block = 0;
348
349 uint32_t bitmap_block_addr;
350 block_t *bitmap_block;
351 uint32_t rel_block_idx = 0;
352 uint32_t free_blocks;
353 uint32_t goal;
354
355 /* Find GOAL */
356 errno_t rc = ext4_balloc_find_goal(inode_ref, &goal);
357 if (rc != EOK)
358 return rc;
359
360 ext4_superblock_t *sb = inode_ref->fs->superblock;
361
362 /* Load block group number for goal and relative index */
363 uint32_t block_group = ext4_filesystem_blockaddr2group(sb, goal);
364 uint32_t index_in_group =
365 ext4_filesystem_blockaddr2_index_in_group(sb, goal);
366
367 /* Load block group reference */
368 ext4_block_group_ref_t *bg_ref;
369 rc = ext4_filesystem_get_block_group_ref(inode_ref->fs,
370 block_group, &bg_ref);
371 if (rc != EOK)
372 return rc;
373
374 free_blocks =
375 ext4_block_group_get_free_blocks_count(bg_ref->block_group, sb);
376 if (free_blocks == 0) {
377 /* This group has no free blocks */
378 goto goal_failed;
379 }
380
381 /* Compute indexes */
382 uint32_t first_in_group =
383 ext4_balloc_get_first_data_block_in_group(sb, bg_ref);
384
385 uint32_t first_in_group_index =
386 ext4_filesystem_blockaddr2_index_in_group(sb, first_in_group);
387
388 if (index_in_group < first_in_group_index)
389 index_in_group = first_in_group_index;
390
391 /* Load block with bitmap */
392 bitmap_block_addr =
393 ext4_block_group_get_block_bitmap(bg_ref->block_group, sb);
394
395 rc = block_get(&bitmap_block, inode_ref->fs->device,
396 bitmap_block_addr, BLOCK_FLAGS_NONE);
397 if (rc != EOK) {
398 ext4_filesystem_put_block_group_ref(bg_ref);
399 return rc;
400 }
401
402 /* Check if goal is free */
403 if (ext4_bitmap_is_free_bit(bitmap_block->data, index_in_group)) {
404 ext4_bitmap_set_bit(bitmap_block->data, index_in_group);
405 bitmap_block->dirty = true;
406 rc = block_put(bitmap_block);
407 if (rc != EOK) {
408 ext4_filesystem_put_block_group_ref(bg_ref);
409 return rc;
410 }
411
412 allocated_block =
413 ext4_filesystem_index_in_group2blockaddr(sb, index_in_group,
414 block_group);
415
416 goto success;
417 }
418
419 uint32_t blocks_in_group =
420 ext4_superblock_get_blocks_in_group(sb, block_group);
421
422 uint32_t end_idx = (index_in_group + 63) & ~63;
423 if (end_idx > blocks_in_group)
424 end_idx = blocks_in_group;
425
426 /* Try to find free block near to goal */
427 for (uint32_t tmp_idx = index_in_group + 1; tmp_idx < end_idx;
428 ++tmp_idx) {
429 if (ext4_bitmap_is_free_bit(bitmap_block->data, tmp_idx)) {
430 ext4_bitmap_set_bit(bitmap_block->data, tmp_idx);
431 bitmap_block->dirty = true;
432 rc = block_put(bitmap_block);
433 if (rc != EOK)
434 return rc;
435
436 allocated_block =
437 ext4_filesystem_index_in_group2blockaddr(sb, tmp_idx,
438 block_group);
439
440 goto success;
441 }
442 }
443
444 /* Find free BYTE in bitmap */
445 rc = ext4_bitmap_find_free_byte_and_set_bit(bitmap_block->data,
446 index_in_group, &rel_block_idx, blocks_in_group);
447 if (rc == EOK) {
448 bitmap_block->dirty = true;
449 rc = block_put(bitmap_block);
450 if (rc != EOK)
451 return rc;
452
453 allocated_block =
454 ext4_filesystem_index_in_group2blockaddr(sb, rel_block_idx,
455 block_group);
456
457 goto success;
458 }
459
460 /* Find free bit in bitmap */
461 rc = ext4_bitmap_find_free_bit_and_set(bitmap_block->data,
462 index_in_group, &rel_block_idx, blocks_in_group);
463 if (rc == EOK) {
464 bitmap_block->dirty = true;
465 rc = block_put(bitmap_block);
466 if (rc != EOK)
467 return rc;
468
469 allocated_block =
470 ext4_filesystem_index_in_group2blockaddr(sb, rel_block_idx,
471 block_group);
472
473 goto success;
474 }
475
476 /* No free block found yet */
477 rc = block_put(bitmap_block);
478 if (rc != EOK) {
479 ext4_filesystem_put_block_group_ref(bg_ref);
480 return rc;
481 }
482
483goal_failed:
484
485 rc = ext4_filesystem_put_block_group_ref(bg_ref);
486 if (rc != EOK)
487 return rc;
488
489 /* Try other block groups */
490 uint32_t block_group_count = ext4_superblock_get_block_group_count(sb);
491
492 uint32_t bgid = (block_group + 1) % block_group_count;
493 uint32_t count = block_group_count;
494
495 while (count > 0) {
496 rc = ext4_filesystem_get_block_group_ref(inode_ref->fs, bgid,
497 &bg_ref);
498 if (rc != EOK)
499 return rc;
500
501 free_blocks =
502 ext4_block_group_get_free_blocks_count(bg_ref->block_group, sb);
503 if (free_blocks == 0) {
504 /* This group has no free blocks */
505 goto next_group;
506 }
507
508 /* Load block with bitmap */
509 bitmap_block_addr =
510 ext4_block_group_get_block_bitmap(bg_ref->block_group, sb);
511
512 rc = block_get(&bitmap_block, inode_ref->fs->device,
513 bitmap_block_addr, 0);
514 if (rc != EOK) {
515 ext4_filesystem_put_block_group_ref(bg_ref);
516 return rc;
517 }
518
519 /* Compute indexes */
520 first_in_group =
521 ext4_balloc_get_first_data_block_in_group(sb, bg_ref);
522 index_in_group =
523 ext4_filesystem_blockaddr2_index_in_group(sb, first_in_group);
524 blocks_in_group = ext4_superblock_get_blocks_in_group(sb, bgid);
525
526 first_in_group_index =
527 ext4_filesystem_blockaddr2_index_in_group(sb, first_in_group);
528
529 if (index_in_group < first_in_group_index)
530 index_in_group = first_in_group_index;
531
532 /* Try to find free byte in bitmap */
533 rc = ext4_bitmap_find_free_byte_and_set_bit(bitmap_block->data,
534 index_in_group, &rel_block_idx, blocks_in_group);
535 if (rc == EOK) {
536 bitmap_block->dirty = true;
537 rc = block_put(bitmap_block);
538 if (rc != EOK) {
539 ext4_filesystem_put_block_group_ref(bg_ref);
540 return rc;
541 }
542
543 allocated_block =
544 ext4_filesystem_index_in_group2blockaddr(sb, rel_block_idx,
545 bgid);
546
547 goto success;
548 }
549
550 /* Try to find free bit in bitmap */
551 rc = ext4_bitmap_find_free_bit_and_set(bitmap_block->data,
552 index_in_group, &rel_block_idx, blocks_in_group);
553 if (rc == EOK) {
554 bitmap_block->dirty = true;
555 rc = block_put(bitmap_block);
556 if (rc != EOK) {
557 ext4_filesystem_put_block_group_ref(bg_ref);
558 return rc;
559 }
560
561 allocated_block =
562 ext4_filesystem_index_in_group2blockaddr(sb, rel_block_idx,
563 bgid);
564
565 goto success;
566 }
567
568 rc = block_put(bitmap_block);
569 if (rc != EOK) {
570 ext4_filesystem_put_block_group_ref(bg_ref);
571 return rc;
572 }
573
574next_group:
575 rc = ext4_filesystem_put_block_group_ref(bg_ref);
576 if (rc != EOK)
577 return rc;
578
579 /* Goto next group */
580 bgid = (bgid + 1) % block_group_count;
581 count--;
582 }
583
584 return ENOSPC;
585
586success:
587 /* Empty command - because of syntax */
588 ;
589
590 uint32_t block_size = ext4_superblock_get_block_size(sb);
591
592 /* Update superblock free blocks count */
593 uint32_t sb_free_blocks = ext4_superblock_get_free_blocks_count(sb);
594 sb_free_blocks--;
595 ext4_superblock_set_free_blocks_count(sb, sb_free_blocks);
596
597 /* Update inode blocks (different block size!) count */
598 uint64_t ino_blocks =
599 ext4_inode_get_blocks_count(sb, inode_ref->inode);
600 ino_blocks += block_size / EXT4_INODE_BLOCK_SIZE;
601 ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks);
602 inode_ref->dirty = true;
603
604 /* Update block group free blocks count */
605 uint32_t bg_free_blocks =
606 ext4_block_group_get_free_blocks_count(bg_ref->block_group, sb);
607 bg_free_blocks--;
608 ext4_block_group_set_free_blocks_count(bg_ref->block_group, sb,
609 bg_free_blocks);
610 bg_ref->dirty = true;
611
612 rc = ext4_filesystem_put_block_group_ref(bg_ref);
613
614 *fblock = allocated_block;
615 return rc;
616}
617
618/** Try to allocate concrete block.
619 *
620 * @param inode_ref Inode to allocate block for
621 * @param fblock Block address to allocate
622 * @param free Output value - if target block is free
623 *
624 * @return Error code
625 *
626 */
627errno_t ext4_balloc_try_alloc_block(ext4_inode_ref_t *inode_ref, uint32_t fblock,
628 bool *free)
629{
630 errno_t rc;
631
632 ext4_filesystem_t *fs = inode_ref->fs;
633 ext4_superblock_t *sb = fs->superblock;
634
635 /* Compute indexes */
636 uint32_t block_group = ext4_filesystem_blockaddr2group(sb, fblock);
637 uint32_t index_in_group =
638 ext4_filesystem_blockaddr2_index_in_group(sb, fblock);
639
640 /* Load block group reference */
641 ext4_block_group_ref_t *bg_ref;
642 rc = ext4_filesystem_get_block_group_ref(fs, block_group, &bg_ref);
643 if (rc != EOK)
644 return rc;
645
646 /* Load block with bitmap */
647 uint32_t bitmap_block_addr =
648 ext4_block_group_get_block_bitmap(bg_ref->block_group, sb);
649 block_t *bitmap_block;
650 rc = block_get(&bitmap_block, fs->device, bitmap_block_addr, 0);
651 if (rc != EOK) {
652 ext4_filesystem_put_block_group_ref(bg_ref);
653 return rc;
654 }
655
656 /* Check if block is free */
657 *free = ext4_bitmap_is_free_bit(bitmap_block->data, index_in_group);
658
659 /* Allocate block if possible */
660 if (*free) {
661 ext4_bitmap_set_bit(bitmap_block->data, index_in_group);
662 bitmap_block->dirty = true;
663 }
664
665 /* Release block with bitmap */
666 rc = block_put(bitmap_block);
667 if (rc != EOK) {
668 /* Error in saving bitmap */
669 ext4_filesystem_put_block_group_ref(bg_ref);
670 return rc;
671 }
672
673 /* If block is not free, return */
674 if (!(*free))
675 goto terminate;
676
677 uint32_t block_size = ext4_superblock_get_block_size(sb);
678
679 /* Update superblock free blocks count */
680 uint32_t sb_free_blocks = ext4_superblock_get_free_blocks_count(sb);
681 sb_free_blocks--;
682 ext4_superblock_set_free_blocks_count(sb, sb_free_blocks);
683
684 /* Update inode blocks count */
685 uint64_t ino_blocks =
686 ext4_inode_get_blocks_count(sb, inode_ref->inode);
687 ino_blocks += block_size / EXT4_INODE_BLOCK_SIZE;
688 ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks);
689 inode_ref->dirty = true;
690
691 /* Update block group free blocks count */
692 uint32_t free_blocks =
693 ext4_block_group_get_free_blocks_count(bg_ref->block_group, sb);
694 free_blocks--;
695 ext4_block_group_set_free_blocks_count(bg_ref->block_group,
696 sb, free_blocks);
697 bg_ref->dirty = true;
698
699terminate:
700 return ext4_filesystem_put_block_group_ref(bg_ref);
701}
702
703/**
704 * @}
705 */
Note: See TracBrowser for help on using the repository browser.