SUMMARY: Doh! Rebuild Partition Table

From: Scott Ruffner (
Date: Thu Dec 28 2000 - 16:33:14 CST

Well, I've gotten the partitions back. Thanks to all who replied - there
were two replies which addressed the problem. The first, and the one
which I have included below, gave me the hint I needed: the "octal dump"

The problem was that I had whacked the disk's label by putting it on an
x86 box. However, the partitions were untouched and the data never messed
with (when I relocated the partitions, they fsck'ed as clean). I just
needed to find the starting point of each slice. There is a "magic
number" included in each superblock, so you can search for that. The
tricky part is how to do that - I was fortunate to have Michael Maciolek's
suggestion so that I wasn't hacking out some quickie tool to do this for
me: Here's his answer, amended to help other knuckleheads (like me) avoid
obvious mistakes:

On Wed, 27 Dec 2000, Michael Maciolek wrote:
> Date: Wed, 27 Dec 2000 18:20:41 -0500 (EST)
> From: Michael Maciolek <>
> To: Scott Ruffner <>
> Subject: Re: Doh! Rebuild Partition Table
> Assuming the contents of the partitions are still be intact, and all
> you need to do is rebuild your partition table, this method should
> work for you.
> For the sake of this example, I'm going to assume your disk is c0t3d0
> and it contains five partitions: root, swap, /usr, /var, /opt. Make
> appropriate substitutions for your physical disk and partition names.
> I'm taking a few things for granted: that you don't have any 'holes'
> in your partition map; all your partitions begin and end on cylinder
> boundaries; you have the correct disk geometry; your filesystems are
> all standard UFS (no Veritas or foreign filesystem types). If any of
> these assumptions are wrong in your case, you may still be able to
> use some of the techniques described here, or adapt them to your own
> circumstances.
> Each filesystem contains information about its own size in its header -
> the only problem is 'swap', which is a raw partition and has no
> filesystem (therefore, no helpful header to tell you how big it is.)
> You've already got your root filesystem, but this is a good sanity
> check and you'll need to repeat this procedure on the others, so think
> of this as a 'dry run.'
> Do an 'fstyp -v /dev/rdsk/c0t3d0s2 | head -12' and look at the 12th
> line, which tells you how many cylinders in the first filesystem. Use
> this to relabel your root partition. (run 'format', modify the
> partition table, save it.) While you're in there, set slice 3 to to
> start just after the end of root; make it extend to the end of the
> disk. You'll truncate it later, but for the moment, it gives you a
> 'handle' on everything on the disk that's not part of the root
> partition.
> Now, run an fsck on the root filesystem, just to be sure it's OK.
> Mount it on a temporary mount point so you can peek at your vfstab,
> which will tell you the names and slice numbers for all your other
> partitions, e.g. root on slice 0, swap on slice 1, var on slice 3, usr
> on slice 4, or whatever you have on your system.

I already had my root partition back, because it is conveniently located
at the beginning of the disk, so the superblock is easy to find. I made
an arbitrarily large partition, and then used fstyp to find the size of
the partition (in cylinders). I fixed the size, and then re-mounted, and
looked in /var/sadm/system/logs/install_log to see how big the other
filesystems were - this was helpful for sanity checking.

> The 'swap' partition is the most difficult part of this exercise.
> Assuming the rest of your partitions are contiguous, you'll be able to
> compute the start of one if you know the end of its predecessor, but
> 'swap' is tricky because it doesn't have any kind of built-in marker to
> tell you how big it is. Your goal is to find the end of the swap
> partition (and the start of the next real filesystem after it.) Unless
> you're a very good guesser, you don't want to poke around
> want a methodical approach.
> Every filesystem has a filesystem header, and one constant element in
> that header is a 'magic number', hexadecimal 0x011954, which occurs
> 9564 bytes past the beginning of the filesystem, i.e. it's stored in
> bytes 9564-9567. This gives you something to look for that will tell
> you where the next filesystem header might be.
> All you have to do is look for occurrences of the magic number, which
> will either be:
> (a) a random natural occurrence of that bit pattern,
> (b) an actual filesystem header [SUCCESS],
> or (c) a replica of the filesystem header which occurs
> 020000 bytes (octal) after the real header.
> Use od to dump the contents of slice 3 (assuming you configured slice
> 3 to extend from the end of your root partition all the way to the end
> of the disk; you *did* do that before, didn't you?). Grep for the
> magic number:
> od -x /dev/rdsk/c0t3d0s3 | grep '0001 1954$'
> This will look for the 'magic number' (which happens to occur at the
> end of a line of od's output). There may be other random occurrences
> of data which are identical to the magic number, but not many at the
> end of an 'od' line (16-byte boundary) and fewer still that occur at
> some address and again 020000 bytes beyond that address. Still, you
> may get some false-positives, so be prepared to do some trial-and-
> error work. Let the 'od' run for a while - a big swap area can take
> a long time (as much as an hour?) to dump and search. Be patient.

This actually took a good bit longer - I let it run overnight, and on a
4.3GB slice, it still hadn't finished, although it had gone far enough to
get the relevant lines.

> Eventually, you'll see a line that looks something like this, and it
> should be followed closely by another line that's identical except for
> the left-most number, which will be 020000 greater. Example:
> 276522520 0000 0008 0000 035c 0000 0560 0001 1954
> 276542520 0000 0008 0000 035c 0000 0560 0001 1954
> ---- ----
> Check: 276522520 + 020000 = 276542520 (octal)
> Reviewing...the first number is an octal address - it's the location
> of this particular 16-byte string of numbers. Now for the magic. If
> you subtract octal 022520 from the first number, you get the start of
> that partition, i.e. the size of your swap space.
> In this case, you would compute 276522520 - 22520 (octal) and get
> 276500000. Dividing by 512 is easy - drop the last 3 zeroes (9 bits)
> so now you know your next partition is at sector 276500 (octal).
> You can use the 'dc' calculator to convert octal to decimal. Tell it
> to use an input-base of 8, and leave the output-base set to 10; just
> enter the number, print and quit:
> # echo 8 i 276500 p q | dc
> 97600
> This tells us our next UFS partition starts at sector 97600. (In this
> case, my disk geometry is 80 sectors/track, 10 heads/cylinder, so we
> can compute the starting cylinder by dividing the sector number by the
> size of a cylinder (sectors-per-track * heads):
> 97600 / (80 * 10) = 122.
> Now go into 'format' and adjust slice 1 (swap) to have the size you
> just computed, and set slice 3 (/usr) to start where 1 ends.

Ok, this had me stumped for a while - foolishly I made the rash assumption
that the cylinder count I just got was the absolute cylinder number for
the start of the partition - CAUTION - this is the SIZE of the swap
partition in cylinders! The value you calculate is offset by the size of
the preceding partition. I know Mark's instructions seem clear in
hindsight, but this had me stumped for a bit.

> The rest of the disk is easy; you repeat the technique described for
> the 'root' filesystem to figure the size of each other partition, use
> 'fstyp' and walk your way through to the end.
> Give everything a full 'fsck' as you work your way through, and use
> read-only mounts to verify the readability of each partition.
> Michael Maciolek
> Senior Network/Systems Engineer 781-273-3081 voice/fax
> Exodus Professional Services
> ---------------------------------------------------------------------

Yes, the rest was easy, especially since I had gotten values for all the
rest of my partitions, and the spacing matched the sized recorded in the
install_log. However, it would still be quite effective even if I hadn't
had the install_log information.

A second approach was suggested by:

Michael P. Sullivan                                  
Distributed Computing Systems, LLC
Cell: 516-429-2080 
    * UNIX Systems and Database Consulting, Architecture and Management *
"The two most common elements in the universe are hydrogen... and
                                   Harlan Ellison

Michael suggested using format and fstyp in a script stepping through the disk cylinder by cylinder until cylinders are found which have the filesystem header. I suspect this would work just fine, since fstyp was the hint I had that I was in the wrong place, and how I knew I had finally found the right cylinder. This would be relatively simple to do - I didn't take this approach, since I initially expected the octal dump to be faster - this is probably not a valid assumption, since the octal dump checks every byte, and the script approach just checks the cylinder boundaries (where things are located).

The first approach seems more elegant to me, and you need only run the octal dump long enough to get to the first boundary. Then fstyp gives you the size of each partition in cylinders, so the process may not take too long.

Nothing like a Homer Simpson learning moment.

Scott ================================================================== Scott Ruffner Computer Systems Senior Engineer Computer Science Department University of Virginia (804)982-2219

_______________________________________________ sunmanagers mailing list

This archive was generated by hypermail 2.1.2 : Fri Sep 28 2001 - 23:14:25 CDT