diff options
Diffstat (limited to 'fs/fuse/file.c')
-rw-r--r-- | fs/fuse/file.c | 111 |
1 files changed, 86 insertions, 25 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index c4b98c03a46e..0fcdba9d47c0 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -28,7 +28,9 @@ static int fuse_send_open(struct inode *inode, struct file *file, int isdir, | |||
28 | return PTR_ERR(req); | 28 | return PTR_ERR(req); |
29 | 29 | ||
30 | memset(&inarg, 0, sizeof(inarg)); | 30 | memset(&inarg, 0, sizeof(inarg)); |
31 | inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); | 31 | inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY); |
32 | if (!fc->atomic_o_trunc) | ||
33 | inarg.flags &= ~O_TRUNC; | ||
32 | req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; | 34 | req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; |
33 | req->in.h.nodeid = get_node_id(inode); | 35 | req->in.h.nodeid = get_node_id(inode); |
34 | req->in.numargs = 1; | 36 | req->in.numargs = 1; |
@@ -54,6 +56,7 @@ struct fuse_file *fuse_file_alloc(void) | |||
54 | kfree(ff); | 56 | kfree(ff); |
55 | ff = NULL; | 57 | ff = NULL; |
56 | } | 58 | } |
59 | INIT_LIST_HEAD(&ff->write_entry); | ||
57 | atomic_set(&ff->count, 0); | 60 | atomic_set(&ff->count, 0); |
58 | } | 61 | } |
59 | return ff; | 62 | return ff; |
@@ -148,12 +151,18 @@ int fuse_release_common(struct inode *inode, struct file *file, int isdir) | |||
148 | { | 151 | { |
149 | struct fuse_file *ff = file->private_data; | 152 | struct fuse_file *ff = file->private_data; |
150 | if (ff) { | 153 | if (ff) { |
154 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
155 | |||
151 | fuse_release_fill(ff, get_node_id(inode), file->f_flags, | 156 | fuse_release_fill(ff, get_node_id(inode), file->f_flags, |
152 | isdir ? FUSE_RELEASEDIR : FUSE_RELEASE); | 157 | isdir ? FUSE_RELEASEDIR : FUSE_RELEASE); |
153 | 158 | ||
154 | /* Hold vfsmount and dentry until release is finished */ | 159 | /* Hold vfsmount and dentry until release is finished */ |
155 | ff->reserved_req->vfsmount = mntget(file->f_path.mnt); | 160 | ff->reserved_req->vfsmount = mntget(file->f_path.mnt); |
156 | ff->reserved_req->dentry = dget(file->f_path.dentry); | 161 | ff->reserved_req->dentry = dget(file->f_path.dentry); |
162 | |||
163 | spin_lock(&fc->lock); | ||
164 | list_del(&ff->write_entry); | ||
165 | spin_unlock(&fc->lock); | ||
157 | /* | 166 | /* |
158 | * Normally this will send the RELEASE request, | 167 | * Normally this will send the RELEASE request, |
159 | * however if some asynchronous READ or WRITE requests | 168 | * however if some asynchronous READ or WRITE requests |
@@ -180,7 +189,7 @@ static int fuse_release(struct inode *inode, struct file *file) | |||
180 | * Scramble the ID space with XTEA, so that the value of the files_struct | 189 | * Scramble the ID space with XTEA, so that the value of the files_struct |
181 | * pointer is not exposed to userspace. | 190 | * pointer is not exposed to userspace. |
182 | */ | 191 | */ |
183 | static u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id) | 192 | u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id) |
184 | { | 193 | { |
185 | u32 *k = fc->scramble_key; | 194 | u32 *k = fc->scramble_key; |
186 | u64 v = (unsigned long) id; | 195 | u64 v = (unsigned long) id; |
@@ -299,11 +308,19 @@ void fuse_read_fill(struct fuse_req *req, struct fuse_file *ff, | |||
299 | } | 308 | } |
300 | 309 | ||
301 | static size_t fuse_send_read(struct fuse_req *req, struct file *file, | 310 | static size_t fuse_send_read(struct fuse_req *req, struct file *file, |
302 | struct inode *inode, loff_t pos, size_t count) | 311 | struct inode *inode, loff_t pos, size_t count, |
312 | fl_owner_t owner) | ||
303 | { | 313 | { |
304 | struct fuse_conn *fc = get_fuse_conn(inode); | 314 | struct fuse_conn *fc = get_fuse_conn(inode); |
305 | struct fuse_file *ff = file->private_data; | 315 | struct fuse_file *ff = file->private_data; |
316 | |||
306 | fuse_read_fill(req, ff, inode, pos, count, FUSE_READ); | 317 | fuse_read_fill(req, ff, inode, pos, count, FUSE_READ); |
318 | if (owner != NULL) { | ||
319 | struct fuse_read_in *inarg = &req->misc.read_in; | ||
320 | |||
321 | inarg->read_flags |= FUSE_READ_LOCKOWNER; | ||
322 | inarg->lock_owner = fuse_lock_owner_id(fc, owner); | ||
323 | } | ||
307 | request_send(fc, req); | 324 | request_send(fc, req); |
308 | return req->out.args[0].size; | 325 | return req->out.args[0].size; |
309 | } | 326 | } |
@@ -327,7 +344,8 @@ static int fuse_readpage(struct file *file, struct page *page) | |||
327 | req->out.page_zeroing = 1; | 344 | req->out.page_zeroing = 1; |
328 | req->num_pages = 1; | 345 | req->num_pages = 1; |
329 | req->pages[0] = page; | 346 | req->pages[0] = page; |
330 | fuse_send_read(req, file, inode, page_offset(page), PAGE_CACHE_SIZE); | 347 | fuse_send_read(req, file, inode, page_offset(page), PAGE_CACHE_SIZE, |
348 | NULL); | ||
331 | err = req->out.h.error; | 349 | err = req->out.h.error; |
332 | fuse_put_request(fc, req); | 350 | fuse_put_request(fc, req); |
333 | if (!err) | 351 | if (!err) |
@@ -434,30 +452,47 @@ out: | |||
434 | return err; | 452 | return err; |
435 | } | 453 | } |
436 | 454 | ||
437 | static size_t fuse_send_write(struct fuse_req *req, struct file *file, | 455 | static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, |
438 | struct inode *inode, loff_t pos, size_t count) | 456 | struct inode *inode, loff_t pos, size_t count, |
457 | int writepage) | ||
439 | { | 458 | { |
440 | struct fuse_conn *fc = get_fuse_conn(inode); | 459 | struct fuse_conn *fc = get_fuse_conn(inode); |
441 | struct fuse_file *ff = file->private_data; | 460 | struct fuse_write_in *inarg = &req->misc.write.in; |
442 | struct fuse_write_in inarg; | 461 | struct fuse_write_out *outarg = &req->misc.write.out; |
443 | struct fuse_write_out outarg; | ||
444 | 462 | ||
445 | memset(&inarg, 0, sizeof(struct fuse_write_in)); | 463 | memset(inarg, 0, sizeof(struct fuse_write_in)); |
446 | inarg.fh = ff->fh; | 464 | inarg->fh = ff->fh; |
447 | inarg.offset = pos; | 465 | inarg->offset = pos; |
448 | inarg.size = count; | 466 | inarg->size = count; |
467 | inarg->write_flags = writepage ? FUSE_WRITE_CACHE : 0; | ||
449 | req->in.h.opcode = FUSE_WRITE; | 468 | req->in.h.opcode = FUSE_WRITE; |
450 | req->in.h.nodeid = get_node_id(inode); | 469 | req->in.h.nodeid = get_node_id(inode); |
451 | req->in.argpages = 1; | 470 | req->in.argpages = 1; |
452 | req->in.numargs = 2; | 471 | req->in.numargs = 2; |
453 | req->in.args[0].size = sizeof(struct fuse_write_in); | 472 | if (fc->minor < 9) |
454 | req->in.args[0].value = &inarg; | 473 | req->in.args[0].size = FUSE_COMPAT_WRITE_IN_SIZE; |
474 | else | ||
475 | req->in.args[0].size = sizeof(struct fuse_write_in); | ||
476 | req->in.args[0].value = inarg; | ||
455 | req->in.args[1].size = count; | 477 | req->in.args[1].size = count; |
456 | req->out.numargs = 1; | 478 | req->out.numargs = 1; |
457 | req->out.args[0].size = sizeof(struct fuse_write_out); | 479 | req->out.args[0].size = sizeof(struct fuse_write_out); |
458 | req->out.args[0].value = &outarg; | 480 | req->out.args[0].value = outarg; |
481 | } | ||
482 | |||
483 | static size_t fuse_send_write(struct fuse_req *req, struct file *file, | ||
484 | struct inode *inode, loff_t pos, size_t count, | ||
485 | fl_owner_t owner) | ||
486 | { | ||
487 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
488 | fuse_write_fill(req, file->private_data, inode, pos, count, 0); | ||
489 | if (owner != NULL) { | ||
490 | struct fuse_write_in *inarg = &req->misc.write.in; | ||
491 | inarg->write_flags |= FUSE_WRITE_LOCKOWNER; | ||
492 | inarg->lock_owner = fuse_lock_owner_id(fc, owner); | ||
493 | } | ||
459 | request_send(fc, req); | 494 | request_send(fc, req); |
460 | return outarg.size; | 495 | return req->misc.write.out.size; |
461 | } | 496 | } |
462 | 497 | ||
463 | static int fuse_write_begin(struct file *file, struct address_space *mapping, | 498 | static int fuse_write_begin(struct file *file, struct address_space *mapping, |
@@ -478,6 +513,7 @@ static int fuse_buffered_write(struct file *file, struct inode *inode, | |||
478 | int err; | 513 | int err; |
479 | size_t nres; | 514 | size_t nres; |
480 | struct fuse_conn *fc = get_fuse_conn(inode); | 515 | struct fuse_conn *fc = get_fuse_conn(inode); |
516 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
481 | unsigned offset = pos & (PAGE_CACHE_SIZE - 1); | 517 | unsigned offset = pos & (PAGE_CACHE_SIZE - 1); |
482 | struct fuse_req *req; | 518 | struct fuse_req *req; |
483 | 519 | ||
@@ -491,7 +527,7 @@ static int fuse_buffered_write(struct file *file, struct inode *inode, | |||
491 | req->num_pages = 1; | 527 | req->num_pages = 1; |
492 | req->pages[0] = page; | 528 | req->pages[0] = page; |
493 | req->page_offset = offset; | 529 | req->page_offset = offset; |
494 | nres = fuse_send_write(req, file, inode, pos, count); | 530 | nres = fuse_send_write(req, file, inode, pos, count, NULL); |
495 | err = req->out.h.error; | 531 | err = req->out.h.error; |
496 | fuse_put_request(fc, req); | 532 | fuse_put_request(fc, req); |
497 | if (!err && !nres) | 533 | if (!err && !nres) |
@@ -499,6 +535,7 @@ static int fuse_buffered_write(struct file *file, struct inode *inode, | |||
499 | if (!err) { | 535 | if (!err) { |
500 | pos += nres; | 536 | pos += nres; |
501 | spin_lock(&fc->lock); | 537 | spin_lock(&fc->lock); |
538 | fi->attr_version = ++fc->attr_version; | ||
502 | if (pos > inode->i_size) | 539 | if (pos > inode->i_size) |
503 | i_size_write(inode, pos); | 540 | i_size_write(inode, pos); |
504 | spin_unlock(&fc->lock); | 541 | spin_unlock(&fc->lock); |
@@ -591,9 +628,11 @@ static ssize_t fuse_direct_io(struct file *file, const char __user *buf, | |||
591 | nbytes = (req->num_pages << PAGE_SHIFT) - req->page_offset; | 628 | nbytes = (req->num_pages << PAGE_SHIFT) - req->page_offset; |
592 | nbytes = min(count, nbytes); | 629 | nbytes = min(count, nbytes); |
593 | if (write) | 630 | if (write) |
594 | nres = fuse_send_write(req, file, inode, pos, nbytes); | 631 | nres = fuse_send_write(req, file, inode, pos, nbytes, |
632 | current->files); | ||
595 | else | 633 | else |
596 | nres = fuse_send_read(req, file, inode, pos, nbytes); | 634 | nres = fuse_send_read(req, file, inode, pos, nbytes, |
635 | current->files); | ||
597 | fuse_release_user_pages(req, !write); | 636 | fuse_release_user_pages(req, !write); |
598 | if (req->out.h.error) { | 637 | if (req->out.h.error) { |
599 | if (!res) | 638 | if (!res) |
@@ -695,7 +734,8 @@ static int convert_fuse_file_lock(const struct fuse_file_lock *ffl, | |||
695 | } | 734 | } |
696 | 735 | ||
697 | static void fuse_lk_fill(struct fuse_req *req, struct file *file, | 736 | static void fuse_lk_fill(struct fuse_req *req, struct file *file, |
698 | const struct file_lock *fl, int opcode, pid_t pid) | 737 | const struct file_lock *fl, int opcode, pid_t pid, |
738 | int flock) | ||
699 | { | 739 | { |
700 | struct inode *inode = file->f_path.dentry->d_inode; | 740 | struct inode *inode = file->f_path.dentry->d_inode; |
701 | struct fuse_conn *fc = get_fuse_conn(inode); | 741 | struct fuse_conn *fc = get_fuse_conn(inode); |
@@ -708,6 +748,8 @@ static void fuse_lk_fill(struct fuse_req *req, struct file *file, | |||
708 | arg->lk.end = fl->fl_end; | 748 | arg->lk.end = fl->fl_end; |
709 | arg->lk.type = fl->fl_type; | 749 | arg->lk.type = fl->fl_type; |
710 | arg->lk.pid = pid; | 750 | arg->lk.pid = pid; |
751 | if (flock) | ||
752 | arg->lk_flags |= FUSE_LK_FLOCK; | ||
711 | req->in.h.opcode = opcode; | 753 | req->in.h.opcode = opcode; |
712 | req->in.h.nodeid = get_node_id(inode); | 754 | req->in.h.nodeid = get_node_id(inode); |
713 | req->in.numargs = 1; | 755 | req->in.numargs = 1; |
@@ -727,7 +769,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl) | |||
727 | if (IS_ERR(req)) | 769 | if (IS_ERR(req)) |
728 | return PTR_ERR(req); | 770 | return PTR_ERR(req); |
729 | 771 | ||
730 | fuse_lk_fill(req, file, fl, FUSE_GETLK, 0); | 772 | fuse_lk_fill(req, file, fl, FUSE_GETLK, 0, 0); |
731 | req->out.numargs = 1; | 773 | req->out.numargs = 1; |
732 | req->out.args[0].size = sizeof(outarg); | 774 | req->out.args[0].size = sizeof(outarg); |
733 | req->out.args[0].value = &outarg; | 775 | req->out.args[0].value = &outarg; |
@@ -740,7 +782,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl) | |||
740 | return err; | 782 | return err; |
741 | } | 783 | } |
742 | 784 | ||
743 | static int fuse_setlk(struct file *file, struct file_lock *fl) | 785 | static int fuse_setlk(struct file *file, struct file_lock *fl, int flock) |
744 | { | 786 | { |
745 | struct inode *inode = file->f_path.dentry->d_inode; | 787 | struct inode *inode = file->f_path.dentry->d_inode; |
746 | struct fuse_conn *fc = get_fuse_conn(inode); | 788 | struct fuse_conn *fc = get_fuse_conn(inode); |
@@ -757,7 +799,7 @@ static int fuse_setlk(struct file *file, struct file_lock *fl) | |||
757 | if (IS_ERR(req)) | 799 | if (IS_ERR(req)) |
758 | return PTR_ERR(req); | 800 | return PTR_ERR(req); |
759 | 801 | ||
760 | fuse_lk_fill(req, file, fl, opcode, pid); | 802 | fuse_lk_fill(req, file, fl, opcode, pid, flock); |
761 | request_send(fc, req); | 803 | request_send(fc, req); |
762 | err = req->out.h.error; | 804 | err = req->out.h.error; |
763 | /* locking is restartable */ | 805 | /* locking is restartable */ |
@@ -783,8 +825,25 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl) | |||
783 | if (fc->no_lock) | 825 | if (fc->no_lock) |
784 | err = posix_lock_file_wait(file, fl); | 826 | err = posix_lock_file_wait(file, fl); |
785 | else | 827 | else |
786 | err = fuse_setlk(file, fl); | 828 | err = fuse_setlk(file, fl, 0); |
829 | } | ||
830 | return err; | ||
831 | } | ||
832 | |||
833 | static int fuse_file_flock(struct file *file, int cmd, struct file_lock *fl) | ||
834 | { | ||
835 | struct inode *inode = file->f_path.dentry->d_inode; | ||
836 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
837 | int err; | ||
838 | |||
839 | if (fc->no_lock) { | ||
840 | err = flock_lock_file_wait(file, fl); | ||
841 | } else { | ||
842 | /* emulate flock with POSIX locks */ | ||
843 | fl->fl_owner = (fl_owner_t) file; | ||
844 | err = fuse_setlk(file, fl, 1); | ||
787 | } | 845 | } |
846 | |||
788 | return err; | 847 | return err; |
789 | } | 848 | } |
790 | 849 | ||
@@ -836,6 +895,7 @@ static const struct file_operations fuse_file_operations = { | |||
836 | .release = fuse_release, | 895 | .release = fuse_release, |
837 | .fsync = fuse_fsync, | 896 | .fsync = fuse_fsync, |
838 | .lock = fuse_file_lock, | 897 | .lock = fuse_file_lock, |
898 | .flock = fuse_file_flock, | ||
839 | .splice_read = generic_file_splice_read, | 899 | .splice_read = generic_file_splice_read, |
840 | }; | 900 | }; |
841 | 901 | ||
@@ -848,6 +908,7 @@ static const struct file_operations fuse_direct_io_file_operations = { | |||
848 | .release = fuse_release, | 908 | .release = fuse_release, |
849 | .fsync = fuse_fsync, | 909 | .fsync = fuse_fsync, |
850 | .lock = fuse_file_lock, | 910 | .lock = fuse_file_lock, |
911 | .flock = fuse_file_flock, | ||
851 | /* no mmap and splice_read */ | 912 | /* no mmap and splice_read */ |
852 | }; | 913 | }; |
853 | 914 | ||