diff options
Diffstat (limited to 'fs/fuse/inode.c')
-rw-r--r-- | fs/fuse/inode.c | 44 |
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 | } |
355 | EXPORT_SYMBOL_GPL(fuse_conn_kill); | 371 | EXPORT_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); |