| @@ -1075,6 +1075,32 @@ out: · 1074 unmodified lines |
| 1075 | 1075 | return ret; |
| 1076 | 1076 | } |
| 1077 | 1077 | |
| 1078 | +static void ext4_fc_update_stats(struct super_block *sb, int status, |
| 1079 | + u64 commit_time, int nblks) |
| 1080 | +{ |
| 1081 | + struct ext4_fc_stats *stats = &EXT4_SB(sb)->s_fc_stats; |
| 1082 | + |
| 1083 | + jbd_debug(1, "Fast commit ended with status = %d", status); |
| 1084 | + if (status == EXT4_FC_STATUS_OK) { |
| 1085 | + stats->fc_num_commits++; |
| 1086 | + stats->fc_numblks += nblks; |
| 1087 | + if (likely(stats->s_fc_avg_commit_time)) |
| 1088 | + stats->s_fc_avg_commit_time = |
| 1089 | + (commit_time + |
| 1090 | + stats->s_fc_avg_commit_time * 3) / 4; |
| 1091 | + else |
| 1092 | + stats->s_fc_avg_commit_time = commit_time; |
| 1093 | + } else if (status == EXT4_FC_STATUS_FAILED || |
| 1094 | + status == EXT4_FC_STATUS_INELIGIBLE) { |
| 1095 | + if (status == EXT4_FC_STATUS_FAILED) |
| 1096 | + stats->fc_failed_commits++; |
| 1097 | + stats->fc_ineligible_commits++; |
| 1098 | + } else { |
| 1099 | + stats->fc_skipped_commits++; |
| 1100 | + } |
| 1101 | + trace_ext4_fc_commit_stop(sb, nblks, status); |
| 1102 | +} |
| 1103 | + |
| 1078 | 1104 | /* |
| 1079 | 1105 | * The main commit entry point. Performs a fast commit for transaction |
| 1080 | 1106 | * commit_tid if needed. If it's not possible to perform a fast commit |
| @@ -1087,7 +1113,7 @@ int ext4_fc_commit(journal_t *journal, tid_t commit_tid) · 6 unmodified lines |
| 1087 | 1113 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| 1088 | 1114 | int nblks = 0, ret, bsize = journal->j_blocksize; |
| 1089 | 1115 | int subtid = atomic_read(&sbi->s_fc_subtid); |
| 1090 | | − int reason = EXT4_FC_REASON_OK, fc_bufs_before = 0; |
| 1116 | + int status = EXT4_FC_STATUS_OK, fc_bufs_before = 0; |
| 1091 | 1117 | ktime_t start_time, commit_time; |
| 1092 | 1118 | |
| 1093 | 1119 | trace_ext4_fc_commit_start(sb); |
| @@ -1104,69 +1130,52 @@ restart_fc: · 10 unmodified lines |
| 1104 | 1130 | if (atomic_read(&sbi->s_fc_subtid) <= subtid && |
| 1105 | 1131 | commit_tid > journal->j_commit_sequence) |
| 1106 | 1132 | goto restart_fc; |
| 1107 | | − reason = EXT4_FC_REASON_ALREADY_COMMITTED; |
| 1108 | | − goto out; |
| 1133 | + ext4_fc_update_stats(sb, EXT4_FC_STATUS_SKIPPED, 0, 0); |
| 1134 | + return 0; |
| 1109 | 1135 | } else if (ret) { |
| 1110 | | − sbi->s_fc_stats.fc_ineligible_reason_count[EXT4_FC_COMMIT_FAILED]++; |
| 1111 | | − reason = EXT4_FC_REASON_FC_START_FAILED; |
| 1112 | | − goto out; |
| 1136 | + /* |
| 1137 | + * Commit couldn't start. Just update stats and perform a |
| 1138 | + * full commit. |
| 1139 | + */ |
| 1140 | + ext4_fc_update_stats(sb, EXT4_FC_STATUS_FAILED, 0, 0); |
| 1141 | + return jbd2_complete_transaction(journal, commit_tid); |
| 1113 | 1142 | } |
| 1143 | + |
| 1114 | 1144 | /* |
| 1115 | 1145 | * After establishing journal barrier via jbd2_fc_begin_commit(), check |
| 1116 | 1146 | * if we are fast commit ineligible. |
| 1117 | 1147 | */ |
| 1118 | 1148 | if (ext4_test_mount_flag(sb, EXT4_MF_FC_INELIGIBLE)) { |
| 1119 | | − reason = EXT4_FC_REASON_INELIGIBLE; |
| 1120 | | − goto out; |
| 1149 | + status = EXT4_FC_STATUS_INELIGIBLE; |
| 1150 | + goto fallback; |
| 1121 | 1151 | } |
| 1122 | 1152 | |
| 1123 | 1153 | fc_bufs_before = (sbi->s_fc_bytes + bsize - 1) / bsize; |
| 1124 | 1154 | ret = ext4_fc_perform_commit(journal); |
| 1125 | 1155 | if (ret < 0) { |
| 1126 | | − sbi->s_fc_stats.fc_ineligible_reason_count[EXT4_FC_COMMIT_FAILED]++; |
| 1127 | | − reason = EXT4_FC_REASON_FC_FAILED; |
| 1128 | | − goto out; |
| 1156 | + status = EXT4_FC_STATUS_FAILED; |
| 1157 | + goto fallback; |
| 1129 | 1158 | } |
| 1130 | 1159 | nblks = (sbi->s_fc_bytes + bsize - 1) / bsize - fc_bufs_before; |
| 1131 | 1160 | ret = jbd2_fc_wait_bufs(journal, nblks); |
| 1132 | 1161 | if (ret < 0) { |
| 1133 | | − sbi->s_fc_stats.fc_ineligible_reason_count[EXT4_FC_COMMIT_FAILED]++; |
| 1134 | | − reason = EXT4_FC_REASON_FC_FAILED; |
| 1135 | | − goto out; |
| 1162 | + status = EXT4_FC_STATUS_FAILED; |
| 1163 | + goto fallback; |
| 1136 | 1164 | } |
| 1137 | 1165 | atomic_inc(&sbi->s_fc_subtid); |
| 1138 | | − jbd2_fc_end_commit(journal); |
| 1139 | | −out: |
| 1140 | | − spin_lock(&sbi->s_fc_lock); |
| 1141 | | − if (reason != EXT4_FC_REASON_OK && |
| 1142 | | − reason != EXT4_FC_REASON_ALREADY_COMMITTED) { |
| 1143 | | − sbi->s_fc_stats.fc_ineligible_commits++; |
| 1144 | | − } else { |
| 1145 | | − sbi->s_fc_stats.fc_num_commits++; |
| 1146 | | − sbi->s_fc_stats.fc_numblks += nblks; |
| 1147 | | − } |
| 1148 | | − spin_unlock(&sbi->s_fc_lock); |
| 1149 | | − nblks = (reason == EXT4_FC_REASON_OK) ? nblks : 0; |
| 1150 | | − trace_ext4_fc_commit_stop(sb, nblks, reason); |
| 1151 | | − commit_time = ktime_to_ns(ktime_sub(ktime_get(), start_time)); |
| 1166 | + ret = jbd2_fc_end_commit(journal); |
| 1152 | 1167 | /* |
| 1153 | | − * weight the commit time higher than the average time so we don't |
| 1154 | | − * react too strongly to vast changes in the commit time |
| 1168 | + * weight the commit time higher than the average time so we |
| 1169 | + * don't react too strongly to vast changes in the commit time |
| 1155 | 1170 | */ |
| 1156 | | − if (likely(sbi->s_fc_avg_commit_time)) |
| 1157 | | − sbi->s_fc_avg_commit_time = (commit_time + |
| 1158 | | − sbi->s_fc_avg_commit_time * 3) / 4; |
| 1159 | | − else |
| 1160 | | − sbi->s_fc_avg_commit_time = commit_time; |
| 1161 | | − jbd_debug(1, |
| 1162 | | − "Fast commit ended with blks = %d, reason = %d, subtid - %d", |
| 1163 | | − nblks, reason, subtid); |
| 1164 | | − if (reason == EXT4_FC_REASON_FC_FAILED) |
| 1165 | | − return jbd2_fc_end_commit_fallback(journal); |
| 1166 | | − if (reason == EXT4_FC_REASON_FC_START_FAILED || |
| 1167 | | − reason == EXT4_FC_REASON_INELIGIBLE) |
| 1168 | | − return jbd2_complete_transaction(journal, commit_tid); |
| 1169 | | − return 0; |
| 1171 | + commit_time = ktime_to_ns(ktime_sub(ktime_get(), start_time)); |
| 1172 | + ext4_fc_update_stats(sb, status, commit_time, nblks); |
| 1173 | + return ret; |
| 1174 | + |
| 1175 | +fallback: |
| 1176 | + ret = jbd2_fc_end_commit_fallback(journal); |
| 1177 | + ext4_fc_update_stats(sb, status, 0, 0); |
| 1178 | + return ret; |
| 1170 | 1179 | } |
| 1171 | 1180 | |
| 1172 | 1181 | /* |
| @@ -2124,7 +2133,7 @@ int ext4_fc_info_show(struct seq_file *seq, void *v) · 951 unmodified lines |
| 2124 | 2133 | "fc stats:\n%ld commits\n%ld ineligible\n%ld numblks\n%lluus avg_commit_time\n", |
| 2125 | 2134 | stats->fc_num_commits, stats->fc_ineligible_commits, |
| 2126 | 2135 | stats->fc_numblks, |
| 2127 | | − div_u64(sbi->s_fc_avg_commit_time, 1000)); |
| 2136 | + div_u64(stats->s_fc_avg_commit_time, 1000)); |
| 2128 | 2137 | seq_puts(seq, "Ineligible reasons:\n"); |
| 2129 | 2138 | for (i = 0; i < EXT4_FC_REASON_MAX; i++) |
| 2130 | 2139 | seq_printf(seq, "\"%s\":\t%d\n", fc_ineligible_reasons[i], |