Leave no leftover for a folder kept only while empty, and name filesystems by more than their mount point (hq ADR 0325 third review)

A folder kept because it was empty, then covered by its disk, was said as unhealthy
leftover entries for ever: its entries sit on a hidden empty folder and grant nothing,
so they are now forgotten, and only entries walked onto data under a warrant are kept
to be taken out. A warrant and a kept folder now name their filesystem by mount point,
source and type, so another pool at the same point is a move; records naming a mount
point are read as its name. A record with no access ids is said under a path-free name.
This commit is contained in:
2026-10-12 19:06:34 +02:00
parent d2d9fbbd7d
commit f0adb177f0
5 changed files with 181 additions and 44 deletions
+113 -18
View File
@@ -937,9 +937,51 @@ func TestEntriesThatCouldNotBeDroppedAreSaidUntilTheyAre(t *testing.T) {
}
}
// Review L3: a disk mounted over a folder kept below it leaves the mesh's entries there recorded and said; once that
// filesystem holds the folder again, they are taken out.
// Review L3: a disk mounted over a folder taken below it on a warrant leaves the mesh's entries on that data
// recorded and said; once that filesystem holds the folder again, they are taken out.
func TestEntriesLeftOnAFilesystemNoLongerAtTheFolderAreDroppedWhenItIsBack(t *testing.T) {
dir := aclFolder(t)
keeping(t, nil, nil)
pool := filepath.Join(dir, "pool")
lib := filepath.Join(pool, "media")
if err := os.MkdirAll(filepath.Join(lib, "old"), 0o755); err != nil {
t.Fatal(err)
}
a := accessJSON("radarr.media", lib, "read-write", false, "mesh-radarr:61001:read-write:container")
if _, _, err := applyAccesses(t, store.State{}, a); err != nil {
t.Fatal(err)
}
done, _, err := TakeFolder(context.Background(), declare(t, a), "radarr.media", lib, "w-1", "op", noServices)
if err != nil {
t.Fatal(err)
}
<-done
film := filepath.Join(lib, "film")
if err := os.WriteFile(film, []byte("data"), 0o644); err != nil {
t.Fatal(err)
}
_ = unix.Removexattr(film, aclAccessXattr)
MountPoints = func() []string { return []string{"/", pool} }
if _, _, err := applyAccesses(t, store.State{}, a); err != nil {
t.Fatal(err)
}
if left := Leftovers(); len(left) != 1 || !strings.Contains(left[0].Why, "no longer at its folder") {
t.Fatalf("entries left on the data taken below are not said: %+v", left)
}
// The pool goes: the filesystem below holds the folder again, and the entries left there are taken out.
MountPoints = func() []string { return []string{"/"} }
ReconcileKept(context.Background())
if _, still := func() (uint16, bool) { a, _, _ := readACLs(t, filepath.Join(lib, "old")); return a.perm(aclUser, radarr) }(); still {
t.Fatal("the entries left on the filesystem that came back were not taken out")
}
if left := Leftovers(); len(left) != 0 {
t.Fatalf("still said after they were taken out: %+v", left)
}
}
// Review (third) M: a folder kept only because it was empty leaves nothing said when a disk mounts over it — its
// entries sit on an empty folder hidden under the mount and grant nothing on data.
func TestAFolderKeptEmptyLeavesNoLeftoverWhenADiskMountsOverIt(t *testing.T) {
dir := aclFolder(t)
keeping(t, nil, nil)
pool := filepath.Join(dir, "pool")
@@ -951,26 +993,79 @@ func TestEntriesLeftOnAFilesystemNoLongerAtTheFolderAreDroppedWhenItIsBack(t *te
if _, _, err := applyAccesses(t, store.State{}, a); err != nil {
t.Fatal(err)
}
film := filepath.Join(lib, "film")
if err := os.WriteFile(film, []byte("data"), 0o644); err != nil {
t.Fatal(err)
}
_ = unix.Removexattr(film, aclAccessXattr)
MountPoints = func() []string { return []string{"/", pool} }
if _, _, err := applyAccesses(t, store.State{}, a); err != nil {
report, _, err := applyAccesses(t, store.State{}, a)
if err != nil {
t.Fatal(err)
}
if left := Leftovers(); len(left) != 1 || !strings.Contains(left[0].Why, "no longer at its folder") {
t.Fatalf("entries left on the filesystem below are not said: %+v", left)
}
// The pool goes: the filesystem below holds the folder again, and the entries left there are taken out.
MountPoints = func() []string { return []string{"/"} }
ReconcileKept(context.Background())
if _, still := func() (uint16, bool) { a, _, _ := readACLs(t, lib); return a.perm(aclUser, radarr) }(); still {
t.Fatal("the entries left on the filesystem that came back were not taken out")
}
if left := Leftovers(); len(left) != 0 {
t.Fatalf("still said after they were taken out: %+v", left)
t.Fatalf("a folder kept while empty is said as leftover entries for ever: %+v", left)
}
if rec, _ := keptRecord(lib); len(rec.Left) != 0 {
t.Errorf("entries on the hidden empty folder are recorded: %+v", rec.Left)
}
if o := outcomeOf(report, "radarr.media"); !strings.Contains(o.Detail, "forgotten") {
t.Errorf("the forgetting is not said: %+v", o)
}
}
// Review (third) low: a record written before it kept the accesses' ids is said too, under a name with no path.
func TestALeftoverWithNoAccessIdsIsSaidUnderAPathFreeName(t *testing.T) {
keeping(t, nil, nil)
path := "/srv/media/old"
_ = KeptFolders.Update(path, func(f *store.KeptFolder, _ bool) bool {
f.Kept, f.Users = true, []store.KeptUser{{Identity: "mesh-radarr", UID: radarr, Use: "read-write", From: "container"}}
f.Act = &store.KeptAct{State: "waiting"}
return true
})
left := Leftovers()
if len(left) != 1 || left[0].Module != "radarr" || strings.Contains(left[0].Why, path) ||
strings.Contains(left[0].Access, "/") {
t.Fatalf("a record without ids is not said, path-free: %+v", left)
}
}
// Review (third) low: another filesystem mounted at the same point is not the one the warrant was for.
func TestAnotherFilesystemAtTheSameMountPointIsNotTaken(t *testing.T) {
dir := aclFolder(t)
pool := filepath.Join(dir, "pool")
lib := filepath.Join(pool, "media")
if err := os.MkdirAll(filepath.Join(lib, "old"), 0o755); err != nil {
t.Fatal(err)
}
keeping(t, []string{pool}, nil)
source := "tank/a"
was := MountSource
MountSource = func(point string) (string, string) {
if point == pool {
return source, "zfs"
}
return "", ""
}
defer func() { MountSource = was }()
notTaken := accessJSON("radarr.media", lib, "read-write", false, "mesh-radarr:61001:read-write:container")
if _, _, err := applyAccesses(t, store.State{}, notTaken); err != nil {
t.Fatal(err)
}
done, _, err := TakeFolder(context.Background(), declare(t, notTaken), "radarr.media", lib, "w-1", "op", noServices)
if err != nil {
t.Fatal(err)
}
<-done
taken := accessJSON("radarr.media", lib, "read-write", true, "mesh-radarr:61001:read-write:container")
if report, _, _ := applyAccesses(t, store.State{}, taken); outcomeOf(report, "radarr.media").Action == "waiting" {
t.Fatal("the folder taken waits on its own filesystem")
}
source = "tank/b" // another pool imported at the same mount point
report, _, err := applyAccesses(t, store.State{}, taken)
if err != nil {
t.Fatal(err)
}
if o := outcomeOf(report, "radarr.media"); o.Action != "waiting" {
t.Fatalf("another filesystem at the same mount point was kept on the old warrant: %+v", o)
}
if v := AccessVerdict(context.Background(), lib, true, true); v.Kind != VerdictWaitKeep {
t.Fatalf("the look judges it %s", v.Kind)
}
}