I have made the following changes intended for : CE:Adaptation:x86-generic / virtualbox
Please review and accept or decline. BOSS has already run some checks on this request. See the "Messages from BOSS" section below. https://build.pub.meego.com//request/show/7789 Thank You, rbraakman [This message was auto-generated] --- Request # 7789: Messages from BOSS: WARNING check_package_is_complete_sources (virtualbox) failed: No dsc file found Extra source files: boss.conf, virtualbox.changes_suse. State: review at 2013-02-01T10:39:53 by bossbot Reviews: accepted by bossbot : Prechecks succeeded. new for CE-maintainers : Please replace this text with a review and approve/reject the review (not the SR). BOSS will take care of the rest Changes: submit: home:rbraakman:branches:CE:Adaptation:x86-generic / virtualbox -> CE:Adaptation:x86-generic / virtualbox changes files: -------------- --- virtualbox.changes +++ virtualbox.changes @@ -0,0 +1,7 @@ +* Fri Feb 01 2013 Richard Braakman <[email protected]> - 4.2.4 +- Ensure build failure if guest modules do not compile +- [vboxsf] + Bugfixes to shared folders module + Enable writable mmap (needed by zypper, building kernel, probably more) + Performance improvements, it is now about 40% slower than guest-native + new: ---- vbox-fix-restat.diff vbox-handles.diff vbox-less-restat.diff vbox-mmap.diff spec files: ----------- --- virtualbox.spec +++ virtualbox.spec @@ -109,6 +109,10 @@ Patch103: vbox-disable-updates.diff #use pie/fPIE for setuid binaries (bnc#743143) Patch104: vbox-fpie.diff +Patch201: vbox-fix-restat.diff +Patch202: vbox-less-restat.diff +Patch203: vbox-handles.diff +Patch204: vbox-mmap.diff BuildRoot: %{_tmppath}/%{name}-%{version}-build #PreReq: pwdutils permissions Requires: %{name}-host-kmp = %version @@ -171,7 +175,10 @@ #Y%patch101 %patch103 %patch104 -p1 -#Y%patch105 -p1 +%patch201 -p1 +%patch202 -p1 +%patch203 -p1 +%patch204 -p1 #copy user manual %__cp %{S:1} UserManual.pdf #copy kbuild config @@ -258,6 +265,11 @@ for module_name in modules_build_dir/*/. do %__make -C $KERNEL_DIR modules_install M=$(dirname $PWD/$module_name) + if [ ! -f "$INSTALL_MOD_PATH"/lib/modules/*/vbox/$(basename $(dirname $module_name)).* ] + then + echo "Failed to build $module_name" + exit 1 + fi done # Clean up spurious stuff rm -f %{buildroot}/lib/modules/*/modules.* other changes: -------------- ++++++ vbox-fix-restat.diff (new) --- vbox-fix-restat.diff +++ vbox-fix-restat.diff @@ -0,0 +1,18 @@ +commit 96893793b5d3636198b36f531d328970ce40331d +Author: Richard Braakman <[email protected]> +Date: Fri Jan 25 11:33:47 2013 +0200 + + Bugfix: set force_restat back to 0 when restatting + +diff --git a/src/VBox/Additions/linux/sharedfolders/utils.c b/src/VBox/Additions/linux/sharedfolders/utils.c +index aa9c396..7ba8276 100644 +--- a/src/VBox/Additions/linux/sharedfolders/utils.c ++++ b/src/VBox/Additions/linux/sharedfolders/utils.c +@@ -238,6 +238,7 @@ int sf_inode_revalidate(struct dentry *dentry) + return 0; + } + ++ sf_i->force_restat = 0; + err = sf_stat(__func__, sf_g, sf_i->path, &info, 1); + if (err) + return err; ++++++ vbox-handles.diff (new) --- vbox-handles.diff +++ vbox-handles.diff @@ -0,0 +1,215 @@ +commit 6dfd0c7549b3406e0bd94c6417ba590249f7f60e +Author: Richard Braakman <[email protected]> +Date: Thu Jan 31 01:15:25 2013 +0200 + + vboxsf: make sure writepage still works after concurrent open/close + +diff --git a/src/VBox/Additions/linux/sharedfolders/dirops.c b/src/VBox/Additions/linux/sharedfolders/dirops.c +index d0d7b85..5e32135 100644 +--- a/src/VBox/Additions/linux/sharedfolders/dirops.c ++++ b/src/VBox/Additions/linux/sharedfolders/dirops.c +@@ -358,8 +358,10 @@ static struct dentry *sf_lookup(struct inode *parent, struct dentry *dentry + err = -ENOMEM; + goto fail1; + } ++ INIT_LIST_HEAD(&sf_new_i->handles); + sf_new_i->handle = SHFL_HANDLE_NIL; + sf_new_i->force_reread = 0; ++ sf_new_i->force_restat = 0; + + ino = iunique(parent->i_sb, 1); + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) +@@ -458,6 +460,7 @@ static int sf_instantiate(struct inode *parent, struct dentry *dentry, + #else + dentry->d_op = &sf_dentry_ops; + #endif ++ INIT_LIST_HEAD(&sf_new_i->handles); + sf_new_i->force_restat = 0; + sf_new_i->force_reread = 0; + +diff --git a/src/VBox/Additions/linux/sharedfolders/regops.c b/src/VBox/Additions/linux/sharedfolders/regops.c +index 1ba03e3..db1641b 100644 +--- a/src/VBox/Additions/linux/sharedfolders/regops.c ++++ b/src/VBox/Additions/linux/sharedfolders/regops.c +@@ -294,21 +294,6 @@ static int sf_reg_open(struct inode *inode, struct file *file) + return -ENOMEM; + } + +- /* Already open? */ +- if (sf_i->handle != SHFL_HANDLE_NIL) +- { +- /* +- * This inode was created with sf_create_aux(). Check the CreateFlags: +- * O_CREAT, O_TRUNC: inherent true (file was just created). Not sure +- * about the access flags (SHFL_CF_ACCESS_*). +- */ +- sf_r->handle = sf_i->handle; +- sf_i->handle = SHFL_HANDLE_NIL; +- sf_i->file = file; +- file->private_data = sf_r; +- return 0; +- } +- + RT_ZERO(params); + params.Handle = SHFL_HANDLE_NIL; + /* We check the value of params.Handle afterwards to find out if +@@ -371,6 +356,19 @@ static int sf_reg_open(struct inode *inode, struct file *file) + params.CreateFlags |= SHFL_CF_ACCESS_APPEND; + } + ++ /* Already open? */ ++ if (sf_i->handle != SHFL_HANDLE_NIL) ++ { ++ /* ++ * This inode was created with sf_create_aux(). Check the CreateFlags: ++ * O_CREAT, O_TRUNC: inherent true (file was just created). Not sure ++ * about the access flags (SHFL_CF_ACCESS_*). ++ */ ++ sf_r->handle = sf_i->handle; ++ sf_i->handle = SHFL_HANDLE_NIL; ++ goto out; ++ } ++ + params.Info.Attr.fMode = inode->i_mode; + LogFunc(("sf_reg_open: calling vboxCallCreate, file %s, flags=%#x, %#x\n", + sf_i->path->String.utf8 , file->f_flags, params.CreateFlags)); +@@ -404,7 +402,10 @@ static int sf_reg_open(struct inode *inode, struct file *file) + sf_init_inode(sf_g, inode, ¶ms.Info); + + sf_r->handle = params.Handle; +- sf_i->file = file; ++ out: ++ sf_r->createflags = params.CreateFlags; ++ INIT_LIST_HEAD(&sf_r->head); ++ list_add(&sf_r->head, &sf_i->handles); + file->private_data = sf_r; + return rc_linux; + } +@@ -440,14 +441,16 @@ static int sf_reg_release(struct inode *inode, struct file *file) + && filemap_fdatawrite(inode->i_mapping) != -EIO) + filemap_fdatawait(inode->i_mapping); + #endif ++ ++ list_del(&sf_r->head); ++ + rc = vboxCallClose(&client_handle, &sf_g->map, sf_r->handle); + if (RT_FAILURE(rc)) + LogFunc(("vboxCallClose failed rc=%Rrc\n", rc)); + +- kfree(sf_r); +- sf_i->file = NULL; + sf_i->handle = SHFL_HANDLE_NIL; + file->private_data = NULL; ++ kfree(sf_r); + return 0; + } + +@@ -600,6 +603,26 @@ struct inode_operations sf_reg_iops = + + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) ++/* Helper function to pick a suitable handle for pagecache operations. ++ * It picks the most recently opened handle for this inode that has the ++ * requested flags (SHFL_CF_ACCESS_READ or SHFL_CF_ACCESS_WRITE). ++ * Handles with SHFL_CF_ACCESS_APPEND are not suitable for paged use ++ * so they are always skipped. ++ */ ++static struct sf_reg_info *sf_select_handle(struct inode *inode, u32 flags) ++{ ++ struct sf_inode_info *sf_i = GET_INODE_INFO(inode); ++ struct sf_reg_info *sf_r; ++ ++ list_for_each_entry(sf_r, &sf_i->handles, head) ++ { ++ if ( sf_r->handle != SHFL_HANDLE_NIL ++ && (sf_r->createflags & (flags | SHFL_CF_ACCESS_APPEND)) == flags) ++ return sf_r; ++ } ++ return NULL; ++} ++ + static int sf_readpage(struct file *file, struct page *page) + { + struct inode *inode = file->f_dentry->d_inode; +@@ -636,9 +659,7 @@ sf_writepage(struct page *page, struct writeback_control *wbc) + struct address_space *mapping = page->mapping; + struct inode *inode = mapping->host; + struct sf_glob_info *sf_g = GET_GLOB_INFO(inode->i_sb); +- struct sf_inode_info *sf_i = GET_INODE_INFO(inode); +- struct file *file = sf_i->file; +- struct sf_reg_info *sf_r = file->private_data; ++ struct sf_reg_info *sf_r; + char *buf; + uint32_t nwritten = PAGE_SIZE; + int end_index = inode->i_size >> PAGE_SHIFT; +@@ -647,6 +668,15 @@ sf_writepage(struct page *page, struct writeback_control *wbc) + + TRACE(); + ++ sf_r = sf_select_handle(inode, SHFL_CF_ACCESS_WRITE); ++ if (unlikely(!sf_r)) ++ { ++ /* At least the handle of whoever wrote to the page should ++ * still be available; see the wait in sf_reg_release() */ ++ WARN_ONCE(1, "vboxsf: could not find handle for writepage"); ++ return -EBADF; ++ } ++ + if (page->index >= end_index) + nwritten = inode->i_size & (PAGE_SIZE-1); + +diff --git a/src/VBox/Additions/linux/sharedfolders/vfsmod.c b/src/VBox/Additions/linux/sharedfolders/vfsmod.c +index 3c55136..79097c5 100644 +--- a/src/VBox/Additions/linux/sharedfolders/vfsmod.c ++++ b/src/VBox/Additions/linux/sharedfolders/vfsmod.c +@@ -237,6 +237,7 @@ static int sf_read_super_aux(struct super_block *sb, void *data, int flags) + goto fail1; + } + ++ INIT_LIST_HEAD(&sf_i->handles); + sf_i->handle = SHFL_HANDLE_NIL; + sf_i->path = kmalloc(sizeof(SHFLSTRING) + 1, GFP_KERNEL); + if (!sf_i->path) +@@ -372,6 +373,7 @@ static void sf_clear_inode(struct inode *inode) + if (!sf_i) + return; + ++ WARN_ON(!list_empty(&sf_i->handles)); + BUG_ON(!sf_i->path); + kfree(sf_i->path); + kfree(sf_i); +@@ -394,6 +396,7 @@ static void sf_evict_inode(struct inode *inode) + if (!sf_i) + return; + ++ WARN_ON(!list_empty(&sf_i->handles)); + BUG_ON(!sf_i->path); + kfree(sf_i->path); + kfree(sf_i); +diff --git a/src/VBox/Additions/linux/sharedfolders/vfsmod.h b/src/VBox/Additions/linux/sharedfolders/vfsmod.h +index 6a20eb7..c7df740 100644 +--- a/src/VBox/Additions/linux/sharedfolders/vfsmod.h ++++ b/src/VBox/Additions/linux/sharedfolders/vfsmod.h +@@ -58,11 +58,11 @@ struct sf_inode_info + int force_restat; + /* directory content changed, update the whole directory on next sf_getdent */ + int force_reread; +- /* file structure, only valid between open() and release() */ +- struct file *file; + /* handle valid if a file was created with sf_create_aux until it will (16 more lines skipped) ++++++ vbox-less-restat.diff (new) --- vbox-less-restat.diff +++ vbox-less-restat.diff @@ -0,0 +1,56 @@ +commit 05d5aa0d4f45d2a60ce22a0b2d5df8353429d744 +Author: Richard Braakman <[email protected]> +Date: Tue Jan 29 14:57:49 2013 +0200 + + linux sharedfolders: remove redundant statting + + There's no need to force a restat right after filling a new inode with stat + information. Also, open() can use the stat info it gets with the handle + instead of statting again. + +diff --git a/src/VBox/Additions/linux/sharedfolders/dirops.c b/src/VBox/Additions/linux/sharedfolders/dirops.c +index f7f558a..d0d7b85 100644 +--- a/src/VBox/Additions/linux/sharedfolders/dirops.c ++++ b/src/VBox/Additions/linux/sharedfolders/dirops.c +@@ -458,7 +458,7 @@ static int sf_instantiate(struct inode *parent, struct dentry *dentry, + #else + dentry->d_op = &sf_dentry_ops; + #endif +- sf_new_i->force_restat = 1; ++ sf_new_i->force_restat = 0; + sf_new_i->force_reread = 0; + + d_instantiate(dentry, inode); +diff --git a/src/VBox/Additions/linux/sharedfolders/regops.c b/src/VBox/Additions/linux/sharedfolders/regops.c +index 37adbcb..1ba03e3 100644 +--- a/src/VBox/Additions/linux/sharedfolders/regops.c ++++ b/src/VBox/Additions/linux/sharedfolders/regops.c +@@ -302,7 +302,6 @@ static int sf_reg_open(struct inode *inode, struct file *file) + * O_CREAT, O_TRUNC: inherent true (file was just created). Not sure + * about the access flags (SHFL_CF_ACCESS_*). + */ +- sf_i->force_restat = 1; + sf_r->handle = sf_i->handle; + sf_i->handle = SHFL_HANDLE_NIL; + sf_i->file = file; +@@ -378,6 +377,7 @@ static int sf_reg_open(struct inode *inode, struct file *file) + rc = vboxCallCreate(&client_handle, &sf_g->map, sf_i->path, ¶ms); + if (RT_FAILURE(rc)) + { ++ sf_i->force_restat = 1; + LogFunc(("vboxCallCreate failed flags=%d,%#x rc=%Rrc\n", + file->f_flags, params.CreateFlags, rc)); + kfree(sf_r); +@@ -398,9 +398,11 @@ static int sf_reg_open(struct inode *inode, struct file *file) + default: + break; + } ++ sf_i->force_restat = 1; + } ++ else ++ sf_init_inode(sf_g, inode, ¶ms.Info); + +- sf_i->force_restat = 1; + sf_r->handle = params.Handle; + sf_i->file = file; + file->private_data = sf_r; ++++++ vbox-mmap.diff (new) --- vbox-mmap.diff +++ vbox-mmap.diff @@ -0,0 +1,151 @@ +diff --git a/src/VBox/Additions/linux/sharedfolders/regops.c b/src/VBox/Additions/linux/sharedfolders/regops.c +index db1641b..094d277 100644 +--- a/src/VBox/Additions/linux/sharedfolders/regops.c ++++ b/src/VBox/Additions/linux/sharedfolders/regops.c +@@ -16,7 +16,7 @@ + */ + + /* +- * Limitations: only COW memory mapping is supported ++ * Limitations: MAP_SHARED mmap does not notice changes made on the host. + */ + + #include "vfsmod.h" +@@ -329,25 +329,22 @@ static int sf_reg_open(struct inode *inode, struct file *file) + } + } + +- if (!(params.CreateFlags & SHFL_CF_ACCESS_READWRITE)) ++ switch (file->f_flags & O_ACCMODE) + { +- switch (file->f_flags & O_ACCMODE) +- { +- case O_RDONLY: +- params.CreateFlags |= SHFL_CF_ACCESS_READ; +- break; ++ case O_RDONLY: ++ params.CreateFlags |= SHFL_CF_ACCESS_READ; ++ break; + +- case O_WRONLY: +- params.CreateFlags |= SHFL_CF_ACCESS_WRITE; +- break; ++ case O_WRONLY: ++ params.CreateFlags |= SHFL_CF_ACCESS_WRITE; ++ break; + +- case O_RDWR: +- params.CreateFlags |= SHFL_CF_ACCESS_READWRITE; +- break; ++ case O_RDWR: ++ params.CreateFlags |= SHFL_CF_ACCESS_READWRITE; ++ break; + +- default: +- BUG (); +- } ++ default: ++ BUG (); + } + + if (file->f_flags & O_APPEND) +@@ -489,7 +486,7 @@ static struct page *sf_reg_nopage(struct vm_area_struct *vma, unsigned long vadd + /* Don't use GFP_HIGHUSER as long as sf_reg_read_aux() calls vboxCallRead() + * which works on virtual addresses. On Linux cannot reliably determine the + * physical address for high memory, see rtR0MemObjNativeLockKernel(). */ +- page = alloc_page(GFP_USER); ++ page = find_or_create_page(inode->i_mapping, vmf->pgoff, GFP_USER); + if (!page) { + LogRelFunc(("failed to allocate page\n")); + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25) +@@ -510,7 +507,8 @@ static struct page *sf_reg_nopage(struct vm_area_struct *vma, unsigned long vadd + if (err) + { + kunmap(page); +- put_page(page); ++ unlock_page(page); ++ page_cache_release(page); + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25) + return VM_FAULT_SIGBUS; + #else +@@ -534,7 +532,9 @@ static struct page *sf_reg_nopage(struct vm_area_struct *vma, unsigned long vadd + memset(buf + nread, 0, PAGE_SIZE - nread); + + flush_dcache_page(page); ++ SetPageUptodate(page); + kunmap(page); ++ unlock_page(page); + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25) + vmf->page = page; + return 0; +@@ -544,24 +544,51 @@ static struct page *sf_reg_nopage(struct vm_area_struct *vma, unsigned long vadd + #endif + } + ++/** ++ * Prepare for a mmap page to be made writable. ++ * Check that the page is still there, and lock it if necessary to keep it there. ++ * Part of MAP_SHARED support. ++ * ++ * @returns VM_FAULT_LOCKED if the page is ready, otherwise VM_FAULT_NOPAGE. ++ */ ++static int sf_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) ++{ ++ struct page *page = vmf->page; ++ struct inode *inode = vma->vm_file->f_path.dentry->d_inode; ++ loff_t size; ++ ++ TRACE(); ++ ++ lock_page(page); ++ size = i_size_read(inode); ++ if (page->mapping != inode->i_mapping || page_offset(page) > size) ++ { ++ /* file was truncated */ ++ unlock_page(page); ++ return VM_FAULT_NOPAGE; ++ } ++ ++ wait_on_page_writeback(page); ++ return VM_FAULT_LOCKED; ++} ++ + static struct vm_operations_struct sf_vma_ops = + { + #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 25) +- .fault = sf_reg_fault ++ .fault = sf_reg_fault, + #else +- .nopage = sf_reg_nopage ++ .nopage = sf_reg_nopage, + #endif ++ .page_mkwrite = sf_page_mkwrite + }; + + static int sf_reg_mmap(struct file *file, struct vm_area_struct *vma) + { +- TRACE(); +- if (vma->vm_flags & VM_SHARED) +- { +- LogFunc(("shared mmapping not available\n")); +- return -EINVAL; +- } ++ struct sf_reg_info *sf_r = file->private_data; + ++ TRACE(); ++ if (sf_r->createflags & SHFL_CF_ACCESS_APPEND) ++ return -EINVAL; /* can't simulate page operations */ + vma->vm_ops = &sf_vma_ops; + return 0; + } +@@ -689,8 +716,8 @@ sf_writepage(struct page *page, struct writeback_control *wbc) + goto out; + } + +- if (off > inode->i_size) +- inode->i_size = off; ++ if (off + nwritten > inode->i_size) ++ inode->i_size = off + nwritten; + + if (PageError(page)) + ClearPageError(page);
