diff options
author | Miklos Szeredi <miklos@szeredi.hu> | 2005-09-09 16:10:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-09 17:03:46 -0400 |
commit | db50b96c0f28a21c5a4a19ecaba12d0972aab06a (patch) | |
tree | d7f2cb99de499c116ce08153a369044af0622c16 /fs/fuse/file.c | |
parent | 06663267b4b1e85ece73236ea720355668d4f736 (diff) |
[PATCH] FUSE - readpages operation
This patch adds readpages support to FUSE.
With the help of the readpages() operation multiple reads are bundled
together and sent as a single request to userspace. This can improve
reading performace.
Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/fuse/file.c')
-rw-r--r-- | fs/fuse/file.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 96ea302db184..86ffb6db5fe7 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -227,6 +227,72 @@ static int fuse_readpage(struct file *file, struct page *page) | |||
227 | return err; | 227 | return err; |
228 | } | 228 | } |
229 | 229 | ||
230 | static int fuse_send_readpages(struct fuse_req *req, struct file *file, | ||
231 | struct inode *inode) | ||
232 | { | ||
233 | loff_t pos = (loff_t) req->pages[0]->index << PAGE_CACHE_SHIFT; | ||
234 | size_t count = req->num_pages << PAGE_CACHE_SHIFT; | ||
235 | unsigned i; | ||
236 | req->out.page_zeroing = 1; | ||
237 | fuse_send_read(req, file, inode, pos, count); | ||
238 | for (i = 0; i < req->num_pages; i++) { | ||
239 | struct page *page = req->pages[i]; | ||
240 | if (!req->out.h.error) | ||
241 | SetPageUptodate(page); | ||
242 | unlock_page(page); | ||
243 | } | ||
244 | return req->out.h.error; | ||
245 | } | ||
246 | |||
247 | struct fuse_readpages_data { | ||
248 | struct fuse_req *req; | ||
249 | struct file *file; | ||
250 | struct inode *inode; | ||
251 | }; | ||
252 | |||
253 | static int fuse_readpages_fill(void *_data, struct page *page) | ||
254 | { | ||
255 | struct fuse_readpages_data *data = _data; | ||
256 | struct fuse_req *req = data->req; | ||
257 | struct inode *inode = data->inode; | ||
258 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
259 | |||
260 | if (req->num_pages && | ||
261 | (req->num_pages == FUSE_MAX_PAGES_PER_REQ || | ||
262 | (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || | ||
263 | req->pages[req->num_pages - 1]->index + 1 != page->index)) { | ||
264 | int err = fuse_send_readpages(req, data->file, inode); | ||
265 | if (err) { | ||
266 | unlock_page(page); | ||
267 | return err; | ||
268 | } | ||
269 | fuse_reset_request(req); | ||
270 | } | ||
271 | req->pages[req->num_pages] = page; | ||
272 | req->num_pages ++; | ||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static int fuse_readpages(struct file *file, struct address_space *mapping, | ||
277 | struct list_head *pages, unsigned nr_pages) | ||
278 | { | ||
279 | struct inode *inode = mapping->host; | ||
280 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
281 | struct fuse_readpages_data data; | ||
282 | int err; | ||
283 | data.file = file; | ||
284 | data.inode = inode; | ||
285 | data.req = fuse_get_request_nonint(fc); | ||
286 | if (!data.req) | ||
287 | return -EINTR; | ||
288 | |||
289 | err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); | ||
290 | if (!err && data.req->num_pages) | ||
291 | err = fuse_send_readpages(data.req, file, inode); | ||
292 | fuse_put_request(fc, data.req); | ||
293 | return err; | ||
294 | } | ||
295 | |||
230 | static ssize_t fuse_send_write(struct fuse_req *req, struct file *file, | 296 | static ssize_t fuse_send_write(struct fuse_req *req, struct file *file, |
231 | struct inode *inode, loff_t pos, size_t count) | 297 | struct inode *inode, loff_t pos, size_t count) |
232 | { | 298 | { |
@@ -331,6 +397,7 @@ static struct address_space_operations fuse_file_aops = { | |||
331 | .readpage = fuse_readpage, | 397 | .readpage = fuse_readpage, |
332 | .prepare_write = fuse_prepare_write, | 398 | .prepare_write = fuse_prepare_write, |
333 | .commit_write = fuse_commit_write, | 399 | .commit_write = fuse_commit_write, |
400 | .readpages = fuse_readpages, | ||
334 | .set_page_dirty = fuse_set_page_dirty, | 401 | .set_page_dirty = fuse_set_page_dirty, |
335 | }; | 402 | }; |
336 | 403 | ||