| # Copyright (C) 2011 Red Hat, Inc. All rights reserved. | |
| # This file is part of LVM2. | |
| # This copyrighted material is made available to anyone wishing to use, | |
| # modify, copy, or redistribute it subject to the terms and conditions | |
| # of the GNU Lesser General Public License v.2.1. | |
| # You should have received a copy of the GNU Lesser General Public License | |
| # along with this program; if not, write to the Free Software Foundation, | |
| # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| # | |
| # Author(s): | |
| # Jonathan Brassow <jbrassow@redhat.com> | |
| # | |
| # Copy this file to ~/.gdbinit or <working_dir>/.gdbinit | |
| printf "\n\n" | |
| printf "Loading commands:\n" | |
| printf " - dm_list_size <list ptr>\n" | |
| printf " - pv_dev_name <PV ptr>\n" | |
| printf " - first_seg <LV ptr>\n" | |
| printf " - lv_status <LV ptr>\n" | |
| printf " - lv_status_r <LV ptr>\n" | |
| printf " - lv_is_mirrored <LV ptr>\n" | |
| printf " - seg_item <seg ptr> <index>\n" | |
| printf " - seg_status <seg ptr>\n" | |
| printf " - segs_using_this_lv <seg ptr>\n" | |
| printf " - seg_pvs <list ptr>\n" | |
| printf " - \n" | |
| printf "Use 'help <command>' for more info\n" | |
| printf "\n\n" | |
| printf "Popular breakpoints:\n" | |
| printf "break _alloc_image_components\n" | |
| printf "run --repair --use-policies vg/lv\n" | |
| printf "\n\n" | |
| set follow-fork-mode child | |
| # Conventions: | |
| # foo : function named 'foo' available to user | |
| # __foo : an internal function | |
| # | |
| # External functions should have a corresponding 'document' | |
| # section. Internal functions should have leading comments | |
| define dm_list_size | |
| set $_DLS_list_head = (struct dm_list *)$arg0 | |
| set $_DLS_list = $_DLS_list_head->n | |
| set $_DLS_size = 0 | |
| while (($_DLS_list != $_DLS_list_head) && ($_DLS_size < 100)) | |
| set $_DLS_list = $_DLS_list->n | |
| set $_DLS_size++ | |
| end | |
| printf "%d list items\n", $_DLS_size | |
| end | |
| document dm_list_size | |
| Returns the number of elements in the dm_list | |
| Usage: dm_list_size <list ptr> | |
| end | |
| define pv_dev_name | |
| set $_PDN_pv = (struct physical_volume *)$arg0 | |
| set $_PDN_dev = $_PDN_pv->dev | |
| set $_PDN_strl = (struct str_list *)$_PDN_dev->aliases.n | |
| printf "%s\n", $_PDN_strl->str | |
| end | |
| document pv_dev_name | |
| Print the name of the PV for the given PV pointer | |
| Usage: pv_dev_name <PV ptr> | |
| end | |
| define seg_pvs | |
| set $_SP_list_head = (struct dm_list *)$arg0 | |
| set $_SP_list = $_SP_list_head->n | |
| while (($_SP_list != $_SP_list_head) && ($_SP_size < 100)) | |
| set $_SP_spv = (struct seg_pvs *)$_SP_list | |
| printf "* Can't print PV list\n" | |
| set $_SP_list = $_SP_list->n | |
| end | |
| printf "%d list items\n", $_SP_size | |
| end | |
| document seg_pvs | |
| Print the elements of a seg_pvs list | |
| Usage: seg_pvs <list ptr> | |
| end | |
| # | |
| # __first_seg <return> <LV> | |
| define __first_seg | |
| set $arg0 = 0x0 | |
| set $_FS_lv = (struct logical_volume *)$arg1 | |
| if ($_FS_lv->segments.n != &$_FS_lv->segments) | |
| set $arg0 = (struct lv_segment *)$_FS_lv->segments.n | |
| end | |
| end | |
| define first_seg | |
| set $_seg = 0 | |
| set $_lv=(struct logical_volume *)$arg0 | |
| __first_seg $_seg $_lv | |
| if ($_seg) | |
| p $_seg | |
| else | |
| printf "No segments (list empty)\n" | |
| end | |
| end | |
| document first_seg | |
| Returns the pointer to the first segment of an LV | |
| Usage: first_seg <LV ptr> | |
| WARNING: If the list pointer in 'struct lv_segment' moves, | |
| this function will be wrong. | |
| end | |
| # | |
| # __seg_type <return> <seg> <index> | |
| define __seg_type | |
| set $arg0 = 0x0 | |
| set $_ST_seg = (struct lv_segment *)$arg1 | |
| set $_ST_index= $arg2 | |
| set $_ST_area = $_ST_seg->areas[$_ST_index] | |
| set $_ST_type = $_ST_area.type | |
| set $arg0 = $_ST_type | |
| end | |
| # | |
| # __seg_item <return> <seg> <index> | |
| define __seg_item | |
| set $arg0 = 0x0 | |
| set $_SI_seg = (struct lv_segment *)$arg1 | |
| set $_SI_index= $arg2 | |
| if ($_SI_index < $_SI_seg->area_count) | |
| set $_SI_area = $_SI_seg->areas[$_SI_index] | |
| set $_SI_type = $_SI_area.type | |
| if ($_SI_type == AREA_PV) | |
| set $arg0 = $_SI_area.u.pv.pvseg->pv | |
| else | |
| if ($_SI_type == AREA_LV) | |
| set $arg0 = $_SI_area.u.lv.lv | |
| end | |
| end | |
| end | |
| end | |
| # | |
| # __seg_metaitem <return> <seg> <index> | |
| define __seg_metaitem | |
| set $arg0 = 0x0 | |
| set $_SMI_seg = (struct lv_segment *)$arg1 | |
| set $_SMI_index= $arg2 | |
| if (($_SMI_index < $_SMI_seg->area_count) && $_SMI_seg->meta_areas) | |
| set $_SMI_area = $_SMI_seg->meta_areas[$_SMI_index] | |
| set $_SMI_type = $_SMI_area.type | |
| if ($_SMI_type == AREA_PV) | |
| set $arg0 = $_SMI_area.u.pv.pvseg->pv | |
| else | |
| if ($_SMI_type == AREA_LV) | |
| set $arg0 = $_SMI_area.u.lv.lv | |
| end | |
| end | |
| end | |
| end | |
| define seg_item | |
| set $_item = 0x0 | |
| __seg_item $_item $arg0 $arg1 | |
| if ($_item) | |
| p $_item | |
| else | |
| printf "AREA_UNASSIGNED or invalid\n" | |
| end | |
| end | |
| define seg_metaitem | |
| set $_metaitem = 0x0 | |
| __seg_metaitem $_metaitem $arg0 $arg1 | |
| if ($_metaitem) | |
| p $_metaitem | |
| else | |
| printf "AREA_UNASSIGNED or invalid\n" | |
| end | |
| end | |
| document seg_item | |
| Returns the pointer to the LV or PV for the indexed area of a segment | |
| Usage: seg_item <struct lv_segment *> <index> | |
| Example - Getting to the sub-lv of a mirror: | |
| (gdb) p lv->name | |
| $1 = 0x712548 "lv" | |
| (gdb) first_seg lv | |
| $2 = (struct lv_segment *) 0x7128b8 | |
| (gdb) seg_item $2 0 | |
| $3 = (struct logical_volume *) 0x712688 | |
| (gdb) p $3->name | |
| $4 = 0x712770 "lv_mimage_0" | |
| end | |
| define __status | |
| set $_s_status = $arg0->status | |
| # Constants defined in metadata-exported.h | |
| # if ($_s_status & RAID) | |
| if ($_s_status & 0x0000000100000000LU) | |
| set $_s_status = $_s_status & ~0x0000000100000000LU | |
| printf " RAID" | |
| end | |
| # if ($_s_status & RAID_META) | |
| if ($_s_status & 0x0000000200000000LU) | |
| set $_s_status = $_s_status & ~0x0000000200000000LU | |
| printf " RAID_META" | |
| end | |
| # if ($_s_status & RAID_IMAGE) | |
| if ($_s_status & 0x0000000400000000LU) | |
| set $_s_status = $_s_status & ~0x0000000400000000LU | |
| printf " RAID_IMAGE" | |
| end | |
| # if ($_s_status & MIRRORED) | |
| if ($_s_status & 0x00008000U) | |
| set $_s_status = $_s_status & ~0x00008000U | |
| printf " MIRRORED" | |
| end | |
| # if ($_s_status & MIRROR_LOG) | |
| if ($_s_status & 0x00020000U) | |
| set $_s_status = $_s_status & ~0x00020000U | |
| printf " MIRROR_LOG" | |
| end | |
| # if ($_s_status & MIRROR_IMAGE) | |
| if ($_s_status & 0x00040000U) | |
| set $_s_status = $_s_status & ~0x00040000U | |
| printf " MIRROR_IMAGE" | |
| end | |
| # if ($_s_status & VISIBLE_LV) | |
| if ($_s_status & 0x00000040U) | |
| printf " VISIBLE_LV" | |
| set $_s_status = $_s_status & ~0x00000040U | |
| else | |
| printf " *HIDDEN_LV*" | |
| end | |
| # if ($_s_status & FIXED_MINOR) | |
| if ($_s_status & 0x00000080U) | |
| set $_s_status = $_s_status & ~0x00000080U | |
| printf " FIXED_MINOR" | |
| end | |
| # if ($_s_status & LVM_READ) | |
| if ($_s_status & 0x00000100U) | |
| set $_s_status = $_s_status & ~0x00000100U | |
| printf " LVM_READ" | |
| end | |
| # if ($_s_status & LVM_WRITE) | |
| if ($_s_status & 0x00000200U) | |
| set $_s_status = $_s_status & ~0x00000200U | |
| printf " LVM_WRITE" | |
| end | |
| # if ($_s_status & SNAPSHOT) | |
| if ($_s_status & 0x00001000U) | |
| set $_s_status = $_s_status & ~0x00001000U | |
| printf " SNAPSHOT" | |
| end | |
| # if ($_s_status & PVMOVE) | |
| if ($_s_status & 0x00002000U) | |
| set $_s_status = $_s_status & ~0x00002000U | |
| printf " PVMOVE" | |
| end | |
| # if ($_s_status & LOCKED) | |
| if ($_s_status & 0x00004000U) | |
| set $_s_status = $_s_status & ~0x00004000U | |
| printf " LOCKED" | |
| end | |
| # if ($_s_status & LV_NOTSYNCED) | |
| if ($_s_status & 0x00080000U) | |
| set $_s_status = $_s_status & ~0x00080000U | |
| printf " LV_NOTSYNCED" | |
| end | |
| # if ($_s_status & CONVERTING) | |
| if ($_s_status & 0x00400000U) | |
| set $_s_status = $_s_status & ~0x00400000U | |
| printf " CONVERTING" | |
| end | |
| # if ($_s_status & LV_REBUILD) | |
| if ($_s_status & 0x100000U) | |
| set $_s_status = $_s_status & ~0x100000U | |
| printf " LV_REBUILD" | |
| end | |
| # if ($_s_status & PARTIAL_LV) | |
| if ($_s_status & 0x1000000U) | |
| set $_s_status = $_s_status & ~0x1000000U | |
| printf " PARTIAL_LV" | |
| end | |
| # if ($_s_status & MERGING) | |
| if ($_s_status & 0x10000000U) | |
| set $_s_status = $_s_status & ~0x10000000U | |
| printf " MERGING" | |
| end | |
| # if ($_s_status & LV_WRITEMOSTLY) | |
| if ($_s_status & 0x10000000000U) | |
| set $_s_status = $_s_status & ~0x10000000000U | |
| printf " LV_WRITEMOSTLY" | |
| end | |
| if ($_s_status) | |
| printf " 0x%x", $_s_status | |
| end | |
| end | |
| # | |
| # __print_indent <num indents> [No marks] | |
| define __print_indent | |
| set $_PI_indent = $arg0 | |
| set $_PI_lead_mark = 0 | |
| while ($_PI_indent) | |
| if ($_PI_indent == 1) | |
| if ($argc > 1) | |
| if ($_PI_lead_mark) | |
| printf " " | |
| else | |
| printf "| " | |
| end | |
| else | |
| printf "|-----> " | |
| end | |
| else | |
| printf "| " | |
| set $_PI_lead_mark = 1 | |
| end | |
| set $_PI_indent-- | |
| end | |
| end | |
| define lv_status | |
| # Use __lv because we don't want to overwrite higher functions | |
| set $__lv = (struct logical_volume *)$arg0 | |
| if ($argc == 2) | |
| __print_indent $arg1 | |
| end | |
| printf "%s->status:", $__lv->name | |
| __status $__lv | |
| printf "\n" | |
| end | |
| document lv_status | |
| Display the flags that are set on an LV. | |
| Usage: lv_status <LV ptr> | |
| end | |
| define seg_status | |
| set $_seg=(struct lv_segment *)$arg0 | |
| if ($argc == 2) | |
| __print_indent $arg1 1 | |
| end | |
| printf "[ (%s) seg->status:", $_seg->lv->name | |
| __status $_seg | |
| printf " ]\n" | |
| end | |
| document seg_status | |
| Display the flags that are set on an lv_segment. | |
| Usage: seg_status <(struct lv_segment *)> | |
| end | |
| # | |
| # get_only_segment_using_this_lv <return> <LV> | |
| define __get_only_segment_using_this_lv | |
| set $arg0 = 0x0 | |
| set $_lv=(struct logical_volume *)$arg1 | |
| set $_seg_list_head = &$_lv->segs_using_this_lv | |
| set $_s = $_lv->segs_using_this_lv.n | |
| set $_i = 0 | |
| while (($_s != $_seg_list_head) && ($_i < 100)) | |
| set $_seg_list = (struct seg_list *)$_s | |
| set $_seg = (struct lv_segment *)$_seg_list->seg | |
| set $_i++ | |
| set $_s = $_s->n | |
| end | |
| if ($_i > 1) | |
| printf "More than %s using %s\n", ($_i > 99) ? "100 segments" : "one segment", $_lv->name | |
| end | |
| if ($_i == 1) | |
| set $arg0 = $_seg | |
| end | |
| end | |
| define segs_using_this_lv | |
| set $_lv=(struct logical_volume *)$arg0 | |
| set $_seg_list_head = &$_lv->segs_using_this_lv | |
| set $_s = $_lv->segs_using_this_lv.n | |
| set $_i = 0 | |
| if ($_s != $_seg_list_head) | |
| printf "Segments using %s\n", $_lv->name | |
| else | |
| printf "No segments using %s\n", $_lv->name | |
| end | |
| while ($_s != $_seg_list_head) | |
| set $_seg_list = (struct seg_list *)$_s | |
| set $_seg = (struct lv_segment *)$_seg_list->seg | |
| printf " %d) seg: %p", $_i, $_seg | |
| if ($_seg->lv < 0x200) | |
| printf " [BAD LV POINTER FROM THIS SEG]\n" | |
| else | |
| printf " [seg found in %s]\n", $_seg->lv->name | |
| end | |
| set $_i++ | |
| set $_s = $_s->n | |
| end | |
| end | |
| document segs_using_this_lv | |
| Display the segments (and their associated LV) using an LV | |
| Usage: segs_using_this_lv <LV ptr> | |
| Example: | |
| (gdb) lv_is_mirrored lv | |
| lv is mirrored ('core' log) | |
| (gdb) segs_using_this_lv lv | |
| No segments using lv | |
| (gdb) first_seg lv | |
| $1 = (struct lv_segment *) 0x92d360 | |
| (gdb) seg_item $1 0 | |
| $2 = (struct logical_volume *) 0x928f58 | |
| (gdb) segs_using_this_lv $2 | |
| Segments using lv_mimage_0 | |
| 0) seg: 0x92d360 [seg found in lv] | |
| end | |
| # | |
| # __next_area_index <return> <seg> <seg_item> | |
| define __next_area_index | |
| set $arg0 = 0x0 | |
| set $_seg = (struct lv_segment *)$arg1 | |
| set $_item = 0x0 | |
| set $_i = 0 | |
| __seg_item $_item $_seg $_i | |
| while ($_item && ($_item != $arg2)) | |
| set $_i++ | |
| __seg_item $_item $_seg $_i | |
| end | |
| # $_i points to current, now get next (if there) | |
| set $_i++ | |
| __seg_item $_item $_seg $_i | |
| if ($_item) | |
| set $arg0 = $_i | |
| end | |
| end | |
| # | |
| # __lv_status_r <LV> | |
| # Decend tree, printing LV and seg status as we go. This | |
| # performs a depth first approach (but can't come up) | |
| # | |
| # or | |
| # | |
| # __lv_status_r <sub_lv> <seg using sub_lv> | |
| # Try continuing decent of tree by first shifting to the | |
| # next 'area' in the seg ($arg1). If no more areas, then | |
| # try going to the next segment. | |
| define __lv_status_r | |
| if ($argc == 1) | |
| set $_lv=(struct logical_volume *)$arg0 | |
| set $_seg_list_head = &$_lv->segments | |
| set $_s = $_lv->segments.n | |
| set $_area_index = 0 | |
| # printf "\n" | |
| lv_status $_lv $indent | |
| else | |
| set $_seg = (struct lv_segment *)$arg1 | |
| __next_area_index $_area_index $_seg $arg0 | |
| # Don't fuck this up. We need the next two lines here. | |
| set $_lv=(struct logical_volume *)$_seg->lv | |
| set $_seg_list_head = &$_lv->segments | |
| set $_s = (struct dm_list *)$_seg | |
| if (!$_area_index) | |
| set $_s = $_s->n | |
| end | |
| end | |
| if ($_s == $_seg_list_head) | |
| if ($argc == 1) | |
| __print_indent $indent 1 | |
| printf "[ No segments for %s ]\n", $_lv->name | |
| end | |
| __get_only_segment_using_this_lv $_seg $_lv | |
| if ($_seg && $indent) | |
| set $indent-- | |
| __lv_status_r $_lv $_seg | |
| end | |
| else | |
| set $_seg = (struct lv_segment *)$_s | |
| set $_type = 0x0 | |
| if (!$_area_index) | |
| seg_status $_seg $indent | |
| end | |
| __seg_type $_type $_seg $_area_index | |
| if ($_type == AREA_LV) | |
| set $indent++ | |
| __seg_metaitem $_lv $_seg $_area_index | |
| if ($_lv) | |
| set $rindent = $indent | |
| set $rseg = $_seg | |
| set $rarea_index = $_area_index | |
| set $rlv = $_lv | |
| __lv_status_r $_lv | |
| set $indent = $rindent | |
| set $_seg = $rseg | |
| set $_area_index = $rarea_index | |
| set $_lv = $rlv | |
| end | |
| __seg_item $_lv $_seg $_area_index | |
| __lv_status_r $_lv | |
| else | |
| if ($_seg->log_lv) | |
| set $indent++ | |
| set $_log_seg = 0x0 | |
| __first_seg $_log_seg $_seg->log_lv | |
| lv_status $_seg->log_lv $indent | |
| seg_status $_log_seg $indent | |
| set $indent-- | |
| end | |
| __get_only_segment_using_this_lv $_seg $_lv | |
| if ($_seg) | |
| set $indent-- | |
| __lv_status_r $_lv $_seg | |
| end | |
| end | |
| end | |
| end | |
| define lv_status_r | |
| set $indent = 0 | |
| __lv_status_r $arg0 | |
| end | |
| document lv_status_r | |
| Display the status flags of an LV and its sub_lvs. | |
| Usage: lv_status_r <LV ptr> | |
| This function is useful for checking that all the LVs that | |
| compose a logical volume have the correct flags set (and also | |
| their associated lv_segments) | |
| end | |
| define lv_is_mirrored | |
| set $_lv=(struct logical_volume *)$arg0 | |
| set $_fs=(struct lv_segment *)$_lv->segments.n | |
| set $_log_lv=(struct logical_volume *)$_fs->log_lv | |
| # if ($_lv->status & MIRRORED) | |
| if ($_lv->status & 0x00008000U) | |
| printf "%s is mirrored (", $_lv->name | |
| if ($_log_lv) | |
| if ($_log_lv->status & 0x00008000U) | |
| printf "'mirrored' log)\n" | |
| else | |
| printf "'disk' log)\n" | |
| end | |
| else | |
| printf "'core' log)\n" | |
| end | |
| else | |
| printf "%s is not mirrored\n", $_lv->name | |
| end | |
| end | |
| document lv_is_mirrored | |
| Report whether the given LV is mirrored (and its log type). | |
| Usage: lv_is_mirrored <LV ptr> | |
| end |