xfs: inform the xfsaild of the push target before sleeping

When trying to reserve log space, we find the amount of space
we need, then go to sleep waiting for space. When we are
woken, we try to push the tail of the log forward to make
sure we have space available.

Unfortunately, this means that if there is not space available, and
everyone who needs space goes to sleep there is no-one left to push
the tail of the log to make space available. Once we have a thread
waiting for space to become available, the others queue up behind
it in a FIFO, and none of them push the tail of the log.

This can result in everyone going to sleep in xlog_grant_log_space()
if the first sleeper races with the last I/O that moves the tail
of the log forward. With no further I/O tomove the tail of the log,
there is nothing to wake the sleepers and hence all transactions
just stop.

Fix this by making sure the xfsaild will create enough space for the
transaction that is about to sleep by moving the push target far
enough forwards to ensure that that the curent proceeees will have
enough space available when it is woken. That is, we push the
AIL before we go to sleep.

Because we've inserted the log ticket into the queue before we've
pushed and gone to sleep, subsequent transactions will wait behind
this one. Hence we are guaranteed to have space available when we
are woken.

Signed-off-by: Dave Chinner <david@fromorbit.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>

authored by

Dave Chinner and committed by
Christoph Hellwig
9d7fef74 c626d174

+19 -18
+19 -18
fs/xfs/xfs_log.c
··· 2560 xlog_ins_ticketq(&log->l_reserve_headq, tic); 2561 xlog_trace_loggrant(log, tic, 2562 "xlog_grant_log_space: sleep 2"); 2563 XFS_STATS_INC(xs_sleep_logspace); 2564 sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); 2565 2566 - if (XLOG_FORCED_SHUTDOWN(log)) { 2567 - spin_lock(&log->l_grant_lock); 2568 goto error_return; 2569 - } 2570 2571 xlog_trace_loggrant(log, tic, 2572 "xlog_grant_log_space: wake 2"); 2573 - xlog_grant_push_ail(log->l_mp, need_bytes); 2574 - spin_lock(&log->l_grant_lock); 2575 goto redo; 2576 } else if (tic->t_flags & XLOG_TIC_IN_Q) 2577 xlog_del_ticketq(&log->l_reserve_headq, tic); ··· 2651 * for more free space, otherwise try to get some space for 2652 * this transaction. 2653 */ 2654 - 2655 if ((ntic = log->l_write_headq)) { 2656 free_bytes = xlog_space_left(log, log->l_grant_write_cycle, 2657 log->l_grant_write_bytes); ··· 2671 2672 xlog_trace_loggrant(log, tic, 2673 "xlog_regrant_write_log_space: sleep 1"); 2674 XFS_STATS_INC(xs_sleep_logspace); 2675 sv_wait(&tic->t_wait, PINOD|PLTWAIT, 2676 &log->l_grant_lock, s); 2677 2678 /* If we're shutting down, this tic is already 2679 * off the queue */ 2680 - if (XLOG_FORCED_SHUTDOWN(log)) { 2681 - spin_lock(&log->l_grant_lock); 2682 goto error_return; 2683 - } 2684 2685 xlog_trace_loggrant(log, tic, 2686 "xlog_regrant_write_log_space: wake 1"); 2687 - xlog_grant_push_ail(log->l_mp, tic->t_unit_res); 2688 - spin_lock(&log->l_grant_lock); 2689 } 2690 } 2691 - 2692 - need_bytes = tic->t_unit_res; 2693 2694 redo: 2695 if (XLOG_FORCED_SHUTDOWN(log)) ··· 2699 if (free_bytes < need_bytes) { 2700 if ((tic->t_flags & XLOG_TIC_IN_Q) == 0) 2701 xlog_ins_ticketq(&log->l_write_headq, tic); 2702 XFS_STATS_INC(xs_sleep_logspace); 2703 sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); 2704 2705 /* If we're shutting down, this tic is already off the queue */ 2706 - if (XLOG_FORCED_SHUTDOWN(log)) { 2707 - spin_lock(&log->l_grant_lock); 2708 goto error_return; 2709 - } 2710 2711 xlog_trace_loggrant(log, tic, 2712 "xlog_regrant_write_log_space: wake 2"); 2713 - xlog_grant_push_ail(log->l_mp, need_bytes); 2714 - spin_lock(&log->l_grant_lock); 2715 goto redo; 2716 } else if (tic->t_flags & XLOG_TIC_IN_Q) 2717 xlog_del_ticketq(&log->l_write_headq, tic);
··· 2560 xlog_ins_ticketq(&log->l_reserve_headq, tic); 2561 xlog_trace_loggrant(log, tic, 2562 "xlog_grant_log_space: sleep 2"); 2563 + spin_unlock(&log->l_grant_lock); 2564 + xlog_grant_push_ail(log->l_mp, need_bytes); 2565 + spin_lock(&log->l_grant_lock); 2566 + 2567 XFS_STATS_INC(xs_sleep_logspace); 2568 sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); 2569 2570 + spin_lock(&log->l_grant_lock); 2571 + if (XLOG_FORCED_SHUTDOWN(log)) 2572 goto error_return; 2573 2574 xlog_trace_loggrant(log, tic, 2575 "xlog_grant_log_space: wake 2"); 2576 goto redo; 2577 } else if (tic->t_flags & XLOG_TIC_IN_Q) 2578 xlog_del_ticketq(&log->l_reserve_headq, tic); ··· 2650 * for more free space, otherwise try to get some space for 2651 * this transaction. 2652 */ 2653 + need_bytes = tic->t_unit_res; 2654 if ((ntic = log->l_write_headq)) { 2655 free_bytes = xlog_space_left(log, log->l_grant_write_cycle, 2656 log->l_grant_write_bytes); ··· 2670 2671 xlog_trace_loggrant(log, tic, 2672 "xlog_regrant_write_log_space: sleep 1"); 2673 + spin_unlock(&log->l_grant_lock); 2674 + xlog_grant_push_ail(log->l_mp, need_bytes); 2675 + spin_lock(&log->l_grant_lock); 2676 + 2677 XFS_STATS_INC(xs_sleep_logspace); 2678 sv_wait(&tic->t_wait, PINOD|PLTWAIT, 2679 &log->l_grant_lock, s); 2680 2681 /* If we're shutting down, this tic is already 2682 * off the queue */ 2683 + spin_lock(&log->l_grant_lock); 2684 + if (XLOG_FORCED_SHUTDOWN(log)) 2685 goto error_return; 2686 2687 xlog_trace_loggrant(log, tic, 2688 "xlog_regrant_write_log_space: wake 1"); 2689 } 2690 } 2691 2692 redo: 2693 if (XLOG_FORCED_SHUTDOWN(log)) ··· 2699 if (free_bytes < need_bytes) { 2700 if ((tic->t_flags & XLOG_TIC_IN_Q) == 0) 2701 xlog_ins_ticketq(&log->l_write_headq, tic); 2702 + spin_unlock(&log->l_grant_lock); 2703 + xlog_grant_push_ail(log->l_mp, need_bytes); 2704 + spin_lock(&log->l_grant_lock); 2705 + 2706 XFS_STATS_INC(xs_sleep_logspace); 2707 sv_wait(&tic->t_wait, PINOD|PLTWAIT, &log->l_grant_lock, s); 2708 2709 /* If we're shutting down, this tic is already off the queue */ 2710 + spin_lock(&log->l_grant_lock); 2711 + if (XLOG_FORCED_SHUTDOWN(log)) 2712 goto error_return; 2713 2714 xlog_trace_loggrant(log, tic, 2715 "xlog_regrant_write_log_space: wake 2"); 2716 goto redo; 2717 } else if (tic->t_flags & XLOG_TIC_IN_Q) 2718 xlog_del_ticketq(&log->l_write_headq, tic);