How to Shrink a mirrored ZFS rpool

The other day I wanted to shrink the size of my OpenSolaris ZFS root pool.The root pool is generally pretty small, and when possible I try to keep real data out of the root pool. In the case of target system, it has 4 disks and I have separate mirrored data pool. So I've got nearly 1 TB on two disks (root pool mirroring) just sitting idle, which could be used for something like say installing other O/Ses on bare iron (yeah, sometimes I still like to do that).

Anyways, maybe I am pathetic at web searches but after a few minutes of searching I could not find an answer. So I thought about it for a while and came up with a plausible way to do it, without the need of a live CD or usb stick or anything (did I mention I'm lazy, and didn't really feel like burning a CD)

The method I came up with is this, I'll follow up a summary with more detailed steps. Note that although this procedure is to shrink a mirrored root pool, you can probably use the same method on a non-mirrored pool, as long as you have a spare hard drive or partition somewhere.

  1. Break the root pool mirror
  2. Create a temporary root pool, resized appropriately, and boot to it
  3. Destroy the real root pool, resize it, and boot back to it
  4. Destroy the temporary root pool.
  5. Reattach the mirror to the resized root pool

It sounds pretty simple, but there are a lot of steps involved. So here are the details.

In my case, I have a mirrored root pool made of the two devices

c2t0d0s0
c2t1d0s0

Break the root pool mirror.

zpool detach rpool c2t1d0s0
Create a temporary root pool, resized appropriately, and boot to it.

First, you need to resize the Solaris fdisk partition, I usually just use the fdisk option in format, the general outline for this procedure is the following:

  1. Run format
  2. Select the disk you just detached (c2t1d0)
  3. Start fdisk
  4. Delete the Solaris partition
  5. Create a new Solaris partition with a smaller size (say 50% of the disk, for example)
  6. Save and exit fdisk
  7. Start the partition tool
  8. Adjust the disk slices so that s0 contains the entire disk
  9. Label the disk
  10. Exit format.
Now, create a temporary root pool, I'll call it tpool
zpool create -f tpool c2t1d0s0

Copy the data from the root pool to the temporary pool with ZFS send & receive

zfs snapshot -r rpool@shrink
zfs send -vR rpool@shrink | zfs receive -vfd tpool

Now, before you can boot to the temporary pool, there's a couple setting you need to change so its identified as tpool properly.

First, change the boot sign of the temporary pool

rm /tpool/boot/grub/bootsign/pool_rpool
touch /tpool/boot/grub/bootsign/pool_tpool

Now, set the bootfs option on the pool

zfs set bootfs=tpool/ROOT/opensolaris-5 tpool

And finally, make sure to install GRUB on the disk

cd /boot/GRUB
/sbin/installgrub stage1 stage2 /dev/rdsk/c2t1d0s0 

Now, reboot. Make sure do do a full PROM boot instead of the newer Quick boot

reboot -p

At grub, edit the boot entry - by typing 'e' - for the BE you want to boot into, change references from rpool to tpool. In my case the boot commands ended up looking like

findroot (pool_tpool,0,a)
bootfs tpool/ROOT/opensolaris-5
kernel$ /platform/i86pc/kernel/$ISADIR/unix -B $ZFS-BOOTFS,console=text
module$ /platform/i86pc/$ISADIR/boot_archive

Then type 'b' to boot. When the system has completed booting, you should be booted off the temporary pool. You can verify this by

df -h /

Destroy the real root pool, resize it, and boot back to it.

First off, before you can destroy the root pool, the system might have some active references into the pool, like for swap and dump, and maybe some datasets like /export, you need to deactivate these before destroying the rpool.

swap -d /dev/zvol/dsk/rpool/swap
dumpadm -d /dev/zvol/dsk/tpool/dump
zfs set mountpoint=none rpool/export
zfs set mountpoint=none rpool/export/home

Now you should be able to destroy the original rpool

zpool destroy rpool

If you get "busy" errors, try destroying the datasets which should identify why its busy, and deactivate them.

zfs destroy -r rpool
zpool destroy rpool

With the original root pool destroyed, you can now repartition the device in the original pool to the new size.

  1. Run format
  2. Select the disk you just detached (c2t2d0)
  3. Start fdisk
  4. Delete the Solaris partition
  5. Create a new Solaris partition with a smaller size (say 50% of the disk, for example)
  6. Save and exit fdisk
  7. Start the partition tool
  8. Adjust the disk slices so that s0 contains the entire disk
  9. Label the disk
  10. Exit format.

With the Solaris partition resized, recreate rpool

zfs create rpool c2t2d0s0

And reverse the process of migrating to the temporary pool by moving the data back to the new root pool

zfs send -vR tpool@shrink | zfs receive -vfd rpool

Once again, set the bootfs option on the pool

zfs set bootfs=rpool/ROOT/opensolaris-5 rpool

Reinstall GRUB

cd /boot/grub
/sbin/installgrub stage1 stage2 /dev/rdsk/c2t2d0s0 

And do a full PROM boot

reboot -p

Destroy the temporary root pool & remirror root pool.

At this point the rpool is resized smaller, but not mirrored. To mirror again destroy the temporary pool

zpool destroy tpool

Attach tpool device to the rpool

zpool attach rpool c2t2d0s0 c2t1d0s0

And finally install grub once again for good measure

/sbin/installgrub stage1 stage2 /dev/rdsk/c2t1d0s0

Voila.

Comments:

is there any reason that the boot sign has to be removed first instead of just renamed (with mv)? Is there something linked somehow to the inode?

Posted by derek on September 08, 2010 at 04:50 AM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

mock

Search

Top Tags
Categories
Archives
« March 2015
SunMonTueWedThuFriSat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
    
       
Today
Bookmarks
Blogroll

No bookmarks in folder