aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/libxfs/xfs_defer.c50
-rw-r--r--fs/xfs/libxfs/xfs_defer.h31
-rw-r--r--fs/xfs/xfs_trace.h2
-rw-r--r--fs/xfs/xfs_trans_bmap.c1
-rw-r--r--fs/xfs/xfs_trans_extfree.c2
-rw-r--r--fs/xfs/xfs_trans_refcount.c1
-rw-r--r--fs/xfs/xfs_trans_rmap.c1
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
438out: 441out:
@@ -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 @@
9struct xfs_defer_op_type; 9struct 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 */
16struct 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 */
28enum xfs_defer_ops_type { 14enum 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 */
28struct 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
37void xfs_defer_add(struct xfs_trans *tp, enum xfs_defer_ops_type type, 37void xfs_defer_add(struct xfs_trans *tp, enum xfs_defer_ops_type type,
38 struct list_head *h); 38 struct list_head *h);
39int xfs_defer_finish_noroll(struct xfs_trans **tp); 39int 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. */
45struct xfs_defer_op_type { 45struct 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
59extern const struct xfs_defer_op_type xfs_bmap_update_defer_type; 58extern 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
224const struct xfs_defer_op_type xfs_bmap_update_defer_type = { 224const 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
210const struct xfs_defer_op_type xfs_extent_free_defer_type = { 210const 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 */
278const struct xfs_defer_op_type xfs_agfl_free_defer_type = { 277const 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
231const struct xfs_defer_op_type xfs_refcount_update_defer_type = { 231const 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
248const struct xfs_defer_op_type xfs_rmap_update_defer_type = { 248const 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,