Commit 2eac9eb8a2e64cbfcc300e9a8098edf424c1d16c
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse
Pull fuse updates from Miklos Szeredi. * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse: fuse: verify all ioctl retry iov elements fuse: add missing INIT flag descriptions fuse: add missing INIT flags fuse: update attributes on aio_read fuse: invalidate inode mapping if mtime changes fuse: add FUSE_AUTO_INVAL_DATA init flag
Showing 4 changed files Side-by-side Diff
fs/fuse/file.c
... | ... | @@ -703,13 +703,16 @@ |
703 | 703 | unsigned long nr_segs, loff_t pos) |
704 | 704 | { |
705 | 705 | struct inode *inode = iocb->ki_filp->f_mapping->host; |
706 | + struct fuse_conn *fc = get_fuse_conn(inode); | |
706 | 707 | |
707 | - if (pos + iov_length(iov, nr_segs) > i_size_read(inode)) { | |
708 | + /* | |
709 | + * In auto invalidate mode, always update attributes on read. | |
710 | + * Otherwise, only update if we attempt to read past EOF (to ensure | |
711 | + * i_size is up to date). | |
712 | + */ | |
713 | + if (fc->auto_inval_data || | |
714 | + (pos + iov_length(iov, nr_segs) > i_size_read(inode))) { | |
708 | 715 | int err; |
709 | - /* | |
710 | - * If trying to read past EOF, make sure the i_size | |
711 | - * attribute is up-to-date. | |
712 | - */ | |
713 | 716 | err = fuse_update_attributes(inode, NULL, iocb->ki_filp, NULL); |
714 | 717 | if (err) |
715 | 718 | return err; |
... | ... | @@ -1700,7 +1703,7 @@ |
1700 | 1703 | size_t n; |
1701 | 1704 | u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT; |
1702 | 1705 | |
1703 | - for (n = 0; n < count; n++) { | |
1706 | + for (n = 0; n < count; n++, iov++) { | |
1704 | 1707 | if (iov->iov_len > (size_t) max) |
1705 | 1708 | return -ENOMEM; |
1706 | 1709 | max -= iov->iov_len; |
fs/fuse/fuse_i.h
... | ... | @@ -484,6 +484,9 @@ |
484 | 484 | /** Is fallocate not implemented by fs? */ |
485 | 485 | unsigned no_fallocate:1; |
486 | 486 | |
487 | + /** Use enhanced/automatic page cache invalidation. */ | |
488 | + unsigned auto_inval_data:1; | |
489 | + | |
487 | 490 | /** The number of requests waiting for completion */ |
488 | 491 | atomic_t num_waiting; |
489 | 492 |
fs/fuse/inode.c
... | ... | @@ -197,6 +197,7 @@ |
197 | 197 | struct fuse_conn *fc = get_fuse_conn(inode); |
198 | 198 | struct fuse_inode *fi = get_fuse_inode(inode); |
199 | 199 | loff_t oldsize; |
200 | + struct timespec old_mtime; | |
200 | 201 | |
201 | 202 | spin_lock(&fc->lock); |
202 | 203 | if (attr_version != 0 && fi->attr_version > attr_version) { |
203 | 204 | |
... | ... | @@ -204,15 +205,35 @@ |
204 | 205 | return; |
205 | 206 | } |
206 | 207 | |
208 | + old_mtime = inode->i_mtime; | |
207 | 209 | fuse_change_attributes_common(inode, attr, attr_valid); |
208 | 210 | |
209 | 211 | oldsize = inode->i_size; |
210 | 212 | i_size_write(inode, attr->size); |
211 | 213 | spin_unlock(&fc->lock); |
212 | 214 | |
213 | - if (S_ISREG(inode->i_mode) && oldsize != attr->size) { | |
214 | - truncate_pagecache(inode, oldsize, attr->size); | |
215 | - invalidate_inode_pages2(inode->i_mapping); | |
215 | + if (S_ISREG(inode->i_mode)) { | |
216 | + bool inval = false; | |
217 | + | |
218 | + if (oldsize != attr->size) { | |
219 | + truncate_pagecache(inode, oldsize, attr->size); | |
220 | + inval = true; | |
221 | + } else if (fc->auto_inval_data) { | |
222 | + struct timespec new_mtime = { | |
223 | + .tv_sec = attr->mtime, | |
224 | + .tv_nsec = attr->mtimensec, | |
225 | + }; | |
226 | + | |
227 | + /* | |
228 | + * Auto inval mode also checks and invalidates if mtime | |
229 | + * has changed. | |
230 | + */ | |
231 | + if (!timespec_equal(&old_mtime, &new_mtime)) | |
232 | + inval = true; | |
233 | + } | |
234 | + | |
235 | + if (inval) | |
236 | + invalidate_inode_pages2(inode->i_mapping); | |
216 | 237 | } |
217 | 238 | } |
218 | 239 | |
... | ... | @@ -834,6 +855,8 @@ |
834 | 855 | fc->big_writes = 1; |
835 | 856 | if (arg->flags & FUSE_DONT_MASK) |
836 | 857 | fc->dont_mask = 1; |
858 | + if (arg->flags & FUSE_AUTO_INVAL_DATA) | |
859 | + fc->auto_inval_data = 1; | |
837 | 860 | } else { |
838 | 861 | ra_pages = fc->max_read / PAGE_CACHE_SIZE; |
839 | 862 | fc->no_lock = 1; |
... | ... | @@ -859,7 +882,8 @@ |
859 | 882 | arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; |
860 | 883 | arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | |
861 | 884 | FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | |
862 | - FUSE_FLOCK_LOCKS; | |
885 | + FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ | | |
886 | + FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA; | |
863 | 887 | req->in.h.opcode = FUSE_INIT; |
864 | 888 | req->in.numargs = 1; |
865 | 889 | req->in.args[0].size = sizeof(*arg); |
include/linux/fuse.h
... | ... | @@ -57,6 +57,9 @@ |
57 | 57 | * |
58 | 58 | * 7.19 |
59 | 59 | * - add FUSE_FALLOCATE |
60 | + * | |
61 | + * 7.20 | |
62 | + * - add FUSE_AUTO_INVAL_DATA | |
60 | 63 | */ |
61 | 64 | |
62 | 65 | #ifndef _LINUX_FUSE_H |
... | ... | @@ -88,7 +91,7 @@ |
88 | 91 | #define FUSE_KERNEL_VERSION 7 |
89 | 92 | |
90 | 93 | /** Minor version number of this interface */ |
91 | -#define FUSE_KERNEL_MINOR_VERSION 19 | |
94 | +#define FUSE_KERNEL_MINOR_VERSION 20 | |
92 | 95 | |
93 | 96 | /** The node ID of the root inode */ |
94 | 97 | #define FUSE_ROOT_ID 1 |
95 | 98 | |
96 | 99 | |
97 | 100 | |
98 | 101 | |
... | ... | @@ -163,10 +166,19 @@ |
163 | 166 | /** |
164 | 167 | * INIT request/reply flags |
165 | 168 | * |
169 | + * FUSE_ASYNC_READ: asynchronous read requests | |
166 | 170 | * FUSE_POSIX_LOCKS: remote locking for POSIX file locks |
171 | + * FUSE_FILE_OPS: kernel sends file handle for fstat, etc... (not yet supported) | |
172 | + * FUSE_ATOMIC_O_TRUNC: handles the O_TRUNC open flag in the filesystem | |
167 | 173 | * FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".." |
174 | + * FUSE_BIG_WRITES: filesystem can handle write size larger than 4kB | |
168 | 175 | * FUSE_DONT_MASK: don't apply umask to file mode on create operations |
176 | + * FUSE_SPLICE_WRITE: kernel supports splice write on the device | |
177 | + * FUSE_SPLICE_MOVE: kernel supports splice move on the device | |
178 | + * FUSE_SPLICE_READ: kernel supports splice read on the device | |
169 | 179 | * FUSE_FLOCK_LOCKS: remote locking for BSD style file locks |
180 | + * FUSE_HAS_IOCTL_DIR: kernel supports ioctl on directories | |
181 | + * FUSE_AUTO_INVAL_DATA: automatically invalidate cached pages | |
170 | 182 | */ |
171 | 183 | #define FUSE_ASYNC_READ (1 << 0) |
172 | 184 | #define FUSE_POSIX_LOCKS (1 << 1) |
173 | 185 | |
... | ... | @@ -175,7 +187,12 @@ |
175 | 187 | #define FUSE_EXPORT_SUPPORT (1 << 4) |
176 | 188 | #define FUSE_BIG_WRITES (1 << 5) |
177 | 189 | #define FUSE_DONT_MASK (1 << 6) |
190 | +#define FUSE_SPLICE_WRITE (1 << 7) | |
191 | +#define FUSE_SPLICE_MOVE (1 << 8) | |
192 | +#define FUSE_SPLICE_READ (1 << 9) | |
178 | 193 | #define FUSE_FLOCK_LOCKS (1 << 10) |
194 | +#define FUSE_HAS_IOCTL_DIR (1 << 11) | |
195 | +#define FUSE_AUTO_INVAL_DATA (1 << 12) | |
179 | 196 | |
180 | 197 | /** |
181 | 198 | * CUSE INIT request/reply flags |