Skip to content

Commit

Permalink
Optimize bootfs memory utilization
Browse files Browse the repository at this point in the history
This patch optimizes RAM utilization of bootfs by
eliminating unnecessary copy of data. It does so by
pointing created file nodes to existing data offset in memory
which is part of area where kernel is copied after decompression.

In essence we add new flag rn_owns_buf to RAMFS ramfs_node to track
if we can actually free memory whenever it happens. By default
rn_owns_buf is set to true but new function ramfs_set_file_data called
from unpack_bootfs() sets it to false.

The savings of RAM are equal to the size of build/release/bootfs.bin
which means we save around 700K with ZFS images, 0 with ROSF and
as much as application code size with RAMFS where the improvement
is most significant especially with Java images.

Please note that file data referenced by nodes created during
unpack_bootfs() would point to wherever bootfs.bin data is in
the uncompressed kernel area which means it is most likely not aligned
which possibly means slower access. This could be improved by
making individual files aligned in bootfs.bin.

Fixes #977

Signed-off-by: Waldemar Kozaczuk <jwkozaczuk@gmail.com>
Message-Id: <20180823225354.7535-1-jwkozaczuk@gmail.com>
  • Loading branch information
wkozaczuk authored and nyh committed Aug 26, 2018
1 parent 9e3f243 commit bf73b9a
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 8 deletions.
1 change: 1 addition & 0 deletions fs/ramfs/ramfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ struct ramfs_node {
struct timespec rn_atime;
struct timespec rn_mtime;
int rn_mode;
bool rn_owns_buf;
};

struct ramfs_node *ramfs_allocate_node(const char *name, int type);
Expand Down
38 changes: 34 additions & 4 deletions fs/ramfs/ramfs_vnops.cc
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,15 @@ ramfs_allocate_node(const char *name, int type)
np->rn_mode = S_IFREG|0777;

set_times_to_now(&(np->rn_ctime), &(np->rn_atime), &(np->rn_mtime));
np->rn_owns_buf = true;

return np;
}

void
ramfs_free_node(struct ramfs_node *np)
{
if (np->rn_buf != NULL)
if (np->rn_buf != NULL && np->rn_owns_buf)
free(np->rn_buf);

free(np->rn_name);
Expand Down Expand Up @@ -336,7 +337,8 @@ ramfs_truncate(struct vnode *vp, off_t length)

if (length == 0) {
if (np->rn_buf != NULL) {
free(np->rn_buf);
if(np->rn_owns_buf)
free(np->rn_buf);
np->rn_buf = NULL;
np->rn_bufsize = 0;
}
Expand All @@ -348,10 +350,12 @@ ramfs_truncate(struct vnode *vp, off_t length)
return EIO;
if (np->rn_size != 0) {
memcpy(new_buf, np->rn_buf, vp->v_size);
free(np->rn_buf);
if(np->rn_owns_buf)
free(np->rn_buf);
}
np->rn_buf = (char *) new_buf;
np->rn_bufsize = new_size;
np->rn_owns_buf = true;
}
np->rn_size = length;
vp->v_size = length;
Expand Down Expand Up @@ -413,6 +417,30 @@ ramfs_read(struct vnode *vp, struct file *fp, struct uio *uio, int ioflag)
return uiomove(np->rn_buf + uio->uio_offset, len, uio);
}

int
ramfs_set_file_data(struct vnode *vp, const void *data, size_t size)
{
struct ramfs_node *np = (ramfs_node *) vp->v_data;

if (vp->v_type == VDIR) {
return EISDIR;
}
if (vp->v_type != VREG) {
return EINVAL;
}
if (np->rn_buf) {
return EINVAL;
}

np->rn_buf = (char *) data;
np->rn_bufsize = size;
np->rn_size = size;
vp->v_size = size;
np->rn_owns_buf = false;

return 0;
}

static int
ramfs_write(struct vnode *vp, struct uio *uio, int ioflag)
{
Expand Down Expand Up @@ -448,13 +476,15 @@ ramfs_write(struct vnode *vp, struct uio *uio, int ioflag)
return EIO;
if (np->rn_size != 0) {
memcpy(new_buf, np->rn_buf, vp->v_size);
free(np->rn_buf);
if(np->rn_owns_buf)
free(np->rn_buf);
}
np->rn_buf = (char *) new_buf;
np->rn_bufsize = new_size;
}
np->rn_size = end_pos;
vp->v_size = end_pos;
np->rn_owns_buf = true;
}

set_times_to_now(&(np->rn_mtime), &(np->rn_ctime));
Expand Down
18 changes: 14 additions & 4 deletions fs/vfs/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2132,6 +2132,7 @@ struct bootfs_metadata {

extern char bootfs_start;

int ramfs_set_file_data(struct vnode *vp, const void *data, size_t size);
void unpack_bootfs(void)
{
struct bootfs_metadata *md = (struct bootfs_metadata *)&bootfs_start;
Expand Down Expand Up @@ -2173,13 +2174,22 @@ void unpack_bootfs(void)
sys_panic("unpack_bootfs failed");
}

ret = write(fd, &bootfs_start + md[i].offset, md[i].size);
if (ret != md[i].size) {
kprintf("write failed, ret = %d, errno = %d\n",
ret, errno);
struct file *fp;
int error = fget(fd, &fp);
if (error) {
kprintf("couldn't fget %s: %d\n",
md[i].name, error);
sys_panic("unpack_bootfs failed");
}

struct vnode *vp = fp->f_dentry->d_vnode;
ret = ramfs_set_file_data(vp, &bootfs_start + md[i].offset, md[i].size);
if (ret) {
kprintf("ramfs_set_file_data failed, ret = %d\n", ret);
sys_panic("unpack_bootfs failed");
}

fdrop(fp);
close(fd);
}
}
Expand Down

0 comments on commit bf73b9a

Please sign in to comment.