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
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
|
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
# 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.
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
sed -i -e 's/CheckSpace/#CheckSpace/' /etc/pacman.conf
It would be useful if someone would try pacman-git to confirm.
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?