From 23ab7b858a4d80bfe1505b895f03c36949b5b62c Mon Sep 17 00:00:00 2001 From: Matt Heon Date: Tue, 22 Oct 2024 08:19:38 -0400 Subject: [PATCH] Set quota on volume root directory, not _data This will appease the higher-level quota logic. Basically, to find a free quota ID to prevent reuse, we will iterate through the contents of the directory and check the quota IDs of all subdirectories, then use the first free ID found that is larger than the base ID (the one set on the base directory). Problem: our volumes use a two-tier directory structure, where the volume has an outer directory (with the name of the actual volume) and an inner directory (always named _data). We were only setting the quota on _data, meaning the outer directory did not have an ID, and the ID-choosing logic thus never detected that any IDs had been allocated and always chose the same ID. Setting the ID on the outer directory with PROJINHERIT set makes the ID allocation logic work properly, and guarantees children inherit the ID - so _data and all contents of the volume get the ID as we'd expect. No tests as we don't have a filesystem in our CI that supports XFS quotas (setting it on / needs kernel flags added). Fixes https://issues.redhat.com/browse/RHEL-18038 Signed-off-by: Matt Heon --- libpod/runtime_volume_common.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libpod/runtime_volume_common.go b/libpod/runtime_volume_common.go index 532ea195a3..f215667c16 100644 --- a/libpod/runtime_volume_common.go +++ b/libpod/runtime_volume_common.go @@ -201,7 +201,11 @@ func (r *Runtime) newVolume(ctx context.Context, noCreatePluginVolume bool, opti Inodes: volume.config.Inodes, Size: volume.config.Size, } - if err := q.SetQuota(fullVolPath, quota); err != nil { + // Must use volPathRoot not fullVolPath, as we need the + // base path for the volume - without the `_data` + // subdirectory - so the quota ID assignment logic works + // properly. + if err := q.SetQuota(volPathRoot, quota); err != nil { return nil, fmt.Errorf("failed to set size quota size=%d inodes=%d for volume directory %q: %w", volume.config.Size, volume.config.Inodes, fullVolPath, err) } }