| .. | .. |
|---|
| 78 | 78 | return ret; |
|---|
| 79 | 79 | } |
|---|
| 80 | 80 | |
|---|
| 81 | +static int ext4_fsync_nojournal(struct inode *inode, bool datasync, |
|---|
| 82 | + bool *needs_barrier) |
|---|
| 83 | +{ |
|---|
| 84 | + int ret, err; |
|---|
| 85 | + |
|---|
| 86 | + ret = sync_mapping_buffers(inode->i_mapping); |
|---|
| 87 | + if (!(inode->i_state & I_DIRTY_ALL)) |
|---|
| 88 | + return ret; |
|---|
| 89 | + if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) |
|---|
| 90 | + return ret; |
|---|
| 91 | + |
|---|
| 92 | + err = sync_inode_metadata(inode, 1); |
|---|
| 93 | + if (!ret) |
|---|
| 94 | + ret = err; |
|---|
| 95 | + |
|---|
| 96 | + if (!ret) |
|---|
| 97 | + ret = ext4_sync_parent(inode); |
|---|
| 98 | + if (test_opt(inode->i_sb, BARRIER)) |
|---|
| 99 | + *needs_barrier = true; |
|---|
| 100 | + |
|---|
| 101 | + return ret; |
|---|
| 102 | +} |
|---|
| 103 | + |
|---|
| 104 | +static int ext4_fsync_journal(struct inode *inode, bool datasync, |
|---|
| 105 | + bool *needs_barrier) |
|---|
| 106 | +{ |
|---|
| 107 | + struct ext4_inode_info *ei = EXT4_I(inode); |
|---|
| 108 | + journal_t *journal = EXT4_SB(inode->i_sb)->s_journal; |
|---|
| 109 | + tid_t commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid; |
|---|
| 110 | + |
|---|
| 111 | + if (journal->j_flags & JBD2_BARRIER && |
|---|
| 112 | + !jbd2_trans_will_send_data_barrier(journal, commit_tid)) |
|---|
| 113 | + *needs_barrier = true; |
|---|
| 114 | + |
|---|
| 115 | + return ext4_fc_commit(journal, commit_tid); |
|---|
| 116 | +} |
|---|
| 117 | + |
|---|
| 81 | 118 | /* |
|---|
| 82 | 119 | * akpm: A new design for ext4_sync_file(). |
|---|
| 83 | 120 | * |
|---|
| .. | .. |
|---|
| 89 | 126 | * What we do is just kick off a commit and wait on it. This will snapshot the |
|---|
| 90 | 127 | * inode to disk. |
|---|
| 91 | 128 | */ |
|---|
| 92 | | - |
|---|
| 93 | 129 | int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync) |
|---|
| 94 | 130 | { |
|---|
| 95 | | - struct inode *inode = file->f_mapping->host; |
|---|
| 96 | | - struct ext4_inode_info *ei = EXT4_I(inode); |
|---|
| 97 | | - journal_t *journal = EXT4_SB(inode->i_sb)->s_journal; |
|---|
| 98 | 131 | int ret = 0, err; |
|---|
| 99 | | - tid_t commit_tid; |
|---|
| 100 | 132 | bool needs_barrier = false; |
|---|
| 133 | + struct inode *inode = file->f_mapping->host; |
|---|
| 134 | + struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); |
|---|
| 101 | 135 | |
|---|
| 102 | | - if (unlikely(ext4_forced_shutdown(EXT4_SB(inode->i_sb)))) |
|---|
| 136 | + if (unlikely(ext4_forced_shutdown(sbi))) |
|---|
| 103 | 137 | return -EIO; |
|---|
| 104 | 138 | |
|---|
| 105 | 139 | J_ASSERT(ext4_journal_current_handle() == NULL); |
|---|
| .. | .. |
|---|
| 109 | 143 | if (sb_rdonly(inode->i_sb)) { |
|---|
| 110 | 144 | /* Make sure that we read updated s_mount_flags value */ |
|---|
| 111 | 145 | smp_rmb(); |
|---|
| 112 | | - if (EXT4_SB(inode->i_sb)->s_mount_flags & EXT4_MF_FS_ABORTED) |
|---|
| 146 | + if (ext4_test_mount_flag(inode->i_sb, EXT4_MF_FS_ABORTED)) |
|---|
| 113 | 147 | ret = -EROFS; |
|---|
| 114 | | - goto out; |
|---|
| 115 | | - } |
|---|
| 116 | | - |
|---|
| 117 | | - if (!journal) { |
|---|
| 118 | | - ret = __generic_file_fsync(file, start, end, datasync); |
|---|
| 119 | | - if (!ret) |
|---|
| 120 | | - ret = ext4_sync_parent(inode); |
|---|
| 121 | | - if (test_opt(inode->i_sb, BARRIER)) |
|---|
| 122 | | - goto issue_flush; |
|---|
| 123 | 148 | goto out; |
|---|
| 124 | 149 | } |
|---|
| 125 | 150 | |
|---|
| 126 | 151 | ret = file_write_and_wait_range(file, start, end); |
|---|
| 127 | 152 | if (ret) |
|---|
| 128 | | - return ret; |
|---|
| 153 | + goto out; |
|---|
| 154 | + |
|---|
| 129 | 155 | /* |
|---|
| 130 | 156 | * data=writeback,ordered: |
|---|
| 131 | 157 | * The caller's filemap_fdatawrite()/wait will sync the data. |
|---|
| .. | .. |
|---|
| 140 | 166 | * (they were dirtied by commit). But that's OK - the blocks are |
|---|
| 141 | 167 | * safe in-journal, which is all fsync() needs to ensure. |
|---|
| 142 | 168 | */ |
|---|
| 143 | | - if (ext4_should_journal_data(inode)) { |
|---|
| 169 | + if (!sbi->s_journal) |
|---|
| 170 | + ret = ext4_fsync_nojournal(inode, datasync, &needs_barrier); |
|---|
| 171 | + else if (ext4_should_journal_data(inode)) |
|---|
| 144 | 172 | ret = ext4_force_commit(inode->i_sb); |
|---|
| 145 | | - goto out; |
|---|
| 146 | | - } |
|---|
| 173 | + else |
|---|
| 174 | + ret = ext4_fsync_journal(inode, datasync, &needs_barrier); |
|---|
| 147 | 175 | |
|---|
| 148 | | - commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid; |
|---|
| 149 | | - if (journal->j_flags & JBD2_BARRIER && |
|---|
| 150 | | - !jbd2_trans_will_send_data_barrier(journal, commit_tid)) |
|---|
| 151 | | - needs_barrier = true; |
|---|
| 152 | | - ret = jbd2_complete_transaction(journal, commit_tid); |
|---|
| 153 | 176 | if (needs_barrier) { |
|---|
| 154 | | - issue_flush: |
|---|
| 155 | | - err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); |
|---|
| 177 | + err = blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL); |
|---|
| 156 | 178 | if (!ret) |
|---|
| 157 | 179 | ret = err; |
|---|
| 158 | 180 | } |
|---|