Merge pull request 'mounts: list says an armed automount waits, not mounted (issue 437)' (#196) from fix/437-an-armed-automount-is-not-mounted into main
This commit was merged in pull request #196.
This commit is contained in:
@@ -593,7 +593,7 @@ func (a *Applier) judge(p Pair, states map[string]map[string]string, mounted map
|
||||
}
|
||||
mnt, auto := states[p.MountUnit], states[p.AutoUnit]
|
||||
cur, isMounted := mounted[p.Mountpoint]
|
||||
isMounted = isMounted && cur.Type != "autofs"
|
||||
isMounted = isMounted && !cur.IsAutomount()
|
||||
switch {
|
||||
case !there && p.Occasional:
|
||||
return StateAbsent, "not present: " + tried.Error()
|
||||
|
||||
@@ -158,7 +158,7 @@ func kindOf(what, fstype string) string {
|
||||
// there, or nothing when it is, or nothing is mounted there but an automount.
|
||||
func (m *Machine) notOwnSource(kind, what, point string, mounted map[string]Mounted) error {
|
||||
mt, there := mounted[point]
|
||||
if !there || mt.Type == "autofs" {
|
||||
if !there || mt.IsAutomount() {
|
||||
return nil
|
||||
}
|
||||
if kind != "" && m.sourceIs(kind, what, mt) {
|
||||
@@ -172,7 +172,7 @@ func (m *Machine) notOwnSource(kind, what, point string, mounted map[string]Moun
|
||||
func (m *Machine) mountpointFree(p Pair, own map[string]bool, mounted map[string]Mounted) error {
|
||||
ours := own[p.MountUnit] && own[p.AutoUnit]
|
||||
if mt, there := mounted[p.Mountpoint]; there {
|
||||
if mt.Type == "autofs" {
|
||||
if mt.IsAutomount() {
|
||||
if ours {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -135,6 +135,14 @@ type Mounted struct {
|
||||
Options string `json:"options,omitempty"`
|
||||
}
|
||||
|
||||
// IsAutomount says whether this line is only the autofs mount an armed automount leaves at its point.
|
||||
// Nothing is mounted there yet: the share is mounted over it at first use, and that line then wins in
|
||||
// ParseMountinfo. Every judgement of "mounted" asks this one question, so List, the look and the checks
|
||||
// before a mount cannot disagree (novox/hq issue 437).
|
||||
func (mt Mounted) IsAutomount() bool {
|
||||
return mt.Type == "autofs"
|
||||
}
|
||||
|
||||
// ParseMountinfo reads /proc/self/mountinfo: per line the mount point (field 5), and after the " - "
|
||||
// separator the type, the source and the superblock options. The last mount at a point wins, as it
|
||||
// is the one a path resolves to.
|
||||
@@ -400,7 +408,7 @@ func (mt *Mount) say() string {
|
||||
if mt.MountUnit.Result != "" && mt.MountUnit.Result != "success" {
|
||||
state += ", " + mt.MountUnit.Result
|
||||
}
|
||||
case mt.MountedNow != nil:
|
||||
case mt.MountedNow != nil && !mt.MountedNow.IsAutomount():
|
||||
state = "mounted"
|
||||
case mt.Automount != nil && mt.Automount.Active == "active":
|
||||
state = "not mounted, waits for its first use (automount " + mt.Automount.Sub + ")"
|
||||
|
||||
@@ -258,6 +258,35 @@ func TestListReadsTheRootMountsUnit(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// The desktop's recalbox share as it stood on 2026-10-11 (novox/hq issue 437): its automount armed
|
||||
// (active, waiting), its mount unit inactive, and in mountinfo only the autofs line the armed automount
|
||||
// leaves at the point, with the superblock options the desktop showed. Nothing is mounted there, so it
|
||||
// must be said as waiting for its first use, never as mounted. /mnt/backup in TestList keeps the other
|
||||
// half: an nfs4 line over the autofs line is mounted.
|
||||
func TestListSaysAnArmedAutomountIsNotMounted(t *testing.T) {
|
||||
f := newFake(t)
|
||||
f.file("/etc/fstab", "//192.0.2.176/Share /mnt/recalbox cifs username=root,password=s3cret,iocharset=utf8,sec=ntlmssp 0 0\n")
|
||||
f.file("/proc/self/mountinfo", "22 1 259:3 / / rw,relatime shared:1 - ext4 /dev/nvme0n1p3 rw\n"+
|
||||
"40 22 0:50 / /mnt/recalbox rw,relatime shared:30 - autofs systemd-1 rw,fd=116,pgrp=1,timeout=600,minproto=5,maxproto=5,direct,pipe_ino=68285996\n")
|
||||
f.answers["systemctl list-units --type=mount,automount --all --no-legend --plain --no-pager"] = desktopListUnits
|
||||
names := strings.Join(ParseListUnits(desktopListUnits), " ")
|
||||
f.answers["systemctl show -p "+ShowProperties+" --no-pager -- "+names] =
|
||||
"Id=mnt-recalbox.automount\nWhere=/mnt/recalbox\nResult=success\nActiveState=active\nSubState=waiting\n" +
|
||||
"FragmentPath=/etc/systemd/system/mnt-recalbox.automount\nUnitFileState=enabled\n\n" +
|
||||
"Id=mnt-recalbox.mount\nWhere=/mnt/recalbox\nWhat=//192.0.2.176/Share\nType=cifs\n" +
|
||||
"Options=credentials=/var/lib/mounts/smb-recalbox.credentials,iocharset=utf8,_netdev,nofail,uid=1000,gid=1000\n" +
|
||||
"Result=success\nActiveState=inactive\nSubState=dead\nFragmentPath=/etc/systemd/system/mnt-recalbox.mount\n" +
|
||||
"TimeoutUSec=10s\nUnitFileState=enabled-runtime\n"
|
||||
r := f.machine().List(false, "recalbox")
|
||||
if len(r.Said) != 1 {
|
||||
t.Fatalf("said %q, want one line for /mnt/recalbox", r.Said)
|
||||
}
|
||||
want := "/mnt/recalbox (cifs from //192.0.2.176/Share): not mounted, waits for its first use (automount waiting); from /etc/fstab line 1, no nofail"
|
||||
if r.Said[0] != want {
|
||||
t.Errorf("said %q,\nwant %q", r.Said[0], want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestListNarrowed(t *testing.T) {
|
||||
m := listFake(t).machine()
|
||||
if r := m.List(true, ""); len(r.Mounts) != 3 {
|
||||
|
||||
Reference in New Issue
Block a user