Source code for crash.subsystem.storage.device_mapper
# -*- coding: utf-8 -*-
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
from typing import Callable, Any
from crash.util import container_of
from crash.util.symbols import Types
from crash.subsystem.storage import block_device_name
from crash.subsystem.storage.decoders import Decoder, decode_bio
import gdb
[docs]class ClonedBioReqDecoder(Decoder):
"""
Decodes a request-based device mapper cloned bio
This decodes a cloned bio generated by request-based device mapper targets.
Args:
bio: A ``struct bio`` generated by a request-based device mapper
target. The value must be of type ``struct bio``.
"""
_types = Types(['struct dm_rq_clone_bio_info *'])
__endio__ = 'end_clone_bio'
_description = '{:x} bio: Request-based Device Mapper on {}'
_get_clone_bio_rq_info: Callable[[Any, gdb.Value], gdb.Value]
def __init__(self, bio: gdb.Value) -> None:
super().__init__()
self.bio = bio
if self._get_clone_bio_rq_info is None:
if 'clone' in self._types.dm_rq_clone_bio_info_p_type.target():
getter = self._get_clone_bio_rq_info_3_7
else:
getter = self._get_clone_bio_rq_info_old
self._get_clone_bio_rq_info = getter
[docs] def interpret(self) -> None:
"""Interprets the request-based device mapper bio to populate its
attributes"""
# pylint: disable=attribute-defined-outside-init
self.info = self._get_clone_bio_rq_info(self.bio)
self.tio = self.info['tio']
def __str__(self) -> str:
return self._description.format(int(self.bio),
block_device_name(self.bio['bi_bdev']))
def __next__(self) -> Decoder:
return decode_bio(self.info['orig'])
def _get_clone_bio_rq_info_old(self, bio: gdb.Value) -> gdb.Value:
return bio['bi_private'].cast(self._types.dm_rq_clone_bio_info_p_type)
def _get_clone_bio_rq_info_3_7(self, bio: gdb.Value) -> gdb.Value:
return container_of(bio, self._types.dm_rq_clone_bio_info_p_type, 'clone')
ClonedBioReqDecoder.register()
[docs]class ClonedBioDecoder(Decoder):
"""
Decodes a bio-based device mapper cloned bio
This method decodes cloned bio generated by request-based
device mapper targets.
Args:
bio: A ``struct bio`` generated by a bio-based device mapper target.
The value must be of type ``struct bio``.
Attributes:
bio (:obj:`gdb.Value`): A ``struct bio`` generated by a bio-based
device mapper target. The value is of type ``struct bio``.
next_bio (:obj:`gdb.Value`): The struct bio that generated this one.
The value is of type ``struct bio``.
tio (:obj:`gdb.Value`): The dm target i/o operation for this bio. The
value is of type ``struct dm_target_io``.
"""
_types = Types(['struct dm_target_io *'])
_get_clone_bio_tio: Callable[[Any, gdb.Value], gdb.Value]
__endio__ = 'clone_endio'
_description = "{:x} bio: device mapper clone: {}[{}] -> {}[{}]"
def __init__(self, bio: gdb.Value) -> None:
super().__init__()
self.bio = bio
if self._get_clone_bio_tio is None:
if 'clone' in self._types.dm_target_io_p_type.target():
getter = self._get_clone_bio_tio_3_15
else:
getter = self._get_clone_bio_tio_old
self._get_clone_bio_tio = getter
[docs] def interpret(self) -> None:
"""Interprets the cloned device mapper bio to populate its
attributes"""
# pylint: disable=attribute-defined-outside-init
self.tio = self._get_clone_bio_tio(self.bio)
self.next_bio = self.tio['io']['bio']
def __str__(self) -> str:
return self._description.format(
int(self.bio), block_device_name(self.bio['bi_bdev']),
int(self.bio['bi_sector']),
block_device_name(self.next_bio['bi_bdev']),
int(self.next_bio['bi_sector']))
def __next__(self) -> Decoder:
return decode_bio(self.next_bio)
def _get_clone_bio_tio_old(self, bio: gdb.Value) -> gdb.Value:
return bio['bi_private'].cast(self._types.dm_target_io_p_type)
def _get_clone_bio_tio_3_15(self, bio: gdb.Value) -> gdb.Value:
return container_of(bio['bi_private'],
self._types.dm_clone_bio_info_p_type, 'clone')
ClonedBioDecoder.register()