Introduction

Although it is possible to resize your partition on-line, be aware that you should always have a backup when operating with your data. As one of my colleague was saying:

There are two kinds of people: those who do backups and those who will be.

Yeah, you have been warned!

We start this short tutorial with only 50GB for logs here:

$ df -h /var/log
/dev/sdc1        50G   11G   37G  23% /var/log

Make a backup

Seriously, you should have one.

Enlarging file system

Get some free space

This is most tricky and I will leave it up to you. You will have to end up with some free space. Delete some partition, add a disk and resize your LVM groups or ask a guy in storage room for additional space. If you want to resize normal partition on disk, free space must be accessible after resized partition. If you are using LVM it is not necessary.

I just added some space in my VMware setup.

Resize you partition

If you don’t want to reboot your system you must rescan already discovered devices. One way of rescanning a disk is:

$ echo 1 > /sys/class/scsi_device/0:0:2:0/device/rescan

Where 0:0:2:0 is a device number.

If you have a normal partition, use fdisk. In a nutshell you need to delete old partition and create new one. Very important thing is to begin new partition exactly in place where old one was made. Otherwise you won’t see your data. This is why you have to have a free disk space after partition to resize. (Note: if you have big disks like over 2TB or GPT partitions, consider using gdisk or parted instead)

$ fdisk -l /dev/sdc
Disk /dev/sdc: 100 GiB, 107374182400 bytes, 209715200 sectors
(...)

$ fdisk /dev/sdc
Welcome to fdisk (util-linux 2.25.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Command (m for help): p
Disk /dev/sdc: 100 GiB, 107374182400 bytes, 209715200 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xf0e53bce

Device     Boot Start       End   Sectors Size Id Type
/dev/sdc1        2048 104855551 104853504  50G 83 Linux

Command (m for help): d
Selected partition 1
Partition 1 has been deleted.

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-209715199, default 2048): 2048
Last sector, +sectors or +size{K,M,G,T,P} (2048-209715199, default 209715199): <enter>

Created a new partition 1 of type 'Linux' and of size 100 GiB.

Command (m for help): p
Disk /dev/sdc: 100 GiB, 107374182400 bytes, 209715200 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0xf0e53bce

Device     Boot Start       End   Sectors  Size Id Type
/dev/sdc1        2048 209715199 209713152  100G 83 Linux

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Re-reading the partition table failed.: Device or resource busy

The kernel still uses the old table. The new table will be used at the next reboot or after you run partprobe(8) or kpartx(8).

2016-12-06 10:01:06-10:01:32 fdisk /dev/sdc # 1

Resize file system

At this point you will have to notify kernel that partition was changed. If you have parted installed, you can use partprobe. But on almost every modern distribution partx should be available by default.

$ partx -u /dev/sdc1

Now you need to resize file system. For ext3 or ext4 use resize2fs command.

$ resize2fs /dev/sdc1
resize2fs 1.42.12 (29-Aug-2014)
Filesystem at /dev/sdc1 is mounted on /var/log; on-line resizing required
old_desc_blocks = 4, new_desc_blocks = 7
The filesystem on /dev/sdc1 is now 26214144 (4k) blocks long.

2016-12-06 10:04:35 resize2fs /dev/sdc1

End result

$ df -h /var/log
Filesystem      Size  Used Avail Use% Mounted on
/dev/sdc1        99G   11G   83G  12% /var/log
2016-12-06 10:04:44 df -h /var/log

As you see our partition and file system is resized. All done on-line.

Shrinking file system

Opposite to enlarging partition, on-line shrinking of partition is not supported with e2fsprogs. Rest of the process is very similar, steps however should be taken in appropriate order.

I’ve prepared a test partition for this exercise. It is 10 GB partition and I will want to shrink it to about 5 GB. I also made sure that there is some data at the end of partition. Here are the steps to create this simple test. Start with empty 10 GB partition:

[root@node1 shrink]# df -h /mnt/shrink
Filesystem               Size  Used Avail Use% Mounted on
/dev/vdb                 9.8G   37M  9.2G   1% /mnt/shrink

Fill it up with data. I used dd command to create a 1 GB file filled from /dev/urandom (I could use /dev/zero to speed things up, but I want to have more entropy to make sure my data is not lost) DD was repeated 10 times making sure all space is used.

[root@node1 shrink]# for i in `seq 1 10`; do dd if=/dev/urandom of=file${i} bs=10M count=100; done
(...)
1048576000 bytes (1.0 GB) copied, 70.8624 s, 14.8 MB/s
100+0 records in
100+0 records out
1048576000 bytes (1.0 GB) copied, 71.2416 s, 14.7 MB/s
dd: error writing ‘file10’: No space left on device
90+0 records in
89+0 records out

As you see, we have full disk here:

[root@node1 shrink]# df -h /mnt/shrink
Filesystem      Size  Used Avail Use% Mounted on
/dev/vdb        9.8G  9.8G     0 100% /mnt/shrink

[root@node1 shrink]# ls -lh /mnt/shrink
total 9.7G
-rw-r--r--. 1 root root 1000M Feb 14 14:46 file1
-rw-r--r--. 1 root root  900M Feb 14 14:56 file10
-rw-r--r--. 1 root root 1000M Feb 14 14:47 file2
-rw-r--r--. 1 root root 1000M Feb 14 14:48 file3
-rw-r--r--. 1 root root 1000M Feb 14 14:49 file4
-rw-r--r--. 1 root root 1000M Feb 14 14:51 file5
-rw-r--r--. 1 root root 1000M Feb 14 14:52 file6
-rw-r--r--. 1 root root 1000M Feb 14 14:53 file7
-rw-r--r--. 1 root root 1000M Feb 14 14:54 file8
-rw-r--r--. 1 root root 1000M Feb 14 14:55 file9

I used full space to be sure that during process I will have some data at the end of partition. Now, let’s make some room for shrinkage and calculate md5 sums of our precious data:

[root@node1 shrink]# rm -fv file1 file3 file5 file7 file9
removed ‘file1’
removed ‘file3’
removed ‘file5’
removed ‘file7’
removed ‘file9’

[root@node1 shrink]# df -h /mnt/shrink/
Filesystem      Size  Used Avail Use% Mounted on
/dev/vdb        9.8G  4.9G  4.4G  53% /mnt/shrink

[root@node1 shrink]# md5sum file* | tee  md5sums
6feb8004942c743c22d28e98350335c5  file10
bd80b03c00154889c7468968b1ad0b91  file2
17476fbf042ae4b7fb39eca435495a56  file4
1af18ebe829a8e8611c4a83470f827ce  file6
abf578cdbf775c86180c4badfeae6cb2  file8

[root@node1 shrink]# fdisk /dev/vdb
Welcome to fdisk (util-linux 2.23.2).

Command (m for help): p

Disk /dev/vdb: 10.7 GB, 10737418240 bytes, 20971520 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0xf9f78b75

   Device Boot      Start         End      Blocks   Id  System
/dev/vdb1            2048    20971519    10484736   83  Linux

I removed every second file to make sure my data is scattered all the place.

Shrinking file system

In the end you are going to shrink partition. That means that you want to move your data from space you are leaving behind. So first we will shrink file system. Resize2fs will force you to check your data integrity if you didn’t do that earlier.

[root@node1 mnt]# umount /mnt/shrink/

[root@node1 mnt]# resize2fs /dev/vdb1 2G
resize2fs 1.42.9 (28-Dec-2013)
Please run 'e2fsck -f /dev/vdb1' first.

[root@node1 mnt]# e2fsck -f /dev/vdb1 
e2fsck 1.42.9 (28-Dec-2013)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
/lost+found not found.  Create<y>? yes
Pass 4: Checking reference counts
Pass 5: Checking group summary information

/dev/vdb1: ***** FILE SYSTEM WAS MODIFIED *****
/dev/vdb1: 17/655360 files (0.0% non-contiguous), 1337085/2621184 blocks

As you see I had an error in my file system that was corrected before operation. Also don’t worry about size, resize2fs will check if you are not trying to set too small file system:

[root@node1 mnt]# resize2fs /dev/vdb1 2G
resize2fs 1.42.9 (28-Dec-2013)
resize2fs: New size smaller than minimum (1330374)

[root@node1 mnt]# resize2fs /dev/vdb1 5220M  #5G was a little too small
resize2fs 1.42.9 (28-Dec-2013)
Resizing the filesystem on /dev/vdb1 to 1336320 (4k) blocks.
The filesystem on /dev/vdb1 is now 1336320 blocks long.

Resizing partition

Your file system is now smaller but in order to use freed space we have to change partition size. Note that this operation depends on you and can cause data loss (did I mention making a backup?). Basically you will have to delete actual partition and create new one, smaller. I will use fdisk to this task but if you have bigger disk (over 2TB) or GPT partitions use parted or gdisk.

Fdisk works in sectors. And now you will have to calculate how many sectors your new partition should have. Refer to output of resize command and fdisk for clues. Resize2fs told us that our file system has 1336320 blocks 4 kB each (1336320 (4k) blocks). When I ask fdisk about informations it will tell me that

[root@node1 mnt]# fdisk -l /dev/vdb1 

Disk /dev/vdb1: 5473 MB, 5473567232 bytes, 10690561 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes

it has sectors sized as 512 bytes. Now do a simple math:

sectors = (blocks * block_size_in_bytes) / sector_size

sectors = (1336320 * 4 * 1024) / 512 = 10690560

Now you are ready to recreate your partition. Make sure to set starting sector as the same as before.

[root@node1 mnt]# fdisk /dev/vdb
Welcome to fdisk (util-linux 2.23.2).

Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.


Command (m for help): p

Disk /dev/vdb: 10.7 GB, 10737418240 bytes, 20971520 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0xf9f78b75

   Device Boot      Start         End      Blocks   Id  System
/dev/vdb1            2048    20971519    10484736   83  Linux

Command (m for help): d
Selected partition 1
Partition 1 is deleted

Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Partition number (1-4, default 1): 
First sector (2048-20971519, default 2048): 2048
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-20971519, default 20971519): +10690560
Partition 1 of type Linux and of size 5.1 GiB is set

Command (m for help): p

Disk /dev/vdb: 10.7 GB, 10737418240 bytes, 20971520 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0xf9f78b75

   Device Boot      Start         End      Blocks   Id  System
/dev/vdb1            2048    10692608     5345280+  83  Linux

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

End result

Now you can mount your partition:

[root@node1 mnt]# mount /dev/vdb1 /mnt/shrink/

And verify your data:

[root@node1 shrink]# df -h /mnt/shrink/
Filesystem      Size  Used Avail Use% Mounted on
/dev/vdb1       4.9G  4.9G     0 100% /mnt/shrink

[root@node1 shrink]# md5sum -c md5sums 
file10: OK
file2: OK
file4: OK
file6: OK
file8: OK

2 thoughts on “Live resizing of partition and file system under Linux”

Leave a Reply