github.com/swiftstack/ProxyFS@v0.0.0-20210203235616-4017c267d62f/evtlog/config.go (about) 1 // Copyright (c) 2015-2021, NVIDIA CORPORATION. 2 // SPDX-License-Identifier: Apache-2.0 3 4 package evtlog 5 6 import ( 7 "fmt" 8 "syscall" 9 "time" 10 11 "github.com/swiftstack/ProxyFS/conf" 12 "github.com/swiftstack/ProxyFS/logger" 13 "github.com/swiftstack/ProxyFS/trackedlock" 14 "github.com/swiftstack/ProxyFS/transitions" 15 ) 16 17 // #include <errno.h> 18 // #include <stdint.h> 19 // #include <sys/ipc.h> 20 // #include <sys/shm.h> 21 // #include <sys/types.h> 22 // 23 // uintptr_t shmat_returning_uintptr(int shmid, uintptr_t shmaddr, int shmflg) { 24 // void *shmat_return; 25 // shmat_return = shmat(shmid, (void *)shmaddr, shmflg); 26 // return (uintptr_t)shmat_return; 27 // } 28 // 29 // int shmdt_returning_errno(uintptr_t shmaddr) { 30 // int shmdt_return; 31 // shmdt_return = shmdt((void *)shmaddr); 32 // if (0 == shmdt_return) { 33 // return 0; 34 // } else { 35 // return errno; 36 // } 37 // } 38 import "C" 39 40 type globalsStruct struct { 41 trackedlock.Mutex // While there can only ever be a single Consumer, multiple Producers are possible (within the same process) 42 eventLogEnabled bool 43 eventLogBufferKey uint64 44 eventLogBufferLength uint64 45 eventLogLockMinBackoff time.Duration 46 eventLogLockMaxBackoff time.Duration 47 shmKey C.key_t 48 shmSize C.size_t 49 shmID C.int 50 shmAddr C.uintptr_t 51 shmKnownToBeInitialized bool // Iindicates that this instance "knows" initialization has completed 52 } 53 54 var globals globalsStruct 55 56 type eventLogConfigSettings struct { 57 eventLogEnabled bool 58 eventLogBufferKey uint64 59 eventLogBufferLength uint64 60 eventLogLockMinBackoff time.Duration 61 eventLogLockMaxBackoff time.Duration 62 } 63 64 func init() { 65 transitions.Register("evtlog", &globals) 66 } 67 68 // Extract the settings from the confMap and perform minimal sanity checking 69 // 70 func parseConfMap(confMap conf.ConfMap) (settings eventLogConfigSettings, err error) { 71 settings.eventLogEnabled, err = confMap.FetchOptionValueBool("EventLog", "Enabled") 72 if (nil != err) || !settings.eventLogEnabled { 73 // ignore parsing errors and treat this as logging disabled 74 settings.eventLogEnabled = false 75 err = nil 76 return 77 } 78 79 settings.eventLogBufferKey, err = confMap.FetchOptionValueUint64("EventLog", "BufferKey") 80 if nil != err { 81 err = fmt.Errorf("confMap.FetchOptionValueUint32(\"EventLog\", \"BufferKey\") failed: %v", err) 82 return 83 } 84 85 settings.eventLogBufferLength, err = confMap.FetchOptionValueUint64("EventLog", "BufferLength") 86 if nil != err { 87 err = fmt.Errorf("confMap.FetchOptionValueUint64(\"EventLog\", \"BufferLength\") failed: %v", err) 88 return 89 } 90 if 0 != (globals.eventLogBufferLength % 4) { 91 err = fmt.Errorf("confMap.FetchOptionValueUint64(\"EventLog\", \"BufferLength\") not divisible by 4") 92 return 93 } 94 95 settings.eventLogLockMinBackoff, err = confMap.FetchOptionValueDuration("EventLog", "MinBackoff") 96 if nil != err { 97 err = fmt.Errorf("confMap.FetchOptionValueDuration(\"EventLog\", \"MinBackoff\") failed: %v", err) 98 return 99 } 100 101 settings.eventLogLockMaxBackoff, err = confMap.FetchOptionValueDuration("EventLog", "MaxBackoff") 102 if nil != err { 103 err = fmt.Errorf("confMap.FetchOptionValueDuration(\"EventLog\", \"MaxBackoff\") failed: %v", err) 104 return 105 } 106 107 return 108 } 109 110 func (dummy *globalsStruct) Up(confMap conf.ConfMap) (err error) { 111 var settings eventLogConfigSettings 112 113 settings, err = parseConfMap(confMap) 114 if nil != err { 115 return 116 } 117 118 logger.Infof("evtlog.Up(): event logging is %v", settings.eventLogEnabled) 119 120 globals.eventLogEnabled = settings.eventLogEnabled 121 if !globals.eventLogEnabled { 122 return 123 } 124 125 globals.eventLogBufferKey = settings.eventLogBufferKey 126 globals.eventLogBufferLength = settings.eventLogBufferLength 127 globals.eventLogLockMinBackoff = settings.eventLogLockMinBackoff 128 globals.eventLogLockMaxBackoff = settings.eventLogLockMaxBackoff 129 130 err = enableLogging() 131 return 132 } 133 134 func (dummy *globalsStruct) VolumeGroupCreated(confMap conf.ConfMap, volumeGroupName string, activePeer string, virtualIPAddr string) (err error) { 135 return nil 136 } 137 func (dummy *globalsStruct) VolumeGroupMoved(confMap conf.ConfMap, volumeGroupName string, activePeer string, virtualIPAddr string) (err error) { 138 return nil 139 } 140 func (dummy *globalsStruct) VolumeGroupDestroyed(confMap conf.ConfMap, volumeGroupName string) (err error) { 141 return nil 142 } 143 func (dummy *globalsStruct) VolumeCreated(confMap conf.ConfMap, volumeName string, volumeGroupName string) (err error) { 144 return nil 145 } 146 func (dummy *globalsStruct) VolumeMoved(confMap conf.ConfMap, volumeName string, volumeGroupName string) (err error) { 147 return nil 148 } 149 func (dummy *globalsStruct) VolumeDestroyed(confMap conf.ConfMap, volumeName string) (err error) { 150 return nil 151 } 152 func (dummy *globalsStruct) ServeVolume(confMap conf.ConfMap, volumeName string) (err error) { 153 return nil 154 } 155 func (dummy *globalsStruct) UnserveVolume(confMap conf.ConfMap, volumeName string) (err error) { 156 return nil 157 } 158 func (dummy *globalsStruct) VolumeToBeUnserved(confMap conf.ConfMap, volumeName string) (err error) { 159 return nil 160 } 161 func (dummy *globalsStruct) SignaledStart(confMap conf.ConfMap) (err error) { 162 return nil 163 } 164 165 func (dummy *globalsStruct) SignaledFinish(confMap conf.ConfMap) (err error) { 166 var settings eventLogConfigSettings 167 168 settings, err = parseConfMap(confMap) 169 if nil != err { 170 return 171 } 172 173 logger.Infof("evtlog.Signaled(): event logging is now %v (was %v)", settings.eventLogEnabled, globals.eventLogEnabled) 174 175 if !settings.eventLogEnabled { 176 if !globals.eventLogEnabled { 177 // was disabled and still is; no work to do 178 return 179 } 180 181 // was enabled but is now disabled 182 err = disableLogging() 183 return 184 } 185 186 // event logging will be enabled 187 // 188 // if it was enabled previously certain settings cannot be changed 189 if globals.eventLogEnabled { 190 if settings.eventLogBufferKey != globals.eventLogBufferKey { 191 err = fmt.Errorf("confMap[EventLog][BufferKey] not modifable without a restart") 192 return 193 } 194 if settings.eventLogBufferLength != globals.eventLogBufferLength { 195 err = fmt.Errorf("confMap[EventLog][BufferLength] not modifable without a restart") 196 return 197 } 198 } 199 200 globals.eventLogEnabled = settings.eventLogEnabled 201 globals.eventLogBufferKey = settings.eventLogBufferKey 202 globals.eventLogBufferLength = settings.eventLogBufferLength 203 globals.eventLogLockMinBackoff = settings.eventLogLockMinBackoff 204 globals.eventLogLockMaxBackoff = settings.eventLogLockMaxBackoff 205 206 err = enableLogging() 207 return 208 } 209 210 func (dummy *globalsStruct) Down(confMap conf.ConfMap) (err error) { 211 if globals.eventLogEnabled { 212 err = disableLogging() 213 } 214 215 return 216 } 217 218 func enableLogging() (err error) { 219 var ( 220 rmidResult C.int 221 errno error 222 sharedMemoryObjectPermissions C.int 223 ) 224 225 globals.shmKey = C.key_t(globals.eventLogBufferKey) 226 globals.shmSize = C.size_t(globals.eventLogBufferLength) 227 228 sharedMemoryObjectPermissions = 0 | 229 syscall.S_IRUSR | 230 syscall.S_IWUSR | 231 syscall.S_IRGRP | 232 syscall.S_IWGRP | 233 syscall.S_IROTH | 234 syscall.S_IWOTH 235 236 globals.shmID, errno = C.shmget(globals.shmKey, globals.shmSize, C.IPC_CREAT|sharedMemoryObjectPermissions) 237 238 if C.int(-1) == globals.shmID { 239 globals.eventLogEnabled = false 240 err = fmt.Errorf("C.shmget(globals.shmKey, globals.shmSize, C.IPC_CREAT) failed with errno: %v", errno) 241 return 242 } 243 244 globals.shmAddr = C.shmat_returning_uintptr(globals.shmID, C.uintptr_t(0), C.int(0)) 245 246 if ^C.uintptr_t(0) == globals.shmAddr { 247 globals.eventLogEnabled = false 248 rmidResult = C.shmctl(globals.shmID, C.IPC_RMID, nil) 249 if C.int(-1) == rmidResult { 250 err = fmt.Errorf("C.shmat_returning_uintptr(globals.shmID, C.uintptr_t(0), C.int(0)) then C.shmctl(globals.shmID, C.IPC_RMID, nil) failed") 251 return 252 } 253 err = fmt.Errorf("C.shmat_returning_uintptr(globals.shmID, C.uintptr_t(0), C.int(0)) failed") 254 return 255 } 256 257 globals.eventLogEnabled = true 258 259 err = nil 260 return 261 } 262 263 func disableLogging() (err error) { 264 var ( 265 shmdtErrnoReturn syscall.Errno 266 shmdtIntReturn C.int 267 ) 268 269 globals.eventLogEnabled = false 270 271 shmdtIntReturn = C.shmdt_returning_errno(globals.shmAddr) 272 if C.int(0) != shmdtIntReturn { 273 shmdtErrnoReturn = syscall.Errno(shmdtIntReturn) 274 err = fmt.Errorf("C.shmdt() returned non-zero failure... errno: %v", shmdtErrnoReturn.Error()) 275 return 276 } 277 278 err = nil 279 return 280 }