FreeBSD 提供了 growfs( 命令。这使得能够实时地调整文件系统的大小, 因而不再受其限制。
http://www.freebsd.org/doc/zh_CN.GB2312/books/handbook/disk-organization.html
growfs 的使用还是受很多限制吧。仔细规划分区的大小,不要把希望寄托在 growfs 上面。
Growing FreeBSD's filesystems with growfs(8)
Introduction
During 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 fight
Before detailing the operations through one example, there are many things to know:
* Playing with filesystems is always a dangerous operation: do it only if it is mandatory and be sure to backup your data.
* growfs(8) can only grow – not shrink – filesystems. You would not be able to shrink the filesystem once it has been expanded.
* growfs(8) cannot enlarge a filesystem that does not have any free space around it.
* We will need to use growfs(8), disklabel(8), fdisk(8) and fsck(8). So print these manual pages and read them. Having a printed version under hand during the process is useful. Remember, in single user mode you can't read manual pages.
* To modify filesystems, we'll have to calculate sizes and sector numbers, so if you're bad at mental arithmetic use a calculator.
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:
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
Are we happy with this entry? [n] y
The data for partition 4 is:
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:
4:
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 partition
Here 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:
*
cylinders: 178 to 359
*
sectors/unit: 2859570 to 5763072
*
c: 2859570 to 5763072
*
f: 2339378 to 5242880
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:
Do you want to change it? [n] n
The data for partition 4 is:
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:
4:
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.
Conclusion
For 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 Fonvieille
fonvi@easynet.fr