Release 4.11 fs/proc/kcore.c
/*
* fs/proc/kcore.c kernel ELF core dumper
*
* Modelled on fs/exec.c:aout_core_dump()
* Jeremy Fitzhardinge <jeremy@sw.oz.au>
* ELF version written by David Howells <David.Howells@nexor.co.uk>
* Modified and incorporated into 2.3.x by Tigran Aivazian <tigran@veritas.com>
* Support to dump vmalloc'd areas (ELF only), Tigran Aivazian <tigran@veritas.com>
* Safe accesses to vmalloc/direct-mapped discontiguous areas, Kanoj Sarcar <kanoj@sgi.com>
*/
#include <linux/mm.h>
#include <linux/proc_fs.h>
#include <linux/kcore.h>
#include <linux/user.h>
#include <linux/capability.h>
#include <linux/elf.h>
#include <linux/elfcore.h>
#include <linux/notifier.h>
#include <linux/vmalloc.h>
#include <linux/highmem.h>
#include <linux/printk.h>
#include <linux/bootmem.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <asm/io.h>
#include <linux/list.h>
#include <linux/ioport.h>
#include <linux/memory.h>
#include <linux/sched/task.h>
#include <asm/sections.h>
#include "internal.h"
#define CORE_STR "CORE"
#ifndef ELF_CORE_EFLAGS
#define ELF_CORE_EFLAGS 0
#endif
static struct proc_dir_entry *proc_root_kcore;
#ifndef kc_vaddr_to_offset
#define kc_vaddr_to_offset(v) ((v) - PAGE_OFFSET)
#endif
#ifndef kc_offset_to_vaddr
#define kc_offset_to_vaddr(o) ((o) + PAGE_OFFSET)
#endif
/* An ELF note in memory */
struct memelfnote
{
const char *name;
int type;
unsigned int datasz;
void *data;
};
static LIST_HEAD(kclist_head);
static DEFINE_RWLOCK(kclist_lock);
static int kcore_need_update = 1;
void
kclist_add(struct kcore_list *new, void *addr, size_t size, int type)
{
new->addr = (unsigned long)addr;
new->size = size;
new->type = type;
write_lock(&kclist_lock);
list_add_tail(&new->list, &kclist_head);
write_unlock(&kclist_lock);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Andrew Morton | 48 | 73.85% | 1 | 33.33% |
Kamezawa Hiroyuki | 17 | 26.15% | 2 | 66.67% |
Total | 65 | 100.00% | 3 | 100.00% |
static size_t get_kcore_size(int *nphdr, size_t *elf_buflen)
{
size_t try, size;
struct kcore_list *m;
*nphdr = 1; /* PT_NOTE */
size = 0;
list_for_each_entry(m, &kclist_head, list) {
try = kc_vaddr_to_offset((size_t)m->addr + m->size);
if (try > size)
size = try;
*nphdr = *nphdr + 1;
}
*elf_buflen = sizeof(struct elfhdr) +
(*nphdr + 2)*sizeof(struct elf_phdr) +
3 * ((sizeof(struct elf_note)) +
roundup(sizeof(CORE_STR), 4)) +
roundup(sizeof(struct elf_prstatus), 4) +
roundup(sizeof(struct elf_prpsinfo), 4) +
roundup(arch_task_struct_size, 4);
*elf_buflen = PAGE_ALIGN(*elf_buflen);
return size + *elf_buflen;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kamezawa Hiroyuki | 142 | 85.54% | 1 | 20.00% |
Linus Torvalds (pre-git) | 21 | 12.65% | 2 | 40.00% |
Andrew Morton | 2 | 1.20% | 1 | 20.00% |
Dave Hansen | 1 | 0.60% | 1 | 20.00% |
Total | 166 | 100.00% | 5 | 100.00% |
static void free_kclist_ents(struct list_head *head)
{
struct kcore_list *tmp, *pos;
list_for_each_entry_safe(pos, tmp, head, list) {
list_del(&pos->list);
kfree(pos);
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kamezawa Hiroyuki | 44 | 100.00% | 1 | 100.00% |
Total | 44 | 100.00% | 1 | 100.00% |
/*
* Replace all KCORE_RAM/KCORE_VMEMMAP information with passed list.
*/
static void __kcore_update_ram(struct list_head *list)
{
int nphdr;
size_t size;
struct kcore_list *tmp, *pos;
LIST_HEAD(garbage);
write_lock(&kclist_lock);
if (kcore_need_update) {
list_for_each_entry_safe(pos, tmp, &kclist_head, list) {
if (pos->type == KCORE_RAM
|| pos->type == KCORE_VMEMMAP)
list_move(&pos->list, &garbage);
}
list_splice_tail(list, &kclist_head);
} else
list_splice(list, &garbage);
kcore_need_update = 0;
proc_root_kcore->size = get_kcore_size(&nphdr, &size);
write_unlock(&kclist_lock);
free_kclist_ents(&garbage);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kamezawa Hiroyuki | 125 | 100.00% | 3 | 100.00% |
Total | 125 | 100.00% | 3 | 100.00% |
#ifdef CONFIG_HIGHMEM
/*
* If no highmem, we can assume [0...max_low_pfn) continuous range of memory
* because memory hole is not as big as !HIGHMEM case.
* (HIGHMEM is special because part of memory is _invisible_ from the kernel.)
*/
static int kcore_update_ram(void)
{
LIST_HEAD(head);
struct kcore_list *ent;
int ret = 0;
ent = kmalloc(sizeof(*ent), GFP_KERNEL);
if (!ent)
return -ENOMEM;
ent->addr = (unsigned long)__va(0);
ent->size = max_low_pfn << PAGE_SHIFT;
ent->type = KCORE_RAM;
list_add(&ent->list, &head);
__kcore_update_ram(&head);
return ret;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kamezawa Hiroyuki | 92 | 100.00% | 1 | 100.00% |
Total | 92 | 100.00% | 1 | 100.00% |
#else /* !CONFIG_HIGHMEM */
#ifdef CONFIG_SPARSEMEM_VMEMMAP
/* calculate vmemmap's address from given system ram pfn and register it */
static int
get_sparsemem_vmemmap_info(struct kcore_list *ent, struct list_head *head)
{
unsigned long pfn = __pa(ent->addr) >> PAGE_SHIFT;
unsigned long nr_pages = ent->size >> PAGE_SHIFT;
unsigned long start, end;
struct kcore_list *vmm, *tmp;
start = ((unsigned long)pfn_to_page(pfn)) & PAGE_MASK;
end = ((unsigned long)pfn_to_page(pfn + nr_pages)) - 1;
end = PAGE_ALIGN(end);
/* overlap check (because we have to align page */
list_for_each_entry(tmp, head, list) {
if (tmp->type != KCORE_VMEMMAP)
continue;
if (start < tmp->addr + tmp->size)
if (end > tmp->addr)
end = tmp->addr;
}
if (start < end) {
vmm = kmalloc(sizeof(*vmm), GFP_KERNEL);
if (!vmm)
return 0;
vmm->addr = start;
vmm->size = end - start;
vmm->type = KCORE_VMEMMAP;
list_add_tail(&vmm->list, head);
}
return 1;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kamezawa Hiroyuki | 198 | 99.00% | 1 | 33.33% |
Fabian Frederick | 1 | 0.50% | 1 | 33.33% |
Djalal Harouni | 1 | 0.50% | 1 | 33.33% |
Total | 200 | 100.00% | 3 | 100.00% |
#else
static int
get_sparsemem_vmemmap_info(struct kcore_list *ent, struct list_head *head)
{
return 1;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kamezawa Hiroyuki | 18 | 94.74% | 1 | 50.00% |
Djalal Harouni | 1 | 5.26% | 1 | 50.00% |
Total | 19 | 100.00% | 2 | 100.00% |
#endif
static int
kclist_add_private(unsigned long pfn, unsigned long nr_pages, void *arg)
{
struct list_head *head = (struct list_head *)arg;
struct kcore_list *ent;
ent = kmalloc(sizeof(*ent), GFP_KERNEL);
if (!ent)
return -ENOMEM;
ent->addr = (unsigned long)__va((pfn << PAGE_SHIFT));
ent->size = nr_pages << PAGE_SHIFT;
/* Sanity check: Can happen in 32bit arch...maybe */
if (ent->addr < (unsigned long) __va(0))
goto free_out;
/* cut not-mapped area. ....from ppc-32 code. */
if (ULONG_MAX - ent->addr < ent->size)
ent->size = ULONG_MAX - ent->addr;
/* cut when vmalloc() area is higher than direct-map area */
if (VMALLOC_START > (unsigned long)__va(0)) {
if (ent->addr > VMALLOC_START)
goto free_out;
if (VMALLOC_START - ent->addr < ent->size)
ent->size = VMALLOC_START - ent->addr;
}
ent->type = KCORE_RAM;
list_add_tail(&ent->list, head);
if (!get_sparsemem_vmemmap_info(ent, head)) {
list_del(&ent->list);
goto free_out;
}
return 0;
free_out:
kfree(ent);
return 1;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kamezawa Hiroyuki | 225 | 100.00% | 2 | 100.00% |
Total | 225 | 100.00% | 2 | 100.00% |
static int kcore_update_ram(void)
{
int nid, ret;
unsigned long end_pfn;
LIST_HEAD(head);
/* Not inialized....update now */
/* find out "max pfn" */
end_pfn = 0;
for_each_node_state(nid, N_MEMORY) {
unsigned long node_end;
node_end = node_end_pfn(nid);
if (end_pfn < node_end)
end_pfn = node_end;
}
/* scan 0 to max_pfn */
ret = walk_system_ram_range(0, end_pfn, &head, kclist_add_private);
if (ret) {
free_kclist_ents(&head);
return -ENOMEM;
}
__kcore_update_ram(&head);
return ret;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kamezawa Hiroyuki | 66 | 68.04% | 2 | 25.00% |
Linus Torvalds (pre-git) | 20 | 20.62% | 2 | 25.00% |
Magnus Damm | 6 | 6.19% | 1 | 12.50% |
Andrew Morton | 3 | 3.09% | 1 | 12.50% |
Lai Jiangshan | 1 | 1.03% | 1 | 12.50% |
Xishi Qiu | 1 | 1.03% | 1 | 12.50% |
Total | 97 | 100.00% | 8 | 100.00% |
#endif /* CONFIG_HIGHMEM */
/*****************************************************************************/
/*
* determine size of ELF note
*/
static int notesize(struct memelfnote *en)
{
int sz;
sz = sizeof(struct elf_note);
sz += roundup((strlen(en->name) + 1), 4);
sz += roundup(en->datasz, 4);
return sz;
} Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 50 | 92.59% | 1 | 50.00% |
Vivek Goyal | 4 | 7.41% | 1 | 50.00% |
Total | 54 | 100.00% | 2 | 100.00% |
/* end notesize() */
/*****************************************************************************/
/*
* store a note in the header buffer
*/
static char *storenote(struct memelfnote *men, char *bufp)
{
struct elf_note en;
#define DUMP_WRITE(addr,nr) do { memcpy(bufp,addr,nr); bufp += nr; } while(0)
en.n_namesz = strlen(men->name) + 1;
en.n_descsz = men->datasz;
en.n_type = men->type;
DUMP_WRITE(&en, sizeof(en));
DUMP_WRITE(men->name, en.n_namesz);
/* XXX - cast from long long to long to avoid need for libgcc.a */
bufp = (char*) roundup((unsigned long)bufp,4);
DUMP_WRITE(men->data, men->datasz);
bufp = (char*) roundup((unsigned long)bufp,4);
#undef DUMP_WRITE
return bufp;
} Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 130 | 98.48% | 1 | 50.00% |
Vivek Goyal | 2 | 1.52% | 1 | 50.00% |
Total | 132 | 100.00% | 2 | 100.00% |
/* end storenote() */
/*
* store an ELF coredump header in the supplied buffer
* nphdr is the number of elf_phdr to insert
*/
static void elf_kcore_store_hdr(char *bufp, int nphdr, int dataoff)
{
struct elf_prstatus prstatus; /* NT_PRSTATUS */
struct elf_prpsinfo prpsinfo; /* NT_PRPSINFO */
struct elf_phdr *nhdr, *phdr;
struct elfhdr *elf;
struct memelfnote notes[3];
off_t offset = 0;
struct kcore_list *m;
/* setup ELF header */
elf = (struct elfhdr *) bufp;
bufp += sizeof(struct elfhdr);
offset += sizeof(struct elfhdr);
memcpy(elf->e_ident, ELFMAG, SELFMAG);
elf->e_ident[EI_CLASS] = ELF_CLASS;
elf->e_ident[EI_DATA] = ELF_DATA;
elf->e_ident[EI_VERSION]= EV_CURRENT;
elf->e_ident[EI_OSABI] = ELF_OSABI;
memset(elf->e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
elf->e_type = ET_CORE;
elf->e_machine = ELF_ARCH;
elf->e_version = EV_CURRENT;
elf->e_entry = 0;
elf->e_phoff = sizeof(struct elfhdr);
elf->e_shoff = 0;
elf->e_flags = ELF_CORE_EFLAGS;
elf->e_ehsize = sizeof(struct elfhdr);
elf->e_phentsize= sizeof(struct elf_phdr);
elf->e_phnum = nphdr;
elf->e_shentsize= 0;
elf->e_shnum = 0;
elf->e_shstrndx = 0;
/* setup ELF PT_NOTE program header */
nhdr = (struct elf_phdr *) bufp;
bufp += sizeof(struct elf_phdr);
offset += sizeof(struct elf_phdr);
nhdr->p_type = PT_NOTE;
nhdr->p_offset = 0;
nhdr->p_vaddr = 0;
nhdr->p_paddr = 0;
nhdr->p_filesz = 0;
nhdr->p_memsz = 0;
nhdr->p_flags = 0;
nhdr->p_align = 0;
/* setup ELF PT_LOAD program header for every area */
list_for_each_entry(m, &kclist_head, list) {
phdr = (struct elf_phdr *) bufp;
bufp += sizeof(struct elf_phdr);
offset += sizeof(struct elf_phdr);
phdr->p_type = PT_LOAD;
phdr->p_flags = PF_R|PF_W|PF_X;
phdr->p_offset = kc_vaddr_to_offset(m->addr) + dataoff;
phdr->p_vaddr = (size_t)m->addr;
if (m->type == KCORE_RAM || m->type == KCORE_TEXT)
phdr->p_paddr = __pa(m->addr);
else
phdr->p_paddr = (elf_addr_t)-1;
phdr->p_filesz = phdr->p_memsz = m->size;
phdr->p_align = PAGE_SIZE;
}
/*
* Set up the notes in similar form to SVR4 core dumps made
* with info from their /proc.
*/
nhdr->p_offset = offset;
/* set up the process status */
notes[0].name = CORE_STR;
notes[0].type = NT_PRSTATUS;
notes[0].datasz = sizeof(struct elf_prstatus);
notes[0].data = &prstatus;
memset(&prstatus, 0, sizeof(struct elf_prstatus));
nhdr->p_filesz = notesize(¬es[0]);
bufp = storenote(¬es[0], bufp);
/* set up the process info */
notes[1].name = CORE_STR;
notes[1].type = NT_PRPSINFO;
notes[1].datasz = sizeof(struct elf_prpsinfo);
notes[1].data = &prpsinfo;
memset(&prpsinfo, 0, sizeof(struct elf_prpsinfo));
prpsinfo.pr_state = 0;
prpsinfo.pr_sname = 'R';
prpsinfo.pr_zomb = 0;
strcpy(prpsinfo.pr_fname, "vmlinux");
strlcpy(prpsinfo.pr_psargs, saved_command_line, sizeof(prpsinfo.pr_psargs));
nhdr->p_filesz += notesize(¬es[1]);
bufp = storenote(¬es[1], bufp);
/* set up the task structure */
notes[2].name = CORE_STR;
notes[2].type = NT_TASKSTRUCT;
notes[2].datasz = arch_task_struct_size;
notes[2].data = current;
nhdr->p_filesz += notesize(¬es[2]);
bufp = storenote(¬es[2], bufp);
} Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 635 | 88.81% | 5 | 35.71% |
Pratyush Anand | 31 | 4.34% | 1 | 7.14% |
Andrew Morton | 15 | 2.10% | 1 | 7.14% |
Matthew Wilcox | 9 | 1.26% | 1 | 7.14% |
Kamezawa Hiroyuki | 8 | 1.12% | 1 | 7.14% |
Zhao Hongjiang | 7 | 0.98% | 1 | 7.14% |
Yoshinori Sato | 5 | 0.70% | 1 | 7.14% |
Magnus Damm | 3 | 0.42% | 1 | 7.14% |
Dave Hansen | 1 | 0.14% | 1 | 7.14% |
Edgar E. Iglesias | 1 | 0.14% | 1 | 7.14% |
Total | 715 | 100.00% | 14 | 100.00% |
/* end elf_kcore_store_hdr() */
/*****************************************************************************/
/*
* read from the ELF header and then kernel memory
*/
static ssize_t
read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
{
char *buf = file->private_data;
ssize_t acc = 0;
size_t size, tsz;
size_t elf_buflen;
int nphdr;
unsigned long start;
read_lock(&kclist_lock);
size = get_kcore_size(&nphdr, &elf_buflen);
if (buflen == 0 || *fpos >= size) {
read_unlock(&kclist_lock);
return 0;
}
/* trim buflen to not go beyond EOF */
if (buflen > size - *fpos)
buflen = size - *fpos;
/* construct an ELF core header if we'll need some of it */
if (*fpos < elf_buflen) {
char * elf_buf;
tsz = elf_buflen - *fpos;
if (buflen < tsz)
tsz = buflen;
elf_buf = kzalloc(elf_buflen, GFP_ATOMIC);
if (!elf_buf) {
read_unlock(&kclist_lock);
return -ENOMEM;
}
elf_kcore_store_hdr(elf_buf, nphdr, elf_buflen);
read_unlock(&kclist_lock);
if (copy_to_user(buffer, elf_buf + *fpos, tsz)) {
kfree(elf_buf);
return -EFAULT;
}
kfree(elf_buf);
buflen -= tsz;
*fpos += tsz;
buffer += tsz;
acc += tsz;
/* leave now if filled buffer already */
if (buflen == 0)
return acc;
} else
read_unlock(&kclist_lock);
/*
* Check to see if our file offset matches with any of
* the addresses in the elf_phdr on our list.
*/
start = kc_offset_to_vaddr(*fpos - elf_buflen);
if ((tsz = (PAGE_SIZE - (start & ~PAGE_MASK))) > buflen)
tsz = buflen;
while (buflen) {
struct kcore_list *m;
read_lock(&kclist_lock);
list_for_each_entry(m, &kclist_head, list) {
if (start >= m->addr && start < (m->addr+m->size))
break;
}
read_unlock(&kclist_lock);
if (&m->list == &kclist_head) {
if (clear_user(buffer, tsz))
return -EFAULT;
} else if (is_vmalloc_or_module_addr((void *)start)) {
vread(buf, (char *)start, tsz);
/* we have to zero-fill user buffer even if no read */
if (copy_to_user(buffer, buf, tsz))
return -EFAULT;
} else {
if (kern_addr_valid(start)) {
unsigned long n;
/*
* Using bounce buffer to bypass the
* hardened user copy kernel text checks.
*/
memcpy(buf, (char *) start, tsz);
n = copy_to_user(buffer, buf, tsz);
/*
* We cannot distinguish between fault on source
* and fault on destination. When this happens
* we clear too and hope it will trigger the
* EFAULT again.
*/
if (n) {
if (clear_user(buffer + tsz - n,
n))
return -EFAULT;
}
} else {
if (clear_user(buffer, tsz))
return -EFAULT;
}
}
buflen -= tsz;
*fpos += tsz;
buffer += tsz;
acc += tsz;
start += tsz;
tsz = (buflen > PAGE_SIZE ? PAGE_SIZE : buflen);
}
return acc;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Linus Torvalds (pre-git) | 369 | 71.51% | 8 | 38.10% |
Andrew Morton | 97 | 18.80% | 2 | 9.52% |
Jiri Olsa | 24 | 4.65% | 2 | 9.52% |
Kamezawa Hiroyuki | 13 | 2.52% | 3 | 14.29% |
Dan Carpenter | 5 | 0.97% | 1 | 4.76% |
Christoph Lameter | 4 | 0.78% | 1 | 4.76% |
Prasanna Meda | 1 | 0.19% | 1 | 4.76% |
Laura Vasilescu | 1 | 0.19% | 1 | 4.76% |
Panagiotis Issaris | 1 | 0.19% | 1 | 4.76% |
Andries E. Brouwer | 1 | 0.19% | 1 | 4.76% |
Total | 516 | 100.00% | 21 | 100.00% |
static int open_kcore(struct inode *inode, struct file *filp)
{
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
filp->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!filp->private_data)
return -ENOMEM;
if (kcore_need_update)
kcore_update_ram();
if (i_size_read(inode) != proc_root_kcore->size) {
inode_lock(inode);
i_size_write(inode, proc_root_kcore->size);
inode_unlock(inode);
}
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kamezawa Hiroyuki | 68 | 73.91% | 2 | 50.00% |
Jiri Olsa | 22 | 23.91% | 1 | 25.00% |
Al Viro | 2 | 2.17% | 1 | 25.00% |
Total | 92 | 100.00% | 4 | 100.00% |
static int release_kcore(struct inode *inode, struct file *file)
{
kfree(file->private_data);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Jiri Olsa | 26 | 100.00% | 1 | 100.00% |
Total | 26 | 100.00% | 1 | 100.00% |
static const struct file_operations proc_kcore_operations = {
.read = read_kcore,
.open = open_kcore,
.release = release_kcore,
.llseek = default_llseek,
};
/* just remember that we have to update kcore */
static int __meminit kcore_callback(struct notifier_block *self,
unsigned long action, void *arg)
{
switch (action) {
case MEM_ONLINE:
case MEM_OFFLINE:
write_lock(&kclist_lock);
kcore_need_update = 1;
write_unlock(&kclist_lock);
}
return NOTIFY_OK;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kamezawa Hiroyuki | 51 | 100.00% | 1 | 100.00% |
Total | 51 | 100.00% | 1 | 100.00% |
static struct notifier_block kcore_callback_nb __meminitdata = {
.notifier_call = kcore_callback,
.priority = 0,
};
static struct kcore_list kcore_vmalloc;
#ifdef CONFIG_ARCH_PROC_KCORE_TEXT
static struct kcore_list kcore_text;
/*
* If defined, special segment is used for mapping kernel text instead of
* direct-map area. We need to create special TEXT section.
*/
static void __init proc_kcore_text_init(void)
{
kclist_add(&kcore_text, _text, _end - _text, KCORE_TEXT);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kamezawa Hiroyuki | 21 | 91.30% | 1 | 50.00% |
Fengguang Wu | 2 | 8.70% | 1 | 50.00% |
Total | 23 | 100.00% | 2 | 100.00% |
#else
static void __init proc_kcore_text_init(void)
{
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kamezawa Hiroyuki | 8 | 100.00% | 1 | 100.00% |
Total | 8 | 100.00% | 1 | 100.00% |
#endif
#if defined(CONFIG_MODULES) && defined(MODULES_VADDR)
/*
* MODULES_VADDR has no intersection with VMALLOC_ADDR.
*/
struct kcore_list kcore_modules;
static void __init add_modules_range(void)
{
if (MODULES_VADDR != VMALLOC_START && MODULES_END != VMALLOC_END) {
kclist_add(&kcore_modules, (void *)MODULES_VADDR,
MODULES_END - MODULES_VADDR, KCORE_VMALLOC);
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kamezawa Hiroyuki | 27 | 69.23% | 1 | 50.00% |
Baoquan He | 12 | 30.77% | 1 | 50.00% |
Total | 39 | 100.00% | 2 | 100.00% |
#else
static void __init add_modules_range(void)
{
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kamezawa Hiroyuki | 8 | 100.00% | 1 | 100.00% |
Total | 8 | 100.00% | 1 | 100.00% |
#endif
static int __init proc_kcore_init(void)
{
proc_root_kcore = proc_create("kcore", S_IRUSR, NULL,
&proc_kcore_operations);
if (!proc_root_kcore) {
pr_err("couldn't create /proc/kcore\n");
return 0; /* Always returns 0. */
}
/* Store text area if it's special */
proc_kcore_text_init();
/* Store vmalloc area */
kclist_add(&kcore_vmalloc, (void *)VMALLOC_START,
VMALLOC_END - VMALLOC_START, KCORE_VMALLOC);
add_modules_range();
/* Store direct-map area from physical memory map */
kcore_update_ram();
register_hotmemory_notifier(&kcore_callback_nb);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kamezawa Hiroyuki | 48 | 61.54% | 5 | 62.50% |
Alexey Dobriyan | 26 | 33.33% | 1 | 12.50% |
Andrew Morton | 4 | 5.13% | 2 | 25.00% |
Total | 78 | 100.00% | 8 | 100.00% |
fs_initcall(proc_kcore_init);
Overall Contributors
Person | Tokens | Prop | Commits | CommitProp |
Kamezawa Hiroyuki | 1281 | 42.08% | 11 | 16.92% |
Linus Torvalds (pre-git) | 1281 | 42.08% | 12 | 18.46% |
Andrew Morton | 223 | 7.33% | 6 | 9.23% |
Jiri Olsa | 77 | 2.53% | 2 | 3.08% |
Alexey Dobriyan | 36 | 1.18% | 1 | 1.54% |
Pratyush Anand | 31 | 1.02% | 1 | 1.54% |
Magnus Damm | 13 | 0.43% | 1 | 1.54% |
Baoquan He | 12 | 0.39% | 1 | 1.54% |
Edgar E. Iglesias | 10 | 0.33% | 1 | 1.54% |
Matthew Wilcox | 9 | 0.30% | 1 | 1.54% |
Zhao Hongjiang | 7 | 0.23% | 1 | 1.54% |
Vivek Goyal | 6 | 0.20% | 1 | 1.54% |
Yoshinori Sato | 5 | 0.16% | 1 | 1.54% |
Dan Carpenter | 5 | 0.16% | 1 | 1.54% |
Christoph Lameter | 4 | 0.13% | 1 | 1.54% |
Linus Torvalds | 4 | 0.13% | 2 | 3.08% |
David Howells | 4 | 0.13% | 2 | 3.08% |
Frédéric Weisbecker | 4 | 0.13% | 1 | 1.54% |
Thomas Gleixner | 4 | 0.13% | 1 | 1.54% |
Ingo Molnar | 3 | 0.10% | 1 | 1.54% |
Tejun Heo | 3 | 0.10% | 1 | 1.54% |
Randy Dunlap | 3 | 0.10% | 1 | 1.54% |
Djalal Harouni | 2 | 0.07% | 1 | 1.54% |
Tony Luck | 2 | 0.07% | 1 | 1.54% |
Dave Hansen | 2 | 0.07% | 1 | 1.54% |
Fengguang Wu | 2 | 0.07% | 1 | 1.54% |
Al Viro | 2 | 0.07% | 1 | 1.54% |
Dave Anderson | 1 | 0.03% | 1 | 1.54% |
Laura Vasilescu | 1 | 0.03% | 1 | 1.54% |
Xishi Qiu | 1 | 0.03% | 1 | 1.54% |
Andries E. Brouwer | 1 | 0.03% | 1 | 1.54% |
Lai Jiangshan | 1 | 0.03% | 1 | 1.54% |
Fabian Frederick | 1 | 0.03% | 1 | 1.54% |
Prasanna Meda | 1 | 0.03% | 1 | 1.54% |
Paul Gortmaker | 1 | 0.03% | 1 | 1.54% |
Panagiotis Issaris | 1 | 0.03% | 1 | 1.54% |
Total | 3044 | 100.00% | 65 | 100.00% |
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.