block/blk-rq-qos.c
Source file repositories/reference/linux-study-clean/block/blk-rq-qos.c
File Facts
- System
- Linux kernel
- Corpus path
block/blk-rq-qos.c- Extension
.c- Size
- 9726 bytes
- Lines
- 375
- Domain
- Representative Device Path
- Bucket
- PCIe NVMe Storage Path
- Inferred role
- Representative Device Path: implementation source
- Status
- source implementation candidate
Why This File Exists
Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.
- Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
blk-rq-qos.h
Detected Declarations
struct rq_qos_wait_datafunction atomic_inc_belowfunction rq_wait_inc_belowfunction __rq_qos_cleanupfunction __rq_qos_donefunction __rq_qos_issuefunction __rq_qos_requeuefunction __rq_qos_throttlefunction __rq_qos_trackfunction __rq_qos_mergefunction __rq_qos_done_biofunction __rq_qos_queue_depth_changedfunction rq_depth_calc_max_depthfunction rq_depth_scale_upfunction rq_depth_scale_downfunction rq_qos_wake_functionfunction rq_qos_waitfunction rq_qos_exitfunction rq_qos_addfunction rq_qos_del
Annotated Snippet
struct rq_qos_wait_data {
struct wait_queue_entry wq;
struct rq_wait *rqw;
acquire_inflight_cb_t *cb;
void *private_data;
bool got_token;
};
static int rq_qos_wake_function(struct wait_queue_entry *curr,
unsigned int mode, int wake_flags, void *key)
{
struct rq_qos_wait_data *data = container_of(curr,
struct rq_qos_wait_data,
wq);
/*
* If we fail to get a budget, return -1 to interrupt the wake up loop
* in __wake_up_common.
*/
if (!data->cb(data->rqw, data->private_data))
return -1;
data->got_token = true;
/*
* autoremove_wake_function() removes the wait entry only when it
* actually changed the task state. We want the wait always removed.
* Remove explicitly and use default_wake_function().
*/
default_wake_function(curr, mode, wake_flags, key);
/*
* Note that the order of operations is important as finish_wait()
* tests whether @curr is removed without grabbing the lock. This
* should be the last thing to do to make sure we will not have a
* UAF access to @data. And the semantics of memory barrier in it
* also make sure the waiter will see the latest @data->got_token
* once list_empty_careful() in finish_wait() returns true.
*/
list_del_init_careful(&curr->entry);
return 1;
}
/**
* rq_qos_wait - throttle on a rqw if we need to
* @rqw: rqw to throttle on
* @private_data: caller provided specific data
* @acquire_inflight_cb: inc the rqw->inflight counter if we can
* @cleanup_cb: the callback to cleanup in case we race with a waker
*
* This provides a uniform place for the rq_qos users to do their throttling.
* Since you can end up with a lot of things sleeping at once, this manages the
* waking up based on the resources available. The acquire_inflight_cb should
* inc the rqw->inflight if we have the ability to do so, or return false if not
* and then we will sleep until the room becomes available.
*
* cleanup_cb is in case that we race with a waker and need to cleanup the
* inflight count accordingly.
*/
void rq_qos_wait(struct rq_wait *rqw, void *private_data,
acquire_inflight_cb_t *acquire_inflight_cb,
cleanup_cb_t *cleanup_cb)
{
struct rq_qos_wait_data data = {
.rqw = rqw,
.cb = acquire_inflight_cb,
.private_data = private_data,
.got_token = false,
};
bool first_waiter;
/*
* If there are no waiters in the waiting queue, try to increase the
* inflight counter if we can. Otherwise, prepare for adding ourselves
* to the waiting queue.
*/
if (!waitqueue_active(&rqw->wait) && acquire_inflight_cb(rqw, private_data))
return;
init_wait_func(&data.wq, rq_qos_wake_function);
first_waiter = prepare_to_wait_exclusive(&rqw->wait, &data.wq,
TASK_UNINTERRUPTIBLE);
/*
* Make sure there is at least one inflight process; otherwise, waiters
* will never be woken up. Since there may be no inflight process before
* adding ourselves to the waiting queue above, we need to try to
* increase the inflight counter for ourselves. And it is sufficient to
* guarantee that at least the first waiter to enter the waiting queue
* will re-check the waiting condition before going to sleep, thus
* ensuring forward progress.
*/
if (!data.got_token && first_waiter && acquire_inflight_cb(rqw, private_data)) {
Annotation
- Immediate include surface: `blk-rq-qos.h`.
- Detected declarations: `struct rq_qos_wait_data`, `function atomic_inc_below`, `function rq_wait_inc_below`, `function __rq_qos_cleanup`, `function __rq_qos_done`, `function __rq_qos_issue`, `function __rq_qos_requeue`, `function __rq_qos_throttle`, `function __rq_qos_track`, `function __rq_qos_merge`.
- Atlas domain: Representative Device Path / PCIe NVMe Storage Path.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.