aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2011-07-17 23:40:18 -0400
committerAlex Elder <aelder@sgi.com>2011-07-20 19:37:46 -0400
commitaf3e40228fb2dbc18d94fbd5103f07344a720ae7 (patch)
treee33bac82ebcf5fccf7f3d25cb8dc9b764736fc06
parent16b5902943c793e632cf8c9526619f59893bdc29 (diff)
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: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Alex Elder <aelder@sgi.com>
-rw-r--r--fs/xfs/xfs_trans_ail.c79
-rw-r--r--fs/xfs/xfs_trans_priv.h4
2 files changed, 28 insertions, 55 deletions
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index 7908c798a02b..43233e92f0f6 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -163,17 +163,11 @@ xfs_ail_max_lsn(
163} 163}
164 164
165/* 165/*
166 * AIL traversal cursor initialisation. 166 * The cursor keeps track of where our current traversal is up to by tracking
167 * 167 * the next item in the list for us. However, for this to be safe, removing an
168 * The cursor keeps track of where our current traversal is up 168 * object from the AIL needs to invalidate any cursor that points to it. hence
169 * to by tracking the next ƣtem in the list for us. However, for 169 * the traversal cursor needs to be linked to the struct xfs_ail so that
170 * this to be safe, removing an object from the AIL needs to invalidate 170 * deletion can search all the active cursors for invalidation.
171 * any cursor that points to it. hence the traversal cursor needs to
172 * be linked to the struct xfs_ail so that deletion can search all the
173 * active cursors for invalidation.
174 *
175 * We don't link the push cursor because it is embedded in the struct
176 * xfs_ail and hence easily findable.
177 */ 171 */
178STATIC void 172STATIC void
179xfs_trans_ail_cursor_init( 173xfs_trans_ail_cursor_init(
@@ -181,17 +175,12 @@ xfs_trans_ail_cursor_init(
181 struct xfs_ail_cursor *cur) 175 struct xfs_ail_cursor *cur)
182{ 176{
183 cur->item = NULL; 177 cur->item = NULL;
184 if (cur == &ailp->xa_cursors) 178 list_add_tail(&cur->list, &ailp->xa_cursors);
185 return;
186
187 cur->next = ailp->xa_cursors.next;
188 ailp->xa_cursors.next = cur;
189} 179}
190 180
191/* 181/*
192 * Get the next item in the traversal and advance the cursor. 182 * Get the next item in the traversal and advance the cursor. If the cursor
193 * If the cursor was invalidated (inidicated by a lip of 1), 183 * was invalidated (indicated by a lip of 1), restart the traversal.
194 * restart the traversal.
195 */ 184 */
196struct xfs_log_item * 185struct xfs_log_item *
197xfs_trans_ail_cursor_next( 186xfs_trans_ail_cursor_next(
@@ -208,40 +197,25 @@ xfs_trans_ail_cursor_next(
208} 197}
209 198
210/* 199/*
211 * Now that the traversal is complete, we need to remove the cursor 200 * When the traversal is complete, we need to remove the cursor from the list
212 * from the list of traversing cursors. Avoid removing the embedded 201 * of traversing cursors.
213 * push cursor, but use the fact it is always present to make the
214 * list deletion simple.
215 */ 202 */
216void 203void
217xfs_trans_ail_cursor_done( 204xfs_trans_ail_cursor_done(
218 struct xfs_ail *ailp, 205 struct xfs_ail *ailp,
219 struct xfs_ail_cursor *done) 206 struct xfs_ail_cursor *cur)
220{ 207{
221 struct xfs_ail_cursor *prev = NULL; 208 cur->item = NULL;
222 struct xfs_ail_cursor *cur; 209 list_del_init(&cur->list);
223
224 done->item = NULL;
225 if (done == &ailp->xa_cursors)
226 return;
227 prev = &ailp->xa_cursors;
228 for (cur = prev->next; cur; prev = cur, cur = prev->next) {
229 if (cur == done) {
230 prev->next = cur->next;
231 break;
232 }
233 }
234 ASSERT(cur);
235} 210}
236 211
237/* 212/*
238 * Invalidate any cursor that is pointing to this item. This is 213 * Invalidate any cursor that is pointing to this item. This is called when an
239 * called when an item is removed from the AIL. Any cursor pointing 214 * item is removed from the AIL. Any cursor pointing to this object is now
240 * to this object is now invalid and the traversal needs to be 215 * invalid and the traversal needs to be terminated so it doesn't reference a
241 * terminated so it doesn't reference a freed object. We set the 216 * freed object. We set the low bit of the cursor item pointer so we can
242 * cursor item to a value of 1 so we can distinguish between an 217 * distinguish between an invalidation and the end of the list when getting the
243 * invalidation and the end of the list when getting the next item 218 * next item from the cursor.
244 * from the cursor.
245 */ 219 */
246STATIC void 220STATIC void
247xfs_trans_ail_cursor_clear( 221xfs_trans_ail_cursor_clear(
@@ -250,8 +224,7 @@ xfs_trans_ail_cursor_clear(
250{ 224{
251 struct xfs_ail_cursor *cur; 225 struct xfs_ail_cursor *cur;
252 226
253 /* need to search all cursors */ 227 list_for_each_entry(cur, &ailp->xa_cursors, list) {
254 for (cur = &ailp->xa_cursors; cur; cur = cur->next) {
255 if (cur->item == lip) 228 if (cur->item == lip)
256 cur->item = (struct xfs_log_item *) 229 cur->item = (struct xfs_log_item *)
257 ((__psint_t)cur->item | 1); 230 ((__psint_t)cur->item | 1);
@@ -405,7 +378,7 @@ xfs_ail_worker(
405 struct xfs_ail *ailp = container_of(to_delayed_work(work), 378 struct xfs_ail *ailp = container_of(to_delayed_work(work),
406 struct xfs_ail, xa_work); 379 struct xfs_ail, xa_work);
407 xfs_mount_t *mp = ailp->xa_mount; 380 xfs_mount_t *mp = ailp->xa_mount;
408 struct xfs_ail_cursor *cur = &ailp->xa_cursors; 381 struct xfs_ail_cursor cur;
409 xfs_log_item_t *lip; 382 xfs_log_item_t *lip;
410 xfs_lsn_t lsn; 383 xfs_lsn_t lsn;
411 xfs_lsn_t target; 384 xfs_lsn_t target;
@@ -417,13 +390,12 @@ xfs_ail_worker(
417 390
418 spin_lock(&ailp->xa_lock); 391 spin_lock(&ailp->xa_lock);
419 target = ailp->xa_target; 392 target = ailp->xa_target;
420 xfs_trans_ail_cursor_init(ailp, cur); 393 lip = xfs_trans_ail_cursor_first(ailp, &cur, ailp->xa_last_pushed_lsn);
421 lip = xfs_trans_ail_cursor_first(ailp, cur, ailp->xa_last_pushed_lsn);
422 if (!lip || XFS_FORCED_SHUTDOWN(mp)) { 394 if (!lip || XFS_FORCED_SHUTDOWN(mp)) {
423 /* 395 /*
424 * AIL is empty or our push has reached the end. 396 * AIL is empty or our push has reached the end.
425 */ 397 */
426 xfs_trans_ail_cursor_done(ailp, cur); 398 xfs_trans_ail_cursor_done(ailp, &cur);
427 spin_unlock(&ailp->xa_lock); 399 spin_unlock(&ailp->xa_lock);
428 goto out_done; 400 goto out_done;
429 } 401 }
@@ -511,12 +483,12 @@ xfs_ail_worker(
511 if (stuck > 100) 483 if (stuck > 100)
512 break; 484 break;
513 485
514 lip = xfs_trans_ail_cursor_next(ailp, cur); 486 lip = xfs_trans_ail_cursor_next(ailp, &cur);
515 if (lip == NULL) 487 if (lip == NULL)
516 break; 488 break;
517 lsn = lip->li_lsn; 489 lsn = lip->li_lsn;
518 } 490 }
519 xfs_trans_ail_cursor_done(ailp, cur); 491 xfs_trans_ail_cursor_done(ailp, &cur);
520 spin_unlock(&ailp->xa_lock); 492 spin_unlock(&ailp->xa_lock);
521 493
522 if (flush_log) { 494 if (flush_log) {
@@ -848,6 +820,7 @@ xfs_trans_ail_init(
848 820
849 ailp->xa_mount = mp; 821 ailp->xa_mount = mp;
850 INIT_LIST_HEAD(&ailp->xa_ail); 822 INIT_LIST_HEAD(&ailp->xa_ail);
823 INIT_LIST_HEAD(&ailp->xa_cursors);
851 spin_lock_init(&ailp->xa_lock); 824 spin_lock_init(&ailp->xa_lock);
852 INIT_DELAYED_WORK(&ailp->xa_work, xfs_ail_worker); 825 INIT_DELAYED_WORK(&ailp->xa_work, xfs_ail_worker);
853 mp->m_ail = ailp; 826 mp->m_ail = ailp;
diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h
index c0cb40890329..212946b97239 100644
--- a/fs/xfs/xfs_trans_priv.h
+++ b/fs/xfs/xfs_trans_priv.h
@@ -53,7 +53,7 @@ void xfs_trans_committed_bulk(struct xfs_ail *ailp, struct xfs_log_vec *lv,
53 * of the list to trigger traversal restarts. 53 * of the list to trigger traversal restarts.
54 */ 54 */
55struct xfs_ail_cursor { 55struct xfs_ail_cursor {
56 struct xfs_ail_cursor *next; 56 struct list_head list;
57 struct xfs_log_item *item; 57 struct xfs_log_item *item;
58}; 58};
59 59
@@ -66,7 +66,7 @@ struct xfs_ail {
66 struct xfs_mount *xa_mount; 66 struct xfs_mount *xa_mount;
67 struct list_head xa_ail; 67 struct list_head xa_ail;
68 xfs_lsn_t xa_target; 68 xfs_lsn_t xa_target;
69 struct xfs_ail_cursor xa_cursors; 69 struct list_head xa_cursors;
70 spinlock_t xa_lock; 70 spinlock_t xa_lock;
71 struct delayed_work xa_work; 71 struct delayed_work xa_work;
72 xfs_lsn_t xa_last_pushed_lsn; 72 xfs_lsn_t xa_last_pushed_lsn;