Message ID | 20191031234618.15403-18-david@fromorbit.com (mailing list archive) |
---|---|
State | Deferred, archived |
Headers | show |
Series | mm, xfs: non-blocking inode reclaim | expand |
On Fri, Nov 01, 2019 at 10:46:07AM +1100, Dave Chinner wrote: > From: Dave Chinner <dchinner@redhat.com> > > Provide an interface to push the AIL to a target LSN and wait for > the tail of the log to move past that LSN. This is used to wait for > all items older than a specific LSN to either be cleaned (written > back) or relogged to a higher LSN in the AIL. The primary use for > this is to allow IO free inode reclaim throttling. > > Factor the common AIL deletion code that does all the wakeups into a > helper so we only have one copy of this somewhat tricky code to > interface with all the wakeups necessary when the LSN of the log > tail changes. > The above paragraph doesn't seem applicable to this patch. With that fixed: Reviewed-by: Brian Foster <bfoster@redhat.com> > xfs_ail_push_sync() is temporary infrastructure to facilitate > non-blocking, IO-less inode reclaim throttling that allows further > structural changes to be made. Once those structural changes are > made, the need for this function goes away and it is removed. In > essence, it is only provided to ensure git bisects don't break while > the changes to the reclaim algorithms are in progress. > > Signed-off-by: Dave Chinner <dchinner@redhat.com> > --- > fs/xfs/xfs_trans_ail.c | 32 ++++++++++++++++++++++++++++++++ > fs/xfs/xfs_trans_priv.h | 2 ++ > 2 files changed, 34 insertions(+) > > diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c > index 685a21cd24c0..3e1d0e1439e2 100644 > --- a/fs/xfs/xfs_trans_ail.c > +++ b/fs/xfs/xfs_trans_ail.c > @@ -662,6 +662,36 @@ xfs_ail_push_all( > xfs_ail_push(ailp, threshold_lsn); > } > > +/* > + * Push the AIL to a specific lsn and wait for it to complete. > + */ > +void > +xfs_ail_push_sync( > + struct xfs_ail *ailp, > + xfs_lsn_t threshold_lsn) > +{ > + struct xfs_log_item *lip; > + DEFINE_WAIT(wait); > + > + spin_lock(&ailp->ail_lock); > + while ((lip = xfs_ail_min(ailp)) != NULL) { > + prepare_to_wait(&ailp->ail_push, &wait, TASK_UNINTERRUPTIBLE); > + if (XFS_FORCED_SHUTDOWN(ailp->ail_mount) || > + XFS_LSN_CMP(threshold_lsn, lip->li_lsn) < 0) > + break; > + if (XFS_LSN_CMP(threshold_lsn, ailp->ail_target) > 0) > + ailp->ail_target = threshold_lsn; > + wake_up_process(ailp->ail_task); > + spin_unlock(&ailp->ail_lock); > + schedule(); > + spin_lock(&ailp->ail_lock); > + } > + spin_unlock(&ailp->ail_lock); > + > + finish_wait(&ailp->ail_push, &wait); > +} > + > + > /* > * Push out all items in the AIL immediately and wait until the AIL is empty. > */ > @@ -702,6 +732,7 @@ xfs_ail_update_finish( > if (!XFS_FORCED_SHUTDOWN(mp)) > xlog_assign_tail_lsn_locked(mp); > > + wake_up_all(&ailp->ail_push); > if (list_empty(&ailp->ail_head)) > wake_up_all(&ailp->ail_empty); > spin_unlock(&ailp->ail_lock); > @@ -858,6 +889,7 @@ xfs_trans_ail_init( > spin_lock_init(&ailp->ail_lock); > INIT_LIST_HEAD(&ailp->ail_buf_list); > init_waitqueue_head(&ailp->ail_empty); > + init_waitqueue_head(&ailp->ail_push); > > ailp->ail_task = kthread_run(xfsaild, ailp, "xfsaild/%s", > ailp->ail_mount->m_fsname); > diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h > index 35655eac01a6..1b6f4bbd47c0 100644 > --- a/fs/xfs/xfs_trans_priv.h > +++ b/fs/xfs/xfs_trans_priv.h > @@ -61,6 +61,7 @@ struct xfs_ail { > int ail_log_flush; > struct list_head ail_buf_list; > wait_queue_head_t ail_empty; > + wait_queue_head_t ail_push; > }; > > /* > @@ -113,6 +114,7 @@ xfs_trans_ail_remove( > } > > void xfs_ail_push(struct xfs_ail *, xfs_lsn_t); > +void xfs_ail_push_sync(struct xfs_ail *, xfs_lsn_t); > void xfs_ail_push_all(struct xfs_ail *); > void xfs_ail_push_all_sync(struct xfs_ail *); > struct xfs_log_item *xfs_ail_min(struct xfs_ail *ailp); > -- > 2.24.0.rc0 >
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index 685a21cd24c0..3e1d0e1439e2 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c @@ -662,6 +662,36 @@ xfs_ail_push_all( xfs_ail_push(ailp, threshold_lsn); } +/* + * Push the AIL to a specific lsn and wait for it to complete. + */ +void +xfs_ail_push_sync( + struct xfs_ail *ailp, + xfs_lsn_t threshold_lsn) +{ + struct xfs_log_item *lip; + DEFINE_WAIT(wait); + + spin_lock(&ailp->ail_lock); + while ((lip = xfs_ail_min(ailp)) != NULL) { + prepare_to_wait(&ailp->ail_push, &wait, TASK_UNINTERRUPTIBLE); + if (XFS_FORCED_SHUTDOWN(ailp->ail_mount) || + XFS_LSN_CMP(threshold_lsn, lip->li_lsn) < 0) + break; + if (XFS_LSN_CMP(threshold_lsn, ailp->ail_target) > 0) + ailp->ail_target = threshold_lsn; + wake_up_process(ailp->ail_task); + spin_unlock(&ailp->ail_lock); + schedule(); + spin_lock(&ailp->ail_lock); + } + spin_unlock(&ailp->ail_lock); + + finish_wait(&ailp->ail_push, &wait); +} + + /* * Push out all items in the AIL immediately and wait until the AIL is empty. */ @@ -702,6 +732,7 @@ xfs_ail_update_finish( if (!XFS_FORCED_SHUTDOWN(mp)) xlog_assign_tail_lsn_locked(mp); + wake_up_all(&ailp->ail_push); if (list_empty(&ailp->ail_head)) wake_up_all(&ailp->ail_empty); spin_unlock(&ailp->ail_lock); @@ -858,6 +889,7 @@ xfs_trans_ail_init( spin_lock_init(&ailp->ail_lock); INIT_LIST_HEAD(&ailp->ail_buf_list); init_waitqueue_head(&ailp->ail_empty); + init_waitqueue_head(&ailp->ail_push); ailp->ail_task = kthread_run(xfsaild, ailp, "xfsaild/%s", ailp->ail_mount->m_fsname); diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h index 35655eac01a6..1b6f4bbd47c0 100644 --- a/fs/xfs/xfs_trans_priv.h +++ b/fs/xfs/xfs_trans_priv.h @@ -61,6 +61,7 @@ struct xfs_ail { int ail_log_flush; struct list_head ail_buf_list; wait_queue_head_t ail_empty; + wait_queue_head_t ail_push; }; /* @@ -113,6 +114,7 @@ xfs_trans_ail_remove( } void xfs_ail_push(struct xfs_ail *, xfs_lsn_t); +void xfs_ail_push_sync(struct xfs_ail *, xfs_lsn_t); void xfs_ail_push_all(struct xfs_ail *); void xfs_ail_push_all_sync(struct xfs_ail *); struct xfs_log_item *xfs_ail_min(struct xfs_ail *ailp);