fix(volume): write state.pb into a real dir when -dir.idx is unset (#9178)

* fix(volume): write state.pb into a real dir when -dir.idx is unset

When -dir.idx is not set, NewStore passed the empty default to
NewState, making the state.pb path resolve to a relative "state.pb"
against the process CWD. Under systemd (where CWD is typically /),
this caused "open state.pb: permission denied" for operations such
as `volumeServer.state -maintenanceOn`, even though the configured
user owned the data dirs.

Fall back to the first disk location's IdxDirectory so state.pb lives
next to the volume data, consistent with other per-server artifacts.

Fixes #9173

* fix(volume): always resolve state.pb dir via first disk location

Use s.Locations[0].IdxDirectory unconditionally when a location
exists so state.pb inherits the same resolution (~ expansion and
empty-idxFolder fallback) already applied for the .idx files.
Fall back to util.ResolvePath(idxFolder) in the location-less case
so a relative or tilde-prefixed -dir.idx is still normalized.

Addresses PR feedback on #9178.
This commit is contained in:
Chris Lu 2026-04-21 14:52:59 -07:00 committed by GitHub
parent c40db5a52d
commit 45ba71a189
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -154,8 +154,17 @@ func NewStore(
}
wg.Wait()
// Resolve state.pb's directory via the first disk location so it inherits
// the same `~` expansion and empty-idxFolder fallback used for .idx files,
// and is never written as a relative path against the process CWD (#9173).
stateDir := idxFolder
if len(s.Locations) > 0 {
stateDir = s.Locations[0].IdxDirectory
} else if stateDir != "" {
stateDir = util.ResolvePath(stateDir)
}
var err error
s.State, err = NewState(idxFolder)
s.State, err = NewState(stateDir)
if err != nil {
glog.Fatalf("failed to resolve state for volume %s: %v", id, err)
}