Read a filesystem that could not be named as unknown, never as a move (hq ADR 0325 sixth review)
A name read that timed out gave an empty name, which differed from the recorded one and so reset the record: a folder kept while empty asked again, a warranted one was walked again. An unnamed filesystem now leaves the folder exactly as it is, the access is said not known for that look, and it resumes once it is named.
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -1370,7 +1371,7 @@ func TestNamingAHungFilesystemIsOneReadPerMount(t *testing.T) {
|
||||
<-release
|
||||
return ""
|
||||
}
|
||||
defer func() { close(release); MountUUID, statBound = was, wasBound }()
|
||||
defer func() { close(release); flightsDone(t); MountUUID, statBound = was, wasBound }()
|
||||
for i := 0; i < 5; i++ {
|
||||
if id := PlacedID("/a/dead/mount"); id != "" {
|
||||
t.Fatalf("a filesystem that does not answer is named %s", id)
|
||||
@@ -1382,3 +1383,66 @@ func TestNamingAHungFilesystemIsOneReadPerMount(t *testing.T) {
|
||||
t.Fatalf("%d reads of one mount were started while the first hung", started)
|
||||
}
|
||||
}
|
||||
|
||||
// Review (sixth): a name read that does not answer is unknown, never a move — a folder kept while empty and filled
|
||||
// since is not asked about again, a warranted one is not walked again, and nothing of either record is reset.
|
||||
func TestAFilesystemNotNamedThisTimeIsNeverAMove(t *testing.T) {
|
||||
uuid, fsid, source := "6f1c0a4e-1b2d-4c3e-8f00-aa11bb22cc33", "0000080100000000", "/dev/sdb1"
|
||||
_, lib, access := poolNamed(t, &uuid, &fsid, &source)
|
||||
// The name's reads hang past their bound while hanging is set; installed once, before anything reads it.
|
||||
var hanging atomic.Bool
|
||||
release := make(chan struct{})
|
||||
named := MountUUID
|
||||
MountUUID = func(p string) string {
|
||||
if hanging.Load() {
|
||||
<-release
|
||||
}
|
||||
return named(p)
|
||||
}
|
||||
takeIt(t, lib, access)
|
||||
taken := strings.Replace(access, `"taken":false`, `"taken":true`, 1)
|
||||
before, _ := keptRecord(lib)
|
||||
|
||||
wasBound := statBound
|
||||
statBound = 20 * time.Millisecond
|
||||
hanging.Store(true)
|
||||
report, _, err := applyAccesses(t, store.State{}, taken)
|
||||
hanging.Store(false)
|
||||
close(release)
|
||||
flightsDone(t)
|
||||
statBound = wasBound
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if o := outcomeOf(report, "radarr.media"); o.Action != "waiting" || !strings.Contains(o.Detail, "could not be named") {
|
||||
t.Fatalf("a folder whose filesystem was not named this time is not said so: %+v", o)
|
||||
}
|
||||
after, _ := keptRecord(lib)
|
||||
if !after.Kept || after.Placed != before.Placed || after.TakenOn != before.TakenOn || len(after.Left) != 0 ||
|
||||
!sameUsers(after.Users, before.Users) {
|
||||
t.Fatalf("the record was reset by a name not read:\nbefore %+v\nafter %+v", before, after)
|
||||
}
|
||||
|
||||
// Named again: kept as it was, with nothing asked and nothing walked.
|
||||
waitFor(t, "the hung read returned", func() bool { return PlacedID(filepath.Dir(lib)) == before.Placed })
|
||||
report, _, err = applyAccesses(t, store.State{}, taken)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if o := outcomeOf(report, "radarr.media"); o.Action == "waiting" {
|
||||
t.Fatalf("named again, the folder asks again: %+v", o)
|
||||
}
|
||||
if r, _ := keptRecord(lib); r.Act == nil || r.Act.Act != "take" {
|
||||
t.Errorf("the folder was walked again: %+v", r.Act)
|
||||
}
|
||||
}
|
||||
|
||||
// flightsDone waits until no read of a hung test is in flight: it goes on reading the stand-ins after its release.
|
||||
func flightsDone(t *testing.T) {
|
||||
t.Helper()
|
||||
waitFor(t, "the hung reads returned", func() bool {
|
||||
inFlight.Lock()
|
||||
defer inFlight.Unlock()
|
||||
return len(inFlight.reads) == 0
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user