aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fuse/inode.c')
-rw-r--r--fs/fuse/inode.c44
1 files changed, 35 insertions, 9 deletions
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 1cd61652018c..fca222dabe3c 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -197,6 +197,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
197 struct fuse_conn *fc = get_fuse_conn(inode); 197 struct fuse_conn *fc = get_fuse_conn(inode);
198 struct fuse_inode *fi = get_fuse_inode(inode); 198 struct fuse_inode *fi = get_fuse_inode(inode);
199 loff_t oldsize; 199 loff_t oldsize;
200 struct timespec old_mtime;
200 201
201 spin_lock(&fc->lock); 202 spin_lock(&fc->lock);
202 if (attr_version != 0 && fi->attr_version > attr_version) { 203 if (attr_version != 0 && fi->attr_version > attr_version) {
@@ -204,15 +205,35 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
204 return; 205 return;
205 } 206 }
206 207
208 old_mtime = inode->i_mtime;
207 fuse_change_attributes_common(inode, attr, attr_valid); 209 fuse_change_attributes_common(inode, attr, attr_valid);
208 210
209 oldsize = inode->i_size; 211 oldsize = inode->i_size;
210 i_size_write(inode, attr->size); 212 i_size_write(inode, attr->size);
211 spin_unlock(&fc->lock); 213 spin_unlock(&fc->lock);
212 214
213 if (S_ISREG(inode->i_mode) && oldsize != attr->size) { 215 if (S_ISREG(inode->i_mode)) {
214 truncate_pagecache(inode, oldsize, attr->size); 216 bool inval = false;
215 invalidate_inode_pages2(inode->i_mapping); 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
@@ -346,11 +367,6 @@ void fuse_conn_kill(struct fuse_conn *fc)
346 wake_up_all(&fc->waitq); 367 wake_up_all(&fc->waitq);
347 wake_up_all(&fc->blocked_waitq); 368 wake_up_all(&fc->blocked_waitq);
348 wake_up_all(&fc->reserved_req_waitq); 369 wake_up_all(&fc->reserved_req_waitq);
349 mutex_lock(&fuse_mutex);
350 list_del(&fc->entry);
351 fuse_ctl_remove_conn(fc);
352 mutex_unlock(&fuse_mutex);
353 fuse_bdi_destroy(fc);
354} 370}
355EXPORT_SYMBOL_GPL(fuse_conn_kill); 371EXPORT_SYMBOL_GPL(fuse_conn_kill);
356 372
@@ -359,7 +375,14 @@ static void fuse_put_super(struct super_block *sb)
359 struct fuse_conn *fc = get_fuse_conn_super(sb); 375 struct fuse_conn *fc = get_fuse_conn_super(sb);
360 376
361 fuse_send_destroy(fc); 377 fuse_send_destroy(fc);
378
362 fuse_conn_kill(fc); 379 fuse_conn_kill(fc);
380 mutex_lock(&fuse_mutex);
381 list_del(&fc->entry);
382 fuse_ctl_remove_conn(fc);
383 mutex_unlock(&fuse_mutex);
384 fuse_bdi_destroy(fc);
385
363 fuse_conn_put(fc); 386 fuse_conn_put(fc);
364} 387}
365 388
@@ -834,6 +857,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
834 fc->big_writes = 1; 857 fc->big_writes = 1;
835 if (arg->flags & FUSE_DONT_MASK) 858 if (arg->flags & FUSE_DONT_MASK)
836 fc->dont_mask = 1; 859 fc->dont_mask = 1;
860 if (arg->flags & FUSE_AUTO_INVAL_DATA)
861 fc->auto_inval_data = 1;
837 } else { 862 } else {
838 ra_pages = fc->max_read / PAGE_CACHE_SIZE; 863 ra_pages = fc->max_read / PAGE_CACHE_SIZE;
839 fc->no_lock = 1; 864 fc->no_lock = 1;
@@ -859,7 +884,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req)
859 arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; 884 arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE;
860 arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | 885 arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC |
861 FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | 886 FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK |
862 FUSE_FLOCK_LOCKS; 887 FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ |
888 FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA;
863 req->in.h.opcode = FUSE_INIT; 889 req->in.h.opcode = FUSE_INIT;
864 req->in.numargs = 1; 890 req->in.numargs = 1;
865 req->in.args[0].size = sizeof(*arg); 891 req->in.args[0].size = sizeof(*arg);