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

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
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -399,7 +399,6 @@ cifs_evict_inode(struct inode *inode)
{
	truncate_inode_pages_final(&inode->i_data);
	clear_inode(inode);
	cifs_fscache_release_inode_cookie(inode);
}

static void
+1 −0
Original line number Diff line number Diff line
@@ -2101,6 +2101,7 @@ cifs_writev_complete(struct work_struct *work)
		else if (wdata->result < 0)
			SetPageError(page);
		end_page_writeback(page);
		cifs_readpage_to_fscache(inode, page);
		put_page(page);
	}
	if (wdata->result != -EAGAIN)
+13 −2
Original line number Diff line number Diff line
@@ -377,6 +377,8 @@ static void cifsFileInfo_put_final(struct cifsFileInfo *cifs_file)
	struct cifsLockInfo *li, *tmp;
	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
	 * is closed anyway.
@@ -882,8 +884,10 @@ int cifs_close(struct inode *inode, struct file *file)
		if ((cinode->oplock == CIFS_CACHE_RHW_FLG) &&
		    cinode->lease_granted &&
		    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);
				cifs_fscache_update_inode_cookie(inode);
			}
			spin_lock(&cinode->deferred_lock);
			cifs_add_deferred_close(cfile, dclose);
			if (cfile->deferred_close_scheduled &&
@@ -4170,6 +4174,10 @@ static vm_fault_t
cifs_page_mkwrite(struct vm_fault *vmf)
{
	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);
	return VM_FAULT_LOCKED;
@@ -4235,13 +4243,16 @@ cifs_readv_complete(struct work_struct *work)
		    (rdata->result == -EAGAIN && got_bytes)) {
			flush_dcache_page(page);
			SetPageUptodate(page);
		}
		} else
			SetPageError(page);

		unlock_page(page);

		if (rdata->result == 0 ||
		    (rdata->result == -EAGAIN && got_bytes))
			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);

+33 −8
Original line number Diff line number Diff line
@@ -176,28 +176,33 @@ void cifs_fscache_release_inode_cookie(struct inode *inode)
		auxdata.last_change_time_nsec = cifsi->vfs_inode.i_ctime.tv_nsec;

		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);
		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);

	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);
		fscache_uncache_all_inode_pages(cifsi->fscache, inode);
		fscache_relinquish_cookie(cifsi->fscache, NULL, true);
		cifsi->fscache = NULL;
		fscache_update_cookie(cifsi->fscache, &auxdata);
	}
}

void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
{
	if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
		cifs_fscache_disable_inode_cookie(inode);
	else
	cifs_fscache_enable_inode_cookie(inode);
}

@@ -310,6 +315,8 @@ void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
	struct cifsInodeInfo *cifsi = CIFS_I(inode);
	int ret;

	WARN_ON(!cifsi->fscache);

	cifs_dbg(FYI, "%s: (fsc: %p, p: %p, i: %p)\n",
		 __func__, cifsi->fscache, page, inode);
	ret = fscache_write_page(cifsi->fscache, page,
@@ -334,3 +341,21 @@ void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode)
	fscache_wait_on_page_write(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);
}
+23 −0
Original line number Diff line number Diff line
@@ -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_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_reset_inode_cookie(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_readpage_from_fscache(struct inode *, struct page *);
extern int __cifs_readpages_from_fscache(struct inode *,
@@ -76,6 +79,20 @@ static inline void cifs_fscache_invalidate_page(struct page *page,
		__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,
					     struct page *page)
{
@@ -123,6 +140,7 @@ static inline void
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_update_inode_cookie(struct inode *inode) {}
static inline void cifs_fscache_set_inode_cookie(struct inode *inode,
						 struct file *filp) {}
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)

static inline void cifs_fscache_invalidate_page(struct page *page,
			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
cifs_readpage_from_fscache(struct inode *inode, struct page *page)
{
Loading