mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 04:34:03 +02:00
module/dups: Avoid unnecessary kmod_dup_req allocations
The kmod dups code preallocates kmod_dup_req before taking kmod_dup_mutex to avoid allocating memory while holding the lock. This provides little benefit, since the allocation is fast and can safely be done under the lock. On the other hand, it leads to unnecessary allocations when the request turns out to be a duplicate and slightly complicates the code. Allocate kmod_dup_req only when needed and introduce a helper function alloc_kmod_req() to initialize the structure. Reviewed-by: Aaron Tomlin <atomlin@atomlin.com> Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
This commit is contained in:
parent
5eecb11b54
commit
96e6f752fc
|
|
@ -104,28 +104,31 @@ static void kmod_dup_request_delete(struct work_struct *work)
|
|||
put_kmod_req(kmod_req);
|
||||
}
|
||||
|
||||
static struct kmod_dup_req *alloc_kmod_req(const char *module_name)
|
||||
{
|
||||
struct kmod_dup_req *kmod_req = kzalloc_obj(*kmod_req);
|
||||
|
||||
if (!kmod_req)
|
||||
return NULL;
|
||||
|
||||
refcount_set(&kmod_req->refcount, 1);
|
||||
strscpy(kmod_req->name, module_name);
|
||||
INIT_DELAYED_WORK(&kmod_req->delete_work, kmod_dup_request_delete);
|
||||
init_completion(&kmod_req->first_req_done);
|
||||
return kmod_req;
|
||||
}
|
||||
|
||||
bool kmod_dup_request_exists_wait(char *module_name, bool wait, int *dup_ret)
|
||||
{
|
||||
struct kmod_dup_req *kmod_req, *new_kmod_req;
|
||||
struct kmod_dup_req *kmod_req;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Pre-allocate the entry in case we have to use it later
|
||||
* to avoid contention with the mutex.
|
||||
*/
|
||||
new_kmod_req = kzalloc_obj(*new_kmod_req);
|
||||
if (!new_kmod_req)
|
||||
return false;
|
||||
|
||||
refcount_set(&new_kmod_req->refcount, 1);
|
||||
strscpy(new_kmod_req->name, module_name);
|
||||
INIT_DELAYED_WORK(&new_kmod_req->delete_work, kmod_dup_request_delete);
|
||||
init_completion(&new_kmod_req->first_req_done);
|
||||
|
||||
mutex_lock(&kmod_dup_mutex);
|
||||
|
||||
kmod_req = kmod_dup_request_lookup(module_name);
|
||||
if (!kmod_req) {
|
||||
struct kmod_dup_req *new_kmod_req;
|
||||
|
||||
/*
|
||||
* If the first request that came through for a module
|
||||
* was with request_module_nowait() we cannot wait for it
|
||||
|
|
@ -138,7 +141,6 @@ bool kmod_dup_request_exists_wait(char *module_name, bool wait, int *dup_ret)
|
|||
* would benefit from duplicate detection.
|
||||
*/
|
||||
if (!wait) {
|
||||
kfree(new_kmod_req);
|
||||
pr_debug("New request_module_nowait() for %s -- cannot track duplicates for this request\n", module_name);
|
||||
mutex_unlock(&kmod_dup_mutex);
|
||||
return false;
|
||||
|
|
@ -149,6 +151,11 @@ bool kmod_dup_request_exists_wait(char *module_name, bool wait, int *dup_ret)
|
|||
* keep tab on duplicates later.
|
||||
*/
|
||||
pr_debug("New request_module() for %s\n", module_name);
|
||||
new_kmod_req = alloc_kmod_req(module_name);
|
||||
if (!new_kmod_req) {
|
||||
mutex_unlock(&kmod_dup_mutex);
|
||||
return false;
|
||||
}
|
||||
list_add(&new_kmod_req->list, &dup_kmod_reqs);
|
||||
mutex_unlock(&kmod_dup_mutex);
|
||||
return false;
|
||||
|
|
@ -158,7 +165,6 @@ bool kmod_dup_request_exists_wait(char *module_name, bool wait, int *dup_ret)
|
|||
mutex_unlock(&kmod_dup_mutex);
|
||||
|
||||
/* We are dealing with a duplicate request now */
|
||||
kfree(new_kmod_req);
|
||||
|
||||
/*
|
||||
* To fix these try to use try_then_request_module() instead as that
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user