diff options
author | Maxim Patlasov <mpatlasov@parallels.com> | 2012-10-26 11:48:42 -0400 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2013-01-24 10:21:26 -0500 |
commit | 4d53dc99baf139e4fa0d395f7658032cc2eb3297 (patch) | |
tree | 4709fcfd8631d744abc95195a257b67000e863fa /fs/fuse | |
parent | b111c8c0e3e5e780ae0758fc4c1c376a7c9d5997 (diff) |
fuse: rework fuse_retrieve()
The patch reworks fuse_retrieve() to allocate only so many page pointers
as needed. The core part of the patch is the following calculation:
num_pages = (num + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
(thanks Miklos for formula). All other changes are mostly shuffling lines.
Signed-off-by: Maxim Patlasov <mpatlasov@parallels.com>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs/fuse')
-rw-r--r-- | fs/fuse/dev.c | 25 |
1 files changed, 15 insertions, 10 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index ff5e8bed5d88..28d9792de4a2 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -1577,13 +1577,24 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, | |||
1577 | unsigned int num; | 1577 | unsigned int num; |
1578 | unsigned int offset; | 1578 | unsigned int offset; |
1579 | size_t total_len = 0; | 1579 | size_t total_len = 0; |
1580 | int num_pages; | ||
1580 | 1581 | ||
1581 | req = fuse_get_req(fc, FUSE_MAX_PAGES_PER_REQ); | 1582 | offset = outarg->offset & ~PAGE_CACHE_MASK; |
1583 | file_size = i_size_read(inode); | ||
1584 | |||
1585 | num = outarg->size; | ||
1586 | if (outarg->offset > file_size) | ||
1587 | num = 0; | ||
1588 | else if (outarg->offset + num > file_size) | ||
1589 | num = file_size - outarg->offset; | ||
1590 | |||
1591 | num_pages = (num + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
1592 | num_pages = min(num_pages, FUSE_MAX_PAGES_PER_REQ); | ||
1593 | |||
1594 | req = fuse_get_req(fc, num_pages); | ||
1582 | if (IS_ERR(req)) | 1595 | if (IS_ERR(req)) |
1583 | return PTR_ERR(req); | 1596 | return PTR_ERR(req); |
1584 | 1597 | ||
1585 | offset = outarg->offset & ~PAGE_CACHE_MASK; | ||
1586 | |||
1587 | req->in.h.opcode = FUSE_NOTIFY_REPLY; | 1598 | req->in.h.opcode = FUSE_NOTIFY_REPLY; |
1588 | req->in.h.nodeid = outarg->nodeid; | 1599 | req->in.h.nodeid = outarg->nodeid; |
1589 | req->in.numargs = 2; | 1600 | req->in.numargs = 2; |
@@ -1592,14 +1603,8 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, | |||
1592 | req->end = fuse_retrieve_end; | 1603 | req->end = fuse_retrieve_end; |
1593 | 1604 | ||
1594 | index = outarg->offset >> PAGE_CACHE_SHIFT; | 1605 | index = outarg->offset >> PAGE_CACHE_SHIFT; |
1595 | file_size = i_size_read(inode); | ||
1596 | num = outarg->size; | ||
1597 | if (outarg->offset > file_size) | ||
1598 | num = 0; | ||
1599 | else if (outarg->offset + num > file_size) | ||
1600 | num = file_size - outarg->offset; | ||
1601 | 1606 | ||
1602 | while (num && req->num_pages < FUSE_MAX_PAGES_PER_REQ) { | 1607 | while (num && req->num_pages < num_pages) { |
1603 | struct page *page; | 1608 | struct page *page; |
1604 | unsigned int this_num; | 1609 | unsigned int this_num; |
1605 | 1610 | ||