aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/ext4_jbd2.c8
-rw-r--r--fs/ext4/extents.c10
-rw-r--r--fs/jbd2/transaction.c58
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 */
99static 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))
101static 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);
1128out: 1172out:
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/*