From c02a9aa3bcc1bf77c6c03fe3d28b82556def4077 Mon Sep 17 00:00:00 2001 From: "A.I" Date: Mon, 13 Jun 2016 19:02:39 -0700 Subject: [PATCH] Patch to make vboxsf faster with cache from https://github.com/kokukuma/vboxguest http://dsas.blog.klab.org/archives/52231356.html --- .../0001-Add-a-patch-for-regops.c.patch | 41 -- .../0001-Patch-to-make-vboxsf-faster.patch | 458 ++++++++++++++++++ ...002-More-buffer-to-read-write-faster.patch | 28 -- .../patches/0002-Remove-sf_file_write.patch | 89 ++++ 4 files changed, 547 insertions(+), 69 deletions(-) delete mode 100644 virtualbox/iso/patches/0001-Add-a-patch-for-regops.c.patch create mode 100644 virtualbox/iso/patches/0001-Patch-to-make-vboxsf-faster.patch delete mode 100644 virtualbox/iso/patches/0002-More-buffer-to-read-write-faster.patch create mode 100644 virtualbox/iso/patches/0002-Remove-sf_file_write.patch diff --git a/virtualbox/iso/patches/0001-Add-a-patch-for-regops.c.patch b/virtualbox/iso/patches/0001-Add-a-patch-for-regops.c.patch deleted file mode 100644 index 8bf76f8..0000000 --- a/virtualbox/iso/patches/0001-Add-a-patch-for-regops.c.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 9545ae0be6abe57df6452b41a3b10caeca2a2c72 Mon Sep 17 00:00:00 2001 -From: "A.I" -Date: Mon, 20 Jun 2016 18:59:52 -0700 -Subject: [PATCH 1/2] Add a patch for regops.c - -- based on http://d.hatena.ne.jp/hiboma/20140320/1395312958 ---- - regops.c | 10 +++++++++- - 1 file changed, 9 insertions(+), 1 deletion(-) - -diff --git a/regops.c b/regops.c -index 1d2b921..036484f 100644 ---- a/regops.c -+++ b/regops.c -@@ -561,6 +561,14 @@ static int sf_reg_mmap(struct file *file, struct vm_area_struct *vma) - return 0; - } - -+ssize_t sf_reg_splice_read(struct file *in, loff_t *ppos, -+ struct pipe_inode_info *pipe, size_t len, -+ unsigned int flags) -+{ -+ invalidate_mapping_pages(in->f_mapping, 0, -1); -+ return generic_file_splice_read(in, ppos, pipe, len, flags); -+} -+ - struct file_operations sf_reg_fops = - { - .read = sf_reg_read, -@@ -570,7 +578,7 @@ struct file_operations sf_reg_fops = - .mmap = sf_reg_mmap, - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) - # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) -- .splice_read = generic_file_splice_read, -+ .splice_read = sf_reg_splice_read, - # else - .sendfile = generic_file_sendfile, - # endif --- -2.5.4 (Apple Git-61) - diff --git a/virtualbox/iso/patches/0001-Patch-to-make-vboxsf-faster.patch b/virtualbox/iso/patches/0001-Patch-to-make-vboxsf-faster.patch new file mode 100644 index 0000000..b204915 --- /dev/null +++ b/virtualbox/iso/patches/0001-Patch-to-make-vboxsf-faster.patch @@ -0,0 +1,458 @@ +From cfc53dfea674f0b24f706a9f8cce271229ab9394 Mon Sep 17 00:00:00 2001 +From: "A.I" +Date: Mon, 13 Jun 2016 19:26:08 -0700 +Subject: [PATCH 1/2] Patch to make vboxsf faster + +from https://github.com/kokukuma/vboxguest +http://dsas.blog.klab.org/archives/52231356.html +--- + regops.c | 285 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- + utils.c | 18 +++- + 2 files changed, 282 insertions(+), 21 deletions(-) + +diff --git a/regops.c b/regops.c +index 1d2b921..09cc13c 100644 +--- a/regops.c ++++ b/regops.c +@@ -29,8 +29,8 @@ static void *alloc_bounce_buffer(size_t *tmp_sizep, PRTCCPHYS physp, size_t + + /* try for big first. */ + tmp_size = RT_ALIGN_Z(xfer_size, PAGE_SIZE); +- if (tmp_size > 16U*_1K) +- tmp_size = 16U*_1K; ++ if (tmp_size > 128U*_1K) ++ tmp_size = 128U*_1K; + tmp = kmalloc(tmp_size, GFP_KERNEL); + if (!tmp) + { +@@ -91,6 +91,60 @@ static int sf_reg_write_aux(const char *caller, struct sf_glob_info *sf_g, + return 0; + } + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++ ++#include ++static ssize_t ++sf_file_read(struct kiocb *iocb, struct iov_iter *iov) ++{ ++ int err; ++ struct dentry *dentry; ++ ++ dentry = iocb->ki_filp->f_path.dentry; ++ err = sf_inode_revalidate(dentry); ++ if (err) ++ return err; ++ return generic_file_read_iter(iocb, iov); ++} ++ ++static int sf_need_sync_write(struct file *file, struct inode *inode) ++{ ++ // >= kernel version 2.6.33 ++ if (IS_SYNC(inode) || file->f_flags & O_DSYNC) ++ { ++ return 1; ++ } ++ return 0; ++} ++ ++static ssize_t ++sf_file_write(struct kiocb *iocb, struct iov_iter *iov) ++{ ++ int err; ++ ssize_t result; ++ struct file *file = iocb->ki_filp; ++ struct dentry *dentry = file->f_path.dentry; ++ struct inode *inode = dentry->d_inode; ++ ++ err = sf_inode_revalidate(dentry); ++ if (err) ++ return err; ++ ++ result = generic_file_write_iter(iocb, iov); ++ ++ if (result >= 0 && sf_need_sync_write(file, inode)) ++ { ++ err = vfs_fsync(file, 0); ++ if (err < 0) ++ { ++ result = err; ++ } ++ } ++ return result; ++} ++ ++#else /* KERNEL_VERSION >= 3.16.0 */ ++ + /** + * Read from a regular file. + * +@@ -266,6 +320,37 @@ fail: + return err; + } + ++#endif /* KERNEL_VERSION >= 3.16.0 */ ++ ++static loff_t ++sf_file_llseek(struct file *file, loff_t offset, int origin) ++{ ++ int err; ++ struct dentry *dentry; ++ ++ dentry = file->f_path.dentry; ++ err = sf_inode_revalidate(dentry); ++ if (err) ++ return err; ++ return generic_file_llseek(file, offset, origin); ++} ++ ++# if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) ++static ssize_t ++sf_file_splice_read(struct file *file, loff_t *offset, struct pipe_inode_info *pipe, size_t len, unsigned int flags) ++{ ++ int err; ++ struct dentry *dentry; ++ ++ dentry = file->f_path.dentry; ++ err = sf_inode_revalidate(dentry); ++ if (err) ++ return err; ++ return generic_file_splice_read(file, offset, pipe, len, flags); ++} ++ ++# endif /* KERNEL_VERSION >= 2.6.23 */ ++ + /** + * Open a regular file. + * +@@ -485,7 +570,8 @@ static struct page *sf_reg_nopage(struct vm_area_struct *vma, unsigned long vadd + * which works on virtual addresses. On Linux cannot reliably determine the + * physical address for high memory, see rtR0MemObjNativeLockKernel(). */ + page = alloc_page(GFP_USER); +- if (!page) { ++ if (!page) ++ { + LogRelFunc(("failed to allocate page\n")); + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25) + return VM_FAULT_OOM; +@@ -544,7 +630,7 @@ static struct vm_operations_struct sf_vma_ops = + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25) + .fault = sf_reg_fault + #else +- .nopage = sf_reg_nopage ++ .nopage = sf_reg_nopage + #endif + }; + +@@ -563,30 +649,34 @@ static int sf_reg_mmap(struct file *file, struct vm_area_struct *vma) + + struct file_operations sf_reg_fops = + { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) ++#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) ++ .read = new_sync_read, ++ .write = new_sync_write, ++#endif // LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) ++ .read_iter = sf_file_read, ++ .write_iter = sf_file_write, ++#else + .read = sf_reg_read, +- .open = sf_reg_open, + .write = sf_reg_write, ++ .aio_read = generic_file_aio_read, ++ .aio_write = generic_file_aio_write, ++#endif ++ .open = sf_reg_open, + .release = sf_reg_release, + .mmap = sf_reg_mmap, + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) + # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) +- .splice_read = generic_file_splice_read, ++ .splice_read = sf_file_splice_read, + # else + .sendfile = generic_file_sendfile, + # endif +-# if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) +- .read_iter = generic_file_read_iter, +- .write_iter = generic_file_write_iter, +-# else +- .aio_read = generic_file_aio_read, +- .aio_write = generic_file_aio_write, +-# endif + # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) + .fsync = noop_fsync, + # else + .fsync = simple_sync_file, + # endif +- .llseek = generic_file_llseek, ++ .llseek = sf_file_llseek, + #endif + }; + +@@ -633,6 +723,85 @@ static int sf_readpage(struct file *file, struct page *page) + return 0; + } + ++static int sf_readpages(struct file *file, struct address_space *mapping, ++ struct list_head *pages, unsigned nr_pages) ++{ ++ RTCCPHYS tmp_phys; ++ struct dentry *dentry = file->f_path.dentry; ++ struct inode *inode = dentry->d_inode; ++ struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb); ++ struct sf_reg_info *sf_r = file->private_data; ++ void *physbuf; ++ int bufsize; ++ int bufsize2; ++ size_t tmp_size; ++ pgoff_t buf_startindex = 0; ++ pgoff_t pages_in_buf = 0; ++ int err = 0; ++ ++ ++ /* first try to get everything in one read */ ++ bufsize2 = PAGE_SIZE * (list_entry(pages->next, struct page, lru)->index ++ - list_entry(pages->prev, struct page, lru)->index); ++ bufsize = PAGE_SIZE * nr_pages; ++ if (bufsize > 32 * PAGE_SIZE) ++ bufsize = 32 * PAGE_SIZE; ++ ++ if (!bufsize) ++ return 0; ++ ++ physbuf = alloc_bounce_buffer(&tmp_size, &tmp_phys, bufsize, __PRETTY_FUNCTION__); ++ if (!physbuf) ++ return -ENOMEM; ++ ++ ++ while (!list_empty(pages)) ++ { ++ struct page *page = list_entry((pages)->prev, struct page, lru); ++ loff_t off = (loff_t) page->index << PAGE_SHIFT; ++ list_del(&page->lru); ++ if (add_to_page_cache_lru(page, mapping, page->index, GFP_KERNEL)) ++ { ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) ++ put_page(page); ++#else ++ page_cache_release(page); ++#endif ++ continue; ++ } ++ ++ /* read the next chunk if needed */ ++ if (page->index >= buf_startindex + pages_in_buf) ++ { ++ uint32_t nread = tmp_size; ++ err = sf_reg_read_aux(__func__, sf_g, sf_r, physbuf, &nread, off); ++ if (err || nread == 0) ++ break; ++ ++ buf_startindex = page->index; ++ pages_in_buf = nread >> PAGE_SHIFT; ++ if (nread != PAGE_ALIGN(nread)) ++ { ++ pages_in_buf++; ++ memset(physbuf + nread, 0, (pages_in_buf << PAGE_SHIFT) - nread); ++ } ++ } ++ copy_page(page_address(page), ++ physbuf + ((page->index - buf_startindex) << PAGE_SHIFT)); ++ ++ flush_dcache_page(page); ++ SetPageUptodate(page); ++ unlock_page(page); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) ++ put_page(page); ++#else ++ page_cache_release(page); ++#endif ++ } ++ free_bounce_buffer(physbuf); ++ return err; ++} ++ + static int + sf_writepage(struct page *page, struct writeback_control *wbc) + { +@@ -677,12 +846,71 @@ out: + } + + # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) ++ ++/* ++ * Determine the number of bytes of data the page contains ++ */ ++static inline ++unsigned int sf_page_length(struct page *page) ++{ ++ //loff_t i_size = i_size_read(page_file_mapping(page)->host); ++ loff_t i_size = page->mapping->host->i_size; ++ ++ if (i_size > 0) ++ { ++ pgoff_t page_index = page_file_index(page); ++ pgoff_t end_index = (i_size - 1) >> PAGE_CACHE_SHIFT; ++ if (page_index < end_index) ++ return PAGE_CACHE_SIZE; ++ if (page_index == end_index) ++ return ((i_size - 1) & ~PAGE_CACHE_MASK) + 1; ++ } ++ return 0; ++} ++ ++static int sf_want_read_modify_write(struct file *file, struct page *page, ++ loff_t pos, unsigned len) ++{ ++ unsigned int pglen = sf_page_length(page); ++ unsigned int offset = pos & (PAGE_CACHE_SIZE - 1); ++ unsigned int end = offset + len; ++ ++ if ((file->f_mode & FMODE_READ) && /* open for read? */ ++ !PageUptodate(page) && /* Uptodate? */ ++ !PagePrivate(page) && /* i/o request already? */ ++ pglen && /* valid bytes of file? */ ++ (end < pglen || offset)) /* replace all valid bytes? */ ++ return 1; ++ return 0; ++} ++ + int sf_write_begin(struct file *file, struct address_space *mapping, loff_t pos, + unsigned len, unsigned flags, struct page **pagep, void **fsdata) + { +- TRACE(); ++ int ret; ++ pgoff_t index = pos >> PAGE_CACHE_SHIFT; ++ struct page *page; ++ int once_thru = 0; + +- return simple_write_begin(file, mapping, pos, len, flags, pagep, fsdata); ++start: ++ page = grab_cache_page_write_begin(mapping, index, flags); ++ if (!page) ++ return -ENOMEM; ++ *pagep = page; ++ ++ if (!once_thru && sf_want_read_modify_write(file, page, pos, len)) ++ { ++ once_thru = 1; ++ ret = sf_readpage(file, page); ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) ++ put_page(page); ++#else ++ page_cache_release(page); ++#endif ++ if (!ret) ++ goto start; ++ } ++ return ret; + } + + int sf_write_end(struct file *file, struct address_space *mapping, loff_t pos, +@@ -693,6 +921,7 @@ int sf_write_end(struct file *file, struct address_space *mapping, loff_t pos, + struct sf_reg_info *sf_r = file->private_data; + void *buf; + unsigned from = pos & (PAGE_SIZE - 1); ++ unsigned to = from + len; + uint32_t nwritten = len; + int err; + +@@ -702,10 +931,27 @@ int sf_write_end(struct file *file, struct address_space *mapping, loff_t pos, + err = sf_reg_write_aux(__func__, sf_g, sf_r, buf+from, &nwritten, pos); + kunmap(page); + +- if (!PageUptodate(page) && err == PAGE_SIZE) +- SetPageUptodate(page); ++ if (!PageUptodate(page)) ++ { ++ unsigned pglen = sf_page_length(page); + +- if (err >= 0) { ++ if (pglen == 0) ++ { ++ zero_user_segments(page, 0, from, to, PAGE_CACHE_SIZE); ++ SetPageUptodate(page); ++ } ++ else if (to >= pglen) ++ { ++ zero_user_segment(page, to, PAGE_CACHE_SIZE); ++ if (from == 0) ++ SetPageUptodate(page); ++ } ++ else ++ zero_user_segment(page, pglen, PAGE_CACHE_SIZE); ++ } ++ ++ if (err >= 0) ++ { + pos += nwritten; + if (pos > inode->i_size) + inode->i_size = pos; +@@ -726,6 +972,7 @@ int sf_write_end(struct file *file, struct address_space *mapping, loff_t pos, + struct address_space_operations sf_reg_aops = + { + .readpage = sf_readpage, ++ .readpages = sf_readpages, + .writepage = sf_writepage, + # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) + .write_begin = sf_write_begin, +diff --git a/utils.c b/utils.c +index e50af9a..64043f5 100644 +--- a/utils.c ++++ b/utils.c +@@ -220,6 +220,7 @@ int sf_inode_revalidate(struct dentry *dentry) + struct sf_glob_info *sf_g; + struct sf_inode_info *sf_i; + SHFLFSOBJINFO info; ++ time_t old_time; + + TRACE(); + if (!dentry || !dentry->d_inode) +@@ -243,7 +244,7 @@ int sf_inode_revalidate(struct dentry *dentry) + + if (!sf_i->force_restat) + { +- if (jiffies - dentry->d_time < sf_g->ttl) ++ if (jiffies - dentry->d_time <= sf_g->ttl) + return 0; + } + +@@ -252,7 +253,18 @@ int sf_inode_revalidate(struct dentry *dentry) + return err; + + dentry->d_time = jiffies; ++ ++ old_time = dentry->d_inode->i_mtime.tv_sec; ++ sf_ftime_from_timespec(&dentry->d_inode->i_mtime, &info.ModificationTime); ++ ++ if (info.cbObject != dentry->d_inode->i_size || ++ old_time != dentry->d_inode->i_mtime.tv_sec) ++ { ++ invalidate_inode_pages2(dentry->d_inode->i_mapping); ++ } ++ + sf_init_inode(sf_g, dentry->d_inode, &info); ++ sf_i->force_restat = 0; + return 0; + } + +@@ -411,6 +423,8 @@ int sf_setattr(struct dentry *dentry, struct iattr *iattr) + if (RT_FAILURE(rc)) + LogFunc(("VbglR0SfClose(%s) failed rc=%Rrc\n", sf_i->path->String.utf8, rc)); + ++ // To get the host dentry forcibly. ++ dentry->d_time = 0; + return sf_inode_revalidate(dentry); + + fail1: +@@ -872,7 +886,7 @@ int sf_init_backing_dev(struct sf_glob_info *sf_g) + static uint64_t s_u64Sequence = 0; + uint64_t u64CurrentSequence = ASMAtomicIncU64(&s_u64Sequence); + +- sf_g->bdi.ra_pages = 0; /* No readahead */ ++ sf_g->bdi.ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_CACHE_SIZE; /* 32 */ + # if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 12) + sf_g->bdi.capabilities = BDI_CAP_MAP_DIRECT /* MAP_SHARED */ + | BDI_CAP_MAP_COPY /* MAP_PRIVATE */ +-- +2.5.4 (Apple Git-61) + diff --git a/virtualbox/iso/patches/0002-More-buffer-to-read-write-faster.patch b/virtualbox/iso/patches/0002-More-buffer-to-read-write-faster.patch deleted file mode 100644 index a1f95ce..0000000 --- a/virtualbox/iso/patches/0002-More-buffer-to-read-write-faster.patch +++ /dev/null @@ -1,28 +0,0 @@ -From b7108fc13b1081ae03cd9eb081407e373925e32f Mon Sep 17 00:00:00 2001 -From: "A.I" -Date: Mon, 20 Jun 2016 19:04:01 -0700 -Subject: [PATCH 2/2] More buffer to read/write faster - -128K = VM_MAX_READAHEAD * 1024 ---- - regops.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/regops.c b/regops.c -index 036484f..ee6741b 100644 ---- a/regops.c -+++ b/regops.c -@@ -29,8 +29,8 @@ static void *alloc_bounce_buffer(size_t *tmp_sizep, PRTCCPHYS physp, size_t - - /* try for big first. */ - tmp_size = RT_ALIGN_Z(xfer_size, PAGE_SIZE); -- if (tmp_size > 16U*_1K) -- tmp_size = 16U*_1K; -+ if (tmp_size > 128U*_1K) -+ tmp_size = 128U*_1K; - tmp = kmalloc(tmp_size, GFP_KERNEL); - if (!tmp) - { --- -2.5.4 (Apple Git-61) - diff --git a/virtualbox/iso/patches/0002-Remove-sf_file_write.patch b/virtualbox/iso/patches/0002-Remove-sf_file_write.patch new file mode 100644 index 0000000..1d0ee24 --- /dev/null +++ b/virtualbox/iso/patches/0002-Remove-sf_file_write.patch @@ -0,0 +1,89 @@ +From 32a69b3b8308b7acecc374eac4939fce5d60137b Mon Sep 17 00:00:00 2001 +From: "A.I" +Date: Fri, 17 Jun 2016 07:44:28 -0700 +Subject: [PATCH 2/2] Remove sf_file_write() + +--- + regops.c | 43 +++---------------------------------------- + 1 file changed, 3 insertions(+), 40 deletions(-) + +diff --git a/regops.c b/regops.c +index 09cc13c..314b5a9 100644 +--- a/regops.c ++++ b/regops.c +@@ -107,42 +107,6 @@ sf_file_read(struct kiocb *iocb, struct iov_iter *iov) + return generic_file_read_iter(iocb, iov); + } + +-static int sf_need_sync_write(struct file *file, struct inode *inode) +-{ +- // >= kernel version 2.6.33 +- if (IS_SYNC(inode) || file->f_flags & O_DSYNC) +- { +- return 1; +- } +- return 0; +-} +- +-static ssize_t +-sf_file_write(struct kiocb *iocb, struct iov_iter *iov) +-{ +- int err; +- ssize_t result; +- struct file *file = iocb->ki_filp; +- struct dentry *dentry = file->f_path.dentry; +- struct inode *inode = dentry->d_inode; +- +- err = sf_inode_revalidate(dentry); +- if (err) +- return err; +- +- result = generic_file_write_iter(iocb, iov); +- +- if (result >= 0 && sf_need_sync_write(file, inode)) +- { +- err = vfs_fsync(file, 0); +- if (err < 0) +- { +- result = err; +- } +- } +- return result; +-} +- + #else /* KERNEL_VERSION >= 3.16.0 */ + + /** +@@ -220,6 +184,8 @@ fail: + return err; + } + ++#endif /* KERNEL_VERSION >= 3.16.0 */ ++ + /** + * Write to a regular file. + * +@@ -320,8 +286,6 @@ fail: + return err; + } + +-#endif /* KERNEL_VERSION >= 3.16.0 */ +- + static loff_t + sf_file_llseek(struct file *file, loff_t offset, int origin) + { +@@ -652,10 +616,9 @@ struct file_operations sf_reg_fops = + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) + #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) + .read = new_sync_read, +- .write = new_sync_write, + #endif // LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) + .read_iter = sf_file_read, +- .write_iter = sf_file_write, ++ .write = sf_reg_write, + #else + .read = sf_reg_read, + .write = sf_reg_write, +-- +2.5.4 (Apple Git-61) +