drivers/md/dm-vdo/indexer/funnel-requestqueue.c

Source file repositories/reference/linux-study-clean/drivers/md/dm-vdo/indexer/funnel-requestqueue.c

File Facts

System
Linux kernel
Corpus path
drivers/md/dm-vdo/indexer/funnel-requestqueue.c
Extension
.c
Size
8207 bytes
Lines
280
Domain
Driver Families
Bucket
drivers/md
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct uds_request_queue {
	/* Wait queue for synchronizing producers and consumer */
	struct wait_queue_head wait_head;
	/* Function to process a request */
	uds_request_queue_processor_fn processor;
	/* Queue of new incoming requests */
	struct funnel_queue *main_queue;
	/* Queue of old requests to retry */
	struct funnel_queue *retry_queue;
	/* The thread id of the worker thread */
	struct thread *thread;
	/* True if the worker was started */
	bool started;
	/* When true, requests can be enqueued */
	bool running;
	/* A flag set when the worker is waiting without a timeout */
	atomic_t dormant;
};

static inline struct uds_request *poll_queues(struct uds_request_queue *queue)
{
	struct funnel_queue_entry *entry;

	entry = vdo_funnel_queue_poll(queue->retry_queue);
	if (entry != NULL)
		return container_of(entry, struct uds_request, queue_link);

	entry = vdo_funnel_queue_poll(queue->main_queue);
	if (entry != NULL)
		return container_of(entry, struct uds_request, queue_link);

	return NULL;
}

static inline bool are_queues_idle(struct uds_request_queue *queue)
{
	return vdo_is_funnel_queue_idle(queue->retry_queue) &&
	       vdo_is_funnel_queue_idle(queue->main_queue);
}

/*
 * Determine if there is a next request to process, and return it if there is. Also return flags
 * indicating whether the worker thread can sleep (for the use of wait_event() macros) and whether
 * the thread did sleep before returning a new request.
 */
static inline bool dequeue_request(struct uds_request_queue *queue,
				   struct uds_request **request_ptr, bool *waited_ptr)
{
	struct uds_request *request = poll_queues(queue);

	if (request != NULL) {
		*request_ptr = request;
		return true;
	}

	if (!READ_ONCE(queue->running)) {
		/* Wake the worker thread so it can exit. */
		*request_ptr = NULL;
		return true;
	}

	*request_ptr = NULL;
	*waited_ptr = true;
	return false;
}

static void wait_for_request(struct uds_request_queue *queue, bool dormant,
			     unsigned long timeout, struct uds_request **request,
			     bool *waited)
{
	if (dormant) {
		wait_event_interruptible(queue->wait_head,
					 (dequeue_request(queue, request, waited) ||
					  !are_queues_idle(queue)));
		return;
	}

	wait_event_interruptible_hrtimeout(queue->wait_head,
					   dequeue_request(queue, request, waited),
					   ns_to_ktime(timeout));
}

static void request_queue_worker(void *arg)
{
	struct uds_request_queue *queue = arg;
	struct uds_request *request = NULL;
	unsigned long time_batch = DEFAULT_WAIT_TIME;
	bool dormant = atomic_read(&queue->dormant);
	bool waited = false;
	long current_batch = 0;

Annotation

Implementation Notes