2011-03-10 16:45:12 +03:00
# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Author(s):
# Jonathan Brassow <jbrassow@redhat.com>
#
# Copy this file to ~/.gdbinit or <working_dir>/.gdbinit
printf "\n\n"
printf "Loading commands:\n"
2011-09-28 20:32:22 +04:00
printf " - dm_list_size <list ptr>\n"
2011-03-10 16:45:12 +03:00
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 " - \n"
printf "Use 'help <command>' for more info\n"
printf "\n\n"
printf "Popular breakpoints:\n"
2011-09-28 20:32:22 +04:00
printf "break _get_udev_flags\n"
printf "run --splitmirrors 1 -n split vg/lv\n"
2011-03-10 16:45:12 +03:00
printf "\n\n"
set follow-fork-mode child
2011-03-12 01:16:38 +03:00
# 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
2011-09-28 20:32:22 +04:00
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
2011-03-12 01:16:38 +03:00
#
# __first_seg <return> <LV>
define __first_seg
set $arg0 = 0x0
2011-03-14 21:05:56 +03:00
set $_FS_lv = (struct logical_volume *)$arg1
2011-03-12 01:16:38 +03:00
2011-03-14 21:05:56 +03:00
if ($_FS_lv->segments.n != &$_FS_lv->segments)
set $arg0 = (struct lv_segment *)$_FS_lv->segments.n
2011-03-12 01:16:38 +03:00
end
end
2011-03-10 16:45:12 +03:00
define first_seg
2011-03-12 01:16:38 +03:00
set $_seg = 0
set $_lv=(struct logical_volume *)$arg0
2011-03-10 16:45:12 +03:00
2011-03-12 01:16:38 +03:00
__first_seg $_seg $_lv
if ($_seg)
p $_seg
2011-03-10 16:45:12 +03:00
else
2011-03-12 01:16:38 +03:00
printf "No segments (list empty)\n"
2011-03-10 16:45:12 +03:00
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
2011-03-12 01:16:38 +03:00
#
2011-07-01 20:15:25 +04:00
# __seg_type <return> <seg> <index>
2011-03-12 01:16:38 +03:00
define __seg_type
set $arg0 = 0x0
2011-03-14 21:05:56 +03:00
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
2011-03-12 01:16:38 +03:00
2011-03-14 21:05:56 +03:00
set $arg0 = $_ST_type
2011-03-12 01:16:38 +03:00
end
2011-03-10 16:45:12 +03:00
2011-03-12 01:16:38 +03:00
#
# __seg_item <return> <seg> <index>
define __seg_item
set $arg0 = 0x0
2011-03-14 21:05:56 +03:00
set $_SI_seg = (struct lv_segment *)$arg1
set $_SI_index= $arg2
2011-03-12 01:16:38 +03:00
2011-03-14 21:05:56 +03:00
if ($_SI_index < $_SI_seg->area_count)
set $_SI_area = $_SI_seg->areas[$_SI_index]
set $_SI_type = $_SI_area.type
2011-03-12 01:16:38 +03:00
2011-03-14 21:05:56 +03:00
if ($_SI_type == AREA_PV)
set $arg0 = $_SI_area.u.pv.pvseg->pv
2011-03-10 16:45:12 +03:00
else
2011-03-14 21:05:56 +03:00
if ($_SI_type == AREA_LV)
set $arg0 = $_SI_area.u.lv.lv
2011-03-12 01:16:38 +03:00
end
2011-03-10 16:45:12 +03:00
end
end
end
2011-07-01 20:15:25 +04:00
#
# __seg_metaitem <return> <seg> <index>
define __seg_metaitem
set $arg0 = 0x0
set $_SMI_seg = (struct lv_segment *)$arg1
set $_SMI_index= $arg2
2011-09-02 01:01:12 +04:00
if (($_SMI_index < $_SMI_seg->area_count) && $_SMI_seg->meta_areas)
2011-07-01 20:15:25 +04:00
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
2011-03-12 01:16:38 +03:00
define seg_item
set $_item = 0x0
__seg_item $_item $arg0 $arg1
if ($_item)
p $_item
else
printf "AREA_UNASSIGNED or invalid\n"
end
end
2011-07-01 20:15:25 +04:00
define seg_metaitem
set $_metaitem = 0x0
__seg_metaitem $_metaitem $arg0 $arg1
if ($_metaitem)
p $_metaitem
else
printf "AREA_UNASSIGNED or invalid\n"
end
end
2011-03-10 16:45:12 +03:00
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
2011-07-01 20:15:25 +04:00
set $_s_status = $arg0->status
2011-03-10 16:45:12 +03:00
# Constants defined in metadata-exported.h
2011-09-02 01:01:12 +04:00
# if ($_s_status & RAID)
2011-09-09 02:19:45 +04:00
if ($_s_status & 0x0000000100000000LU)
set $_s_status = $_s_status & ~0x0000000100000000LU
2011-09-02 01:01:12 +04:00
printf " RAID"
end
# if ($_s_status & RAID_META)
2011-09-09 02:19:45 +04:00
if ($_s_status & 0x0000000200000000LU)
set $_s_status = $_s_status & ~0x0000000200000000LU
2011-09-02 01:01:12 +04:00
printf " RAID_META"
end
# if ($_s_status & RAID_IMAGE)
2011-09-09 02:19:45 +04:00
if ($_s_status & 0x0000000400000000LU)
set $_s_status = $_s_status & ~0x0000000400000000LU
2011-09-02 01:01:12 +04:00
printf " RAID_IMAGE"
end
2011-09-13 17:57:02 +04:00
# 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
2011-07-01 20:15:25 +04:00
# if ($_s_status & VISIBLE_LV)
if ($_s_status & 0x00000040U)
2011-03-10 16:45:12 +03:00
printf " VISIBLE_LV"
2011-07-01 20:15:25 +04:00
set $_s_status = $_s_status & ~0x00000040U
2011-03-10 16:45:12 +03:00
else
printf " *HIDDEN_LV*"
end
2011-07-01 20:15:25 +04:00
# if ($_s_status & FIXED_MINOR)
if ($_s_status & 0x00000080U)
set $_s_status = $_s_status & ~0x00000080U
2011-03-10 16:45:12 +03:00
printf " FIXED_MINOR"
end
2011-09-02 01:01:12 +04:00
# 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
2011-07-01 20:15:25 +04:00
# if ($_s_status & SNAPSHOT)
if ($_s_status & 0x00001000U)
set $_s_status = $_s_status & ~0x00001000U
2011-03-10 16:45:12 +03:00
printf " SNAPSHOT"
end
2011-07-01 20:15:25 +04:00
# if ($_s_status & PVMOVE)
if ($_s_status & 0x00002000U)
set $_s_status = $_s_status & ~0x00002000U
2011-03-10 16:45:12 +03:00
printf " PVMOVE"
end
2011-07-01 20:15:25 +04:00
# if ($_s_status & LOCKED)
if ($_s_status & 0x00004000U)
set $_s_status = $_s_status & ~0x00004000U
2011-03-10 16:45:12 +03:00
printf " LOCKED"
end
2011-07-01 20:15:25 +04:00
# if ($_s_status & LV_NOTSYNCED)
if ($_s_status & 0x00080000U)
set $_s_status = $_s_status & ~0x00080000U
2011-03-11 21:22:39 +03:00
printf " LV_NOTSYNCED"
2011-03-10 16:45:12 +03:00
end
2011-07-01 20:15:25 +04:00
# if ($_s_status & CONVERTING)
if ($_s_status & 0x00400000U)
set $_s_status = $_s_status & ~0x00400000U
2011-03-10 16:45:12 +03:00
printf " CONVERTING"
end
2011-09-02 01:01:12 +04:00
# if ($_s_status & MERGING)
if ($_s_status & 0x10000000U)
set $_s_status = $_s_status & ~0x10000000U
printf " MERGING"
2011-07-01 20:15:25 +04:00
end
if ($_s_status)
printf " 0x%x", $_s_status
end
2011-03-10 16:45:12 +03:00
end
2011-03-14 21:05:56 +03:00
#
# __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
2011-03-10 16:45:12 +03:00
define lv_status
2011-03-12 01:25:36 +03:00
# Use __lv because we don't want to overwrite higher functions
set $__lv = (struct logical_volume *)$arg0
2011-03-10 16:45:12 +03:00
2011-03-14 21:05:56 +03:00
if ($argc == 2)
__print_indent $arg1
end
2011-03-12 01:25:36 +03:00
printf "%s->status:", $__lv->name
__status $__lv
2011-03-10 16:45:12 +03:00
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
2011-03-14 21:05:56 +03:00
if ($argc == 2)
__print_indent $arg1 1
end
2011-03-12 01:16:38 +03:00
printf "[ (%s) seg->status:", $_seg->lv->name
2011-03-10 16:45:12 +03:00
__status $_seg
2011-03-12 01:16:38 +03:00
printf " ]\n"
2011-03-10 16:45:12 +03:00
end
document seg_status
Display the flags that are set on an lv_segment.
2011-03-14 21:05:56 +03:00
Usage: seg_status <(struct lv_segment *)>
2011-03-10 16:45:12 +03:00
end
2011-03-12 01:16:38 +03:00
#
# 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
2011-03-10 16:45:12 +03:00
set $_i = 0
2011-03-12 01:16:38 +03:00
while (($_s != $_seg_list_head) && ($_i < 100))
set $_seg_list = (struct seg_list *)$_s
set $_seg = (struct lv_segment *)$_seg_list->seg
2011-03-10 16:45:12 +03:00
2011-03-12 01:16:38 +03:00
set $_i++
set $_s = $_s->n
2011-03-10 16:45:12 +03:00
end
2011-03-12 01:16:38 +03:00
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
2011-03-10 16:45:12 +03:00
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
2011-03-12 01:16:38 +03:00
set $_i++
2011-03-10 16:45:12 +03:00
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
2011-03-12 01:16:38 +03:00
#
# __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)
2011-09-02 01:01:12 +04:00
#
2011-03-12 01:16:38 +03:00
# or
2011-09-02 01:01:12 +04:00
#
2011-03-12 01:16:38 +03:00
# __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
2011-03-14 21:05:56 +03:00
# printf "\n"
lv_status $_lv $indent
2011-03-12 01:16:38 +03:00
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)
2011-03-29 16:53:13 +04:00
__print_indent $indent 1
2011-03-12 01:16:38 +03:00
printf "[ No segments for %s ]\n", $_lv->name
end
2011-03-29 16:53:13 +04:00
__get_only_segment_using_this_lv $_seg $_lv
if ($_seg && $indent)
set $indent--
__lv_status_r $_lv $_seg
end
2011-03-12 01:16:38 +03:00
else
set $_seg = (struct lv_segment *)$_s
set $_type = 0x0
if (!$_area_index)
2011-03-14 21:05:56 +03:00
seg_status $_seg $indent
2011-03-12 01:16:38 +03:00
end
__seg_type $_type $_seg $_area_index
if ($_type == AREA_LV)
2011-03-14 21:05:56 +03:00
set $indent++
2011-07-01 20:15:25 +04:00
__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
2011-03-12 01:16:38 +03:00
__seg_item $_lv $_seg $_area_index
__lv_status_r $_lv
else
2011-03-12 01:25:36 +03:00
if ($_seg->log_lv)
2011-03-14 21:05:56 +03:00
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--
2011-03-12 01:25:36 +03:00
end
2011-03-12 01:16:38 +03:00
__get_only_segment_using_this_lv $_seg $_lv
if ($_seg)
2011-03-14 21:05:56 +03:00
set $indent--
2011-03-12 01:16:38 +03:00
__lv_status_r $_lv $_seg
end
end
end
end
define lv_status_r
2011-03-14 21:05:56 +03:00
set $indent = 0
2011-03-12 01:16:38 +03:00
__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
2011-03-10 16:45:12 +03:00
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