- Fix mount point property race condition causing segmentation fault failures
This commit is contained in:
parent
4dcea86954
commit
7c7ef79611
|
@ -22,6 +22,9 @@ func Test(t *testing.T) {
|
||||||
|
|
||||||
zfsTestDatasetCreate(t)
|
zfsTestDatasetCreate(t)
|
||||||
zfsTestDatasetOpen(t)
|
zfsTestDatasetOpen(t)
|
||||||
|
// zfsTestMountPointConcurrency(t)
|
||||||
|
// time.Sleep(15 * time.Second)
|
||||||
|
|
||||||
zfsTestDatasetSnapshot(t)
|
zfsTestDatasetSnapshot(t)
|
||||||
zfsTestDatasetOpenAll(t)
|
zfsTestDatasetOpenAll(t)
|
||||||
zfsTestDatasetSetProperty(t)
|
zfsTestDatasetSetProperty(t)
|
||||||
|
|
30
zfs.go
30
zfs.go
|
@ -125,13 +125,12 @@ func DatasetOpenSingle(path string) (d Dataset, err error) {
|
||||||
if d.list == nil || d.list.zh == nil {
|
if d.list == nil || d.list.zh == nil {
|
||||||
err = LastError()
|
err = LastError()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = fmt.Errorf("dataset not found.")
|
err = fmt.Errorf("dataset not found")
|
||||||
}
|
}
|
||||||
err = fmt.Errorf("%s - %s", err.Error(), path)
|
err = fmt.Errorf("%s - %s", err.Error(), path)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d.Type = DatasetType(C.dataset_type(d.list))
|
d.Type = DatasetType(C.dataset_type(d.list))
|
||||||
d.Properties = make(map[Prop]Property)
|
|
||||||
err = d.ReloadProperties()
|
err = d.ReloadProperties()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -317,11 +316,17 @@ func (d *Dataset) ReloadProperties() (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d.Properties = make(map[Prop]Property)
|
d.Properties = make(map[Prop]Property)
|
||||||
Global.Mtx.Lock()
|
|
||||||
defer Global.Mtx.Unlock()
|
|
||||||
C.zfs_refresh_properties(d.list.zh)
|
C.zfs_refresh_properties(d.list.zh)
|
||||||
for prop := DatasetPropType; prop < DatasetNumProps; prop++ {
|
for prop := DatasetPropType; prop < DatasetNumProps; prop++ {
|
||||||
plist := C.read_dataset_property(d.list, C.int(prop))
|
var plist *C.property_list_t
|
||||||
|
if prop == DatasetPropMounted || prop == DatasetPropMountpoint {
|
||||||
|
// prevent zfs mountpoint race conditions
|
||||||
|
Global.Mtx.Lock()
|
||||||
|
plist = C.read_dataset_property(d.list, C.int(prop))
|
||||||
|
Global.Mtx.Unlock()
|
||||||
|
} else {
|
||||||
|
plist = C.read_dataset_property(d.list, C.int(prop))
|
||||||
|
}
|
||||||
if plist == nil {
|
if plist == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -339,8 +344,11 @@ func (d *Dataset) GetProperty(p Prop) (prop Property, err error) {
|
||||||
err = errors.New(msgDatasetIsNil)
|
err = errors.New(msgDatasetIsNil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if p == DatasetPropMounted || p == DatasetPropMountpoint {
|
||||||
|
// prevent zfs mountpoint race conditions
|
||||||
Global.Mtx.Lock()
|
Global.Mtx.Lock()
|
||||||
defer Global.Mtx.Unlock()
|
defer Global.Mtx.Unlock()
|
||||||
|
}
|
||||||
plist := C.read_dataset_property(d.list, C.int(p))
|
plist := C.read_dataset_property(d.list, C.int(p))
|
||||||
if plist == nil {
|
if plist == nil {
|
||||||
err = LastError()
|
err = LastError()
|
||||||
|
@ -381,6 +389,11 @@ func (d *Dataset) SetProperty(p Prop, value string) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
csValue := C.CString(value)
|
csValue := C.CString(value)
|
||||||
|
if p == DatasetPropMounted || p == DatasetPropMountpoint {
|
||||||
|
// prevent zfs mountpoint race conditions
|
||||||
|
Global.Mtx.Lock()
|
||||||
|
defer Global.Mtx.Unlock()
|
||||||
|
}
|
||||||
errcode := C.dataset_prop_set(d.list, C.zfs_prop_t(p), csValue)
|
errcode := C.dataset_prop_set(d.list, C.zfs_prop_t(p), csValue)
|
||||||
C.free(unsafe.Pointer(csValue))
|
C.free(unsafe.Pointer(csValue))
|
||||||
if errcode != 0 {
|
if errcode != 0 {
|
||||||
|
@ -388,9 +401,14 @@ func (d *Dataset) SetProperty(p Prop, value string) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Update Properties member with change made
|
// Update Properties member with change made
|
||||||
if _, err = d.GetProperty(p); err != nil {
|
plist := C.read_dataset_property(d.list, C.int(p))
|
||||||
|
if plist == nil {
|
||||||
|
err = LastError()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
defer C.free_properties(plist)
|
||||||
|
d.Properties[p] = Property{Value: C.GoString(&(*plist).value[0]),
|
||||||
|
Source: C.GoString(&(*plist).source[0])}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
34
zfs_test.go
34
zfs_test.go
|
@ -4,7 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/bicomsystems/go-libzfs"
|
zfs "github.com/bicomsystems/go-libzfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
@ -203,6 +203,38 @@ func zfsTestDatasetDestroy(t *testing.T) {
|
||||||
print("PASS\n\n")
|
print("PASS\n\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func zfsTestMountPointConcurrency(t *testing.T) {
|
||||||
|
println("TEST DATASET MountPointConcurrency( ", TSTDatasetPath, " ) ... ")
|
||||||
|
d, err := zfs.DatasetOpen(TSTDatasetPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer d.Close()
|
||||||
|
gr1 := make(chan bool)
|
||||||
|
gr2 := make(chan bool)
|
||||||
|
go func() {
|
||||||
|
for i := 0; i < 30; i++ {
|
||||||
|
println("reload properties:", i)
|
||||||
|
// d.SetProperty(zfs.DatasetPropMountpoint, "/TEST")
|
||||||
|
d.ReloadProperties()
|
||||||
|
}
|
||||||
|
gr1 <- true
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
println("set mountpoint:", i)
|
||||||
|
d.SetProperty(zfs.DatasetPropMountpoint, "/TEST")
|
||||||
|
// d.GetProperty(zfs.DatasetPropMountpoint)
|
||||||
|
}
|
||||||
|
gr2 <- true
|
||||||
|
}()
|
||||||
|
d.SetProperty(zfs.DatasetPropMountpoint, "none")
|
||||||
|
|
||||||
|
<-gr1
|
||||||
|
<-gr2
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
// EXAMPLES:
|
// EXAMPLES:
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue