mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 04:00:52 +07:00
NFS: Read pages from FS-Cache into an NFS inode
Read pages from an FS-Cache data storage object representing an inode into an NFS inode. Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Steve Dickson <steved@redhat.com> Acked-by: Trond Myklebust <Trond.Myklebust@netapp.com> Acked-by: Al Viro <viro@zeniv.linux.org.uk> Tested-by: Daire Byrne <Daire.Byrne@framestore.com>
This commit is contained in:
parent
f42b293d6d
commit
9a9fc1c033
112
fs/nfs/fscache.c
112
fs/nfs/fscache.c
@ -381,3 +381,115 @@ void __nfs_fscache_invalidate_page(struct page *page, struct inode *inode)
|
||||
nfs_add_fscache_stats(page->mapping->host,
|
||||
NFSIOS_FSCACHE_PAGES_UNCACHED, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle completion of a page being read from the cache.
|
||||
* - Called in process (keventd) context.
|
||||
*/
|
||||
static void nfs_readpage_from_fscache_complete(struct page *page,
|
||||
void *context,
|
||||
int error)
|
||||
{
|
||||
dfprintk(FSCACHE,
|
||||
"NFS: readpage_from_fscache_complete (0x%p/0x%p/%d)\n",
|
||||
page, context, error);
|
||||
|
||||
/* if the read completes with an error, we just unlock the page and let
|
||||
* the VM reissue the readpage */
|
||||
if (!error) {
|
||||
SetPageUptodate(page);
|
||||
unlock_page(page);
|
||||
} else {
|
||||
error = nfs_readpage_async(context, page->mapping->host, page);
|
||||
if (error)
|
||||
unlock_page(page);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve a page from fscache
|
||||
*/
|
||||
int __nfs_readpage_from_fscache(struct nfs_open_context *ctx,
|
||||
struct inode *inode, struct page *page)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dfprintk(FSCACHE,
|
||||
"NFS: readpage_from_fscache(fsc:%p/p:%p(i:%lx f:%lx)/0x%p)\n",
|
||||
NFS_I(inode)->fscache, page, page->index, page->flags, inode);
|
||||
|
||||
ret = fscache_read_or_alloc_page(NFS_I(inode)->fscache,
|
||||
page,
|
||||
nfs_readpage_from_fscache_complete,
|
||||
ctx,
|
||||
GFP_KERNEL);
|
||||
|
||||
switch (ret) {
|
||||
case 0: /* read BIO submitted (page in fscache) */
|
||||
dfprintk(FSCACHE,
|
||||
"NFS: readpage_from_fscache: BIO submitted\n");
|
||||
nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_OK, 1);
|
||||
return ret;
|
||||
|
||||
case -ENOBUFS: /* inode not in cache */
|
||||
case -ENODATA: /* page not in cache */
|
||||
nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_FAIL, 1);
|
||||
dfprintk(FSCACHE,
|
||||
"NFS: readpage_from_fscache %d\n", ret);
|
||||
return 1;
|
||||
|
||||
default:
|
||||
dfprintk(FSCACHE, "NFS: readpage_from_fscache %d\n", ret);
|
||||
nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_FAIL, 1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve a set of pages from fscache
|
||||
*/
|
||||
int __nfs_readpages_from_fscache(struct nfs_open_context *ctx,
|
||||
struct inode *inode,
|
||||
struct address_space *mapping,
|
||||
struct list_head *pages,
|
||||
unsigned *nr_pages)
|
||||
{
|
||||
int ret, npages = *nr_pages;
|
||||
|
||||
dfprintk(FSCACHE, "NFS: nfs_getpages_from_fscache (0x%p/%u/0x%p)\n",
|
||||
NFS_I(inode)->fscache, npages, inode);
|
||||
|
||||
ret = fscache_read_or_alloc_pages(NFS_I(inode)->fscache,
|
||||
mapping, pages, nr_pages,
|
||||
nfs_readpage_from_fscache_complete,
|
||||
ctx,
|
||||
mapping_gfp_mask(mapping));
|
||||
if (*nr_pages < npages)
|
||||
nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_OK,
|
||||
npages);
|
||||
if (*nr_pages > 0)
|
||||
nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_FAIL,
|
||||
*nr_pages);
|
||||
|
||||
switch (ret) {
|
||||
case 0: /* read submitted to the cache for all pages */
|
||||
BUG_ON(!list_empty(pages));
|
||||
BUG_ON(*nr_pages != 0);
|
||||
dfprintk(FSCACHE,
|
||||
"NFS: nfs_getpages_from_fscache: submitted\n");
|
||||
|
||||
return ret;
|
||||
|
||||
case -ENOBUFS: /* some pages aren't cached and can't be */
|
||||
case -ENODATA: /* some pages aren't cached */
|
||||
dfprintk(FSCACHE,
|
||||
"NFS: nfs_getpages_from_fscache: no page: %d\n", ret);
|
||||
return 1;
|
||||
|
||||
default:
|
||||
dfprintk(FSCACHE,
|
||||
"NFS: nfs_getpages_from_fscache: ret %d\n", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -86,6 +86,12 @@ extern void nfs_fscache_reset_inode_cookie(struct inode *);
|
||||
extern void __nfs_fscache_invalidate_page(struct page *, struct inode *);
|
||||
extern int nfs_fscache_release_page(struct page *, gfp_t);
|
||||
|
||||
extern int __nfs_readpage_from_fscache(struct nfs_open_context *,
|
||||
struct inode *, struct page *);
|
||||
extern int __nfs_readpages_from_fscache(struct nfs_open_context *,
|
||||
struct inode *, struct address_space *,
|
||||
struct list_head *, unsigned *);
|
||||
|
||||
/*
|
||||
* wait for a page to complete writing to the cache
|
||||
*/
|
||||
@ -107,6 +113,32 @@ static inline void nfs_fscache_invalidate_page(struct page *page,
|
||||
__nfs_fscache_invalidate_page(page, inode);
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve a page from an inode data storage object.
|
||||
*/
|
||||
static inline int nfs_readpage_from_fscache(struct nfs_open_context *ctx,
|
||||
struct inode *inode,
|
||||
struct page *page)
|
||||
{
|
||||
if (NFS_I(inode)->fscache)
|
||||
return __nfs_readpage_from_fscache(ctx, inode, page);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve a set of pages from an inode data storage object.
|
||||
*/
|
||||
static inline int nfs_readpages_from_fscache(struct nfs_open_context *ctx,
|
||||
struct inode *inode,
|
||||
struct address_space *mapping,
|
||||
struct list_head *pages,
|
||||
unsigned *nr_pages)
|
||||
{
|
||||
if (NFS_I(inode)->fscache)
|
||||
return __nfs_readpages_from_fscache(ctx, inode, mapping, pages,
|
||||
nr_pages);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
#else /* CONFIG_NFS_FSCACHE */
|
||||
static inline int nfs_fscache_register(void) { return 0; }
|
||||
@ -138,5 +170,20 @@ static inline void nfs_fscache_invalidate_page(struct page *page,
|
||||
static inline void nfs_fscache_wait_on_page_write(struct nfs_inode *nfsi,
|
||||
struct page *page) {}
|
||||
|
||||
static inline int nfs_readpage_from_fscache(struct nfs_open_context *ctx,
|
||||
struct inode *inode,
|
||||
struct page *page)
|
||||
{
|
||||
return -ENOBUFS;
|
||||
}
|
||||
static inline int nfs_readpages_from_fscache(struct nfs_open_context *ctx,
|
||||
struct inode *inode,
|
||||
struct address_space *mapping,
|
||||
struct list_head *pages,
|
||||
unsigned *nr_pages)
|
||||
{
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NFS_FSCACHE */
|
||||
#endif /* _NFS_FSCACHE_H */
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "internal.h"
|
||||
#include "iostat.h"
|
||||
#include "fscache.h"
|
||||
|
||||
#define NFSDBG_FACILITY NFSDBG_PAGECACHE
|
||||
|
||||
@ -510,8 +511,15 @@ int nfs_readpage(struct file *file, struct page *page)
|
||||
} else
|
||||
ctx = get_nfs_open_context(nfs_file_open_context(file));
|
||||
|
||||
if (!IS_SYNC(inode)) {
|
||||
error = nfs_readpage_from_fscache(ctx, inode, page);
|
||||
if (error == 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = nfs_readpage_async(ctx, inode, page);
|
||||
|
||||
out:
|
||||
put_nfs_open_context(ctx);
|
||||
return error;
|
||||
out_unlock:
|
||||
@ -584,6 +592,15 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
|
||||
return -EBADF;
|
||||
} else
|
||||
desc.ctx = get_nfs_open_context(nfs_file_open_context(filp));
|
||||
|
||||
/* attempt to read as many of the pages as possible from the cache
|
||||
* - this returns -ENOBUFS immediately if the cookie is negative
|
||||
*/
|
||||
ret = nfs_readpages_from_fscache(desc.ctx, inode, mapping,
|
||||
pages, &nr_pages);
|
||||
if (ret == 0)
|
||||
goto read_complete; /* all pages were read */
|
||||
|
||||
if (rsize < PAGE_CACHE_SIZE)
|
||||
nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0);
|
||||
else
|
||||
@ -594,6 +611,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
|
||||
nfs_pageio_complete(&pgio);
|
||||
npages = (pgio.pg_bytes_written + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
|
||||
nfs_add_stats(inode, NFSIOS_READPAGES, npages);
|
||||
read_complete:
|
||||
put_nfs_open_context(desc.ctx);
|
||||
out:
|
||||
return ret;
|
||||
|
Loading…
Reference in New Issue
Block a user