source: mainline/uspace/lib/ext4/src/superblock.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: 30.0 KB
Line 
1/*
2 * Copyright (c) 2011 Martin Sucha
3 * Copyright (c) 2012 Frantisek Princ
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup libext4
31 * @{
32 */
33
34/**
35 * @file superblock.c
36 * @brief Ext4 superblock operations.
37 */
38
39#include <block.h>
40#include <byteorder.h>
41#include <errno.h>
42#include <mem.h>
43#include <stdlib.h>
44#include "ext4/superblock.h"
45
46/** Get number of i-nodes in the whole filesystem.
47 *
48 * @param sb Superblock
49 *
50 * @return Number of i-nodes
51 *
52 */
53uint32_t ext4_superblock_get_inodes_count(ext4_superblock_t *sb)
54{
55 return uint32_t_le2host(sb->inodes_count);
56}
57
58/** Set number of i-nodes in the whole filesystem.
59 *
60 * @param sb Superblock
61 * @param count Number of i-nodes
62 *
63 */
64void ext4_superblock_set_inodes_count(ext4_superblock_t *sb, uint32_t count)
65{
66 sb->inodes_count = host2uint32_t_le(count);
67}
68
69/** Get number of data blocks in the whole filesystem.
70 *
71 * @param sb Superblock
72 *
73 * @return Number of data blocks
74 *
75 */
76uint64_t ext4_superblock_get_blocks_count(ext4_superblock_t *sb)
77{
78 return ((uint64_t) uint32_t_le2host(sb->blocks_count_hi) << 32) |
79 uint32_t_le2host(sb->blocks_count_lo);
80}
81
82/** Set number of data blocks in the whole filesystem.
83 *
84 * @param sb Superblock
85 * @param count Number of data blocks
86 *
87 */
88void ext4_superblock_set_blocks_count(ext4_superblock_t *sb, uint64_t count)
89{
90 sb->blocks_count_lo = host2uint32_t_le((count << 32) >> 32);
91 sb->blocks_count_hi = host2uint32_t_le(count >> 32);
92}
93
94/** Get number of reserved data blocks in the whole filesystem.
95 *
96 * @param sb Superblock
97 *
98 * @return Number of reserved data blocks
99 *
100 */
101uint64_t ext4_superblock_get_reserved_blocks_count(ext4_superblock_t *sb)
102{
103 return ((uint64_t)
104 uint32_t_le2host(sb->reserved_blocks_count_hi) << 32) |
105 uint32_t_le2host(sb->reserved_blocks_count_lo);
106}
107
108/** Set number of reserved data blocks in the whole filesystem.
109 *
110 * @param sb Superblock
111 * @param count Number of reserved data blocks
112 *
113 */
114void ext4_superblock_set_reserved_blocks_count(ext4_superblock_t *sb,
115 uint64_t count)
116{
117 sb->reserved_blocks_count_lo = host2uint32_t_le((count << 32) >> 32);
118 sb->reserved_blocks_count_hi = host2uint32_t_le(count >> 32);
119}
120
121/** Get number of free data blocks in the whole filesystem.
122 *
123 * @param sb Superblock
124 *
125 * @return Number of free data blocks
126 *
127 */
128uint64_t ext4_superblock_get_free_blocks_count(ext4_superblock_t *sb)
129{
130 return ((uint64_t)
131 uint32_t_le2host(sb->free_blocks_count_hi) << 32) |
132 uint32_t_le2host(sb->free_blocks_count_lo);
133}
134
135/** Set number of free data blocks in the whole filesystem.
136 *
137 * @param sb Superblock
138 * @param count Number of free data blocks
139 *
140 */
141void ext4_superblock_set_free_blocks_count(ext4_superblock_t *sb,
142 uint64_t count)
143{
144 sb->free_blocks_count_lo = host2uint32_t_le((count << 32) >> 32);
145 sb->free_blocks_count_hi = host2uint32_t_le(count >> 32);
146}
147
148/** Get number of free i-nodes in the whole filesystem.
149 *
150 * @param sb Superblock
151 *
152 * @return Number of free i-nodes
153 *
154 */
155uint32_t ext4_superblock_get_free_inodes_count(ext4_superblock_t *sb)
156{
157 return uint32_t_le2host(sb->free_inodes_count);
158}
159
160/** Set number of free i-nodes in the whole filesystem.
161 *
162 * @param sb Superblock
163 * @param count Number of free i-nodes
164 *
165 */
166void ext4_superblock_set_free_inodes_count(ext4_superblock_t *sb,
167 uint32_t count)
168{
169 sb->free_inodes_count = host2uint32_t_le(count);
170}
171
172/** Get index of first data block (block where the superblock is located)
173 *
174 * @param sb Superblock
175 *
176 * @return Index of the first data block
177 *
178 */
179uint32_t ext4_superblock_get_first_data_block(ext4_superblock_t *sb)
180{
181 return uint32_t_le2host(sb->first_data_block);
182}
183
184/** Set index of first data block (block where the superblock is located)
185 *
186 * @param sb Superblock
187 * @param first Index of the first data block
188 *
189 */
190void ext4_superblock_set_first_data_block(ext4_superblock_t *sb,
191 uint32_t first)
192{
193 sb->first_data_block = host2uint32_t_le(first);
194}
195
196/** Get logarithmic block size (1024 << size == block_size)
197 *
198 * @param sb Superblock
199 *
200 * @return Logarithmic block size
201 *
202 */
203uint32_t ext4_superblock_get_log_block_size(ext4_superblock_t *sb)
204{
205 return uint32_t_le2host(sb->log_block_size);
206}
207
208/** Set logarithmic block size (1024 << size == block_size)
209 *
210 * @param sb Superblock
211 *
212 * @return Logarithmic block size
213 *
214 */
215void ext4_superblock_set_log_block_size(ext4_superblock_t *sb,
216 uint32_t log_size)
217{
218 sb->log_block_size = host2uint32_t_le(log_size);
219}
220
221/** Get size of data block (in bytes).
222 *
223 * @param sb Superblock
224 *
225 * @return Size of data block
226 *
227 */
228uint32_t ext4_superblock_get_block_size(ext4_superblock_t *sb)
229{
230 return 1024 << ext4_superblock_get_log_block_size(sb);
231}
232
233/** Set size of data block (in bytes).
234 *
235 * @param sb Superblock
236 * @param size Size of data block (must be power of 2, at least 1024)
237 *
238 */
239void ext4_superblock_set_block_size(ext4_superblock_t *sb, uint32_t size)
240{
241 uint32_t log = 0;
242 uint32_t tmp = size / EXT4_MIN_BLOCK_SIZE;
243
244 tmp >>= 1;
245 while (tmp) {
246 log++;
247 tmp >>= 1;
248 }
249
250 ext4_superblock_set_log_block_size(sb, log);
251}
252
253/** Get logarithmic fragment size (1024 << size)
254 *
255 * @param sb Superblock
256 *
257 * @return Logarithmic fragment size
258 *
259 */
260uint32_t ext4_superblock_get_log_frag_size(ext4_superblock_t *sb)
261{
262 return uint32_t_le2host(sb->log_frag_size);
263}
264
265/** Set logarithmic fragment size (1024 << size)
266 *
267 * @param sb Superblock
268 * @param frag_size Logarithmic fragment size
269 *
270 */
271void ext4_superblock_set_log_frag_size(ext4_superblock_t *sb,
272 uint32_t frag_size)
273{
274 sb->log_frag_size = host2uint32_t_le(frag_size);
275}
276
277/** Get size of fragment (in bytes).
278 *
279 * @param sb Superblock
280 *
281 * @return Size of fragment
282 *
283 */
284uint32_t ext4_superblock_get_frag_size(ext4_superblock_t *sb)
285{
286 return 1024 << ext4_superblock_get_log_frag_size(sb);
287}
288
289/** Set size of fragment (in bytes).
290 *
291 * @param sb Superblock
292 * @param size Size of fragment (must be power of 2, at least 1024)
293 *
294 */
295void ext4_superblock_set_frag_size(ext4_superblock_t *sb, uint32_t size)
296{
297 uint32_t log = 0;
298 uint32_t tmp = size / EXT4_MIN_BLOCK_SIZE;
299
300 tmp >>= 1;
301 while (tmp) {
302 log++;
303 tmp >>= 1;
304 }
305
306 ext4_superblock_set_log_frag_size(sb, log);
307}
308
309/** Get number of data blocks per block group (except last BG)
310 *
311 * @param sb Superblock
312 *
313 * @return Data blocks per block group
314 *
315 */
316uint32_t ext4_superblock_get_blocks_per_group(ext4_superblock_t *sb)
317{
318 return uint32_t_le2host(sb->blocks_per_group);
319}
320
321/** Set number of data blocks per block group (except last BG)
322 *
323 * @param sb Superblock
324 * @param blocks Data blocks per block group
325 *
326 */
327void ext4_superblock_set_blocks_per_group(ext4_superblock_t *sb,
328 uint32_t blocks)
329{
330 sb->blocks_per_group = host2uint32_t_le(blocks);
331}
332
333/** Get number of fragments per block group (except last BG)
334 *
335 * @param sb Superblock
336 *
337 * @return Fragments per block group
338 *
339 */
340uint32_t ext4_superblock_get_frags_per_group(ext4_superblock_t *sb)
341{
342 return uint32_t_le2host(sb->frags_per_group);
343}
344
345/** Set number of fragment per block group (except last BG)
346 *
347 * @param sb Superblock
348 * @param frags Fragments per block group
349 */
350void ext4_superblock_set_frags_per_group(ext4_superblock_t *sb, uint32_t frags)
351{
352 sb->frags_per_group = host2uint32_t_le(frags);
353}
354
355/** Get number of i-nodes per block group (except last BG)
356 *
357 * @param sb Superblock
358 *
359 * @return I-nodes per block group
360 *
361 */
362uint32_t ext4_superblock_get_inodes_per_group(ext4_superblock_t *sb)
363{
364 return uint32_t_le2host(sb->inodes_per_group);
365}
366
367/** Set number of i-nodes per block group (except last BG)
368 *
369 * @param sb Superblock
370 * @param inodes I-nodes per block group
371 *
372 */
373void ext4_superblock_set_inodes_per_group(ext4_superblock_t *sb,
374 uint32_t inodes)
375{
376 sb->inodes_per_group = host2uint32_t_le(inodes);
377}
378
379/** Get time when filesystem was mounted (POSIX time).
380 *
381 * @param sb Superblock
382 *
383 * @return Mount time
384 *
385 */
386uint32_t ext4_superblock_get_mount_time(ext4_superblock_t *sb)
387{
388 return uint32_t_le2host(sb->mount_time);
389}
390
391/** Set time when filesystem was mounted (POSIX time).
392 *
393 * @param sb Superblock
394 * @param time Mount time
395 *
396 */
397void ext4_superblock_set_mount_time(ext4_superblock_t *sb, uint32_t time)
398{
399 sb->mount_time = host2uint32_t_le(time);
400}
401
402/** Get time when filesystem was last accesed by write operation (POSIX time).
403 *
404 * @param sb Superblock
405 *
406 * @return Write time
407 *
408 */
409uint32_t ext4_superblock_get_write_time(ext4_superblock_t *sb)
410{
411 return uint32_t_le2host(sb->write_time);
412}
413
414/** Set time when filesystem was last accesed by write operation (POSIX time).
415 *
416 * @param sb Superblock
417 * @param time Write time
418 *
419 */
420void ext4_superblock_set_write_time(ext4_superblock_t *sb, uint32_t time)
421{
422 sb->write_time = host2uint32_t_le(time);
423}
424
425/** Get number of mount from last filesystem check.
426 *
427 * @param sb Superblock
428 *
429 * @return Number of mounts
430 *
431 */
432uint16_t ext4_superblock_get_mount_count(ext4_superblock_t *sb)
433{
434 return uint16_t_le2host(sb->mount_count);
435}
436
437/** Set number of mount from last filesystem check.
438 *
439 * @param sb Superblock
440 * @param count Number of mounts
441 *
442 */
443void ext4_superblock_set_mount_count(ext4_superblock_t *sb, uint16_t count)
444{
445 sb->mount_count = host2uint16_t_le(count);
446}
447
448/** Get maximum number of mount from last filesystem check.
449 *
450 * @param sb Superblock
451 *
452 * @return Maximum number of mounts
453 *
454 */
455uint16_t ext4_superblock_get_max_mount_count(ext4_superblock_t *sb)
456{
457 return uint16_t_le2host(sb->max_mount_count);
458}
459
460/** Set maximum number of mount from last filesystem check.
461 *
462 * @param sb Superblock
463 * @param count Maximum number of mounts
464 *
465 */
466void ext4_superblock_set_max_mount_count(ext4_superblock_t *sb, uint16_t count)
467{
468 sb->max_mount_count = host2uint16_t_le(count);
469}
470
471/** Get superblock magic value.
472 *
473 * @param sb Superblock
474 *
475 * @return Magic value
476 *
477 */
478uint16_t ext4_superblock_get_magic(ext4_superblock_t *sb)
479{
480 return uint16_t_le2host(sb->magic);
481}
482
483/** Set superblock magic value.
484 *
485 * @param sb Superblock
486 * @param magic Magic value
487 *
488 */
489void ext4_superblock_set_magic(ext4_superblock_t *sb, uint16_t magic)
490{
491 sb->magic = host2uint16_t_le(magic);
492}
493
494/** Get filesystem state.
495 *
496 * @param sb Superblock
497 *
498 * @return Filesystem state
499 *
500 */
501uint16_t ext4_superblock_get_state(ext4_superblock_t *sb)
502{
503 return uint16_t_le2host(sb->state);
504}
505
506/** Set filesystem state.
507 *
508 * @param sb Superblock
509 * @param state Filesystem state
510 *
511 */
512void ext4_superblock_set_state(ext4_superblock_t *sb, uint16_t state)
513{
514 sb->state = host2uint16_t_le(state);
515}
516
517/** Get behavior code when errors detected.
518 *
519 * @param sb Superblock
520 *
521 * @return Behavior code
522 *
523 */
524uint16_t ext4_superblock_get_errors(ext4_superblock_t *sb)
525{
526 return uint16_t_le2host(sb->errors);
527}
528
529/** Set behavior code when errors detected.
530 *
531 * @param sb Superblock
532 * @param errors Behavior code
533 *
534 */
535void ext4_superblock_set_errors(ext4_superblock_t *sb, uint16_t errors)
536{
537 sb->errors = host2uint16_t_le(errors);
538}
539
540/** Get minor revision level of the filesystem.
541 *
542 * @param sb Superblock
543 *
544 * @return Minor revision level
545 *
546 */
547uint16_t ext4_superblock_get_minor_rev_level(ext4_superblock_t *sb)
548{
549 return uint16_t_le2host(sb->minor_rev_level);
550}
551
552/** Set minor revision level of the filesystem.
553 *
554 * @param sb Superblock
555 * @param level Minor revision level
556 *
557 */
558void ext4_superblock_set_minor_rev_level(ext4_superblock_t *sb, uint16_t level)
559{
560 sb->minor_rev_level = host2uint16_t_le(level);
561}
562
563/** Get time of the last filesystem check.
564 *
565 * @param sb Superblock
566 *
567 * @return Time of the last check (POSIX)
568 *
569 */
570uint32_t ext4_superblock_get_last_check_time(ext4_superblock_t *sb)
571{
572 return uint32_t_le2host(sb->last_check_time);
573}
574
575/** Set time of the last filesystem check.
576 *
577 * @param sb Superblock
578 * @param time Time of the last check (POSIX)
579 *
580 */
581void ext4_superblock_set_last_check_time(ext4_superblock_t *sb, uint32_t time)
582{
583 sb->state = host2uint32_t_le(time);
584}
585
586/** Get maximum time interval between two filesystem checks.
587 *
588 * @param sb Superblock
589 *
590 * @return Time interval between two check (POSIX)
591 *
592 */
593uint32_t ext4_superblock_get_check_interval(ext4_superblock_t *sb)
594{
595 return uint32_t_le2host(sb->check_interval);
596}
597
598/** Set maximum time interval between two filesystem checks.
599 *
600 * @param sb Superblock
601 * @param interval Time interval between two check (POSIX)
602 *
603 */
604void ext4_superblock_set_check_interval(ext4_superblock_t *sb, uint32_t interval)
605{
606 sb->check_interval = host2uint32_t_le(interval);
607}
608
609/** Get operation system identifier, on which the filesystem was created.
610 *
611 * @param sb Superblock
612 *
613 * @return Operation system identifier
614 *
615 */
616uint32_t ext4_superblock_get_creator_os(ext4_superblock_t *sb)
617{
618 return uint32_t_le2host(sb->creator_os);
619}
620
621/** Set operation system identifier, on which the filesystem was created.
622 *
623 * @param sb Superblock
624 * @param os Operation system identifier
625 *
626 */
627void ext4_superblock_set_creator_os(ext4_superblock_t *sb, uint32_t os)
628{
629 sb->creator_os = host2uint32_t_le(os);
630}
631
632/** Get revision level of the filesystem.
633 *
634 * @param sb Superblock
635 *
636 * @return Revision level
637 *
638 */
639uint32_t ext4_superblock_get_rev_level(ext4_superblock_t *sb)
640{
641 return uint32_t_le2host(sb->rev_level);
642}
643
644/** Set revision level of the filesystem.
645 *
646 * @param sb Superblock
647 * @param level Revision level
648 *
649 */
650void ext4_superblock_set_rev_level(ext4_superblock_t *sb, uint32_t level)
651{
652 sb->rev_level = host2uint32_t_le(level);
653}
654
655/** Get default user id for reserved blocks.
656 *
657 * @param sb Superblock
658 *
659 * @return Default user id for reserved blocks.
660 *
661 */
662uint16_t ext4_superblock_get_def_resuid(ext4_superblock_t *sb)
663{
664 return uint16_t_le2host(sb->def_resuid);
665}
666
667/** Set default user id for reserved blocks.
668 *
669 * @param sb Superblock
670 * @param uid Default user id for reserved blocks.
671 *
672 */
673void ext4_superblock_set_def_resuid(ext4_superblock_t *sb, uint16_t uid)
674{
675 sb->def_resuid = host2uint16_t_le(uid);
676}
677
678/** Get default group id for reserved blocks.
679 *
680 * @param sb Superblock
681 *
682 * @return Default group id for reserved blocks.
683 *
684 */
685uint16_t ext4_superblock_get_def_resgid(ext4_superblock_t *sb)
686{
687 return uint16_t_le2host(sb->def_resgid);
688}
689
690/** Set default group id for reserved blocks.
691 *
692 * @param sb Superblock
693 * @param gid Default group id for reserved blocks.
694 *
695 */
696void ext4_superblock_set_def_resgid(ext4_superblock_t *sb, uint16_t gid)
697{
698 sb->def_resgid = host2uint16_t_le(gid);
699}
700
701/** Get index of the first i-node, which can be used for allocation.
702 *
703 * @param sb Superblock
704 *
705 * @return I-node index
706 *
707 */
708uint32_t ext4_superblock_get_first_inode(ext4_superblock_t *sb)
709{
710 return uint32_t_le2host(sb->first_inode);
711}
712
713/** Set index of the first i-node, which can be used for allocation.
714 *
715 * @param sb Superblock
716 * @param first_inode I-node index
717 *
718 */
719void ext4_superblock_set_first_inode(ext4_superblock_t *sb,
720 uint32_t first_inode)
721{
722 sb->first_inode = host2uint32_t_le(first_inode);
723}
724
725/** Get size of i-node structure.
726 *
727 * For the oldest revision return constant number.
728 *
729 * @param sb Superblock
730 *
731 * @return Size of i-node structure
732 *
733 */
734uint16_t ext4_superblock_get_inode_size(ext4_superblock_t *sb)
735{
736 if (ext4_superblock_get_rev_level(sb) == 0)
737 return EXT4_REV0_INODE_SIZE;
738
739 return uint16_t_le2host(sb->inode_size);
740}
741
742/** Set size of i-node structure.
743 *
744 * @param sb Superblock
745 * @param size Size of i-node structure
746 *
747 */
748void ext4_superblock_set_inode_size(ext4_superblock_t *sb, uint16_t size)
749{
750 sb->inode_size = host2uint16_t_le(size);
751}
752
753/** Get index of block group, where superblock copy is located.
754 *
755 * @param sb Superblock
756 *
757 * @return Block group index
758 *
759 */
760uint16_t ext4_superblock_get_block_group_index(ext4_superblock_t *sb)
761{
762 return uint16_t_le2host(sb->block_group_index);
763}
764
765/** Set index of block group, where superblock copy is located.
766 *
767 * @param sb Superblock
768 * @param bgid Block group index
769 *
770 */
771void ext4_superblock_set_block_group_index(ext4_superblock_t *sb, uint16_t bgid)
772{
773 sb->block_group_index = host2uint16_t_le(bgid);
774}
775
776/** Get compatible features supported by the filesystem.
777 *
778 * @param sb Superblock
779 *
780 * @return Compatible features bitmap
781 *
782 */
783uint32_t ext4_superblock_get_features_compatible(ext4_superblock_t *sb)
784{
785 return uint32_t_le2host(sb->features_compatible);
786}
787
788/** Set compatible features supported by the filesystem.
789 *
790 * @param sb Superblock
791 * @param features Compatible features bitmap
792 *
793 */
794void ext4_superblock_set_features_compatible(ext4_superblock_t *sb,
795 uint32_t features)
796{
797 sb->features_compatible = host2uint32_t_le(features);
798}
799
800/** Get incompatible features supported by the filesystem.
801 *
802 * @param sb Superblock
803 *
804 * @return Incompatible features bitmap
805 *
806 */
807uint32_t ext4_superblock_get_features_incompatible(ext4_superblock_t *sb)
808{
809 return uint32_t_le2host(sb->features_incompatible);
810}
811
812/** Set incompatible features supported by the filesystem.
813 *
814 * @param sb Superblock
815 * @param features Incompatible features bitmap
816 *
817 */
818void ext4_superblock_set_features_incompatible(ext4_superblock_t *sb,
819 uint32_t features)
820{
821 sb->features_incompatible = host2uint32_t_le(features);
822}
823
824/** Get compatible features supported by the filesystem.
825 *
826 * @param sb Superblock
827 *
828 * @return Read-only compatible features bitmap
829 *
830 */
831uint32_t ext4_superblock_get_features_read_only(ext4_superblock_t *sb)
832{
833 return uint32_t_le2host(sb->features_read_only);
834}
835
836/** Set compatible features supported by the filesystem.
837 *
838 * @param sb Superblock
839 * @param feature Read-only compatible features bitmap
840 *
841 */
842void ext4_superblock_set_features_read_only(ext4_superblock_t *sb,
843 uint32_t features)
844{
845 sb->features_read_only = host2uint32_t_le(features);
846}
847
848/** Get UUID of the filesystem.
849 *
850 * @param sb superblock
851 *
852 * @return Pointer to UUID array
853 *
854 */
855const uint8_t *ext4_superblock_get_uuid(ext4_superblock_t *sb)
856{
857 return sb->uuid;
858}
859
860/** Set UUID of the filesystem.
861 *
862 * @param sb Superblock
863 * @param uuid Pointer to UUID array
864 *
865 */
866void ext4_superblock_set_uuid(ext4_superblock_t *sb, const uint8_t *uuid)
867{
868 memcpy(sb->uuid, uuid, sizeof(sb->uuid));
869}
870
871/** Get name of the filesystem volume.
872 *
873 * @param sb Superblock
874 *
875 * @return Name of the volume
876 *
877 */
878const char *ext4_superblock_get_volume_name(ext4_superblock_t *sb)
879{
880 return sb->volume_name;
881}
882
883/** Set name of the filesystem volume.
884 *
885 * @param sb Superblock
886 * @param name New name of the volume
887 */
888void ext4_superblock_set_volume_name(ext4_superblock_t *sb, const char *name)
889{
890 memcpy(sb->volume_name, name, sizeof(sb->volume_name));
891}
892
893/** Get name of the directory, where this filesystem was mounted at last.
894 *
895 * @param sb Superblock
896 *
897 * @return Directory name
898 *
899 */
900const char *ext4_superblock_get_last_mounted(ext4_superblock_t *sb)
901{
902 return sb->last_mounted;
903}
904
905/** Set name of the directory, where this filesystem was mounted at last.
906 *
907 * @param sb Superblock
908 * @param last Directory name
909 *
910 */
911void ext4_superblock_set_last_mounted(ext4_superblock_t *sb, const char *last)
912{
913 memcpy(sb->last_mounted, last, sizeof(sb->last_mounted));
914}
915
916/** Get last orphaned i-node index.
917 *
918 * Orphans are stored in linked list.
919 *
920 * @param sb Superblock
921 *
922 * @return Last orphaned i-node index
923 *
924 */
925uint32_t ext4_superblock_get_last_orphan(ext4_superblock_t *sb)
926{
927 return uint32_t_le2host(sb->last_orphan);
928}
929
930/** Set last orphaned i-node index.
931 *
932 * Orphans are stored in linked list.
933 *
934 * @param sb Superblock
935 * @param last_orphan Last orphaned i-node index
936 *
937 */
938void ext4_superblock_set_last_orphan(ext4_superblock_t *sb,
939 uint32_t last_orphan)
940{
941 sb->last_orphan = host2uint32_t_le(last_orphan);
942}
943
944/** Get hash seed for directory index hash function.
945 *
946 * @param sb Superblock
947 *
948 * @return Hash seed pointer
949 *
950 */
951const uint32_t *ext4_superblock_get_hash_seed(ext4_superblock_t *sb)
952{
953 return sb->hash_seed;
954}
955
956/** Set hash seed for directory index hash function.
957 *
958 * @param sb Superblock
959 * @param seed Hash seed pointer
960 *
961 */
962void ext4_superblock_set_hash_seed(ext4_superblock_t *sb, const uint32_t *seed)
963{
964 memcpy(sb->hash_seed, seed, sizeof(sb->hash_seed));
965}
966
967/** Get default version of the hash algorithm version for directory index.
968 *
969 * @param sb Superblock
970 *
971 * @return Default hash version
972 *
973 */
974uint8_t ext4_superblock_get_default_hash_version(ext4_superblock_t *sb)
975{
976 return sb->default_hash_version;
977}
978
979/** Set default version of the hash algorithm version for directory index.
980 *
981 * @param sb Superblock
982 * @param version Default hash version
983 *
984 */
985void ext4_superblock_set_default_hash_version(ext4_superblock_t *sb,
986 uint8_t version)
987{
988 sb->default_hash_version = version;
989}
990
991/** Get size of block group descriptor structure.
992 *
993 * Output value is checked for minimal size.
994 *
995 * @param sb Superblock
996 *
997 * @return Size of block group descriptor
998 *
999 */
1000uint16_t ext4_superblock_get_desc_size(ext4_superblock_t *sb)
1001{
1002 uint16_t size = uint16_t_le2host(sb->desc_size);
1003
1004 if (size < EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
1005 size = EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE;
1006
1007 return size;
1008}
1009
1010/** Set size of block group descriptor structure.
1011 *
1012 * Input value is checked for minimal size.
1013 *
1014 * @param sb Superblock
1015 * @param size Size of block group descriptor
1016 *
1017 */
1018void ext4_superblock_set_desc_size(ext4_superblock_t *sb, uint16_t size)
1019{
1020 if (size < EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
1021 sb->desc_size =
1022 host2uint16_t_le(EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE);
1023
1024 sb->desc_size = host2uint16_t_le(size);
1025}
1026
1027/** Get superblock flags.
1028 *
1029 * @param sb Superblock
1030 *
1031 * @return Flags from the superblock
1032 *
1033 */
1034uint32_t ext4_superblock_get_flags(ext4_superblock_t *sb)
1035{
1036 return uint32_t_le2host(sb->flags);
1037}
1038
1039/** Set superblock flags.
1040 *
1041 * @param sb Superblock
1042 * @param flags Flags for the superblock
1043 *
1044 */
1045void ext4_superblock_set_flags(ext4_superblock_t *sb, uint32_t flags)
1046{
1047 sb->flags = host2uint32_t_le(flags);
1048}
1049
1050/*
1051 * More complex superblock operations
1052 */
1053
1054/** Check if superblock has specified flag.
1055 *
1056 * @param sb Superblock
1057 * @param flag Flag to be checked
1058 *
1059 * @return True, if superblock has the flag
1060 *
1061 */
1062bool ext4_superblock_has_flag(ext4_superblock_t *sb, uint32_t flag)
1063{
1064 if (ext4_superblock_get_flags(sb) & flag)
1065 return true;
1066
1067 return false;
1068}
1069
1070/** Check if filesystem supports compatible feature.
1071 *
1072 * @param sb Superblock
1073 * @param feature Feature to be checked
1074 *
1075 * @return True, if filesystem supports the feature
1076 *
1077 */
1078bool ext4_superblock_has_feature_compatible(ext4_superblock_t *sb,
1079 uint32_t feature)
1080{
1081 if (ext4_superblock_get_features_compatible(sb) & feature)
1082 return true;
1083
1084 return false;
1085}
1086
1087/** Check if filesystem supports incompatible feature.
1088 *
1089 * @param sb Superblock
1090 * @param feature Feature to be checked
1091 *
1092 * @return True, if filesystem supports the feature
1093 *
1094 */
1095bool ext4_superblock_has_feature_incompatible(ext4_superblock_t *sb,
1096 uint32_t feature)
1097{
1098 if (ext4_superblock_get_features_incompatible(sb) & feature)
1099 return true;
1100
1101 return false;
1102}
1103
1104/** Check if filesystem supports read-only compatible feature.
1105 *
1106 * @param sb Superblock
1107 * @param feature Feature to be checked
1108 *
1109 * @return True, if filesystem supports the feature
1110 *
1111 */
1112bool ext4_superblock_has_feature_read_only(ext4_superblock_t *sb,
1113 uint32_t feature)
1114{
1115 if (ext4_superblock_get_features_read_only(sb) & feature)
1116 return true;
1117
1118 return false;
1119}
1120
1121/** Read superblock directly from block device.
1122 *
1123 * @param service_id Block device identifier
1124 * @param sb Output pointer to memory structure
1125 *
1126 * @return Eerror code.
1127 *
1128 */
1129errno_t ext4_superblock_read_direct(service_id_t service_id, ext4_superblock_t **sb)
1130{
1131 /* Allocated memory for superblock structure */
1132 void *data = malloc(EXT4_SUPERBLOCK_SIZE);
1133 if (data == NULL)
1134 return ENOMEM;
1135
1136 /* Read data from block device */
1137 errno_t rc = block_read_bytes_direct(service_id, EXT4_SUPERBLOCK_OFFSET,
1138 EXT4_SUPERBLOCK_SIZE, data);
1139
1140 if (rc != EOK) {
1141 free(data);
1142 return rc;
1143 }
1144
1145 /* Set output value */
1146 (*sb) = data;
1147
1148 return EOK;
1149}
1150
1151/** Write superblock structure directly to block device.
1152 *
1153 * @param service_id Block device identifier
1154 * @param sb Superblock to be written
1155 *
1156 * @return Error code
1157 *
1158 */
1159errno_t ext4_superblock_write_direct(service_id_t service_id, ext4_superblock_t *sb)
1160{
1161 /* Load physical block size from block device */
1162 size_t phys_block_size;
1163 errno_t rc = block_get_bsize(service_id, &phys_block_size);
1164 if (rc != EOK)
1165 return rc;
1166
1167 /* Compute address of the first block */
1168 uint64_t first_block = EXT4_SUPERBLOCK_OFFSET / phys_block_size;
1169
1170 /* Compute number of block to write */
1171 size_t block_count = EXT4_SUPERBLOCK_SIZE / phys_block_size;
1172
1173 /* Check alignment */
1174 if (EXT4_SUPERBLOCK_SIZE % phys_block_size)
1175 block_count++;
1176
1177 /* Write data */
1178 return block_write_direct(service_id, first_block, block_count, sb);
1179}
1180
1181/** Release the memory allocated for the superblock structure
1182 *
1183 * @param sb Superblock to be freed
1184 *
1185 */
1186void ext4_superblock_release(ext4_superblock_t *sb)
1187{
1188 free(sb);
1189}
1190
1191/** Check sanity of the superblock.
1192 *
1193 * This check is performed at mount time.
1194 * Checks are described by one-line comments in the code.
1195 *
1196 * @param sb Superblock to check
1197 *
1198 * @return Error code
1199 *
1200 */
1201errno_t ext4_superblock_check_sanity(ext4_superblock_t *sb)
1202{
1203 if (ext4_superblock_get_magic(sb) != EXT4_SUPERBLOCK_MAGIC)
1204 return ENOTSUP;
1205
1206 if (ext4_superblock_get_inodes_count(sb) == 0)
1207 return ENOTSUP;
1208
1209 if (ext4_superblock_get_blocks_count(sb) == 0)
1210 return ENOTSUP;
1211
1212 if (ext4_superblock_get_blocks_per_group(sb) == 0)
1213 return ENOTSUP;
1214
1215 if (ext4_superblock_get_inodes_per_group(sb) == 0)
1216 return ENOTSUP;
1217
1218 if (ext4_superblock_get_inode_size(sb) < 128)
1219 return ENOTSUP;
1220
1221 if (ext4_superblock_get_first_inode(sb) < 11)
1222 return ENOTSUP;
1223
1224 if (ext4_superblock_get_desc_size(sb) <
1225 EXT4_MIN_BLOCK_GROUP_DESCRIPTOR_SIZE)
1226 return ENOTSUP;
1227
1228 if (ext4_superblock_get_desc_size(sb) >
1229 EXT4_MAX_BLOCK_GROUP_DESCRIPTOR_SIZE)
1230 return ENOTSUP;
1231
1232 return EOK;
1233}
1234
1235/** Compute number of block groups in the filesystem.
1236 *
1237 * @param sb Superblock
1238 *
1239 * @return Number of block groups
1240 *
1241 */
1242uint32_t ext4_superblock_get_block_group_count(ext4_superblock_t *sb)
1243{
1244 uint64_t blocks_count = ext4_superblock_get_blocks_count(sb);
1245 uint32_t blocks_per_group = ext4_superblock_get_blocks_per_group(sb);
1246
1247 uint32_t block_groups_count = blocks_count / blocks_per_group;
1248
1249 if (blocks_count % blocks_per_group)
1250 block_groups_count++;
1251
1252 return block_groups_count;
1253}
1254
1255/** Compute number of blocks in specified block group.
1256 *
1257 * @param sb Superblock
1258 * @param bgid Block group index
1259 *
1260 * @return Number of blocks
1261 *
1262 */
1263uint32_t ext4_superblock_get_blocks_in_group(ext4_superblock_t *sb, uint32_t bgid)
1264{
1265 uint32_t block_group_count =
1266 ext4_superblock_get_block_group_count(sb);
1267 uint32_t blocks_per_group =
1268 ext4_superblock_get_blocks_per_group(sb);
1269 uint64_t total_blocks =
1270 ext4_superblock_get_blocks_count(sb);
1271
1272 if (bgid < block_group_count - 1)
1273 return blocks_per_group;
1274 else
1275 return (total_blocks - ((block_group_count - 1) * blocks_per_group));
1276}
1277
1278/** Compute number of i-nodes in specified block group.
1279 *
1280 * @param sb Superblock
1281 * @param bgid Block group index
1282 *
1283 * @return Number of i-nodes
1284 *
1285 */
1286uint32_t ext4_superblock_get_inodes_in_group(ext4_superblock_t *sb, uint32_t bgid)
1287{
1288 uint32_t block_group_count =
1289 ext4_superblock_get_block_group_count(sb);
1290 uint32_t inodes_per_group =
1291 ext4_superblock_get_inodes_per_group(sb);
1292 uint32_t total_inodes =
1293 ext4_superblock_get_inodes_count(sb);
1294
1295 if (bgid < block_group_count - 1)
1296 return inodes_per_group;
1297 else
1298 return (total_inodes - ((block_group_count - 1) * inodes_per_group));
1299}
1300
1301/** Get the backup groups used with SPARSE_SUPER2
1302 *
1303 * @param sb Pointer to the superblock
1304 * @param g1 Output pointer to the first backup group
1305 * @param g2 Output pointer to the second backup group
1306 */
1307void ext4_superblock_get_backup_groups_sparse2(ext4_superblock_t *sb,
1308 uint32_t *g1, uint32_t *g2)
1309{
1310 *g1 = uint32_t_le2host(sb->backup_bgs[0]);
1311 *g2 = uint32_t_le2host(sb->backup_bgs[1]);
1312}
1313
1314/** Set the backup groups (SPARSE SUPER2)
1315 *
1316 * @param sb Pointer to the superblock
1317 * @param g1 Index of the first group
1318 * @param g2 Index of the second group
1319 */
1320void ext4_superblock_set_backup_groups_sparse2(ext4_superblock_t *sb,
1321 uint32_t g1, uint32_t g2)
1322{
1323 sb->backup_bgs[0] = host2uint32_t_le(g1);
1324 sb->backup_bgs[1] = host2uint32_t_le(g2);
1325}
1326
1327/** Get the number of blocks (per group) reserved to GDT expansion
1328 *
1329 * @param sb Pointer to the superblock
1330 *
1331 * @return Number of blocks
1332 */
1333uint32_t ext4_superblock_get_reserved_gdt_blocks(ext4_superblock_t *sb)
1334{
1335 return uint32_t_le2host(sb->reserved_gdt_blocks);
1336}
1337
1338/** Set the number of blocks (per group) reserved to GDT expansion
1339 *
1340 * @param sb Pointer to the superblock
1341 * @param n Number of reserved blocks
1342 */
1343void ext4_superblock_set_reserved_gdt_blocks(ext4_superblock_t *sb,
1344 uint32_t n)
1345{
1346 sb->reserved_gdt_blocks = host2uint32_t_le(n);
1347}
1348
1349/**
1350 * @}
1351 */
Note: See TracBrowser for help on using the repository browser.