aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;