source: mainline/uspace/lib/ext4/libext4_superblock.c@ 2add9ec

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

Superblock comments

  • Property mode set to 100644
File size: 25.7 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/**
34 * @file libext4_superblock.c
35 * @brief Ext4 superblock operations.
36 */
37
38#include <byteorder.h>
39#include <errno.h>
40#include <libblock.h>
41#include <malloc.h>
42#include "libext4.h"
43
44/** Get number of i-nodes in the whole filesystem.
45 *
46 * @param sb superblock
47 * @return number of i-nodes
48 */
49uint32_t ext4_superblock_get_inodes_count(ext4_superblock_t *sb)
50{
51 return uint32_t_le2host(sb->inodes_count);
52}
53
54/** Set number of i-nodes in the whole filesystem.
55 *
56 * @param sb superblock
57 * @param count number of i-nodes
58 */
59void ext4_superblock_set_inodes_count(ext4_superblock_t *sb, uint32_t count)
60{
61 sb->inodes_count = host2uint32_t_le(count);
62}
63
64/** Get number of data blocks in the whole filesystem.
65 *
66 * @param sb superblock
67 * @return number of data blocks
68 */
69uint64_t ext4_superblock_get_blocks_count(ext4_superblock_t *sb)
70{
71 return ((uint64_t)uint32_t_le2host(sb->blocks_count_hi) << 32) |
72 uint32_t_le2host(sb->blocks_count_lo);
73}
74
75/** Set number of data blocks in the whole filesystem.
76 *
77 * @param sb superblock
78 * @param count number of data blocks
79 */
80void ext4_superblock_set_blocks_count(ext4_superblock_t *sb, uint64_t count)
81{
82 sb->blocks_count_lo = host2uint32_t_le((count << 32) >> 32);
83 sb->blocks_count_hi = host2uint32_t_le(count >> 32);
84}
85
86/** Get number of reserved data blocks in the whole filesystem.
87 *
88 * @param sb superblock
89 * @return number of reserved data blocks
90 */
91uint64_t ext4_superblock_get_reserved_blocks_count(ext4_superblock_t *sb)
92{
93 return ((uint64_t)uint32_t_le2host(sb->reserved_blocks_count_hi) << 32) |
94 uint32_t_le2host(sb->reserved_blocks_count_lo);
95}
96
97/** Set number of reserved data blocks in the whole filesystem.
98 *
99 * @param sb superblock
100 * @param count number of reserved data blocks
101 */
102void ext4_superblock_set_reserved_blocks_count(ext4_superblock_t *sb, uint64_t count)
103{
104 sb->reserved_blocks_count_lo = host2uint32_t_le((count << 32) >> 32);
105 sb->reserved_blocks_count_hi = host2uint32_t_le(count >> 32);
106}
107
108/** Get number of free data blocks in the whole filesystem.
109 *
110 * @param sb superblock
111 * @return number of free data blocks
112 */
113uint64_t ext4_superblock_get_free_blocks_count(ext4_superblock_t *sb)
114{
115 return ((uint64_t)uint32_t_le2host(sb->free_blocks_count_hi) << 32) |
116 uint32_t_le2host(sb->free_blocks_count_lo);
117}
118
119/** Set number of free data blocks in the whole filesystem.
120 *
121 * @param sb superblock
122 * @param count number of free data blocks
123 */
124void ext4_superblock_set_free_blocks_count(ext4_superblock_t *sb, uint64_t count)
125{
126 sb->free_blocks_count_lo = host2uint32_t_le((count << 32) >> 32);
127 sb->free_blocks_count_hi = host2uint32_t_le(count >> 32);
128}
129
130/** Get number of free i-nodes in the whole filesystem.
131 *
132 * @param sb superblock
133 * @return number of free i-nodes
134 */
135uint32_t ext4_superblock_get_free_inodes_count(ext4_superblock_t *sb)
136{
137 return uint32_t_le2host(sb->free_inodes_count);
138}
139
140/** Set number of free i-nodes in the whole filesystem.
141 *
142 * @param sb superblock
143 * @param count number of free i-nodes
144 */
145void ext4_superblock_set_free_inodes_count(ext4_superblock_t *sb, uint32_t count)
146{
147 sb->free_inodes_count = host2uint32_t_le(count);
148}
149
150/** Get index of first data block (block, where is located superblock)
151 *
152 * @param sb superblock
153 * @return index of the first data block
154 */
155uint32_t ext4_superblock_get_first_data_block(ext4_superblock_t *sb)
156{
157 return uint32_t_le2host(sb->first_data_block);
158}
159
160/** Set index of first data block (block, where is located superblock)
161 *
162 * @param sb superblock
163 * @param first index of the first data block
164 */
165void ext4_superblock_set_first_data_block(ext4_superblock_t *sb, uint32_t first)
166{
167 sb->first_data_block = host2uint32_t_le(first);
168}
169
170/** Get logarithmic block size (1024 << size == block_size)
171 *
172 * @param sb superblock
173 * @return logarithmic block size
174 */
175uint32_t ext4_superblock_get_log_block_size(ext4_superblock_t *sb)
176{
177 return uint32_t_le2host(sb->log_block_size);
178}
179
180/** Set logarithmic block size (1024 << size == block_size)
181 *
182 * @param sb superblock
183 * @return logarithmic block size
184 */
185void ext4_superblock_set_log_block_size(ext4_superblock_t *sb, uint32_t log_size)
186{
187 sb->log_block_size = host2uint32_t_le(log_size);
188}
189
190/** Get size of data block (in bytes).
191 *
192 * @param sb superblock
193 * @return size of data block
194 */
195uint32_t ext4_superblock_get_block_size(ext4_superblock_t *sb)
196{
197 return 1024 << ext4_superblock_get_log_block_size(sb);
198}
199
200/** Set size of data block (in bytes).
201 *
202 * @param sb superblock
203 * @param size size of data block (must be power of 2, at least 1024)
204 */
205void ext4_superblock_set_block_size(ext4_superblock_t *sb, uint32_t size)
206{
207 uint32_t log = 0;
208 uint32_t tmp = size / EXT4_MIN_BLOCK_SIZE;
209
210 tmp >>= 1;
211 while (tmp) {
212 log++;
213 tmp >>= 1;
214 }
215
216 ext4_superblock_set_log_block_size(sb, log);
217}
218
219/** Get number of data blocks per block group (except last BG)
220 *
221 * @param sb superblock
222 * @return data blocks per block group
223 */
224uint32_t ext4_superblock_get_blocks_per_group(ext4_superblock_t *sb)
225{
226 return uint32_t_le2host(sb->blocks_per_group);
227}
228
229/** Set number of data blocks per block group (except last BG)
230 *
231 * @param sb superblock
232 * @param blocks data blocks per block group
233 */
234void ext4_superblock_set_blocks_per_group(ext4_superblock_t *sb, uint32_t blocks)
235{
236 sb->blocks_per_group = host2uint32_t_le(blocks);
237}
238
239/** Get number of i-nodes per block group (except last BG)
240 *
241 * @param sb superblock
242 * @return i-nodes per block group
243 */
244uint32_t ext4_superblock_get_inodes_per_group(ext4_superblock_t *sb)
245{
246 return uint32_t_le2host(sb->inodes_per_group);
247}
248
249/** Set number of i-nodes per block group (except last BG)
250 *
251 * @param sb superblock
252 * @param inodes i-nodes per block group
253 */
254void ext4_superblock_set_inodes_per_group(ext4_superblock_t *sb, uint32_t inodes)
255{
256 sb->inodes_per_group = host2uint32_t_le(inodes);
257}
258
259/** Get time when filesystem was mounted (POSIX time).
260 *
261 * @param sb superblock
262 * @return mount time
263 */
264uint32_t ext4_superblock_get_mount_time(ext4_superblock_t *sb)
265{
266 return uint32_t_le2host(sb->mount_time);
267}
268
269/** Set time when filesystem was mounted (POSIX time).
270 *
271 * @param sb superblock
272 * @param time mount time
273 */
274void ext4_superblock_set_mount_time(ext4_superblock_t *sb, uint32_t time)
275{
276 sb->mount_time = host2uint32_t_le(time);
277}
278
279/** Get time when filesystem was last accesed by write operation (POSIX time).
280 *
281 * @param sb superblock
282 * @return write time
283 */
284uint32_t ext4_superblock_get_write_time(ext4_superblock_t *sb)
285{
286 return uint32_t_le2host(sb->write_time);
287}
288
289/** Set time when filesystem was last accesed by write operation (POSIX time).
290 *
291 * @param sb superblock
292 * @param time write time
293 */
294void ext4_superblock_set_write_time(ext4_superblock_t *sb, uint32_t time)
295{
296 sb->write_time = host2uint32_t_le(time);
297}
298
299/** Get number of mount from last filesystem check.
300 *
301 * @param sb superblock
302 * @return number of mounts
303 */
304uint16_t ext4_superblock_get_mount_count(ext4_superblock_t *sb)
305{
306 return uint16_t_le2host(sb->mount_count);
307}
308
309/** Set number of mount from last filesystem check.
310 *
311 * @param sb superblock
312 * @param count number of mounts
313 */
314void ext4_superblock_set_mount_count(ext4_superblock_t *sb, uint16_t count)
315{
316 sb->mount_count = host2uint16_t_le(count);
317}
318
319/** Get maximum number of mount from last filesystem check.
320 *
321 * @param sb superblock
322 * @return maximum number of mounts
323 */
324uint16_t ext4_superblock_get_max_mount_count(ext4_superblock_t *sb)
325{
326 return uint16_t_le2host(sb->max_mount_count);
327}
328
329/** Set maximum number of mount from last filesystem check.
330 *
331 * @param sb superblock
332 * @param count maximum number of mounts
333 */
334void ext4_superblock_set_max_mount_count(ext4_superblock_t *sb, uint16_t count)
335{
336 sb->max_mount_count = host2uint16_t_le(count);
337}
338
339/** Get superblock magic value.
340 *
341 * @param sb superblock
342 * @return magic value
343 */
344uint16_t ext4_superblock_get_magic(ext4_superblock_t *sb)
345{
346 return uint16_t_le2host(sb->magic);
347}
348
349/** Set superblock magic value.
350 *
351 * @param sb superblock
352 * @param magic value
353 */
354void ext4_superblock_set_magic(ext4_superblock_t *sb, uint16_t magic)
355{
356 sb->magic = host2uint16_t_le(magic);
357}
358
359/** Get filesystem state.
360 *
361 * @param sb superblock
362 * @return filesystem state
363 */
364uint16_t ext4_superblock_get_state(ext4_superblock_t *sb)
365{
366 return uint16_t_le2host(sb->state);
367}
368
369/** Set filesystem state.
370 *
371 * @param sb superblock
372 * @param state filesystem state
373 */
374void ext4_superblock_set_state(ext4_superblock_t *sb, uint16_t state)
375{
376 sb->state = host2uint16_t_le(state);
377}
378
379/** Get behavior code when errors detected.
380 *
381 * @param sb superblock
382 * @return behavior code
383 */
384uint16_t ext4_superblock_get_errors(ext4_superblock_t *sb)
385{
386 return uint16_t_le2host(sb->errors);
387}
388
389/** Set behavior code when errors detected.
390 *
391 * @param sb superblock
392 * @param errors behavior code
393 */
394void ext4_superblock_set_errors(ext4_superblock_t *sb, uint16_t errors)
395{
396 sb->errors = host2uint16_t_le(errors);
397}
398
399/** Get minor revision level of the filesystem.
400 *
401 * @param sb superblock
402 * @return minor revision level
403 */
404uint16_t ext4_superblock_get_minor_rev_level(ext4_superblock_t *sb)
405{
406 return uint16_t_le2host(sb->minor_rev_level);
407}
408
409/** Set minor revision level of the filesystem.
410 *
411 * @param sb superblock
412 * @param level minor revision level
413 */
414void ext4_superblock_set_minor_rev_level(ext4_superblock_t *sb, uint16_t level)
415{
416 sb->minor_rev_level = host2uint16_t_le(level);
417}
418
419/** Get time of the last filesystem check.
420 *
421 * @param sb superblock
422 * @return time of the last check (POSIX)
423 */
424uint32_t ext4_superblock_get_last_check_time(ext4_superblock_t *sb)
425{
426 return uint32_t_le2host(sb->last_check_time);
427}
428
429/** Set time of the last filesystem check.
430 *
431 * @param sb superblock
432 * @param time time of the last check (POSIX)
433 */
434void ext4_superblock_set_last_check_time(ext4_superblock_t *sb, uint32_t time)
435{
436 sb->state = host2uint32_t_le(time);
437}
438
439/** Get maximum time interval between two filesystem checks.
440 *
441 * @param sb superblock
442 * @return time interval between two check (POSIX)
443 */
444uint32_t ext4_superblock_get_check_interval(ext4_superblock_t *sb){
445 return uint32_t_le2host(sb->check_interval);
446}
447
448/** Set maximum time interval between two filesystem checks.
449 *
450 * @param sb superblock
451 * @param interval time interval between two check (POSIX)
452 */
453void ext4_superblock_set_check_interval(ext4_superblock_t *sb, uint32_t interval)
454{
455 sb->check_interval = host2uint32_t_le(interval);
456}
457
458/** Get operation system identifier, on which the filesystem was created.
459 *
460 * @param sb superblock
461 * @return operation system identifier
462 */
463uint32_t ext4_superblock_get_creator_os(ext4_superblock_t *sb)
464{
465 return uint32_t_le2host(sb->creator_os);
466}
467
468/** Set operation system identifier, on which the filesystem was created.
469 *
470 * @param sb superblock
471 * @param os operation system identifier
472 */
473void ext4_superblock_set_creator_os(ext4_superblock_t *sb, uint32_t os)
474{
475 sb->creator_os = host2uint32_t_le(os);
476}
477
478/** Get revision level of the filesystem.
479 *
480 * @param sb superblock
481 * @return revision level
482 */
483uint32_t ext4_superblock_get_rev_level(ext4_superblock_t *sb)
484{
485 return uint32_t_le2host(sb->rev_level);
486}
487
488/** Set revision level of the filesystem.
489 *
490 * @param sb superblock
491 * @param level revision level
492 */
493void ext4_superblock_set_rev_level(ext4_superblock_t *sb, uint32_t level)
494{
495 sb->rev_level = host2uint32_t_le(level);
496}
497
498/** Get default user id for reserved blocks.
499 *
500 * @param sb superblock
501 * @return default user id for reserved blocks.
502 */
503uint16_t ext4_superblock_get_def_resuid(ext4_superblock_t *sb)
504{
505 return uint16_t_le2host(sb->def_resuid);
506}
507
508/** Set default user id for reserved blocks.
509 *
510 * @param sb superblock
511 * @param uid default user id for reserved blocks.
512 */
513void ext4_superblock_set_def_resuid(ext4_superblock_t *sb, uint16_t uid)
514{
515 sb->def_resuid = host2uint16_t_le(uid);
516}
517
518/** Get default group id for reserved blocks.
519 *
520 * @param sb superblock
521 * @return default group id for reserved blocks.
522 */
523uint16_t ext4_superblock_get_def_resgid(ext4_superblock_t *sb)
524{
525 return uint16_t_le2host(sb->def_resgid);
526}
527
528/** Set default group id for reserved blocks.
529 *
530 * @param sb superblock
531 * @param gid default group id for reserved blocks.
532 */
533void ext4_superblock_set_def_resgid(ext4_superblock_t *sb, uint16_t gid)
534{
535 sb->def_resgid = host2uint16_t_le(gid);
536}
537
538/** Get index of the first i-node, which can be used for allocation.
539 *
540 * @param sb superblock
541 * @return i-node index
542 */
543uint32_t ext4_superblock_get_first_inode(ext4_superblock_t *sb)
544{
545 return uint32_t_le2host(sb->first_inode);
546}
547
548/** Set index of the first i-node, which can be used for allocation.
549 *
550 * @param sb superblock
551 * @param first_inode i-node index
552 */
553void ext4_superblock_set_first_inode(ext4_superblock_t *sb, uint32_t first_inode)
554{
555 sb->first_inode = host2uint32_t_le(first_inode);
556}
557
558/** Get size of i-node structure.
559 *
560 * For the oldest revision return constant number.
561 *
562 * @param sb superblock
563 * @return size of i-node structure
564 */
565uint16_t ext4_superblock_get_inode_size(ext4_superblock_t *sb)
566{
567 if (ext4_superblock_get_rev_level(sb) == 0) {
568 return EXT4_REV0_INODE_SIZE;
569 }
570 return uint16_t_le2host(sb->inode_size);
571}
572
573/** Set size of i-node structure.
574 *
575 * @param sb superblock
576 * @param size size of i-node structure
577 */
578void ext4_superblock_set_inode_size(ext4_superblock_t *sb, uint16_t size)
579{
580 sb->inode_size = host2uint16_t_le(size);
581}
582
583/** Get index of block group, where superblock copy is located.
584 *
585 * @param sb superblock
586 * @return block group index
587 */
588uint16_t ext4_superblock_get_block_group_index(ext4_superblock_t *sb)
589{
590 return uint16_t_le2host(sb->block_group_index);
591}
592
593/** Set index of block group, where superblock copy is located.
594 *
595 * @param sb superblock
596 * @param bgid block group index
597 */
598void ext4_superblock_set_block_group_index(ext4_superblock_t *sb, uint16_t bgid)
599{
600 sb->block_group_index = host2uint16_t_le(bgid);
601}
602
603/** Get compatible features supported by the filesystem.
604 *
605 * @param sb superblock
606 * @return compatible features bitmap
607 */
608uint32_t ext4_superblock_get_features_compatible(ext4_superblock_t *sb)
609{
610 return uint32_t_le2host(sb->features_compatible);
611}
612
613/** Set compatible features supported by the filesystem.
614 *
615 * @param sb superblock
616 * @param features compatible features bitmap
617 */
618void ext4_superblock_set_features_compatible(ext4_superblock_t *sb, uint32_t features)
619{
620 sb->features_compatible = host2uint32_t_le(features);
621}
622
623/** Get incompatible features supported by the filesystem.
624 *
625 * @param sb superblock
626 * @return incompatible features bitmap
627 */
628uint32_t ext4_superblock_get_features_incompatible(ext4_superblock_t *sb)
629{
630 return uint32_t_le2host(sb->features_incompatible);
631}
632
633/** Set incompatible features supported by the filesystem.
634 *
635 * @param sb superblock
636 * @param features incompatible features bitmap
637 */
638void ext4_superblock_set_features_incompatible(ext4_superblock_t *sb, uint32_t features)
639{
640 sb->features_incompatible = host2uint32_t_le(features);
641}
642
643/** Get compatible features supported by the filesystem.
644 *
645 * @param sb superblock
646 * @return read-only compatible features bitmap
647 */
648uint32_t ext4_superblock_get_features_read_only(ext4_superblock_t *sb)
649{
650 return uint32_t_le2host(sb->features_read_only);
651}
652
653/** Set compatible features supported by the filesystem.
654 *
655 * @param sb superblock
656 * @param feature read-only compatible features bitmap
657 */
658void ext4_superblock_set_features_read_only(ext4_superblock_t *sb, uint32_t features)
659{
660 sb->features_read_only = host2uint32_t_le(features);
661}
662
663/** Get UUID of the filesystem.
664 *
665 * @param sb superblock
666 * @return pointer to UUID array
667 */
668const uint8_t * ext4_superblock_get_uuid(ext4_superblock_t *sb)
669{
670 return sb->uuid;
671}
672
673/** Set UUID of the filesystem.
674 *
675 * @param sb superblock
676 * @param uuid pointer to UUID array
677 */
678void ext4_superblock_set_uuid(ext4_superblock_t *sb, const uint8_t *uuid)
679{
680 memcpy(sb->uuid, uuid, sizeof(sb->uuid));
681}
682
683/** Get name of the filesystem volume.
684 *
685 * @param sb superblock
686 * @return name of the volume
687 */
688const char * ext4_superblock_get_volume_name(ext4_superblock_t *sb)
689{
690 return sb->volume_name;
691}
692
693/** Set name of the filesystem volume.
694 *
695 * @param sb superblock
696 * @param name new name of the volume
697 */
698void ext4_superblock_set_volume_name(ext4_superblock_t *sb, const char *name)
699{
700 memcpy(sb->volume_name, name, sizeof(sb->volume_name));
701}
702
703/** Get name of the directory, where this filesystem was mounted at last.
704 *
705 * @param sb superblock
706 * @return directory name
707 */
708const char * ext4_superblock_get_last_mounted(ext4_superblock_t *sb)
709{
710 return sb->last_mounted;
711}
712
713/** Set name of the directory, where this filesystem was mounted at last.
714 *
715 * @param sb superblock
716 * @param last directory name
717 */
718void ext4_superblock_set_last_mounted(ext4_superblock_t *sb, const char *last)
719{
720 memcpy(sb->last_mounted, last, sizeof(sb->last_mounted));
721}
722
723/** Get last orphaned i-node index.
724 *
725 * Orphans are stored in linked list.
726 *
727 * @param sb superblock
728 * @return last orphaned i-node index
729 */
730uint32_t ext4_superblock_get_last_orphan(ext4_superblock_t *sb)
731{
732 return uint32_t_le2host(sb->last_orphan);
733}
734
735/** Set last orphaned i-node index.
736 *
737 * Orphans are stored in linked list.
738 *
739 * @param sb superblock
740 * @param last_orphan last orphaned i-node index
741 */
742void ext4_superblock_set_last_orphan(ext4_superblock_t *sb, uint32_t last_orphan)
743{
744 sb->last_orphan = host2uint32_t_le(last_orphan);
745}
746
747/** Get hash seed for directory index hash function.
748 *
749 * @param sb superblock
750 * @return hash seed pointer
751 */
752const uint32_t * ext4_superblock_get_hash_seed(ext4_superblock_t *sb)
753{
754 return sb->hash_seed;
755}
756
757/** Set hash seed for directory index hash function.
758 *
759 * @param sb superblock
760 * @param seed hash seed pointer
761 */
762void ext4_superblock_set_hash_seed(ext4_superblock_t *sb, const uint32_t *seed)
763{
764 memcpy(sb->hash_seed, seed, sizeof(sb->hash_seed));
765}
766
767/** Get default version of the hash algorithm version for directory index.
768 *
769 * @param sb superblock
770 * @return default hash version
771 */
772uint8_t ext4_superblock_get_default_hash_version(ext4_superblock_t *sb)
773{
774 return sb->default_hash_version;
775}
776
777/** Set default version of the hash algorithm version for directory index.
778 *
779 * @param sb superblock
780 * @param version default hash version
781 */
782void ext4_superblock_set_default_hash_version(ext4_superblock_t *sb, uint8_t version)
783{
784 sb->default_hash_version = version;
785}
786
787/** Get size of block group descriptor structure.
788 *
789 * Output value is checked for minimal size.
790 *
791 * @param sb superblock
792 * @return size of block group descriptor
793 */
794uint16_t ext4_superblock_get_desc_size(ext4_superblock_t *sb)
795{
796 uint16_t size = uint16_t_le2host(sb->desc_size);
797
798 if (size < EXT4_BLOCK_MIN_GROUP_DESCRIPTOR_SIZE) {
799 size = EXT4_BLOCK_MIN_GROUP_DESCRIPTOR_SIZE;
800 }
801
802 return size;
803}
804
805/** Set size of block group descriptor structure.
806 *
807 * Input value is checked for minimal size.
808 *
809 * @param sb superblock
810 * @param size size of block group descriptor
811 */
812void ext4_superblock_set_desc_size(ext4_superblock_t *sb, uint16_t size)
813{
814 if (size < EXT4_BLOCK_MIN_GROUP_DESCRIPTOR_SIZE) {
815 sb->desc_size = host2uint16_t_le(EXT4_BLOCK_MIN_GROUP_DESCRIPTOR_SIZE);
816 }
817
818 sb->desc_size = host2uint16_t_le(size);
819}
820
821/** Get superblock flags.
822 *
823 * @param sb superblock
824 * @return flags from the superblock
825 */
826uint32_t ext4_superblock_get_flags(ext4_superblock_t *sb)
827{
828 return uint32_t_le2host(sb->flags);
829}
830
831/** Set superblock flags.
832 *
833 * @param sb superblock
834 * @param flags flags for the superblock
835 */
836void ext4_superblock_set_flags(ext4_superblock_t *sb, uint32_t flags)
837{
838 sb->flags = host2uint32_t_le(flags);
839}
840
841/*
842 * More complex superblock operations
843 */
844
845/** Check if superblock has specified flag.
846 *
847 * @param sb superblock
848 * @param flag flag to be checked
849 * @return true, if superblock has the flag
850 */
851bool ext4_superblock_has_flag(ext4_superblock_t *sb, uint32_t flag)
852{
853 if (ext4_superblock_get_flags(sb) & flag) {
854 return true;
855 }
856 return false;
857}
858
859/** Check if filesystem supports compatible feature.
860 *
861 * @param sb superblock
862 * @param feature feature to be checked
863 * @return true, if filesystem supports the feature
864 */
865bool ext4_superblock_has_feature_compatible(ext4_superblock_t *sb, uint32_t feature)
866{
867 if (ext4_superblock_get_features_compatible(sb) & feature) {
868 return true;
869 }
870 return false;
871}
872
873/** Check if filesystem supports incompatible feature.
874 *
875 * @param sb superblock
876 * @param feature feature to be checked
877 * @return true, if filesystem supports the feature
878 */
879bool ext4_superblock_has_feature_incompatible(ext4_superblock_t *sb, uint32_t feature)
880{
881 if (ext4_superblock_get_features_incompatible(sb) & feature) {
882 return true;
883 }
884 return false;
885}
886
887/** Check if filesystem supports read-only compatible feature.
888 *
889 * @param sb superblock
890 * @param feature feature to be checked
891 * @return true, if filesystem supports the feature
892 */
893bool ext4_superblock_has_feature_read_only(ext4_superblock_t *sb, uint32_t feature)
894{
895 if (ext4_superblock_get_features_read_only(sb) & feature) {
896 return true;
897 }
898 return false;
899}
900
901/** Read superblock directly from block device.
902 *
903 * @param service_id block device identifier
904 * @param sb output pointer to memory structure
905 * @return error code.
906 */
907int ext4_superblock_read_direct(service_id_t service_id,
908 ext4_superblock_t **sb)
909{
910 int rc;
911
912 // Allocated memory for superblock structure
913 void *data = malloc(EXT4_SUPERBLOCK_SIZE);
914 if (data == NULL) {
915 return ENOMEM;
916 }
917
918 // Read data from block device
919 rc = block_read_bytes_direct(service_id, EXT4_SUPERBLOCK_OFFSET,
920 EXT4_SUPERBLOCK_SIZE, data);
921
922 if (rc != EOK) {
923 free(data);
924 return rc;
925 }
926
927 // Set output value
928 (*sb) = data;
929
930 return EOK;
931}
932
933/** Write superblock structure directly to block device.
934 *
935 * @param service_id block device identifier
936 * @param sb superblock to be written
937 * @return error code
938 */
939int ext4_superblock_write_direct(service_id_t service_id,
940 ext4_superblock_t *sb)
941{
942 int rc;
943 uint32_t phys_block_size;
944
945 // Load physical block size from block device
946 rc = block_get_bsize(service_id, &phys_block_size);
947 if (rc != EOK) {
948 return rc;
949 }
950
951 // Compute address of the first block
952 uint64_t first_block = EXT4_SUPERBLOCK_OFFSET / phys_block_size;
953 // Compute number of block to write
954 uint32_t block_count = EXT4_SUPERBLOCK_SIZE / phys_block_size;
955
956 // Check alignment
957 if (EXT4_SUPERBLOCK_SIZE % phys_block_size) {
958 block_count++;
959 }
960
961 // Write data
962 return block_write_direct(service_id, first_block, block_count, sb);
963
964}
965
966/** TODO comment
967 *
968 */
969int ext4_superblock_check_sanity(ext4_superblock_t *sb)
970{
971 if (ext4_superblock_get_magic(sb) != EXT4_SUPERBLOCK_MAGIC) {
972 return ENOTSUP;
973 }
974
975 // block size
976 // desc size
977
978
979 // TODO more checks !!!
980
981 return EOK;
982}
983
984/** Compute number of block groups in the filesystem.
985 *
986 * @param sb superblock
987 * @return number of block groups
988 */
989uint32_t ext4_superblock_get_block_group_count(ext4_superblock_t *sb)
990{
991 uint64_t blocks_count = ext4_superblock_get_blocks_count(sb);
992 uint32_t blocks_per_group = ext4_superblock_get_blocks_per_group(sb);
993
994 uint32_t block_groups_count = blocks_count / blocks_per_group;
995
996 if (blocks_count % blocks_per_group) {
997 block_groups_count++;
998 }
999
1000 return block_groups_count;
1001
1002}
1003
1004/** Compute number of blocks in specified block group.
1005 *
1006 * @param sb superblock
1007 * @param bgid block group index
1008 * @return number of blocks
1009 */
1010uint32_t ext4_superblock_get_blocks_in_group(ext4_superblock_t *sb, uint32_t bgid)
1011{
1012 uint32_t block_group_count = ext4_superblock_get_block_group_count(sb);
1013 uint32_t blocks_per_group = ext4_superblock_get_blocks_per_group(sb);
1014 uint64_t total_blocks = ext4_superblock_get_blocks_count(sb);
1015
1016 if (bgid < block_group_count - 1) {
1017 return blocks_per_group;
1018 } else {
1019 return (total_blocks - ((block_group_count - 1) * blocks_per_group));
1020 }
1021
1022}
1023
1024/** Compute number of i-nodes in specified block group.
1025 *
1026 * @param sb superblock
1027 * @param bgid block group index
1028 * @return number of i-nodes
1029 */
1030uint32_t ext4_superblock_get_inodes_in_group(ext4_superblock_t *sb, uint32_t bgid)
1031{
1032 uint32_t block_group_count = ext4_superblock_get_block_group_count(sb);
1033 uint32_t inodes_per_group = ext4_superblock_get_inodes_per_group(sb);
1034 uint32_t total_inodes = ext4_superblock_get_inodes_count(sb);
1035
1036 if (bgid < block_group_count - 1) {
1037 return inodes_per_group;
1038 } else {
1039 return (total_inodes - ((block_group_count - 1) * inodes_per_group));
1040 }
1041
1042}
1043
1044/**
1045 * @}
1046 */
Note: See TracBrowser for help on using the repository browser.