diff options
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_alloc.c | 34 | ||||
-rw-r--r-- | fs/xfs/xfs_alloc.h | 5 | ||||
-rw-r--r-- | fs/xfs/xfs_super.c | 16 |
3 files changed, 54 insertions, 1 deletions
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index ce84ffd0264c..31e90335b83d 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include "xfs_error.h" | 35 | #include "xfs_error.h" |
36 | #include "xfs_trace.h" | 36 | #include "xfs_trace.h" |
37 | 37 | ||
38 | struct workqueue_struct *xfs_alloc_wq; | ||
38 | 39 | ||
39 | #define XFS_ABSDIFF(a,b) (((a) <= (b)) ? ((b) - (a)) : ((a) - (b))) | 40 | #define XFS_ABSDIFF(a,b) (((a) <= (b)) ? ((b) - (a)) : ((a) - (b))) |
40 | 41 | ||
@@ -2207,7 +2208,7 @@ xfs_alloc_read_agf( | |||
2207 | * group or loop over the allocation groups to find the result. | 2208 | * group or loop over the allocation groups to find the result. |
2208 | */ | 2209 | */ |
2209 | int /* error */ | 2210 | int /* error */ |
2210 | xfs_alloc_vextent( | 2211 | __xfs_alloc_vextent( |
2211 | xfs_alloc_arg_t *args) /* allocation argument structure */ | 2212 | xfs_alloc_arg_t *args) /* allocation argument structure */ |
2212 | { | 2213 | { |
2213 | xfs_agblock_t agsize; /* allocation group size */ | 2214 | xfs_agblock_t agsize; /* allocation group size */ |
@@ -2417,6 +2418,37 @@ error0: | |||
2417 | return error; | 2418 | return error; |
2418 | } | 2419 | } |
2419 | 2420 | ||
2421 | static void | ||
2422 | xfs_alloc_vextent_worker( | ||
2423 | struct work_struct *work) | ||
2424 | { | ||
2425 | struct xfs_alloc_arg *args = container_of(work, | ||
2426 | struct xfs_alloc_arg, work); | ||
2427 | unsigned long pflags; | ||
2428 | |||
2429 | /* we are in a transaction context here */ | ||
2430 | current_set_flags_nested(&pflags, PF_FSTRANS); | ||
2431 | |||
2432 | args->result = __xfs_alloc_vextent(args); | ||
2433 | complete(args->done); | ||
2434 | |||
2435 | current_restore_flags_nested(&pflags, PF_FSTRANS); | ||
2436 | } | ||
2437 | |||
2438 | |||
2439 | int /* error */ | ||
2440 | xfs_alloc_vextent( | ||
2441 | xfs_alloc_arg_t *args) /* allocation argument structure */ | ||
2442 | { | ||
2443 | DECLARE_COMPLETION_ONSTACK(done); | ||
2444 | |||
2445 | args->done = &done; | ||
2446 | INIT_WORK(&args->work, xfs_alloc_vextent_worker); | ||
2447 | queue_work(xfs_alloc_wq, &args->work); | ||
2448 | wait_for_completion(&done); | ||
2449 | return args->result; | ||
2450 | } | ||
2451 | |||
2420 | /* | 2452 | /* |
2421 | * Free an extent. | 2453 | * Free an extent. |
2422 | * Just break up the extent address and hand off to xfs_free_ag_extent | 2454 | * Just break up the extent address and hand off to xfs_free_ag_extent |
diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h index 2f52b924be79..ab5d0fd2f535 100644 --- a/fs/xfs/xfs_alloc.h +++ b/fs/xfs/xfs_alloc.h | |||
@@ -25,6 +25,8 @@ struct xfs_perag; | |||
25 | struct xfs_trans; | 25 | struct xfs_trans; |
26 | struct xfs_busy_extent; | 26 | struct xfs_busy_extent; |
27 | 27 | ||
28 | extern struct workqueue_struct *xfs_alloc_wq; | ||
29 | |||
28 | /* | 30 | /* |
29 | * Freespace allocation types. Argument to xfs_alloc_[v]extent. | 31 | * Freespace allocation types. Argument to xfs_alloc_[v]extent. |
30 | */ | 32 | */ |
@@ -119,6 +121,9 @@ typedef struct xfs_alloc_arg { | |||
119 | char isfl; /* set if is freelist blocks - !acctg */ | 121 | char isfl; /* set if is freelist blocks - !acctg */ |
120 | char userdata; /* set if this is user data */ | 122 | char userdata; /* set if this is user data */ |
121 | xfs_fsblock_t firstblock; /* io first block allocated */ | 123 | xfs_fsblock_t firstblock; /* io first block allocated */ |
124 | struct completion *done; | ||
125 | struct work_struct work; | ||
126 | int result; | ||
122 | } xfs_alloc_arg_t; | 127 | } xfs_alloc_arg_t; |
123 | 128 | ||
124 | /* | 129 | /* |
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 06d23b976f4c..5484888d39c4 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c | |||
@@ -1607,12 +1607,28 @@ xfs_init_workqueues(void) | |||
1607 | xfs_syncd_wq = alloc_workqueue("xfssyncd", WQ_NON_REENTRANT, 0); | 1607 | xfs_syncd_wq = alloc_workqueue("xfssyncd", WQ_NON_REENTRANT, 0); |
1608 | if (!xfs_syncd_wq) | 1608 | if (!xfs_syncd_wq) |
1609 | return -ENOMEM; | 1609 | return -ENOMEM; |
1610 | |||
1611 | /* | ||
1612 | * The allocation workqueue can be used in memory reclaim situations | ||
1613 | * (writepage path), and parallelism is only limited by the number of | ||
1614 | * AGs in all the filesystems mounted. Hence use the default large | ||
1615 | * max_active value for this workqueue. | ||
1616 | */ | ||
1617 | xfs_alloc_wq = alloc_workqueue("xfsalloc", WQ_MEM_RECLAIM, 0); | ||
1618 | if (!xfs_alloc_wq) | ||
1619 | goto out_destroy_syncd; | ||
1620 | |||
1610 | return 0; | 1621 | return 0; |
1622 | |||
1623 | out_destroy_syncd: | ||
1624 | destroy_workqueue(xfs_syncd_wq); | ||
1625 | return -ENOMEM; | ||
1611 | } | 1626 | } |
1612 | 1627 | ||
1613 | STATIC void | 1628 | STATIC void |
1614 | xfs_destroy_workqueues(void) | 1629 | xfs_destroy_workqueues(void) |
1615 | { | 1630 | { |
1631 | destroy_workqueue(xfs_alloc_wq); | ||
1616 | destroy_workqueue(xfs_syncd_wq); | 1632 | destroy_workqueue(xfs_syncd_wq); |
1617 | } | 1633 | } |
1618 | 1634 | ||