blkcg: update blkg_lookup_create() to do locking
[sfrench/cifs-2.6.git] / block / blk-iolatency.c
index 28f80d22752858a2b1fcdfefb5f079469ec480ee..e6f68f15dee98e8a7f939a15b8141bbe9d9d682e 100644 (file)
@@ -276,10 +276,8 @@ static inline bool iolatency_may_queue(struct iolatency_grp *iolat,
 
 static void __blkcg_iolatency_throttle(struct rq_qos *rqos,
                                       struct iolatency_grp *iolat,
-                                      spinlock_t *lock, bool issue_as_root,
+                                      bool issue_as_root,
                                       bool use_memdelay)
-       __releases(lock)
-       __acquires(lock)
 {
        struct rq_wait *rqw = &iolat->rq_wait;
        unsigned use_delay = atomic_read(&lat_to_blkg(iolat)->use_delay);
@@ -311,14 +309,7 @@ static void __blkcg_iolatency_throttle(struct rq_qos *rqos,
                if (iolatency_may_queue(iolat, &wait, first_block))
                        break;
                first_block = false;
-
-               if (lock) {
-                       spin_unlock_irq(lock);
-                       io_schedule();
-                       spin_lock_irq(lock);
-               } else {
-                       io_schedule();
-               }
+               io_schedule();
        } while (1);
 
        finish_wait(&rqw->wait, &wait);
@@ -478,16 +469,35 @@ static void check_scale_change(struct iolatency_grp *iolat)
        scale_change(iolat, direction > 0);
 }
 
-static void blkcg_iolatency_throttle(struct rq_qos *rqos, struct bio *bio,
-                                    spinlock_t *lock)
+static void blkcg_iolatency_throttle(struct rq_qos *rqos, struct bio *bio)
 {
        struct blk_iolatency *blkiolat = BLKIOLATENCY(rqos);
-       struct blkcg_gq *blkg = bio->bi_blkg;
+       struct blkcg *blkcg;
+       struct blkcg_gq *blkg;
+       struct request_queue *q = rqos->q;
        bool issue_as_root = bio_issue_as_root_blkg(bio);
 
        if (!blk_iolatency_enabled(blkiolat))
                return;
 
+       rcu_read_lock();
+       bio_associate_blkcg(bio, NULL);
+       blkcg = bio_blkcg(bio);
+       blkg = blkg_lookup(blkcg, q);
+       if (unlikely(!blkg)) {
+               spin_lock_irq(&q->queue_lock);
+               blkg = __blkg_lookup_create(blkcg, q);
+               if (IS_ERR(blkg))
+                       blkg = NULL;
+               spin_unlock_irq(&q->queue_lock);
+       }
+       if (!blkg)
+               goto out;
+
+       bio_issue_init(&bio->bi_issue, bio_sectors(bio));
+       bio_associate_blkg(bio, blkg);
+out:
+       rcu_read_unlock();
        while (blkg && blkg->parent) {
                struct iolatency_grp *iolat = blkg_to_lat(blkg);
                if (!iolat) {
@@ -496,7 +506,7 @@ static void blkcg_iolatency_throttle(struct rq_qos *rqos, struct bio *bio,
                }
 
                check_scale_change(iolat);
-               __blkcg_iolatency_throttle(rqos, iolat, lock, issue_as_root,
+               __blkcg_iolatency_throttle(rqos, iolat, issue_as_root,
                                     (bio->bi_opf & REQ_SWAP) == REQ_SWAP);
                blkg = blkg->parent;
        }
@@ -708,7 +718,7 @@ static void blkiolatency_timer_fn(struct timer_list *t)
                 * We could be exiting, don't access the pd unless we have a
                 * ref on the blkg.
                 */
-               if (!blkg_tryget(blkg))
+               if (!blkg_try_get(blkg))
                        continue;
 
                iolat = blkg_to_lat(blkg);