diff options
author | Frederic Robra | 2019-06-25 17:03:28 +0200 |
---|---|---|
committer | Frederic Robra | 2019-06-25 17:03:28 +0200 |
commit | 43e57ce5e11e9052f5a7db66f2e8613f1784f919 (patch) | |
tree | c5e1372a160b2601f61b18d617b71799b06b02ae /LOCKS | |
download | dnbd3-ng-43e57ce5e11e9052f5a7db66f2e8613f1784f919.tar.gz dnbd3-ng-43e57ce5e11e9052f5a7db66f2e8613f1784f919.tar.xz dnbd3-ng-43e57ce5e11e9052f5a7db66f2e8613f1784f919.zip |
first version of dnbd3-ng
Diffstat (limited to 'LOCKS')
-rw-r--r-- | LOCKS | 80 |
1 files changed, 80 insertions, 0 deletions
@@ -0,0 +1,80 @@ +Some notes about locking in dnbd3 + +The order of aquiring multiple locks is +VERY IMPORTANT, as you'll produce a possible deadlock +if you do it in the wrong order. +Take very good care of locking order if you have lots +of functions that call each other. You might lose +track of what's going on. ;) + +===== FUSE ===== +mutexInit +newAltLock +altLock +connection.sendMutex +requests.lock + +===== SERVER ===== +This is a list of used locks, in the order they +have to be aquired if you must hold multiple locks: +remoteCloneLock | reloadLock +_clients_lock +_clients[].lock +integrityQueueLock +_images_lock +_images[].lock +pendingLockConsume +pendingLockProduce +uplink.queueLock +altServersLock +client.sendMutex +client.statsLock +statisticsSentLock +statisticsReceivedLock +uplink.rttLock + +If you need to lock multiple clients/images/... at once, +lock the client with the lowest array index first. + +If the program logic would require to aquire the +locks in a different order, you HAVE TO rework the +code. +For example, if you hold the lock for client 10 and +you need to look up some other client. You MUST NOT +simply fetch the _clients_lock now and then iterate +over the clients until you find the one you need, +as it violates the above order to first lock on the +clients array and then the clients lock. +Instead, you need to release client 10's lock, +then lock on _clients_lock and iterate over the +clients. Now you check if you either encounter +the client you originally held the lock on, or +the client you are looking for. You immediately +lock on those two. You can then release the +_clients_lock and work with both clients. +pseudo code: + +// client10 is assumed to be a pointer to +// a client, which happens to be at index 10 +lock (client10->lock); +.... +// oh, i need another client +unlock(client10->lock); +lock(_clients_lock); +client clientA = NULL, clientB = NULL; +for (i = 0; i < _num_clients; ++i) { + if (client[i] == client10) { + clientA = client[i]; + lock(clientA.lock); + } else if (client[i].something == <whatever>) { + clientB = client[i]; + lock(clientB.lock); + } +} +unlock(_clients_lock); +if (clientA && clientB) { // Make sure we actually found both! + // DO something important with both clients +} +if (clientA) unlock(clientA.lock); +if (clientB) unlock(clientB.lock); + |