source: mainline/uspace/lib/ext4/libext4_superblock.c@ 22fb7ab

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 22fb7ab was eb94d84, checked in by Maurizio Lombardi <m.lombardi85@…>, 10 years ago

libext4: fix memory leak, release the superblock structure if the mount operation fails

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