![]() |
|
| Daemon News Ezine | BSD News | BSD Mall | BSD Support Forum | BSD Advocacy | BSD Updates |
Growing FreeBSD's filesystems with growfs(8)Marc Fonvieille <fonvi@easynet.fr>IntroductionDuring installation it is important to size filesystems so that we won't be forced to resize them later. However, it often appears with time that one of the partitions is too small. Until today it was impossible to expand the size of a filesystem. FreeBSD 4.4-RELEASE comes with a new utility: growfs(8). This program permits us to enlarge, in certains conditions, the size of an existing ufs filesystem.
Preparing the fightBefore detailing the operations through one example, there are many things to know:
I did my experiments on a machine running 4.4-PRERELEASE with a 6.4G hard drive. Here is the partition table of this hard drive: # fdisk -s /dev/ad0: 784 cyl 255 hd 63 sec Part Start Size Type Flags 1: 63 2088387 0x06 0x00 2: 2088450 2859570 0xa5 0x80 3: 4948020 7646940 0xa5 0x00 As we can see, first slice is a msdos filesystem (type 0x06) and the others are FreeBSD filesystem (type 0xa5). The 4.4-PRERELEASE is on the second one; on the last, there's an old 3.5-STABLE system. I don't need the latter, so I will remove it and use the free space to enlarge the second slice. If I call fdisk(8) with no arguments, it prints the following:
******* Working on device /dev/ad0 *******
parameters extracted from in-core disklabel are:
cylinders=784 heads=255 sectors/track=63 (16065 blks/cyl)
parameters to be used for BIOS calculations are:
cylinders=784 heads=255 sectors/track=63 (16065 blks/cyl)
Media sector size is 512
Warning: BIOS sector numbering starts with sector 1
Information from DOS bootblock is:
The data for partition 1 is:
sysid 6,(Primary 'big' DOS (> 32MB))
start 63, size 2088387 (1019 Meg), flag 0
beg: cyl 0/ head 1/ sector 1;
end: cyl 129/ head 254/ sector 63
The data for partition 2 is:
sysid 165,(FreeBSD/NetBSD/386BSD)
start 2088450, size 2859570 (1396 Meg), flag 80 (active)
beg: cyl 130/ head 0/ sector 1;
end: cyl 307/ head 254/ sector 63
The data for partition 3 is:
sysid 165,(FreeBSD/NetBSD/386BSD)
start 4948020, size 7646940 (3733 Meg), flag 0
beg: cyl 308/ head 0/ sector 1;
end: cyl 783/ head 254/ sector 63
The data for partition 4 is:
<UNUSED>
The first thing to do is remove that third slice. I booted on the 4.4-PRERELEASE system and here's how it went:
# fdisk -u
******* Working on device /dev/ad0 *******
parameters extracted from in-core disklabel are:
cylinders=784 heads=255 sectors/track=63 (16065 blks/cyl)
parameters to be used for BIOS calculations are:
cylinders=784 heads=255 sectors/track=63 (16065 blks/cyl)
Do you want to change our idea of what BIOS thinks ? [n] n
Media sector size is 512
Warning: BIOS sector numbering starts with sector 1
Information from DOS bootblock is:
The data for partition 1 is:
sysid 6,(Primary 'big' DOS (> 32MB))
start 63, size 2088387 (1019 Meg), flag 0
beg: cyl 0/ head 1/ sector 1;
end: cyl 129/ head 254/ sector 63
Do you want to change it? [n] n
The data for partition 2 is:
sysid 165,(FreeBSD/NetBSD/386BSD)
start 2088450, size 2859570 (1396 Meg), flag 80 (active)
beg: cyl 130/ head 0/ sector 1;
end: cyl 307/ head 254/ sector 63
Do you want to change it? [n] n
The data for partition 3 is:
sysid 165,(FreeBSD/NetBSD/386BSD)
start 4948020, size 7646940 (3733 Meg), flag 0
beg: cyl 308/ head 0/ sector 1;
end: cyl 783/ head 254/ sector 63
Do you want to change it? [n] y
Supply a decimal value for "sysid (165=FreeBSD)" [165] 0
Supply a decimal value for "start" [4948020] 0
Supply a decimal value for "size" [7646940] 0
Explicitly specify beg/end address ? [n] y
Supply a decimal value for "beginning cylinder" [0] 0
Supply a decimal value for "beginning head" [0] 0
Supply a decimal value for "beginning sector" [0] 0
Supply a decimal value for "ending cylinder" [0] 0
Supply a decimal value for "ending head" [0] 0
Supply a decimal value for "ending sector" [0] 0
<UNUSED>
Are we happy with this entry? [n] y
The data for partition 4 is:
<UNUSED>
Do you want to change it? [n] n
Do you want to change the active partition? [n] n
We haven't changed the partition table yet. This is your last chance.
parameters extracted from in-core disklabel are:
cylinders=784 heads=255 sectors/track=63 (16065 blks/cyl)
parameters to be used for BIOS calculations are:
cylinders=784 heads=255 sectors/track=63 (16065 blks/cyl)
Information from DOS bootblock is:
1: sysid 6,(Primary 'big' DOS (> 32MB))
start 63, size 2088387 (1019 Meg), flag 0
beg: cyl 0/ head 1/ sector 1;
end: cyl 129/ head 254/ sector 63
2: sysid 165,(FreeBSD/NetBSD/386BSD)
start 2088450, size 2859570 (1396 Meg), flag 80 (active)
beg: cyl 130/ head 0/ sector 1;
end: cyl 307/ head 254/ sector 63
3: <UNUSED>
4: <UNUSED>
Should we write new partition table? [n] y
#
Specifying a partition type of zero is equal to clear the partition and mark it as unused, but we must specify 0 values for all parameters concerning that partition (start, size...). Don't forget that what is called "partition" in fdisk, is known as "slice" in FreeBSD. Now fdisk -s prints: # fdisk -s /dev/ad0: 784 cyl 255 hd 63 sec Part Start Size Type Flags 1: 63 2088387 0x06 0x00 2: 2088450 2859570 0xa5 0x80 After that, I performed the command fsck to check the filesystem. Expanding the /usr partitionHere is the current size of partitions: # df -h Filesystem Size Used Avail Capacity Mounted on /dev/ad0s2a 39M 31M 4.4M 88% / /dev/ad0s2f 1.1G 810M 208M 80% /usr /dev/ad0s2e 145M 308K 133M 0% /var procfs 4.0K 4.0K 0B 100% /proc The /usr is too small for me; I need something like 2.5G Before using growfs(8), the slice must be labeled as a bigger size with disklabel(8) and fdisk(8). Have a look at the current label of /dev/ad0s2: # /dev/ad0s2c: type: ESDI disk: ad0s2 label: flags: bytes/sector: 512 sectors/track: 63 tracks/cylinder: 255 sectors/cylinder: 16065 cylinders: 178 sectors/unit: 2859570 rpm: 3600 interleave: 1 trackskew: 0 cylinderskew: 0 headswitch: 0 # milliseconds track-to-track seek: 0 # milliseconds drivedata: 0 8 partitions: # size offset fstype [fsize bsize bps/cpg] a: 81920 0 4.2BSD 1024 8192 16 # (Cyl. 0 - 5*) b: 131072 81920 swap # (Cyl. 5*- 13*) c: 2859570 0 unused 0 0 # (Cyl. 0 - 177) e: 307200 212992 4.2BSD 1024 8192 16 # (Cyl. 13*- 32*) f: 2339378 520192 4.2BSD 1024 8192 16 # (Cyl. 32*- 177*) /usr is 2339378 sectors large. We have a 512-byte sector (look at bytes/sector parameter), and /usr in (human-readable) size is: (2339378/2)/1024 Megabytes, or 1142.27MB (same as given by the df -h command above, 1.1G). I had said that I wanted a 2.5G large partition for /usr. Let's do some calculations: 2.5G is 2.5*1024*1024K with 512-bytes sector it gives 2.5*1024*1024*2= 5242880 sectors We already use 2339378 sectors for /usr, we have to add 5242880-2339378= 2903502 sectors to /usr and so to the whole slice. The whole slice size will be: 2859570+2903502= 5763072 sectors There are 16065 sectors/cylinder, so 5763072 sectors require about 359 cylinders. As summary, we will have to change these parameters in the label:
If I try to edit the label, disklabel(8) refuses these values; the slice is already full. I have to use fdisk(8) to enlarge the slice before labeling it. The delicate work begins here, so to avoid problems I log in as single user then launch fdisk(8):
# fdisk -u
******* Working on device /dev/ad0 *******
parameters extracted from in-core disklabel are:
cylinders=784 heads=255 sectors/track=63 (16065 blks/cyl)
parameters to be used for BIOS calculations are:
cylinders=784 heads=255 sectors/track=63 (16065 blks/cyl)
Do you want to change our idea of what BIOS thinks ? [n] n
Media sector size is 512
Warning: BIOS sector numbering starts with sector 1
Information from DOS bootblock is:
The data for partition 1 is:
sysid 6,(Primary 'big' DOS (> 32MB))
start 63, size 2088387 (1019 Meg), flag 0
beg: cyl 0/ head 1/ sector 1;
end: cyl 129/ head 254/ sector 63
Do you want to change it? [n] n
The data for partition 2 is:
sysid 165,(FreeBSD/NetBSD/386BSD)
start 2088450, size 2859570 (1396 Meg), flag 80 (active)
beg: cyl 130/ head 0/ sector 1;
end: cyl 307/ head 254/ sector 63
Do you want to change it? [n] y
Supply a decimal value for "sysid (165=FreeBSD)" [165] 165
Supply a decimal value for "start" [2088450] 2088450
Supply a decimal value for "size" [2859570] 5763072
Explicitly specify beg/end address ? [n] y
Supply a decimal value for "beginning cylinder" [130] 130
Supply a decimal value for "beginning head" [0] 0
Supply a decimal value for "beginning sector" [1] 1
Supply a decimal value for "ending cylinder" [307] 489
Supply a decimal value for "ending head" [254] 254
Supply a decimal value for "ending sector" [63] 63
Are we happy with this entry? [n] y
The data for partition 3 is:
<UNUSED>
Do you want to change it? [n] n
The data for partition 4 is:
<UNUSED>
Do you want to change it? [n] n
Do you want to change the active partition? [n] n
We haven't changed the partition table yet. This is your last chance.
parameters extracted from in-core disklabel are:
cylinders=784 heads=255 sectors/track=63 (16065 blks/cyl)
parameters to be used for BIOS calculations are:
cylinders=784 heads=255 sectors/track=63 (16065 blks/cyl)
Information from DOS bootblock is:
1: sysid 6,(Primary 'big' DOS (> 32MB))
start 63, size 2088387 (1019 Meg), flag 0
beg: cyl 0/ head 1/ sector 1;
end: cyl 129/ head 254/ sector 63
2: sysid 165,(FreeBSD/NetBSD/386BSD)
start 2088450, size 5763072 (2814 Meg), flag 80 (active)
beg: cyl 130/ head 0/ sector 1;
end: cyl 489/ head 254/ sector 63
3: <UNUSED>
4: <UNUSED>
Should we write new partition table? [n] y
#
As you can see, I used the value calculated earlier; the end cylinder is given by 130+359. After that I decided to reboot: Then always in single user: # fdisk -s /dev/ad0: 784 cyl 255 hd 63 sec Part Start Size Type Flags 1: 63 2088387 0x06 0x00 2: 2088450 5763072 0xa5 0x80 I edit the disklabel: # disklabel -e -r /dev/ad0s2 as the following: # /dev/ad0s2c: type: ESDI disk: ad0s2 label: flags: bytes/sector: 512 sectors/track: 63 tracks/cylinder: 255 sectors/cylinder: 16065 cylinders: 358 sectors/unit: 5763072 rpm: 3600 interleave: 1 trackskew: 0 cylinderskew: 0 headswitch: 0 # milliseconds track-to-track seek: 0 # milliseconds drivedata: 0 8 partitions: # size offset fstype [fsize bsize bps/cpg] a: 81920 0 4.2BSD 1024 8192 16 # (Cyl. 0 - 5*) b: 131072 81920 swap # (Cyl. 5*- 13*) c: 5763072 0 unused 0 0 # (Cyl. 0 - 177) e: 307200 212992 4.2BSD 1024 8192 16 # (Cyl. 13*- 32*) f: 5242880 520192 4.2BSD 1024 8192 16 # (Cyl. 32*- 177*) # In my case, cylinders and sectors/unit were automatically changed to the new values; only c and f sizes have to be modified. My comments follow the hash marks (#). Now we are ready to use growfs(8). We must umount the /usr partition before: # umount /usr # growfs -s 52422880 /dev/ad0s2f growfs(8) will ask you if you did a backup of your data; answer 'Yes', and you will see the process begin. When it is over, we can check the new size of /usr: # mount /usr # df -h Filesystem Size Used Avail Capacity Mounted on /dev/ad0s2a 39M 31M 4.4M 88% / /dev/ad0s2f 2.4G 810M 1.4G 35% /usr /dev/ad0s2e 145M 79M 55M 59% /var procfs 4.0K 4.0K 0B 100% /proc Now the /usr is 2.4G large, but I allocated 2.5G. The missing size is the percentage of space held back from normal users, which is 8% of the whole filesystem by default. For more information see the tunefs(8) manual page. To check the new filesystem, I used fsck(8): # fsck ** /dev/ad0s2a (NO WRITE) ** Last Mounted on / ** Root file system ** Phase 1 - Check Blocks and Sizes ** Phase 2 - Check Pathnames ** Phase 3 - Check Connectivity ** Phase 4 - Check Reference Counts ** Phase 5 - Check Cyl groups 1145 files, 31975 used, 7672 free (136 frags, 942 blocks, 0.3% fragmentation) ** /dev/ad0s2f (NO WRITE) ** Last Mounted on /usr ** Phase 1 - Check Blocks and Sizes ** Phase 2 - Check Pathnames ** Phase 3 - Check Connectivity ** Phase 4 - Check Reference Counts ** Phase 5 - Check Cyl groups SUMMARY INFORMATION BAD SALVAGE? no BLK(S) MISSING IN BIT MAPS SALVAGE? no 123343 files, 829946 used, 1711476 free (7748 frags, 212966 blocks, 0.3% fragmentation) ** /dev/ad0s2e (NO WRITE) ** Last Mounted on /var ** Phase 1 - Check Blocks and Sizes ** Phase 2 - Check Pathnames ** Phase 3 - Check Connectivity ** Phase 4 - Check Reference Counts ** Phase 5 - Check Cyl groups 104 files, 80898 used, 67925 free (29 frags, 8487 blocks, 0.0% fragmentation) We can ignore both SALVAGE messages. If we relaunch fsck(8), all is well. ConclusionFor me, growfs(8) did the job well, but remember that modifying your filesystem isn't a simple operation, so be careful and double-check everything. I have not tried to enlarge a vinum filesystem, but the process must be the same. Once again FreeBSD developers give us a superb tool. I hope a shrinkfs tool will be also developed in the future. Marc Fonvieillefonvi@easynet.fr |