s3: Optimize g_lock_lock for a heavily contended case
authorVolker Lendecke <vl@samba.org>
Mon, 15 Feb 2010 15:57:16 +0000 (16:57 +0100)
committerVolker Lendecke <vl@samba.org>
Tue, 16 Feb 2010 12:21:10 +0000 (13:21 +0100)
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.

source3/lib/g_lock.c

index 42c0397189d707154376f2db6995a379cf565523..e2620255d9c00b13f21e5fd995b64a3629dde355 100644 (file)
@@ -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)) {