fs/proc/vmcore.c

Source file repositories/reference/linux-study-clean/fs/proc/vmcore.c

File Facts

System
Linux kernel
Corpus path
fs/proc/vmcore.c
Extension
.c
Size
46258 bytes
Lines
1757
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct vmcoredd_node {
	struct list_head list;	/* List of dumps */
	void *buf;		/* Buffer containing device's dump */
	unsigned int size;	/* Size of the buffer */
};

/* Device Dump list and mutex to synchronize access to list */
static LIST_HEAD(vmcoredd_list);

static bool vmcoredd_disabled;
core_param(novmcoredd, vmcoredd_disabled, bool, 0);
#endif /* CONFIG_PROC_VMCORE_DEVICE_DUMP */

/* Device Dump Size */
static size_t vmcoredd_orig_sz;

static DEFINE_MUTEX(vmcore_mutex);

DEFINE_STATIC_SRCU(vmcore_cb_srcu);
/* List of registered vmcore callbacks. */
static LIST_HEAD(vmcore_cb_list);
/* Whether the vmcore has been opened once. */
static bool vmcore_opened;
/* Whether the vmcore is currently open. */
static unsigned int vmcore_open;

static void vmcore_process_device_ram(struct vmcore_cb *cb);

void register_vmcore_cb(struct vmcore_cb *cb)
{
	INIT_LIST_HEAD(&cb->next);
	mutex_lock(&vmcore_mutex);
	list_add_tail(&cb->next, &vmcore_cb_list);
	/*
	 * Registering a vmcore callback after the vmcore was opened is
	 * very unusual (e.g., manual driver loading).
	 */
	if (vmcore_opened)
		pr_warn_once("Unexpected vmcore callback registration\n");
	if (!vmcore_open && cb->get_device_ram)
		vmcore_process_device_ram(cb);
	mutex_unlock(&vmcore_mutex);
}
EXPORT_SYMBOL_GPL(register_vmcore_cb);

void unregister_vmcore_cb(struct vmcore_cb *cb)
{
	mutex_lock(&vmcore_mutex);
	list_del_rcu(&cb->next);
	/*
	 * Unregistering a vmcore callback after the vmcore was opened is
	 * very unusual (e.g., forced driver removal), but we cannot stop
	 * unregistering.
	 */
	if (vmcore_opened)
		pr_warn_once("Unexpected vmcore callback unregistration\n");
	mutex_unlock(&vmcore_mutex);

	synchronize_srcu(&vmcore_cb_srcu);
}
EXPORT_SYMBOL_GPL(unregister_vmcore_cb);

static bool pfn_is_ram(unsigned long pfn)
{
	struct vmcore_cb *cb;
	bool ret = true;

	list_for_each_entry_srcu(cb, &vmcore_cb_list, next,
				 srcu_read_lock_held(&vmcore_cb_srcu)) {
		if (unlikely(!cb->pfn_is_ram))
			continue;
		ret = cb->pfn_is_ram(cb, pfn);
		if (!ret)
			break;
	}

	return ret;
}

static int open_vmcore(struct inode *inode, struct file *file)
{
	mutex_lock(&vmcore_mutex);
	vmcore_opened = true;
	if (vmcore_open + 1 == 0) {
		mutex_unlock(&vmcore_mutex);
		return -EBUSY;
	}
	vmcore_open++;
	mutex_unlock(&vmcore_mutex);

Annotation

Implementation Notes