Resizing Partitions
This is a HOWTO on resizing diskslices/partitons with FreeBSD.
NOTE: this has the potential to break things very badly, be sure you have backups of anything you do this on. Also make sure that you specify the right disk, most of these tools will assume the primary hard drive of your machine, and you might not want to be messing with that (unless you know what you're doing).
The Situation
I have a 245 meg disk image I want to put on my 1G CompactFlash card. I don't want to waste 75% of the space so I need to resize the slices and the filesystem.
Once the image is dded to the flash card the setup is as follows:
- /dev/ad4 - entire device
- /dev/ad4a - the first slice (unused)
- /dev/ad4c - the 'entire' /dev/ad4 disk
- /dev/ad4s1 - the first slice of ad4c (same as ad4cs1)
- /dev/ad4s1a - the first slice of ad4s1 (the actual freebsd filesystem)
- /dev/ad4s1c - the 'entire' /dev/ad4s1 slice
the 'c' slices are always, by convention, the entire slice. So, you can see we only have one real 'slice' on the disk. Now we need to start changing the slice sizes...
Changing the slice sizes with disklabel(8) and fdisk
Disklabeling the root of the drive
(do we *really* need to disklabel this?) Notice that to make /dev/ad4s1 bigger, we'll need to resize /dev/ad4 first, to make it the proper size, we use disklabel for this:
$disklabel -e /dev/ad4
# /dev/ad4: 8 partitions: # size offset fstype [fsize bsize bps/cpg] a: 501744 16 unused 0 0 c: 501760 0 unused 0 0 # "raw" part, don't edit
The units of size here are 'sectors' which, by default, are 512 bytes, so if we do the math ((501760*512)/1024)/1024 we find the disk is 245 megs.
Now, we need to define a NEW size for this stuff, and since HD manufactures want to rip you off, they assume that a kilobyte has 1000 bytes (not 1024) and a megabyte has 1,000,000 bytes and so on. This makes storage smaller than it seems (256 meg card is really ~245) and it makes some fun math for us. My CF card is a gig so... (1000*1000*1000)/512 = 1,953,125 sectors or ~953 megs. So, we edit the disklabel to reflect this:
# /dev/ad4: 8 partitions: # size offset fstype [fsize bsize bps/cpg] a: 1953109 16 unused 0 0 c: 1953125 0 unused 0 0 # "raw" part, don't edit
Note the 16 sector offset has been preserved on the 'a' slice.
Resizing the drive with fdisk
Now, we need to actually modify the partition table to reflect this change:
fdisk -u /dev/ad4
Tell it you want to change the first partition, accept the default until it asks you about the size. Then input the size of the 'a' slice minus 32 (because of the "start" value fdisk reports) 1953077
Keep accepting the defaults until it asks you if you want to write the new partition table, say yes here.
Disklabling the first slice
Now, we need to disklabel the first slice too:
$disklabel -e /dev/ad4s1
# /dev/ad4s1: 8 partitions: # size offset fstype [fsize bsize bps/cpg] a: 501712 16 4.2BSD 2048 16384 31360 c: 501728 0 unused 0 0 # "raw" part, don't edit
So, there's the 'real' filesystem that we're ultimately trying to resize. So we just edit the disklabel again, using the sector size of the 'a' slice we just resized above (1953077)
# /dev/ad4s1: 8 partitions: # size offset fstype [fsize bsize bps/cpg] a: 1953061 16 4.2BSD 2048 16384 31360 c: 1953077 0 unused 0 0 # "raw" part, don't edit
Using growfs(8) to increase the filesystem size
Okay, now we're ready to do the final step:
growfs /dev/ad4s1a
Yo'll be asked if your data was backed up, type the appropiate response (the 'Yes' is case-sensitive). If you type yes it will do the resize and it all should be good... If it's not, then it's time to dig out that backup...
Recommended Reading
man disklabel man fdisk man growfs