FS#45070 - pacstrap fails with Partition /mnt too full when using zfs even tho space is sufficient

Attached to Project: Pacman
Opened by Dave Cottlehuber (dch) - Sunday, 24 May 2015, 17:48 GMT
Last edited by Doug Newgard (Scimmia) - Monday, 25 May 2015, 14:07 GMT
Task Type Bug Report
Category Packages: Core
Status Unconfirmed
Assigned To No-one
Architecture All
Severity Low
Priority Normal
Reported Version
Due in Version Undecided
Due Date Undecided
Percent Complete 0%
Votes 0
Private No

Details

Description:

pacstrap (assuming this is actually pacman) calculates disk space incorrectly when installing into a zpool. Note that this is not about whether the zpool has compression enabled or not, but about the detected space via stat vs actual disk space free. I'm not sure if this is a pacstrap issue or some underlying stat call due to ZOL mounts.

Additional info:
* package version(s)

1 root@archiso ~ # pacstrap /mnt base base-devel grub-efi-x86_64 zsh vim efibootmgr openssh tmux git gnupg rsync wget curl sudo
...
(163/163) checking for file conflicts [###############################################################] 100%
(163/163) checking available disk space [###############################################################] 100%

error: Partition /mnt too full: 46597 blocks needed, 26002 blocks free
error: not enough free disk space
error: failed to commit transaction (not enough free disk space)
Errors occurred, no packages were upgraded.
==> ERROR: Failed to install packages to new root

1 root@archiso ~ # df -h

Filesystem Size Used Avail Use% Mounted on
dev 227M 0 227M 0% /dev
run 239M 32M 207M 14% /run
/dev/sr0 626M 626M 0 100% /run/archiso/bootmnt
cowspace 256M 32M 225M 13% /run/archiso/cowspace
/dev/loop0 272M 272M 0 100% /run/archiso/sfs/airootfs
/dev/mapper/arch_airootfs 32G 803M 31G 3% /
tmpfs 239M 0 239M 0% /dev/shm
tmpfs 239M 0 239M 0% /sys/fs/cgroup
tmpfs 239M 0 239M 0% /tmp
tmpfs 239M 996K 238M 1% /etc/pacman.d/gnupg
tmpfs 48M 0 48M 0% /run/user/0
zroot/ARCH/default 3.5G 246M 3.2G 8% /mnt
zroot/home 3.2G 128K 3.2G 1% /mnt/home


# stat -f /mnt
File: "/mnt"
ID: 10b65a9a002c28e3 Namelen: 255 Type: zfs
Block size: 131072 Fundamental block size: 131072
Blocks: Total: 27966 Free: 26002 Available: 26002
Inodes: Total: 6656901 Free: 6656704


* config and/or log files etc.

Steps to reproduce:

- create a VM with say a 4GiB disk
- GPT partitions - 0,5GiB ef00 and 3,5GiB a504 (FreeBSD-ZFS)
- boot off a zfs enabled iso (or normal ISO and load up zfs from git)
- create and mount the zpool at /mnt
- use a pacstrap big enough to bump you over:

pacstrap /mnt base base-devel grub-efi-x86_64 zsh vim efibootmgr openssh tmux git gnupg rsync wget curl sudo

This task depends upon

Comment by Dave Cottlehuber (dch) - Sunday, 24 May 2015, 18:07 GMT
NB this zpool uses ashift (larger 4k blocks) & recordsize of 128k:

# zfs get recordsize zroot
NAME PROPERTY VALUE SOURCE
zroot recordsize 128K default

# zpool get ashift zroot
NAME PROPERTY VALUE SOURCE
zroot ashift 12 local


pacstrap calls pacman & the check appears to take place in lib/libalpm/diskspace.c

static int check_mountpoint(alpm_handle_t *handle, alpm_mountpoint_t *mp)
{
/* cushion is roughly min(5% capacity, 20MiB) */
fsblkcnt_t fivepc = (mp->fsp.f_blocks / 20) + 1;
fsblkcnt_t twentymb = (20 * 1024 * 1024 / mp->fsp.f_bsize) + 1;
fsblkcnt_t cushion = fivepc < twentymb ? fivepc : twentymb;
blkcnt_t needed = mp->max_blocks_needed + cushion;

_alpm_log(handle, ALPM_LOG_DEBUG,
"partition %s, needed %jd, cushion %ju, free %ju\n",
mp->mount_dir, (intmax_t)mp->max_blocks_needed,
(uintmax_t)cushion, (uintmax_t)mp->fsp.f_bfree);
if(needed >= 0 && (fsblkcnt_t)needed > mp->fsp.f_bfree) {
_alpm_log(handle, ALPM_LOG_ERROR,
_("Partition %s too full: %jd blocks needed, %jd blocks free\n"),
mp->mount_dir, (intmax_t)needed, (uintmax_t)mp->fsp.f_bfree);
return 1;
}
return 0;
}


hopefully that with the `stat /mnt` info is enough to find a solution.
Comment by Ruben Kelevra (RubenKelevra) - Tuesday, 12 January 2016, 14:19 GMT
I confirm this issue, try to install arch on a small device with compression and run in this error. Since the device is large enough to hold the complete uncompressed package-size this is a bug, not an incompatibility.

pacstrap /mnt base

[...]

Total Installed Size: 586.60 MiB

root@archiso ~ # df -h | grep '/mnt'
zroot 1.7G 233M 1.5G 14% /mnt
/dev/sda1 100M 1.3M 98M 3% /mnt/boot

Comment by Ruben Kelevra (RubenKelevra) - Tuesday, 12 January 2016, 14:26 GMT
Workaround for this issue is disable diskspace check:


sed -i -e 's/CheckSpace/#CheckSpace/' /etc/pacman.conf
Comment by Allan McRae (Allan) - Wednesday, 02 November 2016, 04:13 GMT
My guess is this is fixed with commit 8c55c009.

It would be useful if someone would try pacman-git to confirm.
Comment by zerkshop (zerkshop) - Wednesday, 23 August 2023, 23:26 GMT
This is still an issue in 2023. I ran into this and made some notes here: https://github.com/openzfs/zfs/discussions/15198

In summary:
- doing a `pacman -S` with lots of packages in a VM
- zfs list reported 14.1G avail on the root dataset
- pacman says "Net Upgrade Size: 4786.55 MiB"
- pacman says "error: Partition / too full: 172351 blocks needed, 115656 blocks free"
- I can confirm the block details with a statvfs.h program:
- fsInfo.f_blocks: 126059
- fsInfo.f_bfree: 115656
- fsInfo.f_bavail: 115656
- fsInfo.f_bsize: 131072
- the block size is reported as 131072=128KB, and 115656 x 128KB = 14.1G as expected the same as pacman reports
- Yet pacman is asking for 172351 blocks, or a whopping 21GB for a "Net Upgrade Size: 4786.55 MiB"
- the pacman/lib/libalpm/diskspace.c calculate_installed_size() is rounding every file up to this 128KB block size, resulting in a huge over-estimation
- Can work-around with changing "pacman -S --noconfirm --needed $PACKAGES" to "for pkg in $PACKAGES; do pacman -S --noconfirm --needed $pkg; done" which will reduce the over-estimation error if there are a lot of packages
- Also great we can disable CheckSpace as noted above.

My pool has ashift=12, so the smallest block possible is actually 4kB not 128KB as assumed by pacman.

It might make sense for pacman to use f_frsize, the fragment size, instead of f_bsize for this calculation. Found this interesting excerpt from https://stackoverflow.com/a/73875570

> For most Linux file systems, the values of f_bsize and f_frsize are the same. However, some file systems support the notion of block fragments, which can be used to allocate a smaller unit of storage at the end of the file if a full block is not required. This avoids the waste of space that would otherwise occur if a full block was allocated. On such file systems, f_frsize is the size of a fragment, and f_bsize is the size of a whole block. (The notion of fragments in UNIX file systems first appeared in the early 1980s with the 4.2BSD Fast File System, described in [McKusick et al., 1984].)

Yet still there would need to be a change to openzfs because currently f_frsize and f_bsize are set to the maximum blocksize. The reason isn't super clear to me:

> Unfortunately, under Linux the fragment size and block size are often used interchangeably. Thus we are forced to report both of them as the filesystem's maximum block size.

Otherwise, what if there was a pacman.conf line to manually specify the block size to use?

Loading...