@@ -404,6 +404,7 @@ struct ioc_pcpu_stat {
struct ioc {
struct rq_qos rqos;
+ refcount_t ref;
bool enabled;
struct ioc_params params;
@@ -2816,6 +2817,12 @@ static void ioc_rqos_queue_depth_changed(struct rq_qos *rqos)
spin_unlock_irq(&ioc->lock);
}
+static void ioc_put(struct ioc *ioc)
+{
+ if (refcount_dec_and_test(&ioc->ref))
+ kfree(ioc);
+}
+
static void ioc_rqos_exit(struct rq_qos *rqos)
{
struct ioc *ioc = rqos_to_ioc(rqos);
@@ -2828,7 +2835,7 @@ static void ioc_rqos_exit(struct rq_qos *rqos)
del_timer_sync(&ioc->timer);
free_percpu(ioc->pcpu_stat);
- kfree(ioc);
+ ioc_put(ioc);
}
static struct rq_qos_ops ioc_rqos_ops = {
@@ -2883,6 +2890,7 @@ static int blk_iocost_init(struct gendisk *disk)
ioc->period_at = ktime_to_us(ktime_get());
atomic64_set(&ioc->cur_period, 0);
atomic_set(&ioc->hweight_gen, 0);
+ refcount_set(&ioc->ref, 1);
spin_lock_irq(&ioc->lock);
ioc->autop_idx = AUTOP_INVALID;
@@ -2983,6 +2991,7 @@ static void iocg_put(struct ioc_gq *iocg)
spin_unlock_irqrestore(&ioc->lock, flags);
hrtimer_cancel(&iocg->waitq_timer);
+ ioc_put(ioc);
}
free_percpu(iocg->pcpu_stat);
@@ -3004,6 +3013,7 @@ static void ioc_pd_init(struct blkg_policy_data *pd)
ioc_now(ioc, &now);
iocg->ioc = ioc;
+ refcount_inc(&ioc->ref);
atomic64_set(&iocg->vtime, now.vnow);
atomic64_set(&iocg->done_vtime, now.vnow);
atomic64_set(&iocg->active_period, atomic64_read(&ioc->cur_period));