Commit af3e4022 authored by Dave Chinner's avatar Dave Chinner Committed by Alex Elder

xfs: convert AIL cursors to use struct list_head

The list of active AIL cursors uses a roll-your-own linked list with
special casing for the AIL push cursor. Simplify this code by
replacing the list with standard struct list_head lists, and use a
separate list_head to track the active cursors. This allows us to
treat the AIL push cursor as a generic cursor rather than as a
special case, further simplifying the code.

Further, fix the duplicate push cursor initialisation that the
special case handling was hiding, and clean up all the comments
around the active cursor list handling.
Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarAlex Elder <aelder@sgi.com>
parent 16b59029
...@@ -163,17 +163,11 @@ xfs_ail_max_lsn( ...@@ -163,17 +163,11 @@ xfs_ail_max_lsn(
} }
/* /*
* AIL traversal cursor initialisation. * The cursor keeps track of where our current traversal is up to by tracking
* * the next item in the list for us. However, for this to be safe, removing an
* The cursor keeps track of where our current traversal is up * object from the AIL needs to invalidate any cursor that points to it. hence
* to by tracking the next ƣtem in the list for us. However, for * the traversal cursor needs to be linked to the struct xfs_ail so that
* this to be safe, removing an object from the AIL needs to invalidate * deletion can search all the active cursors for invalidation.
* any cursor that points to it. hence the traversal cursor needs to
* be linked to the struct xfs_ail so that deletion can search all the
* active cursors for invalidation.
*
* We don't link the push cursor because it is embedded in the struct
* xfs_ail and hence easily findable.
*/ */
STATIC void STATIC void
xfs_trans_ail_cursor_init( xfs_trans_ail_cursor_init(
...@@ -181,17 +175,12 @@ xfs_trans_ail_cursor_init( ...@@ -181,17 +175,12 @@ xfs_trans_ail_cursor_init(
struct xfs_ail_cursor *cur) struct xfs_ail_cursor *cur)
{ {
cur->item = NULL; cur->item = NULL;
if (cur == &ailp->xa_cursors) list_add_tail(&cur->list, &ailp->xa_cursors);
return;
cur->next = ailp->xa_cursors.next;
ailp->xa_cursors.next = cur;
} }
/* /*
* Get the next item in the traversal and advance the cursor. * Get the next item in the traversal and advance the cursor. If the cursor
* If the cursor was invalidated (inidicated by a lip of 1), * was invalidated (indicated by a lip of 1), restart the traversal.
* restart the traversal.
*/ */
struct xfs_log_item * struct xfs_log_item *
xfs_trans_ail_cursor_next( xfs_trans_ail_cursor_next(
...@@ -208,40 +197,25 @@ xfs_trans_ail_cursor_next( ...@@ -208,40 +197,25 @@ xfs_trans_ail_cursor_next(
} }
/* /*
* Now that the traversal is complete, we need to remove the cursor * When the traversal is complete, we need to remove the cursor from the list
* from the list of traversing cursors. Avoid removing the embedded * of traversing cursors.
* push cursor, but use the fact it is always present to make the
* list deletion simple.
*/ */
void void
xfs_trans_ail_cursor_done( xfs_trans_ail_cursor_done(
struct xfs_ail *ailp, struct xfs_ail *ailp,
struct xfs_ail_cursor *done) struct xfs_ail_cursor *cur)
{ {
struct xfs_ail_cursor *prev = NULL; cur->item = NULL;
struct xfs_ail_cursor *cur; list_del_init(&cur->list);
done->item = NULL;
if (done == &ailp->xa_cursors)
return;
prev = &ailp->xa_cursors;
for (cur = prev->next; cur; prev = cur, cur = prev->next) {
if (cur == done) {
prev->next = cur->next;
break;
}
}
ASSERT(cur);
} }
/* /*
* Invalidate any cursor that is pointing to this item. This is * Invalidate any cursor that is pointing to this item. This is called when an
* called when an item is removed from the AIL. Any cursor pointing * item is removed from the AIL. Any cursor pointing to this object is now
* to this object is now invalid and the traversal needs to be * invalid and the traversal needs to be terminated so it doesn't reference a
* terminated so it doesn't reference a freed object. We set the * freed object. We set the low bit of the cursor item pointer so we can
* cursor item to a value of 1 so we can distinguish between an * distinguish between an invalidation and the end of the list when getting the
* invalidation and the end of the list when getting the next item * next item from the cursor.
* from the cursor.
*/ */
STATIC void STATIC void
xfs_trans_ail_cursor_clear( xfs_trans_ail_cursor_clear(
...@@ -250,8 +224,7 @@ xfs_trans_ail_cursor_clear( ...@@ -250,8 +224,7 @@ xfs_trans_ail_cursor_clear(
{ {
struct xfs_ail_cursor *cur; struct xfs_ail_cursor *cur;
/* need to search all cursors */ list_for_each_entry(cur, &ailp->xa_cursors, list) {
for (cur = &ailp->xa_cursors; cur; cur = cur->next) {
if (cur->item == lip) if (cur->item == lip)
cur->item = (struct xfs_log_item *) cur->item = (struct xfs_log_item *)
((__psint_t)cur->item | 1); ((__psint_t)cur->item | 1);
...@@ -405,7 +378,7 @@ xfs_ail_worker( ...@@ -405,7 +378,7 @@ xfs_ail_worker(
struct xfs_ail *ailp = container_of(to_delayed_work(work), struct xfs_ail *ailp = container_of(to_delayed_work(work),
struct xfs_ail, xa_work); struct xfs_ail, xa_work);
xfs_mount_t *mp = ailp->xa_mount; xfs_mount_t *mp = ailp->xa_mount;
struct xfs_ail_cursor *cur = &ailp->xa_cursors; struct xfs_ail_cursor cur;
xfs_log_item_t *lip; xfs_log_item_t *lip;
xfs_lsn_t lsn; xfs_lsn_t lsn;
xfs_lsn_t target; xfs_lsn_t target;
...@@ -417,13 +390,12 @@ xfs_ail_worker( ...@@ -417,13 +390,12 @@ xfs_ail_worker(
spin_lock(&ailp->xa_lock); spin_lock(&ailp->xa_lock);
target = ailp->xa_target; target = ailp->xa_target;
xfs_trans_ail_cursor_init(ailp, cur); lip = xfs_trans_ail_cursor_first(ailp, &cur, ailp->xa_last_pushed_lsn);
lip = xfs_trans_ail_cursor_first(ailp, cur, ailp->xa_last_pushed_lsn);
if (!lip || XFS_FORCED_SHUTDOWN(mp)) { if (!lip || XFS_FORCED_SHUTDOWN(mp)) {
/* /*
* AIL is empty or our push has reached the end. * AIL is empty or our push has reached the end.
*/ */
xfs_trans_ail_cursor_done(ailp, cur); xfs_trans_ail_cursor_done(ailp, &cur);
spin_unlock(&ailp->xa_lock); spin_unlock(&ailp->xa_lock);
goto out_done; goto out_done;
} }
...@@ -511,12 +483,12 @@ xfs_ail_worker( ...@@ -511,12 +483,12 @@ xfs_ail_worker(
if (stuck > 100) if (stuck > 100)
break; break;
lip = xfs_trans_ail_cursor_next(ailp, cur); lip = xfs_trans_ail_cursor_next(ailp, &cur);
if (lip == NULL) if (lip == NULL)
break; break;
lsn = lip->li_lsn; lsn = lip->li_lsn;
} }
xfs_trans_ail_cursor_done(ailp, cur); xfs_trans_ail_cursor_done(ailp, &cur);
spin_unlock(&ailp->xa_lock); spin_unlock(&ailp->xa_lock);
if (flush_log) { if (flush_log) {
...@@ -848,6 +820,7 @@ xfs_trans_ail_init( ...@@ -848,6 +820,7 @@ xfs_trans_ail_init(
ailp->xa_mount = mp; ailp->xa_mount = mp;
INIT_LIST_HEAD(&ailp->xa_ail); INIT_LIST_HEAD(&ailp->xa_ail);
INIT_LIST_HEAD(&ailp->xa_cursors);
spin_lock_init(&ailp->xa_lock); spin_lock_init(&ailp->xa_lock);
INIT_DELAYED_WORK(&ailp->xa_work, xfs_ail_worker); INIT_DELAYED_WORK(&ailp->xa_work, xfs_ail_worker);
mp->m_ail = ailp; mp->m_ail = ailp;
......
...@@ -53,7 +53,7 @@ void xfs_trans_committed_bulk(struct xfs_ail *ailp, struct xfs_log_vec *lv, ...@@ -53,7 +53,7 @@ void xfs_trans_committed_bulk(struct xfs_ail *ailp, struct xfs_log_vec *lv,
* of the list to trigger traversal restarts. * of the list to trigger traversal restarts.
*/ */
struct xfs_ail_cursor { struct xfs_ail_cursor {
struct xfs_ail_cursor *next; struct list_head list;
struct xfs_log_item *item; struct xfs_log_item *item;
}; };
...@@ -66,7 +66,7 @@ struct xfs_ail { ...@@ -66,7 +66,7 @@ struct xfs_ail {
struct xfs_mount *xa_mount; struct xfs_mount *xa_mount;
struct list_head xa_ail; struct list_head xa_ail;
xfs_lsn_t xa_target; xfs_lsn_t xa_target;
struct xfs_ail_cursor xa_cursors; struct list_head xa_cursors;
spinlock_t xa_lock; spinlock_t xa_lock;
struct delayed_work xa_work; struct delayed_work xa_work;
xfs_lsn_t xa_last_pushed_lsn; xfs_lsn_t xa_last_pushed_lsn;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment