All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rusty Russell <rusty@rustcorp.com.au>
To: Kay Sievers <kay.sievers@vrfy.org>
Cc: Andreas Robinson <andr345@gmail.com>,
	sam@ravnborg.org, linux-kernel@vger.kernel.org,
	Jon Masters <jonathan@jonmasters.org>,
	heiko.carstens@de.ibm.com
Subject: Re: [RFC PATCH 0/6] module, kbuild: Faster boot with custom kernel.
Date: Wed, 25 Feb 2009 17:33:56 +1030	[thread overview]
Message-ID: <200902251733.57069.rusty@rustcorp.com.au> (raw)
In-Reply-To: <ac3eb2510902230842n278503a7w33d5ac2e622ec711@mail.gmail.com>

On Tuesday 24 February 2009 03:12:28 Kay Sievers wrote:
> Rusty,
> are you taking care, that this patch gets merged somewhere, and shows
> up in -next?

Yep, already done.

> I still get a ~10% improvement without the mutex, and traces show some
> parallelism from different modprobe processes. Any idea how to safely
> minimize the time we need to hold it?

OK, let's do that then.

<hack hack>

Here's a backported version which you should be able to simply apply; it'll
be good to check that we still win...

Thanks!
Rusty.

diff --git a/kernel/module.c b/kernel/module.c
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -75,7 +75,8 @@ static DECLARE_WAIT_QUEUE_HEAD(module_wq
 
 static BLOCKING_NOTIFIER_HEAD(module_notify_list);
 
-/* Bounds of module allocation, for speeding __module_text_address */
+/* Bounds of module allocation, for speeding __module_address.
+ * Protected by module_mutex. */
 static unsigned long module_addr_min = -1UL, module_addr_max = 0;
 
 int register_module_notifier(struct notifier_block * nb)
@@ -328,7 +329,7 @@ static bool find_symbol_in_section(const
 }
 
 /* Find a symbol, return value, (optional) crc and (optional) module
- * which owns it */
+ * which owns it.  Needs preempt disabled or module_mutex. */
 static unsigned long find_symbol(const char *name,
 				 struct module **owner,
 				 const unsigned long **crc,
@@ -408,8 +409,9 @@ static void *percpu_modalloc(unsigned lo
 {
 	unsigned long extra;
 	unsigned int i;
-	void *ptr;
+	void *ptr = NULL;
 
+	mutex_lock(&module_mutex);
 	if (align > PAGE_SIZE) {
 		printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n",
 		       name, align, PAGE_SIZE);
@@ -434,24 +436,32 @@ static void *percpu_modalloc(unsigned lo
 		ptr += extra;
 
 		/* Split block if warranted */
-		if (pcpu_size[i] - size > sizeof(unsigned long))
-			if (!split_block(i, size))
-				return NULL;
+		if (pcpu_size[i] - size > sizeof(unsigned long)) {
+			if (!split_block(i, size)) {
+				ptr = NULL;
+				break;
+			}
+		}
 
 		/* Mark allocated */
 		pcpu_size[i] = -pcpu_size[i];
-		return ptr;
+		break;
 	}
+	mutex_unlock(&module_mutex);
 
-	printk(KERN_WARNING "Could not allocate %lu bytes percpu data\n",
-	       size);
-	return NULL;
+	if (!ptr)
+		printk(KERN_WARNING
+		       "Could not allocate %lu bytes percpu data\n", size);
+	return ptr;
 }
 
 static void percpu_modfree(void *freeme)
 {
 	unsigned int i;
-	void *ptr = __per_cpu_start + block_size(pcpu_size[0]);
+	void *ptr;
+
+	mutex_lock(&module_mutex);
+	ptr = __per_cpu_start + block_size(pcpu_size[0]);
 
 	/* First entry is core kernel percpu data. */
 	for (i = 1; i < pcpu_num_used; ptr += block_size(pcpu_size[i]), i++) {
@@ -478,6 +488,7 @@ static void percpu_modfree(void *freeme)
 		memmove(&pcpu_size[i+1], &pcpu_size[i+2],
 			(pcpu_num_used - (i+1)) * sizeof(pcpu_size[0]));
 	}
+	mutex_unlock(&module_mutex);
 }
 
 static unsigned int find_pcpusec(Elf_Ehdr *hdr,
@@ -606,7 +617,7 @@ static int already_uses(struct module *a
 	return 0;
 }
 
-/* Module a uses b */
+/* Module a uses b: caller needs module_mutex() */
 static int use_module(struct module *a, struct module *b)
 {
 	struct module_use *use;
@@ -646,6 +657,7 @@ static void module_unload_free(struct mo
 {
 	struct module *i;
 
+	mutex_lock(&module_mutex);
 	list_for_each_entry(i, &modules, list) {
 		struct module_use *use;
 
@@ -661,6 +673,7 @@ static void module_unload_free(struct mo
 			}
 		}
 	}
+	mutex_unlock(&module_mutex);
 }
 
 #ifdef CONFIG_MODULE_FORCE_UNLOAD
@@ -823,9 +836,13 @@ SYSCALL_DEFINE2(delete_module, const cha
 	/* Store the name of the last unloaded module for diagnostic purposes */
 	strlcpy(last_unloaded_module, mod->name, sizeof(last_unloaded_module));
 	unregister_dynamic_debug_module(mod->name);
+
+	/* free_module doesn't want module_mutex held by caller. */
+	mutex_unlock(&module_mutex);
 	free_module(mod);
+	goto out_stop;
 
- out:
+out:
 	mutex_unlock(&module_mutex);
 out_stop:
 	stop_machine_destroy();
@@ -1062,8 +1079,7 @@ static inline int same_magic(const char 
 }
 #endif /* CONFIG_MODVERSIONS */
 
-/* Resolve a symbol for this module.  I.e. if we find one, record usage.
-   Must be holding module_mutex. */
+/* Resolve a symbol for this module.  I.e. if we find one, record usage. */
 static unsigned long resolve_symbol(Elf_Shdr *sechdrs,
 				    unsigned int versindex,
 				    const char *name,
@@ -1073,6 +1089,7 @@ static unsigned long resolve_symbol(Elf_
 	unsigned long ret;
 	const unsigned long *crc;
 
+	mutex_lock(&module_mutex);
 	ret = find_symbol(name, &owner, &crc,
 			  !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true);
 	if (!IS_ERR_VALUE(ret)) {
@@ -1082,6 +1099,7 @@ static unsigned long resolve_symbol(Elf_
 		    !use_module(mod, owner))
 			ret = -EINVAL;
 	}
+	mutex_unlock(&module_mutex);
 	return ret;
 }
 
@@ -1442,11 +1460,14 @@ static int __unlink_module(void *_mod)
 	return 0;
 }
 
-/* Free a module, remove from lists, etc (must hold module_mutex). */
+/* Free a module, remove from lists, etc. */
 static void free_module(struct module *mod)
 {
 	/* Delete from various lists */
+	mutex_lock(&module_mutex);	
 	stop_machine(__unlink_module, mod, NULL);
+	mutex_unlock(&module_mutex);
+
 	remove_notes_attrs(mod);
 	remove_sect_attrs(mod);
 	mod_kobject_remove(mod);
@@ -1520,14 +1541,19 @@ static int verify_export_symbols(struct 
 
 	for (i = 0; i < ARRAY_SIZE(arr); i++) {
 		for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) {
+
+			/* Stopping preemption makes find_symbol safe. */
+			preempt_disable();
 			if (!IS_ERR_VALUE(find_symbol(s->name, &owner,
 						      NULL, true, false))) {
+				preempt_enable();
 				printk(KERN_ERR
 				       "%s: exports duplicate symbol %s"
 				       " (owned by %s)\n",
 				       mod->name, s->name, module_name(owner));
 				return -ENOEXEC;
 			}
+			preempt_enable();
 		}
 	}
 	return 0;
@@ -1850,11 +1876,13 @@ static void *module_alloc_update_bounds(
 	void *ret = module_alloc(size);
 
 	if (ret) {
+		mutex_lock(&module_mutex);
 		/* Update module bounds. */
 		if ((unsigned long)ret < module_addr_min)
 			module_addr_min = (unsigned long)ret;
 		if ((unsigned long)ret + size > module_addr_max)
 			module_addr_max = (unsigned long)ret + size;
+		mutex_unlock(&module_mutex);
 	}
 	return ret;
 }
@@ -2256,7 +2284,9 @@ static noinline struct module *load_modu
 	 * function to insert in a way safe to concurrent readers.
 	 * The mutex protects against concurrent writers.
 	 */
+	mutex_lock(&module_mutex);
 	list_add_rcu(&mod->list, &modules);
+	mutex_unlock(&module_mutex);
 
 	err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp, NULL);
 	if (err < 0)
@@ -2275,8 +2305,10 @@ static noinline struct module *load_modu
 	return mod;
 
  unlink:
+	mutex_lock(&module_mutex);
 	/* Unlink carefully: kallsyms could be walking list. */
 	list_del_rcu(&mod->list);
+	mutex_unlock(&module_mutex);
 	synchronize_sched();
 	module_arch_cleanup(mod);
  cleanup:
@@ -2317,19 +2349,10 @@ SYSCALL_DEFINE3(init_module, void __user
 	if (!capable(CAP_SYS_MODULE))
 		return -EPERM;
 
-	/* Only one module load at a time, please */
-	if (mutex_lock_interruptible(&module_mutex) != 0)
-		return -EINTR;
-
 	/* Do all the hard work */
 	mod = load_module(umod, len, uargs);
-	if (IS_ERR(mod)) {
-		mutex_unlock(&module_mutex);
+	if (IS_ERR(mod))
 		return PTR_ERR(mod);
-	}
-
-	/* Drop lock so they can recurse */
-	mutex_unlock(&module_mutex);
 
 	blocking_notifier_call_chain(&module_notify_list,
 			MODULE_STATE_COMING, mod);
@@ -2345,9 +2368,7 @@ SYSCALL_DEFINE3(init_module, void __user
 		module_put(mod);
 		blocking_notifier_call_chain(&module_notify_list,
 					     MODULE_STATE_GOING, mod);
-		mutex_lock(&module_mutex);
 		free_module(mod);
-		mutex_unlock(&module_mutex);
 		wake_up(&module_wq);
 		return ret;
 	}
@@ -2366,14 +2387,15 @@ SYSCALL_DEFINE3(init_module, void __user
 	blocking_notifier_call_chain(&module_notify_list,
 				     MODULE_STATE_LIVE, mod);
 
-	mutex_lock(&module_mutex);
+	/* Be a little careful here: an oops may look at this mem right now. */
+	mod->init_size = 0;
+	mod->init_text_size = 0;
+	wmb();
+	module_free(mod, mod->module_init);
+	mod->module_init = NULL;
+
 	/* Drop initial reference. */
 	module_put(mod);
-	module_free(mod, mod->module_init);
-	mod->module_init = NULL;
-	mod->init_size = 0;
-	mod->init_text_size = 0;
-	mutex_unlock(&module_mutex);
 
 	return 0;
 }

  reply	other threads:[~2009-02-25  7:04 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-02-15 18:20 [RFC PATCH 0/6] module, kbuild: Faster boot with custom kernel Andreas Robinson
2009-02-15 18:20 ` [RFC PATCH 1/6] New option: Static linking of external modules Andreas Robinson
2009-02-15 18:20 ` [RFC PATCH 2/6] module: add module ELF section with module_init() pointer Andreas Robinson
2009-02-15 18:20 ` [RFC PATCH 3/6] module: always prefix module parameters with the module name Andreas Robinson
2009-02-15 18:20 ` [RFC PATCH 4/6] kbuild: allow linking of an external object into vmlinux Andreas Robinson
2009-02-15 18:20 ` [RFC PATCH 5/6] scripts: new module preprocessor for static linking Andreas Robinson
2009-02-15 18:20 ` [RFC PATCH 6/6] kbuild: enable relinking of vmlinux without full kernel tree Andreas Robinson
2009-02-16 22:51 ` [RFC PATCH 0/6] module, kbuild: Faster boot with custom kernel Rusty Russell
2009-02-17 10:42   ` Andreas Robinson
2009-02-17 11:53     ` Kay Sievers
2009-02-18  4:58       ` Rusty Russell
2009-02-18  9:15         ` Kay Sievers
2009-02-18 10:25           ` Andreas Robinson
2009-02-20  0:37             ` Andreas Robinson
2009-02-20  1:55               ` Kay Sievers
2009-02-21 11:43                 ` Andreas Robinson
2009-03-02 14:32                   ` Andreas Robinson
2009-03-02 15:59                     ` Kay Sievers
2009-03-02 16:20                     ` Arjan van de Ven
2009-03-02 16:29                       ` Kay Sievers
2009-03-02 18:27                         ` Arjan van de Ven
2009-03-02 21:41                           ` Andreas Robinson
2009-03-04 18:47                           ` Andreas Robinson
2009-03-06  0:18                             ` Arjan van de Ven
2009-03-06 15:15                               ` Andreas Robinson
2009-03-06 15:45                                 ` Arjan van de Ven
2009-03-08 10:47                                   ` Andreas Robinson
2009-03-08 16:01                                     ` Arjan van de Ven
2009-03-08 20:13                                       ` [PATCH] sata_nv: add a module parameter to enable async scanning Andreas Robinson
2009-03-09 17:12                                       ` [RFC PATCH 0/6] module, kbuild: Faster boot with custom kernel Will Newton
2009-03-06  7:05                       ` fastboot kernel parameter Sitsofe Wheeler
2009-03-06 11:23                         ` Arjan van de Ven
2009-02-24  1:27               ` [RFC PATCH 0/6] module, kbuild: Faster boot with custom kernel Rusty Russell
2009-02-18 11:57           ` Rusty Russell
2009-02-18 13:57             ` Kay Sievers
2009-02-19 11:15               ` Rusty Russell
2009-02-19 11:41                 ` Kay Sievers
2009-02-19 20:48                   ` Kay Sievers
2009-02-19 21:59                     ` Kay Sievers
2009-02-20  0:58                       ` Rusty Russell
2009-02-20  1:33                         ` Kay Sievers
2009-02-24  1:39                           ` Rusty Russell
2009-02-20 11:32                         ` Rusty Russell
2009-02-23 16:42                           ` Kay Sievers
2009-02-25  7:03                             ` Rusty Russell [this message]
2009-02-25 18:12                               ` Kay Sievers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200902251733.57069.rusty@rustcorp.com.au \
    --to=rusty@rustcorp.com.au \
    --cc=andr345@gmail.com \
    --cc=heiko.carstens@de.ibm.com \
    --cc=jonathan@jonmasters.org \
    --cc=kay.sievers@vrfy.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=sam@ravnborg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.