diff options
Diffstat (limited to 'fs/xfs/xfs_btree.c')
-rw-r--r-- | fs/xfs/xfs_btree.c | 82 |
1 files changed, 81 insertions, 1 deletions
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c index bf810c6baf2b..cf893bc1e373 100644 --- a/fs/xfs/xfs_btree.c +++ b/fs/xfs/xfs_btree.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include "xfs_error.h" | 33 | #include "xfs_error.h" |
34 | #include "xfs_trace.h" | 34 | #include "xfs_trace.h" |
35 | #include "xfs_cksum.h" | 35 | #include "xfs_cksum.h" |
36 | #include "xfs_alloc.h" | ||
36 | 37 | ||
37 | /* | 38 | /* |
38 | * Cursor allocation zone. | 39 | * Cursor allocation zone. |
@@ -2323,7 +2324,7 @@ error1: | |||
2323 | * record (to be inserted into parent). | 2324 | * record (to be inserted into parent). |
2324 | */ | 2325 | */ |
2325 | STATIC int /* error */ | 2326 | STATIC int /* error */ |
2326 | xfs_btree_split( | 2327 | __xfs_btree_split( |
2327 | struct xfs_btree_cur *cur, | 2328 | struct xfs_btree_cur *cur, |
2328 | int level, | 2329 | int level, |
2329 | union xfs_btree_ptr *ptrp, | 2330 | union xfs_btree_ptr *ptrp, |
@@ -2503,6 +2504,85 @@ error0: | |||
2503 | return error; | 2504 | return error; |
2504 | } | 2505 | } |
2505 | 2506 | ||
2507 | struct xfs_btree_split_args { | ||
2508 | struct xfs_btree_cur *cur; | ||
2509 | int level; | ||
2510 | union xfs_btree_ptr *ptrp; | ||
2511 | union xfs_btree_key *key; | ||
2512 | struct xfs_btree_cur **curp; | ||
2513 | int *stat; /* success/failure */ | ||
2514 | int result; | ||
2515 | bool kswapd; /* allocation in kswapd context */ | ||
2516 | struct completion *done; | ||
2517 | struct work_struct work; | ||
2518 | }; | ||
2519 | |||
2520 | /* | ||
2521 | * Stack switching interfaces for allocation | ||
2522 | */ | ||
2523 | static void | ||
2524 | xfs_btree_split_worker( | ||
2525 | struct work_struct *work) | ||
2526 | { | ||
2527 | struct xfs_btree_split_args *args = container_of(work, | ||
2528 | struct xfs_btree_split_args, work); | ||
2529 | unsigned long pflags; | ||
2530 | unsigned long new_pflags = PF_FSTRANS; | ||
2531 | |||
2532 | /* | ||
2533 | * we are in a transaction context here, but may also be doing work | ||
2534 | * in kswapd context, and hence we may need to inherit that state | ||
2535 | * temporarily to ensure that we don't block waiting for memory reclaim | ||
2536 | * in any way. | ||
2537 | */ | ||
2538 | if (args->kswapd) | ||
2539 | new_pflags |= PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD; | ||
2540 | |||
2541 | current_set_flags_nested(&pflags, new_pflags); | ||
2542 | |||
2543 | args->result = __xfs_btree_split(args->cur, args->level, args->ptrp, | ||
2544 | args->key, args->curp, args->stat); | ||
2545 | complete(args->done); | ||
2546 | |||
2547 | current_restore_flags_nested(&pflags, new_pflags); | ||
2548 | } | ||
2549 | |||
2550 | /* | ||
2551 | * BMBT split requests often come in with little stack to work on. Push | ||
2552 | * them off to a worker thread so there is lots of stack to use. For the other | ||
2553 | * btree types, just call directly to avoid the context switch overhead here. | ||
2554 | */ | ||
2555 | STATIC int /* error */ | ||
2556 | xfs_btree_split( | ||
2557 | struct xfs_btree_cur *cur, | ||
2558 | int level, | ||
2559 | union xfs_btree_ptr *ptrp, | ||
2560 | union xfs_btree_key *key, | ||
2561 | struct xfs_btree_cur **curp, | ||
2562 | int *stat) /* success/failure */ | ||
2563 | { | ||
2564 | struct xfs_btree_split_args args; | ||
2565 | DECLARE_COMPLETION_ONSTACK(done); | ||
2566 | |||
2567 | if (cur->bc_btnum != XFS_BTNUM_BMAP) | ||
2568 | return __xfs_btree_split(cur, level, ptrp, key, curp, stat); | ||
2569 | |||
2570 | args.cur = cur; | ||
2571 | args.level = level; | ||
2572 | args.ptrp = ptrp; | ||
2573 | args.key = key; | ||
2574 | args.curp = curp; | ||
2575 | args.stat = stat; | ||
2576 | args.done = &done; | ||
2577 | args.kswapd = current_is_kswapd(); | ||
2578 | INIT_WORK_ONSTACK(&args.work, xfs_btree_split_worker); | ||
2579 | queue_work(xfs_alloc_wq, &args.work); | ||
2580 | wait_for_completion(&done); | ||
2581 | destroy_work_on_stack(&args.work); | ||
2582 | return args.result; | ||
2583 | } | ||
2584 | |||
2585 | |||
2506 | /* | 2586 | /* |
2507 | * Copy the old inode root contents into a real block and make the | 2587 | * Copy the old inode root contents into a real block and make the |
2508 | * broot point to it. | 2588 | * broot point to it. |