aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2010-12-20 20:09:20 -0500
committerDave Chinner <david@fromorbit.com>2010-12-20 20:09:20 -0500
commit2ced19cbae5448b720919a494606c62095d4f4db (patch)
treee011a53041289ed4f9c8e78f6d88cd3454c9c39b /fs/xfs
parenteb40a87500ac2f6be7eaf8ebb35610e6d0e60e9a (diff)
xfs: make AIL tail pushing independent of the grant lock
The xlog_grant_push_ail() currently takes the grant lock internally to sample the tail lsn, last sync lsn and the reserve grant head. Most of the callers already hold the grant lock but have to drop it before calling xlog_grant_push_ail(). This is a left over from when the AIL tail pushing was done in line and hence xlog_grant_push_ail had to drop the grant lock. AIL push is now done in another thread and hence we can safely hold the grant lock over the entire xlog_grant_push_ail call. Push the grant lock outside of xlog_grant_push_ail() to simplify the locking and synchronisation needed for tail pushing. This will reduce traffic on the grant lock by itself, but this is only one step in preparing for the complete removal of the grant lock. While there, clean up the formatting of xlog_grant_push_ail() to match the rest of the XFS code. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_log.c111
1 files changed, 54 insertions, 57 deletions
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index cc0504e0bb3b..1e2020d5a8b6 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -70,7 +70,7 @@ STATIC void xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog);
70/* local functions to manipulate grant head */ 70/* local functions to manipulate grant head */
71STATIC int xlog_grant_log_space(xlog_t *log, 71STATIC int xlog_grant_log_space(xlog_t *log,
72 xlog_ticket_t *xtic); 72 xlog_ticket_t *xtic);
73STATIC void xlog_grant_push_ail(xfs_mount_t *mp, 73STATIC void xlog_grant_push_ail(struct log *log,
74 int need_bytes); 74 int need_bytes);
75STATIC void xlog_regrant_reserve_log_space(xlog_t *log, 75STATIC void xlog_regrant_reserve_log_space(xlog_t *log,
76 xlog_ticket_t *ticket); 76 xlog_ticket_t *ticket);
@@ -318,7 +318,9 @@ xfs_log_reserve(
318 318
319 trace_xfs_log_reserve(log, internal_ticket); 319 trace_xfs_log_reserve(log, internal_ticket);
320 320
321 xlog_grant_push_ail(mp, internal_ticket->t_unit_res); 321 spin_lock(&log->l_grant_lock);
322 xlog_grant_push_ail(log, internal_ticket->t_unit_res);
323 spin_unlock(&log->l_grant_lock);
322 retval = xlog_regrant_write_log_space(log, internal_ticket); 324 retval = xlog_regrant_write_log_space(log, internal_ticket);
323 } else { 325 } else {
324 /* may sleep if need to allocate more tickets */ 326 /* may sleep if need to allocate more tickets */
@@ -332,9 +334,11 @@ xfs_log_reserve(
332 334
333 trace_xfs_log_reserve(log, internal_ticket); 335 trace_xfs_log_reserve(log, internal_ticket);
334 336
335 xlog_grant_push_ail(mp, 337 spin_lock(&log->l_grant_lock);
338 xlog_grant_push_ail(log,
336 (internal_ticket->t_unit_res * 339 (internal_ticket->t_unit_res *
337 internal_ticket->t_cnt)); 340 internal_ticket->t_cnt));
341 spin_unlock(&log->l_grant_lock);
338 retval = xlog_grant_log_space(log, internal_ticket); 342 retval = xlog_grant_log_space(log, internal_ticket);
339 } 343 }
340 344
@@ -1185,59 +1189,58 @@ xlog_commit_record(
1185 * water mark. In this manner, we would be creating a low water mark. 1189 * water mark. In this manner, we would be creating a low water mark.
1186 */ 1190 */
1187STATIC void 1191STATIC void
1188xlog_grant_push_ail(xfs_mount_t *mp, 1192xlog_grant_push_ail(
1189 int need_bytes) 1193 struct log *log,
1194 int need_bytes)
1190{ 1195{
1191 xlog_t *log = mp->m_log; /* pointer to the log */ 1196 xfs_lsn_t threshold_lsn = 0;
1192 xfs_lsn_t tail_lsn; /* lsn of the log tail */ 1197 xfs_lsn_t tail_lsn;
1193 xfs_lsn_t threshold_lsn = 0; /* lsn we'd like to be at */ 1198 int free_blocks;
1194 int free_blocks; /* free blocks left to write to */ 1199 int free_bytes;
1195 int free_bytes; /* free bytes left to write to */ 1200 int threshold_block;
1196 int threshold_block; /* block in lsn we'd like to be at */ 1201 int threshold_cycle;
1197 int threshold_cycle; /* lsn cycle we'd like to be at */ 1202 int free_threshold;
1198 int free_threshold; 1203
1199 1204 ASSERT(BTOBB(need_bytes) < log->l_logBBsize);
1200 ASSERT(BTOBB(need_bytes) < log->l_logBBsize); 1205
1201 1206 tail_lsn = log->l_tail_lsn;
1202 spin_lock(&log->l_grant_lock); 1207 free_bytes = xlog_space_left(log, &log->l_grant_reserve_head);
1203 free_bytes = xlog_space_left(log, &log->l_grant_reserve_head); 1208 free_blocks = BTOBBT(free_bytes);
1204 tail_lsn = log->l_tail_lsn; 1209
1205 free_blocks = BTOBBT(free_bytes); 1210 /*
1206 1211 * Set the threshold for the minimum number of free blocks in the
1207 /* 1212 * log to the maximum of what the caller needs, one quarter of the
1208 * Set the threshold for the minimum number of free blocks in the 1213 * log, and 256 blocks.
1209 * log to the maximum of what the caller needs, one quarter of the 1214 */
1210 * log, and 256 blocks. 1215 free_threshold = BTOBB(need_bytes);
1211 */ 1216 free_threshold = MAX(free_threshold, (log->l_logBBsize >> 2));
1212 free_threshold = BTOBB(need_bytes); 1217 free_threshold = MAX(free_threshold, 256);
1213 free_threshold = MAX(free_threshold, (log->l_logBBsize >> 2)); 1218 if (free_blocks >= free_threshold)
1214 free_threshold = MAX(free_threshold, 256); 1219 return;
1215 if (free_blocks < free_threshold) { 1220
1216 threshold_block = BLOCK_LSN(tail_lsn) + free_threshold; 1221 threshold_block = BLOCK_LSN(tail_lsn) + free_threshold;
1217 threshold_cycle = CYCLE_LSN(tail_lsn); 1222 threshold_cycle = CYCLE_LSN(tail_lsn);
1218 if (threshold_block >= log->l_logBBsize) { 1223 if (threshold_block >= log->l_logBBsize) {
1219 threshold_block -= log->l_logBBsize; 1224 threshold_block -= log->l_logBBsize;
1220 threshold_cycle += 1; 1225 threshold_cycle += 1;
1221 } 1226 }
1222 threshold_lsn = xlog_assign_lsn(threshold_cycle, threshold_block); 1227 threshold_lsn = xlog_assign_lsn(threshold_cycle,
1223 1228 threshold_block);
1224 /* Don't pass in an lsn greater than the lsn of the last 1229 /*
1230 * Don't pass in an lsn greater than the lsn of the last
1225 * log record known to be on disk. 1231 * log record known to be on disk.
1226 */ 1232 */
1227 if (XFS_LSN_CMP(threshold_lsn, log->l_last_sync_lsn) > 0) 1233 if (XFS_LSN_CMP(threshold_lsn, log->l_last_sync_lsn) > 0)
1228 threshold_lsn = log->l_last_sync_lsn; 1234 threshold_lsn = log->l_last_sync_lsn;
1229 } 1235
1230 spin_unlock(&log->l_grant_lock); 1236 /*
1231 1237 * Get the transaction layer to kick the dirty buffers out to
1232 /* 1238 * disk asynchronously. No point in trying to do this if
1233 * Get the transaction layer to kick the dirty buffers out to 1239 * the filesystem is shutting down.
1234 * disk asynchronously. No point in trying to do this if 1240 */
1235 * the filesystem is shutting down. 1241 if (!XLOG_FORCED_SHUTDOWN(log))
1236 */ 1242 xfs_trans_ail_push(log->l_ailp, threshold_lsn);
1237 if (threshold_lsn && 1243}
1238 !XLOG_FORCED_SHUTDOWN(log))
1239 xfs_trans_ail_push(log->l_ailp, threshold_lsn);
1240} /* xlog_grant_push_ail */
1241 1244
1242/* 1245/*
1243 * The bdstrat callback function for log bufs. This gives us a central 1246 * The bdstrat callback function for log bufs. This gives us a central
@@ -2543,9 +2546,7 @@ redo:
2543 2546
2544 trace_xfs_log_grant_sleep2(log, tic); 2547 trace_xfs_log_grant_sleep2(log, tic);
2545 2548
2546 spin_unlock(&log->l_grant_lock); 2549 xlog_grant_push_ail(log, need_bytes);
2547 xlog_grant_push_ail(log->l_mp, need_bytes);
2548 spin_lock(&log->l_grant_lock);
2549 2550
2550 XFS_STATS_INC(xs_sleep_logspace); 2551 XFS_STATS_INC(xs_sleep_logspace);
2551 xlog_wait(&tic->t_wait, &log->l_grant_lock); 2552 xlog_wait(&tic->t_wait, &log->l_grant_lock);
@@ -2641,9 +2642,7 @@ xlog_regrant_write_log_space(xlog_t *log,
2641 2642
2642 trace_xfs_log_regrant_write_sleep1(log, tic); 2643 trace_xfs_log_regrant_write_sleep1(log, tic);
2643 2644
2644 spin_unlock(&log->l_grant_lock); 2645 xlog_grant_push_ail(log, need_bytes);
2645 xlog_grant_push_ail(log->l_mp, need_bytes);
2646 spin_lock(&log->l_grant_lock);
2647 2646
2648 XFS_STATS_INC(xs_sleep_logspace); 2647 XFS_STATS_INC(xs_sleep_logspace);
2649 xlog_wait(&tic->t_wait, &log->l_grant_lock); 2648 xlog_wait(&tic->t_wait, &log->l_grant_lock);
@@ -2666,9 +2665,7 @@ redo:
2666 if (free_bytes < need_bytes) { 2665 if (free_bytes < need_bytes) {
2667 if (list_empty(&tic->t_queue)) 2666 if (list_empty(&tic->t_queue))
2668 list_add_tail(&tic->t_queue, &log->l_writeq); 2667 list_add_tail(&tic->t_queue, &log->l_writeq);
2669 spin_unlock(&log->l_grant_lock); 2668 xlog_grant_push_ail(log, need_bytes);
2670 xlog_grant_push_ail(log->l_mp, need_bytes);
2671 spin_lock(&log->l_grant_lock);
2672 2669
2673 XFS_STATS_INC(xs_sleep_logspace); 2670 XFS_STATS_INC(xs_sleep_logspace);
2674 trace_xfs_log_regrant_write_sleep2(log, tic); 2671 trace_xfs_log_regrant_write_sleep2(log, tic);