Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 22 Jan 2003 23:26:38 +0100 (MET)
From:      j@uriah.heep.sax.de (Joerg Wunsch)
To:        freebsd-current@freebsd.org
Subject:   Re: vinum root [Was: I want a sysctl kern.allow_shooting_into_my_foot!]
Message-ID:  <200301222226.h0MMQcir091526@uriah.heep.sax.de>
References:  <20030122121739.GA758@cicely8.cicely.de> <25074.1043238359@critter.freebsd.dk> <20030122124403.GB758@cicely8.cicely.de> <20030122135404.B70341@uriah.heep.sax.de> <20030122130644.GA52953@tara.freenix.org> <200301221959.h0MJxIiW088157@uriah.heep.sax.de>

next in thread | previous in thread | raw e-mail | index | archive | help
--=-=-=__JEFYY++WJ2yEhnYf+wtH98VHF__=-=-=

j@uriah.heep.sax.de (Joerg Wunsch) wrote:

> The biggest problem of all this is, of course, the bootstrapping
> step.  The bootstrap still needs an `a' partition in order to read
> at least /boot/loader etc. from.  The solution is to produce a faked
> overlay `a' partition that sits at exactly the point where the
> corresponding vinum subdisk of the root device is located.

Here's the first cut of a script that would set this up.
-- 
cheers, J"org               .-.-.   --... ...--   -.. .  DL8DTL

http://www.sax.de/~joerg/                        NIC: JW11-RIPE
Never trust an operating system you don't have sources for. ;-)
--=-=-=__JEFYY++WJ2yEhnYf+wtH98VHF__=-=-=
Content-Type: text/plain; charset=iso-8859-1
Content-Disposition: attachment; filename="vinum-a-part.pl"

#!/usr/bin/perl -w
#
# Copyright (c) 2003 Joerg Wunsch
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# $FreeBSD$
#

# Create overlay partition `a' for all devices that are part of the
# named vinum root volume.

$ENV{PATH} = "/sbin:/bin:/usr/sbin:/usr/bin";
if (defined($ENV{TMPDIR})) {
    $tmpdir = $ENV{TMPDIR};
} else {
    $tmpdir = "/tmp";
}
$tempname = "${tmpdir}/vinum-a-part.$$";

die "usage: $0 <rootvolname>\n" unless $#ARGV == 0;

$rootvol = $ARGV[0];
$nsds = $nlines = 0;

# First, find out the components of our ${rootvol}.  Make sure all our
# plexes have only one subdisks, and are of type "concat".  Remember
# the subdisks found for step #2.

open(V, "vinum l -r $rootvol|") || die "Cannot start vinum(8)\n";
while (<V>) {
    chomp;
    if (/^P/) {
	/^P\s+(\S+)\s+([CSR5]+)\s+.*Subdisks:\s+(\d+)/;
	$pname = $1;
	$org = $2;
	$nsd = $3;
	$nsd > 1 && die "Plex $pname has more than one subdisk.\n";
	$org ne "C" && die "Plex $pname is not a concat plex.\n";
    } elsif (/^S/) {
	/^S\s+(\S+)\s/;
	$sdnames[$nsds++] = $1;
    }
    $nlines++;
}
close(V);
die "Volume $rootvol not found.\n" unless $nlines > 0;
die "Volume $rootvol has no subdisks.\n" unless $nsds > 0;

# Now, for each of the subdisks found, determine size and offset
# inside the vinum drive.  Then figure out the disk device (and
# perhaps slice) it belongs to.  Analyze the label of that device, to
# see whether the vinum partition is really there.

# If there is already an `a' partition, analyze it.  If it already
# matches our expectations, just proceed.  If it is inside the vinum
# partition but has wrong parameters, leave it to the operator for a
# manual fix, and proceed.  If it is outside vinum, try moving it into
# one of the partition slots `d' through `h'.  Failing this, proceed
# to the next subdisk.

# If successful, create a new label with our new `a' partition.

foreach $sd (@sdnames) {
    open(V, "vinum l -v $sd 2>/dev/null |") || die "Cannot start vinum(8)\n";
    $size = $offset = 0;
    $devname = $dev = $part = "";
    while (<V>) {
	if (/Size:\s+(\d+)\s+bytes/) {
	    $size = $1;
	} elsif (/Drive\s+\S+\s+[(](\S+)[)].*offset\s+(\d+)/) {
	    $devname = $1;
	    $offset = $2;
	}
    }
    close(V);
    die "Cannot find parameters for sd $sd.\n" unless
	$size > 0 && $offset > 0 && $devname ne "";
    $devname =~ s,^/dev/,,;
    $devname =~ m|^([a-z]+\d+(s\d+)?)([a-h])$|;
    $dev = $1;
    $part = $3;
    die "Cannot figure out device and partition from $devname.\n"
	unless $dev ne "" && $part ne "";
    $size /= 512;
    $offset /= 512;

    system("disklabel $dev > $tempname") &&
	die "Cannot run disklabel(8)\n";

    %parts = ();
    $blurb = "";
    open(L, $tempname) || die "Cannot read temp file $tempname\n";
    while (<L>) {
	if (/^\s+([a-h]):/) {
	    chomp;
	    $parts{$1} = $_;
	} else {
	    $blurb .= $_;
	}
    }
    close(L);
    unlink $tempname;

    die "Vinum partition ${part} not found on ${dev}\n"
	unless defined($parts{$part});
    $parts{$part} =~ /:\s+(\d+)\s+(\d+)\s+(\S+)/;
    $vinsize = $1;
    $vinoff = $2;
    die "Vinum partition ${part} on ${dev} not type `vinum'\n"
	unless $3 eq "vinum";

    if (defined($parts{a})) {
	print "${dev}: existing `a' partition found, ";
	$parts{a} =~ /:\s+(\d+)\s+(\d+)/;
	$psize = $1;
	$poff = $2;
	if ($poff >= $vinoff && $poff + $psize <= $vinoff + $vinsize) {
	    # `a' partition overlaps vinum partition
	    if ($poff == $vinoff + $offset &&
		$psize == $size) {
		print "already correctly set up.\n";
		next;
	    }
	    print "is inside the vinum partition but wrong.\n";
	    printf "Size/offset %d/%d, should be %d/%d,manual fix required.\n",
	    $psize, $poff, $size, $vinoff + $offset;
	    next;
	}
	for ($c = 'd'; $c <= 'h'; $c++) {
	    if (!defined($parts{$c})) {
		print "will be moved to partition `$c'\n";
		$parts{a} =~ s/^\s+a:/ $c:/;
		$parts{$c} = $parts{a};
		$parts{a} = undef;
		last;
	    }
	}
	if ($c > 'h') {
	    print "cannot be moved, no free slot.\n";
	    next;
	}
    }
    $parts{a} = " a: ${size} " . ($vinoff + $offset) . " 4.2BSD 2048 16384 0";
    open(L, ">${tempname}") || die "Cannot create ${tempname}.\n";
    print L $blurb;
    foreach $p (sort(keys(%parts))) {
	print L $parts{$p} . "\n";
    }
    close(L);
    system("disklabel -R $dev ${tempname}") &&
	die "disklabel $dev failed ($?)\n";
    unlink $tempname;
    print "${dev}: partition `a' successfully created.\n";
}
--=-=-=__JEFYY++WJ2yEhnYf+wtH98VHF__=-=-=--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200301222226.h0MMQcir091526>