Skip to content
This repository has been archived by the owner on Nov 4, 2020. It is now read-only.

Commit

Permalink
implemented EXT2 ata request stacking + bugfixing
Browse files Browse the repository at this point in the history
  • Loading branch information
vhaudiquet committed Apr 17, 2018
1 parent c6893c0 commit 543c496
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 35 deletions.
92 changes: 70 additions & 22 deletions filesystem/ext2.c
Expand Up @@ -25,6 +25,8 @@ static error_t ext2_std_inode_write(fsnode_t* node);
static error_t ext2_inode_read_content(fsnode_t* node, u32 offset, u32 size, void* buffer);
static error_t ext2_inode_write_content(fsnode_t* node, u32 offset, u32 size, void* buffer);

static void ext2_queue_read(ext2_read_request_t* requests, u32 sector, u32 count, u32 offset, void* buffer);

static error_t ext2_remove_dirent(char* name, fsnode_t* dir);
static error_t ext2_create_dirent(u32 inode, char* name, fsnode_t* dir);

Expand Down Expand Up @@ -514,6 +516,11 @@ static error_t ext2_inode_read_content(fsnode_t* node, u32 offset, u32 size, voi

u32 currentloc = 0;

//prepare request array
u32 request_size = (size + ((size % ext2->block_size) ? ext2->block_size : 0))/ext2->block_size;
ext2_read_request_t* requests = kmalloc(sizeof(ext2_read_request_t)*request_size);
memset(requests, 0, sizeof(ext2_read_request_t)*request_size);

//reading 12 direct pointers at first
u32 i;
for(i=first_block;i<12;i++)
Expand All @@ -522,21 +529,19 @@ static error_t ext2_inode_read_content(fsnode_t* node, u32 offset, u32 size, voi
if(!inode->direct_block_pointers[i])
{
kprintf("%v[WARNING] [SEVERE] EXT2 Filesystem might be corrupted (direct block pointer %u ->0)\n", 0b00000110, i);
kfree(requests);
return ERROR_FILE_CORRUPTED_FS;
}

error_t err = block_read_flexible(ext2->superblock_offset+BLOCK_OFFSET(inode->direct_block_pointers[i]), offset, buffer+currentloc, size >= ext2->block_size ? ext2->block_size : size, fs->drive);
if(err != ERROR_NONE) err = block_read_flexible(ext2->superblock_offset+BLOCK_OFFSET(inode->direct_block_pointers[i]), offset, buffer+currentloc, size >= ext2->block_size ? ext2->block_size : size, fs->drive);
if(err != ERROR_NONE) err = block_read_flexible(ext2->superblock_offset+BLOCK_OFFSET(inode->direct_block_pointers[i]), offset, buffer+currentloc, size >= ext2->block_size ? ext2->block_size : size, fs->drive);
if(err != ERROR_NONE) return err;
ext2_queue_read(requests, ext2->superblock_offset+BLOCK_OFFSET(inode->direct_block_pointers[i]), size >= ext2->block_size ? ext2->block_size : size, offset, buffer+currentloc);

currentloc+=ext2->block_size;
if(offset) offset = 0;

if(size >= ext2->block_size) size -= ext2->block_size;
else size = 0;

if(!size) return ERROR_NONE;
if(!size) goto send_requests;
}

//resetting block counter
Expand All @@ -546,11 +551,12 @@ static error_t ext2_inode_read_content(fsnode_t* node, u32 offset, u32 size, voi
if(!inode->singly_indirect_block_pointer)
{
kprintf("%v[WARNING] [SEVERE] EXT2 Filesystem might be corrupted (singly indirect pointer->0)\n", 0b00000110);
kfree(requests);
return ERROR_FILE_CORRUPTED_FS;
}
u32* singly_indirect_block = kmalloc(ext2->block_size);
error_t readerr0 = block_read_flexible(ext2->superblock_offset+BLOCK_OFFSET(inode->singly_indirect_block_pointer), 0, (u8*) singly_indirect_block, ext2->block_size, fs->drive);
if(readerr0 != ERROR_NONE) {kfree(singly_indirect_block); return readerr0;}
if(readerr0 != ERROR_NONE) {kfree(singly_indirect_block); kfree(requests); return readerr0;}

for(;i<(ext2->block_size/4);i++)
{
Expand All @@ -559,19 +565,19 @@ static error_t ext2_inode_read_content(fsnode_t* node, u32 offset, u32 size, voi
{
kprintf("%v[WARNING] [SEVERE] EXT2 Filesystem might be corrupted (singly indirect pointer->direct block pointer->0)\n", 0b00000110);
kfree(singly_indirect_block);
kfree(requests);
return ERROR_FILE_CORRUPTED_FS;
}

error_t err = block_read_flexible(ext2->superblock_offset+BLOCK_OFFSET(singly_indirect_block[i]), offset, buffer+currentloc, size >= ext2->block_size ? ext2->block_size : size, fs->drive);
if(err != ERROR_NONE) {kfree(singly_indirect_block); return err;}
ext2_queue_read(requests, ext2->superblock_offset+BLOCK_OFFSET(singly_indirect_block[i]), size >= ext2->block_size ? ext2->block_size : size, offset, buffer+currentloc);

currentloc+=ext2->block_size;
if(offset) offset = 0;

if(size >= ext2->block_size) size -= ext2->block_size;
else size = 0;

if(!size) {kfree(singly_indirect_block); return ERROR_NONE;}
if(!size) {kfree(singly_indirect_block); goto send_requests;}
}

kfree(singly_indirect_block);
Expand All @@ -583,11 +589,12 @@ static error_t ext2_inode_read_content(fsnode_t* node, u32 offset, u32 size, voi
if(!inode->doubly_indirect_block_pointer)
{
kprintf("%v[WARNING] [SEVERE] EXT2 Filesystem might be corrupted (doubly indirect pointer->0)\n", 0b00000110);
kfree(requests);
return ERROR_FILE_CORRUPTED_FS;
}
u32* doubly_indirect_block = kmalloc(ext2->block_size);
error_t readerr1 = block_read_flexible(ext2->superblock_offset+BLOCK_OFFSET(inode->doubly_indirect_block_pointer), 0, (u8*) doubly_indirect_block, ext2->block_size, fs->drive);
if(readerr1 != ERROR_NONE) {kfree(doubly_indirect_block); return readerr1;}
if(readerr1 != ERROR_NONE) {kfree(doubly_indirect_block); kfree(requests); return readerr1;}

u32 j;
for(j = 0;j<(ext2->block_size/4);j++)
Expand All @@ -597,11 +604,12 @@ static error_t ext2_inode_read_content(fsnode_t* node, u32 offset, u32 size, voi
{
kprintf("%v[WARNING] [SEVERE] EXT2 Filesystem might be corrupted (doubly indirect pointer->singly indirect pointer->0)\n", 0b00000110);
kfree(doubly_indirect_block);
kfree(requests);
return ERROR_FILE_CORRUPTED_FS;
}
u32* sib = kmalloc(ext2->block_size);
error_t readerr2 = block_read_flexible(ext2->superblock_offset+BLOCK_OFFSET(doubly_indirect_block[j]), 0, (u8*) sib, ext2->block_size, fs->drive);
if(readerr2 != ERROR_NONE) {kfree(sib); kfree(doubly_indirect_block); return readerr2;}
if(readerr2 != ERROR_NONE) {kfree(sib); kfree(doubly_indirect_block); kfree(requests); return readerr2;}

for(;i<(ext2->block_size/4);i++)
{
Expand All @@ -610,19 +618,19 @@ static error_t ext2_inode_read_content(fsnode_t* node, u32 offset, u32 size, voi
{
kprintf("%v[WARNING] [SEVERE] EXT2 Filesystem might be corrupted (doubly->singly->direct->0)\n", 0b00000110);
kfree(sib); kfree(doubly_indirect_block);
kfree(requests);
return ERROR_FILE_CORRUPTED_FS;
}

error_t err = block_read_flexible(ext2->superblock_offset+BLOCK_OFFSET(sib[i]), offset, buffer+currentloc, size >= ext2->block_size ? ext2->block_size : size, fs->drive);
ext2_queue_read(requests, ext2->superblock_offset+BLOCK_OFFSET(sib[i]), size >= ext2->block_size ? ext2->block_size : size, offset, buffer+currentloc);

currentloc+=ext2->block_size;
if(offset) offset = 0;

if(size >= ext2->block_size) size -= ext2->block_size;
else size = 0;

if(err != ERROR_NONE) {kfree(sib); kfree(doubly_indirect_block); return err;}
if(!size) {kfree(sib); kfree(doubly_indirect_block); return ERROR_NONE;}

if(!size) {kfree(sib); kfree(doubly_indirect_block); goto send_requests;}
}

kfree(sib);
Expand All @@ -636,11 +644,12 @@ static error_t ext2_inode_read_content(fsnode_t* node, u32 offset, u32 size, voi
if(!inode->triply_indirect_block_pointer)
{
kprintf("%v[WARNING] [SEVERE] EXT2 Filesystem might be corrupted (triply indirect pointer->0)\n", 0b00000110);
kfree(requests);
return ERROR_FILE_CORRUPTED_FS;
}
u32* triply_indirect_block = kmalloc(ext2->block_size);
error_t readerr3 = block_read_flexible(ext2->superblock_offset+BLOCK_OFFSET(inode->triply_indirect_block_pointer), 0, (u8*) triply_indirect_block, ext2->block_size, fs->drive);
if(readerr3 != ERROR_NONE) {kfree(triply_indirect_block); return readerr3;}
if(readerr3 != ERROR_NONE) {kfree(triply_indirect_block); kfree(requests); return readerr3;}

u32 k;
for(k=0;k<(ext2->block_size/4);k++)
Expand All @@ -649,11 +658,12 @@ static error_t ext2_inode_read_content(fsnode_t* node, u32 offset, u32 size, voi
{
kprintf("%v[WARNING] [SEVERE] EXT2 Filesystem might be corrupted (triply indirect pointer->doubly indirect pointer->0)\n", 0b00000110);
kfree(triply_indirect_block);
kfree(requests);
return ERROR_FILE_CORRUPTED_FS;
}
u32* dib = kmalloc(ext2->block_size);
error_t readerr4 = block_read_flexible(ext2->superblock_offset+BLOCK_OFFSET(triply_indirect_block[j]), 0, (u8*) dib, ext2->block_size, fs->drive);
if(readerr4 != ERROR_NONE){kfree(triply_indirect_block); kfree(dib); return readerr4;}
if(readerr4 != ERROR_NONE){kfree(triply_indirect_block); kfree(dib); kfree(requests); return readerr4;}

for(j=0;j<(ext2->block_size/4);j++)
{
Expand All @@ -662,11 +672,12 @@ static error_t ext2_inode_read_content(fsnode_t* node, u32 offset, u32 size, voi
{
kprintf("%v[WARNING] [SEVERE] EXT2 Filesystem might be corrupted (tip->dip->sip->0)\n", 0b00000110);
kfree(triply_indirect_block); kfree(dib);
kfree(requests);
return ERROR_FILE_CORRUPTED_FS;
}
u32* sib = kmalloc(ext2->block_size);
error_t readerr5 = block_read_flexible(ext2->superblock_offset+BLOCK_OFFSET(dib[j]), 0, (u8*) sib, ext2->block_size, fs->drive);
if(readerr5 != ERROR_NONE){kfree(triply_indirect_block); kfree(dib); kfree(sib); return readerr5;}
if(readerr5 != ERROR_NONE){kfree(triply_indirect_block); kfree(dib); kfree(sib); kfree(requests); return readerr5;}

for(;i<(ext2->block_size/4);i++)
{
Expand All @@ -675,19 +686,19 @@ static error_t ext2_inode_read_content(fsnode_t* node, u32 offset, u32 size, voi
{
kprintf("%v[WARNING] [SEVERE] EXT2 Filesystem might be corrupted (tip->dip->sip->direct->0)\n", 0b00000110);
kfree(sib); kfree(dib); kfree(triply_indirect_block);
kfree(requests);
return ERROR_FILE_CORRUPTED_FS;
}

error_t err = block_read_flexible(ext2->superblock_offset+BLOCK_OFFSET(sib[i]), offset, buffer+currentloc, size >= ext2->block_size ? ext2->block_size : size, fs->drive);
if(err != ERROR_NONE){kfree(triply_indirect_block); kfree(dib); kfree(sib); return err;}
ext2_queue_read(requests, ext2->superblock_offset+BLOCK_OFFSET(singly_indirect_block[i]), size >= ext2->block_size ? ext2->block_size : size, offset, buffer+currentloc);

currentloc+=ext2->block_size;
if(offset) offset = 0;

if(size >= ext2->block_size) size -= ext2->block_size;
else size = 0;

if(!size) {kfree(sib); kfree(dib); kfree(triply_indirect_block); return ERROR_NONE;}
if(!size) {kfree(sib); kfree(dib); kfree(triply_indirect_block); goto send_requests;}
}

kfree(sib);
Expand All @@ -700,9 +711,46 @@ static error_t ext2_inode_read_content(fsnode_t* node, u32 offset, u32 size, voi

kfree(triply_indirect_block);

/* sending all queued requests */
send_requests:
{
u32 ri = 0;
while(requests[ri].sector && (ri < request_size))
{
error_t err = block_read_flexible(requests[ri].sector, requests[ri].offset, (u8*) requests[ri].buffer, requests[ri].count, fs->drive);
if(err != ERROR_NONE) err = block_read_flexible(requests[ri].sector, requests[ri].offset, (u8*) requests[ri].buffer, requests[ri].count, fs->drive);
if(err != ERROR_NONE) {kfree(requests); return err;}
ri++;
}
}

kfree(requests);

return ERROR_NONE;
}

/*
* This function add a block_read request to the request array, merging it with another if sectors are contiguous
*/
static void ext2_queue_read(ext2_read_request_t* requests, u32 sector, u32 count, u32 offset, void* buffer)
{
u32 i = 0;
while(requests[i].sector)
{
if((requests[i].sector == (sector - (requests[i].count/BYTES_PER_SECTOR))) && (((u32) requests[i].buffer) == (((u32)buffer) - requests[i].count)))
{
requests[i].count += count;
return;
}
i++;
}

requests[i].sector = sector;
requests[i].count = count;
requests[i].offset = offset;
requests[i].buffer = buffer;
}

/*
* This function writes the content of 'buffer' to an ext2 file/inode (fsnode_t)
*/
Expand Down
8 changes: 8 additions & 0 deletions filesystem/ext2.h
Expand Up @@ -133,6 +133,14 @@ typedef struct ext2fs_specific
u32 blockgroup_count;
} ext2fs_specific_t;

typedef struct ext2_read_request
{
u32 sector;
u32 count;
u32 offset;
void* buffer;
} ext2_read_request_t;

file_system_t* ext2_init(block_device_t* drive, u8 partition);
fsnode_t* ext2_open(fsnode_t* dir, char* name);
error_t ext2_write_file(fd_t* fd, void* buffer, u64 count);
Expand Down
4 changes: 3 additions & 1 deletion tasking/processes/elf.c
Expand Up @@ -144,10 +144,12 @@ void* elf_load(fd_t* file, u32* page_directory, list_entry_t* data_loc, u32* dat
data_loc = data_loc->next;
(*data_size)++;

asm("cli"); //critical, we dont want process to be scheduled
pd_switch(page_directory);
memcpy((void*)prg_h[i].p_vaddr, buffer + prg_h[i].p_offset, prg_h[i].p_filesz);
memset((void*)prg_h[i].p_vaddr + prg_h[i].p_filesz, 0, prg_h[i].p_memsz - prg_h[i].p_filesz);
pd_switch(kernel_page_directory);
pd_switch(current_process->page_directory);
asm("sti"); //end of critical, we restored page dir
}
//freeing last list entry, unused
kfree(data_loc);
Expand Down
9 changes: 8 additions & 1 deletion tasking/processes/process.c
Expand Up @@ -67,6 +67,9 @@ error_t load_executable(process_t* process, fd_t* executable, int argc, char** a
if((!code_offset) | (((u32)code_offset) > 0xC0000000))
{kfree(data_loc); return UNKNOWN_ERROR;}

//that part is critical, we dont want the process to be scheduled from here
asm("cli");

//TODO: check if this area isnt already mapped by elf code/data
void* stack_offset = (void*) 0xC0000000;

Expand Down Expand Up @@ -135,6 +138,9 @@ error_t load_executable(process_t* process, fd_t* executable, int argc, char** a
process->active_thread->esp = (u32) stack_offset;
process->active_thread->eip = (u32) code_offset;

//re-enabling interrupts at end of critical part
asm("sti");

return ERROR_NONE;
}

Expand Down Expand Up @@ -331,6 +337,7 @@ process_t* fork(process_t* old_process, u32 old_esp)
tr->files_size = old_process->files_size;
tr->files_count = old_process->files_count;
tr->files = kmalloc(old_process->files_size*sizeof(fd_t));
memset(tr->files, 0, old_process->files_size*sizeof(fd_t));
u32 i = 0;
for(;i<old_process->files_size;i++)
{
Expand All @@ -341,7 +348,7 @@ process_t* fork(process_t* old_process, u32 old_esp)
memcpy(toadd, tocopy, sizeof(fd_t));
tr->files[i] = toadd;
}

scheduler_add_process(tr);

return tr;
Expand Down
7 changes: 4 additions & 3 deletions tasking/processes/syscalls.c
Expand Up @@ -57,7 +57,7 @@ void syscall_open(u32 ebx, u32 ecx, u32 edx)
{
current_process->files_size*=2;
current_process->files = krealloc(current_process->files, current_process->files_size*sizeof(fd_t));
memset(current_process->files+current_process->files_size/2, 0, current_process->files_size/2);
memset((void*)(((u32)current_process->files)+(current_process->files_size/2)*sizeof(fd_t)), 0, (current_process->files_size/2)*sizeof(fd_t));
}

u32 i = 0;
Expand All @@ -77,9 +77,10 @@ void syscall_close(u32 ebx, u32 ecx, u32 edx)
{
if((ebx >= 3) && (current_process->files_size >= ebx) && (current_process->files[ebx]))
{
close_file(current_process->files[ebx]);
fd_t* file = current_process->files[ebx];
current_process->files[ebx] = 0;
current_process->files_count--;
close_file(file);
}
}

Expand Down Expand Up @@ -335,7 +336,7 @@ void syscall_exec(u32 ebx, u32 ecx, u32 edx)
if((current_process->files_size < ebx) | (!current_process->files[ebx])) {asm("mov %0, %%eax ; mov %0, %%ecx"::"N"(ERROR_FILE_NOT_FOUND)); return;}

error_t is_elf = elf_check(current_process->files[ebx]);
if(is_elf != ERROR_NONE) {asm("mov %0, %%eax ; mov %0, %%ecx"::"g"(is_elf)); return;}
if(is_elf != ERROR_NONE) {asm("mov %0, %%eax ; mov %0, %%ecx"::"g"(is_elf):"%eax", "%ecx"); return;}

free_process_memory(current_process);

Expand Down
8 changes: 4 additions & 4 deletions tasking/processes/threads.c
Expand Up @@ -70,10 +70,10 @@ void scheduler_remove_thread(process_t* process, thread_t* thread)
asm("cli"); //critical section, we don't want the process to be scheduled from here
thread_t* next = queue_take(process->running_threads);

__asm__ __volatile__("mov %%ebx, %0":"=m"(current_process->active_thread->gregs.ebx));
__asm__ __volatile__("mov %%edi, %0":"=m"(current_process->active_thread->gregs.edi));
__asm__ __volatile__("mov %%esi, %0":"=m"(current_process->active_thread->gregs.esi));
__asm__ __volatile__("mov %%ebp, %0":"=m"(current_process->active_thread->ebp));
__asm__ __volatile__("mov %%ebx, %0":"=m"(current_process->active_thread->gregs.ebx)::"%ebx");
__asm__ __volatile__("mov %%edi, %0":"=m"(current_process->active_thread->gregs.edi)::"%edi");
__asm__ __volatile__("mov %%esi, %0":"=m"(current_process->active_thread->gregs.esi)::"%esi");
__asm__ __volatile__("mov %%ebp, %0":"=m"(current_process->active_thread->ebp)::"%ebp");
//save segment registers
__asm__ __volatile__ ("mov %%ds, %0 ; mov %%es, %1 ; mov %%fs, %2 ; mov %%gs, %3":"=m"(current_process->active_thread->sregs.ds), "=m"(current_process->active_thread->sregs.es), "=m"(current_process->active_thread->sregs.fs), "=m"(current_process->active_thread->sregs.gs));

Expand Down
8 changes: 4 additions & 4 deletions tasking/scheduler/scheduler.c
Expand Up @@ -80,10 +80,10 @@ void scheduler_remove_process(process_t* process)

//following convention, functions can trash eax/ecx/edx, so we dont care about theses
//we need to save ebx/esi/edi, and to keep something (stack frame) on ebp (but we dont really care)
__asm__ __volatile__("mov %%ebx, %0":"=m"(current_process->active_thread->gregs.ebx));
__asm__ __volatile__("mov %%edi, %0":"=m"(current_process->active_thread->gregs.edi));
__asm__ __volatile__("mov %%esi, %0":"=m"(current_process->active_thread->gregs.esi));
__asm__ __volatile__("mov %%ebp, %0":"=m"(current_process->active_thread->ebp));
__asm__ __volatile__("mov %%ebx, %0":"=m"(current_process->active_thread->gregs.ebx)::"%ebx");
__asm__ __volatile__("mov %%edi, %0":"=m"(current_process->active_thread->gregs.edi)::"%edi");
__asm__ __volatile__("mov %%esi, %0":"=m"(current_process->active_thread->gregs.esi)::"%esi");
__asm__ __volatile__("mov %%ebp, %0":"=m"(current_process->active_thread->ebp)::"%ebp");
//save segment registers
__asm__ __volatile__ ("mov %%ds, %0 ; mov %%es, %1 ; mov %%fs, %2 ; mov %%gs, %3":"=m"(current_process->active_thread->sregs.ds), "=m"(current_process->active_thread->sregs.es), "=m"(current_process->active_thread->sregs.fs), "=m"(current_process->active_thread->sregs.gs));

Expand Down

0 comments on commit 543c496

Please sign in to comment.