Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

gfs2: add some missing log locking

Function gfs2_logd() calls the log flushing functions gfs2_ail1_start(),
gfs2_ail1_wait(), and gfs2_ail1_empty() without holding sdp->sd_log_flush_lock,
but these functions require exclusion against concurrent transactions.

To fix that, add a non-locking __gfs2_log_flush() function. Then, in
gfs2_logd(), take sdp->sd_log_flush_lock before calling the above mentioned log
flushing functions and __gfs2_log_flush().

Fixes: 5e4c7632aae1c ("gfs2: Issue revokes more intelligently")
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>

+20 -8
+20 -8
fs/gfs2/log.c
··· 1053 1053 } 1054 1054 1055 1055 /** 1056 - * gfs2_log_flush - flush incore transaction(s) 1056 + * __gfs2_log_flush - flush incore transaction(s) 1057 1057 * @sdp: The filesystem 1058 1058 * @gl: The glock structure to flush. If NULL, flush the whole incore log 1059 1059 * @flags: The log header flags: GFS2_LOG_HEAD_FLUSH_* and debug flags 1060 1060 * 1061 1061 */ 1062 1062 1063 - void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags) 1063 + static void __gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, 1064 + u32 flags) 1064 1065 { 1065 1066 struct gfs2_trans *tr = NULL; 1066 1067 unsigned int reserved_blocks = 0, used_blocks = 0; ··· 1069 1068 unsigned int first_log_head; 1070 1069 unsigned int reserved_revokes = 0; 1071 1070 1072 - down_write(&sdp->sd_log_flush_lock); 1073 1071 trace_gfs2_log_flush(sdp, 1, flags); 1074 1072 1075 1073 repeat: ··· 1180 1180 gfs2_assert_withdraw(sdp, used_blocks < reserved_blocks); 1181 1181 gfs2_log_release(sdp, reserved_blocks - used_blocks); 1182 1182 } 1183 - up_write(&sdp->sd_log_flush_lock); 1184 1183 gfs2_trans_free(sdp, tr); 1185 1184 trace_gfs2_log_flush(sdp, 0, flags); 1186 1185 return; ··· 1198 1199 spin_unlock(&sdp->sd_ail_lock); 1199 1200 tr = NULL; 1200 1201 goto out_end; 1202 + } 1203 + 1204 + void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags) 1205 + { 1206 + down_write(&sdp->sd_log_flush_lock); 1207 + __gfs2_log_flush(sdp, gl, flags); 1208 + up_write(&sdp->sd_log_flush_lock); 1201 1209 } 1202 1210 1203 1211 /** ··· 1338 1332 break; 1339 1333 1340 1334 if (gfs2_jrnl_flush_reqd(sdp) || t == 0) { 1335 + down_write(&sdp->sd_log_flush_lock); 1341 1336 gfs2_ail1_empty(sdp, 0); 1342 - gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL | 1343 - GFS2_LFC_LOGD_JFLUSH_REQD); 1337 + __gfs2_log_flush(sdp, NULL, 1338 + GFS2_LOG_HEAD_FLUSH_NORMAL | 1339 + GFS2_LFC_LOGD_JFLUSH_REQD); 1340 + up_write(&sdp->sd_log_flush_lock); 1344 1341 } 1345 1342 1346 1343 if (test_bit(SDF_FORCE_AIL_FLUSH, &sdp->sd_flags) || 1347 1344 gfs2_ail_flush_reqd(sdp)) { 1348 1345 clear_bit(SDF_FORCE_AIL_FLUSH, &sdp->sd_flags); 1346 + down_write(&sdp->sd_log_flush_lock); 1349 1347 gfs2_ail1_start(sdp); 1350 1348 gfs2_ail1_wait(sdp); 1351 1349 gfs2_ail1_empty(sdp, 0); 1352 - gfs2_log_flush(sdp, NULL, GFS2_LOG_HEAD_FLUSH_NORMAL | 1353 - GFS2_LFC_LOGD_AIL_FLUSH_REQD); 1350 + __gfs2_log_flush(sdp, NULL, 1351 + GFS2_LOG_HEAD_FLUSH_NORMAL | 1352 + GFS2_LFC_LOGD_AIL_FLUSH_REQD); 1353 + up_write(&sdp->sd_log_flush_lock); 1354 1354 } 1355 1355 1356 1356 t = gfs2_tune_get(sdp, gt_logd_secs) * HZ;