@@ -19,11 +19,9 @@ package mountreconcile
1919import (
2020 "bytes"
2121 "fmt"
22- "os"
2322 goexec "os/exec"
2423 "path"
2524 "strings"
26- "syscall"
2725 "time"
2826
2927 "github.com/cvmfs-contrib/cvmfs-csi/internal/exec"
@@ -42,13 +40,29 @@ type Opts struct {
4240func RunBlocking (o * Opts ) error {
4341 t := time .NewTicker (o .Period )
4442
43+ doReconcile := func () {
44+ log .Tracef ("Reconciling /cvmfs" )
45+ if err := reconcile (); err != nil {
46+ log .Errorf ("Failed to reconcile /cvmfs: %v" , err )
47+ }
48+ }
49+
50+ // Run at start so that broken mounts after nodeplugin Pod
51+ // restart are cleaned up.
52+ //
53+ // Known issue with CVMFS v2.11.0: first run of cvmfs_talk
54+ // on corrupted mounts sometimes results in the program exiting
55+ // due to SIGABRT, as a result of a failed assertion:
56+ // (num_bytes >= 0)
57+ // && (static_cast<size_t>(num_bytes) == nbyte)
58+ // This does not trigger reconciliation. On the second retry,
59+ // the command runs normally and the mount is cleaned.
60+ doReconcile ()
61+
4562 for {
4663 select {
4764 case <- t .C :
48- log .Tracef ("Reconciling /cvmfs" )
49- if err := reconcile (); err != nil {
50- log .Errorf ("Failed to reconcile /cvmfs: %v" , err )
51- }
65+ doReconcile ()
5266 }
5367 }
5468}
@@ -108,28 +122,14 @@ func repoNeedsUnmount(repo string) (bool, error) {
108122 const cvmfsErrConnRefused = "(111 - Connection refused)\x0A "
109123 const cvmfsErrClientNotRunning = "Seems like CernVM-FS is not running"
110124
111- if bytes .HasSuffix (out , []byte (cvmfsErrConnRefused )) ||
112- bytes .HasPrefix (out , []byte (cvmfsErrClientNotRunning )) {
113- // It seems that the CVMFS client exited.
114- // Use stat syscall to check for ENOTCONN, i.e. the mount is corrupted,
115- // confirming what cvmfs_talk returned.
116-
117- _ , err := os .Stat (path .Join (mountPathPrefix , repo ))
118- if err != nil {
119- if err .(* os.PathError ).Err == syscall .ENOTCONN {
120- return true , nil
121- }
122-
123- // It's something else.
124- return false , fmt .Errorf ("unexpected error from stat: %v" , err )
125- }
125+ outputHasKnownErr := bytes .HasSuffix (out , []byte (cvmfsErrConnRefused )) ||
126+ bytes .HasPrefix (out , []byte (cvmfsErrClientNotRunning ))
126127
127- // stat should have failed! Fall through and fail.
128+ if ! outputHasKnownErr {
129+ return false , fmt .Errorf ("failed to talk to CVMFS client (%v): %s" , err , out )
128130 }
129131
130- // If we got here, the error reported by cvmfs_talk
131- // is something else and we should fail too.
132- return false , fmt .Errorf ("failed to talk to CVMFS client (%v): %s" , err , out )
132+ return true , nil
133133}
134134
135135func reconcile () error {
0 commit comments