3月 282008
 

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
[email protected]

 回复

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>