Base the LAYOUTGET arguments on the actual required byte ranges rather than asking for the whole file layout. Add a check in readpage_async_filler that the layout segment retrieved in pnfs_pageio_init_read still covers the current page and if not, try getting a new one. Signed-off-by: Benny Halevy <bhalevy@xxxxxxxxxxx> --- fs/nfs/file.c | 2 +- fs/nfs/pnfs.c | 13 ++++++------- fs/nfs/pnfs.h | 21 ++++++++------------- fs/nfs/read.c | 17 ++++++++++++++++- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/fs/nfs/file.c b/fs/nfs/file.c index b05c1ff..228f41e 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -390,7 +390,7 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping, pnfs_update_layout(mapping->host, nfs_file_open_context(file), - 0, NFS4_MAX_UINT64, IOMODE_RW, + pos, len, IOMODE_RW, &lseg); start: /* diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index e6261a3..de716f6 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -600,11 +600,10 @@ send_layoutget(struct inode *ino, pnfs_layout_release(lo, NULL); return -ENOMEM; } - lgp->args.minlength = NFS4_MAX_UINT64; + lgp->args.minlength = PAGE_CACHE_SIZE - + (range->offset & (PAGE_CACHE_SIZE-1)); lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE; - lgp->args.range.iomode = range->iomode; - lgp->args.range.offset = 0; - lgp->args.range.length = NFS4_MAX_UINT64; + lgp->args.range = *range; lgp->args.type = server->pnfs_curr_ld->id; lgp->args.inode = ino; lgp->lsegpp = lsegpp; @@ -1028,8 +1027,8 @@ _pnfs_update_layout(struct inode *ino, { struct pnfs_layout_range arg = { .iomode = iomode, - .offset = 0, - .length = NFS4_MAX_UINT64, + .offset = pos, + .length = count, }; struct nfs_inode *nfsi = NFS_I(ino); struct pnfs_layout_hdr *lo; @@ -1330,7 +1329,7 @@ pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, readahead_range(inode, pages, &loff, &count); if (count > 0) { - _pnfs_update_layout(inode, ctx, loff, count, IOMODE_READ, + pnfs_update_layout(inode, ctx, loff, count, IOMODE_READ, &pgio->pg_lseg); if (!pgio->pg_lseg) return; diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 81534aa..b666f53 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -188,19 +188,14 @@ static inline int pnfs_return_layout(struct inode *ino, return 0; } -static inline void pnfs_update_layout(struct inode *ino, - struct nfs_open_context *ctx, - loff_t pos, u64 count, enum pnfs_iomode access_type, - struct pnfs_layout_segment **lsegpp) -{ - struct nfs_server *nfss = NFS_SERVER(ino); - - if (pnfs_enabled_sb(nfss)) - _pnfs_update_layout(ino, ctx, pos, count, access_type, lsegpp); - else { - if (lsegpp) - *lsegpp = NULL; - } +#define pnfs_update_layout(ino, ctx, pos, count, access_type, lsegpp) { \ + if (pnfs_enabled_sb(NFS_SERVER(ino))) { \ + dprintk("%s: updating %s layout pos %llu count %llu\n", __func__, \ + (access_type) == IOMODE_READ ? "READ" : "WRITE", \ + (unsigned long long)(pos), (unsigned long long)(count)); \ + _pnfs_update_layout(ino, ctx, pos, count, access_type, lsegpp); \ + } else \ + *lsegpp = NULL; \ } static inline int pnfs_get_write_status(struct nfs_write_data *data) diff --git a/fs/nfs/read.c b/fs/nfs/read.c index dde7996..36eef5e 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -121,12 +121,14 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, LIST_HEAD(one_request); struct nfs_page *new; unsigned int len; + loff_t pgoffs; struct pnfs_layout_segment *lseg; len = nfs_page_length(page); if (len == 0) return nfs_return_empty_page(page); - pnfs_update_layout(inode, ctx, 0, NFS4_MAX_UINT64, IOMODE_READ, &lseg); + pgoffs = (loff_t)page->index << PAGE_CACHE_SHIFT; + pnfs_update_layout(inode, ctx, pgoffs, len, IOMODE_READ, &lseg); new = nfs_create_request(ctx, inode, page, 0, len, lseg); put_lseg(lseg); if (IS_ERR(new)) { @@ -603,14 +605,27 @@ readpage_async_filler(void *data, struct page *page) { struct nfs_readdesc *desc = (struct nfs_readdesc *)data; struct inode *inode = page->mapping->host; + struct pnfs_layout_range *range; struct nfs_page *new; unsigned int len; + loff_t pgoff; int error; len = nfs_page_length(page); if (len == 0) return nfs_return_empty_page(page); + pgoff = (loff_t)page->index << PAGE_CACHE_SHIFT; + range = desc->pgio->pg_lseg ? &desc->pgio->pg_lseg->range : NULL; + if (!range || + (range->offset > pgoff + len) || + (range->offset + range->length < pgoff)) { + put_lseg(desc->pgio->pg_lseg); + desc->pgio->pg_lseg = NULL; + pnfs_update_layout(inode, desc->ctx, pgoff, len, IOMODE_READ, + &desc->pgio->pg_lseg); + } + new = nfs_create_request(desc->ctx, inode, page, 0, len, desc->pgio->pg_lseg); if (IS_ERR(new)) -- 1.7.2.3 -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html