Set volume NeedsCopyUp to false iff data was copied up

Currently Docker copies up the first volume on a mountpoint with
data.

Fixes: https://github.com/containers/podman/issues/12714

Also added NeedsCopyUP, NeedsChown and MountCount to the podman volume
inspect code.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh
2022-01-06 10:42:34 -05:00
parent c0b3df8059
commit 13f3fd2555
4 changed files with 58 additions and 7 deletions

View File

@ -1700,13 +1700,6 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string)
if vol.state.NeedsCopyUp {
logrus.Debugf("Copying up contents from container %s to volume %s", c.ID(), vol.Name())
// Set NeedsCopyUp to false immediately, so we don't try this
// again when there are already files copied.
vol.state.NeedsCopyUp = false
if err := vol.save(); err != nil {
return nil, err
}
// If the volume is not empty, we should not copy up.
volMount := vol.mountPoint()
contents, err := ioutil.ReadDir(volMount)
@ -1753,6 +1746,13 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string)
return vol, nil
}
// Set NeedsCopyUp to false since we are about to do first copy
// Do not copy second time.
vol.state.NeedsCopyUp = false
if err := vol.save(); err != nil {
return nil, err
}
// Buildah Copier accepts a reader, so we'll need a pipe.
reader, writer := io.Pipe()
defer reader.Close()

View File

@ -48,4 +48,12 @@ type InspectVolumeData struct {
// volume for a specific container, and will be be removed when any
// container using it is removed.
Anonymous bool `json:"Anonymous,omitempty"`
// MountCount is the number of times this volume has been mounted.
MountCount uint `json:"MountCount"`
// NeedsCopyUp indicates that the next time the volume is mounted into
NeedsCopyUp bool `json:"NeedsCopyUp,omitempty"`
// NeedsChown indicates that the next time the volume is mounted into
// a container, the container will chown the volume to the container process
// UID/GID.
NeedsChown bool `json:"NeedsChown,omitempty"`
}

View File

@ -60,6 +60,9 @@ func (v *Volume) Inspect() (*define.InspectVolumeData, error) {
data.UID = v.uid()
data.GID = v.gid()
data.Anonymous = v.config.IsAnon
data.MountCount = v.state.MountCount
data.NeedsCopyUp = v.state.NeedsCopyUp
data.NeedsChown = v.state.NeedsChown
return data, nil
}

View File

@ -345,4 +345,44 @@ EOF
is "$output" "tmpfs" "volume should be tmpfs"
}
# Named volumes copyup
@test "podman volume create copyup" {
myvolume=myvol$(random_string)
mylabel=$(random_string)
# Create a named volume
run_podman volume create $myvolume
is "$output" "$myvolume" "output from volume create"
# Confirm that it shows up in 'volume ls', and confirm values
run_podman volume ls --format json
tests="
Name | $myvolume
Driver | local
NeedsCopyUp | true
NeedsChown | true
"
parse_table "$tests" | while read field expect; do
actual=$(jq -r ".[0].$field" <<<"$output")
is "$actual" "$expect" "volume ls .$field"
done
run_podman run --rm --volume $myvolume:/vol $IMAGE true
run_podman volume inspect --format '{{ .NeedsCopyUp }}' $myvolume
is "${output}" "true" "If content in dest '/vol' empty NeedsCopyUP should still be true"
run_podman volume inspect --format '{{ .NeedsChown }}' $myvolume
is "${output}" "false" "After first use within a container NeedsChown should still be false"
run_podman run --rm --volume $myvolume:/etc $IMAGE ls /etc/passwd
run_podman volume inspect --format '{{ .NeedsCopyUp }}' $myvolume
is "${output}" "false" "If content in dest '/etc' non-empty NeedsCopyUP should still have happend and be false"
run_podman volume inspect --format '{{.Mountpoint}}' $myvolume
mountpoint="$output"
test -e "$mountpoint/passwd"
# Clean up
run_podman volume rm $myvolume
}
# vim: filetype=sh