Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions libcontainer/specconv/spec_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -1164,11 +1164,11 @@ func parseMountOptions(options []string) *configs.Mount {
} else {
recAttrSet |= f.flag
recAttrClr &= ^f.flag
if f.flag&unix.MOUNT_ATTR__ATIME == f.flag {
// https://man7.org/linux/man-pages/man2/mount_setattr.2.html
// "cannot simply specify the access-time setting in attr_set, but must also include MOUNT_ATTR__ATIME in the attr_clr field."
recAttrClr |= unix.MOUNT_ATTR__ATIME
}
}
if f.flag&unix.MOUNT_ATTR__ATIME == f.flag {
// https://man7.org/linux/man-pages/man2/mount_setattr.2.html
// "cannot simply specify the access-time setting in attr_set, but must also include MOUNT_ATTR__ATIME in the attr_clr field."
recAttrClr |= unix.MOUNT_ATTR__ATIME
}
} else if f, exists := extensionFlags[o]; exists {
if f.clear {
Expand Down
52 changes: 51 additions & 1 deletion tests/integration/mounts_recursive.bats
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function teardown_volume() {

function setup() {
setup_volume
setup_busybox
setup_debian
}

function teardown() {
Expand Down Expand Up @@ -76,3 +76,53 @@ function teardown() {
[ "$status" -eq 1 ]
[[ "${output}" == *"Read-only file system"* ]]
}

# https://github.com/opencontainers/runc/issues/5095
@test "runc run [ check rbind,r*atime mounts]" {
requires_kernel 5.12
update_config ".mounts += [{source: \"${TESTVOLUME}\" , destination: \"/mnt1\", options: [\"rbind\",\"ratime\"]}]"
update_config ".mounts += [{source: \"${TESTVOLUME}\" , destination: \"/mnt2\", options: [\"rbind\",\"rnoatime\"]}]"
update_config ".mounts += [{source: \"${TESTVOLUME}\" , destination: \"/mnt3\", options: [\"rbind\",\"rstrictatime\"]}]"
update_config ".mounts += [{source: \"${TESTVOLUME}\" , destination: \"/mnt4\", options: [\"rbind\",\"rnostrictatime\"]}]"
update_config ".mounts += [{source: \"${TESTVOLUME}\" , destination: \"/mnt5\", options: [\"rbind\",\"rrelatime\"]}]"
update_config ".mounts += [{source: \"${TESTVOLUME}\" , destination: \"/mnt6\", options: [\"rbind\",\"rnorelatime\"]}]"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got stuck on this part.

When specifying rnorelatime, it maps to unix.MOUNT_ATTR_RELATIME, but MOUNT_ATTR_RELATIME is defined as 0x0. As a result, recAttrSet &= ^f.flag becomes recAttrSet &= ^0, which is effectively a no-op.

This seems incorrect from a specification point of view.
rnorelatime is the recursive form of norelatime, and according to mount(8):

norelatime: Do not use the relatime feature. See also the strictatime mount option.

Personally, I think it would be more consistent to map rnorelatime to MOUNT_ATTR_STRICTATIME, e.g.:

"rnorelatime": {false, unix.MOUNT_ATTR_STRICTATIME}

so that rnorelatime recursively enforces strictatime.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had the same thought. My integration test shows rnorelatime and rrelatime are functionally equivalent here. You're right. WDYT @cyphar

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are overthinking it. The "norelatime" attribute just removes the "MS_RELATIME" if it is previously set. An example is, there is an entry in /etc/fstab that has relatime option, and then you use mount(8) command with -o norelatime option for the same destination.

In any case, it should NOT set strictatime.

Since we only have 1 source of mount options in runc (unlike mount which reads fstab first and then command line options), norelatime should probably be a no-op (unless relatime is specified earlier, in which case it should merely remove the MS_RELATIME flag).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also suggest not overthinking it. When I redid the mount flags a while ago I hit the RELATIME-is-now-default (and mount(2) flags for atime are even more confusing). norelatime is a no-op because it became the default and atime mount flags were pretty sctrwed up on Linux as a result. If a user wants strictatime they should set it explicitly, and we should not do any more magic.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the explanation. I understand now.

I’m OK with this change.
Thanks again for making the fix.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To confirm: the intent is that norelatime is a no-op, not an alias for strictatime, and the patch reflects that.
Thanks for the discussion, @saku3 .


runc run -d --console-socket "$CONSOLE_SOCKET" test_rbind_ratime
[ "$status" -eq 0 ]

runc exec test_rbind_ratime findmnt --noheadings -o options /mnt1
[[ "${output}" == "rw,relatime,"* ]]

runc exec test_rbind_ratime findmnt --noheadings -o options /mnt1/subvol
[[ "${output}" == "rw,relatime,"* ]]

runc exec test_rbind_ratime findmnt --noheadings -o options /mnt2
[[ "${output}" == "rw,noatime,"* ]]

runc exec test_rbind_ratime findmnt --noheadings -o options /mnt2/subvol
[[ "${output}" == "rw,noatime,"* ]]

runc exec test_rbind_ratime findmnt --noheadings -o options /mnt3
[[ "${output}" == "rw,"* ]]

runc exec test_rbind_ratime findmnt --noheadings -o options /mnt3/subvol
[[ "${output}" == "rw,"* ]]

runc exec test_rbind_ratime findmnt --noheadings -o options /mnt4
[[ "${output}" == "rw,relatime,"* ]]

runc exec test_rbind_ratime findmnt --noheadings -o options /mnt4/subvol
[[ "${output}" == "rw,relatime,"* ]]

runc exec test_rbind_ratime findmnt --noheadings -o options /mnt5
[[ "${output}" == "rw,relatime,"* ]]

runc exec test_rbind_ratime findmnt --noheadings -o options /mnt5/subvol
[[ "${output}" == "rw,relatime,"* ]]

runc exec test_rbind_ratime findmnt --noheadings -o options /mnt6
[[ "${output}" == "rw,relatime,"* ]]

runc exec test_rbind_ratime findmnt --noheadings -o options /mnt6/subvol
[[ "${output}" == "rw,relatime,"* ]]
}