.. | .. |
---|
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 | } |
---|