drivers/base/devcoredump.c
Source file repositories/reference/linux-study-clean/drivers/base/devcoredump.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/base/devcoredump.c- Extension
.c- Size
- 13935 bytes
- Lines
- 474
- Domain
- Driver Families
- Bucket
- drivers/base
- Inferred role
- Driver Families: exported/initcall integration point
- Status
- integration implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Exports symbols or registers init work; inspect boot/module ordering and who consumes the exported contract.
- 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/device.hlinux/devcoredump.hlinux/list.hlinux/slab.hlinux/fs.hlinux/workqueue.h
Detected Declarations
struct devcd_entryfunction device_addfunction devcd_dev_releasefunction __devcd_delfunction devcd_delfunction devcd_data_readfunction devcd_data_writefunction devcd_freefunction disabled_showfunction disabled_storefunction devcd_readvfunction devcd_freevfunction dev_coredumpvfunction devcd_match_failingfunction devcd_free_sgtablefunction devcd_read_from_sgtablefunction dev_coredump_putfunction dev_coredumpm_timeoutfunction dev_coredumpsgfunction devcoredump_initexport dev_coredumpvexport dev_coredump_putexport dev_coredumpm_timeoutexport dev_coredumpsg
Annotated Snippet
* To solve this, hold the mutex during device_add(), and set
* init_completed on success before releasing the mutex.
*
* That way the timer will never fire until device_add() is called,
* it will do nothing if init_completed is not set. The timer is also
* cancelled in that case.
*
* The second race involves multiple parallel invocations of devcd_free(),
* add a deleted flag so only 1 can call the destructor.
*/
struct mutex mutex;
bool init_completed, deleted;
struct module *owner;
ssize_t (*read)(char *buffer, loff_t offset, size_t count,
void *data, size_t datalen);
void (*free)(void *data);
/*
* If nothing interferes and device_add() was returns success,
* del_wk will destroy the device after the timer fires.
*
* Multiple userspace processes can interfere in the working of the timer:
* - Writing to the coredump will reschedule the timer to run immediately,
* if still armed.
*
* This is handled by using "if (cancel_delayed_work()) {
* schedule_delayed_work() }", to prevent re-arming after having
* been previously fired.
* - Writing to /sys/class/devcoredump/disabled will destroy the
* coredump synchronously.
* This is handled by using disable_delayed_work_sync(), and then
* checking if deleted flag is set with &devcd->mutex held.
*/
struct delayed_work del_wk;
struct device *failing_dev;
};
static struct devcd_entry *dev_to_devcd(struct device *dev)
{
return container_of(dev, struct devcd_entry, devcd_dev);
}
static void devcd_dev_release(struct device *dev)
{
struct devcd_entry *devcd = dev_to_devcd(dev);
devcd->free(devcd->data);
module_put(devcd->owner);
/*
* this seems racy, but I don't see a notifier or such on
* a struct device to know when it goes away?
*/
if (devcd->failing_dev->kobj.sd)
sysfs_delete_link(&devcd->failing_dev->kobj, &dev->kobj,
"devcoredump");
put_device(devcd->failing_dev);
kfree(devcd);
}
static void __devcd_del(struct devcd_entry *devcd)
{
devcd->deleted = true;
device_del(&devcd->devcd_dev);
put_device(&devcd->devcd_dev);
}
static void devcd_del(struct work_struct *wk)
{
struct devcd_entry *devcd;
bool init_completed;
devcd = container_of(wk, struct devcd_entry, del_wk.work);
/* devcd->mutex serializes against dev_coredumpm_timeout */
mutex_lock(&devcd->mutex);
init_completed = devcd->init_completed;
mutex_unlock(&devcd->mutex);
if (init_completed)
__devcd_del(devcd);
}
static ssize_t devcd_data_read(struct file *filp, struct kobject *kobj,
const struct bin_attribute *bin_attr,
char *buffer, loff_t offset, size_t count)
{
struct device *dev = kobj_to_dev(kobj);
struct devcd_entry *devcd = dev_to_devcd(dev);
Annotation
- Immediate include surface: `linux/module.h`, `linux/device.h`, `linux/devcoredump.h`, `linux/list.h`, `linux/slab.h`, `linux/fs.h`, `linux/workqueue.h`.
- Detected declarations: `struct devcd_entry`, `function device_add`, `function devcd_dev_release`, `function __devcd_del`, `function devcd_del`, `function devcd_data_read`, `function devcd_data_write`, `function devcd_free`, `function disabled_show`, `function disabled_store`.
- Atlas domain: Driver Families / drivers/base.
- Implementation status: integration 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.