aboutsummaryrefslogtreecommitdiffstats
path: root/block/cfq-iosched.c
diff options
context:
space:
mode:
authorVivek Goyal <vgoyal@redhat.com>2009-12-03 12:59:47 -0500
committerJens Axboe <jens.axboe@oracle.com>2009-12-03 13:28:52 -0500
commitb1c3576961847da26c91b1e97f226bb66be5fa3f (patch)
treee228525220031232463f9cbbe017bad67807e6d4 /block/cfq-iosched.c
parent25fb5169d4c9d4255107abbb7c08ab712434efc8 (diff)
blkio: Take care of cgroup deletion and cfq group reference counting
o One can choose to change elevator or delete a cgroup. Implement group reference counting so that both elevator exit and cgroup deletion can take place gracefully. Signed-off-by: Vivek Goyal <vgoyal@redhat.com> Signed-off-by: Nauman Rafique <nauman@google.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block/cfq-iosched.c')
-rw-r--r--block/cfq-iosched.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index a877eeee80af..8bc31a50a57f 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -192,6 +192,7 @@ struct cfq_group {
192 struct blkio_group blkg; 192 struct blkio_group blkg;
193#ifdef CONFIG_CFQ_GROUP_IOSCHED 193#ifdef CONFIG_CFQ_GROUP_IOSCHED
194 struct hlist_node cfqd_node; 194 struct hlist_node cfqd_node;
195 atomic_t ref;
195#endif 196#endif
196}; 197};
197 198
@@ -924,6 +925,14 @@ cfq_find_alloc_cfqg(struct cfq_data *cfqd, struct cgroup *cgroup, int create)
924 *st = CFQ_RB_ROOT; 925 *st = CFQ_RB_ROOT;
925 RB_CLEAR_NODE(&cfqg->rb_node); 926 RB_CLEAR_NODE(&cfqg->rb_node);
926 927
928 /*
929 * Take the initial reference that will be released on destroy
930 * This can be thought of a joint reference by cgroup and
931 * elevator which will be dropped by either elevator exit
932 * or cgroup deletion path depending on who is exiting first.
933 */
934 atomic_set(&cfqg->ref, 1);
935
927 /* Add group onto cgroup list */ 936 /* Add group onto cgroup list */
928 blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd); 937 blkiocg_add_blkio_group(blkcg, &cfqg->blkg, (void *)cfqd);
929 938
@@ -960,7 +969,77 @@ static void cfq_link_cfqq_cfqg(struct cfq_queue *cfqq, struct cfq_group *cfqg)
960 cfqg = &cfqq->cfqd->root_group; 969 cfqg = &cfqq->cfqd->root_group;
961 970
962 cfqq->cfqg = cfqg; 971 cfqq->cfqg = cfqg;
972 /* cfqq reference on cfqg */
973 atomic_inc(&cfqq->cfqg->ref);
974}
975
976static void cfq_put_cfqg(struct cfq_group *cfqg)
977{
978 struct cfq_rb_root *st;
979 int i, j;
980
981 BUG_ON(atomic_read(&cfqg->ref) <= 0);
982 if (!atomic_dec_and_test(&cfqg->ref))
983 return;
984 for_each_cfqg_st(cfqg, i, j, st)
985 BUG_ON(!RB_EMPTY_ROOT(&st->rb) || st->active != NULL);
986 kfree(cfqg);
987}
988
989static void cfq_destroy_cfqg(struct cfq_data *cfqd, struct cfq_group *cfqg)
990{
991 /* Something wrong if we are trying to remove same group twice */
992 BUG_ON(hlist_unhashed(&cfqg->cfqd_node));
993
994 hlist_del_init(&cfqg->cfqd_node);
995
996 /*
997 * Put the reference taken at the time of creation so that when all
998 * queues are gone, group can be destroyed.
999 */
1000 cfq_put_cfqg(cfqg);
1001}
1002
1003static void cfq_release_cfq_groups(struct cfq_data *cfqd)
1004{
1005 struct hlist_node *pos, *n;
1006 struct cfq_group *cfqg;
1007
1008 hlist_for_each_entry_safe(cfqg, pos, n, &cfqd->cfqg_list, cfqd_node) {
1009 /*
1010 * If cgroup removal path got to blk_group first and removed
1011 * it from cgroup list, then it will take care of destroying
1012 * cfqg also.
1013 */
1014 if (!blkiocg_del_blkio_group(&cfqg->blkg))
1015 cfq_destroy_cfqg(cfqd, cfqg);
1016 }
963} 1017}
1018
1019/*
1020 * Blk cgroup controller notification saying that blkio_group object is being
1021 * delinked as associated cgroup object is going away. That also means that
1022 * no new IO will come in this group. So get rid of this group as soon as
1023 * any pending IO in the group is finished.
1024 *
1025 * This function is called under rcu_read_lock(). key is the rcu protected
1026 * pointer. That means "key" is a valid cfq_data pointer as long as we are rcu
1027 * read lock.
1028 *
1029 * "key" was fetched from blkio_group under blkio_cgroup->lock. That means
1030 * it should not be NULL as even if elevator was exiting, cgroup deltion
1031 * path got to it first.
1032 */
1033void cfq_unlink_blkio_group(void *key, struct blkio_group *blkg)
1034{
1035 unsigned long flags;
1036 struct cfq_data *cfqd = key;
1037
1038 spin_lock_irqsave(cfqd->queue->queue_lock, flags);
1039 cfq_destroy_cfqg(cfqd, cfqg_of_blkg(blkg));
1040 spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
1041}
1042
964#else /* GROUP_IOSCHED */ 1043#else /* GROUP_IOSCHED */
965static struct cfq_group *cfq_get_cfqg(struct cfq_data *cfqd, int create) 1044static struct cfq_group *cfq_get_cfqg(struct cfq_data *cfqd, int create)
966{ 1045{
@@ -971,6 +1050,9 @@ cfq_link_cfqq_cfqg(struct cfq_queue *cfqq, struct cfq_group *cfqg) {
971 cfqq->cfqg = cfqg; 1050 cfqq->cfqg = cfqg;
972} 1051}
973 1052
1053static void cfq_release_cfq_groups(struct cfq_data *cfqd) {}
1054static inline void cfq_put_cfqg(struct cfq_group *cfqg) {}
1055
974#endif /* GROUP_IOSCHED */ 1056#endif /* GROUP_IOSCHED */
975 1057
976/* 1058/*
@@ -2172,11 +2254,13 @@ static int cfq_dispatch_requests(struct request_queue *q, int force)
2172 * task holds one reference to the queue, dropped when task exits. each rq 2254 * task holds one reference to the queue, dropped when task exits. each rq
2173 * in-flight on this queue also holds a reference, dropped when rq is freed. 2255 * in-flight on this queue also holds a reference, dropped when rq is freed.
2174 * 2256 *
2257 * Each cfq queue took a reference on the parent group. Drop it now.
2175 * queue lock must be held here. 2258 * queue lock must be held here.
2176 */ 2259 */
2177static void cfq_put_queue(struct cfq_queue *cfqq) 2260static void cfq_put_queue(struct cfq_queue *cfqq)
2178{ 2261{
2179 struct cfq_data *cfqd = cfqq->cfqd; 2262 struct cfq_data *cfqd = cfqq->cfqd;
2263 struct cfq_group *cfqg;
2180 2264
2181 BUG_ON(atomic_read(&cfqq->ref) <= 0); 2265 BUG_ON(atomic_read(&cfqq->ref) <= 0);
2182 2266
@@ -2186,6 +2270,7 @@ static void cfq_put_queue(struct cfq_queue *cfqq)
2186 cfq_log_cfqq(cfqd, cfqq, "put_queue"); 2270 cfq_log_cfqq(cfqd, cfqq, "put_queue");
2187 BUG_ON(rb_first(&cfqq->sort_list)); 2271 BUG_ON(rb_first(&cfqq->sort_list));
2188 BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]); 2272 BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]);
2273 cfqg = cfqq->cfqg;
2189 2274
2190 if (unlikely(cfqd->active_queue == cfqq)) { 2275 if (unlikely(cfqd->active_queue == cfqq)) {
2191 __cfq_slice_expired(cfqd, cfqq, 0); 2276 __cfq_slice_expired(cfqd, cfqq, 0);
@@ -2194,6 +2279,7 @@ static void cfq_put_queue(struct cfq_queue *cfqq)
2194 2279
2195 BUG_ON(cfq_cfqq_on_rr(cfqq)); 2280 BUG_ON(cfq_cfqq_on_rr(cfqq));
2196 kmem_cache_free(cfq_pool, cfqq); 2281 kmem_cache_free(cfq_pool, cfqq);
2282 cfq_put_cfqg(cfqg);
2197} 2283}
2198 2284
2199/* 2285/*
@@ -3369,11 +3455,15 @@ static void cfq_exit_queue(struct elevator_queue *e)
3369 } 3455 }
3370 3456
3371 cfq_put_async_queues(cfqd); 3457 cfq_put_async_queues(cfqd);
3458 cfq_release_cfq_groups(cfqd);
3459 blkiocg_del_blkio_group(&cfqd->root_group.blkg);
3372 3460
3373 spin_unlock_irq(q->queue_lock); 3461 spin_unlock_irq(q->queue_lock);
3374 3462
3375 cfq_shutdown_timer_wq(cfqd); 3463 cfq_shutdown_timer_wq(cfqd);
3376 3464
3465 /* Wait for cfqg->blkg->key accessors to exit their grace periods. */
3466 synchronize_rcu();
3377 kfree(cfqd); 3467 kfree(cfqd);
3378} 3468}
3379 3469
@@ -3401,6 +3491,11 @@ static void *cfq_init_queue(struct request_queue *q)
3401 cfqg->weight = 2*BLKIO_WEIGHT_DEFAULT; 3491 cfqg->weight = 2*BLKIO_WEIGHT_DEFAULT;
3402 3492
3403#ifdef CONFIG_CFQ_GROUP_IOSCHED 3493#ifdef CONFIG_CFQ_GROUP_IOSCHED
3494 /*
3495 * Take a reference to root group which we never drop. This is just
3496 * to make sure that cfq_put_cfqg() does not try to kfree root group
3497 */
3498 atomic_set(&cfqg->ref, 1);
3404 blkiocg_add_blkio_group(&blkio_root_cgroup, &cfqg->blkg, (void *)cfqd); 3499 blkiocg_add_blkio_group(&blkio_root_cgroup, &cfqg->blkg, (void *)cfqd);
3405#endif 3500#endif
3406 /* 3501 /*