Merge pull request #26238 from ArthurWuTW/26102

tmpfs: Add support for noatime mount option
This commit is contained in:
openshift-merge-bot[bot]
2025-07-04 10:55:02 +00:00
committed by GitHub
5 changed files with 37 additions and 3 deletions

View File

@ -100,6 +100,8 @@ Options specific to type=**tmpfs** and **ramfs**:
- *tmpcopyup*: Enable copyup from the image directory at the same location to the tmpfs/ramfs. Used by default. - *tmpcopyup*: Enable copyup from the image directory at the same location to the tmpfs/ramfs. Used by default.
- *noatime*: Disable updating file access times when the file is read.
- *notmpcopyup*: Disable copying files from the image to the tmpfs/ramfs. - *notmpcopyup*: Disable copying files from the image to the tmpfs/ramfs.
- *U*, *chown*: *true* or *false* (default if unspecified: *false*). Recursively change the owner and group of the source volume based on the UID and GID of the container. - *U*, *chown*: *true* or *false* (default if unspecified: *false*). Recursively change the owner and group of the source volume based on the UID and GID of the container.

View File

@ -185,6 +185,10 @@ func processOptionsInternal(options []string, isTmpfs bool, sourcePath string, g
return nil, fmt.Errorf("the 'U' option can only be set once: %w", ErrDupeMntOption) return nil, fmt.Errorf("the 'U' option can only be set once: %w", ErrDupeMntOption)
} }
foundU = true foundU = true
case "noatime":
if !isTmpfs {
return nil, fmt.Errorf("the 'noatime' option is only allowed with tmpfs mounts: %w", ErrBadMntOption)
}
default: default:
return nil, fmt.Errorf("unknown mount option %q: %w", opt, ErrBadMntOption) return nil, fmt.Errorf("unknown mount option %q: %w", opt, ErrBadMntOption)
} }

View File

@ -715,10 +715,10 @@ func TestProcessOptions(t *testing.T) {
}{ }{
{ {
name: "tmpfs", name: "tmpfs",
options: []string{"rw", "size=512m"}, options: []string{"rw", "size=512m", "noatime"},
isTmpfs: true, isTmpfs: true,
sourcePath: "", sourcePath: "",
expected: []string{"nodev", "nosuid", "rprivate", "rw", "size=512m", "tmpcopyup"}, expected: []string{"nodev", "nosuid", "rprivate", "rw", "size=512m", "tmpcopyup", "noatime"},
}, },
{ {
name: "duplicate idmap option", name: "duplicate idmap option",
@ -810,6 +810,12 @@ func TestProcessOptions(t *testing.T) {
options: []string{"bind"}, options: []string{"bind"},
expected: []string{"nodev", "nosuid", "bind", "private"}, expected: []string{"nodev", "nosuid", "bind", "private"},
}, },
{
name: "noatime allowed only with tmpfs",
sourcePath: "/path/to/source",
options: []string{"noatime"},
expectErr: true,
},
} }
for _, tt := range tests { for _, tt := range tests {

View File

@ -8,7 +8,7 @@ t POST containers/create?name=hostconfig_test \
Image=$IMAGE \ Image=$IMAGE \
Cmd='["df","-P","'$tmpfs_name'"]' \ Cmd='["df","-P","'$tmpfs_name'"]' \
HostConfig='{"Binds":["/tmp/doesnotexist:/test1"]' \ HostConfig='{"Binds":["/tmp/doesnotexist:/test1"]' \
TmpFs="{\"$tmpfs_name\":\"rw\"}}" \ TmpFs="{\"$tmpfs_name\":\"rw,noatime\"}}" \
201 \ 201 \
.Id~[0-9a-f]\\{64\\} .Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output") cid=$(jq -r '.Id' <<<"$output")
@ -29,3 +29,11 @@ t GET containers/${cid}/logs?stdout=true 200
# null bytes in the outfile. # null bytes in the outfile.
like "$(tr -d \\0 <$WORKDIR/curl.result.out)" ".* ${tmpfs_name}" \ like "$(tr -d \\0 <$WORKDIR/curl.result.out)" ".* ${tmpfs_name}" \
"'df' output includes tmpfs name" "'df' output includes tmpfs name"
# Reject 'noatime' for bind mount
t POST libpod/containers/create \
Image=$IMAGE \
Mounts='[{"type":"bind","source":"/nosuchdir","destination":"/data","options":["noatime"]}]' \
500 \
.cause="invalid mount option" \
.message~"the 'noatime' option is only allowed with tmpfs mounts"

View File

@ -1131,4 +1131,18 @@ RUN chmod 755 /test1 /test2 /test3`, ALPINE)
outTest := podmanTest.PodmanExitCleanly("run", "--rm", "--mount", fmt.Sprintf("type=volume,src=%s,dest=/mnt", volName), ALPINE, "ls", "/mnt") outTest := podmanTest.PodmanExitCleanly("run", "--rm", "--mount", fmt.Sprintf("type=volume,src=%s,dest=/mnt", volName), ALPINE, "ls", "/mnt")
Expect(outTest.OutputToString()).To(ContainSubstring("testfile")) Expect(outTest.OutputToString()).To(ContainSubstring("testfile"))
}) })
It("podman run --tmpfs with noatime option", func() {
session := podmanTest.Podman([]string{"run", "--rm", "--tmpfs", "/mytmpfs:noatime", ALPINE, "grep", "mytmpfs", "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitCleanly())
output := session.OutputToString()
Expect(output).To(ContainSubstring("noatime"))
session = podmanTest.Podman([]string{"run", "--rm", "--tmpfs", "/mytmpfs", ALPINE, "grep", "mytmpfs", "/proc/self/mountinfo"})
session.WaitWithDefaultTimeout()
Expect(session).Should(ExitCleanly())
output = session.OutputToString()
Expect(output).ToNot(ContainSubstring("noatime"))
})
}) })