Commit 9b84cacd authored by Tejun Heo's avatar Tejun Heo Committed by Jens Axboe

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: default avatarTejun Heo <tj@kernel.org>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 7e5a8794
...@@ -59,7 +59,6 @@ static const int cfq_hist_divisor = 4; ...@@ -59,7 +59,6 @@ static const int cfq_hist_divisor = 4;
#define RQ_CFQG(rq) (struct cfq_group *) ((rq)->elv.priv[1]) #define RQ_CFQG(rq) (struct cfq_group *) ((rq)->elv.priv[1])
static struct kmem_cache *cfq_pool; static struct kmem_cache *cfq_pool;
static struct kmem_cache *cfq_icq_pool;
#define CFQ_PRIO_LISTS IOPRIO_BE_NR #define CFQ_PRIO_LISTS IOPRIO_BE_NR
#define cfq_class_idle(cfqq) ((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE) #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,6 +2706,13 @@ static void cfq_exit_cfqq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
cfq_put_queue(cfqq); cfq_put_queue(cfqq);
} }
static void cfq_init_icq(struct io_cq *icq)
{
struct cfq_io_cq *cic = icq_to_cic(icq);
cic->ttime.last_end_request = jiffies;
}
static void cfq_exit_icq(struct io_cq *icq) static void cfq_exit_icq(struct io_cq *icq)
{ {
struct cfq_io_cq *cic = icq_to_cic(icq); struct cfq_io_cq *cic = icq_to_cic(icq);
...@@ -2723,21 +2729,6 @@ static void cfq_exit_icq(struct io_cq *icq) ...@@ -2723,21 +2729,6 @@ static void cfq_exit_icq(struct io_cq *icq)
} }
} }
static struct cfq_io_cq *cfq_alloc_cic(struct cfq_data *cfqd, gfp_t gfp_mask)
{
struct cfq_io_cq *cic;
cic = kmem_cache_alloc_node(cfq_icq_pool, gfp_mask | __GFP_ZERO,
cfqd->queue->node);
if (cic) {
cic->ttime.last_end_request = jiffies;
INIT_LIST_HEAD(&cic->icq.q_node);
INIT_HLIST_NODE(&cic->icq.ioc_node);
}
return cic;
}
static void cfq_init_prio_data(struct cfq_queue *cfqq, struct io_context *ioc) static void cfq_init_prio_data(struct cfq_queue *cfqq, struct io_context *ioc)
{ {
struct task_struct *tsk = current; struct task_struct *tsk = current;
...@@ -2945,64 +2936,62 @@ cfq_get_queue(struct cfq_data *cfqd, bool is_sync, struct io_context *ioc, ...@@ -2945,64 +2936,62 @@ cfq_get_queue(struct cfq_data *cfqd, bool is_sync, struct io_context *ioc,
} }
/** /**
* cfq_create_cic - create and link a cfq_io_cq * ioc_create_icq - create and link io_cq
* @cfqd: cfqd of interest * @q: request_queue of interest
* @gfp_mask: allocation mask * @gfp_mask: allocation mask
* *
* Make sure cfq_io_cq linking %current->io_context and @cfqd exists. If * Make sure io_cq linking %current->io_context and @q exists. If either
* ioc and/or cic doesn't exist, they will be created using @gfp_mask. * io_context and/or icq don't exist, they will be created using @gfp_mask.
*
* The caller is responsible for ensuring @ioc won't go away and @q is
* alive and will stay alive until this function returns.
*/ */
static int cfq_create_cic(struct cfq_data *cfqd, gfp_t gfp_mask) static struct io_cq *ioc_create_icq(struct request_queue *q, gfp_t gfp_mask)
{ {
struct request_queue *q = cfqd->queue; struct elevator_type *et = q->elevator->type;
struct io_cq *icq = NULL;
struct cfq_io_cq *cic;
struct io_context *ioc; struct io_context *ioc;
int ret = -ENOMEM; struct io_cq *icq;
might_sleep_if(gfp_mask & __GFP_WAIT);
/* allocate stuff */ /* allocate stuff */
ioc = create_io_context(current, gfp_mask, q->node); ioc = create_io_context(current, gfp_mask, q->node);
if (!ioc) if (!ioc)
goto out; return NULL;
cic = cfq_alloc_cic(cfqd, gfp_mask); icq = kmem_cache_alloc_node(et->icq_cache, gfp_mask | __GFP_ZERO,
if (!cic) q->node);
goto out; if (!icq)
icq = &cic->icq; return NULL;
ret = radix_tree_preload(gfp_mask); if (radix_tree_preload(gfp_mask) < 0) {
if (ret) kmem_cache_free(et->icq_cache, icq);
goto out; return NULL;
}
icq->ioc = ioc; icq->ioc = ioc;
icq->q = cfqd->queue; icq->q = q;
INIT_LIST_HEAD(&icq->q_node);
INIT_HLIST_NODE(&icq->ioc_node);
/* lock both q and ioc and try to link @icq */ /* lock both q and ioc and try to link @icq */
spin_lock_irq(q->queue_lock); spin_lock_irq(q->queue_lock);
spin_lock(&ioc->lock); spin_lock(&ioc->lock);
ret = radix_tree_insert(&ioc->icq_tree, q->id, icq); if (likely(!radix_tree_insert(&ioc->icq_tree, q->id, icq))) {
if (likely(!ret)) {
hlist_add_head(&icq->ioc_node, &ioc->icq_list); hlist_add_head(&icq->ioc_node, &ioc->icq_list);
list_add(&icq->q_node, &q->icq_list); list_add(&icq->q_node, &q->icq_list);
icq = NULL; if (et->ops.elevator_init_icq_fn)
} else if (ret == -EEXIST) { et->ops.elevator_init_icq_fn(icq);
/* someone else already did it */ } else {
ret = 0; kmem_cache_free(et->icq_cache, icq);
icq = ioc_lookup_icq(ioc, q);
if (!icq)
printk(KERN_ERR "cfq: icq link failed!\n");
} }
spin_unlock(&ioc->lock); spin_unlock(&ioc->lock);
spin_unlock_irq(q->queue_lock); spin_unlock_irq(q->queue_lock);
radix_tree_preload_end(); radix_tree_preload_end();
out: return icq;
if (ret)
printk(KERN_ERR "cfq: icq link failed!\n");
if (icq)
kmem_cache_free(cfq_icq_pool, icq);
return ret;
} }
/** /**
...@@ -3022,7 +3011,6 @@ static struct cfq_io_cq *cfq_get_cic(struct cfq_data *cfqd, gfp_t gfp_mask) ...@@ -3022,7 +3011,6 @@ static struct cfq_io_cq *cfq_get_cic(struct cfq_data *cfqd, gfp_t gfp_mask)
struct request_queue *q = cfqd->queue; struct request_queue *q = cfqd->queue;
struct cfq_io_cq *cic = NULL; struct cfq_io_cq *cic = NULL;
struct io_context *ioc; struct io_context *ioc;
int err;
lockdep_assert_held(q->queue_lock); lockdep_assert_held(q->queue_lock);
...@@ -3037,9 +3025,9 @@ static struct cfq_io_cq *cfq_get_cic(struct cfq_data *cfqd, gfp_t gfp_mask) ...@@ -3037,9 +3025,9 @@ static struct cfq_io_cq *cfq_get_cic(struct cfq_data *cfqd, gfp_t gfp_mask)
/* slow path - unlock, create missing ones and retry */ /* slow path - unlock, create missing ones and retry */
spin_unlock_irq(q->queue_lock); spin_unlock_irq(q->queue_lock);
err = cfq_create_cic(cfqd, gfp_mask); cic = icq_to_cic(ioc_create_icq(q, gfp_mask));
spin_lock_irq(q->queue_lock); spin_lock_irq(q->queue_lock);
if (err) if (!cic)
return NULL; return NULL;
} }
...@@ -3975,6 +3963,7 @@ static struct elevator_type iosched_cfq = { ...@@ -3975,6 +3963,7 @@ static struct elevator_type iosched_cfq = {
.elevator_completed_req_fn = cfq_completed_request, .elevator_completed_req_fn = cfq_completed_request,
.elevator_former_req_fn = elv_rb_former_request, .elevator_former_req_fn = elv_rb_former_request,
.elevator_latter_req_fn = elv_rb_latter_request, .elevator_latter_req_fn = elv_rb_latter_request,
.elevator_init_icq_fn = cfq_init_icq,
.elevator_exit_icq_fn = cfq_exit_icq, .elevator_exit_icq_fn = cfq_exit_icq,
.elevator_set_req_fn = cfq_set_request, .elevator_set_req_fn = cfq_set_request,
.elevator_put_req_fn = cfq_put_request, .elevator_put_req_fn = cfq_put_request,
...@@ -4028,7 +4017,6 @@ static int __init cfq_init(void) ...@@ -4028,7 +4017,6 @@ static int __init cfq_init(void)
kmem_cache_destroy(cfq_pool); kmem_cache_destroy(cfq_pool);
return ret; return ret;
} }
cfq_icq_pool = iosched_cfq.icq_cache;
blkio_policy_register(&blkio_policy_cfq); blkio_policy_register(&blkio_policy_cfq);
......
...@@ -26,6 +26,7 @@ typedef struct request *(elevator_request_list_fn) (struct request_queue *, stru ...@@ -26,6 +26,7 @@ typedef struct request *(elevator_request_list_fn) (struct request_queue *, stru
typedef void (elevator_completed_req_fn) (struct request_queue *, struct request *); typedef void (elevator_completed_req_fn) (struct request_queue *, struct request *);
typedef int (elevator_may_queue_fn) (struct request_queue *, int); typedef int (elevator_may_queue_fn) (struct request_queue *, int);
typedef void (elevator_init_icq_fn) (struct io_cq *);
typedef void (elevator_exit_icq_fn) (struct io_cq *); typedef void (elevator_exit_icq_fn) (struct io_cq *);
typedef int (elevator_set_req_fn) (struct request_queue *, struct request *, gfp_t); typedef int (elevator_set_req_fn) (struct request_queue *, struct request *, gfp_t);
typedef void (elevator_put_req_fn) (struct request *); typedef void (elevator_put_req_fn) (struct request *);
...@@ -59,6 +60,7 @@ struct elevator_ops ...@@ -59,6 +60,7 @@ struct elevator_ops
elevator_request_list_fn *elevator_former_req_fn; elevator_request_list_fn *elevator_former_req_fn;
elevator_request_list_fn *elevator_latter_req_fn; elevator_request_list_fn *elevator_latter_req_fn;
elevator_init_icq_fn *elevator_init_icq_fn;
elevator_exit_icq_fn *elevator_exit_icq_fn; elevator_exit_icq_fn *elevator_exit_icq_fn;
elevator_set_req_fn *elevator_set_req_fn; elevator_set_req_fn *elevator_set_req_fn;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment