diff options
Diffstat (limited to 'fs/jbd2/commit.c')
-rw-r--r-- | fs/jbd2/commit.c | 88 |
1 files changed, 29 insertions, 59 deletions
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 7c068c189d80..f3ad1598b201 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
@@ -26,7 +26,9 @@ | |||
26 | #include <linux/backing-dev.h> | 26 | #include <linux/backing-dev.h> |
27 | #include <linux/bio.h> | 27 | #include <linux/bio.h> |
28 | #include <linux/blkdev.h> | 28 | #include <linux/blkdev.h> |
29 | #include <linux/bitops.h> | ||
29 | #include <trace/events/jbd2.h> | 30 | #include <trace/events/jbd2.h> |
31 | #include <asm/system.h> | ||
30 | 32 | ||
31 | /* | 33 | /* |
32 | * Default IO end handler for temporary BJ_IO buffer_heads. | 34 | * Default IO end handler for temporary BJ_IO buffer_heads. |
@@ -134,25 +136,11 @@ static int journal_submit_commit_record(journal_t *journal, | |||
134 | 136 | ||
135 | if (journal->j_flags & JBD2_BARRIER && | 137 | if (journal->j_flags & JBD2_BARRIER && |
136 | !JBD2_HAS_INCOMPAT_FEATURE(journal, | 138 | !JBD2_HAS_INCOMPAT_FEATURE(journal, |
137 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) { | 139 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT)) |
138 | ret = submit_bh(WRITE_SYNC_PLUG | WRITE_BARRIER, bh); | 140 | ret = submit_bh(WRITE_SYNC_PLUG | WRITE_FLUSH_FUA, bh); |
139 | if (ret == -EOPNOTSUPP) { | 141 | else |
140 | printk(KERN_WARNING | ||
141 | "JBD2: Disabling barriers on %s, " | ||
142 | "not supported by device\n", journal->j_devname); | ||
143 | write_lock(&journal->j_state_lock); | ||
144 | journal->j_flags &= ~JBD2_BARRIER; | ||
145 | write_unlock(&journal->j_state_lock); | ||
146 | |||
147 | /* And try again, without the barrier */ | ||
148 | lock_buffer(bh); | ||
149 | set_buffer_uptodate(bh); | ||
150 | clear_buffer_dirty(bh); | ||
151 | ret = submit_bh(WRITE_SYNC_PLUG, bh); | ||
152 | } | ||
153 | } else { | ||
154 | ret = submit_bh(WRITE_SYNC_PLUG, bh); | 142 | ret = submit_bh(WRITE_SYNC_PLUG, bh); |
155 | } | 143 | |
156 | *cbh = bh; | 144 | *cbh = bh; |
157 | return ret; | 145 | return ret; |
158 | } | 146 | } |
@@ -166,29 +154,8 @@ static int journal_wait_on_commit_record(journal_t *journal, | |||
166 | { | 154 | { |
167 | int ret = 0; | 155 | int ret = 0; |
168 | 156 | ||
169 | retry: | ||
170 | clear_buffer_dirty(bh); | 157 | clear_buffer_dirty(bh); |
171 | wait_on_buffer(bh); | 158 | wait_on_buffer(bh); |
172 | if (buffer_eopnotsupp(bh) && (journal->j_flags & JBD2_BARRIER)) { | ||
173 | printk(KERN_WARNING | ||
174 | "JBD2: %s: disabling barries on %s - not supported " | ||
175 | "by device\n", __func__, journal->j_devname); | ||
176 | write_lock(&journal->j_state_lock); | ||
177 | journal->j_flags &= ~JBD2_BARRIER; | ||
178 | write_unlock(&journal->j_state_lock); | ||
179 | |||
180 | lock_buffer(bh); | ||
181 | clear_buffer_dirty(bh); | ||
182 | set_buffer_uptodate(bh); | ||
183 | bh->b_end_io = journal_end_buffer_io_sync; | ||
184 | |||
185 | ret = submit_bh(WRITE_SYNC_PLUG, bh); | ||
186 | if (ret) { | ||
187 | unlock_buffer(bh); | ||
188 | return ret; | ||
189 | } | ||
190 | goto retry; | ||
191 | } | ||
192 | 159 | ||
193 | if (unlikely(!buffer_uptodate(bh))) | 160 | if (unlikely(!buffer_uptodate(bh))) |
194 | ret = -EIO; | 161 | ret = -EIO; |
@@ -236,7 +203,7 @@ static int journal_submit_data_buffers(journal_t *journal, | |||
236 | spin_lock(&journal->j_list_lock); | 203 | spin_lock(&journal->j_list_lock); |
237 | list_for_each_entry(jinode, &commit_transaction->t_inode_list, i_list) { | 204 | list_for_each_entry(jinode, &commit_transaction->t_inode_list, i_list) { |
238 | mapping = jinode->i_vfs_inode->i_mapping; | 205 | mapping = jinode->i_vfs_inode->i_mapping; |
239 | jinode->i_flags |= JI_COMMIT_RUNNING; | 206 | set_bit(__JI_COMMIT_RUNNING, &jinode->i_flags); |
240 | spin_unlock(&journal->j_list_lock); | 207 | spin_unlock(&journal->j_list_lock); |
241 | /* | 208 | /* |
242 | * submit the inode data buffers. We use writepage | 209 | * submit the inode data buffers. We use writepage |
@@ -251,7 +218,8 @@ static int journal_submit_data_buffers(journal_t *journal, | |||
251 | spin_lock(&journal->j_list_lock); | 218 | spin_lock(&journal->j_list_lock); |
252 | J_ASSERT(jinode->i_transaction == commit_transaction); | 219 | J_ASSERT(jinode->i_transaction == commit_transaction); |
253 | commit_transaction->t_flushed_data_blocks = 1; | 220 | commit_transaction->t_flushed_data_blocks = 1; |
254 | jinode->i_flags &= ~JI_COMMIT_RUNNING; | 221 | clear_bit(__JI_COMMIT_RUNNING, &jinode->i_flags); |
222 | smp_mb__after_clear_bit(); | ||
255 | wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING); | 223 | wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING); |
256 | } | 224 | } |
257 | spin_unlock(&journal->j_list_lock); | 225 | spin_unlock(&journal->j_list_lock); |
@@ -272,7 +240,7 @@ static int journal_finish_inode_data_buffers(journal_t *journal, | |||
272 | /* For locking, see the comment in journal_submit_data_buffers() */ | 240 | /* For locking, see the comment in journal_submit_data_buffers() */ |
273 | spin_lock(&journal->j_list_lock); | 241 | spin_lock(&journal->j_list_lock); |
274 | list_for_each_entry(jinode, &commit_transaction->t_inode_list, i_list) { | 242 | list_for_each_entry(jinode, &commit_transaction->t_inode_list, i_list) { |
275 | jinode->i_flags |= JI_COMMIT_RUNNING; | 243 | set_bit(__JI_COMMIT_RUNNING, &jinode->i_flags); |
276 | spin_unlock(&journal->j_list_lock); | 244 | spin_unlock(&journal->j_list_lock); |
277 | err = filemap_fdatawait(jinode->i_vfs_inode->i_mapping); | 245 | err = filemap_fdatawait(jinode->i_vfs_inode->i_mapping); |
278 | if (err) { | 246 | if (err) { |
@@ -288,7 +256,8 @@ static int journal_finish_inode_data_buffers(journal_t *journal, | |||
288 | ret = err; | 256 | ret = err; |
289 | } | 257 | } |
290 | spin_lock(&journal->j_list_lock); | 258 | spin_lock(&journal->j_list_lock); |
291 | jinode->i_flags &= ~JI_COMMIT_RUNNING; | 259 | clear_bit(__JI_COMMIT_RUNNING, &jinode->i_flags); |
260 | smp_mb__after_clear_bit(); | ||
292 | wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING); | 261 | wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING); |
293 | } | 262 | } |
294 | 263 | ||
@@ -360,7 +329,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) | |||
360 | int tag_bytes = journal_tag_bytes(journal); | 329 | int tag_bytes = journal_tag_bytes(journal); |
361 | struct buffer_head *cbh = NULL; /* For transactional checksums */ | 330 | struct buffer_head *cbh = NULL; /* For transactional checksums */ |
362 | __u32 crc32_sum = ~0; | 331 | __u32 crc32_sum = ~0; |
363 | int write_op = WRITE; | 332 | int write_op = WRITE_SYNC; |
364 | 333 | ||
365 | /* | 334 | /* |
366 | * First job: lock down the current transaction and wait for | 335 | * First job: lock down the current transaction and wait for |
@@ -701,6 +670,16 @@ start_journal_io: | |||
701 | } | 670 | } |
702 | } | 671 | } |
703 | 672 | ||
673 | err = journal_finish_inode_data_buffers(journal, commit_transaction); | ||
674 | if (err) { | ||
675 | printk(KERN_WARNING | ||
676 | "JBD2: Detected IO errors while flushing file data " | ||
677 | "on %s\n", journal->j_devname); | ||
678 | if (journal->j_flags & JBD2_ABORT_ON_SYNCDATA_ERR) | ||
679 | jbd2_journal_abort(journal, err); | ||
680 | err = 0; | ||
681 | } | ||
682 | |||
704 | /* | 683 | /* |
705 | * If the journal is not located on the file system device, | 684 | * If the journal is not located on the file system device, |
706 | * then we must flush the file system device before we issue | 685 | * then we must flush the file system device before we issue |
@@ -709,8 +688,7 @@ start_journal_io: | |||
709 | if (commit_transaction->t_flushed_data_blocks && | 688 | if (commit_transaction->t_flushed_data_blocks && |
710 | (journal->j_fs_dev != journal->j_dev) && | 689 | (journal->j_fs_dev != journal->j_dev) && |
711 | (journal->j_flags & JBD2_BARRIER)) | 690 | (journal->j_flags & JBD2_BARRIER)) |
712 | blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL, | 691 | blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); |
713 | BLKDEV_IFL_WAIT); | ||
714 | 692 | ||
715 | /* Done it all: now write the commit record asynchronously. */ | 693 | /* Done it all: now write the commit record asynchronously. */ |
716 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, | 694 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, |
@@ -719,19 +697,6 @@ start_journal_io: | |||
719 | &cbh, crc32_sum); | 697 | &cbh, crc32_sum); |
720 | if (err) | 698 | if (err) |
721 | __jbd2_journal_abort_hard(journal); | 699 | __jbd2_journal_abort_hard(journal); |
722 | if (journal->j_flags & JBD2_BARRIER) | ||
723 | blkdev_issue_flush(journal->j_dev, GFP_KERNEL, NULL, | ||
724 | BLKDEV_IFL_WAIT); | ||
725 | } | ||
726 | |||
727 | err = journal_finish_inode_data_buffers(journal, commit_transaction); | ||
728 | if (err) { | ||
729 | printk(KERN_WARNING | ||
730 | "JBD2: Detected IO errors while flushing file data " | ||
731 | "on %s\n", journal->j_devname); | ||
732 | if (journal->j_flags & JBD2_ABORT_ON_SYNCDATA_ERR) | ||
733 | jbd2_journal_abort(journal, err); | ||
734 | err = 0; | ||
735 | } | 700 | } |
736 | 701 | ||
737 | /* Lo and behold: we have just managed to send a transaction to | 702 | /* Lo and behold: we have just managed to send a transaction to |
@@ -845,6 +810,11 @@ wait_for_iobuf: | |||
845 | } | 810 | } |
846 | if (!err && !is_journal_aborted(journal)) | 811 | if (!err && !is_journal_aborted(journal)) |
847 | err = journal_wait_on_commit_record(journal, cbh); | 812 | err = journal_wait_on_commit_record(journal, cbh); |
813 | if (JBD2_HAS_INCOMPAT_FEATURE(journal, | ||
814 | JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT) && | ||
815 | journal->j_flags & JBD2_BARRIER) { | ||
816 | blkdev_issue_flush(journal->j_dev, GFP_KERNEL, NULL); | ||
817 | } | ||
848 | 818 | ||
849 | if (err) | 819 | if (err) |
850 | jbd2_journal_abort(journal, err); | 820 | jbd2_journal_abort(journal, err); |