From bf73b9a4a3ef0e5616be7b7ed51cd1fbae39038e Mon Sep 17 00:00:00 2001 From: Waldemar Kozaczuk Date: Thu, 23 Aug 2018 18:53:54 -0400 Subject: [PATCH] Optimize bootfs memory utilization 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 Message-Id: <20180823225354.7535-1-jwkozaczuk@gmail.com> --- fs/ramfs/ramfs.h | 1 + fs/ramfs/ramfs_vnops.cc | 38 ++++++++++++++++++++++++++++++++++---- fs/vfs/main.cc | 18 ++++++++++++++---- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/fs/ramfs/ramfs.h b/fs/ramfs/ramfs.h index f21ff4bdbc..88ccbe72f6 100644 --- a/fs/ramfs/ramfs.h +++ b/fs/ramfs/ramfs.h @@ -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); diff --git a/fs/ramfs/ramfs_vnops.cc b/fs/ramfs/ramfs_vnops.cc index cf1ae272e6..9291a4ece4 100644 --- a/fs/ramfs/ramfs_vnops.cc +++ b/fs/ramfs/ramfs_vnops.cc @@ -94,6 +94,7 @@ 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; } @@ -101,7 +102,7 @@ ramfs_allocate_node(const char *name, int type) 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); @@ -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; } @@ -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; @@ -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) { @@ -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)); diff --git a/fs/vfs/main.cc b/fs/vfs/main.cc index c41c694792..cd1411170a 100644 --- a/fs/vfs/main.cc +++ b/fs/vfs/main.cc @@ -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; @@ -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); } }