-
Notifications
You must be signed in to change notification settings - Fork 110
/
super.c
94 lines (73 loc) · 2.64 KB
/
super.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*
* Copyright (c) 2010, Gerard Lledó Vives, [email protected]
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. See README and COPYING for
* more details.
*/
#include "types/ext4_super.h"
#include "disk.h"
#include "logging.h"
#include "super.h"
#define GROUP_DESC_MIN_SIZE 0x20
static struct ext4_super_block super;
static struct ext4_group_desc *gdesc_table;
static uint64_t super_block_group_size(void)
{
return BLOCKS2BYTES(super.s_blocks_per_group);
}
static uint32_t super_n_block_groups(void)
{
uint32_t n = (super.s_blocks_count_lo + super.s_blocks_per_group - 1) / super.s_blocks_per_group;
return n ? n : 1;
}
static uint32_t super_group_desc_size(void)
{
if (!super.s_desc_size) return GROUP_DESC_MIN_SIZE;
else return sizeof(struct ext4_group_desc);
}
uint32_t super_block_size(void) {
return ((uint64_t)1) << (super.s_log_block_size + 10);
}
uint32_t super_inodes_per_group(void)
{
return super.s_inodes_per_group;
}
uint32_t super_inode_size(void)
{
return super.s_inode_size;
}
int super_fill(void)
{
disk_read(BOOT_SECTOR_SIZE, sizeof(struct ext4_super_block), &super);
INFO("BLOCK SIZE: %i", super_block_size());
INFO("BLOCK GROUP SIZE: %i", super_block_group_size());
INFO("N BLOCK GROUPS: %i", super_n_block_groups());
INFO("INODE SIZE: %i", super_inode_size());
INFO("INODES PER GROUP: %i", super_inodes_per_group());
return 0;
}
/* FIXME: Handle bg_inode_table_hi when size > GROUP_DESC_MIN_SIZE */
off_t super_group_inode_table_offset(uint32_t inode_num)
{
uint32_t n_group = inode_num / super_inodes_per_group();
ASSERT(n_group < super_n_block_groups());
DEBUG("Inode table offset: 0x%x", gdesc_table[n_group].bg_inode_table_lo);
return BLOCKS2BYTES(gdesc_table[n_group].bg_inode_table_lo);
}
/* struct ext4_group_desc might be bigger than on disk structure, if we are not
* using big ones. That info is in the superblock. Be careful when allocating
* or manipulating this pointers. */
int super_group_fill(void)
{
gdesc_table = malloc(sizeof(struct ext4_group_desc) * super_n_block_groups());
for (uint32_t i = 0; i < super_n_block_groups(); i++) {
off_t bg_off = ALIGN_TO_BLOCKSIZE(BOOT_SECTOR_SIZE + sizeof(struct ext4_super_block));
bg_off += i * super_group_desc_size();
/* disk advances super_group_desc_size(), pointer sizeof(struct...).
* These values might be different!!! */
disk_read(bg_off, super_group_desc_size(), &gdesc_table[i]);
}
return 0;
}