diff options
author | David Howells <dhowells@redhat.com> | 2017-01-05 11:38:34 +0100 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2017-01-06 17:54:41 +0100 |
commit | 196ee9cd2d04728d0ec0038a2856b86142615b11 (patch) | |
tree | 4fd4e796d4f658787ca7e8dc88f8973622fba028 /fs/afs/file.c | |
parent | tools: psock_tpacket: block Rx until socket filter has been added and socket ... (diff) | |
download | linux-196ee9cd2d04728d0ec0038a2856b86142615b11.tar.xz linux-196ee9cd2d04728d0ec0038a2856b86142615b11.zip |
afs: Make afs_fs_fetch_data() take a list of pages
Make afs_fs_fetch_data() take a list of pages for bulk data transfer. This
will allow afs_readpages() to be made more efficient.
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'fs/afs/file.c')
-rw-r--r-- | fs/afs/file.c | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/fs/afs/file.c b/fs/afs/file.c index 6344aee4ac4b..6c262ceef32d 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -101,6 +101,21 @@ int afs_release(struct inode *inode, struct file *file) return 0; } +/* + * Dispose of a ref to a read record. + */ +void afs_put_read(struct afs_read *req) +{ + int i; + + if (atomic_dec_and_test(&req->usage)) { + for (i = 0; i < req->nr_pages; i++) + if (req->pages[i]) + put_page(req->pages[i]); + kfree(req); + } +} + #ifdef CONFIG_AFS_FSCACHE /* * deal with notification that a page was read from the cache @@ -126,9 +141,8 @@ int afs_page_filler(void *data, struct page *page) { struct inode *inode = page->mapping->host; struct afs_vnode *vnode = AFS_FS_I(inode); + struct afs_read *req; struct key *key = data; - size_t len; - off_t offset; int ret; _enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index); @@ -164,12 +178,23 @@ int afs_page_filler(void *data, struct page *page) _debug("cache said ENOBUFS"); default: go_on: - offset = page->index << PAGE_SHIFT; - len = min_t(size_t, i_size_read(inode) - offset, PAGE_SIZE); + req = kzalloc(sizeof(struct afs_read) + sizeof(struct page *), + GFP_KERNEL); + if (!req) + goto enomem; + + atomic_set(&req->usage, 1); + req->pos = (loff_t)page->index << PAGE_SHIFT; + req->len = min_t(size_t, i_size_read(inode) - req->pos, + PAGE_SIZE); + req->nr_pages = 1; + req->pages[0] = page; + get_page(page); /* read the contents of the file from the server into the * page */ - ret = afs_vnode_fetch_data(vnode, key, offset, len, page); + ret = afs_vnode_fetch_data(vnode, key, req); + afs_put_read(req); if (ret < 0) { if (ret == -ENOENT) { _debug("got NOENT from server" @@ -201,6 +226,8 @@ int afs_page_filler(void *data, struct page *page) _leave(" = 0"); return 0; +enomem: + ret = -ENOMEM; error: SetPageError(page); unlock_page(page); |