[systemd-devel] [PATCH 6/7] bus: call __kdbus_domain_user_account() and avoid an extra domain lock

Djalal Harouni tixxdz at opendz.org
Wed Jul 23 14:19:10 PDT 2014


kdbus_bus_new() worst case will take the domain lock 3 times:

kdbus_bus_new()
 => kdbus_domain_user_find_or_new(): will take it 2 times
+
kdbus_bus_new(): will take it an extra time to account the user and
link the bus into the domain bus_list.

We can reduce the worst case to take the domain lock 2 times by
replacing the kdbus_domain_user_find_or_new() with

kdbus_domain_user_find(): take the lock 1 time
kdbus_domain_user_new()
+
kdbus_bus_new(): take the lock 1 time and use the unlocked version
__kdbus_domain_user_account() to account the user.

Signed-off-by: Djalal Harouni <tixxdz at opendz.org>
---
 bus.c    | 21 +++++++++++++++++----
 domain.h | 12 ++++++++++++
 2 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/bus.c b/bus.c
index c329bef..77adf25 100644
--- a/bus.c
+++ b/bus.c
@@ -219,6 +219,7 @@ int kdbus_bus_new(struct kdbus_domain *domain,
 	struct kdbus_bus *b;
 	char prefix[16];
 	int ret;
+	bool new_user = false;
 
 	BUG_ON(*bus);
 
@@ -269,10 +270,15 @@ int kdbus_bus_new(struct kdbus_domain *domain,
 	if (ret < 0)
 		goto exit_free_reg;
 
-	/* account the bus against the user */
-	b->user = kdbus_domain_user_find_or_new(domain, uid);
-	if (IS_ERR(b->user)) {
-		ret = PTR_ERR(b->user);
+	/* account the bus against the user or create a new one */
+	b->user = kdbus_domain_user_find(domain, uid);
+	if (!b->user) {
+		b->user = kdbus_domain_user_new(domain, uid);
+		new_user = true;
+	}
+
+	if (!b->user) {
+		ret = -ENOMEM;
 		goto exit_ep_unref;
 	}
 
@@ -283,6 +289,13 @@ int kdbus_bus_new(struct kdbus_domain *domain,
 		goto exit_unref_user_unlock;
 	}
 
+	/* New user: account the bus against the user */
+	if (new_user) {
+		ret = __kdbus_domain_user_account(domain, b->user);
+		if (ret < 0)
+			goto exit_unref_user_unlock;
+	}
+
 	if (!capable(CAP_IPC_OWNER) &&
 	    atomic_inc_return(&b->user->buses) > KDBUS_USER_MAX_BUSES) {
 		atomic_dec(&b->user->buses);
diff --git a/domain.h b/domain.h
index 9c477db..b17e023 100644
--- a/domain.h
+++ b/domain.h
@@ -99,6 +99,18 @@ int kdbus_domain_new(struct kdbus_domain *parent, const char *name,
 int kdbus_domain_make_user(struct kdbus_cmd_make *cmd, char **name);
 struct kdbus_domain *kdbus_domain_find_by_major(unsigned int major);
 
+struct kdbus_domain_user *
+kdbus_domain_user_new(struct kdbus_domain *domain, kuid_t uid);
+
+struct kdbus_domain_user *
+kdbus_domain_user_find(struct kdbus_domain *domain, kuid_t uid);
+
+int __kdbus_domain_user_account(struct kdbus_domain *domain,
+				struct kdbus_domain_user *user);
+
+int kdbus_domain_user_account(struct kdbus_domain *domain,
+			      struct kdbus_domain_user *user);
+
 struct kdbus_domain_user
 *kdbus_domain_user_find_or_new(struct kdbus_domain *domain, kuid_t uid);
 struct kdbus_domain_user *kdbus_domain_user_ref(struct kdbus_domain_user *u);
-- 
1.9.3



More information about the systemd-devel mailing list