Resizing LVM based SWAP volume on Kubuntu. Lack of RAM

After updating the laptop OS from Kubuntu 20.04 to 22.04 i started experiencing RAM issue i didn't have before on 20.04. The laptop has 8GB Ram and my normal workload is using PyCharm, Vivaldi, Alacritty, Typora, Obsidian. All of them consume less then 8GB. On 22.04 when i run Vivaldi and PyCharm all the memory is swallowed up by them, i have no idea why, but OS functioning became unstable and sometimes i even press hard reboot.

Unfortunately, there are no slots for extending memory and the default swap volume size is around 1GB after standard Ubuntu installation that is used in the case when no free memory is available. All the swap size is also occupied by the two applications and not released. The other point is that OS started cachhing data more aggressively i guess, i failed to release memory by a few approaches

I play Dota 2 from time to time and to run it all the other apps must be closed due to the RAM issue, what an inconvenience. After finishing a couple of games the cache was overfilled and OS gets frozen, that's a total crap. Do you feel my pain now?

According to impossibility of just plugging in one more memory bar a solution to get OS functioning back to stable is only to resize the swap. But it turned out that such the operation is complicated due to LVM based swap as Ubuntu manages volumes with it since 20.04 and i had no free disk space in an LVM pool to add it to the swap volume quickly.

In order to solve the problem a few long and unsafe operations had to be done:

  • Learn how to shrink the space of a file system
  • Shrink it on the laptop disk
  • Extend the swap file size
  • Test OS stability

Disk states

Display initial disk states to compare to the ones at the end.

$ df -h
Filesystem                             Size  Used Avail Use% Mounted on
/dev/mapper/vgkubuntu-root             467G  305G  138G  69% /
/dev/mapper/vgstoragebox-home--backup  290G  161G  114G  59% /media/vol/d4b01a30-f6eb-4b16-9451-1c9fb8366243
$ lsblk
NAME                                        MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
sda                                           8:0    0   1.8T  0 disk
└─luks-4b0ed59d-059f-4f09-b204-1de0e18646ac 253:3    0   1.8T  0 crypt
  ├─vgstoragebox-home--backup               253:4    0   295G  0 lvm   /media/vol/d4b01a30-f6eb-4b16-9451-1c9fb8366243
nvme0n1                                     259:0    0 476.9G  0 disk
└─nvme0n1p3                                 259:3    0 475.7G  0 part
  └─nvme0n1p3_crypt                         253:0    0 475.7G  0 crypt
    ├─vgkubuntu-root                        253:1    0 474.8G  0 lvm   /
    └─vgkubuntu-swap_1                      253:2    0   980M  0 lvm

Shrink the FS. Reduce the LVM volume

By default, when Kubuntu is installed on a LUKS fully encrypted disk LVM management split all the space into two LVM volumes root and swap_1.

$ sudo lvs vgkubuntu
  LV     VG        Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  root   vgkubuntu -wi-ao---- 474.75g
  swap_1 vgkubuntu -wi-a----- 980.00m

Therefore, having no space VFree 0 blocks me from easily extending the swap.

$ sudo vgs vgkubuntu
  VG        #PV #LV #SN Attr   VSize    VFree
  vgkubuntu   1   2   0 wz--n- <475.71g    0 

The first thing have to be done is releasing some space from root which will be added to the swap_1 volume after.

The important notice, releasing file system space is not equal to releasing LVM space. The both have to be done. If to reduce an lvm volume only there is potential to corrupt your data.

Releasing space on an external HDD

Operations on modifying disk space are unsafe and irreversible, due to that, i prefer to make it on an external HDD as a test attempt for further reproducing it on the laptop disk.

There is already the existent backup volume vgstoragebox-home--backup on the HDD that i'm going to shrink it to see how it works, what problems will appear, and how to solve them.

$ lsblk
NAME                                        MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
sda                                           8:0    0   1.8T  0 disk
└─luks-4b0ed59d-059f-4f09-b204-1de0e18646ac 253:3    0   1.8T  0 crypt
  ├─vgstoragebox-home--backup               253:4    0   295G  0 lvm   /media/vol/d4b01a30-f6eb-4b16-9451-1c9fb8366243

The recommendation in the article says to make a file system reduction a bit bigger than an LVM volume one with further extending the file system to all available space of a produced gap. It guarantees that you won't accidentally touch your stored data.

In the current case, the file system size is going to be 292GB and LVM volume size 294GB from 295GB. For dealing with a file system resizing the system package e2fsprogs is taken.

$ sudo resize2fs /dev/vgstoragebox/home-backup 292G
[sudo] password for vol:
resize2fs 1.46.5 (30-Dec-2021)
Filesystem at /dev/vgstoragebox/home-backup is mounted on /media/vol/d4b01a30-f6eb-4b16-9451-1c9fb8366243; on-line resizing required
resize2fs: On-line shrinking not supported

From here and further for many operations the file system and volumes have to stay unmounted. My preference here is udiskcie system package.

$ udisksctl unmount --block-device /dev/mapper/vgstoragebox-home--backup
Unmounted /dev/dm-4.
$ sudo resize2fs /dev/vgstoragebox/home-backup 292G
resize2fs 1.46.5 (30-Dec-2021)
Please run 'e2fsck -f /dev/vgstoragebox/home-backup' first.

After unmounting the warning says to run e2fsck -f before shrinking to check the file system state. The flags -f is for forceful running and -y for answering "yes" to the subsequent questions.

$ sudo e2fsck -f -y /dev/vgstoragebox/home-backup
e2fsck 1.46.5 (30-Dec-2021)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/vgstoragebox/home-backup: 511643/19333120 files (0.2% non-contiguous), 43577986/77332480 blocks
$ sudo resize2fs /dev/vgstoragebox/home-backup 292G
resize2fs 1.46.5 (30-Dec-2021)
Resizing the filesystem on /dev/vgstoragebox/home-backup to 76546048 (4k) blocks.
The filesystem on /dev/vgstoragebox/home-backup is now 76546048 (4k) blocks long.

All goes wll. Display the resize change.

$ udisksctl mount --block-device /dev/mapper/vgstoragebox-home--backup
Mounted /dev/dm-4 at /media/vol/d4b01a30-f6eb-4b16-9451-1c9fb8366243
$ df -h
Filesystem                             Size  Used Avail Use% Mounted on
/dev/mapper/vgstoragebox-home--backup  287G  161G  112G  60% /media/vol/d4b01a30-f6eb-4b16-9451-1c9fb8366243

As you see the file system works with a slightly different space of 287GB, that's normal.

$ udisksctl unmount --block-device /dev/mapper/vgstoragebox-home--backup

The next step is to reduce the LVM volume size.

$ sudo lvchange --activate n vgstoragebox/home-backup
$ sudo lvs
  LV                 VG           Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  home-bckup        vgstoragebox -wi------- 295.00g
$ sudo lvreduce -L 294G /dev/mapper/vgstoragebox-home--backup
  Size of logical volume vgstoragebox/home-backup changed from 295.00 GiB (75520 extents) to 294.00 GiB (75264 extents).
  Logical volume vgstoragebox/home-backup successfully resized.
$ sudo lvs
  LV                 VG           Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  home-backup        vgstoragebox -wi------- 294.00g

The final step here is to occupy all the available space by the file system.

$ sudo lvchange --activate y vgstoragebox/home-backup
$ sudo resize2fs /dev/vgstoragebox/home-backup
resize2fs 1.46.5 (30-Dec-2021)
Filesystem at /dev/vgstoragebox/home-backup is mounted on /media/vol/d4b01a30-f6eb-4b16-9451-1c9fb8366243; on-line resizing required
old_desc_blocks = 37, new_desc_blocks = 37
The filesystem on /dev/vgstoragebox/home-backup is now 77070336 (4k) blocks long.
$ df -h
Filesystem                             Size  Used Avail Use% Mounted on
/dev/mapper/vgstoragebox-home--backup  289G  161G  114G  59% /media/vol/d4b01a30-f6eb-4b16-9451-1c9fb8366243

It's done. The file system now is 289G thats equals to 294GB on a lower level. The experimental attempt succeeded, time to move on to the laptop disk.

Reproduce releasing space from a live OS flash drive

To modify the root volume the OS has to be off. Boot up on a flash drive with a live OS

Open the encrypted laptop disk.

sudo cryptsetup open /dev/nvme0n1p3 laptop-drive

Check that LVM can see the decrypted volumes and the FS is mounted

$ sudo lvs
  LV     VG        Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  root   vgkubuntu -wi-ao---- 474.75g                                                    
  swap_1 vgkubuntu -wi-a----- 980.00m
$ df -h
Filesystem                   Size  Used Avail Use% Mounted on
/dev/mapper/vgkubuntu-root   467G  305G  138G  69% /media/kubuntu/bd15f678-7f4d-4638-96e5-e0ea9d967ec7
$ lsblk
NAME                   MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
nvme0n1                259:0    0   477G  0 disk  
└─nvme0n1p3            259:3    0 475.7G  0 part  
  └─laptop-drive       253:0    0 475.7G  0 crypt 
    ├─vgkubuntu-root   253:1    0 474.8G  0 lvm   /media/kubuntu/bd15f678-7f4d-4638-96e5-e0ea9d967ec7
    └─vgkubuntu-swap_1 253:2    0   980M  0 lvm 

List the file system attributes to compute a proper size to shrink to.

$ sudo dumpe2fs -h /dev/vgkubuntu/root 
dumpe2fs 1.45.5 (07-Jan-2020)
Block count:              124452864
Block size:               4096

Unmount the file system and resize to 464Gb. We compute the size based on Block count, the command df -h output doesn't fit to working with blocks. The current size we have to subtract space from is Block count * Block size / 1024 / 1024 / 0124. In this case, it's 474.75GB - 10GB.

$ udisksctl unmount --block-device /dev/vgkubuntu/root 
Unmounted /dev/dm-1.
sudo e2fsck -f -y /dev/vgkubuntu/root 
/dev/vgkubuntu/root: 2592737/31113216 files (0.3% non-contiguous), 82062147/124452864 blocks
$ sudo resize2fs /dev/vgkubuntu/root 464G
resize2fs 1.45.5 (07-Jan-2020)
The filesystem on /dev/vgkubuntu/root is now 121634816 (4k) blocks long

Reduce the lvm volume to 465GB due to the precaution of keeping stored data untouched.

$ sudo lvchange --activate n vgkubuntu/root
$ sudo lvs
  LV     VG        Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  root   vgkubuntu -wi------- 474.75g                                                    
  swap_1 vgkubuntu -wi-a----- 980.00m 
$ sudo lvreduce -L 465G /dev/vgkubuntu/root
  Size of logical volume vgkubuntu/root changed from 474.75 GiB (121536 extents) to 465.00 GiB (119040 extents).
  Logical volume vgkubuntu/root successfully resized.
$ sudo lvchange --activate y vgkubuntu/root

Now extend the shrunk file system occupying all the available space.

$ sudo resize2fs /dev/vgkubuntu/root
resize2fs 1.45.5 (07-Jan-2020)
Resizing the filesystem on /dev/vgkubuntu/root to 121896960 (4k) blocks.
The filesystem on /dev/vgkubuntu/root is now 121896960 (4k) blocks long.
$ udisksctl mount --block-device /dev/vgkubuntu/root 
Mounted /dev/dm-1 at /media/kubuntu/bd15f678-7f4d-4638-96e5-e0ea9d967ec7.

See the final disk state.

$ df -h
Filesystem                   Size  Used Avail Use% Mounted on
/dev/mapper/vgkubuntu-root   457G  305G  129G  71% /media/kubuntu/bd15f678-7f4d-4638-96e5-e0ea9d967ec7
$ sudo vgs
  VG        #PV #LV #SN Attr   VSize    VFree
  vgkubuntu   1   2   0 wz--n- <475.71g 9.75g

Ok, the VFree space has increased to 9.75GB from 0.

Extend the swap volume

I don't know how big i really need the swap volume to be. For now, i'm adding 3GB and leave some space for a few other purposes. Similiar experience of people who had the same issue i found in the article . The main idea is:

  • Turn the swap off.
  • Add some space to an LVM SWAP volume.
  • Make a new swap.
  • Turn it on.
$ swapon --show
NAME      TYPE      SIZE USED PRIO
/dev/dm-2 partition 980M   0B   -2
$ swapoff -a
$ sudo lvextend --size +3G vgkubuntu/swap_1
  Size of logical volume vgkubuntu/swap_1 changed from 980.00 MiB (245 extents) to <3.96 GiB (1013 extents).
  Logical volume vgkubuntu/swap_1 successfully resized.
$ lsblk
NAME                   MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
└─nvme0n1p3            259:3    0 475.7G  0 part
  └─nvme0n1p3_crypt    253:0    0 475.7G  0 crypt
    ├─vgkubuntu-root   253:1    0   465G  0 lvm   /
    └─vgkubuntu-swap_1 253:2    0     4G  0 lvm
$ sudo mkswap /dev/dm-2
mkswap: /dev/dm-2: warning: wiping old swap signature.
Setting up swapspace version 1, size = 4 GiB (4248825856 bytes)
no label, UUID=ff6f4623-fdb9-4337-9986-e515c8d0b111
$ sudo swapon -a
$ swapon --show
NAME      TYPE      SIZE USED PRIO
/dev/dm-2 partition   4G   0B   -2

Fine, the swap grew up to 4GB. Time to exploitate it and figure out whether the OS issues are gone.

Test stability

To check that a bigger swap makes OS stable i'm playing Dota 2 and experiencing no spikes or other issues anymore. Even when i run many applications it's working much smoother now. And i'm seeing that not all RAM is acquired and the swap stays unfilled completely in comparison to when the size was 980M.

In conclusion, i'd like to understand why the standard Ubuntu installation suggests such a small swap size? For thin and lightweight laptops, the problem of lacking RAM isn't gone.