diff options
Diffstat (limited to 'fs/fuse/file.c')
-rw-r--r-- | fs/fuse/file.c | 84 |
1 files changed, 53 insertions, 31 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 13f8bdec5110..96d513e01a5d 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -223,6 +223,8 @@ void fuse_finish_open(struct inode *inode, struct file *file) | |||
223 | i_size_write(inode, 0); | 223 | i_size_write(inode, 0); |
224 | spin_unlock(&fc->lock); | 224 | spin_unlock(&fc->lock); |
225 | fuse_invalidate_attr(inode); | 225 | fuse_invalidate_attr(inode); |
226 | if (fc->writeback_cache) | ||
227 | file_update_time(file); | ||
226 | } | 228 | } |
227 | if ((file->f_mode & FMODE_WRITE) && fc->writeback_cache) | 229 | if ((file->f_mode & FMODE_WRITE) && fc->writeback_cache) |
228 | fuse_link_write_file(file); | 230 | fuse_link_write_file(file); |
@@ -232,18 +234,26 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir) | |||
232 | { | 234 | { |
233 | struct fuse_conn *fc = get_fuse_conn(inode); | 235 | struct fuse_conn *fc = get_fuse_conn(inode); |
234 | int err; | 236 | int err; |
237 | bool lock_inode = (file->f_flags & O_TRUNC) && | ||
238 | fc->atomic_o_trunc && | ||
239 | fc->writeback_cache; | ||
235 | 240 | ||
236 | err = generic_file_open(inode, file); | 241 | err = generic_file_open(inode, file); |
237 | if (err) | 242 | if (err) |
238 | return err; | 243 | return err; |
239 | 244 | ||
245 | if (lock_inode) | ||
246 | mutex_lock(&inode->i_mutex); | ||
247 | |||
240 | err = fuse_do_open(fc, get_node_id(inode), file, isdir); | 248 | err = fuse_do_open(fc, get_node_id(inode), file, isdir); |
241 | if (err) | ||
242 | return err; | ||
243 | 249 | ||
244 | fuse_finish_open(inode, file); | 250 | if (!err) |
251 | fuse_finish_open(inode, file); | ||
245 | 252 | ||
246 | return 0; | 253 | if (lock_inode) |
254 | mutex_unlock(&inode->i_mutex); | ||
255 | |||
256 | return err; | ||
247 | } | 257 | } |
248 | 258 | ||
249 | static void fuse_prepare_release(struct fuse_file *ff, int flags, int opcode) | 259 | static void fuse_prepare_release(struct fuse_file *ff, int flags, int opcode) |
@@ -314,10 +324,7 @@ static int fuse_release(struct inode *inode, struct file *file) | |||
314 | 324 | ||
315 | /* see fuse_vma_close() for !writeback_cache case */ | 325 | /* see fuse_vma_close() for !writeback_cache case */ |
316 | if (fc->writeback_cache) | 326 | if (fc->writeback_cache) |
317 | filemap_write_and_wait(file->f_mapping); | 327 | write_inode_now(inode, 1); |
318 | |||
319 | if (test_bit(FUSE_I_MTIME_DIRTY, &get_fuse_inode(inode)->state)) | ||
320 | fuse_flush_mtime(file, true); | ||
321 | 328 | ||
322 | fuse_release_common(file, FUSE_RELEASE); | 329 | fuse_release_common(file, FUSE_RELEASE); |
323 | 330 | ||
@@ -439,7 +446,7 @@ static int fuse_flush(struct file *file, fl_owner_t id) | |||
439 | if (fc->no_flush) | 446 | if (fc->no_flush) |
440 | return 0; | 447 | return 0; |
441 | 448 | ||
442 | err = filemap_write_and_wait(file->f_mapping); | 449 | err = write_inode_now(inode, 1); |
443 | if (err) | 450 | if (err) |
444 | return err; | 451 | return err; |
445 | 452 | ||
@@ -480,13 +487,6 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end, | |||
480 | if (is_bad_inode(inode)) | 487 | if (is_bad_inode(inode)) |
481 | return -EIO; | 488 | return -EIO; |
482 | 489 | ||
483 | err = filemap_write_and_wait_range(inode->i_mapping, start, end); | ||
484 | if (err) | ||
485 | return err; | ||
486 | |||
487 | if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir)) | ||
488 | return 0; | ||
489 | |||
490 | mutex_lock(&inode->i_mutex); | 490 | mutex_lock(&inode->i_mutex); |
491 | 491 | ||
492 | /* | 492 | /* |
@@ -494,17 +494,17 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end, | |||
494 | * wait for all outstanding writes, before sending the FSYNC | 494 | * wait for all outstanding writes, before sending the FSYNC |
495 | * request. | 495 | * request. |
496 | */ | 496 | */ |
497 | err = write_inode_now(inode, 0); | 497 | err = filemap_write_and_wait_range(inode->i_mapping, start, end); |
498 | if (err) | 498 | if (err) |
499 | goto out; | 499 | goto out; |
500 | 500 | ||
501 | fuse_sync_writes(inode); | 501 | fuse_sync_writes(inode); |
502 | err = sync_inode_metadata(inode, 1); | ||
503 | if (err) | ||
504 | goto out; | ||
502 | 505 | ||
503 | if (test_bit(FUSE_I_MTIME_DIRTY, &get_fuse_inode(inode)->state)) { | 506 | if ((!isdir && fc->no_fsync) || (isdir && fc->no_fsyncdir)) |
504 | int err = fuse_flush_mtime(file, false); | 507 | goto out; |
505 | if (err) | ||
506 | goto out; | ||
507 | } | ||
508 | 508 | ||
509 | req = fuse_get_req_nopages(fc); | 509 | req = fuse_get_req_nopages(fc); |
510 | if (IS_ERR(req)) { | 510 | if (IS_ERR(req)) { |
@@ -1659,13 +1659,13 @@ static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_req *req) | |||
1659 | fuse_writepage_free(fc, req); | 1659 | fuse_writepage_free(fc, req); |
1660 | } | 1660 | } |
1661 | 1661 | ||
1662 | static struct fuse_file *fuse_write_file_get(struct fuse_conn *fc, | 1662 | static struct fuse_file *__fuse_write_file_get(struct fuse_conn *fc, |
1663 | struct fuse_inode *fi) | 1663 | struct fuse_inode *fi) |
1664 | { | 1664 | { |
1665 | struct fuse_file *ff = NULL; | 1665 | struct fuse_file *ff = NULL; |
1666 | 1666 | ||
1667 | spin_lock(&fc->lock); | 1667 | spin_lock(&fc->lock); |
1668 | if (!WARN_ON(list_empty(&fi->write_files))) { | 1668 | if (!list_empty(&fi->write_files)) { |
1669 | ff = list_entry(fi->write_files.next, struct fuse_file, | 1669 | ff = list_entry(fi->write_files.next, struct fuse_file, |
1670 | write_entry); | 1670 | write_entry); |
1671 | fuse_file_get(ff); | 1671 | fuse_file_get(ff); |
@@ -1675,6 +1675,29 @@ static struct fuse_file *fuse_write_file_get(struct fuse_conn *fc, | |||
1675 | return ff; | 1675 | return ff; |
1676 | } | 1676 | } |
1677 | 1677 | ||
1678 | static struct fuse_file *fuse_write_file_get(struct fuse_conn *fc, | ||
1679 | struct fuse_inode *fi) | ||
1680 | { | ||
1681 | struct fuse_file *ff = __fuse_write_file_get(fc, fi); | ||
1682 | WARN_ON(!ff); | ||
1683 | return ff; | ||
1684 | } | ||
1685 | |||
1686 | int fuse_write_inode(struct inode *inode, struct writeback_control *wbc) | ||
1687 | { | ||
1688 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
1689 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
1690 | struct fuse_file *ff; | ||
1691 | int err; | ||
1692 | |||
1693 | ff = __fuse_write_file_get(fc, fi); | ||
1694 | err = fuse_flush_times(inode, ff); | ||
1695 | if (ff) | ||
1696 | fuse_file_put(ff, 0); | ||
1697 | |||
1698 | return err; | ||
1699 | } | ||
1700 | |||
1678 | static int fuse_writepage_locked(struct page *page) | 1701 | static int fuse_writepage_locked(struct page *page) |
1679 | { | 1702 | { |
1680 | struct address_space *mapping = page->mapping; | 1703 | struct address_space *mapping = page->mapping; |
@@ -2972,6 +2995,9 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, | |||
2972 | bool lock_inode = !(mode & FALLOC_FL_KEEP_SIZE) || | 2995 | bool lock_inode = !(mode & FALLOC_FL_KEEP_SIZE) || |
2973 | (mode & FALLOC_FL_PUNCH_HOLE); | 2996 | (mode & FALLOC_FL_PUNCH_HOLE); |
2974 | 2997 | ||
2998 | if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) | ||
2999 | return -EOPNOTSUPP; | ||
3000 | |||
2975 | if (fc->no_fallocate) | 3001 | if (fc->no_fallocate) |
2976 | return -EOPNOTSUPP; | 3002 | return -EOPNOTSUPP; |
2977 | 3003 | ||
@@ -3017,12 +3043,8 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, | |||
3017 | if (!(mode & FALLOC_FL_KEEP_SIZE)) { | 3043 | if (!(mode & FALLOC_FL_KEEP_SIZE)) { |
3018 | bool changed = fuse_write_update_size(inode, offset + length); | 3044 | bool changed = fuse_write_update_size(inode, offset + length); |
3019 | 3045 | ||
3020 | if (changed && fc->writeback_cache) { | 3046 | if (changed && fc->writeback_cache) |
3021 | struct fuse_inode *fi = get_fuse_inode(inode); | 3047 | file_update_time(file); |
3022 | |||
3023 | inode->i_mtime = current_fs_time(inode->i_sb); | ||
3024 | set_bit(FUSE_I_MTIME_DIRTY, &fi->state); | ||
3025 | } | ||
3026 | } | 3048 | } |
3027 | 3049 | ||
3028 | if (mode & FALLOC_FL_PUNCH_HOLE) | 3050 | if (mode & FALLOC_FL_PUNCH_HOLE) |