- Fix: Concurrent access to properties even for a different pools still cause crash
Prevent concurrent access to all properties with global mutex
This commit is contained in:
parent
7c7ef79611
commit
e24c488fee
30
zfs.go
30
zfs.go
|
@ -311,6 +311,8 @@ func (d *Dataset) PoolName() string {
|
||||||
|
|
||||||
// ReloadProperties re-read dataset's properties
|
// ReloadProperties re-read dataset's properties
|
||||||
func (d *Dataset) ReloadProperties() (err error) {
|
func (d *Dataset) ReloadProperties() (err error) {
|
||||||
|
Global.Mtx.Lock()
|
||||||
|
defer Global.Mtx.Unlock()
|
||||||
if d.list == nil {
|
if d.list == nil {
|
||||||
err = errors.New(msgDatasetIsNil)
|
err = errors.New(msgDatasetIsNil)
|
||||||
return
|
return
|
||||||
|
@ -318,15 +320,7 @@ func (d *Dataset) ReloadProperties() (err error) {
|
||||||
d.Properties = make(map[Prop]Property)
|
d.Properties = make(map[Prop]Property)
|
||||||
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++ {
|
||||||
var plist *C.property_list_t
|
plist := C.read_dataset_property(d.list, C.int(prop))
|
||||||
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
|
||||||
}
|
}
|
||||||
|
@ -340,15 +334,12 @@ func (d *Dataset) ReloadProperties() (err error) {
|
||||||
// GetProperty reload and return single specified property. This also reloads requested
|
// GetProperty reload and return single specified property. This also reloads requested
|
||||||
// property in Properties map.
|
// property in Properties map.
|
||||||
func (d *Dataset) GetProperty(p Prop) (prop Property, err error) {
|
func (d *Dataset) GetProperty(p Prop) (prop Property, err error) {
|
||||||
|
Global.Mtx.Lock()
|
||||||
|
defer Global.Mtx.Unlock()
|
||||||
if d.list == nil {
|
if d.list == nil {
|
||||||
err = errors.New(msgDatasetIsNil)
|
err = errors.New(msgDatasetIsNil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if p == DatasetPropMounted || p == DatasetPropMountpoint {
|
|
||||||
// prevent zfs mountpoint race conditions
|
|
||||||
Global.Mtx.Lock()
|
|
||||||
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()
|
||||||
|
@ -363,6 +354,8 @@ func (d *Dataset) GetProperty(p Prop) (prop Property, err error) {
|
||||||
|
|
||||||
// GetUserProperty - lookup and return user propery
|
// GetUserProperty - lookup and return user propery
|
||||||
func (d *Dataset) GetUserProperty(p string) (prop Property, err error) {
|
func (d *Dataset) GetUserProperty(p string) (prop Property, err error) {
|
||||||
|
Global.Mtx.Lock()
|
||||||
|
defer Global.Mtx.Unlock()
|
||||||
if d.list == nil {
|
if d.list == nil {
|
||||||
err = errors.New(msgDatasetIsNil)
|
err = errors.New(msgDatasetIsNil)
|
||||||
return
|
return
|
||||||
|
@ -384,16 +377,13 @@ func (d *Dataset) GetUserProperty(p string) (prop Property, err error) {
|
||||||
// some can be set only at creation time and some are read only.
|
// some can be set only at creation time and some are read only.
|
||||||
// Always check if returned error and its description.
|
// Always check if returned error and its description.
|
||||||
func (d *Dataset) SetProperty(p Prop, value string) (err error) {
|
func (d *Dataset) SetProperty(p Prop, value string) (err error) {
|
||||||
|
Global.Mtx.Lock()
|
||||||
|
defer Global.Mtx.Unlock()
|
||||||
if d.list == nil {
|
if d.list == nil {
|
||||||
err = errors.New(msgDatasetIsNil)
|
err = errors.New(msgDatasetIsNil)
|
||||||
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 {
|
||||||
|
@ -414,6 +404,8 @@ func (d *Dataset) SetProperty(p Prop, value string) (err error) {
|
||||||
|
|
||||||
// SetUserProperty -
|
// SetUserProperty -
|
||||||
func (d *Dataset) SetUserProperty(prop, value string) (err error) {
|
func (d *Dataset) SetUserProperty(prop, value string) (err error) {
|
||||||
|
Global.Mtx.Lock()
|
||||||
|
defer Global.Mtx.Unlock()
|
||||||
if d.list == nil {
|
if d.list == nil {
|
||||||
err = errors.New(msgDatasetIsNil)
|
err = errors.New(msgDatasetIsNil)
|
||||||
return
|
return
|
||||||
|
|
|
@ -214,7 +214,7 @@ func zfsTestMountPointConcurrency(t *testing.T) {
|
||||||
gr1 := make(chan bool)
|
gr1 := make(chan bool)
|
||||||
gr2 := make(chan bool)
|
gr2 := make(chan bool)
|
||||||
go func() {
|
go func() {
|
||||||
for i := 0; i < 30; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
println("reload properties:", i)
|
println("reload properties:", i)
|
||||||
// d.SetProperty(zfs.DatasetPropMountpoint, "/TEST")
|
// d.SetProperty(zfs.DatasetPropMountpoint, "/TEST")
|
||||||
d.ReloadProperties()
|
d.ReloadProperties()
|
||||||
|
@ -224,11 +224,13 @@ func zfsTestMountPointConcurrency(t *testing.T) {
|
||||||
go func() {
|
go func() {
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
println("set mountpoint:", i)
|
println("set mountpoint:", i)
|
||||||
d.SetProperty(zfs.DatasetPropMountpoint, "/TEST")
|
d.ReloadProperties()
|
||||||
|
// d.SetProperty(zfs.DatasetPropMountpoint, "/TEST")
|
||||||
// d.GetProperty(zfs.DatasetPropMountpoint)
|
// d.GetProperty(zfs.DatasetPropMountpoint)
|
||||||
}
|
}
|
||||||
gr2 <- true
|
gr2 <- true
|
||||||
}()
|
}()
|
||||||
|
|
||||||
d.SetProperty(zfs.DatasetPropMountpoint, "none")
|
d.SetProperty(zfs.DatasetPropMountpoint, "none")
|
||||||
|
|
||||||
<-gr1
|
<-gr1
|
||||||
|
|
Loading…
Reference in New Issue