Skip to content

Commit

Permalink
- Fix: Concurrent access to properties even for a different pools sti…
Browse files Browse the repository at this point in the history
…ll cause crash

Prevent concurrent access to all properties with global mutex
  • Loading branch information
Faruk Kasumovic committed Feb 12, 2020
1 parent 7c7ef79 commit e24c488
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 21 deletions.
30 changes: 11 additions & 19 deletions zfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,22 +311,16 @@ func (d *Dataset) PoolName() string {

// ReloadProperties re-read dataset's properties
func (d *Dataset) ReloadProperties() (err error) {
Global.Mtx.Lock()
defer Global.Mtx.Unlock()
if d.list == nil {
err = errors.New(msgDatasetIsNil)
return
}
d.Properties = make(map[Prop]Property)
C.zfs_refresh_properties(d.list.zh)
for prop := DatasetPropType; prop < DatasetNumProps; 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))
}
plist := C.read_dataset_property(d.list, C.int(prop))
if plist == nil {
continue
}
Expand All @@ -340,15 +334,12 @@ func (d *Dataset) ReloadProperties() (err error) {
// GetProperty reload and return single specified property. This also reloads requested
// property in Properties map.
func (d *Dataset) GetProperty(p Prop) (prop Property, err error) {
Global.Mtx.Lock()
defer Global.Mtx.Unlock()
if d.list == nil {
err = errors.New(msgDatasetIsNil)
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))
if plist == nil {
err = LastError()
Expand All @@ -363,6 +354,8 @@ func (d *Dataset) GetProperty(p Prop) (prop Property, err error) {

// GetUserProperty - lookup and return user propery
func (d *Dataset) GetUserProperty(p string) (prop Property, err error) {
Global.Mtx.Lock()
defer Global.Mtx.Unlock()
if d.list == nil {
err = errors.New(msgDatasetIsNil)
return
Expand All @@ -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.
// Always check if returned error and its description.
func (d *Dataset) SetProperty(p Prop, value string) (err error) {
Global.Mtx.Lock()
defer Global.Mtx.Unlock()
if d.list == nil {
err = errors.New(msgDatasetIsNil)
return
}
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)
C.free(unsafe.Pointer(csValue))
if errcode != 0 {
Expand All @@ -414,6 +404,8 @@ func (d *Dataset) SetProperty(p Prop, value string) (err error) {

// SetUserProperty -
func (d *Dataset) SetUserProperty(prop, value string) (err error) {
Global.Mtx.Lock()
defer Global.Mtx.Unlock()
if d.list == nil {
err = errors.New(msgDatasetIsNil)
return
Expand Down
6 changes: 4 additions & 2 deletions zfs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ func zfsTestMountPointConcurrency(t *testing.T) {
gr1 := make(chan bool)
gr2 := make(chan bool)
go func() {
for i := 0; i < 30; i++ {
for i := 0; i < 100; i++ {
println("reload properties:", i)
// d.SetProperty(zfs.DatasetPropMountpoint, "/TEST")
d.ReloadProperties()
Expand All @@ -224,11 +224,13 @@ func zfsTestMountPointConcurrency(t *testing.T) {
go func() {
for i := 0; i < 100; i++ {
println("set mountpoint:", i)
d.SetProperty(zfs.DatasetPropMountpoint, "/TEST")
d.ReloadProperties()
// d.SetProperty(zfs.DatasetPropMountpoint, "/TEST")
// d.GetProperty(zfs.DatasetPropMountpoint)
}
gr2 <- true
}()

d.SetProperty(zfs.DatasetPropMountpoint, "none")

<-gr1
Expand Down

0 comments on commit e24c488

Please sign in to comment.