Source code for crash.subsystem.storage.blockmq

# -*- coding: utf-8 -*-
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:

from typing import Iterable, Tuple

import gdb

from crash.util.symbols import Types
from crash.subsystem.storage import queue_is_mq, rq_is_sync, rq_in_flight
from crash.types.sbitmap import sbitmap_for_each_set
from crash.exceptions import InvalidArgumentError

[docs] class NoQueueError(RuntimeError): pass
types = Types(['struct request', 'struct request_queue', 'struct sbitmap_queue', 'struct blk_mq_hw_ctx']) def _check_queue_type(queue: gdb.Value) -> None: if not queue_is_mq(queue): raise InvalidArgumentError("Passed request queue is not a multiqueue queue")
[docs] def mq_queue_for_each_hw_ctx(queue: gdb.Value) -> Iterable[gdb.Value]: """ Iterates over each ``struct blk_mq_hw_ctx`` in request_queue This method iterates over each blk-mq hardware context in request_queue and yields each blk_mq_hw_ctx. Args: queue: The ``struct request_queue`` used to iterate. The value must be of type ``struct request_queue``. Yields: :obj:`gdb.Value`: Each blk-mq hardware context contained within the ``request_queue``. The value is of type ``struct blk_mq_hw_ctx``. """ _check_queue_type(queue) for i in range(int(queue['nr_hw_queues'])): yield queue['queue_hw_ctx'][i]
[docs] def mq_for_each_request_in_queue(queue: gdb.Value, reserved: bool = True) \ -> Iterable[gdb.Value]: """ Iterates over each ``struct request`` in request_queue This method iterates over the ``request_queue``'s queuelist and returns a request for each member. This method iterates over the tags of all hardware contexts of ``request_queue`` and returns a request for each member. Args: queue: The ``struct request_queue`` used to iterate. The value must be of type ``struct request_queue``. reserved: If true, also reserved requests will be included in the iteration Yields: :obj:`gdb.Value`: Each ``struct request`` contained within the ``request_queue``'s queuelist. The value is of type ``struct request``. ``request_queue``'s tags. The value is of type ``struct request``. """ if int(queue) == 0: raise NoQueueError("Queue is NULL") _check_queue_type(queue) for hctx in mq_queue_for_each_hw_ctx(queue): tags = hctx['tags'] if int(hctx['nr_ctx']) == 0 or int(tags) == 0: continue if reserved is True and int(tags['nr_reserved_tags']) > 0: for tag in sbitmap_for_each_set(tags['breserved_tags']['sb']): rq = tags['rqs'][tag] if int(rq) != 0 and rq['q'] == queue: yield rq for tag in sbitmap_for_each_set(tags['bitmap_tags']['sb']): rq = tags['rqs'][tag + int(tags['nr_reserved_tags'])] if int(rq) != 0 and rq['q'] == queue: yield rq
[docs] def mq_requests_in_flight(queue: gdb.Value) -> Tuple[int, int]: """ Report how many requests are in flight for this queue Args: queue: The request queue to inspect for requests in flight. The value must be of type ``struct request_queue``. Returns: (:obj:`int`, :obj:`int`): The requests in flight. The first member of the 2-tuple is the number of async requests, the second is the number of sync requests. """ _check_queue_type(queue) in_flight = [0, 0] for rq in mq_for_each_request_in_queue(queue): if rq_in_flight(rq): in_flight[rq_is_sync(rq)] += 1 return (in_flight[0], in_flight[1])
[docs] def mq_requests_queued(queue: gdb.Value) -> Tuple[int, int]: """ Report how many requests are queued for this queue Args: queue: The request queue to inspect for queued requests. The value must be of type ``struct request_queue``. Returns: (:obj:`int`, :obj:`int`): The queued requests. The first member of the 2-tuple is the number of async requests, the second is the number of sync requests. """ _check_queue_type(queue) queued = [0, 0] for rq in mq_for_each_request_in_queue(queue): queued[rq_is_sync(rq)] += 1 return (queued[0], queued[1])
[docs] def mq_queue_request_stats(queue: gdb.Value) -> Tuple[int, int, int, int]: """ Report various request information for this queue Args: queue: The request queue to inspect for request information. The value must be of type ``struct request_queue``. Returns: (:obj:`int`, :obj:`int`, :obj:`int`, :obj:`int`): Number queued async requests, number of queued sync requests, number of async requests being processed by the driver, number of sync requests being processed by the driver. """ _check_queue_type(queue) stats = [0, 0, 0, 0] for rq in mq_for_each_request_in_queue(queue): stats[rq_is_sync(rq)] += 1 if rq_in_flight(rq): stats[2 + rq_is_sync(rq)] += 1 return (stats[0], stats[1], stats[2], stats[3])