diff options
Diffstat (limited to 'fs/jbd2')
-rw-r--r-- | fs/jbd2/checkpoint.c | 13 | ||||
-rw-r--r-- | fs/jbd2/commit.c | 88 | ||||
-rw-r--r-- | fs/jbd2/journal.c | 18 | ||||
-rw-r--r-- | fs/jbd2/transaction.c | 1 |
4 files changed, 53 insertions, 67 deletions
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 5247e7ffdcb4..6a79fd0a1a32 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c | |||
@@ -299,6 +299,16 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, | |||
299 | transaction->t_chp_stats.cs_forced_to_close++; | 299 | transaction->t_chp_stats.cs_forced_to_close++; |
300 | spin_unlock(&journal->j_list_lock); | 300 | spin_unlock(&journal->j_list_lock); |
301 | jbd_unlock_bh_state(bh); | 301 | jbd_unlock_bh_state(bh); |
302 | if (unlikely(journal->j_flags & JBD2_UNMOUNT)) | ||
303 | /* | ||
304 | * The journal thread is dead; so starting and | ||
305 | * waiting for a commit to finish will cause | ||
306 | * us to wait for a _very_ long time. | ||
307 | */ | ||
308 | printk(KERN_ERR "JBD2: %s: " | ||
309 | "Waiting for Godot: block %llu\n", | ||
310 | journal->j_devname, | ||
311 | (unsigned long long) bh->b_blocknr); | ||
302 | jbd2_log_start_commit(journal, tid); | 312 | jbd2_log_start_commit(journal, tid); |
303 | jbd2_log_wait_commit(journal, tid); | 313 | jbd2_log_wait_commit(journal, tid); |
304 | ret = 1; | 314 | ret = 1; |
@@ -532,8 +542,7 @@ int jbd2_cleanup_journal_tail(journal_t *journal) | |||
532 | */ | 542 | */ |
533 | if ((journal->j_fs_dev != journal->j_dev) && | 543 | if ((journal->j_fs_dev != journal->j_dev) && |
534 | (journal->j_flags & JBD2_BARRIER)) | 544 | (journal->j_flags & JBD2_BARRIER)) |
535 | blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL, | 545 | blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); |
536 | BLKDEV_IFL_WAIT); | ||
537 | if (!(journal->j_flags & JBD2_ABORT)) | 546 | if (!(journal->j_flags & JBD2_ABORT)) |
538 | jbd2_journal_update_superblock(journal, 1); | 547 | jbd2_journal_update_superblock(journal, 1); |
539 | return 0; | 548 | return 0; |
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); |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 0e8014ea6b94..c590d155c095 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
@@ -42,12 +42,14 @@ | |||
42 | #include <linux/log2.h> | 42 | #include <linux/log2.h> |
43 | #include <linux/vmalloc.h> | 43 | #include <linux/vmalloc.h> |
44 | #include <linux/backing-dev.h> | 44 | #include <linux/backing-dev.h> |
45 | #include <linux/bitops.h> | ||
45 | 46 | ||
46 | #define CREATE_TRACE_POINTS | 47 | #define CREATE_TRACE_POINTS |
47 | #include <trace/events/jbd2.h> | 48 | #include <trace/events/jbd2.h> |
48 | 49 | ||
49 | #include <asm/uaccess.h> | 50 | #include <asm/uaccess.h> |
50 | #include <asm/page.h> | 51 | #include <asm/page.h> |
52 | #include <asm/system.h> | ||
51 | 53 | ||
52 | EXPORT_SYMBOL(jbd2_journal_extend); | 54 | EXPORT_SYMBOL(jbd2_journal_extend); |
53 | EXPORT_SYMBOL(jbd2_journal_stop); | 55 | EXPORT_SYMBOL(jbd2_journal_stop); |
@@ -478,7 +480,7 @@ int __jbd2_log_start_commit(journal_t *journal, tid_t target) | |||
478 | */ | 480 | */ |
479 | if (!tid_geq(journal->j_commit_request, target)) { | 481 | if (!tid_geq(journal->j_commit_request, target)) { |
480 | /* | 482 | /* |
481 | * We want a new commit: OK, mark the request and wakup the | 483 | * We want a new commit: OK, mark the request and wakeup the |
482 | * commit thread. We do _not_ do the commit ourselves. | 484 | * commit thread. We do _not_ do the commit ourselves. |
483 | */ | 485 | */ |
484 | 486 | ||
@@ -1371,6 +1373,10 @@ int jbd2_journal_check_used_features (journal_t *journal, unsigned long compat, | |||
1371 | 1373 | ||
1372 | if (!compat && !ro && !incompat) | 1374 | if (!compat && !ro && !incompat) |
1373 | return 1; | 1375 | return 1; |
1376 | /* Load journal superblock if it is not loaded yet. */ | ||
1377 | if (journal->j_format_version == 0 && | ||
1378 | journal_get_superblock(journal) != 0) | ||
1379 | return 0; | ||
1374 | if (journal->j_format_version == 1) | 1380 | if (journal->j_format_version == 1) |
1375 | return 0; | 1381 | return 0; |
1376 | 1382 | ||
@@ -1832,7 +1838,6 @@ size_t journal_tag_bytes(journal_t *journal) | |||
1832 | */ | 1838 | */ |
1833 | #define JBD2_MAX_SLABS 8 | 1839 | #define JBD2_MAX_SLABS 8 |
1834 | static struct kmem_cache *jbd2_slab[JBD2_MAX_SLABS]; | 1840 | static struct kmem_cache *jbd2_slab[JBD2_MAX_SLABS]; |
1835 | static DECLARE_MUTEX(jbd2_slab_create_sem); | ||
1836 | 1841 | ||
1837 | static const char *jbd2_slab_names[JBD2_MAX_SLABS] = { | 1842 | static const char *jbd2_slab_names[JBD2_MAX_SLABS] = { |
1838 | "jbd2_1k", "jbd2_2k", "jbd2_4k", "jbd2_8k", | 1843 | "jbd2_1k", "jbd2_2k", "jbd2_4k", "jbd2_8k", |
@@ -1853,6 +1858,7 @@ static void jbd2_journal_destroy_slabs(void) | |||
1853 | 1858 | ||
1854 | static int jbd2_journal_create_slab(size_t size) | 1859 | static int jbd2_journal_create_slab(size_t size) |
1855 | { | 1860 | { |
1861 | static DEFINE_MUTEX(jbd2_slab_create_mutex); | ||
1856 | int i = order_base_2(size) - 10; | 1862 | int i = order_base_2(size) - 10; |
1857 | size_t slab_size; | 1863 | size_t slab_size; |
1858 | 1864 | ||
@@ -1864,16 +1870,16 @@ static int jbd2_journal_create_slab(size_t size) | |||
1864 | 1870 | ||
1865 | if (unlikely(i < 0)) | 1871 | if (unlikely(i < 0)) |
1866 | i = 0; | 1872 | i = 0; |
1867 | down(&jbd2_slab_create_sem); | 1873 | mutex_lock(&jbd2_slab_create_mutex); |
1868 | if (jbd2_slab[i]) { | 1874 | if (jbd2_slab[i]) { |
1869 | up(&jbd2_slab_create_sem); | 1875 | mutex_unlock(&jbd2_slab_create_mutex); |
1870 | return 0; /* Already created */ | 1876 | return 0; /* Already created */ |
1871 | } | 1877 | } |
1872 | 1878 | ||
1873 | slab_size = 1 << (i+10); | 1879 | slab_size = 1 << (i+10); |
1874 | jbd2_slab[i] = kmem_cache_create(jbd2_slab_names[i], slab_size, | 1880 | jbd2_slab[i] = kmem_cache_create(jbd2_slab_names[i], slab_size, |
1875 | slab_size, 0, NULL); | 1881 | slab_size, 0, NULL); |
1876 | up(&jbd2_slab_create_sem); | 1882 | mutex_unlock(&jbd2_slab_create_mutex); |
1877 | if (!jbd2_slab[i]) { | 1883 | if (!jbd2_slab[i]) { |
1878 | printk(KERN_EMERG "JBD2: no memory for jbd2_slab cache\n"); | 1884 | printk(KERN_EMERG "JBD2: no memory for jbd2_slab cache\n"); |
1879 | return -ENOMEM; | 1885 | return -ENOMEM; |
@@ -2206,7 +2212,7 @@ void jbd2_journal_release_jbd_inode(journal_t *journal, | |||
2206 | restart: | 2212 | restart: |
2207 | spin_lock(&journal->j_list_lock); | 2213 | spin_lock(&journal->j_list_lock); |
2208 | /* Is commit writing out inode - we have to wait */ | 2214 | /* Is commit writing out inode - we have to wait */ |
2209 | if (jinode->i_flags & JI_COMMIT_RUNNING) { | 2215 | if (test_bit(__JI_COMMIT_RUNNING, &jinode->i_flags)) { |
2210 | wait_queue_head_t *wq; | 2216 | wait_queue_head_t *wq; |
2211 | DEFINE_WAIT_BIT(wait, &jinode->i_flags, __JI_COMMIT_RUNNING); | 2217 | DEFINE_WAIT_BIT(wait, &jinode->i_flags, __JI_COMMIT_RUNNING); |
2212 | wq = bit_waitqueue(&jinode->i_flags, __JI_COMMIT_RUNNING); | 2218 | wq = bit_waitqueue(&jinode->i_flags, __JI_COMMIT_RUNNING); |
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index f3479d6e0a83..6bf0a242613e 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
@@ -156,6 +156,7 @@ alloc_transaction: | |||
156 | */ | 156 | */ |
157 | repeat: | 157 | repeat: |
158 | read_lock(&journal->j_state_lock); | 158 | read_lock(&journal->j_state_lock); |
159 | BUG_ON(journal->j_flags & JBD2_UNMOUNT); | ||
159 | if (is_journal_aborted(journal) || | 160 | if (is_journal_aborted(journal) || |
160 | (journal->j_errno != 0 && !(journal->j_flags & JBD2_ACK_ERR))) { | 161 | (journal->j_errno != 0 && !(journal->j_flags & JBD2_ACK_ERR))) { |
161 | read_unlock(&journal->j_state_lock); | 162 | read_unlock(&journal->j_state_lock); |