Commit 051732bcbe3cff3fea04dc9042266562fe8b0859
Exists in
master
and in
4 other branches
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse: fuse: check size of FUSE_NOTIFY_INVAL_ENTRY message fuse: mark pages accessed when written to fuse: delete dead .write_begin and .write_end aops fuse: fix flock fuse: fix non-ANSI void function notation
Showing 5 changed files Side-by-side Diff
fs/fuse/dev.c
... | ... | @@ -1358,6 +1358,10 @@ |
1358 | 1358 | if (outarg.namelen > FUSE_NAME_MAX) |
1359 | 1359 | goto err; |
1360 | 1360 | |
1361 | + err = -EINVAL; | |
1362 | + if (size != sizeof(outarg) + outarg.namelen + 1) | |
1363 | + goto err; | |
1364 | + | |
1361 | 1365 | name.name = buf; |
1362 | 1366 | name.len = outarg.namelen; |
1363 | 1367 | err = fuse_copy_one(cs, buf, outarg.namelen + 1); |
fs/fuse/file.c
... | ... | @@ -14,6 +14,7 @@ |
14 | 14 | #include <linux/sched.h> |
15 | 15 | #include <linux/module.h> |
16 | 16 | #include <linux/compat.h> |
17 | +#include <linux/swap.h> | |
17 | 18 | |
18 | 19 | static const struct file_operations fuse_direct_io_file_operations; |
19 | 20 | |
... | ... | @@ -245,6 +246,12 @@ |
245 | 246 | req = ff->reserved_req; |
246 | 247 | fuse_prepare_release(ff, file->f_flags, opcode); |
247 | 248 | |
249 | + if (ff->flock) { | |
250 | + struct fuse_release_in *inarg = &req->misc.release.in; | |
251 | + inarg->release_flags |= FUSE_RELEASE_FLOCK_UNLOCK; | |
252 | + inarg->lock_owner = fuse_lock_owner_id(ff->fc, | |
253 | + (fl_owner_t) file); | |
254 | + } | |
248 | 255 | /* Hold vfsmount and dentry until release is finished */ |
249 | 256 | path_get(&file->f_path); |
250 | 257 | req->misc.release.path = file->f_path; |
... | ... | @@ -755,18 +762,6 @@ |
755 | 762 | return req->misc.write.out.size; |
756 | 763 | } |
757 | 764 | |
758 | -static int fuse_write_begin(struct file *file, struct address_space *mapping, | |
759 | - loff_t pos, unsigned len, unsigned flags, | |
760 | - struct page **pagep, void **fsdata) | |
761 | -{ | |
762 | - pgoff_t index = pos >> PAGE_CACHE_SHIFT; | |
763 | - | |
764 | - *pagep = grab_cache_page_write_begin(mapping, index, flags); | |
765 | - if (!*pagep) | |
766 | - return -ENOMEM; | |
767 | - return 0; | |
768 | -} | |
769 | - | |
770 | 765 | void fuse_write_update_size(struct inode *inode, loff_t pos) |
771 | 766 | { |
772 | 767 | struct fuse_conn *fc = get_fuse_conn(inode); |
... | ... | @@ -779,62 +774,6 @@ |
779 | 774 | spin_unlock(&fc->lock); |
780 | 775 | } |
781 | 776 | |
782 | -static int fuse_buffered_write(struct file *file, struct inode *inode, | |
783 | - loff_t pos, unsigned count, struct page *page) | |
784 | -{ | |
785 | - int err; | |
786 | - size_t nres; | |
787 | - struct fuse_conn *fc = get_fuse_conn(inode); | |
788 | - unsigned offset = pos & (PAGE_CACHE_SIZE - 1); | |
789 | - struct fuse_req *req; | |
790 | - | |
791 | - if (is_bad_inode(inode)) | |
792 | - return -EIO; | |
793 | - | |
794 | - /* | |
795 | - * Make sure writepages on the same page are not mixed up with | |
796 | - * plain writes. | |
797 | - */ | |
798 | - fuse_wait_on_page_writeback(inode, page->index); | |
799 | - | |
800 | - req = fuse_get_req(fc); | |
801 | - if (IS_ERR(req)) | |
802 | - return PTR_ERR(req); | |
803 | - | |
804 | - req->in.argpages = 1; | |
805 | - req->num_pages = 1; | |
806 | - req->pages[0] = page; | |
807 | - req->page_offset = offset; | |
808 | - nres = fuse_send_write(req, file, pos, count, NULL); | |
809 | - err = req->out.h.error; | |
810 | - fuse_put_request(fc, req); | |
811 | - if (!err && !nres) | |
812 | - err = -EIO; | |
813 | - if (!err) { | |
814 | - pos += nres; | |
815 | - fuse_write_update_size(inode, pos); | |
816 | - if (count == PAGE_CACHE_SIZE) | |
817 | - SetPageUptodate(page); | |
818 | - } | |
819 | - fuse_invalidate_attr(inode); | |
820 | - return err ? err : nres; | |
821 | -} | |
822 | - | |
823 | -static int fuse_write_end(struct file *file, struct address_space *mapping, | |
824 | - loff_t pos, unsigned len, unsigned copied, | |
825 | - struct page *page, void *fsdata) | |
826 | -{ | |
827 | - struct inode *inode = mapping->host; | |
828 | - int res = 0; | |
829 | - | |
830 | - if (copied) | |
831 | - res = fuse_buffered_write(file, inode, pos, copied, page); | |
832 | - | |
833 | - unlock_page(page); | |
834 | - page_cache_release(page); | |
835 | - return res; | |
836 | -} | |
837 | - | |
838 | 777 | static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file, |
839 | 778 | struct inode *inode, loff_t pos, |
840 | 779 | size_t count) |
... | ... | @@ -908,6 +847,8 @@ |
908 | 847 | pagefault_enable(); |
909 | 848 | flush_dcache_page(page); |
910 | 849 | |
850 | + mark_page_accessed(page); | |
851 | + | |
911 | 852 | if (!tmp) { |
912 | 853 | unlock_page(page); |
913 | 854 | page_cache_release(page); |
914 | 855 | |
915 | 856 | |
... | ... | @@ -1559,11 +1500,14 @@ |
1559 | 1500 | struct fuse_conn *fc = get_fuse_conn(inode); |
1560 | 1501 | int err; |
1561 | 1502 | |
1562 | - if (fc->no_lock) { | |
1503 | + if (fc->no_flock) { | |
1563 | 1504 | err = flock_lock_file_wait(file, fl); |
1564 | 1505 | } else { |
1506 | + struct fuse_file *ff = file->private_data; | |
1507 | + | |
1565 | 1508 | /* emulate flock with POSIX locks */ |
1566 | 1509 | fl->fl_owner = (fl_owner_t) file; |
1510 | + ff->flock = true; | |
1567 | 1511 | err = fuse_setlk(file, fl, 1); |
1568 | 1512 | } |
1569 | 1513 | |
... | ... | @@ -2201,8 +2145,6 @@ |
2201 | 2145 | .readpage = fuse_readpage, |
2202 | 2146 | .writepage = fuse_writepage, |
2203 | 2147 | .launder_page = fuse_launder_page, |
2204 | - .write_begin = fuse_write_begin, | |
2205 | - .write_end = fuse_write_end, | |
2206 | 2148 | .readpages = fuse_readpages, |
2207 | 2149 | .set_page_dirty = __set_page_dirty_nobuffers, |
2208 | 2150 | .bmap = fuse_bmap, |
fs/fuse/fuse_i.h
... | ... | @@ -135,6 +135,9 @@ |
135 | 135 | |
136 | 136 | /** Wait queue head for poll */ |
137 | 137 | wait_queue_head_t poll_wait; |
138 | + | |
139 | + /** Has flock been performed on this file? */ | |
140 | + bool flock:1; | |
138 | 141 | }; |
139 | 142 | |
140 | 143 | /** One input argument of a request */ |
... | ... | @@ -448,7 +451,7 @@ |
448 | 451 | /** Is removexattr not implemented by fs? */ |
449 | 452 | unsigned no_removexattr:1; |
450 | 453 | |
451 | - /** Are file locking primitives not implemented by fs? */ | |
454 | + /** Are posix file locking primitives not implemented by fs? */ | |
452 | 455 | unsigned no_lock:1; |
453 | 456 | |
454 | 457 | /** Is access not implemented by fs? */ |
... | ... | @@ -471,6 +474,9 @@ |
471 | 474 | |
472 | 475 | /** Don't apply umask to creation modes */ |
473 | 476 | unsigned dont_mask:1; |
477 | + | |
478 | + /** Are BSD file locking primitives not implemented by fs? */ | |
479 | + unsigned no_flock:1; | |
474 | 480 | |
475 | 481 | /** The number of requests waiting for completion */ |
476 | 482 | atomic_t num_waiting; |
fs/fuse/inode.c
... | ... | @@ -71,7 +71,7 @@ |
71 | 71 | unsigned blksize; |
72 | 72 | }; |
73 | 73 | |
74 | -struct fuse_forget_link *fuse_alloc_forget() | |
74 | +struct fuse_forget_link *fuse_alloc_forget(void) | |
75 | 75 | { |
76 | 76 | return kzalloc(sizeof(struct fuse_forget_link), GFP_KERNEL); |
77 | 77 | } |
... | ... | @@ -809,6 +809,10 @@ |
809 | 809 | fc->async_read = 1; |
810 | 810 | if (!(arg->flags & FUSE_POSIX_LOCKS)) |
811 | 811 | fc->no_lock = 1; |
812 | + if (arg->minor >= 17) { | |
813 | + if (!(arg->flags & FUSE_FLOCK_LOCKS)) | |
814 | + fc->no_flock = 1; | |
815 | + } | |
812 | 816 | if (arg->flags & FUSE_ATOMIC_O_TRUNC) |
813 | 817 | fc->atomic_o_trunc = 1; |
814 | 818 | if (arg->minor >= 9) { |
... | ... | @@ -823,6 +827,7 @@ |
823 | 827 | } else { |
824 | 828 | ra_pages = fc->max_read / PAGE_CACHE_SIZE; |
825 | 829 | fc->no_lock = 1; |
830 | + fc->no_flock = 1; | |
826 | 831 | } |
827 | 832 | |
828 | 833 | fc->bdi.ra_pages = min(fc->bdi.ra_pages, ra_pages); |
... | ... | @@ -843,7 +848,8 @@ |
843 | 848 | arg->minor = FUSE_KERNEL_MINOR_VERSION; |
844 | 849 | arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; |
845 | 850 | arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | |
846 | - FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK; | |
851 | + FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | | |
852 | + FUSE_FLOCK_LOCKS; | |
847 | 853 | req->in.h.opcode = FUSE_INIT; |
848 | 854 | req->in.numargs = 1; |
849 | 855 | req->in.args[0].size = sizeof(*arg); |
include/linux/fuse.h
... | ... | @@ -47,6 +47,9 @@ |
47 | 47 | * - FUSE_IOCTL_UNRESTRICTED shall now return with array of 'struct |
48 | 48 | * fuse_ioctl_iovec' instead of ambiguous 'struct iovec' |
49 | 49 | * - add FUSE_IOCTL_32BIT flag |
50 | + * | |
51 | + * 7.17 | |
52 | + * - add FUSE_FLOCK_LOCKS and FUSE_RELEASE_FLOCK_UNLOCK | |
50 | 53 | */ |
51 | 54 | |
52 | 55 | #ifndef _LINUX_FUSE_H |
... | ... | @@ -78,7 +81,7 @@ |
78 | 81 | #define FUSE_KERNEL_VERSION 7 |
79 | 82 | |
80 | 83 | /** Minor version number of this interface */ |
81 | -#define FUSE_KERNEL_MINOR_VERSION 16 | |
84 | +#define FUSE_KERNEL_MINOR_VERSION 17 | |
82 | 85 | |
83 | 86 | /** The node ID of the root inode */ |
84 | 87 | #define FUSE_ROOT_ID 1 |
85 | 88 | |
... | ... | @@ -153,8 +156,10 @@ |
153 | 156 | /** |
154 | 157 | * INIT request/reply flags |
155 | 158 | * |
159 | + * FUSE_POSIX_LOCKS: remote locking for POSIX file locks | |
156 | 160 | * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".." |
157 | 161 | * FUSE_DONT_MASK: don't apply umask to file mode on create operations |
162 | + * FUSE_FLOCK_LOCKS: remote locking for BSD style file locks | |
158 | 163 | */ |
159 | 164 | #define FUSE_ASYNC_READ (1 << 0) |
160 | 165 | #define FUSE_POSIX_LOCKS (1 << 1) |
... | ... | @@ -163,6 +168,7 @@ |
163 | 168 | #define FUSE_EXPORT_SUPPORT (1 << 4) |
164 | 169 | #define FUSE_BIG_WRITES (1 << 5) |
165 | 170 | #define FUSE_DONT_MASK (1 << 6) |
171 | +#define FUSE_FLOCK_LOCKS (1 << 10) | |
166 | 172 | |
167 | 173 | /** |
168 | 174 | * CUSE INIT request/reply flags |
... | ... | @@ -175,6 +181,7 @@ |
175 | 181 | * Release flags |
176 | 182 | */ |
177 | 183 | #define FUSE_RELEASE_FLUSH (1 << 0) |
184 | +#define FUSE_RELEASE_FLOCK_UNLOCK (1 << 1) | |
178 | 185 | |
179 | 186 | /** |
180 | 187 | * Getattr flags |