/* association between a blk cgroup and a request queue */ struct blkcg_gq { /* Pointer to the associated request_queue */ struct request_queue *q; struct list_head q_node; struct hlist_node blkcg_node; struct blkcg *blkcg;
/* all non-root blkcg_gq's are guaranteed to have access to parent */ struct blkcg_gq *parent;
/* reference count */ struct percpu_ref refcnt;
/* is this blkg online? protected by both blkcg and q locks */ bool online;
atomic_t use_delay;
atomic64_t delay_nsec;
atomic64_t delay_start;
u64 last_delay; int last_use;
struct rcu_head rcu_head;
};
struct blkcg { struct cgroup_subsys_state css;
spinlock_t lock;
refcount_t online_pin; /* If there is block congestion on this cgroup. */
atomic_t congestion_count;
/* *Ablkcg_gq(blkg)isassociationbetweenablockcgroup(blkcg)anda *request_queue(q).Thisisusedbyblkcgpolicieswhichneedtotrack *informationperblkcg-qpair. * *Therecanbemultipleactiveblkcgpoliciesandeachblkg:policypairis *representedbyablkg_policy_datawhichisallocatedandfreedbyeach *policy'spd_alloc/free_fn()methods.Apolicycanallocateprivatedata *areabyallocatinglargerdatastructurewhichembedsblkg_policy_data *atthebeginning.
*/ struct blkg_policy_data { /* the blkg and policy id this per-policy data belongs to */ struct blkcg_gq *blkg; int plid; bool online;
};
/* *Policiesthatneedtokeepper-blkcgdatawhichisindependentfromany *request_queueassociatedtoitshouldimplementcpd_alloc/free_fn() *methods.Apolicycanallocateprivatedataareabyallocatinglarger *datastructurewhichembedsblkcg_policy_dataatthebeginning. *cpd_init()isinvokedtoleteachpolicyhandleper-blkcgdata.
*/ struct blkcg_policy_data { /* the blkcg and policy id this per-policy data belongs to */ struct blkcg *blkcg; int plid;
};
staticinlinevoid blkcg_use_delay(struct blkcg_gq *blkg)
{ if (WARN_ON_ONCE(atomic_read(&blkg->use_delay) < 0)) return; if (atomic_add_return(1, &blkg->use_delay) == 1)
atomic_inc(&blkg->blkcg->congestion_count);
}
staticinlineint blkcg_unuse_delay(struct blkcg_gq *blkg)
{ int old = atomic_read(&blkg->use_delay);
if (WARN_ON_ONCE(old < 0)) return0; if (old == 0) return0;
/* *Wedothissonganddancebecausewecanracewithsomebodyelse *addingorremovingdelay.Ifwejustdidanatomic_decwe'dendup *negativeandwe'dalreadybeintrouble.Weneedtosubtract1and *thenchecktoseeifwewerethelastdelaysowecandropthe *congestioncountonthecgroup.
*/ while (old && !atomic_try_cmpxchg(&blkg->use_delay, &old, old - 1))
;
if (old == 0) return0; if (old == 1)
atomic_dec(&blkg->blkcg->congestion_count); return1;
}
/** *blkcg_set_delay-Enableallocatordelaymechanismwiththespecifieddelayamount *@blkg:targetblkg *@delay:delaydurationinnsecs * *Whenenabledwiththisfunction,thedelayisnotdecayedandmustbe *explicitlyclearedwithblkcg_clear_delay().Mustnotbemixedwith *blkcg_[un]use_delay()andblkcg_add_delay()usages.
*/ staticinlinevoid blkcg_set_delay(struct blkcg_gq *blkg, u64 delay)
{ int old = atomic_read(&blkg->use_delay);
/* We only want 1 person setting the congestion count for this blkg. */ if (!old && atomic_try_cmpxchg(&blkg->use_delay, &old, -1))
atomic_inc(&blkg->blkcg->congestion_count);
atomic64_set(&blkg->delay_nsec, delay);
}
/** *blkcg_clear_delay-Disableallocatordelaymechanism *@blkg:targetblkg * *Disableuse_delaymechanism.Seeblkcg_set_delay().
*/ staticinlinevoid blkcg_clear_delay(struct blkcg_gq *blkg)
{ int old = atomic_read(&blkg->use_delay);
/* We only want 1 person clearing the congestion count for this blkg. */ if (old && atomic_try_cmpxchg(&blkg->use_delay, &old, 0))
atomic_dec(&blkg->blkcg->congestion_count);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.