summaryrefslogtreecommitdiffstats
path: root/LOCKS
diff options
context:
space:
mode:
authorFrederic Robra2019-06-25 17:03:28 +0200
committerFrederic Robra2019-06-25 17:03:28 +0200
commit43e57ce5e11e9052f5a7db66f2e8613f1784f919 (patch)
treec5e1372a160b2601f61b18d617b71799b06b02ae /LOCKS
downloaddnbd3-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--LOCKS80
1 files changed, 80 insertions, 0 deletions
diff --git a/LOCKS b/LOCKS
new file mode 100644
index 0000000..935dadb
--- /dev/null
+++ b/LOCKS
@@ -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);
+