Skip to content

Commit

Permalink
backport of commit c329ed8 (#24259)
Browse files Browse the repository at this point in the history
Co-authored-by: Steven Clark <[email protected]>
  • Loading branch information
1 parent 58492f9 commit 4e676c5
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 12 deletions.
4 changes: 4 additions & 0 deletions changelog/24256.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
```release-note:bug
api: Fix deadlock on calls to sys/leader with a namespace configured
on the request.
```
23 changes: 16 additions & 7 deletions vault/ha.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,30 +145,41 @@ func (c *Core) Leader() (isLeader bool, leaderAddr, clusterAddr string, err erro
if c.Sealed() {
return false, "", "", consts.ErrSealed
}

c.stateLock.RLock()
defer c.stateLock.RUnlock()

return c.LeaderLocked()
}

func (c *Core) LeaderLocked() (isLeader bool, leaderAddr, clusterAddr string, err error) {
// Check if HA enabled. We don't need the lock for this check as it's set
// on startup and never modified
if c.ha == nil {
return false, "", "", ErrHANotEnabled
}

// Check if sealed
if c.Sealed() {
return false, "", "", consts.ErrSealed
}

// Check if we are the leader
if !c.standby {
c.stateLock.RUnlock()
return true, c.redirectAddr, c.ClusterAddr(), nil
}

// Initialize a lock
lock, err := c.ha.LockWith(CoreLockPath, "read")
if err != nil {
c.stateLock.RUnlock()
return false, "", "", err
}

// Read the value
held, leaderUUID, err := lock.Value()
if err != nil {
c.stateLock.RUnlock()
return false, "", "", err
}
if !held {
c.stateLock.RUnlock()
return false, "", "", nil
}

Expand All @@ -183,13 +194,11 @@ func (c *Core) Leader() (isLeader bool, leaderAddr, clusterAddr string, err erro
// If the leader hasn't changed, return the cached value; nothing changes
// mid-leadership, and the barrier caches anyways
if leaderUUID == localLeaderUUID && localRedirectAddr != "" {
c.stateLock.RUnlock()
return false, localRedirectAddr, localClusterAddr, nil
}

c.logger.Trace("found new active node information, refreshing")

defer c.stateLock.RUnlock()
c.leaderParamsLock.Lock()
defer c.leaderParamsLock.Unlock()

Expand Down
17 changes: 12 additions & 5 deletions vault/logical_system.go
Original file line number Diff line number Diff line change
Expand Up @@ -4822,8 +4822,15 @@ type LeaderResponse struct {
}

func (core *Core) GetLeaderStatus() (*LeaderResponse, error) {
core.stateLock.RLock()
defer core.stateLock.RUnlock()

return core.GetLeaderStatusLocked()
}

func (core *Core) GetLeaderStatusLocked() (*LeaderResponse, error) {
haEnabled := true
isLeader, address, clusterAddr, err := core.Leader()
isLeader, address, clusterAddr, err := core.LeaderLocked()
if errwrap.Contains(err, ErrHANotEnabled.Error()) {
haEnabled = false
err = nil
Expand All @@ -4837,18 +4844,18 @@ func (core *Core) GetLeaderStatus() (*LeaderResponse, error) {
IsSelf: isLeader,
LeaderAddress: address,
LeaderClusterAddress: clusterAddr,
PerfStandby: core.PerfStandby(),
PerfStandby: core.perfStandby,
}
if isLeader {
resp.ActiveTime = core.ActiveTime()
resp.ActiveTime = core.activeTime
}
if resp.PerfStandby {
resp.PerfStandbyLastRemoteWAL = LastRemoteWAL(core)
} else if isLeader || !haEnabled {
resp.LastWAL = LastWAL(core)
}

resp.RaftCommittedIndex, resp.RaftAppliedIndex = core.GetRaftIndexes()
resp.RaftCommittedIndex, resp.RaftAppliedIndex = core.GetRaftIndexesLocked()
return resp, nil
}

Expand All @@ -4872,7 +4879,7 @@ func (b *SystemBackend) handleSealStatus(ctx context.Context, req *logical.Reque
}

func (b *SystemBackend) handleLeaderStatus(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
status, err := b.Core.GetLeaderStatus()
status, err := b.Core.GetLeaderStatusLocked()
if err != nil {
return nil, err
}
Expand Down
3 changes: 3 additions & 0 deletions vault/raft.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ func (c *Core) GetRaftNodeID() string {
func (c *Core) GetRaftIndexes() (committed uint64, applied uint64) {
c.stateLock.RLock()
defer c.stateLock.RUnlock()
return c.GetRaftIndexesLocked()
}

func (c *Core) GetRaftIndexesLocked() (committed uint64, applied uint64) {
raftStorage, ok := c.underlyingPhysical.(*raft.RaftBackend)
if !ok {
return 0, 0
Expand Down

0 comments on commit 4e676c5

Please sign in to comment.