RxRPC rewrite
-----BEGIN PGP SIGNATURE----- iQIVAwUAWG/Ny/Sw1s6N8H32AQIsiw//TbSOwj8w6PqDpN74dNNAjAG7MvzZ+wIf cYOkNcWUuEbdypUnJxjyYz6yO7q37M+NPI0AAhVECjyb/Zuy9HMa2h/hLmlMEi4Z jfUCUTFbwr+8Z3Rii2P4JWL/fJoGkC9U/nqsL97P6JMXnuX0VIo+6I6VQQymO4GO LgWCo9Vif5eRcmc8PpgQB/DabVqAQUuTRYxu3ffFv6jIHg/Qa3W8l0dfwdalmJbR XaZbaxA6cdXBv5zYhiId1udql/naJ0o+djKy9Bq9k/RfYLw9DIj6+EWz0CscyKck u/ises8Ft0d50zMztNmk9GpJOKeGBJWOypFO3Pq01VT8fZuBzbreXEh7amLswvGg 5Yhgf5M23+QAxWbp34uMG1a6K4mkCBpOw+4BPGGQ1lyf/kGXB1OZP+1d4FjJptVO MQA0ONzqApI8iJuKbtLWJ/UymxxLcDeOGLyruYKXCf+NdSSQowFWlibdF1UEAGP4 RzOeqzzP8ezkR/PQKZLUxgMKiS0JgHglU6y0vdqC+jpC7ekMtmwllwOowj/ZYdZu nsSNh4cXwXub4y4/XSbMSxirxn7c29F0XRHAzWr/LchzZI6rB2WBhwhMEQ++YIEY RzOCY3YhxyPxhd3Dq3bjKMXHGVUzORXP/aPJMqs4d93CYCnedW9zln07UjonxLBI VEMNcSmnIX0= =Bpfo -----END PGP SIGNATURE----- Merge tag 'rxrpc-rewrite-20170106' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs David Howells says: ==================== afs: Implement bulk read This pair of patches implements bulk data reading from an AFS server. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
1c966c5d26
168
fs/afs/file.c
168
fs/afs/file.c
@ -16,6 +16,7 @@
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/task_io_accounting_ops.h>
|
||||
#include "internal.h"
|
||||
|
||||
static int afs_readpage(struct file *file, struct page *page);
|
||||
@ -101,6 +102,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 +142,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 +179,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 +227,8 @@ int afs_page_filler(void *data, struct page *page)
|
||||
_leave(" = 0");
|
||||
return 0;
|
||||
|
||||
enomem:
|
||||
ret = -ENOMEM;
|
||||
error:
|
||||
SetPageError(page);
|
||||
unlock_page(page);
|
||||
@ -234,6 +262,129 @@ static int afs_readpage(struct file *file, struct page *page)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make pages available as they're filled.
|
||||
*/
|
||||
static void afs_readpages_page_done(struct afs_call *call, struct afs_read *req)
|
||||
{
|
||||
struct afs_vnode *vnode = call->reply;
|
||||
struct page *page = req->pages[req->index];
|
||||
|
||||
req->pages[req->index] = NULL;
|
||||
SetPageUptodate(page);
|
||||
|
||||
/* send the page to the cache */
|
||||
#ifdef CONFIG_AFS_FSCACHE
|
||||
if (PageFsCache(page) &&
|
||||
fscache_write_page(vnode->cache, page, GFP_KERNEL) != 0) {
|
||||
fscache_uncache_page(vnode->cache, page);
|
||||
BUG_ON(PageFsCache(page));
|
||||
}
|
||||
#endif
|
||||
unlock_page(page);
|
||||
put_page(page);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a contiguous set of pages.
|
||||
*/
|
||||
static int afs_readpages_one(struct file *file, struct address_space *mapping,
|
||||
struct list_head *pages)
|
||||
{
|
||||
struct afs_vnode *vnode = AFS_FS_I(mapping->host);
|
||||
struct afs_read *req;
|
||||
struct list_head *p;
|
||||
struct page *first, *page;
|
||||
struct key *key = file->private_data;
|
||||
pgoff_t index;
|
||||
int ret, n, i;
|
||||
|
||||
/* Count the number of contiguous pages at the front of the list. Note
|
||||
* that the list goes prev-wards rather than next-wards.
|
||||
*/
|
||||
first = list_entry(pages->prev, struct page, lru);
|
||||
index = first->index + 1;
|
||||
n = 1;
|
||||
for (p = first->lru.prev; p != pages; p = p->prev) {
|
||||
page = list_entry(p, struct page, lru);
|
||||
if (page->index != index)
|
||||
break;
|
||||
index++;
|
||||
n++;
|
||||
}
|
||||
|
||||
req = kzalloc(sizeof(struct afs_read) + sizeof(struct page *) * n,
|
||||
GFP_NOFS);
|
||||
if (!req)
|
||||
return -ENOMEM;
|
||||
|
||||
atomic_set(&req->usage, 1);
|
||||
req->page_done = afs_readpages_page_done;
|
||||
req->pos = first->index;
|
||||
req->pos <<= PAGE_SHIFT;
|
||||
|
||||
/* Transfer the pages to the request. We add them in until one fails
|
||||
* to add to the LRU and then we stop (as that'll make a hole in the
|
||||
* contiguous run.
|
||||
*
|
||||
* Note that it's possible for the file size to change whilst we're
|
||||
* doing this, but we rely on the server returning less than we asked
|
||||
* for if the file shrank. We also rely on this to deal with a partial
|
||||
* page at the end of the file.
|
||||
*/
|
||||
do {
|
||||
page = list_entry(pages->prev, struct page, lru);
|
||||
list_del(&page->lru);
|
||||
index = page->index;
|
||||
if (add_to_page_cache_lru(page, mapping, index,
|
||||
readahead_gfp_mask(mapping))) {
|
||||
#ifdef CONFIG_AFS_FSCACHE
|
||||
fscache_uncache_page(vnode->cache, page);
|
||||
#endif
|
||||
put_page(page);
|
||||
break;
|
||||
}
|
||||
|
||||
req->pages[req->nr_pages++] = page;
|
||||
req->len += PAGE_SIZE;
|
||||
} while (req->nr_pages < n);
|
||||
|
||||
if (req->nr_pages == 0) {
|
||||
kfree(req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = afs_vnode_fetch_data(vnode, key, req);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
task_io_account_read(PAGE_SIZE * req->nr_pages);
|
||||
afs_put_read(req);
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (ret == -ENOENT) {
|
||||
_debug("got NOENT from server"
|
||||
" - marking file deleted and stale");
|
||||
set_bit(AFS_VNODE_DELETED, &vnode->flags);
|
||||
ret = -ESTALE;
|
||||
}
|
||||
|
||||
for (i = 0; i < req->nr_pages; i++) {
|
||||
page = req->pages[i];
|
||||
if (page) {
|
||||
#ifdef CONFIG_AFS_FSCACHE
|
||||
fscache_uncache_page(vnode->cache, page);
|
||||
#endif
|
||||
SetPageError(page);
|
||||
unlock_page(page);
|
||||
}
|
||||
}
|
||||
|
||||
afs_put_read(req);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* read a set of pages
|
||||
*/
|
||||
@ -287,8 +438,11 @@ static int afs_readpages(struct file *file, struct address_space *mapping,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* load the missing pages from the network */
|
||||
ret = read_cache_pages(mapping, pages, afs_page_filler, key);
|
||||
while (!list_empty(pages)) {
|
||||
ret = afs_readpages_one(file, mapping, pages);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
_leave(" = %d [netting]", ret);
|
||||
return ret;
|
||||
|
@ -309,15 +309,19 @@ int afs_fs_fetch_file_status(struct afs_server *server,
|
||||
static int afs_deliver_fs_fetch_data(struct afs_call *call)
|
||||
{
|
||||
struct afs_vnode *vnode = call->reply;
|
||||
struct afs_read *req = call->reply3;
|
||||
const __be32 *bp;
|
||||
struct page *page;
|
||||
unsigned int size;
|
||||
void *buffer;
|
||||
int ret;
|
||||
|
||||
_enter("{%u}", call->unmarshall);
|
||||
_enter("{%u,%zu/%u;%u/%llu}",
|
||||
call->unmarshall, call->offset, call->count,
|
||||
req->remain, req->actual_len);
|
||||
|
||||
switch (call->unmarshall) {
|
||||
case 0:
|
||||
req->actual_len = 0;
|
||||
call->offset = 0;
|
||||
call->unmarshall++;
|
||||
if (call->operation_ID != FSFETCHDATA64) {
|
||||
@ -334,10 +338,8 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
call->count = ntohl(call->tmp);
|
||||
_debug("DATA length MSW: %u", call->count);
|
||||
if (call->count > 0)
|
||||
return -EBADMSG;
|
||||
req->actual_len = ntohl(call->tmp);
|
||||
req->actual_len <<= 32;
|
||||
call->offset = 0;
|
||||
call->unmarshall++;
|
||||
|
||||
@ -349,26 +351,52 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
call->count = ntohl(call->tmp);
|
||||
_debug("DATA length: %u", call->count);
|
||||
if (call->count > PAGE_SIZE)
|
||||
req->actual_len |= ntohl(call->tmp);
|
||||
_debug("DATA length: %llu", req->actual_len);
|
||||
/* Check that the server didn't want to send us extra. We
|
||||
* might want to just discard instead, but that requires
|
||||
* cooperation from AF_RXRPC.
|
||||
*/
|
||||
if (req->actual_len > req->len)
|
||||
return -EBADMSG;
|
||||
call->offset = 0;
|
||||
|
||||
req->remain = req->actual_len;
|
||||
call->offset = req->pos & (PAGE_SIZE - 1);
|
||||
req->index = 0;
|
||||
if (req->actual_len == 0)
|
||||
goto no_more_data;
|
||||
call->unmarshall++;
|
||||
|
||||
begin_page:
|
||||
if (req->remain > PAGE_SIZE - call->offset)
|
||||
size = PAGE_SIZE - call->offset;
|
||||
else
|
||||
size = req->remain;
|
||||
call->count = call->offset + size;
|
||||
ASSERTCMP(call->count, <=, PAGE_SIZE);
|
||||
req->remain -= size;
|
||||
|
||||
/* extract the returned data */
|
||||
case 3:
|
||||
_debug("extract data");
|
||||
if (call->count > 0) {
|
||||
page = call->reply3;
|
||||
buffer = kmap(page);
|
||||
ret = afs_extract_data(call, buffer,
|
||||
call->count, true);
|
||||
kunmap(page);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
_debug("extract data %u/%llu %zu/%u",
|
||||
req->remain, req->actual_len, call->offset, call->count);
|
||||
|
||||
buffer = kmap(req->pages[req->index]);
|
||||
ret = afs_extract_data(call, buffer, call->count, true);
|
||||
kunmap(req->pages[req->index]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (call->offset == PAGE_SIZE) {
|
||||
if (req->page_done)
|
||||
req->page_done(call, req);
|
||||
if (req->remain > 0) {
|
||||
req->index++;
|
||||
call->offset = 0;
|
||||
goto begin_page;
|
||||
}
|
||||
}
|
||||
|
||||
no_more_data:
|
||||
call->offset = 0;
|
||||
call->unmarshall++;
|
||||
|
||||
@ -393,17 +421,25 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
|
||||
}
|
||||
|
||||
if (call->count < PAGE_SIZE) {
|
||||
_debug("clear");
|
||||
page = call->reply3;
|
||||
buffer = kmap(page);
|
||||
buffer = kmap(req->pages[req->index]);
|
||||
memset(buffer + call->count, 0, PAGE_SIZE - call->count);
|
||||
kunmap(page);
|
||||
kunmap(req->pages[req->index]);
|
||||
if (req->page_done)
|
||||
req->page_done(call, req);
|
||||
}
|
||||
|
||||
_leave(" = 0 [done]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void afs_fetch_data_destructor(struct afs_call *call)
|
||||
{
|
||||
struct afs_read *req = call->reply3;
|
||||
|
||||
afs_put_read(req);
|
||||
afs_flat_call_destructor(call);
|
||||
}
|
||||
|
||||
/*
|
||||
* FS.FetchData operation type
|
||||
*/
|
||||
@ -411,14 +447,14 @@ static const struct afs_call_type afs_RXFSFetchData = {
|
||||
.name = "FS.FetchData",
|
||||
.deliver = afs_deliver_fs_fetch_data,
|
||||
.abort_to_error = afs_abort_to_error,
|
||||
.destructor = afs_flat_call_destructor,
|
||||
.destructor = afs_fetch_data_destructor,
|
||||
};
|
||||
|
||||
static const struct afs_call_type afs_RXFSFetchData64 = {
|
||||
.name = "FS.FetchData64",
|
||||
.deliver = afs_deliver_fs_fetch_data,
|
||||
.abort_to_error = afs_abort_to_error,
|
||||
.destructor = afs_flat_call_destructor,
|
||||
.destructor = afs_fetch_data_destructor,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -427,8 +463,7 @@ static const struct afs_call_type afs_RXFSFetchData64 = {
|
||||
static int afs_fs_fetch_data64(struct afs_server *server,
|
||||
struct key *key,
|
||||
struct afs_vnode *vnode,
|
||||
off_t offset, size_t length,
|
||||
struct page *buffer,
|
||||
struct afs_read *req,
|
||||
const struct afs_wait_mode *wait_mode)
|
||||
{
|
||||
struct afs_call *call;
|
||||
@ -436,8 +471,6 @@ static int afs_fs_fetch_data64(struct afs_server *server,
|
||||
|
||||
_enter("");
|
||||
|
||||
ASSERTCMP(length, <, ULONG_MAX);
|
||||
|
||||
call = afs_alloc_flat_call(&afs_RXFSFetchData64, 32, (21 + 3 + 6) * 4);
|
||||
if (!call)
|
||||
return -ENOMEM;
|
||||
@ -445,7 +478,7 @@ static int afs_fs_fetch_data64(struct afs_server *server,
|
||||
call->key = key;
|
||||
call->reply = vnode;
|
||||
call->reply2 = NULL; /* volsync */
|
||||
call->reply3 = buffer;
|
||||
call->reply3 = req;
|
||||
call->service_id = FS_SERVICE;
|
||||
call->port = htons(AFS_FS_PORT);
|
||||
call->operation_ID = FSFETCHDATA64;
|
||||
@ -456,11 +489,12 @@ static int afs_fs_fetch_data64(struct afs_server *server,
|
||||
bp[1] = htonl(vnode->fid.vid);
|
||||
bp[2] = htonl(vnode->fid.vnode);
|
||||
bp[3] = htonl(vnode->fid.unique);
|
||||
bp[4] = htonl(upper_32_bits(offset));
|
||||
bp[5] = htonl((u32) offset);
|
||||
bp[4] = htonl(upper_32_bits(req->pos));
|
||||
bp[5] = htonl(lower_32_bits(req->pos));
|
||||
bp[6] = 0;
|
||||
bp[7] = htonl((u32) length);
|
||||
bp[7] = htonl(lower_32_bits(req->len));
|
||||
|
||||
atomic_inc(&req->usage);
|
||||
return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
|
||||
}
|
||||
|
||||
@ -470,16 +504,16 @@ static int afs_fs_fetch_data64(struct afs_server *server,
|
||||
int afs_fs_fetch_data(struct afs_server *server,
|
||||
struct key *key,
|
||||
struct afs_vnode *vnode,
|
||||
off_t offset, size_t length,
|
||||
struct page *buffer,
|
||||
struct afs_read *req,
|
||||
const struct afs_wait_mode *wait_mode)
|
||||
{
|
||||
struct afs_call *call;
|
||||
__be32 *bp;
|
||||
|
||||
if (upper_32_bits(offset) || upper_32_bits(offset + length))
|
||||
return afs_fs_fetch_data64(server, key, vnode, offset, length,
|
||||
buffer, wait_mode);
|
||||
if (upper_32_bits(req->pos) ||
|
||||
upper_32_bits(req->len) ||
|
||||
upper_32_bits(req->pos + req->len))
|
||||
return afs_fs_fetch_data64(server, key, vnode, req, wait_mode);
|
||||
|
||||
_enter("");
|
||||
|
||||
@ -490,7 +524,7 @@ int afs_fs_fetch_data(struct afs_server *server,
|
||||
call->key = key;
|
||||
call->reply = vnode;
|
||||
call->reply2 = NULL; /* volsync */
|
||||
call->reply3 = buffer;
|
||||
call->reply3 = req;
|
||||
call->service_id = FS_SERVICE;
|
||||
call->port = htons(AFS_FS_PORT);
|
||||
call->operation_ID = FSFETCHDATA;
|
||||
@ -501,9 +535,10 @@ int afs_fs_fetch_data(struct afs_server *server,
|
||||
bp[1] = htonl(vnode->fid.vid);
|
||||
bp[2] = htonl(vnode->fid.vnode);
|
||||
bp[3] = htonl(vnode->fid.unique);
|
||||
bp[4] = htonl(offset);
|
||||
bp[5] = htonl(length);
|
||||
bp[4] = htonl(lower_32_bits(req->pos));
|
||||
bp[5] = htonl(lower_32_bits(req->len));
|
||||
|
||||
atomic_inc(&req->usage);
|
||||
return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode);
|
||||
}
|
||||
|
||||
|
@ -133,6 +133,22 @@ struct afs_call_type {
|
||||
void (*destructor)(struct afs_call *call);
|
||||
};
|
||||
|
||||
/*
|
||||
* Record of an outstanding read operation on a vnode.
|
||||
*/
|
||||
struct afs_read {
|
||||
loff_t pos; /* Where to start reading */
|
||||
loff_t len; /* How much to read */
|
||||
loff_t actual_len; /* How much we're actually getting */
|
||||
atomic_t usage;
|
||||
unsigned int remain; /* Amount remaining */
|
||||
unsigned int index; /* Which page we're reading into */
|
||||
unsigned int pg_offset; /* Offset in page we're at */
|
||||
unsigned int nr_pages;
|
||||
void (*page_done)(struct afs_call *, struct afs_read *);
|
||||
struct page *pages[];
|
||||
};
|
||||
|
||||
/*
|
||||
* record of an outstanding writeback on a vnode
|
||||
*/
|
||||
@ -494,6 +510,7 @@ extern const struct file_operations afs_file_operations;
|
||||
extern int afs_open(struct inode *, struct file *);
|
||||
extern int afs_release(struct inode *, struct file *);
|
||||
extern int afs_page_filler(void *, struct page *);
|
||||
extern void afs_put_read(struct afs_read *);
|
||||
|
||||
/*
|
||||
* flock.c
|
||||
@ -513,7 +530,7 @@ extern int afs_fs_fetch_file_status(struct afs_server *, struct key *,
|
||||
extern int afs_fs_give_up_callbacks(struct afs_server *,
|
||||
const struct afs_wait_mode *);
|
||||
extern int afs_fs_fetch_data(struct afs_server *, struct key *,
|
||||
struct afs_vnode *, off_t, size_t, struct page *,
|
||||
struct afs_vnode *, struct afs_read *,
|
||||
const struct afs_wait_mode *);
|
||||
extern int afs_fs_create(struct afs_server *, struct key *,
|
||||
struct afs_vnode *, const char *, umode_t,
|
||||
@ -699,7 +716,7 @@ extern void afs_vnode_finalise_status_update(struct afs_vnode *,
|
||||
extern int afs_vnode_fetch_status(struct afs_vnode *, struct afs_vnode *,
|
||||
struct key *);
|
||||
extern int afs_vnode_fetch_data(struct afs_vnode *, struct key *,
|
||||
off_t, size_t, struct page *);
|
||||
struct afs_read *);
|
||||
extern int afs_vnode_create(struct afs_vnode *, struct key *, const char *,
|
||||
umode_t, struct afs_fid *, struct afs_file_status *,
|
||||
struct afs_callback *, struct afs_server **);
|
||||
|
@ -393,7 +393,7 @@ no_server:
|
||||
* - TODO implement caching
|
||||
*/
|
||||
int afs_vnode_fetch_data(struct afs_vnode *vnode, struct key *key,
|
||||
off_t offset, size_t length, struct page *page)
|
||||
struct afs_read *desc)
|
||||
{
|
||||
struct afs_server *server;
|
||||
int ret;
|
||||
@ -420,8 +420,8 @@ int afs_vnode_fetch_data(struct afs_vnode *vnode, struct key *key,
|
||||
|
||||
_debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
|
||||
|
||||
ret = afs_fs_fetch_data(server, key, vnode, offset, length,
|
||||
page, &afs_sync_call);
|
||||
ret = afs_fs_fetch_data(server, key, vnode, desc,
|
||||
&afs_sync_call);
|
||||
|
||||
} while (!afs_volume_release_fileserver(vnode, server, ret));
|
||||
|
||||
|
@ -106,6 +106,7 @@ struct afs_volume *afs_volume_lookup(struct afs_mount_params *params)
|
||||
volume->cell = params->cell;
|
||||
volume->vid = vlocation->vldb.vid[params->type];
|
||||
|
||||
volume->bdi.ra_pages = VM_MAX_READAHEAD*1024/PAGE_SIZE;
|
||||
ret = bdi_setup_and_register(&volume->bdi, "afs");
|
||||
if (ret)
|
||||
goto error_bdi;
|
||||
|
@ -86,19 +86,30 @@ void afs_put_writeback(struct afs_writeback *wb)
|
||||
static int afs_fill_page(struct afs_vnode *vnode, struct key *key,
|
||||
loff_t pos, struct page *page)
|
||||
{
|
||||
struct afs_read *req;
|
||||
loff_t i_size;
|
||||
int ret;
|
||||
int len;
|
||||
|
||||
_enter(",,%llu", (unsigned long long)pos);
|
||||
|
||||
req = kzalloc(sizeof(struct afs_read) + sizeof(struct page *),
|
||||
GFP_KERNEL);
|
||||
if (!req)
|
||||
return -ENOMEM;
|
||||
|
||||
atomic_set(&req->usage, 1);
|
||||
req->pos = pos;
|
||||
req->nr_pages = 1;
|
||||
req->pages[0] = page;
|
||||
|
||||
i_size = i_size_read(&vnode->vfs_inode);
|
||||
if (pos + PAGE_SIZE > i_size)
|
||||
len = i_size - pos;
|
||||
req->len = i_size - pos;
|
||||
else
|
||||
len = PAGE_SIZE;
|
||||
req->len = PAGE_SIZE;
|
||||
|
||||
ret = afs_vnode_fetch_data(vnode, key, pos, 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"
|
||||
|
Loading…
Reference in New Issue
Block a user