Commit 2eac9eb8a2e64cbfcc300e9a8098edf424c1d16c

Authored by Linus Torvalds

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

... ... @@ -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;
... ... @@ -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  
... ... @@ -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