NFS: Cleanup for nfs_readpages()
Do the coalescing of read requests into block sized requests at start of I/O as we scan through the pages instead of going through a second pass. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
bcb71bba7e
commit
8b09bee308
|
@ -342,8 +342,8 @@ static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc)
|
||||||
* Returns true if the request 'req' was successfully coalesced into the
|
* Returns true if the request 'req' was successfully coalesced into the
|
||||||
* existing list of pages 'desc'.
|
* existing list of pages 'desc'.
|
||||||
*/
|
*/
|
||||||
static int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
|
int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
|
||||||
struct nfs_page *req)
|
struct nfs_page *req)
|
||||||
{
|
{
|
||||||
while (!nfs_pageio_do_add_request(desc, req)) {
|
while (!nfs_pageio_do_add_request(desc, req)) {
|
||||||
nfs_pageio_doio(desc);
|
nfs_pageio_doio(desc);
|
||||||
|
|
|
@ -321,28 +321,6 @@ out_bad:
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
nfs_pagein_list(struct inode *inode, struct list_head *head, unsigned int rsize)
|
|
||||||
{
|
|
||||||
struct nfs_pageio_descriptor desc;
|
|
||||||
unsigned int pages = 0;
|
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
if (rsize < PAGE_CACHE_SIZE)
|
|
||||||
nfs_pageio_init(&desc, inode, nfs_pagein_multi, rsize, 0);
|
|
||||||
else
|
|
||||||
nfs_pageio_init(&desc, inode, nfs_pagein_one, rsize, 0);
|
|
||||||
|
|
||||||
nfs_pageio_add_list(&desc, head);
|
|
||||||
nfs_pageio_complete(&desc);
|
|
||||||
pages += (desc.pg_bytes_written + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
|
|
||||||
|
|
||||||
nfs_async_read_error(head);
|
|
||||||
if (error >= 0)
|
|
||||||
return pages;
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the callback from RPC telling us whether a reply was
|
* This is the callback from RPC telling us whether a reply was
|
||||||
* received or some error occurred (timeout or socket shutdown).
|
* received or some error occurred (timeout or socket shutdown).
|
||||||
|
@ -532,7 +510,7 @@ out_error:
|
||||||
}
|
}
|
||||||
|
|
||||||
struct nfs_readdesc {
|
struct nfs_readdesc {
|
||||||
struct list_head *head;
|
struct nfs_pageio_descriptor *pgio;
|
||||||
struct nfs_open_context *ctx;
|
struct nfs_open_context *ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -556,19 +534,21 @@ readpage_async_filler(void *data, struct page *page)
|
||||||
}
|
}
|
||||||
if (len < PAGE_CACHE_SIZE)
|
if (len < PAGE_CACHE_SIZE)
|
||||||
memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len);
|
memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len);
|
||||||
nfs_list_add_request(new, desc->head);
|
nfs_pageio_add_request(desc->pgio, new);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nfs_readpages(struct file *filp, struct address_space *mapping,
|
int nfs_readpages(struct file *filp, struct address_space *mapping,
|
||||||
struct list_head *pages, unsigned nr_pages)
|
struct list_head *pages, unsigned nr_pages)
|
||||||
{
|
{
|
||||||
LIST_HEAD(head);
|
struct nfs_pageio_descriptor pgio;
|
||||||
struct nfs_readdesc desc = {
|
struct nfs_readdesc desc = {
|
||||||
.head = &head,
|
.pgio = &pgio,
|
||||||
};
|
};
|
||||||
struct inode *inode = mapping->host;
|
struct inode *inode = mapping->host;
|
||||||
struct nfs_server *server = NFS_SERVER(inode);
|
struct nfs_server *server = NFS_SERVER(inode);
|
||||||
|
size_t rsize = server->rsize;
|
||||||
|
unsigned long npages;
|
||||||
int ret = -ESTALE;
|
int ret = -ESTALE;
|
||||||
|
|
||||||
dprintk("NFS: nfs_readpages (%s/%Ld %d)\n",
|
dprintk("NFS: nfs_readpages (%s/%Ld %d)\n",
|
||||||
|
@ -587,13 +567,16 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
|
||||||
} else
|
} else
|
||||||
desc.ctx = get_nfs_open_context((struct nfs_open_context *)
|
desc.ctx = get_nfs_open_context((struct nfs_open_context *)
|
||||||
filp->private_data);
|
filp->private_data);
|
||||||
|
if (rsize < PAGE_CACHE_SIZE)
|
||||||
|
nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0);
|
||||||
|
else
|
||||||
|
nfs_pageio_init(&pgio, inode, nfs_pagein_one, rsize, 0);
|
||||||
|
|
||||||
ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc);
|
ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc);
|
||||||
if (!list_empty(&head)) {
|
|
||||||
int err = nfs_pagein_list(inode, &head, server->rsize);
|
nfs_pageio_complete(&pgio);
|
||||||
if (!ret)
|
npages = (pgio.pg_bytes_written + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
|
||||||
nfs_add_stats(inode, NFSIOS_READPAGES, err);
|
nfs_add_stats(inode, NFSIOS_READPAGES, npages);
|
||||||
ret = err;
|
|
||||||
}
|
|
||||||
put_nfs_open_context(desc.ctx);
|
put_nfs_open_context(desc.ctx);
|
||||||
out:
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -82,6 +82,8 @@ extern void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
|
||||||
int (*doio)(struct inode *, struct list_head *, size_t, int),
|
int (*doio)(struct inode *, struct list_head *, size_t, int),
|
||||||
size_t bsize,
|
size_t bsize,
|
||||||
int how);
|
int how);
|
||||||
|
extern int nfs_pageio_add_request(struct nfs_pageio_descriptor *,
|
||||||
|
struct nfs_page *);
|
||||||
extern void nfs_pageio_add_list(struct nfs_pageio_descriptor *,
|
extern void nfs_pageio_add_list(struct nfs_pageio_descriptor *,
|
||||||
struct list_head *);
|
struct list_head *);
|
||||||
extern void nfs_pageio_complete(struct nfs_pageio_descriptor *desc);
|
extern void nfs_pageio_complete(struct nfs_pageio_descriptor *desc);
|
||||||
|
|
Loading…
Reference in a new issue