Skip to content

Commit b6ca6fa

Browse files
author
Thomas Hipp
committed
fix LibVirtPoolSync
Declare methods of LibVirtPoolSync as pointers since otherwise the entire construct is ineffective. Callers of `AcquireLock` are now responsible for making sure that the mutex is locked. This will prevent the following errors: * fatal error: concurrent map writes * panic: sync: unlock of unlocked mutex This fixes #121. Signed-off-by: Thomas Hipp <[email protected]>
1 parent 1ec3dcd commit b6ca6fa

File tree

5 files changed

+43
-20
lines changed

5 files changed

+43
-20
lines changed

libvirt/cloudinit_def.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,11 @@ func (ci *defCloudInit) CreateAndUpload(virConn *libvirt.Connect) (string, error
6262
}
6363
defer pool.Free()
6464

65-
PoolSync.AcquireLock(ci.PoolName)
65+
for {
66+
if PoolSync.AcquireLock(ci.PoolName) {
67+
break
68+
}
69+
}
6670
defer PoolSync.ReleaseLock(ci.PoolName)
6771

6872
// Refresh the pool of the volume so that libvirt knows it is

libvirt/coreos_ignition_def.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@ func (ign *defIgnition) CreateAndUpload(virConn *libvirt.Connect) (string, error
3838
}
3939
defer pool.Free()
4040

41-
PoolSync.AcquireLock(ign.PoolName)
41+
for {
42+
if PoolSync.AcquireLock(ign.PoolName) {
43+
break
44+
}
45+
}
4246
defer PoolSync.ReleaseLock(ign.PoolName)
4347

4448
// Refresh the pool of the volume so that libvirt knows it is

libvirt/pool_sync.go

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,56 @@
11
package libvirt
22

3-
import (
4-
"sync"
5-
)
3+
import "sync"
64

75
// LibVirtPoolSync makes possible to synchronize operations
86
// against libvirt pools.
97
// Doing pool.Refresh() operations while uploading or removing
108
// a volume into the pool causes errors inside of libvirtd
119
type LibVirtPoolSync struct {
1210
PoolLocks map[string]*sync.Mutex
11+
PoolLocked map[string]bool
1312
internalMutex sync.Mutex
1413
}
1514

1615
// Allocate a new instance of LibVirtPoolSync
17-
func NewLibVirtPoolSync() LibVirtPoolSync {
16+
func NewLibVirtPoolSync() *LibVirtPoolSync {
1817
pool := LibVirtPoolSync{}
1918
pool.PoolLocks = make(map[string]*sync.Mutex)
19+
pool.PoolLocked = make(map[string]bool)
2020

21-
return pool
21+
return &pool
2222
}
2323

24-
// Acquire a lock for the specified pool
25-
func (ps LibVirtPoolSync) AcquireLock(pool string) {
24+
// Acquire a lock for the specified pool. If the mutex is already locked, the
25+
// method returns false, and does not block. It returns true, if the lock
26+
// could be acquired.
27+
func (ps *LibVirtPoolSync) AcquireLock(pool string) bool {
2628
ps.internalMutex.Lock()
2729
defer ps.internalMutex.Unlock()
2830

29-
lock, exists := ps.PoolLocks[pool]
30-
if !exists {
31-
lock = new(sync.Mutex)
32-
ps.PoolLocks[pool] = lock
31+
if ps.PoolLocks[pool] == nil {
32+
ps.PoolLocks[pool] = new(sync.Mutex)
33+
} else {
34+
if ps.PoolLocked[pool] {
35+
return false
36+
}
3337
}
3438

35-
lock.Lock()
39+
ps.PoolLocks[pool].Lock()
40+
ps.PoolLocked[pool] = true
41+
42+
return true
3643
}
3744

3845
// Release the look for the specified pool
39-
func (ps LibVirtPoolSync) ReleaseLock(pool string) {
46+
func (ps *LibVirtPoolSync) ReleaseLock(pool string) {
4047
ps.internalMutex.Lock()
4148
defer ps.internalMutex.Unlock()
4249

43-
lock, exists := ps.PoolLocks[pool]
44-
if !exists {
50+
if ps.PoolLocks[pool] == nil {
4551
return
4652
}
4753

48-
lock.Unlock()
54+
ps.PoolLocks[pool].Unlock()
55+
ps.PoolLocked[pool] = false
4956
}

libvirt/resource_libvirt_volume.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,11 @@ func resourceLibvirtVolumeCreate(d *schema.ResourceData, meta interface{}) error
9090
poolName = d.Get("pool").(string)
9191
}
9292

93-
PoolSync.AcquireLock(poolName)
93+
for {
94+
if PoolSync.AcquireLock(poolName) {
95+
break
96+
}
97+
}
9498
defer PoolSync.ReleaseLock(poolName)
9599

96100
pool, err := virConn.LookupStoragePoolByName(poolName)

libvirt/utils.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,11 @@ func RemoveVolume(virConn *libvirt.Connect, key string) error {
7878
return fmt.Errorf("Error retrieving name of volume: %s", err)
7979
}
8080

81-
PoolSync.AcquireLock(poolName)
81+
for {
82+
if PoolSync.AcquireLock(poolName) {
83+
break
84+
}
85+
}
8286
defer PoolSync.ReleaseLock(poolName)
8387

8488
WaitForSuccess("Error refreshing pool for volume", func() error {

0 commit comments

Comments
 (0)