1584 lines · 41.9 KB · C
RawDownload
/* * Copyright (C) 2008, 2009 Intel Corporation * Authors: Andi Kleen, Fengguang Wu * * This software may be redistributed and/or modified under the terms of * the GNU General Public License ("GPL") version 2 only as published by the * Free Software Foundation. * * High level machine check handler. Handles pages reported by the * hardware as being corrupted usually due to a multi-bit ECC memory or cache * failure. *  * In addition there is a "soft offline" entry point that allows stop using * not-yet-corrupted-by-suspicious pages without killing anything. * * Handles page cache pages in various states.	The tricky part * here is that we can access any page asynchronously in respect to  * other VM users, because memory failures could happen anytime and  * anywhere. This could violate some of their assumptions. This is why  * this code has to be extremely careful. Generally it tries to use  * normal locking rules, as in get the standard locks, even if that means  * the error handling takes potentially a long time. *  * There are several operations here with exponential complexity because * of unsuitable VM data structures. For example the operation to map back  * from RMAP chains to processes has to walk the complete process list and  * has non linear complexity with the number. But since memory corruptions * are rare we hope to get away with this. This avoids impacting the core  * VM. */ /* * Notebook: * - hugetlb needs more code * - kcore/oldmem/vmcore/mem/kmem check for hwpoison pages * - pass bad pages to kdump next kernel */#include <linux/kernel.h>#include <linux/mm.h>#include <linux/page-flags.h>#include <linux/kernel-page-flags.h>#include <linux/sched.h>#include <linux/ksm.h>#include <linux/rmap.h>#include <linux/export.h>#include <linux/pagemap.h>#include <linux/swap.h>#include <linux/backing-dev.h>#include <linux/migrate.h>#include <linux/page-isolation.h>#include <linux/suspend.h>#include <linux/slab.h>#include <linux/swapops.h>#include <linux/hugetlb.h>#include <linux/memory_hotplug.h>#include <linux/mm_inline.h>#include <linux/kfifo.h>#include "internal.h" int sysctl_memory_failure_early_kill __read_mostly = 0; int sysctl_memory_failure_recovery __read_mostly = 1; atomic_long_t mce_bad_pages __read_mostly = ATOMIC_LONG_INIT(0); #if defined(CONFIG_HWPOISON_INJECT) || defined(CONFIG_HWPOISON_INJECT_MODULE) u32 hwpoison_filter_enable = 0;u32 hwpoison_filter_dev_major = ~0U;u32 hwpoison_filter_dev_minor = ~0U;u64 hwpoison_filter_flags_mask;u64 hwpoison_filter_flags_value;EXPORT_SYMBOL_GPL(hwpoison_filter_enable);EXPORT_SYMBOL_GPL(hwpoison_filter_dev_major);EXPORT_SYMBOL_GPL(hwpoison_filter_dev_minor);EXPORT_SYMBOL_GPL(hwpoison_filter_flags_mask);EXPORT_SYMBOL_GPL(hwpoison_filter_flags_value); static int hwpoison_filter_dev(struct page *p){	struct address_space *mapping;	dev_t dev; 	if (hwpoison_filter_dev_major == ~0U &&	    hwpoison_filter_dev_minor == ~0U)		return 0; 	/*	 * page_mapping() does not accept slab pages.	 */	if (PageSlab(p))		return -EINVAL; 	mapping = page_mapping(p);	if (mapping == NULL || mapping->host == NULL)		return -EINVAL; 	dev = mapping->host->i_sb->s_dev;	if (hwpoison_filter_dev_major != ~0U &&	    hwpoison_filter_dev_major != MAJOR(dev))		return -EINVAL;	if (hwpoison_filter_dev_minor != ~0U &&	    hwpoison_filter_dev_minor != MINOR(dev))		return -EINVAL; 	return 0;} static int hwpoison_filter_flags(struct page *p){	if (!hwpoison_filter_flags_mask)		return 0; 	if ((stable_page_flags(p) & hwpoison_filter_flags_mask) ==				    hwpoison_filter_flags_value)		return 0;	else		return -EINVAL;} /* * This allows stress tests to limit test scope to a collection of tasks * by putting them under some memcg. This prevents killing unrelated/important * processes such as /sbin/init. Note that the target task may share clean * pages with init (eg. libc text), which is harmless. If the target task * share _dirty_ pages with another task B, the test scheme must make sure B * is also included in the memcg. At last, due to race conditions this filter * can only guarantee that the page either belongs to the memcg tasks, or is * a freed page. */#ifdef	CONFIG_CGROUP_MEM_RES_CTLR_SWAPu64 hwpoison_filter_memcg;EXPORT_SYMBOL_GPL(hwpoison_filter_memcg);static int hwpoison_filter_task(struct page *p){	struct mem_cgroup *mem;	struct cgroup_subsys_state *css;	unsigned long ino; 	if (!hwpoison_filter_memcg)		return 0; 	mem = try_get_mem_cgroup_from_page(p);	if (!mem)		return -EINVAL; 	css = mem_cgroup_css(mem);	/* root_mem_cgroup has NULL dentries */	if (!css->cgroup->dentry)		return -EINVAL; 	ino = css->cgroup->dentry->d_inode->i_ino;	css_put(css); 	if (ino != hwpoison_filter_memcg)		return -EINVAL; 	return 0;}#elsestatic int hwpoison_filter_task(struct page *p) { return 0; }#endif int hwpoison_filter(struct page *p){	if (!hwpoison_filter_enable)		return 0; 	if (hwpoison_filter_dev(p))		return -EINVAL; 	if (hwpoison_filter_flags(p))		return -EINVAL; 	if (hwpoison_filter_task(p))		return -EINVAL; 	return 0;}#elseint hwpoison_filter(struct page *p){	return 0;}#endif EXPORT_SYMBOL_GPL(hwpoison_filter); /* * Send all the processes who have the page mapped a signal. * ``action optional'' if they are not immediately affected by the error * ``action required'' if error happened in current execution context */static int kill_proc(struct task_struct *t, unsigned long addr, int trapno,			unsigned long pfn, struct page *page, int flags){	struct siginfo si;	int ret; 	printk(KERN_ERR		"MCE %#lx: Killing %s:%d due to hardware memory corruption\n",		pfn, t->comm, t->pid);	si.si_signo = SIGBUS;	si.si_errno = 0;	si.si_addr = (void *)addr;#ifdef __ARCH_SI_TRAPNO	si.si_trapno = trapno;#endif	si.si_addr_lsb = compound_trans_order(compound_head(page)) + PAGE_SHIFT; 	if ((flags & MF_ACTION_REQUIRED) && t == current) {		si.si_code = BUS_MCEERR_AR;		ret = force_sig_info(SIGBUS, &si, t);	} else {		/*		 * Don't use force here, it's convenient if the signal		 * can be temporarily blocked.		 * This could cause a loop when the user sets SIGBUS		 * to SIG_IGN, but hopefully no one will do that?		 */		si.si_code = BUS_MCEERR_AO;		ret = send_sig_info(SIGBUS, &si, t);  /* synchronous? */	}	if (ret < 0)		printk(KERN_INFO "MCE: Error sending signal to %s:%d: %d\n",		       t->comm, t->pid, ret);	return ret;} /* * When a unknown page type is encountered drain as many buffers as possible * in the hope to turn the page into a LRU or free page, which we can handle. */void shake_page(struct page *p, int access){	if (!PageSlab(p)) {		lru_add_drain_all();		if (PageLRU(p))			return;		drain_all_pages();		if (PageLRU(p) || is_free_buddy_page(p))			return;	} 	/*	 * Only call shrink_slab here (which would also shrink other caches) if	 * access is not potentially fatal.	 */	if (access) {		int nr;		do {			struct shrink_control shrink = {				.gfp_mask = GFP_KERNEL,			}; 			nr = shrink_slab(&shrink, 1000, 1000);			if (page_count(p) == 1)				break;		} while (nr > 10);	}}EXPORT_SYMBOL_GPL(shake_page); /* * Kill all processes that have a poisoned page mapped and then isolate * the page. * * General strategy: * Find all processes having the page mapped and kill them. * But we keep a page reference around so that the page is not * actually freed yet. * Then stash the page away * * There's no convenient way to get back to mapped processes * from the VMAs. So do a brute-force search over all * running processes. * * Remember that machine checks are not common (or rather * if they are common you have other problems), so this shouldn't * be a performance issue. * * Also there are some races possible while we get from the * error detection to actually handle it. */ struct to_kill {	struct list_head nd;	struct task_struct *tsk;	unsigned long addr;	char addr_valid;}; /* * Failure handling: if we can't find or can't kill a process there's * not much we can do.	We just print a message and ignore otherwise. */ /* * Schedule a process for later kill. * Uses GFP_ATOMIC allocations to avoid potential recursions in the VM. * TBD would GFP_NOIO be enough? */static void add_to_kill(struct task_struct *tsk, struct page *p,		       struct vm_area_struct *vma,		       struct list_head *to_kill,		       struct to_kill **tkc){	struct to_kill *tk; 	if (*tkc) {		tk = *tkc;		*tkc = NULL;	} else {		tk = kmalloc(sizeof(struct to_kill), GFP_ATOMIC);		if (!tk) {			printk(KERN_ERR		"MCE: Out of memory while machine check handling\n");			return;		}	}	tk->addr = page_address_in_vma(p, vma);	tk->addr_valid = 1; 	/*	 * In theory we don't have to kill when the page was	 * munmaped. But it could be also a mremap. Since that's	 * likely very rare kill anyways just out of paranoia, but use	 * a SIGKILL because the error is not contained anymore.	 */	if (tk->addr == -EFAULT) {		pr_info("MCE: Unable to find user space address %lx in %s\n",			page_to_pfn(p), tsk->comm);		tk->addr_valid = 0;	}	get_task_struct(tsk);	tk->tsk = tsk;	list_add_tail(&tk->nd, to_kill);} /* * Kill the processes that have been collected earlier. * * Only do anything when DOIT is set, otherwise just free the list * (this is used for clean pages which do not need killing) * Also when FAIL is set do a force kill because something went * wrong earlier. */static void kill_procs(struct list_head *to_kill, int doit, int trapno,			  int fail, struct page *page, unsigned long pfn,			  int flags){	struct to_kill *tk, *next; 	list_for_each_entry_safe (tk, next, to_kill, nd) {		if (doit) {			/*			 * In case something went wrong with munmapping			 * make sure the process doesn't catch the			 * signal and then access the memory. Just kill it.			 */			if (fail || tk->addr_valid == 0) {				printk(KERN_ERR		"MCE %#lx: forcibly killing %s:%d because of failure to unmap corrupted page\n",					pfn, tk->tsk->comm, tk->tsk->pid);				force_sig(SIGKILL, tk->tsk);			} 			/*			 * In theory the process could have mapped			 * something else on the address in-between. We could			 * check for that, but we need to tell the			 * process anyways.			 */			else if (kill_proc(tk->tsk, tk->addr, trapno,					      pfn, page, flags) < 0)				printk(KERN_ERR		"MCE %#lx: Cannot send advisory machine check signal to %s:%d\n",					pfn, tk->tsk->comm, tk->tsk->pid);		}		put_task_struct(tk->tsk);		kfree(tk);	}} static int task_early_kill(struct task_struct *tsk){	if (!tsk->mm)		return 0;	if (tsk->flags & PF_MCE_PROCESS)		return !!(tsk->flags & PF_MCE_EARLY);	return sysctl_memory_failure_early_kill;} /* * Collect processes when the error hit an anonymous page. */static void collect_procs_anon(struct page *page, struct list_head *to_kill,			      struct to_kill **tkc){	struct vm_area_struct *vma;	struct task_struct *tsk;	struct anon_vma *av; 	av = page_lock_anon_vma(page);	if (av == NULL)	/* Not actually mapped anymore */		return; 	read_lock(&tasklist_lock);	for_each_process (tsk) {		struct anon_vma_chain *vmac; 		if (!task_early_kill(tsk))			continue;		list_for_each_entry(vmac, &av->head, same_anon_vma) {			vma = vmac->vma;			if (!page_mapped_in_vma(page, vma))				continue;			if (vma->vm_mm == tsk->mm)				add_to_kill(tsk, page, vma, to_kill, tkc);		}	}	read_unlock(&tasklist_lock);	page_unlock_anon_vma(av);} /* * Collect processes when the error hit a file mapped page. */static void collect_procs_file(struct page *page, struct list_head *to_kill,			      struct to_kill **tkc){	struct vm_area_struct *vma;	struct task_struct *tsk;	struct prio_tree_iter iter;	struct address_space *mapping = page->mapping; 	mutex_lock(&mapping->i_mmap_mutex);	read_lock(&tasklist_lock);	for_each_process(tsk) {		pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); 		if (!task_early_kill(tsk))			continue; 		vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff,				      pgoff) {			/*			 * Send early kill signal to tasks where a vma covers			 * the page but the corrupted page is not necessarily			 * mapped it in its pte.			 * Assume applications who requested early kill want			 * to be informed of all such data corruptions.			 */			if (vma->vm_mm == tsk->mm)				add_to_kill(tsk, page, vma, to_kill, tkc);		}	}	read_unlock(&tasklist_lock);	mutex_unlock(&mapping->i_mmap_mutex);} /* * Collect the processes who have the corrupted page mapped to kill. * This is done in two steps for locking reasons. * First preallocate one tokill structure outside the spin locks, * so that we can kill at least one process reasonably reliable. */static void collect_procs(struct page *page, struct list_head *tokill){	struct to_kill *tk; 	if (!page->mapping)		return; 	tk = kmalloc(sizeof(struct to_kill), GFP_NOIO);	if (!tk)		return;	if (PageAnon(page))		collect_procs_anon(page, tokill, &tk);	else		collect_procs_file(page, tokill, &tk);	kfree(tk);} /* * Error handlers for various types of pages. */ enum outcome {	IGNORED,	/* Error: cannot be handled */	FAILED,		/* Error: handling failed */	DELAYED,	/* Will be handled later */	RECOVERED,	/* Successfully recovered */}; static const char *action_name[] = {	[IGNORED] = "Ignored",	[FAILED] = "Failed",	[DELAYED] = "Delayed",	[RECOVERED] = "Recovered",

Lines 1–500 of 1584.