diff options
-rw-r--r-- | fs/ext4/ext4_jbd2.c | 8 | ||||
-rw-r--r-- | fs/ext4/extents.c | 10 | ||||
-rw-r--r-- | fs/jbd2/transaction.c | 58 |
3 files changed, 64 insertions, 12 deletions
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c index f5240aa15601..aca179017582 100644 --- a/fs/ext4/ext4_jbd2.c +++ b/fs/ext4/ext4_jbd2.c | |||
@@ -109,9 +109,11 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line, | |||
109 | 109 | ||
110 | if (ext4_handle_valid(handle)) { | 110 | if (ext4_handle_valid(handle)) { |
111 | err = jbd2_journal_dirty_metadata(handle, bh); | 111 | err = jbd2_journal_dirty_metadata(handle, bh); |
112 | if (err) | 112 | if (err) { |
113 | ext4_journal_abort_handle(where, line, __func__, | 113 | /* Errors can only happen if there is a bug */ |
114 | bh, handle, err); | 114 | handle->h_err = err; |
115 | __ext4_journal_stop(where, line, handle); | ||
116 | } | ||
115 | } else { | 117 | } else { |
116 | if (inode) | 118 | if (inode) |
117 | mark_buffer_dirty_inode(bh, inode); | 119 | mark_buffer_dirty_inode(bh, inode); |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 9124cd24e093..2c5216a8d03b 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -96,13 +96,17 @@ static int ext4_ext_get_access(handle_t *handle, struct inode *inode, | |||
96 | * - ENOMEM | 96 | * - ENOMEM |
97 | * - EIO | 97 | * - EIO |
98 | */ | 98 | */ |
99 | static int ext4_ext_dirty(handle_t *handle, struct inode *inode, | 99 | #define ext4_ext_dirty(handle, inode, path) \ |
100 | struct ext4_ext_path *path) | 100 | __ext4_ext_dirty(__func__, __LINE__, (handle), (inode), (path)) |
101 | static int __ext4_ext_dirty(const char *where, unsigned int line, | ||
102 | handle_t *handle, struct inode *inode, | ||
103 | struct ext4_ext_path *path) | ||
101 | { | 104 | { |
102 | int err; | 105 | int err; |
103 | if (path->p_bh) { | 106 | if (path->p_bh) { |
104 | /* path points to block */ | 107 | /* path points to block */ |
105 | err = ext4_handle_dirty_metadata(handle, inode, path->p_bh); | 108 | err = __ext4_handle_dirty_metadata(where, line, handle, |
109 | inode, path->p_bh); | ||
106 | } else { | 110 | } else { |
107 | /* path points to leaf/index in inode body */ | 111 | /* path points to leaf/index in inode body */ |
108 | err = ext4_mark_inode_dirty(handle, inode); | 112 | err = ext4_mark_inode_dirty(handle, inode); |
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 2d7109414cdd..cb56fe9aaabb 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
@@ -1049,6 +1049,10 @@ void jbd2_buffer_abort_trigger(struct journal_head *jh, | |||
1049 | * mark dirty metadata which needs to be journaled as part of the current | 1049 | * mark dirty metadata which needs to be journaled as part of the current |
1050 | * transaction. | 1050 | * transaction. |
1051 | * | 1051 | * |
1052 | * The buffer must have previously had jbd2_journal_get_write_access() | ||
1053 | * called so that it has a valid journal_head attached to the buffer | ||
1054 | * head. | ||
1055 | * | ||
1052 | * The buffer is placed on the transaction's metadata list and is marked | 1056 | * The buffer is placed on the transaction's metadata list and is marked |
1053 | * as belonging to the transaction. | 1057 | * as belonging to the transaction. |
1054 | * | 1058 | * |
@@ -1065,11 +1069,16 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh) | |||
1065 | transaction_t *transaction = handle->h_transaction; | 1069 | transaction_t *transaction = handle->h_transaction; |
1066 | journal_t *journal = transaction->t_journal; | 1070 | journal_t *journal = transaction->t_journal; |
1067 | struct journal_head *jh = bh2jh(bh); | 1071 | struct journal_head *jh = bh2jh(bh); |
1072 | int ret = 0; | ||
1068 | 1073 | ||
1069 | jbd_debug(5, "journal_head %p\n", jh); | 1074 | jbd_debug(5, "journal_head %p\n", jh); |
1070 | JBUFFER_TRACE(jh, "entry"); | 1075 | JBUFFER_TRACE(jh, "entry"); |
1071 | if (is_handle_aborted(handle)) | 1076 | if (is_handle_aborted(handle)) |
1072 | goto out; | 1077 | goto out; |
1078 | if (!buffer_jbd(bh)) { | ||
1079 | ret = -EUCLEAN; | ||
1080 | goto out; | ||
1081 | } | ||
1073 | 1082 | ||
1074 | jbd_lock_bh_state(bh); | 1083 | jbd_lock_bh_state(bh); |
1075 | 1084 | ||
@@ -1093,8 +1102,20 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh) | |||
1093 | */ | 1102 | */ |
1094 | if (jh->b_transaction == transaction && jh->b_jlist == BJ_Metadata) { | 1103 | if (jh->b_transaction == transaction && jh->b_jlist == BJ_Metadata) { |
1095 | JBUFFER_TRACE(jh, "fastpath"); | 1104 | JBUFFER_TRACE(jh, "fastpath"); |
1096 | J_ASSERT_JH(jh, jh->b_transaction == | 1105 | if (unlikely(jh->b_transaction != |
1097 | journal->j_running_transaction); | 1106 | journal->j_running_transaction)) { |
1107 | printk(KERN_EMERG "JBD: %s: " | ||
1108 | "jh->b_transaction (%llu, %p, %u) != " | ||
1109 | "journal->j_running_transaction (%p, %u)", | ||
1110 | journal->j_devname, | ||
1111 | (unsigned long long) bh->b_blocknr, | ||
1112 | jh->b_transaction, | ||
1113 | jh->b_transaction ? jh->b_transaction->t_tid : 0, | ||
1114 | journal->j_running_transaction, | ||
1115 | journal->j_running_transaction ? | ||
1116 | journal->j_running_transaction->t_tid : 0); | ||
1117 | ret = -EINVAL; | ||
1118 | } | ||
1098 | goto out_unlock_bh; | 1119 | goto out_unlock_bh; |
1099 | } | 1120 | } |
1100 | 1121 | ||
@@ -1108,9 +1129,32 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh) | |||
1108 | */ | 1129 | */ |
1109 | if (jh->b_transaction != transaction) { | 1130 | if (jh->b_transaction != transaction) { |
1110 | JBUFFER_TRACE(jh, "already on other transaction"); | 1131 | JBUFFER_TRACE(jh, "already on other transaction"); |
1111 | J_ASSERT_JH(jh, jh->b_transaction == | 1132 | if (unlikely(jh->b_transaction != |
1112 | journal->j_committing_transaction); | 1133 | journal->j_committing_transaction)) { |
1113 | J_ASSERT_JH(jh, jh->b_next_transaction == transaction); | 1134 | printk(KERN_EMERG "JBD: %s: " |
1135 | "jh->b_transaction (%llu, %p, %u) != " | ||
1136 | "journal->j_committing_transaction (%p, %u)", | ||
1137 | journal->j_devname, | ||
1138 | (unsigned long long) bh->b_blocknr, | ||
1139 | jh->b_transaction, | ||
1140 | jh->b_transaction ? jh->b_transaction->t_tid : 0, | ||
1141 | journal->j_committing_transaction, | ||
1142 | journal->j_committing_transaction ? | ||
1143 | journal->j_committing_transaction->t_tid : 0); | ||
1144 | ret = -EINVAL; | ||
1145 | } | ||
1146 | if (unlikely(jh->b_next_transaction != transaction)) { | ||
1147 | printk(KERN_EMERG "JBD: %s: " | ||
1148 | "jh->b_next_transaction (%llu, %p, %u) != " | ||
1149 | "transaction (%p, %u)", | ||
1150 | journal->j_devname, | ||
1151 | (unsigned long long) bh->b_blocknr, | ||
1152 | jh->b_next_transaction, | ||
1153 | jh->b_next_transaction ? | ||
1154 | jh->b_next_transaction->t_tid : 0, | ||
1155 | transaction, transaction->t_tid); | ||
1156 | ret = -EINVAL; | ||
1157 | } | ||
1114 | /* And this case is illegal: we can't reuse another | 1158 | /* And this case is illegal: we can't reuse another |
1115 | * transaction's data buffer, ever. */ | 1159 | * transaction's data buffer, ever. */ |
1116 | goto out_unlock_bh; | 1160 | goto out_unlock_bh; |
@@ -1127,7 +1171,9 @@ out_unlock_bh: | |||
1127 | jbd_unlock_bh_state(bh); | 1171 | jbd_unlock_bh_state(bh); |
1128 | out: | 1172 | out: |
1129 | JBUFFER_TRACE(jh, "exit"); | 1173 | JBUFFER_TRACE(jh, "exit"); |
1130 | return 0; | 1174 | if (ret) |
1175 | __WARN(); /* All errors are bugs, so dump the stack */ | ||
1176 | return ret; | ||
1131 | } | 1177 | } |
1132 | 1178 | ||
1133 | /* | 1179 | /* |