Skip to content

Commit bff9da4

Browse files
mheonopenshift-cherrypick-robot
authored and
openshift-cherrypick-robot
committed
Create quota before _data dir for volumes
This resolves an ordering issue that prevented quotas from being applied. XFS quotas are applied recursively, but only for subdirectories created after the quota is applied; if we create `_data` before the quota, and then use `_data` for all data in the volume, the quota will never be used by the volume. Also, add a test that volume quotas are working as designed using an XFS formatted loop device in the system tests. This should prevent any further regressions on basic quota functionality, such as quotas being shared between volumes. Fixes containers#25368 Fixes https://issues.redhat.com/browse/RHEL-82198 Fixes https://issues.redhat.com/browse/RHEL-82199 Signed-off-by: Matt Heon <[email protected]>
1 parent 7b0a999 commit bff9da4

File tree

4 files changed

+96
-11
lines changed

4 files changed

+96
-11
lines changed

libpod/runtime_volume_common.go

+16-11
Original file line numberDiff line numberDiff line change
@@ -168,16 +168,11 @@ func (r *Runtime) newVolume(ctx context.Context, noCreatePluginVolume bool, opti
168168
if err := idtools.SafeChown(volPathRoot, volume.config.UID, volume.config.GID); err != nil {
169169
return nil, fmt.Errorf("chowning volume directory %q to %d:%d: %w", volPathRoot, volume.config.UID, volume.config.GID, err)
170170
}
171-
fullVolPath := filepath.Join(volPathRoot, "_data")
172-
if err := os.MkdirAll(fullVolPath, 0755); err != nil {
173-
return nil, fmt.Errorf("creating volume directory %q: %w", fullVolPath, err)
174-
}
175-
if err := idtools.SafeChown(fullVolPath, volume.config.UID, volume.config.GID); err != nil {
176-
return nil, fmt.Errorf("chowning volume directory %q to %d:%d: %w", fullVolPath, volume.config.UID, volume.config.GID, err)
177-
}
178-
if err := LabelVolumePath(fullVolPath, volume.config.MountLabel); err != nil {
179-
return nil, err
180-
}
171+
172+
// Setting quotas must happen *before* the _data inner directory
173+
// is created, as the volume must be empty for the quota to be
174+
// properly applied - if any subdirectories exist before the
175+
// quota is applied, the quota will not be applied to them.
181176
switch {
182177
case volume.config.DisableQuota:
183178
if volume.config.Size > 0 || volume.config.Inodes > 0 {
@@ -206,10 +201,20 @@ func (r *Runtime) newVolume(ctx context.Context, noCreatePluginVolume bool, opti
206201
// subdirectory - so the quota ID assignment logic works
207202
// properly.
208203
if err := q.SetQuota(volPathRoot, quota); err != nil {
209-
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)
204+
return nil, fmt.Errorf("failed to set size quota size=%d inodes=%d for volume directory %q: %w", volume.config.Size, volume.config.Inodes, volPathRoot, err)
210205
}
211206
}
212207

208+
fullVolPath := filepath.Join(volPathRoot, "_data")
209+
if err := os.MkdirAll(fullVolPath, 0755); err != nil {
210+
return nil, fmt.Errorf("creating volume directory %q: %w", fullVolPath, err)
211+
}
212+
if err := idtools.SafeChown(fullVolPath, volume.config.UID, volume.config.GID); err != nil {
213+
return nil, fmt.Errorf("chowning volume directory %q to %d:%d: %w", fullVolPath, volume.config.UID, volume.config.GID, err)
214+
}
215+
if err := LabelVolumePath(fullVolPath, volume.config.MountLabel); err != nil {
216+
return nil, err
217+
}
213218
volume.config.MountPoint = fullVolPath
214219
}
215220

rpm/podman.spec

+1
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ Requires: openssl
151151
Requires: socat
152152
Requires: buildah
153153
Requires: gnupg
154+
Requires: xfsprogs
154155

155156
%description tests
156157
%{summary}

test/system/161-volume-quotas.bats

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#!/usr/bin/env bats -*- bats -*-
2+
#
3+
# podman volume XFS quota tests
4+
#
5+
# bats file_tags=distro-integration
6+
#
7+
8+
load helpers
9+
10+
function setup() {
11+
basic_setup
12+
13+
run_podman '?' volume rm -a
14+
}
15+
16+
function teardown() {
17+
run_podman '?' rm -af -t 0
18+
run_podman '?' volume rm -a
19+
20+
loop=$PODMAN_TMPDIR/disk.img
21+
vol_path=$PODMAN_TMPDIR/volpath
22+
if [ -f ${loop} ]; then
23+
if [ -d ${vol_path} ]; then
24+
if mountpoint ${vol_path}; then
25+
umount "$vol_path"
26+
fi
27+
rm -rf "$vol_path"
28+
fi
29+
30+
while read path dev; do
31+
if [[ "$path" == "$loop" ]]; then
32+
losetup -d $dev
33+
fi
34+
done < <(losetup -l --noheadings --output BACK-FILE,NAME)
35+
rm -f $loop
36+
fi
37+
38+
basic_teardown
39+
}
40+
41+
@test "podman volumes with XFS quotas" {
42+
skip_if_rootless "Quotas are only possible with root"
43+
skip_if_remote "Requires --root flag, not possible w/ remote"
44+
45+
# Minimum XFS filesystem size is 300mb
46+
loop=$PODMAN_TMPDIR/disk.img
47+
fallocate -l 300m ${loop}
48+
run -0 losetup -f --show $loop
49+
loop_dev="$output"
50+
mkfs.xfs $loop_dev
51+
52+
safe_opts=$(podman_isolation_opts ${PODMAN_TMPDIR})
53+
vol_path=$PODMAN_TMPDIR/volpath
54+
mkdir -p $vol_path
55+
safe_opts="$safe_opts --volumepath=$vol_path"
56+
mount -t xfs -o defaults,pquota $loop_dev $vol_path
57+
58+
vol_one="testvol1"
59+
run_podman $safe_opts volume create --opt o=size=2m $vol_one
60+
61+
vol_two="testvol2"
62+
run_podman $safe_opts volume create --opt o=size=4m $vol_two
63+
64+
ctrname="testctr"
65+
run_podman $safe_opts run -d --name=$ctrname -i -v $vol_one:/one -v $vol_two:/two $IMAGE top
66+
67+
run_podman $safe_opts exec $ctrname dd if=/dev/zero of=/one/oneMB bs=1M count=1
68+
run_podman 1 $safe_opts exec $ctrname dd if=/dev/zero of=/one/twoMB bs=1M count=1
69+
assert "$output" =~ "No space left on device"
70+
run_podman $safe_opts exec $ctrname dd if=/dev/zero of=/two/threeMB bs=1M count=3
71+
run_podman 1 $safe_opts exec $ctrname dd if=/dev/zero of=/two/oneMB bs=1M count=1
72+
assert "$output" =~ "No space left on device"
73+
74+
run_podman $safe_opts rm -f -t 0 $ctrname
75+
run_podman $safe_opts volume rm -af
76+
}
77+
78+
# vim: filetype=sh

test/system/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ Requirements
9292
- socat
9393
- buildah
9494
- gnupg
95+
- xfsprogs
9596

9697

9798
Further Details

0 commit comments

Comments
 (0)