Max OS 0.3
Loading...
Searching...
No Matches
MaxOS::filesystem::format::ext2::Ext2Volume Class Reference

Common operations for an ext2 volume that are used by both files & directories (like block & inode allocation) More...

#include <ext2.h>

Public Member Functions

 Ext2Volume (drivers::disk::Disk *disk, lba_t partition_offset)
 Construct a new Ext2 Volume object, reads the superblock and block group descriptors.
 
void write_block (uint32_t block_num, common::buffer_t *buffer) const
 write a single block from a buffer into onto the disk
 
void write_inode (uint32_t inode_num, inode_t *inode) const
 write an inode to the filesystem
 
uint32_t create_inode (bool is_directory)
 Allocates a new inode and sets the base metadata. Also allocates block 0 of the inode.
 
void free_inode (uint32_t inode)
 Mark an inode as free. Note: does NOT unallocated the inodes blocks, use free_group_blocks().
 
void read_block (uint32_t block_num, common::buffer_t *buffer) const
 Reads a single block from the disk into a buffer.
 
inode_t read_inode (uint32_t inode_num) const
 read an inode from the filesystem
 
uint32_t allocate_block ()
 Allocates a single block to be used by an inode.
 
common::Vector< uint32_tallocate_blocks (uint32_t amount)
 Allocates a set of blocks to be used by an inode.
 
uint32_t bytes_to_blocks (size_t bytes) const
 How many blocks are needed to contain a set amount of bytes.
 
void free_blocks (const common::Vector< uint32_t > &blocks)
 Frees a group of blocks. Preferably with adjacent blocks apearing next to each other but not enforced.
 

Public Attributes

drivers::disk::Diskdisk
 The disk that this volume is on.
 
lba_t partition_offset
 How far into the disk this partition starts.
 
superblock_t superblock
 The superblock of the ext2 filesystem.
 
block_group_descriptor_t ** block_groups
 The block group descriptors.
 
size_t block_size
 How large each block is (in bytes)
 
uint32_t block_group_descriptor_table_block
 Where the block group descriptor table starts.
 
uint32_t block_group_descriptor_table_size
 How many block groups are in the block group descriptor table.
 
uint32_t total_block_groups
 How many block groups are in the filesystem.
 
size_t pointers_per_block
 How many block pointers fit in a block.
 
uint32_t inodes_per_block
 How many inodes fit in a block.
 
uint32_t sectors_per_block
 How many sectors does a block take.
 
common::Spinlock ext2_lock
 Lock for synchronised access to the volume (.
 

Detailed Description

Common operations for an ext2 volume that are used by both files & directories (like block & inode allocation)

Todo:
Free blocks

Definition at line 322 of file ext2.h.

Constructor & Destructor Documentation

◆ Ext2Volume()

Ext2Volume::Ext2Volume ( drivers::disk::Disk disk,
lba_t  partition_offset 
)

Construct a new Ext2 Volume object, reads the superblock and block group descriptors.

Parameters
diskThe disk to read from
partition_offsetThe offset of the partition on the disk in sectors
Todo:
Should lock per file and not expose volume lock

Definition at line 27 of file ext2.cpp.

28: disk(disk),
30 superblock({})
31{
32
33 // Read superblock
37
38 // Validate signature
39 ASSERT(superblock.signature == 0xEF53, "Ext2 Filesystem doesnt have a valid signature\n");
40
41 // Version 0 has constant inode info
42 if(superblock.version_major < 1) {
43 superblock.first_inode = 11;
44 superblock.inode_size = 128;
45 }
46
47 // Parse the superblock
48 block_size = 1024 << superblock.block_size;
49 total_block_groups = (superblock.total_blocks + superblock.blocks_per_group - 1) / superblock.blocks_per_group;
55
56 // Read the block groups
61 for(uint32_t i = 0; i < sectors_to_read; ++i)
62 disk->read(bgdt_lba + i, &bg_buffer, 512);
63
64 // Store the block groups
65 for(uint32_t i = 0; i < total_block_groups; ++i) {
69 }
70}
Wrapper class for a region of bytes in memor in an attempt to add some memory safety....
Definition buffer.h:25
Stores the left, top, width and height of a rectangle.
Definition rectangle.h:22
void read(uint32_t sector, common::buffer_t *data_buffer)
read data from the disk into a buffer (max capacity 512 bytes)
Definition disk.cpp:26
size_t block_size
How large each block is (in bytes)
Definition ext2.h:342
block_group_descriptor_t ** block_groups
The block group descriptors.
Definition ext2.h:340
uint32_t block_group_descriptor_table_block
Where the block group descriptor table starts.
Definition ext2.h:343
size_t pointers_per_block
How many block pointers fit in a block.
Definition ext2.h:346
lba_t partition_offset
How far into the disk this partition starts.
Definition ext2.h:337
uint32_t block_group_descriptor_table_size
How many block groups are in the block group descriptor table.
Definition ext2.h:344
superblock_t superblock
The superblock of the ext2 filesystem.
Definition ext2.h:339
uint32_t sectors_per_block
How many sectors does a block take.
Definition ext2.h:348
uint32_t inodes_per_block
How many inodes fit in a block.
Definition ext2.h:347
uint32_t total_block_groups
How many block groups are in the filesystem.
Definition ext2.h:345
drivers::disk::Disk * disk
The disk that this volume is on.
Definition ext2.h:336
struct PACKED MaxOS::filesystem::format::ext2::BlockGroupDescriptor block_group_descriptor_t
Alias for BlockGroupDescriptor struct.
#define ASSERT(condition, format,...)
If the specified condition is not met then the kernel will crash with the specified message.
Definition logger.h:100
void * memcpy(void *destination, const void *source, uint64_t num)
Copies a block of memory from one location to another.
Definition memoryIO.cpp:165

Member Function Documentation

◆ allocate_block()

uint32_t Ext2Volume::allocate_block ( )

Allocates a single block to be used by an inode.

Returns
The new block number or 0 if the allocation failed

Definition at line 177 of file ext2.cpp.

177 {
178
179 return allocate_blocks(1)[0];
180}
common::Vector< uint32_t > allocate_blocks(uint32_t amount)
Allocates a set of blocks to be used by an inode.
Definition ext2.cpp:188

References allocate_blocks().

Referenced by create_inode().

◆ allocate_blocks()

Vector< uint32_t > Ext2Volume::allocate_blocks ( uint32_t  amount)

Allocates a set of blocks to be used by an inode.

Parameters
amountThe amount of blocks to allocate
Returns
A list of the allocated blocks or [0] if the allocation failed

Definition at line 188 of file ext2.cpp.

188 {
189
190 // No blocks to allocate
191 if(!amount)
192 return { 1, 0 };
193
194 // Find the block group with enough free blocks
197 if(block_group->free_blocks >= amount)
198 return allocate_group_blocks(bg_index, amount);
199
200 // No block group can contain the block so split across multiple
202 while(amount > 0) {
203
204 // Find the block group with most free blocks
206 uint32_t bg_index = 0;
208 if(block_groups[bg_index]->free_blocks > block_group->free_blocks)
210
211 // No space
212 if(block_group->free_blocks == 0)
213 return { 1, 0 };
214
215 // Allocate the remaining blocks
216 auto allocated = allocate_group_blocks(bg_index, 1);
217 amount -= allocated.size();
218 for(auto block : allocated)
219 result.push_back(block);
220 }
221
222 return result;
223}
void free_blocks(const common::Vector< uint32_t > &blocks)
Frees a group of blocks. Preferably with adjacent blocks apearing next to each other but not enforced...
Definition ext2.cpp:464

References block_groups, free_blocks(), and total_block_groups.

Referenced by allocate_block(), and MaxOS::filesystem::format::ext2::InodeHandler::grow().

◆ bytes_to_blocks()

uint32_t Ext2Volume::bytes_to_blocks ( size_t  bytes) const

How many blocks are needed to contain a set amount of bytes.

Parameters
bytesBytes needed
Returns
The blocks required

Definition at line 360 of file ext2.cpp.

360 {
361 return (bytes + block_size - 1) / block_size;
362}

References block_size.

Referenced by MaxOS::filesystem::format::ext2::InodeHandler::grow().

◆ create_inode()

uint32_t Ext2Volume::create_inode ( bool  is_directory)

Allocates a new inode and sets the base metadata. Also allocates block 0 of the inode.

Parameters
is_directoryis the inode to be used for a directory
Returns
The new inode

Definition at line 370 of file ext2.cpp.

370 {
371
372 ext2_lock.lock();
373
374 // Find the block group with enough free inodes
376 uint32_t bg_index = 0;
378 if(block_group->free_inodes >= 1)
379 break;
380
381 // Read bitmap
383 read_block(block_group->block_inode_bitmap, &bitmap);
384
385 // First group contains reserved inodes
387 if(bg_index == 0 && superblock.first_inode > 1)
388 inode_index = superblock.first_inode - 1;
389
390 // Find a free inode
391 for(; inode_index < superblock.inodes_per_group; ++inode_index) {
392
393 // Block is already used
394 if((bitmap.raw()[inode_index / 8] & (1u << (inode_index % 8))) != 0)
395 continue;
396
397 // Mark as used
398 block_group->free_inodes--;
399 superblock.unallocated_inodes--;
400 bitmap.raw()[inode_index / 8] |= (uint8_t) (1u << (inode_index % 8));
401
402 break;
403 }
404
405 // Convert into the 1-based inode index in the group
406 inode_index += bg_index * superblock.inodes_per_group + 1;
407
408 // Save the changed metadata
409 write_block(block_group->block_inode_bitmap, &bitmap);
410 write_back_block_groups();
411 write_back_superblock();
412
413 // Create the inode
414 inode_t inode { };
415 inode.creation_time = time_to_epoch(Clock::active_clock()->get_time());
416 inode.last_modification_time = time_to_epoch(Clock::active_clock()->get_time());
417 inode.block_pointers[0] = allocate_block();
418 inode.hard_links = is_directory ? 2 : 1;
419 inode.type = ((uint16_t) (is_directory ? InodeType::DIRECTORY : InodeType::FILE) >> 12) & 0xF;
420 inode.permissions =
421 (uint16_t) (is_directory ? InodePermissionsDefaults::DIRECTORY : InodePermissionsDefaults::FILE) & 0x0FFF;
422 write_inode(inode_index, &inode);
423
425 return inode_index;
426}
void lock()
Lock the spinlock once it is available.
Definition spinlock.cpp:24
void unlock()
Unlock the spinlock.
Definition spinlock.cpp:32
static Clock * active_clock()
Gets the currently active clock.
Definition clock.cpp:208
common::Spinlock ext2_lock
Lock for synchronised access to the volume (.
Definition ext2.h:350
void write_block(uint32_t block_num, common::buffer_t *buffer) const
write a single block from a buffer into onto the disk
Definition ext2.cpp:80
void write_inode(uint32_t inode_num, inode_t *inode) const
write an inode to the filesystem
Definition ext2.cpp:102
uint32_t allocate_block()
Allocates a single block to be used by an inode.
Definition ext2.cpp:177
void read_block(uint32_t block_num, common::buffer_t *buffer) const
Reads a single block from the disk into a buffer.
Definition ext2.cpp:129
InodeType
The type of an inode.
Definition ext2.h:206
InodePermissionsDefaults
The default permissions for files and directories.
Definition ext2.h:242
struct PACKED MaxOS::filesystem::format::ext2::Inode inode_t
Alias for Inode struct.

References MaxOS::drivers::clock::Clock::active_clock(), allocate_block(), block_groups, block_size, ext2_lock, MaxOS::common::Spinlock::lock(), read_block(), superblock, total_block_groups, MaxOS::common::Spinlock::unlock(), write_block(), and write_inode().

◆ free_blocks()

void Ext2Volume::free_blocks ( const common::Vector< uint32_t > &  blocks)

Frees a group of blocks. Preferably with adjacent blocks apearing next to each other but not enforced.

Parameters
blocksThe blocks to free

Definition at line 464 of file ext2.cpp.

464 {
465
466 // No blocks to free
467 if(blocks.empty())
468 return;
469
470 uint32_t start = blocks[0];
472 uint32_t amount = 1;
473
474 // Free each adjacent set of blocks
475 for(auto& block : blocks) {
476
477 // First is already accounted for
478 if(block == start)
479 continue;
480
481 // Is this block adjacent
482 if((previous + 1) == block) {
483 previous = block;
484 amount += 1;
485 continue;
486 }
487
488 // Adjacent set has ended
489 uint32_t group = (start - superblock.starting_block) / superblock.blocks_per_group;
490 free_group_blocks(group, amount, start);
491
492 // Reset
493 start = block;
494 previous = start;
495 amount = 1;
496 }
497
498 // Account for the last set of blocks in the loop
499 uint32_t group = (start - superblock.starting_block) / superblock.blocks_per_group;
500 free_group_blocks(group, amount, start);
501}

References superblock.

Referenced by allocate_blocks(), and MaxOS::filesystem::format::ext2::InodeHandler::free().

◆ free_inode()

void Ext2Volume::free_inode ( uint32_t  inode)

Mark an inode as free. Note: does NOT unallocated the inodes blocks, use free_group_blocks().

See also
free_group_blocks
Parameters
inodeThe inode number to mark as free

Definition at line 434 of file ext2.cpp.

434 {
435
436 // Find the block group containing the inode
437 uint32_t bg_index = (inode - 1) / superblock.inodes_per_group;
439
440 // Read bitmap
442 read_block(block_group->block_inode_bitmap, &bitmap);
443
444 // First group contains reserved inodes
445 uint32_t inode_index = (inode - 1) % superblock.inodes_per_group;
446 if(bg_index == 0 && (inode_index < (superblock.first_inode - 1)))
447 return;
448
449 // Mark as used
450 block_group->free_inodes++;
451 superblock.unallocated_inodes++;
452 bitmap.raw()[inode_index / 8] &= (uint8_t) ~(1u << (inode_index % 8));
453
454 // Save the changed metadata
455 write_block(block_group->block_inode_bitmap, &bitmap);
456 write_back_block_groups();
457 write_back_superblock();
458}

References block_groups, block_size, read_block(), superblock, and write_block().

Referenced by MaxOS::filesystem::format::ext2::InodeHandler::free().

◆ read_block()

void Ext2Volume::read_block ( uint32_t  block_num,
common::buffer_t buffer 
) const

Reads a single block from the disk into a buffer.

Parameters
block_numThe block to read
bufferThe buffer to read into

Definition at line 129 of file ext2.cpp.

129 {
130
131 // Ensure the buffer is in the right format
132 buffer->set_offset(0);
133
134 // Read each sector of the block
135 for(size_t i = 0; i < sectors_per_block; ++i)
137
138 // Reset buffer
139 buffer->set_offset(0);
140
141}

References disk, partition_offset, MaxOS::drivers::disk::Disk::read(), sectors_per_block, and MaxOS::common::Buffer::set_offset().

Referenced by create_inode(), free_inode(), MaxOS::filesystem::format::ext2::Ext2File::read(), MaxOS::filesystem::format::ext2::Ext2Directory::read_from_disk(), read_inode(), MaxOS::filesystem::format::ext2::Ext2File::write(), and write_inode().

◆ read_inode()

inode_t Ext2Volume::read_inode ( uint32_t  inode_num) const

read an inode from the filesystem

Parameters
inode_numThe inode index
Returns
The inode read

Definition at line 149 of file ext2.cpp.

149 {
150
151 inode_t inode;
152
153 // Locate the inode
154 uint32_t group = (inode_num - 1) / superblock.inodes_per_group;
155 uint32_t index = (inode_num - 1) % superblock.inodes_per_group;
156
157 // Locate the block
158 uint32_t inode_table = block_groups[group]->inode_table_address;
159 uint32_t offset = index * superblock.inode_size;
160 uint32_t block = offset / block_size;
162
163 // Read the block
164 buffer_t buffer(block_size);
165 read_block(inode_table + block, &buffer);
166
167 // Read the inode from the block
168 buffer.copy_to(&inode, sizeof(inode_t), in_block_offset);
169 return inode;
170}

References block_groups, block_size, MaxOS::common::Buffer::copy_to(), read_block(), and superblock.

◆ write_block()

void Ext2Volume::write_block ( uint32_t  block_num,
common::buffer_t buffer 
) const

write a single block from a buffer into onto the disk

Parameters
block_numThe block to update
bufferThe buffer to read from

Definition at line 80 of file ext2.cpp.

80 {
81
82 // Ensure the buffer is in the right format
83 buffer->set_offset(0);
84 bool old = buffer->update_offset;
85 buffer->update_offset = true;
86
87 // Read each sector of the block
88 for(size_t i = 0; i < sectors_per_block; ++i)
90
91 // Reset buffer
92 buffer->set_offset(0);
93 buffer->update_offset = old;
94}
void write(uint32_t sector, common::buffer_t *data)
write data to the disk from a buffer (max capacity 512 bytes)
Definition disk.cpp:50

References disk, partition_offset, sectors_per_block, MaxOS::common::Buffer::set_offset(), MaxOS::common::Buffer::update_offset, and MaxOS::drivers::disk::Disk::write().

Referenced by create_inode(), free_inode(), MaxOS::filesystem::format::ext2::Ext2File::write(), and write_inode().

◆ write_inode()

void Ext2Volume::write_inode ( uint32_t  inode_num,
inode_t inode 
) const

write an inode to the filesystem

Parameters
inode_numThe inode index
inodeThe inode to read from

Definition at line 102 of file ext2.cpp.

102 {
103
104 // Locate the inode
105 uint32_t group = (inode_num - 1) / superblock.inodes_per_group;
106 uint32_t index = (inode_num - 1) % superblock.inodes_per_group;
107
108 // Locate the block
109 uint32_t inode_table = block_groups[group]->inode_table_address;
110 uint32_t offset = index * superblock.inode_size;
111 uint32_t block = offset / block_size;
113
114 // Read the inode
115 buffer_t buffer(block_size);
116 read_block(inode_table + block, &buffer);
117 buffer.copy_from(inode, sizeof(inode_t), in_block_offset);
118
119 // Modify the block
120 write_block(inode_table + block, &buffer);
121}

References block_groups, block_size, MaxOS::common::Buffer::copy_from(), read_block(), superblock, and write_block().

Referenced by create_inode(), and MaxOS::filesystem::format::ext2::InodeHandler::save().

Member Data Documentation

◆ block_group_descriptor_table_block

uint32_t MaxOS::filesystem::format::ext2::Ext2Volume::block_group_descriptor_table_block

Where the block group descriptor table starts.

Definition at line 343 of file ext2.h.

◆ block_group_descriptor_table_size

uint32_t MaxOS::filesystem::format::ext2::Ext2Volume::block_group_descriptor_table_size

How many block groups are in the block group descriptor table.

Definition at line 344 of file ext2.h.

◆ block_groups

block_group_descriptor_t** MaxOS::filesystem::format::ext2::Ext2Volume::block_groups

The block group descriptors.

Definition at line 340 of file ext2.h.

Referenced by allocate_blocks(), create_inode(), free_inode(), read_inode(), and write_inode().

◆ block_size

◆ disk

drivers::disk::Disk* MaxOS::filesystem::format::ext2::Ext2Volume::disk

The disk that this volume is on.

Definition at line 336 of file ext2.h.

Referenced by read_block(), and write_block().

◆ ext2_lock

common::Spinlock MaxOS::filesystem::format::ext2::Ext2Volume::ext2_lock

◆ inodes_per_block

uint32_t MaxOS::filesystem::format::ext2::Ext2Volume::inodes_per_block

How many inodes fit in a block.

Definition at line 347 of file ext2.h.

◆ partition_offset

lba_t MaxOS::filesystem::format::ext2::Ext2Volume::partition_offset

How far into the disk this partition starts.

Definition at line 337 of file ext2.h.

Referenced by read_block(), and write_block().

◆ pointers_per_block

size_t MaxOS::filesystem::format::ext2::Ext2Volume::pointers_per_block

How many block pointers fit in a block.

Definition at line 346 of file ext2.h.

◆ sectors_per_block

uint32_t MaxOS::filesystem::format::ext2::Ext2Volume::sectors_per_block

How many sectors does a block take.

Definition at line 348 of file ext2.h.

Referenced by read_block(), and write_block().

◆ superblock

superblock_t MaxOS::filesystem::format::ext2::Ext2Volume::superblock

The superblock of the ext2 filesystem.

Definition at line 339 of file ext2.h.

Referenced by create_inode(), free_blocks(), free_inode(), read_inode(), and write_inode().

◆ total_block_groups

uint32_t MaxOS::filesystem::format::ext2::Ext2Volume::total_block_groups

How many block groups are in the filesystem.

Definition at line 345 of file ext2.h.

Referenced by allocate_blocks(), and create_inode().


The documentation for this class was generated from the following files: