Commit 18d04062 authored by Shyam Prasad N's avatar Shyam Prasad N Committed by Steve French

cifs: enable fscache usage even for files opened as rw

So far, the fscache implementation we had supports only
a small set of use cases. Particularly for files opened
with O_RDONLY.

This commit enables it even for rw based file opens. It
also enables the reuse of cached data in case of mount
option (cache=singleclient) where it is guaranteed that
this is the only client (and server) which operates on
the files. There's also a single line change in fscache.c
to get around a bug seen in fscache.
Signed-off-by: default avatarShyam Prasad N <sprasad@microsoft.com>
Acked-by: default avatarRonnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 3d2b50e0
...@@ -399,7 +399,6 @@ cifs_evict_inode(struct inode *inode) ...@@ -399,7 +399,6 @@ cifs_evict_inode(struct inode *inode)
{ {
truncate_inode_pages_final(&inode->i_data); truncate_inode_pages_final(&inode->i_data);
clear_inode(inode); clear_inode(inode);
cifs_fscache_release_inode_cookie(inode);
} }
static void static void
......
...@@ -2101,6 +2101,7 @@ cifs_writev_complete(struct work_struct *work) ...@@ -2101,6 +2101,7 @@ cifs_writev_complete(struct work_struct *work)
else if (wdata->result < 0) else if (wdata->result < 0)
SetPageError(page); SetPageError(page);
end_page_writeback(page); end_page_writeback(page);
cifs_readpage_to_fscache(inode, page);
put_page(page); put_page(page);
} }
if (wdata->result != -EAGAIN) if (wdata->result != -EAGAIN)
......
...@@ -377,6 +377,8 @@ static void cifsFileInfo_put_final(struct cifsFileInfo *cifs_file) ...@@ -377,6 +377,8 @@ static void cifsFileInfo_put_final(struct cifsFileInfo *cifs_file)
struct cifsLockInfo *li, *tmp; struct cifsLockInfo *li, *tmp;
struct super_block *sb = inode->i_sb; struct super_block *sb = inode->i_sb;
cifs_fscache_release_inode_cookie(inode);
/* /*
* Delete any outstanding lock records. We'll lose them when the file * Delete any outstanding lock records. We'll lose them when the file
* is closed anyway. * is closed anyway.
...@@ -882,8 +884,10 @@ int cifs_close(struct inode *inode, struct file *file) ...@@ -882,8 +884,10 @@ int cifs_close(struct inode *inode, struct file *file)
if ((cinode->oplock == CIFS_CACHE_RHW_FLG) && if ((cinode->oplock == CIFS_CACHE_RHW_FLG) &&
cinode->lease_granted && cinode->lease_granted &&
dclose) { dclose) {
if (test_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) if (test_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) {
inode->i_ctime = inode->i_mtime = current_time(inode); inode->i_ctime = inode->i_mtime = current_time(inode);
cifs_fscache_update_inode_cookie(inode);
}
spin_lock(&cinode->deferred_lock); spin_lock(&cinode->deferred_lock);
cifs_add_deferred_close(cfile, dclose); cifs_add_deferred_close(cfile, dclose);
if (cfile->deferred_close_scheduled && if (cfile->deferred_close_scheduled &&
...@@ -4170,6 +4174,10 @@ static vm_fault_t ...@@ -4170,6 +4174,10 @@ static vm_fault_t
cifs_page_mkwrite(struct vm_fault *vmf) cifs_page_mkwrite(struct vm_fault *vmf)
{ {
struct page *page = vmf->page; struct page *page = vmf->page;
struct file *file = vmf->vma->vm_file;
struct inode *inode = file_inode(file);
cifs_fscache_wait_on_page_write(inode, page);
lock_page(page); lock_page(page);
return VM_FAULT_LOCKED; return VM_FAULT_LOCKED;
...@@ -4235,13 +4243,16 @@ cifs_readv_complete(struct work_struct *work) ...@@ -4235,13 +4243,16 @@ cifs_readv_complete(struct work_struct *work)
(rdata->result == -EAGAIN && got_bytes)) { (rdata->result == -EAGAIN && got_bytes)) {
flush_dcache_page(page); flush_dcache_page(page);
SetPageUptodate(page); SetPageUptodate(page);
} } else
SetPageError(page);
unlock_page(page); unlock_page(page);
if (rdata->result == 0 || if (rdata->result == 0 ||
(rdata->result == -EAGAIN && got_bytes)) (rdata->result == -EAGAIN && got_bytes))
cifs_readpage_to_fscache(rdata->mapping->host, page); cifs_readpage_to_fscache(rdata->mapping->host, page);
else
cifs_fscache_uncache_page(rdata->mapping->host, page);
got_bytes -= min_t(unsigned int, PAGE_SIZE, got_bytes); got_bytes -= min_t(unsigned int, PAGE_SIZE, got_bytes);
......
...@@ -176,29 +176,34 @@ void cifs_fscache_release_inode_cookie(struct inode *inode) ...@@ -176,29 +176,34 @@ void cifs_fscache_release_inode_cookie(struct inode *inode)
auxdata.last_change_time_nsec = cifsi->vfs_inode.i_ctime.tv_nsec; auxdata.last_change_time_nsec = cifsi->vfs_inode.i_ctime.tv_nsec;
cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache); cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache);
/* fscache_relinquish_cookie does not seem to update auxdata */
fscache_update_cookie(cifsi->fscache, &auxdata);
fscache_relinquish_cookie(cifsi->fscache, &auxdata, false); fscache_relinquish_cookie(cifsi->fscache, &auxdata, false);
cifsi->fscache = NULL; cifsi->fscache = NULL;
} }
} }
static void cifs_fscache_disable_inode_cookie(struct inode *inode) void cifs_fscache_update_inode_cookie(struct inode *inode)
{ {
struct cifs_fscache_inode_auxdata auxdata;
struct cifsInodeInfo *cifsi = CIFS_I(inode); struct cifsInodeInfo *cifsi = CIFS_I(inode);
if (cifsi->fscache) { if (cifsi->fscache) {
memset(&auxdata, 0, sizeof(auxdata));
auxdata.eof = cifsi->server_eof;
auxdata.last_write_time_sec = cifsi->vfs_inode.i_mtime.tv_sec;
auxdata.last_change_time_sec = cifsi->vfs_inode.i_ctime.tv_sec;
auxdata.last_write_time_nsec = cifsi->vfs_inode.i_mtime.tv_nsec;
auxdata.last_change_time_nsec = cifsi->vfs_inode.i_ctime.tv_nsec;
cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache); cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache);
fscache_uncache_all_inode_pages(cifsi->fscache, inode); fscache_update_cookie(cifsi->fscache, &auxdata);
fscache_relinquish_cookie(cifsi->fscache, NULL, true);
cifsi->fscache = NULL;
} }
} }
void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp) void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
{ {
if ((filp->f_flags & O_ACCMODE) != O_RDONLY) cifs_fscache_enable_inode_cookie(inode);
cifs_fscache_disable_inode_cookie(inode);
else
cifs_fscache_enable_inode_cookie(inode);
} }
void cifs_fscache_reset_inode_cookie(struct inode *inode) void cifs_fscache_reset_inode_cookie(struct inode *inode)
...@@ -310,6 +315,8 @@ void __cifs_readpage_to_fscache(struct inode *inode, struct page *page) ...@@ -310,6 +315,8 @@ void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
struct cifsInodeInfo *cifsi = CIFS_I(inode); struct cifsInodeInfo *cifsi = CIFS_I(inode);
int ret; int ret;
WARN_ON(!cifsi->fscache);
cifs_dbg(FYI, "%s: (fsc: %p, p: %p, i: %p)\n", cifs_dbg(FYI, "%s: (fsc: %p, p: %p, i: %p)\n",
__func__, cifsi->fscache, page, inode); __func__, cifsi->fscache, page, inode);
ret = fscache_write_page(cifsi->fscache, page, ret = fscache_write_page(cifsi->fscache, page,
...@@ -334,3 +341,21 @@ void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode) ...@@ -334,3 +341,21 @@ void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode)
fscache_wait_on_page_write(cookie, page); fscache_wait_on_page_write(cookie, page);
fscache_uncache_page(cookie, page); fscache_uncache_page(cookie, page);
} }
void __cifs_fscache_wait_on_page_write(struct inode *inode, struct page *page)
{
struct cifsInodeInfo *cifsi = CIFS_I(inode);
struct fscache_cookie *cookie = cifsi->fscache;
cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", __func__, page, cookie);
fscache_wait_on_page_write(cookie, page);
}
void __cifs_fscache_uncache_page(struct inode *inode, struct page *page)
{
struct cifsInodeInfo *cifsi = CIFS_I(inode);
struct fscache_cookie *cookie = cifsi->fscache;
cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", __func__, page, cookie);
fscache_uncache_page(cookie, page);
}
...@@ -55,10 +55,13 @@ extern void cifs_fscache_get_super_cookie(struct cifs_tcon *); ...@@ -55,10 +55,13 @@ extern void cifs_fscache_get_super_cookie(struct cifs_tcon *);
extern void cifs_fscache_release_super_cookie(struct cifs_tcon *); extern void cifs_fscache_release_super_cookie(struct cifs_tcon *);
extern void cifs_fscache_release_inode_cookie(struct inode *); extern void cifs_fscache_release_inode_cookie(struct inode *);
extern void cifs_fscache_update_inode_cookie(struct inode *inode);
extern void cifs_fscache_set_inode_cookie(struct inode *, struct file *); extern void cifs_fscache_set_inode_cookie(struct inode *, struct file *);
extern void cifs_fscache_reset_inode_cookie(struct inode *); extern void cifs_fscache_reset_inode_cookie(struct inode *);
extern void __cifs_fscache_invalidate_page(struct page *, struct inode *); extern void __cifs_fscache_invalidate_page(struct page *, struct inode *);
extern void __cifs_fscache_wait_on_page_write(struct inode *inode, struct page *page);
extern void __cifs_fscache_uncache_page(struct inode *inode, struct page *page);
extern int cifs_fscache_release_page(struct page *page, gfp_t gfp); extern int cifs_fscache_release_page(struct page *page, gfp_t gfp);
extern int __cifs_readpage_from_fscache(struct inode *, struct page *); extern int __cifs_readpage_from_fscache(struct inode *, struct page *);
extern int __cifs_readpages_from_fscache(struct inode *, extern int __cifs_readpages_from_fscache(struct inode *,
...@@ -76,6 +79,20 @@ static inline void cifs_fscache_invalidate_page(struct page *page, ...@@ -76,6 +79,20 @@ static inline void cifs_fscache_invalidate_page(struct page *page,
__cifs_fscache_invalidate_page(page, inode); __cifs_fscache_invalidate_page(page, inode);
} }
static inline void cifs_fscache_wait_on_page_write(struct inode *inode,
struct page *page)
{
if (PageFsCache(page))
__cifs_fscache_wait_on_page_write(inode, page);
}
static inline void cifs_fscache_uncache_page(struct inode *inode,
struct page *page)
{
if (PageFsCache(page))
__cifs_fscache_uncache_page(inode, page);
}
static inline int cifs_readpage_from_fscache(struct inode *inode, static inline int cifs_readpage_from_fscache(struct inode *inode,
struct page *page) struct page *page)
{ {
...@@ -123,6 +140,7 @@ static inline void ...@@ -123,6 +140,7 @@ static inline void
cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) {} cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) {}
static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {} static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {}
static inline void cifs_fscache_update_inode_cookie(struct inode *inode) {}
static inline void cifs_fscache_set_inode_cookie(struct inode *inode, static inline void cifs_fscache_set_inode_cookie(struct inode *inode,
struct file *filp) {} struct file *filp) {}
static inline void cifs_fscache_reset_inode_cookie(struct inode *inode) {} static inline void cifs_fscache_reset_inode_cookie(struct inode *inode) {}
...@@ -133,6 +151,11 @@ static inline int cifs_fscache_release_page(struct page *page, gfp_t gfp) ...@@ -133,6 +151,11 @@ static inline int cifs_fscache_release_page(struct page *page, gfp_t gfp)
static inline void cifs_fscache_invalidate_page(struct page *page, static inline void cifs_fscache_invalidate_page(struct page *page,
struct inode *inode) {} struct inode *inode) {}
static inline void cifs_fscache_wait_on_page_write(struct inode *inode,
struct page *page) {}
static inline void cifs_fscache_uncache_page(struct inode *inode,
struct page *page) {}
static inline int static inline int
cifs_readpage_from_fscache(struct inode *inode, struct page *page) cifs_readpage_from_fscache(struct inode *inode, struct page *page)
{ {
......
...@@ -2297,6 +2297,7 @@ cifs_revalidate_mapping(struct inode *inode) ...@@ -2297,6 +2297,7 @@ cifs_revalidate_mapping(struct inode *inode)
{ {
int rc; int rc;
unsigned long *flags = &CIFS_I(inode)->flags; unsigned long *flags = &CIFS_I(inode)->flags;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
/* swapfiles are not supposed to be shared */ /* swapfiles are not supposed to be shared */
if (IS_SWAPFILE(inode)) if (IS_SWAPFILE(inode))
...@@ -2308,11 +2309,16 @@ cifs_revalidate_mapping(struct inode *inode) ...@@ -2308,11 +2309,16 @@ cifs_revalidate_mapping(struct inode *inode)
return rc; return rc;
if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) { if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
/* for cache=singleclient, do not invalidate */
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE)
goto skip_invalidate;
rc = cifs_invalidate_mapping(inode); rc = cifs_invalidate_mapping(inode);
if (rc) if (rc)
set_bit(CIFS_INO_INVALID_MAPPING, flags); set_bit(CIFS_INO_INVALID_MAPPING, flags);
} }
skip_invalidate:
clear_bit_unlock(CIFS_INO_LOCK, flags); clear_bit_unlock(CIFS_INO_LOCK, flags);
smp_mb__after_atomic(); smp_mb__after_atomic();
wake_up_bit(flags, CIFS_INO_LOCK); wake_up_bit(flags, CIFS_INO_LOCK);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment