diff options
Diffstat (limited to 'fs/ext4/fsync.c')
| -rw-r--r-- | fs/ext4/fsync.c | 54 |
1 files changed, 20 insertions, 34 deletions
diff --git a/fs/ext4/fsync.c b/fs/ext4/fsync.c index 2b1531266ee2..0b22497d92e1 100644 --- a/fs/ext4/fsync.c +++ b/fs/ext4/fsync.c | |||
| @@ -51,25 +51,30 @@ | |||
| 51 | int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync) | 51 | int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync) |
| 52 | { | 52 | { |
| 53 | struct inode *inode = dentry->d_inode; | 53 | struct inode *inode = dentry->d_inode; |
| 54 | struct ext4_inode_info *ei = EXT4_I(inode); | ||
| 54 | journal_t *journal = EXT4_SB(inode->i_sb)->s_journal; | 55 | journal_t *journal = EXT4_SB(inode->i_sb)->s_journal; |
| 55 | int err, ret = 0; | 56 | int ret; |
| 57 | tid_t commit_tid; | ||
| 56 | 58 | ||
| 57 | J_ASSERT(ext4_journal_current_handle() == NULL); | 59 | J_ASSERT(ext4_journal_current_handle() == NULL); |
| 58 | 60 | ||
| 59 | trace_ext4_sync_file(file, dentry, datasync); | 61 | trace_ext4_sync_file(file, dentry, datasync); |
| 60 | 62 | ||
| 63 | if (inode->i_sb->s_flags & MS_RDONLY) | ||
| 64 | return 0; | ||
| 65 | |||
| 61 | ret = flush_aio_dio_completed_IO(inode); | 66 | ret = flush_aio_dio_completed_IO(inode); |
| 62 | if (ret < 0) | 67 | if (ret < 0) |
| 63 | goto out; | 68 | return ret; |
| 69 | |||
| 70 | if (!journal) | ||
| 71 | return simple_fsync(file, dentry, datasync); | ||
| 72 | |||
| 64 | /* | 73 | /* |
| 65 | * data=writeback: | 74 | * data=writeback,ordered: |
| 66 | * The caller's filemap_fdatawrite()/wait will sync the data. | 75 | * The caller's filemap_fdatawrite()/wait will sync the data. |
| 67 | * sync_inode() will sync the metadata | 76 | * Metadata is in the journal, we wait for proper transaction to |
| 68 | * | 77 | * commit here. |
| 69 | * data=ordered: | ||
| 70 | * The caller's filemap_fdatawrite() will write the data and | ||
| 71 | * sync_inode() will write the inode if it is dirty. Then the caller's | ||
| 72 | * filemap_fdatawait() will wait on the pages. | ||
| 73 | * | 78 | * |
| 74 | * data=journal: | 79 | * data=journal: |
| 75 | * filemap_fdatawrite won't do anything (the buffers are clean). | 80 | * filemap_fdatawrite won't do anything (the buffers are clean). |
| @@ -79,32 +84,13 @@ int ext4_sync_file(struct file *file, struct dentry *dentry, int datasync) | |||
| 79 | * (they were dirtied by commit). But that's OK - the blocks are | 84 | * (they were dirtied by commit). But that's OK - the blocks are |
| 80 | * safe in-journal, which is all fsync() needs to ensure. | 85 | * safe in-journal, which is all fsync() needs to ensure. |
| 81 | */ | 86 | */ |
| 82 | if (ext4_should_journal_data(inode)) { | 87 | if (ext4_should_journal_data(inode)) |
| 83 | ret = ext4_force_commit(inode->i_sb); | 88 | return ext4_force_commit(inode->i_sb); |
| 84 | goto out; | ||
| 85 | } | ||
| 86 | 89 | ||
| 87 | if (!journal) | 90 | commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid; |
| 88 | ret = sync_mapping_buffers(inode->i_mapping); | 91 | if (jbd2_log_start_commit(journal, commit_tid)) |
| 89 | 92 | jbd2_log_wait_commit(journal, commit_tid); | |
| 90 | if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) | 93 | else if (journal->j_flags & JBD2_BARRIER) |
| 91 | goto out; | ||
| 92 | |||
| 93 | /* | ||
| 94 | * The VFS has written the file data. If the inode is unaltered | ||
| 95 | * then we need not start a commit. | ||
| 96 | */ | ||
| 97 | if (inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC)) { | ||
| 98 | struct writeback_control wbc = { | ||
| 99 | .sync_mode = WB_SYNC_ALL, | ||
| 100 | .nr_to_write = 0, /* sys_fsync did this */ | ||
| 101 | }; | ||
| 102 | err = sync_inode(inode, &wbc); | ||
| 103 | if (ret == 0) | ||
| 104 | ret = err; | ||
| 105 | } | ||
| 106 | out: | ||
| 107 | if (journal && (journal->j_flags & JBD2_BARRIER)) | ||
| 108 | blkdev_issue_flush(inode->i_sb->s_bdev, NULL); | 94 | blkdev_issue_flush(inode->i_sb->s_bdev, NULL); |
| 109 | return ret; | 95 | return ret; |
| 110 | } | 96 | } |
