diff options
author | Tejun Heo <tj@kernel.org> | 2011-12-13 18:33:42 -0500 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2011-12-13 18:33:42 -0500 |
commit | 9b84cacd013996f244d85b3d873287c2a8f88658 (patch) | |
tree | a11b850f9c8b182a7a8141276244a831aaae5291 | |
parent | 7e5a8794492e43e9eebb68a98a23be055888ccd0 (diff) |
block, cfq: restructure io_cq creation path for io_context interface cleanup
Add elevator_ops->elevator_init_icq_fn() and restructure
cfq_create_cic() and rename it to ioc_create_icq().
The new function expects its caller to pass in io_context, uses
elevator_type->icq_cache, handles generic init, calls the new elevator
operation for elevator specific initialization, and returns pointer to
created or looked up icq. This leaves cfq_icq_pool variable without
any user. Removed.
This prepares for io_context interface cleanup and doesn't introduce
any functional difference.
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r-- | block/cfq-iosched.c | 94 | ||||
-rw-r--r-- | include/linux/elevator.h | 2 |
2 files changed, 43 insertions, 53 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index f6d315551496..11f49d036845 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -59,7 +59,6 @@ static const int cfq_hist_divisor = 4; | |||
59 | #define RQ_CFQG(rq) (struct cfq_group *) ((rq)->elv.priv[1]) | 59 | #define RQ_CFQG(rq) (struct cfq_group *) ((rq)->elv.priv[1]) |
60 | 60 | ||
61 | static struct kmem_cache *cfq_pool; | 61 | static struct kmem_cache *cfq_pool; |
62 | static struct kmem_cache *cfq_icq_pool; | ||
63 | 62 | ||
64 | #define CFQ_PRIO_LISTS IOPRIO_BE_NR | 63 | #define CFQ_PRIO_LISTS IOPRIO_BE_NR |
65 | #define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE) | 64 | #define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE) |
@@ -2707,6 +2706,13 @@ static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
2707 | cfq_put_queue(cfqq); | 2706 | cfq_put_queue(cfqq); |
2708 | } | 2707 | } |
2709 | 2708 | ||
2709 | static void cfq_init_icq(struct io_cq *icq) | ||
2710 | { | ||
2711 | struct cfq_io_cq *cic = icq_to_cic(icq); | ||
2712 | |||
2713 | cic->ttime.last_end_request = jiffies; | ||
2714 | } | ||
2715 | |||
2710 | static void cfq_exit_icq(struct io_cq *icq) | 2716 | static void cfq_exit_icq(struct io_cq *icq) |
2711 | { | 2717 | { |
2712 | struct cfq_io_cq *cic = icq_to_cic(icq); | 2718 | struct cfq_io_cq *cic = icq_to_cic(icq); |
@@ -2723,21 +2729,6 @@ static void cfq_exit_icq(struct io_cq *icq) | |||
2723 | } | 2729 | } |
2724 | } | 2730 | } |
2725 | 2731 | ||
2726 | static struct cfq_io_cq *cfq_alloc_cic(struct cfq_data *cfqd, gfp_t gfp_mask) | ||
2727 | { | ||
2728 | struct cfq_io_cq *cic; | ||
2729 | |||
2730 | cic = kmem_cache_alloc_node(cfq_icq_pool, gfp_mask | __GFP_ZERO, | ||
2731 | cfqd->queue->node); | ||
2732 | if (cic) { | ||
2733 | cic->ttime.last_end_request = jiffies; | ||
2734 | INIT_LIST_HEAD(&cic->icq.q_node); | ||
2735 | INIT_HLIST_NODE(&cic->icq.ioc_node); | ||
2736 | } | ||
2737 | |||
2738 | return cic; | ||
2739 | } | ||
2740 | |||
2741 | static void cfq_init_prio_data(struct cfq_queue *cfqq, struct io_context *ioc) | 2732 | static void cfq_init_prio_data(struct cfq_queue *cfqq, struct io_context *ioc) |
2742 | { | 2733 | { |
2743 | struct task_struct *tsk = current; | 2734 | struct task_struct *tsk = current; |
@@ -2945,64 +2936,62 @@ cfq_get_queue(struct cfq_data *cfqd, bool is_sync, struct io_context *ioc, | |||
2945 | } | 2936 | } |
2946 | 2937 | ||
2947 | /** | 2938 | /** |
2948 | * cfq_create_cic - create and link a cfq_io_cq | 2939 | * ioc_create_icq - create and link io_cq |
2949 | * @cfqd: cfqd of interest | 2940 | * @q: request_queue of interest |
2950 | * @gfp_mask: allocation mask | 2941 | * @gfp_mask: allocation mask |
2951 | * | 2942 | * |
2952 | * Make sure cfq_io_cq linking %current->io_context and @cfqd exists. If | 2943 | * Make sure io_cq linking %current->io_context and @q exists. If either |
2953 | * ioc and/or cic doesn't exist, they will be created using @gfp_mask. | 2944 | * io_context and/or icq don't exist, they will be created using @gfp_mask. |
2945 | * | ||
2946 | * The caller is responsible for ensuring @ioc won't go away and @q is | ||
2947 | * alive and will stay alive until this function returns. | ||
2954 | */ | 2948 | */ |
2955 | static int cfq_create_cic(struct cfq_data *cfqd, gfp_t gfp_mask) | 2949 | static struct io_cq *ioc_create_icq(struct request_queue *q, gfp_t gfp_mask) |
2956 | { | 2950 | { |
2957 | struct request_queue *q = cfqd->queue; | 2951 | struct elevator_type *et = q->elevator->type; |
2958 | struct io_cq *icq = NULL; | ||
2959 | struct cfq_io_cq *cic; | ||
2960 | struct io_context *ioc; | 2952 | struct io_context *ioc; |
2961 | int ret = -ENOMEM; | 2953 | struct io_cq *icq; |
2962 | |||
2963 | might_sleep_if(gfp_mask & __GFP_WAIT); | ||
2964 | 2954 | ||
2965 | /* allocate stuff */ | 2955 | /* allocate stuff */ |
2966 | ioc = create_io_context(current, gfp_mask, q->node); | 2956 | ioc = create_io_context(current, gfp_mask, q->node); |
2967 | if (!ioc) | 2957 | if (!ioc) |
2968 | goto out; | 2958 | return NULL; |
2969 | 2959 | ||
2970 | cic = cfq_alloc_cic(cfqd, gfp_mask); | 2960 | icq = kmem_cache_alloc_node(et->icq_cache, gfp_mask | __GFP_ZERO, |
2971 | if (!cic) | 2961 | q->node); |
2972 | goto out; | 2962 | if (!icq) |
2973 | icq = &cic->icq; | 2963 | return NULL; |
2974 | 2964 | ||
2975 | ret = radix_tree_preload(gfp_mask); | 2965 | if (radix_tree_preload(gfp_mask) < 0) { |
2976 | if (ret) | 2966 | kmem_cache_free(et->icq_cache, icq); |
2977 | goto out; | 2967 | return NULL; |
2968 | } | ||
2978 | 2969 | ||
2979 | icq->ioc = ioc; | 2970 | icq->ioc = ioc; |
2980 | icq->q = cfqd->queue; | 2971 | icq->q = q; |
2972 | INIT_LIST_HEAD(&icq->q_node); | ||
2973 | INIT_HLIST_NODE(&icq->ioc_node); | ||
2981 | 2974 | ||
2982 | /* lock both q and ioc and try to link @icq */ | 2975 | /* lock both q and ioc and try to link @icq */ |
2983 | spin_lock_irq(q->queue_lock); | 2976 | spin_lock_irq(q->queue_lock); |
2984 | spin_lock(&ioc->lock); | 2977 | spin_lock(&ioc->lock); |
2985 | 2978 | ||
2986 | ret = radix_tree_insert(&ioc->icq_tree, q->id, icq); | 2979 | if (likely(!radix_tree_insert(&ioc->icq_tree, q->id, icq))) { |
2987 | if (likely(!ret)) { | ||
2988 | hlist_add_head(&icq->ioc_node, &ioc->icq_list); | 2980 | hlist_add_head(&icq->ioc_node, &ioc->icq_list); |
2989 | list_add(&icq->q_node, &q->icq_list); | 2981 | list_add(&icq->q_node, &q->icq_list); |
2990 | icq = NULL; | 2982 | if (et->ops.elevator_init_icq_fn) |
2991 | } else if (ret == -EEXIST) { | 2983 | et->ops.elevator_init_icq_fn(icq); |
2992 | /* someone else already did it */ | 2984 | } else { |
2993 | ret = 0; | 2985 | kmem_cache_free(et->icq_cache, icq); |
2986 | icq = ioc_lookup_icq(ioc, q); | ||
2987 | if (!icq) | ||
2988 | printk(KERN_ERR "cfq: icq link failed!\n"); | ||
2994 | } | 2989 | } |
2995 | 2990 | ||
2996 | spin_unlock(&ioc->lock); | 2991 | spin_unlock(&ioc->lock); |
2997 | spin_unlock_irq(q->queue_lock); | 2992 | spin_unlock_irq(q->queue_lock); |
2998 | |||
2999 | radix_tree_preload_end(); | 2993 | radix_tree_preload_end(); |
3000 | out: | 2994 | return icq; |
3001 | if (ret) | ||
3002 | printk(KERN_ERR "cfq: icq link failed!\n"); | ||
3003 | if (icq) | ||
3004 | kmem_cache_free(cfq_icq_pool, icq); | ||
3005 | return ret; | ||
3006 | } | 2995 | } |
3007 | 2996 | ||
3008 | /** | 2997 | /** |
@@ -3022,7 +3011,6 @@ static struct cfq_io_cq *cfq_get_cic(struct cfq_data *cfqd, gfp_t gfp_mask) | |||
3022 | struct request_queue *q = cfqd->queue; | 3011 | struct request_queue *q = cfqd->queue; |
3023 | struct cfq_io_cq *cic = NULL; | 3012 | struct cfq_io_cq *cic = NULL; |
3024 | struct io_context *ioc; | 3013 | struct io_context *ioc; |
3025 | int err; | ||
3026 | 3014 | ||
3027 | lockdep_assert_held(q->queue_lock); | 3015 | lockdep_assert_held(q->queue_lock); |
3028 | 3016 | ||
@@ -3037,9 +3025,9 @@ static struct cfq_io_cq *cfq_get_cic(struct cfq_data *cfqd, gfp_t gfp_mask) | |||
3037 | 3025 | ||
3038 | /* slow path - unlock, create missing ones and retry */ | 3026 | /* slow path - unlock, create missing ones and retry */ |
3039 | spin_unlock_irq(q->queue_lock); | 3027 | spin_unlock_irq(q->queue_lock); |
3040 | err = cfq_create_cic(cfqd, gfp_mask); | 3028 | cic = icq_to_cic(ioc_create_icq(q, gfp_mask)); |
3041 | spin_lock_irq(q->queue_lock); | 3029 | spin_lock_irq(q->queue_lock); |
3042 | if (err) | 3030 | if (!cic) |
3043 | return NULL; | 3031 | return NULL; |
3044 | } | 3032 | } |
3045 | 3033 | ||
@@ -3975,6 +3963,7 @@ static struct elevator_type iosched_cfq = { | |||
3975 | .elevator_completed_req_fn = cfq_completed_request, | 3963 | .elevator_completed_req_fn = cfq_completed_request, |
3976 | .elevator_former_req_fn = elv_rb_former_request, | 3964 | .elevator_former_req_fn = elv_rb_former_request, |
3977 | .elevator_latter_req_fn = elv_rb_latter_request, | 3965 | .elevator_latter_req_fn = elv_rb_latter_request, |
3966 | .elevator_init_icq_fn = cfq_init_icq, | ||
3978 | .elevator_exit_icq_fn = cfq_exit_icq, | 3967 | .elevator_exit_icq_fn = cfq_exit_icq, |
3979 | .elevator_set_req_fn = cfq_set_request, | 3968 | .elevator_set_req_fn = cfq_set_request, |
3980 | .elevator_put_req_fn = cfq_put_request, | 3969 | .elevator_put_req_fn = cfq_put_request, |
@@ -4028,7 +4017,6 @@ static int __init cfq_init(void) | |||
4028 | kmem_cache_destroy(cfq_pool); | 4017 | kmem_cache_destroy(cfq_pool); |
4029 | return ret; | 4018 | return ret; |
4030 | } | 4019 | } |
4031 | cfq_icq_pool = iosched_cfq.icq_cache; | ||
4032 | 4020 | ||
4033 | blkio_policy_register(&blkio_policy_cfq); | 4021 | blkio_policy_register(&blkio_policy_cfq); |
4034 | 4022 | ||
diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 06e4dd568717..c8f1e67a8ebe 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h | |||
@@ -26,6 +26,7 @@ typedef struct request *(elevator_request_list_fn) (struct request_queue *, stru | |||
26 | typedef void (elevator_completed_req_fn) (struct request_queue *, struct request *); | 26 | typedef void (elevator_completed_req_fn) (struct request_queue *, struct request *); |
27 | typedef int (elevator_may_queue_fn) (struct request_queue *, int); | 27 | typedef int (elevator_may_queue_fn) (struct request_queue *, int); |
28 | 28 | ||
29 | typedef void (elevator_init_icq_fn) (struct io_cq *); | ||
29 | typedef void (elevator_exit_icq_fn) (struct io_cq *); | 30 | typedef void (elevator_exit_icq_fn) (struct io_cq *); |
30 | typedef int (elevator_set_req_fn) (struct request_queue *, struct request *, gfp_t); | 31 | typedef int (elevator_set_req_fn) (struct request_queue *, struct request *, gfp_t); |
31 | typedef void (elevator_put_req_fn) (struct request *); | 32 | typedef void (elevator_put_req_fn) (struct request *); |
@@ -59,6 +60,7 @@ struct elevator_ops | |||
59 | elevator_request_list_fn *elevator_former_req_fn; | 60 | elevator_request_list_fn *elevator_former_req_fn; |
60 | elevator_request_list_fn *elevator_latter_req_fn; | 61 | elevator_request_list_fn *elevator_latter_req_fn; |
61 | 62 | ||
63 | elevator_init_icq_fn *elevator_init_icq_fn; | ||
62 | elevator_exit_icq_fn *elevator_exit_icq_fn; | 64 | elevator_exit_icq_fn *elevator_exit_icq_fn; |
63 | 65 | ||
64 | elevator_set_req_fn *elevator_set_req_fn; | 66 | elevator_set_req_fn *elevator_set_req_fn; |