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:
+113
-18
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user