@@ -16,34 +16,49 @@ package zfs
1616
1717import (
1818 "fmt"
19- "sync"
19+ "sync/atomic "
2020 "time"
2121
2222 zfs "github.com/mistifyio/go-zfs"
2323 "k8s.io/klog/v2"
2424)
2525
26+ // usageCache is a typed wrapper around atomic.Value that eliminates the need
27+ // for type assertions at every call site. It stores filesystem name strings
28+ // mapped to usage values (uint64).
29+ type usageCache struct {
30+ v atomic.Value
31+ }
32+
33+ // Load retrieves the current cache map.
34+ func (c * usageCache ) Load () map [string ]uint64 {
35+ return c .v .Load ().(map [string ]uint64 )
36+ }
37+
38+ // Store saves a new cache map.
39+ func (c * usageCache ) Store (m map [string ]uint64 ) {
40+ c .v .Store (m )
41+ }
42+
2643// zfsWatcher maintains a cache of filesystem -> usage stats for a
2744// zfs filesystem
2845type ZfsWatcher struct {
2946 filesystem string
30- lock * sync.RWMutex
31- cache map [string ]uint64
47+ cache usageCache
3248 period time.Duration
3349 stopChan chan struct {}
3450}
3551
3652// NewThinPoolWatcher returns a new ThinPoolWatcher for the given devicemapper
3753// thin pool name and metadata device or an error.
3854func NewZfsWatcher (filesystem string ) (* ZfsWatcher , error ) {
39-
40- return & ZfsWatcher {
55+ w := & ZfsWatcher {
4156 filesystem : filesystem ,
42- lock : & sync.RWMutex {},
43- cache : make (map [string ]uint64 ),
4457 period : 15 * time .Second ,
4558 stopChan : make (chan struct {}),
46- }, nil
59+ }
60+ w .cache .Store (map [string ]uint64 {})
61+ return w , nil
4762}
4863
4964// Start starts the ZfsWatcher.
@@ -78,22 +93,16 @@ func (w *ZfsWatcher) Stop() {
7893
7994// GetUsage gets the cached usage value of the given filesystem.
8095func (w * ZfsWatcher ) GetUsage (filesystem string ) (uint64 , error ) {
81- w .lock .RLock ()
82- defer w .lock .RUnlock ()
83-
84- v , ok := w .cache [filesystem ]
96+ cache := w .cache .Load ()
97+ v , ok := cache [filesystem ]
8598 if ! ok {
8699 return 0 , fmt .Errorf ("no cached value for usage of filesystem %v" , filesystem )
87100 }
88-
89101 return v , nil
90102}
91103
92104// Refresh performs a zfs get
93105func (w * ZfsWatcher ) Refresh () error {
94- w .lock .Lock ()
95- defer w .lock .Unlock ()
96- newCache := make (map [string ]uint64 )
97106 parent , err := zfs .GetDataset (w .filesystem )
98107 if err != nil {
99108 klog .Errorf ("encountered error getting zfs filesystem: %s: %v" , w .filesystem , err )
@@ -105,10 +114,11 @@ func (w *ZfsWatcher) Refresh() error {
105114 return err
106115 }
107116
117+ newCache := make (map [string ]uint64 )
108118 for _ , ds := range children {
109119 newCache [ds .Name ] = ds .Used
110120 }
111121
112- w .cache = newCache
122+ w .cache . Store ( newCache )
113123 return nil
114124}
0 commit comments