diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/libxfs/xfs_defer.c | 50 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_defer.h | 31 | ||||
-rw-r--r-- | fs/xfs/xfs_trace.h | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_trans_bmap.c | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_trans_extfree.c | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_trans_refcount.c | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_trans_rmap.c | 1 |
7 files changed, 43 insertions, 45 deletions
diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index 277117a8ad13..94f00427de98 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c | |||
@@ -191,15 +191,15 @@ xfs_defer_create_intents( | |||
191 | { | 191 | { |
192 | struct list_head *li; | 192 | struct list_head *li; |
193 | struct xfs_defer_pending *dfp; | 193 | struct xfs_defer_pending *dfp; |
194 | const struct xfs_defer_op_type *ops; | ||
194 | 195 | ||
195 | list_for_each_entry(dfp, &tp->t_dfops, dfp_list) { | 196 | list_for_each_entry(dfp, &tp->t_dfops, dfp_list) { |
196 | dfp->dfp_intent = dfp->dfp_type->create_intent(tp, | 197 | ops = defer_op_types[dfp->dfp_type]; |
197 | dfp->dfp_count); | 198 | dfp->dfp_intent = ops->create_intent(tp, dfp->dfp_count); |
198 | trace_xfs_defer_create_intent(tp->t_mountp, dfp); | 199 | trace_xfs_defer_create_intent(tp->t_mountp, dfp); |
199 | list_sort(tp->t_mountp, &dfp->dfp_work, | 200 | list_sort(tp->t_mountp, &dfp->dfp_work, ops->diff_items); |
200 | dfp->dfp_type->diff_items); | ||
201 | list_for_each(li, &dfp->dfp_work) | 201 | list_for_each(li, &dfp->dfp_work) |
202 | dfp->dfp_type->log_item(tp, dfp->dfp_intent, li); | 202 | ops->log_item(tp, dfp->dfp_intent, li); |
203 | } | 203 | } |
204 | } | 204 | } |
205 | 205 | ||
@@ -210,14 +210,16 @@ xfs_defer_trans_abort( | |||
210 | struct list_head *dop_pending) | 210 | struct list_head *dop_pending) |
211 | { | 211 | { |
212 | struct xfs_defer_pending *dfp; | 212 | struct xfs_defer_pending *dfp; |
213 | const struct xfs_defer_op_type *ops; | ||
213 | 214 | ||
214 | trace_xfs_defer_trans_abort(tp, _RET_IP_); | 215 | trace_xfs_defer_trans_abort(tp, _RET_IP_); |
215 | 216 | ||
216 | /* Abort intent items that don't have a done item. */ | 217 | /* Abort intent items that don't have a done item. */ |
217 | list_for_each_entry(dfp, dop_pending, dfp_list) { | 218 | list_for_each_entry(dfp, dop_pending, dfp_list) { |
219 | ops = defer_op_types[dfp->dfp_type]; | ||
218 | trace_xfs_defer_pending_abort(tp->t_mountp, dfp); | 220 | trace_xfs_defer_pending_abort(tp->t_mountp, dfp); |
219 | if (dfp->dfp_intent && !dfp->dfp_done) { | 221 | if (dfp->dfp_intent && !dfp->dfp_done) { |
220 | dfp->dfp_type->abort_intent(dfp->dfp_intent); | 222 | ops->abort_intent(dfp->dfp_intent); |
221 | dfp->dfp_intent = NULL; | 223 | dfp->dfp_intent = NULL; |
222 | } | 224 | } |
223 | } | 225 | } |
@@ -321,18 +323,20 @@ xfs_defer_cancel_list( | |||
321 | struct xfs_defer_pending *pli; | 323 | struct xfs_defer_pending *pli; |
322 | struct list_head *pwi; | 324 | struct list_head *pwi; |
323 | struct list_head *n; | 325 | struct list_head *n; |
326 | const struct xfs_defer_op_type *ops; | ||
324 | 327 | ||
325 | /* | 328 | /* |
326 | * Free the pending items. Caller should already have arranged | 329 | * Free the pending items. Caller should already have arranged |
327 | * for the intent items to be released. | 330 | * for the intent items to be released. |
328 | */ | 331 | */ |
329 | list_for_each_entry_safe(dfp, pli, dop_list, dfp_list) { | 332 | list_for_each_entry_safe(dfp, pli, dop_list, dfp_list) { |
333 | ops = defer_op_types[dfp->dfp_type]; | ||
330 | trace_xfs_defer_cancel_list(mp, dfp); | 334 | trace_xfs_defer_cancel_list(mp, dfp); |
331 | list_del(&dfp->dfp_list); | 335 | list_del(&dfp->dfp_list); |
332 | list_for_each_safe(pwi, n, &dfp->dfp_work) { | 336 | list_for_each_safe(pwi, n, &dfp->dfp_work) { |
333 | list_del(pwi); | 337 | list_del(pwi); |
334 | dfp->dfp_count--; | 338 | dfp->dfp_count--; |
335 | dfp->dfp_type->cancel_item(pwi); | 339 | ops->cancel_item(pwi); |
336 | } | 340 | } |
337 | ASSERT(dfp->dfp_count == 0); | 341 | ASSERT(dfp->dfp_count == 0); |
338 | kmem_free(dfp); | 342 | kmem_free(dfp); |
@@ -356,7 +360,7 @@ xfs_defer_finish_noroll( | |||
356 | struct list_head *n; | 360 | struct list_head *n; |
357 | void *state; | 361 | void *state; |
358 | int error = 0; | 362 | int error = 0; |
359 | void (*cleanup_fn)(struct xfs_trans *, void *, int); | 363 | const struct xfs_defer_op_type *ops; |
360 | LIST_HEAD(dop_pending); | 364 | LIST_HEAD(dop_pending); |
361 | 365 | ||
362 | ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); | 366 | ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); |
@@ -379,18 +383,18 @@ xfs_defer_finish_noroll( | |||
379 | /* Log an intent-done item for the first pending item. */ | 383 | /* Log an intent-done item for the first pending item. */ |
380 | dfp = list_first_entry(&dop_pending, struct xfs_defer_pending, | 384 | dfp = list_first_entry(&dop_pending, struct xfs_defer_pending, |
381 | dfp_list); | 385 | dfp_list); |
386 | ops = defer_op_types[dfp->dfp_type]; | ||
382 | trace_xfs_defer_pending_finish((*tp)->t_mountp, dfp); | 387 | trace_xfs_defer_pending_finish((*tp)->t_mountp, dfp); |
383 | dfp->dfp_done = dfp->dfp_type->create_done(*tp, dfp->dfp_intent, | 388 | dfp->dfp_done = ops->create_done(*tp, dfp->dfp_intent, |
384 | dfp->dfp_count); | 389 | dfp->dfp_count); |
385 | cleanup_fn = dfp->dfp_type->finish_cleanup; | ||
386 | 390 | ||
387 | /* Finish the work items. */ | 391 | /* Finish the work items. */ |
388 | state = NULL; | 392 | state = NULL; |
389 | list_for_each_safe(li, n, &dfp->dfp_work) { | 393 | list_for_each_safe(li, n, &dfp->dfp_work) { |
390 | list_del(li); | 394 | list_del(li); |
391 | dfp->dfp_count--; | 395 | dfp->dfp_count--; |
392 | error = dfp->dfp_type->finish_item(*tp, li, | 396 | error = ops->finish_item(*tp, li, dfp->dfp_done, |
393 | dfp->dfp_done, &state); | 397 | &state); |
394 | if (error == -EAGAIN) { | 398 | if (error == -EAGAIN) { |
395 | /* | 399 | /* |
396 | * Caller wants a fresh transaction; | 400 | * Caller wants a fresh transaction; |
@@ -406,8 +410,8 @@ xfs_defer_finish_noroll( | |||
406 | * xfs_defer_cancel will take care of freeing | 410 | * xfs_defer_cancel will take care of freeing |
407 | * all these lists and stuff. | 411 | * all these lists and stuff. |
408 | */ | 412 | */ |
409 | if (cleanup_fn) | 413 | if (ops->finish_cleanup) |
410 | cleanup_fn(*tp, state, error); | 414 | ops->finish_cleanup(*tp, state, error); |
411 | goto out; | 415 | goto out; |
412 | } | 416 | } |
413 | } | 417 | } |
@@ -419,20 +423,19 @@ xfs_defer_finish_noroll( | |||
419 | * a Fresh Transaction while Finishing | 423 | * a Fresh Transaction while Finishing |
420 | * Deferred Work" above. | 424 | * Deferred Work" above. |
421 | */ | 425 | */ |
422 | dfp->dfp_intent = dfp->dfp_type->create_intent(*tp, | 426 | dfp->dfp_intent = ops->create_intent(*tp, |
423 | dfp->dfp_count); | 427 | dfp->dfp_count); |
424 | dfp->dfp_done = NULL; | 428 | dfp->dfp_done = NULL; |
425 | list_for_each(li, &dfp->dfp_work) | 429 | list_for_each(li, &dfp->dfp_work) |
426 | dfp->dfp_type->log_item(*tp, dfp->dfp_intent, | 430 | ops->log_item(*tp, dfp->dfp_intent, li); |
427 | li); | ||
428 | } else { | 431 | } else { |
429 | /* Done with the dfp, free it. */ | 432 | /* Done with the dfp, free it. */ |
430 | list_del(&dfp->dfp_list); | 433 | list_del(&dfp->dfp_list); |
431 | kmem_free(dfp); | 434 | kmem_free(dfp); |
432 | } | 435 | } |
433 | 436 | ||
434 | if (cleanup_fn) | 437 | if (ops->finish_cleanup) |
435 | cleanup_fn(*tp, state, error); | 438 | ops->finish_cleanup(*tp, state, error); |
436 | } | 439 | } |
437 | 440 | ||
438 | out: | 441 | out: |
@@ -492,6 +495,7 @@ xfs_defer_add( | |||
492 | struct list_head *li) | 495 | struct list_head *li) |
493 | { | 496 | { |
494 | struct xfs_defer_pending *dfp = NULL; | 497 | struct xfs_defer_pending *dfp = NULL; |
498 | const struct xfs_defer_op_type *ops; | ||
495 | 499 | ||
496 | ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); | 500 | ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); |
497 | BUILD_BUG_ON(ARRAY_SIZE(defer_op_types) != XFS_DEFER_OPS_TYPE_MAX); | 501 | BUILD_BUG_ON(ARRAY_SIZE(defer_op_types) != XFS_DEFER_OPS_TYPE_MAX); |
@@ -504,15 +508,15 @@ xfs_defer_add( | |||
504 | if (!list_empty(&tp->t_dfops)) { | 508 | if (!list_empty(&tp->t_dfops)) { |
505 | dfp = list_last_entry(&tp->t_dfops, | 509 | dfp = list_last_entry(&tp->t_dfops, |
506 | struct xfs_defer_pending, dfp_list); | 510 | struct xfs_defer_pending, dfp_list); |
507 | if (dfp->dfp_type->type != type || | 511 | ops = defer_op_types[dfp->dfp_type]; |
508 | (dfp->dfp_type->max_items && | 512 | if (dfp->dfp_type != type || |
509 | dfp->dfp_count >= dfp->dfp_type->max_items)) | 513 | (ops->max_items && dfp->dfp_count >= ops->max_items)) |
510 | dfp = NULL; | 514 | dfp = NULL; |
511 | } | 515 | } |
512 | if (!dfp) { | 516 | if (!dfp) { |
513 | dfp = kmem_alloc(sizeof(struct xfs_defer_pending), | 517 | dfp = kmem_alloc(sizeof(struct xfs_defer_pending), |
514 | KM_SLEEP | KM_NOFS); | 518 | KM_SLEEP | KM_NOFS); |
515 | dfp->dfp_type = defer_op_types[type]; | 519 | dfp->dfp_type = type; |
516 | dfp->dfp_intent = NULL; | 520 | dfp->dfp_intent = NULL; |
517 | dfp->dfp_done = NULL; | 521 | dfp->dfp_done = NULL; |
518 | dfp->dfp_count = 0; | 522 | dfp->dfp_count = 0; |
diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index 0a4b88e3df74..7c28d7608ac6 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h | |||
@@ -9,20 +9,6 @@ | |||
9 | struct xfs_defer_op_type; | 9 | struct xfs_defer_op_type; |
10 | 10 | ||
11 | /* | 11 | /* |
12 | * Save a log intent item and a list of extents, so that we can replay | ||
13 | * whatever action had to happen to the extent list and file the log done | ||
14 | * item. | ||
15 | */ | ||
16 | struct xfs_defer_pending { | ||
17 | const struct xfs_defer_op_type *dfp_type; /* function pointers */ | ||
18 | struct list_head dfp_list; /* pending items */ | ||
19 | void *dfp_intent; /* log intent item */ | ||
20 | void *dfp_done; /* log done item */ | ||
21 | struct list_head dfp_work; /* work items */ | ||
22 | unsigned int dfp_count; /* # extent items */ | ||
23 | }; | ||
24 | |||
25 | /* | ||
26 | * Header for deferred operation list. | 12 | * Header for deferred operation list. |
27 | */ | 13 | */ |
28 | enum xfs_defer_ops_type { | 14 | enum xfs_defer_ops_type { |
@@ -34,6 +20,20 @@ enum xfs_defer_ops_type { | |||
34 | XFS_DEFER_OPS_TYPE_MAX, | 20 | XFS_DEFER_OPS_TYPE_MAX, |
35 | }; | 21 | }; |
36 | 22 | ||
23 | /* | ||
24 | * Save a log intent item and a list of extents, so that we can replay | ||
25 | * whatever action had to happen to the extent list and file the log done | ||
26 | * item. | ||
27 | */ | ||
28 | struct xfs_defer_pending { | ||
29 | struct list_head dfp_list; /* pending items */ | ||
30 | struct list_head dfp_work; /* work items */ | ||
31 | void *dfp_intent; /* log intent item */ | ||
32 | void *dfp_done; /* log done item */ | ||
33 | unsigned int dfp_count; /* # extent items */ | ||
34 | enum xfs_defer_ops_type dfp_type; | ||
35 | }; | ||
36 | |||
37 | void xfs_defer_add(struct xfs_trans *tp, enum xfs_defer_ops_type type, | 37 | void xfs_defer_add(struct xfs_trans *tp, enum xfs_defer_ops_type type, |
38 | struct list_head *h); | 38 | struct list_head *h); |
39 | int xfs_defer_finish_noroll(struct xfs_trans **tp); | 39 | int xfs_defer_finish_noroll(struct xfs_trans **tp); |
@@ -43,8 +43,6 @@ void xfs_defer_move(struct xfs_trans *dtp, struct xfs_trans *stp); | |||
43 | 43 | ||
44 | /* Description of a deferred type. */ | 44 | /* Description of a deferred type. */ |
45 | struct xfs_defer_op_type { | 45 | struct xfs_defer_op_type { |
46 | enum xfs_defer_ops_type type; | ||
47 | unsigned int max_items; | ||
48 | void (*abort_intent)(void *); | 46 | void (*abort_intent)(void *); |
49 | void *(*create_done)(struct xfs_trans *, void *, unsigned int); | 47 | void *(*create_done)(struct xfs_trans *, void *, unsigned int); |
50 | int (*finish_item)(struct xfs_trans *, struct list_head *, void *, | 48 | int (*finish_item)(struct xfs_trans *, struct list_head *, void *, |
@@ -54,6 +52,7 @@ struct xfs_defer_op_type { | |||
54 | int (*diff_items)(void *, struct list_head *, struct list_head *); | 52 | int (*diff_items)(void *, struct list_head *, struct list_head *); |
55 | void *(*create_intent)(struct xfs_trans *, uint); | 53 | void *(*create_intent)(struct xfs_trans *, uint); |
56 | void (*log_item)(struct xfs_trans *, void *, struct list_head *); | 54 | void (*log_item)(struct xfs_trans *, void *, struct list_head *); |
55 | unsigned int max_items; | ||
57 | }; | 56 | }; |
58 | 57 | ||
59 | extern const struct xfs_defer_op_type xfs_bmap_update_defer_type; | 58 | extern const struct xfs_defer_op_type xfs_bmap_update_defer_type; |
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 8a6532aae779..affa38b6c576 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h | |||
@@ -2276,7 +2276,7 @@ DECLARE_EVENT_CLASS(xfs_defer_pending_class, | |||
2276 | ), | 2276 | ), |
2277 | TP_fast_assign( | 2277 | TP_fast_assign( |
2278 | __entry->dev = mp ? mp->m_super->s_dev : 0; | 2278 | __entry->dev = mp ? mp->m_super->s_dev : 0; |
2279 | __entry->type = dfp->dfp_type->type; | 2279 | __entry->type = dfp->dfp_type; |
2280 | __entry->intent = dfp->dfp_intent; | 2280 | __entry->intent = dfp->dfp_intent; |
2281 | __entry->committed = dfp->dfp_done != NULL; | 2281 | __entry->committed = dfp->dfp_done != NULL; |
2282 | __entry->nr = dfp->dfp_count; | 2282 | __entry->nr = dfp->dfp_count; |
diff --git a/fs/xfs/xfs_trans_bmap.c b/fs/xfs/xfs_trans_bmap.c index e027e68b4f9e..11cff449d055 100644 --- a/fs/xfs/xfs_trans_bmap.c +++ b/fs/xfs/xfs_trans_bmap.c | |||
@@ -222,7 +222,6 @@ xfs_bmap_update_cancel_item( | |||
222 | } | 222 | } |
223 | 223 | ||
224 | const struct xfs_defer_op_type xfs_bmap_update_defer_type = { | 224 | const struct xfs_defer_op_type xfs_bmap_update_defer_type = { |
225 | .type = XFS_DEFER_OPS_TYPE_BMAP, | ||
226 | .max_items = XFS_BUI_MAX_FAST_EXTENTS, | 225 | .max_items = XFS_BUI_MAX_FAST_EXTENTS, |
227 | .diff_items = xfs_bmap_update_diff_items, | 226 | .diff_items = xfs_bmap_update_diff_items, |
228 | .create_intent = xfs_bmap_update_create_intent, | 227 | .create_intent = xfs_bmap_update_create_intent, |
diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c index 1872962aa470..73b11ed6795e 100644 --- a/fs/xfs/xfs_trans_extfree.c +++ b/fs/xfs/xfs_trans_extfree.c | |||
@@ -208,7 +208,6 @@ xfs_extent_free_cancel_item( | |||
208 | } | 208 | } |
209 | 209 | ||
210 | const struct xfs_defer_op_type xfs_extent_free_defer_type = { | 210 | const struct xfs_defer_op_type xfs_extent_free_defer_type = { |
211 | .type = XFS_DEFER_OPS_TYPE_FREE, | ||
212 | .max_items = XFS_EFI_MAX_FAST_EXTENTS, | 211 | .max_items = XFS_EFI_MAX_FAST_EXTENTS, |
213 | .diff_items = xfs_extent_free_diff_items, | 212 | .diff_items = xfs_extent_free_diff_items, |
214 | .create_intent = xfs_extent_free_create_intent, | 213 | .create_intent = xfs_extent_free_create_intent, |
@@ -276,7 +275,6 @@ xfs_agfl_free_finish_item( | |||
276 | 275 | ||
277 | /* sub-type with special handling for AGFL deferred frees */ | 276 | /* sub-type with special handling for AGFL deferred frees */ |
278 | const struct xfs_defer_op_type xfs_agfl_free_defer_type = { | 277 | const struct xfs_defer_op_type xfs_agfl_free_defer_type = { |
279 | .type = XFS_DEFER_OPS_TYPE_AGFL_FREE, | ||
280 | .max_items = XFS_EFI_MAX_FAST_EXTENTS, | 278 | .max_items = XFS_EFI_MAX_FAST_EXTENTS, |
281 | .diff_items = xfs_extent_free_diff_items, | 279 | .diff_items = xfs_extent_free_diff_items, |
282 | .create_intent = xfs_extent_free_create_intent, | 280 | .create_intent = xfs_extent_free_create_intent, |
diff --git a/fs/xfs/xfs_trans_refcount.c b/fs/xfs/xfs_trans_refcount.c index 116c040d54bd..6c947ff4faf6 100644 --- a/fs/xfs/xfs_trans_refcount.c +++ b/fs/xfs/xfs_trans_refcount.c | |||
@@ -229,7 +229,6 @@ xfs_refcount_update_cancel_item( | |||
229 | } | 229 | } |
230 | 230 | ||
231 | const struct xfs_defer_op_type xfs_refcount_update_defer_type = { | 231 | const struct xfs_defer_op_type xfs_refcount_update_defer_type = { |
232 | .type = XFS_DEFER_OPS_TYPE_REFCOUNT, | ||
233 | .max_items = XFS_CUI_MAX_FAST_EXTENTS, | 232 | .max_items = XFS_CUI_MAX_FAST_EXTENTS, |
234 | .diff_items = xfs_refcount_update_diff_items, | 233 | .diff_items = xfs_refcount_update_diff_items, |
235 | .create_intent = xfs_refcount_update_create_intent, | 234 | .create_intent = xfs_refcount_update_create_intent, |
diff --git a/fs/xfs/xfs_trans_rmap.c b/fs/xfs/xfs_trans_rmap.c index f75cdc5b578a..a42890931ecd 100644 --- a/fs/xfs/xfs_trans_rmap.c +++ b/fs/xfs/xfs_trans_rmap.c | |||
@@ -246,7 +246,6 @@ xfs_rmap_update_cancel_item( | |||
246 | } | 246 | } |
247 | 247 | ||
248 | const struct xfs_defer_op_type xfs_rmap_update_defer_type = { | 248 | const struct xfs_defer_op_type xfs_rmap_update_defer_type = { |
249 | .type = XFS_DEFER_OPS_TYPE_RMAP, | ||
250 | .max_items = XFS_RUI_MAX_FAST_EXTENTS, | 249 | .max_items = XFS_RUI_MAX_FAST_EXTENTS, |
251 | .diff_items = xfs_rmap_update_diff_items, | 250 | .diff_items = xfs_rmap_update_diff_items, |
252 | .create_intent = xfs_rmap_update_create_intent, | 251 | .create_intent = xfs_rmap_update_create_intent, |