source: mainline/uspace/lib/ext4/src/superblock.c@ fcb0d76

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since fcb0d76 was fcb0d76, checked in by Jiri Svoboda <jiri@…>, 8 years ago

Libext4 should try to include what it uses.

  • 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 libext4_superblock.c
36 * @brief Ext4 superblock operations.
37 */
38
39#include <block.h>
40#include <byteorder.h>
41#include <errno.h>
42#include <malloc.h>
43#include <mem.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 */
1129int 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 int 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 */
1159int 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 int 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 */
1201int 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.