diff options
Diffstat (limited to 'fs/fuse/file.c')
-rw-r--r-- | fs/fuse/file.c | 52 |
1 files changed, 38 insertions, 14 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 0fcdba9d47c0..bb05d227cf30 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -55,9 +55,10 @@ struct fuse_file *fuse_file_alloc(void) | |||
55 | if (!ff->reserved_req) { | 55 | if (!ff->reserved_req) { |
56 | kfree(ff); | 56 | kfree(ff); |
57 | ff = NULL; | 57 | ff = NULL; |
58 | } else { | ||
59 | INIT_LIST_HEAD(&ff->write_entry); | ||
60 | atomic_set(&ff->count, 0); | ||
58 | } | 61 | } |
59 | INIT_LIST_HEAD(&ff->write_entry); | ||
60 | atomic_set(&ff->count, 0); | ||
61 | } | 62 | } |
62 | return ff; | 63 | return ff; |
63 | } | 64 | } |
@@ -288,14 +289,16 @@ static int fuse_fsync(struct file *file, struct dentry *de, int datasync) | |||
288 | return fuse_fsync_common(file, de, datasync, 0); | 289 | return fuse_fsync_common(file, de, datasync, 0); |
289 | } | 290 | } |
290 | 291 | ||
291 | void fuse_read_fill(struct fuse_req *req, struct fuse_file *ff, | 292 | void fuse_read_fill(struct fuse_req *req, struct file *file, |
292 | struct inode *inode, loff_t pos, size_t count, int opcode) | 293 | struct inode *inode, loff_t pos, size_t count, int opcode) |
293 | { | 294 | { |
294 | struct fuse_read_in *inarg = &req->misc.read_in; | 295 | struct fuse_read_in *inarg = &req->misc.read_in; |
296 | struct fuse_file *ff = file->private_data; | ||
295 | 297 | ||
296 | inarg->fh = ff->fh; | 298 | inarg->fh = ff->fh; |
297 | inarg->offset = pos; | 299 | inarg->offset = pos; |
298 | inarg->size = count; | 300 | inarg->size = count; |
301 | inarg->flags = file->f_flags; | ||
299 | req->in.h.opcode = opcode; | 302 | req->in.h.opcode = opcode; |
300 | req->in.h.nodeid = get_node_id(inode); | 303 | req->in.h.nodeid = get_node_id(inode); |
301 | req->in.numargs = 1; | 304 | req->in.numargs = 1; |
@@ -312,9 +315,8 @@ static size_t fuse_send_read(struct fuse_req *req, struct file *file, | |||
312 | fl_owner_t owner) | 315 | fl_owner_t owner) |
313 | { | 316 | { |
314 | struct fuse_conn *fc = get_fuse_conn(inode); | 317 | struct fuse_conn *fc = get_fuse_conn(inode); |
315 | struct fuse_file *ff = file->private_data; | ||
316 | 318 | ||
317 | fuse_read_fill(req, ff, inode, pos, count, FUSE_READ); | 319 | fuse_read_fill(req, file, inode, pos, count, FUSE_READ); |
318 | if (owner != NULL) { | 320 | if (owner != NULL) { |
319 | struct fuse_read_in *inarg = &req->misc.read_in; | 321 | struct fuse_read_in *inarg = &req->misc.read_in; |
320 | 322 | ||
@@ -375,15 +377,16 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_req *req) | |||
375 | fuse_put_request(fc, req); | 377 | fuse_put_request(fc, req); |
376 | } | 378 | } |
377 | 379 | ||
378 | static void fuse_send_readpages(struct fuse_req *req, struct fuse_file *ff, | 380 | static void fuse_send_readpages(struct fuse_req *req, struct file *file, |
379 | struct inode *inode) | 381 | struct inode *inode) |
380 | { | 382 | { |
381 | struct fuse_conn *fc = get_fuse_conn(inode); | 383 | struct fuse_conn *fc = get_fuse_conn(inode); |
382 | loff_t pos = page_offset(req->pages[0]); | 384 | loff_t pos = page_offset(req->pages[0]); |
383 | size_t count = req->num_pages << PAGE_CACHE_SHIFT; | 385 | size_t count = req->num_pages << PAGE_CACHE_SHIFT; |
384 | req->out.page_zeroing = 1; | 386 | req->out.page_zeroing = 1; |
385 | fuse_read_fill(req, ff, inode, pos, count, FUSE_READ); | 387 | fuse_read_fill(req, file, inode, pos, count, FUSE_READ); |
386 | if (fc->async_read) { | 388 | if (fc->async_read) { |
389 | struct fuse_file *ff = file->private_data; | ||
387 | req->ff = fuse_file_get(ff); | 390 | req->ff = fuse_file_get(ff); |
388 | req->end = fuse_readpages_end; | 391 | req->end = fuse_readpages_end; |
389 | request_send_background(fc, req); | 392 | request_send_background(fc, req); |
@@ -395,7 +398,7 @@ static void fuse_send_readpages(struct fuse_req *req, struct fuse_file *ff, | |||
395 | 398 | ||
396 | struct fuse_fill_data { | 399 | struct fuse_fill_data { |
397 | struct fuse_req *req; | 400 | struct fuse_req *req; |
398 | struct fuse_file *ff; | 401 | struct file *file; |
399 | struct inode *inode; | 402 | struct inode *inode; |
400 | }; | 403 | }; |
401 | 404 | ||
@@ -410,7 +413,7 @@ static int fuse_readpages_fill(void *_data, struct page *page) | |||
410 | (req->num_pages == FUSE_MAX_PAGES_PER_REQ || | 413 | (req->num_pages == FUSE_MAX_PAGES_PER_REQ || |
411 | (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || | 414 | (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || |
412 | req->pages[req->num_pages - 1]->index + 1 != page->index)) { | 415 | req->pages[req->num_pages - 1]->index + 1 != page->index)) { |
413 | fuse_send_readpages(req, data->ff, inode); | 416 | fuse_send_readpages(req, data->file, inode); |
414 | data->req = req = fuse_get_req(fc); | 417 | data->req = req = fuse_get_req(fc); |
415 | if (IS_ERR(req)) { | 418 | if (IS_ERR(req)) { |
416 | unlock_page(page); | 419 | unlock_page(page); |
@@ -434,7 +437,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
434 | if (is_bad_inode(inode)) | 437 | if (is_bad_inode(inode)) |
435 | goto out; | 438 | goto out; |
436 | 439 | ||
437 | data.ff = file->private_data; | 440 | data.file = file; |
438 | data.inode = inode; | 441 | data.inode = inode; |
439 | data.req = fuse_get_req(fc); | 442 | data.req = fuse_get_req(fc); |
440 | err = PTR_ERR(data.req); | 443 | err = PTR_ERR(data.req); |
@@ -444,7 +447,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
444 | err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); | 447 | err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data); |
445 | if (!err) { | 448 | if (!err) { |
446 | if (data.req->num_pages) | 449 | if (data.req->num_pages) |
447 | fuse_send_readpages(data.req, data.ff, inode); | 450 | fuse_send_readpages(data.req, file, inode); |
448 | else | 451 | else |
449 | fuse_put_request(fc, data.req); | 452 | fuse_put_request(fc, data.req); |
450 | } | 453 | } |
@@ -452,11 +455,31 @@ out: | |||
452 | return err; | 455 | return err; |
453 | } | 456 | } |
454 | 457 | ||
455 | static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, | 458 | static ssize_t fuse_file_aio_read(struct kiocb *iocb, const struct iovec *iov, |
459 | unsigned long nr_segs, loff_t pos) | ||
460 | { | ||
461 | struct inode *inode = iocb->ki_filp->f_mapping->host; | ||
462 | |||
463 | if (pos + iov_length(iov, nr_segs) > i_size_read(inode)) { | ||
464 | int err; | ||
465 | /* | ||
466 | * If trying to read past EOF, make sure the i_size | ||
467 | * attribute is up-to-date. | ||
468 | */ | ||
469 | err = fuse_update_attributes(inode, NULL, iocb->ki_filp, NULL); | ||
470 | if (err) | ||
471 | return err; | ||
472 | } | ||
473 | |||
474 | return generic_file_aio_read(iocb, iov, nr_segs, pos); | ||
475 | } | ||
476 | |||
477 | static void fuse_write_fill(struct fuse_req *req, struct file *file, | ||
456 | struct inode *inode, loff_t pos, size_t count, | 478 | struct inode *inode, loff_t pos, size_t count, |
457 | int writepage) | 479 | int writepage) |
458 | { | 480 | { |
459 | struct fuse_conn *fc = get_fuse_conn(inode); | 481 | struct fuse_conn *fc = get_fuse_conn(inode); |
482 | struct fuse_file *ff = file->private_data; | ||
460 | struct fuse_write_in *inarg = &req->misc.write.in; | 483 | struct fuse_write_in *inarg = &req->misc.write.in; |
461 | struct fuse_write_out *outarg = &req->misc.write.out; | 484 | struct fuse_write_out *outarg = &req->misc.write.out; |
462 | 485 | ||
@@ -465,6 +488,7 @@ static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, | |||
465 | inarg->offset = pos; | 488 | inarg->offset = pos; |
466 | inarg->size = count; | 489 | inarg->size = count; |
467 | inarg->write_flags = writepage ? FUSE_WRITE_CACHE : 0; | 490 | inarg->write_flags = writepage ? FUSE_WRITE_CACHE : 0; |
491 | inarg->flags = file->f_flags; | ||
468 | req->in.h.opcode = FUSE_WRITE; | 492 | req->in.h.opcode = FUSE_WRITE; |
469 | req->in.h.nodeid = get_node_id(inode); | 493 | req->in.h.nodeid = get_node_id(inode); |
470 | req->in.argpages = 1; | 494 | req->in.argpages = 1; |
@@ -485,7 +509,7 @@ static size_t fuse_send_write(struct fuse_req *req, struct file *file, | |||
485 | fl_owner_t owner) | 509 | fl_owner_t owner) |
486 | { | 510 | { |
487 | struct fuse_conn *fc = get_fuse_conn(inode); | 511 | struct fuse_conn *fc = get_fuse_conn(inode); |
488 | fuse_write_fill(req, file->private_data, inode, pos, count, 0); | 512 | fuse_write_fill(req, file, inode, pos, count, 0); |
489 | if (owner != NULL) { | 513 | if (owner != NULL) { |
490 | struct fuse_write_in *inarg = &req->misc.write.in; | 514 | struct fuse_write_in *inarg = &req->misc.write.in; |
491 | inarg->write_flags |= FUSE_WRITE_LOCKOWNER; | 515 | inarg->write_flags |= FUSE_WRITE_LOCKOWNER; |
@@ -886,7 +910,7 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block) | |||
886 | static const struct file_operations fuse_file_operations = { | 910 | static const struct file_operations fuse_file_operations = { |
887 | .llseek = generic_file_llseek, | 911 | .llseek = generic_file_llseek, |
888 | .read = do_sync_read, | 912 | .read = do_sync_read, |
889 | .aio_read = generic_file_aio_read, | 913 | .aio_read = fuse_file_aio_read, |
890 | .write = do_sync_write, | 914 | .write = do_sync_write, |
891 | .aio_write = generic_file_aio_write, | 915 | .aio_write = generic_file_aio_write, |
892 | .mmap = fuse_file_mmap, | 916 | .mmap = fuse_file_mmap, |