Search
SailfishOS Open Build Service
>
Projects
>
nemo
:
devel:hw
:
x86:x86-common
>
virtualbox
> vbox-pagecache.diff
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File vbox-pagecache.diff of Package virtualbox (Revision 2)
Currently displaying revision
2
,
show latest
commit ee6ca84b247485b40c375ebb7e29a046446374df Author: Richard Braakman <richard.braakman@jollamobile.com> Date: Thu Jan 31 19:19:22 2013 +0200 sharedfolders: read() from page cache diff --git a/src/VBox/Additions/linux/sharedfolders/dirops.c b/src/VBox/Additions/linux/sharedfolders/dirops.c index 5e32135..1ed25dc 100644 --- a/src/VBox/Additions/linux/sharedfolders/dirops.c +++ b/src/VBox/Additions/linux/sharedfolders/dirops.c @@ -450,9 +450,9 @@ static int sf_instantiate(struct inode *parent, struct dentry *dentry, goto fail1; } + SET_INODE_INFO(inode, sf_new_i); sf_init_inode(sf_g, inode, info); sf_new_i->path = path; - SET_INODE_INFO(inode, sf_new_i); dentry->d_time = jiffies; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38) diff --git a/src/VBox/Additions/linux/sharedfolders/regops.c b/src/VBox/Additions/linux/sharedfolders/regops.c index c39fc97..37849cf 100644 --- a/src/VBox/Additions/linux/sharedfolders/regops.c +++ b/src/VBox/Additions/linux/sharedfolders/regops.c @@ -147,6 +147,13 @@ static ssize_t sf_reg_read(struct file *file, char *buf, size_t size, loff_t *of if (!size) return 0; + /* Try reading from the page cache */ + if (sf_r->generation == inode->i_generation) + return do_sync_read(file, buf, size, off); + else + printk("vboxsf: doing direct read, generation %u != %u\n", + sf_r->generation, inode->i_generation); + tmp = alloc_bounce_buffer(&tmp_size, size, __PRETTY_FUNCTION__); if (!tmp) return -ENOMEM; @@ -265,6 +272,18 @@ static ssize_t sf_reg_write(struct file *file, const char *buf, size_t size, lof break; } + /* force-invalidate the corresponding part of the page cache */ + err = invalidate_inode_pages2_range(inode->i_mapping, + *off >> PAGE_CACHE_SHIFT, + (*off + total_bytes_written - 1) >> PAGE_CACHE_SHIFT); + if (err) + { + printk("vboxsf: could not invalidate inode page cache for %s\n", + sf_i->path->String.utf8); + /** @todo fall back on pagecache write here? */ + inode->i_generation++; /* disable pagecache reads for current fds */ + } + *off += total_bytes_written; if (*off > inode->i_size) inode->i_size = *off; @@ -408,11 +427,15 @@ static int sf_reg_open(struct inode *inode, struct file *file) sf_i->force_restat = 1; } else + { + sf_revalidate_mapping(inode, ¶ms.Info); sf_init_inode(sf_g, inode, ¶ms.Info); + } sf_r->handle = params.Handle; out: sf_r->createflags = params.CreateFlags; + sf_r->generation = inode->i_generation; INIT_LIST_HEAD(&sf_r->head); list_add(&sf_r->head, &sf_i->handles); file->private_data = sf_r; @@ -674,6 +697,15 @@ static int sf_readpage(struct file *file, struct page *page) TRACE(); + sf_r = sf_select_handle(inode, SHFL_CF_ACCESS_READ); + if (unlikely(!sf_r)) + { + struct sf_inode_info *sf_i = GET_INODE_INFO(inode); + WARN(1, "vboxsf: could not find handle for readpage for %s", + sf_i->path->String.utf8); + sf_r = file->private_data; + } + buf = kmap(page); ret = sf_reg_read_aux(__func__, sf_g, sf_r, buf, &nread, off); if (ret) diff --git a/src/VBox/Additions/linux/sharedfolders/utils.c b/src/VBox/Additions/linux/sharedfolders/utils.c index 7ba8276..d2be0c5 100644 --- a/src/VBox/Additions/linux/sharedfolders/utils.c +++ b/src/VBox/Additions/linux/sharedfolders/utils.c @@ -71,6 +71,7 @@ static void sf_timespec_from_ftime(RTTIMESPEC *ts, struct timespec *tv) void sf_init_inode(struct sf_glob_info *sf_g, struct inode *inode, PSHFLFSOBJINFO info) { + struct sf_inode_info *sf_i = GET_INODE_INFO(inode); PSHFLFSOBJATTR attr; int mode; @@ -159,6 +160,49 @@ void sf_init_inode(struct sf_glob_info *sf_g, struct inode *inode, sf_ftime_from_timespec(&inode->i_atime, &info->AccessTime); sf_ftime_from_timespec(&inode->i_ctime, &info->ChangeTime); sf_ftime_from_timespec(&inode->i_mtime, &info->ModificationTime); + + if (attr->enmAdditional == SHFLFSOBJATTRADD_UNIX) + { + sf_i->host_dev = attr->u.Unix.INodeIdDevice; + sf_i->host_ino = attr->u.Unix.INodeId; + } +} + +/* Check if the host-side inode is likely to have had content changes, + * so that we should throw away the cached pages. */ +void sf_revalidate_mapping(struct inode *inode, PSHFLFSOBJINFO info) +{ + struct timespec mtime; + PSHFLFSOBJATTR attr = &info->Attr; + + TRACE(); + + if (i_size_read(inode) != info->cbObject) + { + spin_lock(&inode->i_lock); + truncate_setsize(inode, info->cbObject); + spin_unlock(&inode->i_lock); + goto out_invalid; + } + + sf_ftime_from_timespec(&mtime, &info->ModificationTime); + if (timespec_compare(&inode->i_mtime, &mtime)) + goto out_invalid; + + if (attr->enmAdditional == SHFLFSOBJATTRADD_UNIX) + { + struct sf_inode_info *sf_i = GET_INODE_INFO(inode); + if ( (sf_i->host_dev && sf_i->host_dev != attr->u.Unix.INodeIdDevice) + || (sf_i->host_ino && sf_i->host_ino != attr->u.Unix.INodeId)) + goto out_invalid; + } + + return; + + out_invalid: + invalidate_inode_pages2(inode->i_mapping); + inode->i_generation++; + return; } int sf_stat(const char *caller, struct sf_glob_info *sf_g, @@ -244,6 +288,7 @@ int sf_inode_revalidate(struct dentry *dentry) return err; dentry->d_time = jiffies; + sf_revalidate_mapping(dentry->d_inode, &info); sf_init_inode(sf_g, dentry->d_inode, &info); return 0; } diff --git a/src/VBox/Additions/linux/sharedfolders/vfsmod.c b/src/VBox/Additions/linux/sharedfolders/vfsmod.c index 79097c5..ef4daa9 100644 --- a/src/VBox/Additions/linux/sharedfolders/vfsmod.c +++ b/src/VBox/Additions/linux/sharedfolders/vfsmod.c @@ -300,8 +300,8 @@ static int sf_read_super_aux(struct super_block *sb, void *data, int flags) goto fail4; } - sf_init_inode(sf_g, iroot, &fsinfo); SET_INODE_INFO(iroot, sf_i); + sf_init_inode(sf_g, iroot, &fsinfo); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 25) unlock_new_inode(iroot); diff --git a/src/VBox/Additions/linux/sharedfolders/vfsmod.h b/src/VBox/Additions/linux/sharedfolders/vfsmod.h index c7df740..62fb489 100644 --- a/src/VBox/Additions/linux/sharedfolders/vfsmod.h +++ b/src/VBox/Additions/linux/sharedfolders/vfsmod.h @@ -63,6 +63,10 @@ struct sf_inode_info SHFLHANDLE handle; /* list of sf_reg_info for open files, most recent first */ struct list_head handles; + /* identification of host-side inode, to detect if it changed */ + /* these can be 0 if not known yet */ + RTINODE host_ino; + RTDEV host_dev; }; struct sf_dir_info @@ -84,6 +88,7 @@ struct sf_reg_info SHFLHANDLE handle; u32 createflags; /* SHFL_CF_ flags for this handle */ struct list_head head; /* starts at sf_i->handles */ + u32 generation; }; /* globals */ @@ -103,6 +108,7 @@ extern void sf_init_inode(struct sf_glob_info *sf_g, struct inode *inode, extern int sf_stat(const char *caller, struct sf_glob_info *sf_g, SHFLSTRING *path, PSHFLFSOBJINFO result, int ok_to_fail); extern int sf_inode_revalidate(struct dentry *dentry); +extern void sf_revalidate_mapping(struct inode *inode, PSHFLFSOBJINFO info); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) extern int sf_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *kstat);