fuse: rework fuse_retrieve()
authorMaxim Patlasov <mpatlasov@parallels.com>
Fri, 26 Oct 2012 15:48:42 +0000 (19:48 +0400)
committerMiklos Szeredi <mszeredi@suse.cz>
Thu, 24 Jan 2013 15:21:26 +0000 (16:21 +0100)
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>
fs/fuse/dev.c

index ff5e8be..28d9792 100644 (file)
@@ -1577,13 +1577,24 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
        unsigned int num;
        unsigned int offset;
        size_t total_len = 0;
+       int num_pages;
 
-       req = fuse_get_req(fc, FUSE_MAX_PAGES_PER_REQ);
+       offset = outarg->offset & ~PAGE_CACHE_MASK;
+       file_size = i_size_read(inode);
+
+       num = outarg->size;
+       if (outarg->offset > file_size)
+               num = 0;
+       else if (outarg->offset + num > file_size)
+               num = file_size - outarg->offset;
+
+       num_pages = (num + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       num_pages = min(num_pages, FUSE_MAX_PAGES_PER_REQ);
+
+       req = fuse_get_req(fc, num_pages);
        if (IS_ERR(req))
                return PTR_ERR(req);
 
-       offset = outarg->offset & ~PAGE_CACHE_MASK;
-
        req->in.h.opcode = FUSE_NOTIFY_REPLY;
        req->in.h.nodeid = outarg->nodeid;
        req->in.numargs = 2;
@@ -1592,14 +1603,8 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
        req->end = fuse_retrieve_end;
 
        index = outarg->offset >> PAGE_CACHE_SHIFT;
-       file_size = i_size_read(inode);
-       num = outarg->size;
-       if (outarg->offset > file_size)
-               num = 0;
-       else if (outarg->offset + num > file_size)
-               num = file_size - outarg->offset;
 
-       while (num && req->num_pages < FUSE_MAX_PAGES_PER_REQ) {
+       while (num && req->num_pages < num_pages) {
                struct page *page;
                unsigned int this_num;