summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2010-02-15 16:57:16 +0100
committerVolker Lendecke <vl@samba.org>2010-02-16 13:21:10 +0100
commit07978bd175395e0dc770f68fff5b8bd8b0fdeb51 (patch)
tree82eb86cf2e0c3bc2ff70815bd9262df291146caf
parentf3bdb163f461175c50b4930fa3464beaee30f4a8 (diff)
downloadsamba-07978bd175395e0dc770f68fff5b8bd8b0fdeb51.tar.gz
samba-07978bd175395e0dc770f68fff5b8bd8b0fdeb51.tar.bz2
samba-07978bd175395e0dc770f68fff5b8bd8b0fdeb51.zip
s3: Optimize g_lock_lock for a heavily contended case
Only check the existence of the lock owner in g_lock_parse, check the rest of the records only when we got the lock successfully. This reduces the load on process_exists which can involve a network roundtrip in the clustered case.
-rw-r--r--source3/lib/g_lock.c39
1 files changed, 36 insertions, 3 deletions
diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c
index 42c0397189..e2620255d9 100644
--- a/source3/lib/g_lock.c
+++ b/source3/lib/g_lock.c
@@ -108,6 +108,34 @@ static bool g_lock_parse(TALLOC_CTX *mem_ctx, TDB_DATA data,
(locks[i].lock_type & G_LOCK_PENDING) ?
"(pending)" : "(owner)"));
+ if (((locks[i].lock_type & G_LOCK_PENDING) == 0)
+ && !process_exists(locks[i].pid)) {
+
+ DEBUGADD(10, ("lock owner %s died -- discarding\n",
+ procid_str(talloc_tos(),
+ &locks[i].pid)));
+
+ if (i < (num_locks-1)) {
+ locks[i] = locks[num_locks-1];
+ }
+ num_locks -= 1;
+ }
+ }
+
+ *plocks = locks;
+ *pnum_locks = num_locks;
+ return true;
+}
+
+static void g_lock_cleanup(int *pnum_locks, struct g_lock_rec *locks)
+{
+ int i, num_locks;
+
+ num_locks = *pnum_locks;
+
+ DEBUG(10, ("g_lock_cleanup: %d locks\n", num_locks));
+
+ for (i=0; i<num_locks; i++) {
if (process_exists(locks[i].pid)) {
continue;
}
@@ -119,10 +147,8 @@ static bool g_lock_parse(TALLOC_CTX *mem_ctx, TDB_DATA data,
}
num_locks -= 1;
}
-
- *plocks = locks;
*pnum_locks = num_locks;
- return true;
+ return;
}
static struct g_lock_rec *g_lock_addrec(TALLOC_CTX *mem_ctx,
@@ -239,6 +265,13 @@ again:
locks[our_index].lock_type = lock_type;
}
+ if (NT_STATUS_IS_OK(status) && ((lock_type & G_LOCK_PENDING) == 0)) {
+ /*
+ * Walk through the list of locks, search for dead entries
+ */
+ g_lock_cleanup(&num_locks, locks);
+ }
+
data = make_tdb_data((uint8_t *)locks, num_locks * sizeof(*locks));
store_status = rec->store(rec, data, 0);
if (!NT_STATUS_IS_OK(store_status)) {