kernel/module/dups.c
Source file repositories/reference/linux-study-clean/kernel/module/dups.c
File Facts
- System
- Linux kernel
- Corpus path
kernel/module/dups.c- Extension
.c- Size
- 7687 bytes
- Lines
- 248
- Domain
- Core OS
- Bucket
- Scheduler, Processes, Timers, Sync, And Syscalls
- Inferred role
- Core OS: implementation source
- Status
- source implementation candidate
Why This File Exists
Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/module.hlinux/sched.hlinux/sched/task.hlinux/binfmts.hlinux/syscalls.hlinux/unistd.hlinux/kmod.hlinux/slab.hlinux/completion.hlinux/cred.hlinux/file.hlinux/workqueue.hlinux/security.hlinux/mount.hlinux/kernel.hlinux/init.hlinux/resource.hlinux/notifier.hlinux/suspend.hlinux/rwsem.hlinux/ptrace.hlinux/async.hlinux/uaccess.hinternal.h
Detected Declarations
struct kmod_dup_reqfunction list_for_each_entry_rcufunction kmod_dup_request_deletefunction kmod_dup_request_completefunction kmod_dup_request_exists_waitfunction request_module_nowaitfunction kmod_dup_request_announce
Annotated Snippet
struct kmod_dup_req {
struct list_head list;
char name[MODULE_NAME_LEN];
struct completion first_req_done;
struct work_struct complete_work;
struct delayed_work delete_work;
int dup_ret;
};
static struct kmod_dup_req *kmod_dup_request_lookup(char *module_name)
{
struct kmod_dup_req *kmod_req;
list_for_each_entry_rcu(kmod_req, &dup_kmod_reqs, list,
lockdep_is_held(&kmod_dup_mutex)) {
if (strlen(kmod_req->name) == strlen(module_name) &&
!memcmp(kmod_req->name, module_name, strlen(module_name))) {
return kmod_req;
}
}
return NULL;
}
static void kmod_dup_request_delete(struct work_struct *work)
{
struct kmod_dup_req *kmod_req;
kmod_req = container_of(to_delayed_work(work), struct kmod_dup_req, delete_work);
/*
* The typical situation is a module successully loaded. In that
* situation the module will be present already in userspace. If
* new requests come in after that, userspace will already know the
* module is loaded so will just return 0 right away. There is still
* a small chance right after we delete this entry new request_module()
* calls may happen after that, they can happen. These heuristics
* are to protect finit_module() abuse for auto-loading, if modules
* are still tryign to auto-load even if a module is already loaded,
* that's on them, and those inneficiencies should not be fixed by
* kmod. The inneficies there are a call to modprobe and modprobe
* just returning 0.
*/
mutex_lock(&kmod_dup_mutex);
list_del_rcu(&kmod_req->list);
synchronize_rcu();
mutex_unlock(&kmod_dup_mutex);
kfree(kmod_req);
}
static void kmod_dup_request_complete(struct work_struct *work)
{
struct kmod_dup_req *kmod_req;
kmod_req = container_of(work, struct kmod_dup_req, complete_work);
/*
* This will ensure that the kernel will let all the waiters get
* informed its time to check the return value. It's time to
* go home.
*/
complete_all(&kmod_req->first_req_done);
/*
* Now that we have allowed prior request_module() calls to go on
* with life, let's schedule deleting this entry. We don't have
* to do it right away, but we *eventually* want to do it so to not
* let this linger forever as this is just a boot optimization for
* possible abuses of vmalloc() incurred by finit_module() thrashing.
*/
queue_delayed_work(system_dfl_wq, &kmod_req->delete_work, 60 * HZ);
}
bool kmod_dup_request_exists_wait(char *module_name, bool wait, int *dup_ret)
{
struct kmod_dup_req *kmod_req, *new_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;
memcpy(new_kmod_req->name, module_name, strlen(module_name));
INIT_WORK(&new_kmod_req->complete_work, kmod_dup_request_complete);
INIT_DELAYED_WORK(&new_kmod_req->delete_work, kmod_dup_request_delete);
init_completion(&new_kmod_req->first_req_done);
Annotation
- Immediate include surface: `linux/module.h`, `linux/sched.h`, `linux/sched/task.h`, `linux/binfmts.h`, `linux/syscalls.h`, `linux/unistd.h`, `linux/kmod.h`, `linux/slab.h`.
- Detected declarations: `struct kmod_dup_req`, `function list_for_each_entry_rcu`, `function kmod_dup_request_delete`, `function kmod_dup_request_complete`, `function kmod_dup_request_exists_wait`, `function request_module_nowait`, `function kmod_dup_request_announce`.
- Atlas domain: Core OS / Scheduler, Processes, Timers, Sync, And Syscalls.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.