mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Memory efficiently extract the initrd.
This commit is contained in:
parent
34c65265d0
commit
152d768112
4 changed files with 73 additions and 34 deletions
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013.
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <timespec.h>
|
#include <timespec.h>
|
||||||
|
|
||||||
|
#include <sortix/dirent.h>
|
||||||
#include <sortix/fcntl.h>
|
#include <sortix/fcntl.h>
|
||||||
#include <sortix/initrd.h>
|
#include <sortix/initrd.h>
|
||||||
#include <sortix/mman.h>
|
#include <sortix/mman.h>
|
||||||
|
@ -258,11 +259,11 @@ void Init(addr_t phys, size_t size)
|
||||||
CheckSum();
|
CheckSum();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ExtractDir(ioctx_t* ctx, uint32_t ino, Ref<Descriptor> node);
|
static bool ExtractDir(ioctx_t* ctx, uint32_t ino, Ref<Descriptor> node, Ref<Descriptor> links);
|
||||||
static bool ExtractFile(ioctx_t* ctx, uint32_t ino, Ref<Descriptor> file);
|
static bool ExtractFile(ioctx_t* ctx, uint32_t ino, Ref<Descriptor> file);
|
||||||
static bool ExtractNode(ioctx_t* ctx, uint32_t ino, Ref<Descriptor> node);
|
static bool ExtractNode(ioctx_t* ctx, uint32_t ino, Ref<Descriptor> node, Ref<Descriptor> links);
|
||||||
|
|
||||||
static bool ExtractDir(ioctx_t* ctx, uint32_t ino, Ref<Descriptor> dir)
|
static bool ExtractDir(ioctx_t* ctx, uint32_t ino, Ref<Descriptor> dir, Ref<Descriptor> links)
|
||||||
{
|
{
|
||||||
size_t numfiles = GetNumFiles(ino);
|
size_t numfiles = GetNumFiles(ino);
|
||||||
for ( size_t i = 0; i < numfiles; i++ )
|
for ( size_t i = 0; i < numfiles; i++ )
|
||||||
|
@ -275,7 +276,7 @@ static bool ExtractDir(ioctx_t* ctx, uint32_t ino, Ref<Descriptor> dir)
|
||||||
uint32_t childino = Traverse(ino, name);
|
uint32_t childino = Traverse(ino, name);
|
||||||
if ( !childino )
|
if ( !childino )
|
||||||
return false;
|
return false;
|
||||||
const initrd_inode_t* child = GetInode(childino);
|
initrd_inode_t* child = (initrd_inode_t*) GetInode(childino);
|
||||||
mode_t mode = InitRDModeToHost(child->mode);
|
mode_t mode = InitRDModeToHost(child->mode);
|
||||||
if ( INITRD_S_ISDIR(child->mode) )
|
if ( INITRD_S_ISDIR(child->mode) )
|
||||||
{
|
{
|
||||||
|
@ -284,16 +285,41 @@ static bool ExtractDir(ioctx_t* ctx, uint32_t ino, Ref<Descriptor> dir)
|
||||||
Ref<Descriptor> desc = dir->open(ctx, name, O_SEARCH | O_DIRECTORY, 0);
|
Ref<Descriptor> desc = dir->open(ctx, name, O_SEARCH | O_DIRECTORY, 0);
|
||||||
if ( !desc )
|
if ( !desc )
|
||||||
return false;
|
return false;
|
||||||
if ( !ExtractNode(ctx, childino, desc) )
|
if ( !ExtractNode(ctx, childino, desc, links) )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ( INITRD_S_ISREG(child->mode) )
|
if ( INITRD_S_ISREG(child->mode) )
|
||||||
{
|
{
|
||||||
Ref<Descriptor> desc = dir->open(ctx, name, O_WRITE | O_CREATE, mode);
|
assert(child->nlink != 0);
|
||||||
|
char link_path[sizeof(childino) * 3];
|
||||||
|
snprintf(link_path, sizeof(link_path), "%ju", (uintmax_t) childino);
|
||||||
|
Ref<Descriptor> existing(links->open(ctx, link_path, O_READ, 0));
|
||||||
|
if ( !existing || dir->link(ctx, name, existing) != 0 )
|
||||||
|
{
|
||||||
|
Ref<Descriptor> desc(dir->open(ctx, name, O_WRITE | O_CREATE, mode));
|
||||||
if ( !desc )
|
if ( !desc )
|
||||||
return false;
|
return false;
|
||||||
if ( !ExtractNode(ctx, childino, desc) )
|
if ( !ExtractNode(ctx, childino, desc, links) )
|
||||||
return false;
|
return false;
|
||||||
|
if ( 2 <= child->nlink )
|
||||||
|
links->link(ctx, link_path, desc);
|
||||||
|
}
|
||||||
|
if ( --child->nlink == 0 && INITRD_S_ISREG(child->mode) )
|
||||||
|
{
|
||||||
|
size_t filesize;
|
||||||
|
const uint8_t* data = Open(childino, &filesize);
|
||||||
|
uintptr_t from = (uintptr_t) data;
|
||||||
|
uintptr_t size = filesize;
|
||||||
|
uintptr_t from_aligned = Page::AlignUp(from);
|
||||||
|
uintptr_t from_distance = from_aligned - from;
|
||||||
|
if ( from_distance <= size )
|
||||||
|
{
|
||||||
|
uintptr_t size_aligned = Page::AlignDown(size - from_distance);
|
||||||
|
for ( size_t i = 0; i < size_aligned; i += Page::Size() )
|
||||||
|
Page::Put(Memory::Unmap(from_aligned + i));
|
||||||
|
Memory::Flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -318,7 +344,7 @@ static bool ExtractFile(ioctx_t* ctx, uint32_t ino, Ref<Descriptor> file)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ExtractNode(ioctx_t* ctx, uint32_t ino, Ref<Descriptor> node)
|
static bool ExtractNode(ioctx_t* ctx, uint32_t ino, Ref<Descriptor> node, Ref<Descriptor> links)
|
||||||
{
|
{
|
||||||
const initrd_inode_t* inode = GetInode(ino);
|
const initrd_inode_t* inode = GetInode(ino);
|
||||||
if ( !inode )
|
if ( !inode )
|
||||||
|
@ -328,7 +354,7 @@ static bool ExtractNode(ioctx_t* ctx, uint32_t ino, Ref<Descriptor> node)
|
||||||
if ( node->chown(ctx, inode->uid, inode->gid) < 0 )
|
if ( node->chown(ctx, inode->uid, inode->gid) < 0 )
|
||||||
return false;
|
return false;
|
||||||
if ( INITRD_S_ISDIR(inode->mode) )
|
if ( INITRD_S_ISDIR(inode->mode) )
|
||||||
if ( !ExtractDir(ctx, ino, node) )
|
if ( !ExtractDir(ctx, ino, node, links) )
|
||||||
return false;
|
return false;
|
||||||
if ( INITRD_S_ISREG(inode->mode) )
|
if ( INITRD_S_ISREG(inode->mode) )
|
||||||
if ( !ExtractFile(ctx, ino, node) )
|
if ( !ExtractFile(ctx, ino, node) )
|
||||||
|
@ -340,36 +366,55 @@ static bool ExtractNode(ioctx_t* ctx, uint32_t ino, Ref<Descriptor> node)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExtractInto(Ref<Descriptor> desc)
|
|
||||||
{
|
|
||||||
ioctx_t ctx; SetupKernelIOCtx(&ctx);
|
|
||||||
return ExtractNode(&ctx, sb->root, desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ExtractFromPhysicalInto(addr_t physaddr, size_t size, Ref<Descriptor> desc)
|
bool ExtractFromPhysicalInto(addr_t physaddr, size_t size, Ref<Descriptor> desc)
|
||||||
{
|
{
|
||||||
Init(physaddr, size);
|
Init(physaddr, size);
|
||||||
return ExtractInto(desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Delete()
|
ioctx_t ctx; SetupKernelIOCtx(&ctx);
|
||||||
{
|
if ( desc->mkdir(&ctx, ".initrd-links", 0777) != 0 )
|
||||||
size_t size = initrdsize;
|
return false;
|
||||||
|
|
||||||
initrd = NULL;
|
Ref<Descriptor> links(desc->open(&ctx, ".initrd-links", O_READ | O_DIRECTORY, 0));
|
||||||
initrdsize = 0;
|
if ( !links )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( !ExtractNode(&ctx, sb->root, desc, links) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct kernel_dirent dirent;
|
||||||
|
uint8_t dirent_data[sizeof(struct kernel_dirent) + sizeof(uintmax_t) * 3];
|
||||||
|
};
|
||||||
|
|
||||||
|
while ( 0 < links->readdirents(&ctx, &dirent, sizeof(dirent_data), 1) &&
|
||||||
|
((const char*) dirent.d_name)[0] )
|
||||||
|
{
|
||||||
|
if ( ((const char*) dirent.d_name)[0] == '.' )
|
||||||
|
continue;
|
||||||
|
links->unlink(&ctx, dirent.d_name);
|
||||||
|
links->lseek(&ctx, 0, SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
desc->rmdir(&ctx, ".initrd-links");
|
||||||
|
|
||||||
// Unmap the pages and return the physical frames for reallocation.
|
// Unmap the pages and return the physical frames for reallocation.
|
||||||
addr_t mapat = initrd_addr_alloc.from;
|
addr_t mapat = initrd_addr_alloc.from;
|
||||||
for ( size_t i = 0; i < size; i += Page::Size() )
|
for ( size_t i = 0; i < initrdsize; i += Page::Size() )
|
||||||
{
|
{
|
||||||
|
if ( !Memory::LookUp(mapat + i, NULL, NULL) )
|
||||||
|
continue;
|
||||||
addr_t addr = Memory::Unmap(mapat + i);
|
addr_t addr = Memory::Unmap(mapat + i);
|
||||||
Page::Put(addr);
|
Page::Put(addr);
|
||||||
}
|
}
|
||||||
Memory::Flush();
|
Memory::Flush();
|
||||||
|
|
||||||
|
initrdsize = 0;
|
||||||
|
|
||||||
// Free the used virtual address space.
|
// Free the used virtual address space.
|
||||||
FreeKernelAddress(&initrd_addr_alloc);
|
FreeKernelAddress(&initrd_addr_alloc);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace InitRD
|
} // namespace InitRD
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
|
||||||
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012.
|
Copyright(C) Jonas 'Sortie' Termansen 2011, 2012, 2013, 2014.
|
||||||
|
|
||||||
This file is part of Sortix.
|
This file is part of Sortix.
|
||||||
|
|
||||||
|
@ -33,9 +33,7 @@ class Descriptor;
|
||||||
|
|
||||||
namespace InitRD {
|
namespace InitRD {
|
||||||
|
|
||||||
bool ExtractInto(Ref<Descriptor> desc);
|
|
||||||
bool ExtractFromPhysicalInto(addr_t physaddr, size_t size, Ref<Descriptor> desc);
|
bool ExtractFromPhysicalInto(addr_t physaddr, size_t size, Ref<Descriptor> desc);
|
||||||
void Delete();
|
|
||||||
|
|
||||||
} // namespace InitRD
|
} // namespace InitRD
|
||||||
|
|
||||||
|
|
|
@ -547,9 +547,6 @@ static void BootThread(void* /*user*/)
|
||||||
"needs more memory to boot using this initrd, as a rule of thumb "
|
"needs more memory to boot using this initrd, as a rule of thumb "
|
||||||
"you need twice as much memory as the size of the initrd device.");
|
"you need twice as much memory as the size of the initrd device.");
|
||||||
|
|
||||||
// We no longer need the initrd, so free its resources.
|
|
||||||
InitRD::Delete();
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Stage 5. Loading and Initializing Core Drivers.
|
// Stage 5. Loading and Initializing Core Drivers.
|
||||||
//
|
//
|
||||||
|
|
|
@ -65,7 +65,6 @@
|
||||||
#include <sortix/kernel/worker.h>
|
#include <sortix/kernel/worker.h>
|
||||||
|
|
||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
#include "initrd.h"
|
|
||||||
|
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
#include "x86-family/float.h"
|
#include "x86-family/float.h"
|
||||||
|
|
Loading…
Add table
Reference in a new issue