Merge tag 'v3.10.61' into update
This is the 3.10.61 stable release
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
VERSION = 3
|
||||
PATCHLEVEL = 10
|
||||
SUBLEVEL = 60
|
||||
SUBLEVEL = 61
|
||||
EXTRAVERSION =
|
||||
NAME = TOSSUG Baby Fish
|
||||
|
||||
|
||||
@@ -89,8 +89,7 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
|
||||
const struct exception_table_entry *fixup;
|
||||
int fault, si_code = SEGV_MAPERR;
|
||||
siginfo_t info;
|
||||
unsigned int flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
|
||||
(cause > 0 ? FAULT_FLAG_WRITE : 0));
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
||||
/* As of EV6, a load into $31/$f31 is a prefetch, and never faults
|
||||
(or is suppressed by the PALcode). Support that for older CPUs
|
||||
@@ -115,7 +114,8 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
|
||||
if (address >= TASK_SIZE)
|
||||
goto vmalloc_fault;
|
||||
#endif
|
||||
|
||||
if (user_mode(regs))
|
||||
flags |= FAULT_FLAG_USER;
|
||||
retry:
|
||||
down_read(&mm->mmap_sem);
|
||||
vma = find_vma(mm, address);
|
||||
@@ -142,6 +142,7 @@ retry:
|
||||
} else {
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
goto bad_area;
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
}
|
||||
|
||||
/* If for any reason at all we couldn't handle the fault,
|
||||
|
||||
+8
-9
@@ -59,8 +59,7 @@ void do_page_fault(struct pt_regs *regs, int write, unsigned long address,
|
||||
struct mm_struct *mm = tsk->mm;
|
||||
siginfo_t info;
|
||||
int fault, ret;
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
|
||||
(write ? FAULT_FLAG_WRITE : 0);
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
||||
/*
|
||||
* We fault-in kernel-space virtual memory on-demand. The
|
||||
@@ -88,6 +87,8 @@ void do_page_fault(struct pt_regs *regs, int write, unsigned long address,
|
||||
if (in_atomic() || !mm)
|
||||
goto no_context;
|
||||
|
||||
if (user_mode(regs))
|
||||
flags |= FAULT_FLAG_USER;
|
||||
retry:
|
||||
down_read(&mm->mmap_sem);
|
||||
vma = find_vma(mm, address);
|
||||
@@ -115,12 +116,12 @@ good_area:
|
||||
if (write) {
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
goto bad_area;
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
} else {
|
||||
if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
|
||||
goto bad_area;
|
||||
}
|
||||
|
||||
survive:
|
||||
/*
|
||||
* If for any reason at all we couldn't handle the fault,
|
||||
* make sure we exit gracefully rather than endlessly redo
|
||||
@@ -200,14 +201,12 @@ no_context:
|
||||
die("Oops", regs, address, cause_code);
|
||||
|
||||
out_of_memory:
|
||||
if (is_global_init(tsk)) {
|
||||
yield();
|
||||
goto survive;
|
||||
}
|
||||
up_read(&mm->mmap_sem);
|
||||
|
||||
if (user_mode(regs))
|
||||
do_group_exit(SIGKILL); /* This will never return */
|
||||
if (user_mode(regs)) {
|
||||
pagefault_out_of_memory();
|
||||
return;
|
||||
}
|
||||
|
||||
goto no_context;
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#define _ASMARM_BUG_H
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/opcodes.h>
|
||||
|
||||
#ifdef CONFIG_BUG
|
||||
|
||||
@@ -12,10 +14,10 @@
|
||||
*/
|
||||
#ifdef CONFIG_THUMB2_KERNEL
|
||||
#define BUG_INSTR_VALUE 0xde02
|
||||
#define BUG_INSTR_TYPE ".hword "
|
||||
#define BUG_INSTR(__value) __inst_thumb16(__value)
|
||||
#else
|
||||
#define BUG_INSTR_VALUE 0xe7f001f2
|
||||
#define BUG_INSTR_TYPE ".word "
|
||||
#define BUG_INSTR(__value) __inst_arm(__value)
|
||||
#endif
|
||||
|
||||
|
||||
@@ -33,7 +35,7 @@
|
||||
|
||||
#define __BUG(__file, __line, __value) \
|
||||
do { \
|
||||
asm volatile("1:\t" BUG_INSTR_TYPE #__value "\n" \
|
||||
asm volatile("1:\t" BUG_INSTR(__value) "\n" \
|
||||
".pushsection .rodata.str, \"aMS\", %progbits, 1\n" \
|
||||
"2:\t.asciz " #__file "\n" \
|
||||
".popsection\n" \
|
||||
@@ -48,7 +50,7 @@ do { \
|
||||
|
||||
#define __BUG(__file, __line, __value) \
|
||||
do { \
|
||||
asm volatile(BUG_INSTR_TYPE #__value); \
|
||||
asm volatile(BUG_INSTR(__value) "\n"); \
|
||||
unreachable(); \
|
||||
} while (0)
|
||||
#endif /* CONFIG_DEBUG_BUGVERBOSE */
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <asm/system_info.h>
|
||||
#include <asm/opcodes.h>
|
||||
|
||||
#include "kprobes.h"
|
||||
|
||||
@@ -305,7 +306,8 @@ kprobe_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
|
||||
|
||||
if (handler) {
|
||||
/* We can emulate the instruction in (possibly) modified form */
|
||||
asi->insn[0] = (insn & 0xfff00000) | (rn << 16) | reglist;
|
||||
asi->insn[0] = __opcode_to_mem_arm((insn & 0xfff00000) |
|
||||
(rn << 16) | reglist);
|
||||
asi->insn_handler = handler;
|
||||
return INSN_GOOD;
|
||||
}
|
||||
@@ -334,13 +336,14 @@ prepare_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
|
||||
#ifdef CONFIG_THUMB2_KERNEL
|
||||
if (thumb) {
|
||||
u16 *thumb_insn = (u16 *)asi->insn;
|
||||
thumb_insn[1] = 0x4770; /* Thumb bx lr */
|
||||
thumb_insn[2] = 0x4770; /* Thumb bx lr */
|
||||
/* Thumb bx lr */
|
||||
thumb_insn[1] = __opcode_to_mem_thumb16(0x4770);
|
||||
thumb_insn[2] = __opcode_to_mem_thumb16(0x4770);
|
||||
return insn;
|
||||
}
|
||||
asi->insn[1] = 0xe12fff1e; /* ARM bx lr */
|
||||
asi->insn[1] = __opcode_to_mem_arm(0xe12fff1e); /* ARM bx lr */
|
||||
#else
|
||||
asi->insn[1] = 0xe1a0f00e; /* mov pc, lr */
|
||||
asi->insn[1] = __opcode_to_mem_arm(0xe1a0f00e); /* mov pc, lr */
|
||||
#endif
|
||||
/* Make an ARM instruction unconditional */
|
||||
if (insn < 0xe0000000)
|
||||
@@ -360,12 +363,12 @@ set_emulated_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi,
|
||||
if (thumb) {
|
||||
u16 *ip = (u16 *)asi->insn;
|
||||
if (is_wide_instruction(insn))
|
||||
*ip++ = insn >> 16;
|
||||
*ip++ = insn;
|
||||
*ip++ = __opcode_to_mem_thumb16(insn >> 16);
|
||||
*ip++ = __opcode_to_mem_thumb16(insn);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
asi->insn[0] = insn;
|
||||
asi->insn[0] = __opcode_to_mem_arm(insn);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -163,9 +163,9 @@ t32_decode_ldmstm(kprobe_opcode_t insn, struct arch_specific_insn *asi)
|
||||
enum kprobe_insn ret = kprobe_decode_ldmstm(insn, asi);
|
||||
|
||||
/* Fixup modified instruction to have halfwords in correct order...*/
|
||||
insn = asi->insn[0];
|
||||
((u16 *)asi->insn)[0] = insn >> 16;
|
||||
((u16 *)asi->insn)[1] = insn & 0xffff;
|
||||
insn = __mem_to_opcode_arm(asi->insn[0]);
|
||||
((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(insn >> 16);
|
||||
((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0xffff);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1153,7 +1153,7 @@ t16_decode_hiregs(kprobe_opcode_t insn, struct arch_specific_insn *asi)
|
||||
{
|
||||
insn &= ~0x00ff;
|
||||
insn |= 0x001; /* Set Rdn = R1 and Rm = R0 */
|
||||
((u16 *)asi->insn)[0] = insn;
|
||||
((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(insn);
|
||||
asi->insn_handler = t16_emulate_hiregs;
|
||||
return INSN_GOOD;
|
||||
}
|
||||
@@ -1182,8 +1182,10 @@ t16_decode_push(kprobe_opcode_t insn, struct arch_specific_insn *asi)
|
||||
* and call it with R9=SP and LR in the register list represented
|
||||
* by R8.
|
||||
*/
|
||||
((u16 *)asi->insn)[0] = 0xe929; /* 1st half STMDB R9!,{} */
|
||||
((u16 *)asi->insn)[1] = insn & 0x1ff; /* 2nd half (register list) */
|
||||
/* 1st half STMDB R9!,{} */
|
||||
((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(0xe929);
|
||||
/* 2nd half (register list) */
|
||||
((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0x1ff);
|
||||
asi->insn_handler = t16_emulate_push;
|
||||
return INSN_GOOD;
|
||||
}
|
||||
@@ -1232,8 +1234,10 @@ t16_decode_pop(kprobe_opcode_t insn, struct arch_specific_insn *asi)
|
||||
* and call it with R9=SP and PC in the register list represented
|
||||
* by R8.
|
||||
*/
|
||||
((u16 *)asi->insn)[0] = 0xe8b9; /* 1st half LDMIA R9!,{} */
|
||||
((u16 *)asi->insn)[1] = insn & 0x1ff; /* 2nd half (register list) */
|
||||
/* 1st half LDMIA R9!,{} */
|
||||
((u16 *)asi->insn)[0] = __opcode_to_mem_thumb16(0xe8b9);
|
||||
/* 2nd half (register list) */
|
||||
((u16 *)asi->insn)[1] = __opcode_to_mem_thumb16(insn & 0x1ff);
|
||||
asi->insn_handler = insn & 0x100 ? t16_emulate_pop_pc
|
||||
: t16_emulate_pop_nopc;
|
||||
return INSN_GOOD;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <linux/stop_machine.h>
|
||||
#include <linux/stringify.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/opcodes.h>
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
#include "kprobes.h"
|
||||
@@ -62,10 +63,10 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
|
||||
#ifdef CONFIG_THUMB2_KERNEL
|
||||
thumb = true;
|
||||
addr &= ~1; /* Bit 0 would normally be set to indicate Thumb code */
|
||||
insn = ((u16 *)addr)[0];
|
||||
insn = __mem_to_opcode_thumb16(((u16 *)addr)[0]);
|
||||
if (is_wide_instruction(insn)) {
|
||||
insn <<= 16;
|
||||
insn |= ((u16 *)addr)[1];
|
||||
u16 inst2 = __mem_to_opcode_thumb16(((u16 *)addr)[1]);
|
||||
insn = __opcode_thumb32_compose(insn, inst2);
|
||||
decode_insn = thumb32_kprobe_decode_insn;
|
||||
} else
|
||||
decode_insn = thumb16_kprobe_decode_insn;
|
||||
@@ -73,7 +74,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
|
||||
thumb = false;
|
||||
if (addr & 0x3)
|
||||
return -EINVAL;
|
||||
insn = *p->addr;
|
||||
insn = __mem_to_opcode_arm(*p->addr);
|
||||
decode_insn = arm_kprobe_decode_insn;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -361,15 +361,17 @@ void arm_notify_die(const char *str, struct pt_regs *regs,
|
||||
int is_valid_bugaddr(unsigned long pc)
|
||||
{
|
||||
#ifdef CONFIG_THUMB2_KERNEL
|
||||
unsigned short bkpt;
|
||||
u16 bkpt;
|
||||
u16 insn = __opcode_to_mem_thumb16(BUG_INSTR_VALUE);
|
||||
#else
|
||||
unsigned long bkpt;
|
||||
u32 bkpt;
|
||||
u32 insn = __opcode_to_mem_arm(BUG_INSTR_VALUE);
|
||||
#endif
|
||||
|
||||
if (probe_kernel_address((unsigned *)pc, bkpt))
|
||||
return 0;
|
||||
|
||||
return bkpt == BUG_INSTR_VALUE;
|
||||
return bkpt == insn;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -778,6 +778,7 @@ config NEED_KUSER_HELPERS
|
||||
|
||||
config KUSER_HELPERS
|
||||
bool "Enable kuser helpers in vector page" if !NEED_KUSER_HELPERS
|
||||
depends on MMU
|
||||
default y
|
||||
help
|
||||
Warning: disabling this option may break user programs.
|
||||
|
||||
+13
-10
@@ -262,9 +262,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
||||
struct task_struct *tsk;
|
||||
struct mm_struct *mm;
|
||||
int fault, sig, code;
|
||||
int write = fsr & FSR_WRITE;
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
|
||||
(write ? FAULT_FLAG_WRITE : 0);
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
||||
if (notify_page_fault(regs, fsr))
|
||||
return 0;
|
||||
@@ -283,6 +281,11 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
||||
if (in_atomic() || irqs_disabled() || !mm)
|
||||
goto no_context;
|
||||
|
||||
if (user_mode(regs))
|
||||
flags |= FAULT_FLAG_USER;
|
||||
if (fsr & FSR_WRITE)
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
|
||||
/*
|
||||
* As per x86, we may deadlock here. However, since the kernel only
|
||||
* validly references user space from well defined areas of the code,
|
||||
@@ -350,6 +353,13 @@ retry:
|
||||
if (likely(!(fault & (VM_FAULT_ERROR | VM_FAULT_BADMAP | VM_FAULT_BADACCESS))))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If we are in kernel mode at this point, we
|
||||
* have no context to handle this fault with.
|
||||
*/
|
||||
if (!user_mode(regs))
|
||||
goto no_context;
|
||||
|
||||
if (fault & VM_FAULT_OOM) {
|
||||
/*
|
||||
* We ran out of memory, call the OOM killer, and return to
|
||||
@@ -360,13 +370,6 @@ retry:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are in kernel mode at this point, we
|
||||
* have no context to handle this fault with.
|
||||
*/
|
||||
if (!user_mode(regs))
|
||||
goto no_context;
|
||||
|
||||
if (fault & VM_FAULT_SIGBUS) {
|
||||
/*
|
||||
* We had some memory, but were unable to
|
||||
|
||||
@@ -46,7 +46,7 @@ USER(9f, strh wzr, [x0], #2 )
|
||||
sub x1, x1, #2
|
||||
4: adds x1, x1, #1
|
||||
b.mi 5f
|
||||
strb wzr, [x0]
|
||||
USER(9f, strb wzr, [x0] )
|
||||
5: mov x0, #0
|
||||
ret
|
||||
ENDPROC(__clear_user)
|
||||
|
||||
+17
-14
@@ -199,13 +199,6 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
|
||||
unsigned long vm_flags = VM_READ | VM_WRITE | VM_EXEC;
|
||||
unsigned int mm_flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
||||
if (esr & ESR_LNX_EXEC) {
|
||||
vm_flags = VM_EXEC;
|
||||
} else if ((esr & ESR_WRITE) && !(esr & ESR_CM)) {
|
||||
vm_flags = VM_WRITE;
|
||||
mm_flags |= FAULT_FLAG_WRITE;
|
||||
}
|
||||
|
||||
tsk = current;
|
||||
mm = tsk->mm;
|
||||
|
||||
@@ -220,6 +213,16 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
|
||||
if (in_atomic() || !mm)
|
||||
goto no_context;
|
||||
|
||||
if (user_mode(regs))
|
||||
mm_flags |= FAULT_FLAG_USER;
|
||||
|
||||
if (esr & ESR_LNX_EXEC) {
|
||||
vm_flags = VM_EXEC;
|
||||
} else if ((esr & ESR_WRITE) && !(esr & ESR_CM)) {
|
||||
vm_flags = VM_WRITE;
|
||||
mm_flags |= FAULT_FLAG_WRITE;
|
||||
}
|
||||
|
||||
/*
|
||||
* As per x86, we may deadlock here. However, since the kernel only
|
||||
* validly references user space from well defined areas of the code,
|
||||
@@ -288,6 +291,13 @@ retry:
|
||||
VM_FAULT_BADACCESS))))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If we are in kernel mode at this point, we have no context to
|
||||
* handle this fault with.
|
||||
*/
|
||||
if (!user_mode(regs))
|
||||
goto no_context;
|
||||
|
||||
if (fault & VM_FAULT_OOM) {
|
||||
/*
|
||||
* We ran out of memory, call the OOM killer, and return to
|
||||
@@ -298,13 +308,6 @@ retry:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are in kernel mode at this point, we have no context to
|
||||
* handle this fault with.
|
||||
*/
|
||||
if (!user_mode(regs))
|
||||
goto no_context;
|
||||
|
||||
if (fault & VM_FAULT_SIGBUS) {
|
||||
/*
|
||||
* We had some memory, but were unable to successfully fix up
|
||||
|
||||
@@ -86,6 +86,8 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
if (user_mode(regs))
|
||||
flags |= FAULT_FLAG_USER;
|
||||
retry:
|
||||
down_read(&mm->mmap_sem);
|
||||
|
||||
@@ -228,9 +230,9 @@ no_context:
|
||||
*/
|
||||
out_of_memory:
|
||||
up_read(&mm->mmap_sem);
|
||||
pagefault_out_of_memory();
|
||||
if (!user_mode(regs))
|
||||
goto no_context;
|
||||
pagefault_out_of_memory();
|
||||
return;
|
||||
|
||||
do_sigbus:
|
||||
|
||||
@@ -58,8 +58,7 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
|
||||
struct vm_area_struct * vma;
|
||||
siginfo_t info;
|
||||
int fault;
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
|
||||
((writeaccess & 1) ? FAULT_FLAG_WRITE : 0);
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
||||
D(printk(KERN_DEBUG
|
||||
"Page fault for %lX on %X at %lX, prot %d write %d\n",
|
||||
@@ -117,6 +116,8 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
|
||||
if (in_atomic() || !mm)
|
||||
goto no_context;
|
||||
|
||||
if (user_mode(regs))
|
||||
flags |= FAULT_FLAG_USER;
|
||||
retry:
|
||||
down_read(&mm->mmap_sem);
|
||||
vma = find_vma(mm, address);
|
||||
@@ -155,6 +156,7 @@ retry:
|
||||
} else if (writeaccess == 1) {
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
goto bad_area;
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
} else {
|
||||
if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
|
||||
goto bad_area;
|
||||
|
||||
+6
-4
@@ -34,11 +34,11 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear
|
||||
struct vm_area_struct *vma;
|
||||
struct mm_struct *mm;
|
||||
unsigned long _pme, lrai, lrad, fixup;
|
||||
unsigned long flags = 0;
|
||||
siginfo_t info;
|
||||
pgd_t *pge;
|
||||
pud_t *pue;
|
||||
pte_t *pte;
|
||||
int write;
|
||||
int fault;
|
||||
|
||||
#if 0
|
||||
@@ -81,6 +81,9 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear
|
||||
if (in_atomic() || !mm)
|
||||
goto no_context;
|
||||
|
||||
if (user_mode(__frame))
|
||||
flags |= FAULT_FLAG_USER;
|
||||
|
||||
down_read(&mm->mmap_sem);
|
||||
|
||||
vma = find_vma(mm, ear0);
|
||||
@@ -129,7 +132,6 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear
|
||||
*/
|
||||
good_area:
|
||||
info.si_code = SEGV_ACCERR;
|
||||
write = 0;
|
||||
switch (esr0 & ESR0_ATXC) {
|
||||
default:
|
||||
/* handle write to write protected page */
|
||||
@@ -140,7 +142,7 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear
|
||||
#endif
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
goto bad_area;
|
||||
write = 1;
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
break;
|
||||
|
||||
/* handle read from protected page */
|
||||
@@ -162,7 +164,7 @@ asmlinkage void do_page_fault(int datammu, unsigned long esr0, unsigned long ear
|
||||
* make sure we exit gracefully rather than endlessly redo
|
||||
* the fault.
|
||||
*/
|
||||
fault = handle_mm_fault(mm, vma, ear0, write ? FAULT_FLAG_WRITE : 0);
|
||||
fault = handle_mm_fault(mm, vma, ear0, flags);
|
||||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
|
||||
@@ -53,8 +53,7 @@ void do_page_fault(unsigned long address, long cause, struct pt_regs *regs)
|
||||
int si_code = SEGV_MAPERR;
|
||||
int fault;
|
||||
const struct exception_table_entry *fixup;
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
|
||||
(cause > 0 ? FAULT_FLAG_WRITE : 0);
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
||||
/*
|
||||
* If we're in an interrupt or have no user context,
|
||||
@@ -65,6 +64,8 @@ void do_page_fault(unsigned long address, long cause, struct pt_regs *regs)
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
if (user_mode(regs))
|
||||
flags |= FAULT_FLAG_USER;
|
||||
retry:
|
||||
down_read(&mm->mmap_sem);
|
||||
vma = find_vma(mm, address);
|
||||
@@ -96,6 +97,7 @@ good_area:
|
||||
case FLT_STORE:
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
goto bad_area;
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -90,8 +90,6 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
|
||||
mask = ((((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT)
|
||||
| (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT));
|
||||
|
||||
flags |= ((mask & VM_WRITE) ? FAULT_FLAG_WRITE : 0);
|
||||
|
||||
/* mmap_sem is performance critical.... */
|
||||
prefetchw(&mm->mmap_sem);
|
||||
|
||||
@@ -119,6 +117,10 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
|
||||
if (notify_page_fault(regs, TRAP_BRKPT))
|
||||
return;
|
||||
|
||||
if (user_mode(regs))
|
||||
flags |= FAULT_FLAG_USER;
|
||||
if (mask & VM_WRITE)
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
retry:
|
||||
down_read(&mm->mmap_sem);
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
|
||||
struct mm_struct *mm;
|
||||
struct vm_area_struct * vma;
|
||||
unsigned long page, addr;
|
||||
int write;
|
||||
unsigned long flags = 0;
|
||||
int fault;
|
||||
siginfo_t info;
|
||||
|
||||
@@ -117,6 +117,9 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
|
||||
if (in_atomic() || !mm)
|
||||
goto bad_area_nosemaphore;
|
||||
|
||||
if (error_code & ACE_USERMODE)
|
||||
flags |= FAULT_FLAG_USER;
|
||||
|
||||
/* When running in the kernel we expect faults to occur only to
|
||||
* addresses in user space. All other faults represent errors in the
|
||||
* kernel and should generate an OOPS. Unfortunately, in the case of an
|
||||
@@ -166,14 +169,13 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code,
|
||||
*/
|
||||
good_area:
|
||||
info.si_code = SEGV_ACCERR;
|
||||
write = 0;
|
||||
switch (error_code & (ACE_WRITE|ACE_PROTECTION)) {
|
||||
default: /* 3: write, present */
|
||||
/* fall through */
|
||||
case ACE_WRITE: /* write, not present */
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
goto bad_area;
|
||||
write++;
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
break;
|
||||
case ACE_PROTECTION: /* read, present */
|
||||
case 0: /* read, not present */
|
||||
@@ -194,7 +196,7 @@ good_area:
|
||||
*/
|
||||
addr = (address & PAGE_MASK);
|
||||
set_thread_fault_code(error_code);
|
||||
fault = handle_mm_fault(mm, vma, addr, write ? FAULT_FLAG_WRITE : 0);
|
||||
fault = handle_mm_fault(mm, vma, addr, flags);
|
||||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
|
||||
@@ -88,6 +88,8 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
|
||||
if (in_atomic() || !mm)
|
||||
goto no_context;
|
||||
|
||||
if (user_mode(regs))
|
||||
flags |= FAULT_FLAG_USER;
|
||||
retry:
|
||||
down_read(&mm->mmap_sem);
|
||||
|
||||
|
||||
@@ -53,8 +53,7 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
|
||||
struct vm_area_struct *vma, *prev_vma;
|
||||
siginfo_t info;
|
||||
int fault;
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
|
||||
(write_access ? FAULT_FLAG_WRITE : 0);
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
||||
tsk = current;
|
||||
|
||||
@@ -109,6 +108,8 @@ int do_page_fault(struct pt_regs *regs, unsigned long address,
|
||||
if (in_atomic() || !mm)
|
||||
goto no_context;
|
||||
|
||||
if (user_mode(regs))
|
||||
flags |= FAULT_FLAG_USER;
|
||||
retry:
|
||||
down_read(&mm->mmap_sem);
|
||||
|
||||
@@ -121,6 +122,7 @@ good_area:
|
||||
if (write_access) {
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
goto bad_area;
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
} else {
|
||||
if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
|
||||
goto bad_area;
|
||||
@@ -224,8 +226,10 @@ do_sigbus:
|
||||
*/
|
||||
out_of_memory:
|
||||
up_read(&mm->mmap_sem);
|
||||
if (user_mode(regs))
|
||||
do_group_exit(SIGKILL);
|
||||
if (user_mode(regs)) {
|
||||
pagefault_out_of_memory();
|
||||
return 1;
|
||||
}
|
||||
|
||||
no_context:
|
||||
/* Are we prepared to handle this kernel fault? */
|
||||
|
||||
@@ -92,8 +92,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
|
||||
int code = SEGV_MAPERR;
|
||||
int is_write = error_code & ESR_S;
|
||||
int fault;
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
|
||||
(is_write ? FAULT_FLAG_WRITE : 0);
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
||||
regs->ear = address;
|
||||
regs->esr = error_code;
|
||||
@@ -121,6 +120,9 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
|
||||
die("Weird page fault", regs, SIGSEGV);
|
||||
}
|
||||
|
||||
if (user_mode(regs))
|
||||
flags |= FAULT_FLAG_USER;
|
||||
|
||||
/* When running in the kernel we expect faults to occur only to
|
||||
* addresses in user space. All other faults represent errors in the
|
||||
* kernel and should generate an OOPS. Unfortunately, in the case of an
|
||||
@@ -199,6 +201,7 @@ good_area:
|
||||
if (unlikely(is_write)) {
|
||||
if (unlikely(!(vma->vm_flags & VM_WRITE)))
|
||||
goto bad_area;
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
/* a read */
|
||||
} else {
|
||||
/* protection fault */
|
||||
|
||||
@@ -608,6 +608,7 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
|
||||
r4k_blast_scache();
|
||||
else
|
||||
blast_scache_range(addr, addr + size);
|
||||
preempt_enable();
|
||||
__sync();
|
||||
return;
|
||||
}
|
||||
@@ -649,6 +650,7 @@ static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
|
||||
*/
|
||||
blast_inv_scache_range(addr, addr + size);
|
||||
}
|
||||
preempt_enable();
|
||||
__sync();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -41,8 +41,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long writ
|
||||
const int field = sizeof(unsigned long) * 2;
|
||||
siginfo_t info;
|
||||
int fault;
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
|
||||
(write ? FAULT_FLAG_WRITE : 0);
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
||||
#if 0
|
||||
printk("Cpu%d[%s:%d:%0*lx:%ld:%0*lx]\n", raw_smp_processor_id(),
|
||||
@@ -92,6 +91,8 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, unsigned long writ
|
||||
if (in_atomic() || !mm)
|
||||
goto bad_area_nosemaphore;
|
||||
|
||||
if (user_mode(regs))
|
||||
flags |= FAULT_FLAG_USER;
|
||||
retry:
|
||||
down_read(&mm->mmap_sem);
|
||||
vma = find_vma(mm, address);
|
||||
@@ -113,6 +114,7 @@ good_area:
|
||||
if (write) {
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
goto bad_area;
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
} else {
|
||||
if (cpu_has_rixi) {
|
||||
if (address == regs->cp0_epc && !(vma->vm_flags & VM_EXEC)) {
|
||||
@@ -240,6 +242,8 @@ out_of_memory:
|
||||
* (which will retry the fault, or kill us if we got oom-killed).
|
||||
*/
|
||||
up_read(&mm->mmap_sem);
|
||||
if (!user_mode(regs))
|
||||
goto no_context;
|
||||
pagefault_out_of_memory();
|
||||
return;
|
||||
|
||||
|
||||
@@ -171,6 +171,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,
|
||||
if (in_atomic() || !mm)
|
||||
goto no_context;
|
||||
|
||||
if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR)
|
||||
flags |= FAULT_FLAG_USER;
|
||||
retry:
|
||||
down_read(&mm->mmap_sem);
|
||||
|
||||
@@ -345,9 +347,10 @@ no_context:
|
||||
*/
|
||||
out_of_memory:
|
||||
up_read(&mm->mmap_sem);
|
||||
printk(KERN_ALERT "VM: killing process %s\n", tsk->comm);
|
||||
if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR)
|
||||
do_exit(SIGKILL);
|
||||
if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR) {
|
||||
pagefault_out_of_memory();
|
||||
return;
|
||||
}
|
||||
goto no_context;
|
||||
|
||||
do_sigbus:
|
||||
|
||||
@@ -86,6 +86,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,
|
||||
if (user_mode(regs)) {
|
||||
/* Exception was in userspace: reenable interrupts */
|
||||
local_irq_enable();
|
||||
flags |= FAULT_FLAG_USER;
|
||||
} else {
|
||||
/* If exception was in a syscall, then IRQ's may have
|
||||
* been enabled or disabled. If they were enabled,
|
||||
@@ -267,10 +268,10 @@ out_of_memory:
|
||||
__asm__ __volatile__("l.nop 1");
|
||||
|
||||
up_read(&mm->mmap_sem);
|
||||
printk("VM: killing process %s\n", tsk->comm);
|
||||
if (user_mode(regs))
|
||||
do_exit(SIGKILL);
|
||||
goto no_context;
|
||||
if (!user_mode(regs))
|
||||
goto no_context;
|
||||
pagefault_out_of_memory();
|
||||
return;
|
||||
|
||||
do_sigbus:
|
||||
up_read(&mm->mmap_sem);
|
||||
|
||||
@@ -36,23 +36,16 @@ struct shmid64_ds {
|
||||
unsigned int __unused2;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
/* The 'unsigned int' (formerly 'unsigned long') data types below will
|
||||
* ensure that a 32-bit app calling shmctl(*,IPC_INFO,*) will work on
|
||||
* a wide kernel, but if some of these values are meant to contain pointers
|
||||
* they may need to be 'long long' instead. -PB XXX FIXME
|
||||
*/
|
||||
#endif
|
||||
struct shminfo64 {
|
||||
unsigned int shmmax;
|
||||
unsigned int shmmin;
|
||||
unsigned int shmmni;
|
||||
unsigned int shmseg;
|
||||
unsigned int shmall;
|
||||
unsigned int __unused1;
|
||||
unsigned int __unused2;
|
||||
unsigned int __unused3;
|
||||
unsigned int __unused4;
|
||||
unsigned long shmmax;
|
||||
unsigned long shmmin;
|
||||
unsigned long shmmni;
|
||||
unsigned long shmseg;
|
||||
unsigned long shmall;
|
||||
unsigned long __unused1;
|
||||
unsigned long __unused2;
|
||||
unsigned long __unused3;
|
||||
unsigned long __unused4;
|
||||
};
|
||||
|
||||
#endif /* _PARISC_SHMBUF_H */
|
||||
|
||||
@@ -286,11 +286,11 @@
|
||||
ENTRY_COMP(msgsnd)
|
||||
ENTRY_COMP(msgrcv)
|
||||
ENTRY_SAME(msgget) /* 190 */
|
||||
ENTRY_SAME(msgctl)
|
||||
ENTRY_SAME(shmat)
|
||||
ENTRY_COMP(msgctl)
|
||||
ENTRY_COMP(shmat)
|
||||
ENTRY_SAME(shmdt)
|
||||
ENTRY_SAME(shmget)
|
||||
ENTRY_SAME(shmctl) /* 195 */
|
||||
ENTRY_COMP(shmctl) /* 195 */
|
||||
ENTRY_SAME(ni_syscall) /* streams1 */
|
||||
ENTRY_SAME(ni_syscall) /* streams2 */
|
||||
ENTRY_SAME(lstat64)
|
||||
@@ -323,7 +323,7 @@
|
||||
ENTRY_SAME(epoll_ctl) /* 225 */
|
||||
ENTRY_SAME(epoll_wait)
|
||||
ENTRY_SAME(remap_file_pages)
|
||||
ENTRY_SAME(semtimedop)
|
||||
ENTRY_COMP(semtimedop)
|
||||
ENTRY_COMP(mq_open)
|
||||
ENTRY_SAME(mq_unlink) /* 230 */
|
||||
ENTRY_COMP(mq_timedsend)
|
||||
|
||||
@@ -180,6 +180,10 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
|
||||
if (in_atomic() || !mm)
|
||||
goto no_context;
|
||||
|
||||
if (user_mode(regs))
|
||||
flags |= FAULT_FLAG_USER;
|
||||
if (acc_type & VM_WRITE)
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
retry:
|
||||
down_read(&mm->mmap_sem);
|
||||
vma = find_vma_prev(mm, address, &prev_vma);
|
||||
@@ -203,8 +207,7 @@ good_area:
|
||||
* fault.
|
||||
*/
|
||||
|
||||
fault = handle_mm_fault(mm, vma, address,
|
||||
flags | ((acc_type & VM_WRITE) ? FAULT_FLAG_WRITE : 0));
|
||||
fault = handle_mm_fault(mm, vma, address, flags);
|
||||
|
||||
if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
|
||||
return;
|
||||
|
||||
@@ -223,9 +223,6 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
|
||||
is_write = error_code & ESR_DST;
|
||||
#endif /* CONFIG_4xx || CONFIG_BOOKE */
|
||||
|
||||
if (is_write)
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
|
||||
#ifdef CONFIG_PPC_ICSWX
|
||||
/*
|
||||
* we need to do this early because this "data storage
|
||||
@@ -280,6 +277,9 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
|
||||
|
||||
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
|
||||
|
||||
if (user_mode(regs))
|
||||
flags |= FAULT_FLAG_USER;
|
||||
|
||||
/* When running in the kernel we expect faults to occur only to
|
||||
* addresses in user space. All other faults represent errors in the
|
||||
* kernel and should generate an OOPS. Unfortunately, in the case of an
|
||||
@@ -408,6 +408,7 @@ good_area:
|
||||
} else if (is_write) {
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
goto bad_area;
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
/* a read */
|
||||
} else {
|
||||
/* protection fault */
|
||||
|
||||
@@ -302,6 +302,8 @@ static inline int do_exception(struct pt_regs *regs, int access)
|
||||
address = trans_exc_code & __FAIL_ADDR_MASK;
|
||||
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
|
||||
flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
if (user_mode(regs))
|
||||
flags |= FAULT_FLAG_USER;
|
||||
if (access == VM_WRITE || (trans_exc_code & store_indication) == 0x400)
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
down_read(&mm->mmap_sem);
|
||||
|
||||
+10
-11
@@ -47,6 +47,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
|
||||
struct task_struct *tsk = current;
|
||||
struct mm_struct *mm = tsk->mm;
|
||||
const int field = sizeof(unsigned long) * 2;
|
||||
unsigned long flags = 0;
|
||||
siginfo_t info;
|
||||
int fault;
|
||||
|
||||
@@ -75,6 +76,9 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
|
||||
if (in_atomic() || !mm)
|
||||
goto bad_area_nosemaphore;
|
||||
|
||||
if (user_mode(regs))
|
||||
flags |= FAULT_FLAG_USER;
|
||||
|
||||
down_read(&mm->mmap_sem);
|
||||
vma = find_vma(mm, address);
|
||||
if (!vma)
|
||||
@@ -95,18 +99,18 @@ good_area:
|
||||
if (write) {
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
goto bad_area;
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
} else {
|
||||
if (!(vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC)))
|
||||
goto bad_area;
|
||||
}
|
||||
|
||||
survive:
|
||||
/*
|
||||
* If for any reason at all we couldn't handle the fault,
|
||||
* make sure we exit gracefully rather than endlessly redo
|
||||
* the fault.
|
||||
*/
|
||||
fault = handle_mm_fault(mm, vma, address, write);
|
||||
fault = handle_mm_fault(mm, vma, address, flags);
|
||||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
@@ -167,15 +171,10 @@ no_context:
|
||||
*/
|
||||
out_of_memory:
|
||||
up_read(&mm->mmap_sem);
|
||||
if (is_global_init(tsk)) {
|
||||
yield();
|
||||
down_read(&mm->mmap_sem);
|
||||
goto survive;
|
||||
}
|
||||
printk("VM: killing process %s\n", tsk->comm);
|
||||
if (user_mode(regs))
|
||||
do_group_exit(SIGKILL);
|
||||
goto no_context;
|
||||
if (!user_mode(regs))
|
||||
goto no_context;
|
||||
pagefault_out_of_memory();
|
||||
return;
|
||||
|
||||
do_sigbus:
|
||||
up_read(&mm->mmap_sem);
|
||||
|
||||
+6
-3
@@ -400,9 +400,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
|
||||
struct mm_struct *mm;
|
||||
struct vm_area_struct * vma;
|
||||
int fault;
|
||||
int write = error_code & FAULT_CODE_WRITE;
|
||||
unsigned int flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
|
||||
(write ? FAULT_FLAG_WRITE : 0));
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
||||
tsk = current;
|
||||
mm = tsk->mm;
|
||||
@@ -476,6 +474,11 @@ good_area:
|
||||
|
||||
set_thread_fault_code(error_code);
|
||||
|
||||
if (user_mode(regs))
|
||||
flags |= FAULT_FLAG_USER;
|
||||
if (error_code & FAULT_CODE_WRITE)
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
|
||||
/*
|
||||
* If for any reason at all we couldn't handle the fault,
|
||||
* make sure we exit gracefully rather than endlessly redo
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
extern int __atomic_add_return(int, atomic_t *);
|
||||
extern int atomic_cmpxchg(atomic_t *, int, int);
|
||||
#define atomic_xchg(v, new) (xchg(&((v)->counter), new))
|
||||
extern int atomic_xchg(atomic_t *, int);
|
||||
extern int __atomic_add_unless(atomic_t *, int, int);
|
||||
extern void atomic_set(atomic_t *, int);
|
||||
|
||||
|
||||
@@ -11,22 +11,14 @@
|
||||
#ifndef __ARCH_SPARC_CMPXCHG__
|
||||
#define __ARCH_SPARC_CMPXCHG__
|
||||
|
||||
static inline unsigned long xchg_u32(__volatile__ unsigned long *m, unsigned long val)
|
||||
{
|
||||
__asm__ __volatile__("swap [%2], %0"
|
||||
: "=&r" (val)
|
||||
: "0" (val), "r" (m)
|
||||
: "memory");
|
||||
return val;
|
||||
}
|
||||
|
||||
extern unsigned long __xchg_u32(volatile u32 *m, u32 new);
|
||||
extern void __xchg_called_with_bad_pointer(void);
|
||||
|
||||
static inline unsigned long __xchg(unsigned long x, __volatile__ void * ptr, int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 4:
|
||||
return xchg_u32(ptr, x);
|
||||
return __xchg_u32(ptr, x);
|
||||
}
|
||||
__xchg_called_with_bad_pointer();
|
||||
return x;
|
||||
|
||||
@@ -118,12 +118,18 @@ struct vio_disk_attr_info {
|
||||
u8 vdisk_type;
|
||||
#define VD_DISK_TYPE_SLICE 0x01 /* Slice in block device */
|
||||
#define VD_DISK_TYPE_DISK 0x02 /* Entire block device */
|
||||
u16 resv1;
|
||||
u8 vdisk_mtype; /* v1.1 */
|
||||
#define VD_MEDIA_TYPE_FIXED 0x01 /* Fixed device */
|
||||
#define VD_MEDIA_TYPE_CD 0x02 /* CD Device */
|
||||
#define VD_MEDIA_TYPE_DVD 0x03 /* DVD Device */
|
||||
u8 resv1;
|
||||
u32 vdisk_block_size;
|
||||
u64 operations;
|
||||
u64 vdisk_size;
|
||||
u64 vdisk_size; /* v1.1 */
|
||||
u64 max_xfer_size;
|
||||
u64 resv2[2];
|
||||
u32 phys_block_size; /* v1.2 */
|
||||
u32 resv2;
|
||||
u64 resv3[1];
|
||||
};
|
||||
|
||||
struct vio_disk_desc {
|
||||
@@ -259,7 +265,7 @@ static inline u32 vio_dring_avail(struct vio_dring_state *dr,
|
||||
unsigned int ring_size)
|
||||
{
|
||||
return (dr->pending -
|
||||
((dr->prod - dr->cons) & (ring_size - 1)));
|
||||
((dr->prod - dr->cons) & (ring_size - 1)) - 1);
|
||||
}
|
||||
|
||||
#define VIO_MAX_TYPE_LEN 32
|
||||
|
||||
@@ -581,7 +581,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm)
|
||||
{
|
||||
unsigned long csr_reg, csr, csr_error_bits;
|
||||
irqreturn_t ret = IRQ_NONE;
|
||||
u16 stat;
|
||||
u32 stat;
|
||||
|
||||
csr_reg = pbm->pbm_regs + SCHIZO_PCI_CTRL;
|
||||
csr = upa_readq(csr_reg);
|
||||
@@ -617,7 +617,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm)
|
||||
pbm->name);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
pci_read_config_word(pbm->pci_bus->self, PCI_STATUS, &stat);
|
||||
pbm->pci_ops->read(pbm->pci_bus, 0, PCI_STATUS, 2, &stat);
|
||||
if (stat & (PCI_STATUS_PARITY |
|
||||
PCI_STATUS_SIG_TARGET_ABORT |
|
||||
PCI_STATUS_REC_TARGET_ABORT |
|
||||
@@ -625,7 +625,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm)
|
||||
PCI_STATUS_SIG_SYSTEM_ERROR)) {
|
||||
printk("%s: PCI bus error, PCI_STATUS[%04x]\n",
|
||||
pbm->name, stat);
|
||||
pci_write_config_word(pbm->pci_bus->self, PCI_STATUS, 0xffff);
|
||||
pbm->pci_ops->write(pbm->pci_bus, 0, PCI_STATUS, 2, 0xffff);
|
||||
ret = IRQ_HANDLED;
|
||||
}
|
||||
return ret;
|
||||
|
||||
@@ -821,13 +821,17 @@ void arch_send_call_function_single_ipi(int cpu)
|
||||
void __irq_entry smp_call_function_client(int irq, struct pt_regs *regs)
|
||||
{
|
||||
clear_softint(1 << irq);
|
||||
irq_enter();
|
||||
generic_smp_call_function_interrupt();
|
||||
irq_exit();
|
||||
}
|
||||
|
||||
void __irq_entry smp_call_function_single_client(int irq, struct pt_regs *regs)
|
||||
{
|
||||
clear_softint(1 << irq);
|
||||
irq_enter();
|
||||
generic_smp_call_function_single_interrupt();
|
||||
irq_exit();
|
||||
}
|
||||
|
||||
static void tsb_sync(void *info)
|
||||
|
||||
@@ -40,6 +40,19 @@ int __atomic_add_return(int i, atomic_t *v)
|
||||
}
|
||||
EXPORT_SYMBOL(__atomic_add_return);
|
||||
|
||||
int atomic_xchg(atomic_t *v, int new)
|
||||
{
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(ATOMIC_HASH(v), flags);
|
||||
ret = v->counter;
|
||||
v->counter = new;
|
||||
spin_unlock_irqrestore(ATOMIC_HASH(v), flags);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(atomic_xchg);
|
||||
|
||||
int atomic_cmpxchg(atomic_t *v, int old, int new)
|
||||
{
|
||||
int ret;
|
||||
@@ -132,3 +145,17 @@ unsigned long __cmpxchg_u32(volatile u32 *ptr, u32 old, u32 new)
|
||||
return (unsigned long)prev;
|
||||
}
|
||||
EXPORT_SYMBOL(__cmpxchg_u32);
|
||||
|
||||
unsigned long __xchg_u32(volatile u32 *ptr, u32 new)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 prev;
|
||||
|
||||
spin_lock_irqsave(ATOMIC_HASH(ptr), flags);
|
||||
prev = *ptr;
|
||||
*ptr = new;
|
||||
spin_unlock_irqrestore(ATOMIC_HASH(ptr), flags);
|
||||
|
||||
return (unsigned long)prev;
|
||||
}
|
||||
EXPORT_SYMBOL(__xchg_u32);
|
||||
|
||||
@@ -177,8 +177,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
|
||||
unsigned long g2;
|
||||
int from_user = !(regs->psr & PSR_PS);
|
||||
int fault, code;
|
||||
unsigned int flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
|
||||
(write ? FAULT_FLAG_WRITE : 0));
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
||||
if (text_fault)
|
||||
address = regs->pc;
|
||||
@@ -235,6 +234,11 @@ good_area:
|
||||
goto bad_area;
|
||||
}
|
||||
|
||||
if (from_user)
|
||||
flags |= FAULT_FLAG_USER;
|
||||
if (write)
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
|
||||
/*
|
||||
* If for any reason at all we couldn't handle the fault,
|
||||
* make sure we exit gracefully rather than endlessly redo
|
||||
@@ -383,6 +387,7 @@ static void force_user_fault(unsigned long address, int write)
|
||||
struct vm_area_struct *vma;
|
||||
struct task_struct *tsk = current;
|
||||
struct mm_struct *mm = tsk->mm;
|
||||
unsigned int flags = FAULT_FLAG_USER;
|
||||
int code;
|
||||
|
||||
code = SEGV_MAPERR;
|
||||
@@ -402,11 +407,12 @@ good_area:
|
||||
if (write) {
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
goto bad_area;
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
} else {
|
||||
if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
|
||||
goto bad_area;
|
||||
}
|
||||
switch (handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0)) {
|
||||
switch (handle_mm_fault(mm, vma, address, flags)) {
|
||||
case VM_FAULT_SIGBUS:
|
||||
case VM_FAULT_OOM:
|
||||
goto do_sigbus;
|
||||
|
||||
@@ -323,7 +323,8 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
|
||||
bad_kernel_pc(regs, address);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else
|
||||
flags |= FAULT_FLAG_USER;
|
||||
|
||||
/*
|
||||
* If we're in an interrupt or have no user
|
||||
@@ -426,13 +427,14 @@ good_area:
|
||||
vma->vm_file != NULL)
|
||||
set_thread_fault_code(fault_code |
|
||||
FAULT_CODE_BLKCOMMIT);
|
||||
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
} else {
|
||||
/* Allow reads even for write-only mappings */
|
||||
if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
|
||||
goto bad_area;
|
||||
}
|
||||
|
||||
flags |= ((fault_code & FAULT_CODE_WRITE) ? FAULT_FLAG_WRITE : 0);
|
||||
fault = handle_mm_fault(mm, vma, address, flags);
|
||||
|
||||
if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
|
||||
|
||||
+9
-12
@@ -280,8 +280,7 @@ static int handle_page_fault(struct pt_regs *regs,
|
||||
if (!is_page_fault)
|
||||
write = 1;
|
||||
|
||||
flags = (FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
|
||||
(write ? FAULT_FLAG_WRITE : 0));
|
||||
flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
||||
is_kernel_mode = (EX1_PL(regs->ex1) != USER_PL);
|
||||
|
||||
@@ -365,6 +364,9 @@ static int handle_page_fault(struct pt_regs *regs,
|
||||
goto bad_area_nosemaphore;
|
||||
}
|
||||
|
||||
if (!is_kernel_mode)
|
||||
flags |= FAULT_FLAG_USER;
|
||||
|
||||
/*
|
||||
* When running in the kernel we expect faults to occur only to
|
||||
* addresses in user space. All other faults represent errors in the
|
||||
@@ -425,12 +427,12 @@ good_area:
|
||||
#endif
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
goto bad_area;
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
} else {
|
||||
if (!is_page_fault || !(vma->vm_flags & VM_READ))
|
||||
goto bad_area;
|
||||
}
|
||||
|
||||
survive:
|
||||
/*
|
||||
* If for any reason at all we couldn't handle the fault,
|
||||
* make sure we exit gracefully rather than endlessly redo
|
||||
@@ -568,15 +570,10 @@ no_context:
|
||||
*/
|
||||
out_of_memory:
|
||||
up_read(&mm->mmap_sem);
|
||||
if (is_global_init(tsk)) {
|
||||
yield();
|
||||
down_read(&mm->mmap_sem);
|
||||
goto survive;
|
||||
}
|
||||
pr_alert("VM: killing process %s\n", tsk->comm);
|
||||
if (!is_kernel_mode)
|
||||
do_group_exit(SIGKILL);
|
||||
goto no_context;
|
||||
if (is_kernel_mode)
|
||||
goto no_context;
|
||||
pagefault_out_of_memory();
|
||||
return 0;
|
||||
|
||||
do_sigbus:
|
||||
up_read(&mm->mmap_sem);
|
||||
|
||||
+14
-8
@@ -30,8 +30,7 @@ int handle_page_fault(unsigned long address, unsigned long ip,
|
||||
pmd_t *pmd;
|
||||
pte_t *pte;
|
||||
int err = -EFAULT;
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
|
||||
(is_write ? FAULT_FLAG_WRITE : 0);
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
||||
*code_out = SEGV_MAPERR;
|
||||
|
||||
@@ -42,6 +41,8 @@ int handle_page_fault(unsigned long address, unsigned long ip,
|
||||
if (in_atomic())
|
||||
goto out_nosemaphore;
|
||||
|
||||
if (is_user)
|
||||
flags |= FAULT_FLAG_USER;
|
||||
retry:
|
||||
down_read(&mm->mmap_sem);
|
||||
vma = find_vma(mm, address);
|
||||
@@ -58,12 +59,15 @@ retry:
|
||||
|
||||
good_area:
|
||||
*code_out = SEGV_ACCERR;
|
||||
if (is_write && !(vma->vm_flags & VM_WRITE))
|
||||
goto out;
|
||||
|
||||
/* Don't require VM_READ|VM_EXEC for write faults! */
|
||||
if (!is_write && !(vma->vm_flags & (VM_READ | VM_EXEC)))
|
||||
goto out;
|
||||
if (is_write) {
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
goto out;
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
} else {
|
||||
/* Don't require VM_READ|VM_EXEC for write faults! */
|
||||
if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
|
||||
goto out;
|
||||
}
|
||||
|
||||
do {
|
||||
int fault;
|
||||
@@ -124,6 +128,8 @@ out_of_memory:
|
||||
* (which will retry the fault, or kill us if we got oom-killed).
|
||||
*/
|
||||
up_read(&mm->mmap_sem);
|
||||
if (!is_user)
|
||||
goto out_nosemaphore;
|
||||
pagefault_out_of_memory();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -209,8 +209,7 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
||||
struct task_struct *tsk;
|
||||
struct mm_struct *mm;
|
||||
int fault, sig, code;
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
|
||||
((!(fsr ^ 0x12)) ? FAULT_FLAG_WRITE : 0);
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
||||
tsk = current;
|
||||
mm = tsk->mm;
|
||||
@@ -222,6 +221,11 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
||||
if (in_atomic() || !mm)
|
||||
goto no_context;
|
||||
|
||||
if (user_mode(regs))
|
||||
flags |= FAULT_FLAG_USER;
|
||||
if (!(fsr ^ 0x12))
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
|
||||
/*
|
||||
* As per x86, we may deadlock here. However, since the kernel only
|
||||
* validly references user space from well defined areas of the code,
|
||||
@@ -278,6 +282,13 @@ retry:
|
||||
(VM_FAULT_ERROR | VM_FAULT_BADMAP | VM_FAULT_BADACCESS))))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If we are in kernel mode at this point, we
|
||||
* have no context to handle this fault with.
|
||||
*/
|
||||
if (!user_mode(regs))
|
||||
goto no_context;
|
||||
|
||||
if (fault & VM_FAULT_OOM) {
|
||||
/*
|
||||
* We ran out of memory, call the OOM killer, and return to
|
||||
@@ -288,13 +299,6 @@ retry:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are in kernel mode at this point, we
|
||||
* have no context to handle this fault with.
|
||||
*/
|
||||
if (!user_mode(regs))
|
||||
goto no_context;
|
||||
|
||||
if (fault & VM_FAULT_SIGBUS) {
|
||||
/*
|
||||
* We had some memory, but were unable to
|
||||
|
||||
@@ -2172,6 +2172,9 @@ __init int intel_pmu_init(void)
|
||||
case 62: /* IvyBridge EP */
|
||||
memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
|
||||
sizeof(hw_cache_event_ids));
|
||||
/* dTLB-load-misses on IVB is different than SNB */
|
||||
hw_cache_event_ids[C(DTLB)][C(OP_READ)][C(RESULT_MISS)] = 0x8108; /* DTLB_LOAD_MISSES.DEMAND_LD_MISS_CAUSES_A_WALK */
|
||||
|
||||
memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
|
||||
sizeof(hw_cache_extra_regs));
|
||||
|
||||
|
||||
@@ -1475,15 +1475,6 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
|
||||
force_sig_info(SIGTRAP, &info, tsk);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
# define IS_IA32 1
|
||||
#elif defined CONFIG_IA32_EMULATION
|
||||
# define IS_IA32 is_compat_task()
|
||||
#else
|
||||
# define IS_IA32 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We must return the syscall number to actually look up in the table.
|
||||
* This can be -1L to skip running any syscall at all.
|
||||
@@ -1521,7 +1512,7 @@ long syscall_trace_enter(struct pt_regs *regs)
|
||||
if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
|
||||
trace_sys_enter(regs, regs->orig_ax);
|
||||
|
||||
if (IS_IA32)
|
||||
if (is_ia32_task())
|
||||
audit_syscall_entry(AUDIT_ARCH_I386,
|
||||
regs->orig_ax,
|
||||
regs->bx, regs->cx,
|
||||
|
||||
+1
-1
@@ -4834,7 +4834,7 @@ static int handle_emulation_failure(struct kvm_vcpu *vcpu)
|
||||
|
||||
++vcpu->stat.insn_emulation_fail;
|
||||
trace_kvm_emulate_insn_failed(vcpu);
|
||||
if (!is_guest_mode(vcpu)) {
|
||||
if (!is_guest_mode(vcpu) && kvm_x86_ops->get_cpl(vcpu) == 0) {
|
||||
vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
|
||||
vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_EMULATION;
|
||||
vcpu->run->internal.ndata = 0;
|
||||
|
||||
+22
-21
@@ -842,23 +842,15 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
|
||||
force_sig_info_fault(SIGBUS, code, address, tsk, fault);
|
||||
}
|
||||
|
||||
static noinline int
|
||||
static noinline void
|
||||
mm_fault_error(struct pt_regs *regs, unsigned long error_code,
|
||||
unsigned long address, unsigned int fault)
|
||||
{
|
||||
/*
|
||||
* Pagefault was interrupted by SIGKILL. We have no reason to
|
||||
* continue pagefault.
|
||||
*/
|
||||
if (fatal_signal_pending(current)) {
|
||||
if (!(fault & VM_FAULT_RETRY))
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
if (!(error_code & PF_USER))
|
||||
no_context(regs, error_code, address, 0, 0);
|
||||
return 1;
|
||||
if (fatal_signal_pending(current) && !(error_code & PF_USER)) {
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
no_context(regs, error_code, address, 0, 0);
|
||||
return;
|
||||
}
|
||||
if (!(fault & VM_FAULT_ERROR))
|
||||
return 0;
|
||||
|
||||
if (fault & VM_FAULT_OOM) {
|
||||
/* Kernel mode? Handle exceptions or die: */
|
||||
@@ -866,7 +858,7 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
no_context(regs, error_code, address,
|
||||
SIGSEGV, SEGV_MAPERR);
|
||||
return 1;
|
||||
return;
|
||||
}
|
||||
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
@@ -884,7 +876,6 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
|
||||
else
|
||||
BUG();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int spurious_fault_check(unsigned long error_code, pte_t *pte)
|
||||
@@ -1017,9 +1008,7 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
||||
unsigned long address;
|
||||
struct mm_struct *mm;
|
||||
int fault;
|
||||
int write = error_code & PF_WRITE;
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
|
||||
(write ? FAULT_FLAG_WRITE : 0);
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
||||
tsk = current;
|
||||
mm = tsk->mm;
|
||||
@@ -1089,6 +1078,7 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
||||
if (user_mode_vm(regs)) {
|
||||
local_irq_enable();
|
||||
error_code |= PF_USER;
|
||||
flags |= FAULT_FLAG_USER;
|
||||
} else {
|
||||
if (regs->flags & X86_EFLAGS_IF)
|
||||
local_irq_enable();
|
||||
@@ -1113,6 +1103,9 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code)
|
||||
return;
|
||||
}
|
||||
|
||||
if (error_code & PF_WRITE)
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
|
||||
/*
|
||||
* When running in the kernel we expect faults to occur only to
|
||||
* addresses in user space. All other faults represent errors in
|
||||
@@ -1191,9 +1184,17 @@ good_area:
|
||||
*/
|
||||
fault = handle_mm_fault(mm, vma, address, flags);
|
||||
|
||||
if (unlikely(fault & (VM_FAULT_RETRY|VM_FAULT_ERROR))) {
|
||||
if (mm_fault_error(regs, error_code, address, fault))
|
||||
return;
|
||||
/*
|
||||
* If we need to retry but a fatal signal is pending, handle the
|
||||
* signal first. We do not need to release the mmap_sem because it
|
||||
* would already be released in __lock_page_or_retry in mm/filemap.c.
|
||||
*/
|
||||
if (unlikely((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)))
|
||||
return;
|
||||
|
||||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
mm_fault_error(regs, error_code, address, fault);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -384,7 +384,8 @@ __SYSCALL(174, sys_chroot, 1)
|
||||
#define __NR_pivot_root 175
|
||||
__SYSCALL(175, sys_pivot_root, 2)
|
||||
#define __NR_umount 176
|
||||
__SYSCALL(176, sys_umount, 2)
|
||||
__SYSCALL(176, sys_oldumount, 1)
|
||||
#define __ARCH_WANT_SYS_OLDUMOUNT
|
||||
#define __NR_swapoff 177
|
||||
__SYSCALL(177, sys_swapoff, 1)
|
||||
#define __NR_sync 178
|
||||
|
||||
@@ -72,6 +72,8 @@ void do_page_fault(struct pt_regs *regs)
|
||||
address, exccause, regs->pc, is_write? "w":"", is_exec? "x":"");
|
||||
#endif
|
||||
|
||||
if (user_mode(regs))
|
||||
flags |= FAULT_FLAG_USER;
|
||||
retry:
|
||||
down_read(&mm->mmap_sem);
|
||||
vma = find_vma(mm, address);
|
||||
|
||||
+16
-3
@@ -61,6 +61,7 @@ enum board_ids {
|
||||
/* board IDs by feature in alphabetical order */
|
||||
board_ahci,
|
||||
board_ahci_ign_iferr,
|
||||
board_ahci_nomsi,
|
||||
board_ahci_noncq,
|
||||
board_ahci_nosntf,
|
||||
board_ahci_yes_fbs,
|
||||
@@ -120,6 +121,13 @@ static const struct ata_port_info ahci_port_info[] = {
|
||||
.udma_mask = ATA_UDMA6,
|
||||
.port_ops = &ahci_ops,
|
||||
},
|
||||
[board_ahci_nomsi] = {
|
||||
AHCI_HFLAGS (AHCI_HFLAG_NO_MSI),
|
||||
.flags = AHCI_FLAG_COMMON,
|
||||
.pio_mask = ATA_PIO4,
|
||||
.udma_mask = ATA_UDMA6,
|
||||
.port_ops = &ahci_ops,
|
||||
},
|
||||
[board_ahci_noncq] = {
|
||||
AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ),
|
||||
.flags = AHCI_FLAG_COMMON,
|
||||
@@ -312,6 +320,11 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
||||
{ PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */
|
||||
{ PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */
|
||||
{ PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */
|
||||
{ PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H AHCI */
|
||||
{ PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H RAID */
|
||||
{ PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */
|
||||
{ PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */
|
||||
{ PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
|
||||
|
||||
/* JMicron 360/1/3/5/6, match class to avoid IDE function */
|
||||
{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
|
||||
@@ -474,10 +487,10 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
||||
{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */
|
||||
|
||||
/*
|
||||
* Samsung SSDs found on some macbooks. NCQ times out.
|
||||
* https://bugzilla.kernel.org/show_bug.cgi?id=60731
|
||||
* Samsung SSDs found on some macbooks. NCQ times out if MSI is
|
||||
* enabled. https://bugzilla.kernel.org/show_bug.cgi?id=60731
|
||||
*/
|
||||
{ PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_noncq },
|
||||
{ PCI_VDEVICE(SAMSUNG, 0x1600), board_ahci_nomsi },
|
||||
|
||||
/* Enmotus */
|
||||
{ PCI_DEVICE(0x1c44, 0x8000), board_ahci },
|
||||
|
||||
+128
-46
@@ -9,6 +9,7 @@
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/hdreg.h>
|
||||
#include <linux/genhd.h>
|
||||
#include <linux/cdrom.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/completion.h>
|
||||
@@ -22,8 +23,8 @@
|
||||
|
||||
#define DRV_MODULE_NAME "sunvdc"
|
||||
#define PFX DRV_MODULE_NAME ": "
|
||||
#define DRV_MODULE_VERSION "1.0"
|
||||
#define DRV_MODULE_RELDATE "June 25, 2007"
|
||||
#define DRV_MODULE_VERSION "1.1"
|
||||
#define DRV_MODULE_RELDATE "February 13, 2013"
|
||||
|
||||
static char version[] =
|
||||
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
|
||||
@@ -32,7 +33,7 @@ MODULE_DESCRIPTION("Sun LDOM virtual disk client driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DRV_MODULE_VERSION);
|
||||
|
||||
#define VDC_TX_RING_SIZE 256
|
||||
#define VDC_TX_RING_SIZE 512
|
||||
|
||||
#define WAITING_FOR_LINK_UP 0x01
|
||||
#define WAITING_FOR_TX_SPACE 0x02
|
||||
@@ -65,11 +66,9 @@ struct vdc_port {
|
||||
u64 operations;
|
||||
u32 vdisk_size;
|
||||
u8 vdisk_type;
|
||||
u8 vdisk_mtype;
|
||||
|
||||
char disk_name[32];
|
||||
|
||||
struct vio_disk_geom geom;
|
||||
struct vio_disk_vtoc label;
|
||||
};
|
||||
|
||||
static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio)
|
||||
@@ -79,9 +78,16 @@ static inline struct vdc_port *to_vdc_port(struct vio_driver_state *vio)
|
||||
|
||||
/* Ordered from largest major to lowest */
|
||||
static struct vio_version vdc_versions[] = {
|
||||
{ .major = 1, .minor = 1 },
|
||||
{ .major = 1, .minor = 0 },
|
||||
};
|
||||
|
||||
static inline int vdc_version_supported(struct vdc_port *port,
|
||||
u16 major, u16 minor)
|
||||
{
|
||||
return port->vio.ver.major == major && port->vio.ver.minor >= minor;
|
||||
}
|
||||
|
||||
#define VDCBLK_NAME "vdisk"
|
||||
static int vdc_major;
|
||||
#define PARTITION_SHIFT 3
|
||||
@@ -94,18 +100,54 @@ static inline u32 vdc_tx_dring_avail(struct vio_dring_state *dr)
|
||||
static int vdc_getgeo(struct block_device *bdev, struct hd_geometry *geo)
|
||||
{
|
||||
struct gendisk *disk = bdev->bd_disk;
|
||||
struct vdc_port *port = disk->private_data;
|
||||
sector_t nsect = get_capacity(disk);
|
||||
sector_t cylinders = nsect;
|
||||
|
||||
geo->heads = (u8) port->geom.num_hd;
|
||||
geo->sectors = (u8) port->geom.num_sec;
|
||||
geo->cylinders = port->geom.num_cyl;
|
||||
geo->heads = 0xff;
|
||||
geo->sectors = 0x3f;
|
||||
sector_div(cylinders, geo->heads * geo->sectors);
|
||||
geo->cylinders = cylinders;
|
||||
if ((sector_t)(geo->cylinders + 1) * geo->heads * geo->sectors < nsect)
|
||||
geo->cylinders = 0xffff;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add ioctl/CDROM_GET_CAPABILITY to support cdrom_id in udev
|
||||
* when vdisk_mtype is VD_MEDIA_TYPE_CD or VD_MEDIA_TYPE_DVD.
|
||||
* Needed to be able to install inside an ldom from an iso image.
|
||||
*/
|
||||
static int vdc_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
unsigned command, unsigned long argument)
|
||||
{
|
||||
int i;
|
||||
struct gendisk *disk;
|
||||
|
||||
switch (command) {
|
||||
case CDROMMULTISESSION:
|
||||
pr_debug(PFX "Multisession CDs not supported\n");
|
||||
for (i = 0; i < sizeof(struct cdrom_multisession); i++)
|
||||
if (put_user(0, (char __user *)(argument + i)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
case CDROM_GET_CAPABILITY:
|
||||
disk = bdev->bd_disk;
|
||||
|
||||
if (bdev->bd_disk && (disk->flags & GENHD_FL_CD))
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
|
||||
default:
|
||||
pr_debug(PFX "ioctl %08x not supported\n", command);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct block_device_operations vdc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.getgeo = vdc_getgeo,
|
||||
.ioctl = vdc_ioctl,
|
||||
};
|
||||
|
||||
static void vdc_finish(struct vio_driver_state *vio, int err, int waiting_for)
|
||||
@@ -165,9 +207,9 @@ static int vdc_handle_attr(struct vio_driver_state *vio, void *arg)
|
||||
struct vio_disk_attr_info *pkt = arg;
|
||||
|
||||
viodbg(HS, "GOT ATTR stype[0x%x] ops[%llx] disk_size[%llu] disk_type[%x] "
|
||||
"xfer_mode[0x%x] blksz[%u] max_xfer[%llu]\n",
|
||||
"mtype[0x%x] xfer_mode[0x%x] blksz[%u] max_xfer[%llu]\n",
|
||||
pkt->tag.stype, pkt->operations,
|
||||
pkt->vdisk_size, pkt->vdisk_type,
|
||||
pkt->vdisk_size, pkt->vdisk_type, pkt->vdisk_mtype,
|
||||
pkt->xfer_mode, pkt->vdisk_block_size,
|
||||
pkt->max_xfer_size);
|
||||
|
||||
@@ -192,8 +234,11 @@ static int vdc_handle_attr(struct vio_driver_state *vio, void *arg)
|
||||
}
|
||||
|
||||
port->operations = pkt->operations;
|
||||
port->vdisk_size = pkt->vdisk_size;
|
||||
port->vdisk_type = pkt->vdisk_type;
|
||||
if (vdc_version_supported(port, 1, 1)) {
|
||||
port->vdisk_size = pkt->vdisk_size;
|
||||
port->vdisk_mtype = pkt->vdisk_mtype;
|
||||
}
|
||||
if (pkt->max_xfer_size < port->max_xfer_size)
|
||||
port->max_xfer_size = pkt->max_xfer_size;
|
||||
port->vdisk_block_size = pkt->vdisk_block_size;
|
||||
@@ -236,7 +281,9 @@ static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr,
|
||||
|
||||
__blk_end_request(req, (desc->status ? -EIO : 0), desc->size);
|
||||
|
||||
if (blk_queue_stopped(port->disk->queue))
|
||||
/* restart blk queue when ring is half emptied */
|
||||
if (blk_queue_stopped(port->disk->queue) &&
|
||||
vdc_tx_dring_avail(dr) * 100 / VDC_TX_RING_SIZE >= 50)
|
||||
blk_start_queue(port->disk->queue);
|
||||
}
|
||||
|
||||
@@ -388,12 +435,6 @@ static int __send_request(struct request *req)
|
||||
for (i = 0; i < nsg; i++)
|
||||
len += sg[i].length;
|
||||
|
||||
if (unlikely(vdc_tx_dring_avail(dr) < 1)) {
|
||||
blk_stop_queue(port->disk->queue);
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
desc = vio_dring_cur(dr);
|
||||
|
||||
err = ldc_map_sg(port->vio.lp, sg, nsg,
|
||||
@@ -433,21 +474,32 @@ static int __send_request(struct request *req)
|
||||
port->req_id++;
|
||||
dr->prod = (dr->prod + 1) & (VDC_TX_RING_SIZE - 1);
|
||||
}
|
||||
out:
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void do_vdc_request(struct request_queue *q)
|
||||
static void do_vdc_request(struct request_queue *rq)
|
||||
{
|
||||
while (1) {
|
||||
struct request *req = blk_fetch_request(q);
|
||||
struct request *req;
|
||||
|
||||
if (!req)
|
||||
while ((req = blk_peek_request(rq)) != NULL) {
|
||||
struct vdc_port *port;
|
||||
struct vio_dring_state *dr;
|
||||
|
||||
port = req->rq_disk->private_data;
|
||||
dr = &port->vio.drings[VIO_DRIVER_TX_RING];
|
||||
if (unlikely(vdc_tx_dring_avail(dr) < 1))
|
||||
goto wait;
|
||||
|
||||
blk_start_request(req);
|
||||
|
||||
if (__send_request(req) < 0) {
|
||||
blk_requeue_request(rq, req);
|
||||
wait:
|
||||
/* Avoid pointless unplugs. */
|
||||
blk_stop_queue(rq);
|
||||
break;
|
||||
|
||||
if (__send_request(req) < 0)
|
||||
__blk_end_request_all(req, -EIO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -656,25 +708,27 @@ static int probe_disk(struct vdc_port *port)
|
||||
if (comp.err)
|
||||
return comp.err;
|
||||
|
||||
err = generic_request(port, VD_OP_GET_VTOC,
|
||||
&port->label, sizeof(port->label));
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR PFX "VD_OP_GET_VTOC returns error %d\n", err);
|
||||
return err;
|
||||
}
|
||||
if (vdc_version_supported(port, 1, 1)) {
|
||||
/* vdisk_size should be set during the handshake, if it wasn't
|
||||
* then the underlying disk is reserved by another system
|
||||
*/
|
||||
if (port->vdisk_size == -1)
|
||||
return -ENODEV;
|
||||
} else {
|
||||
struct vio_disk_geom geom;
|
||||
|
||||
err = generic_request(port, VD_OP_GET_DISKGEOM,
|
||||
&port->geom, sizeof(port->geom));
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR PFX "VD_OP_GET_DISKGEOM returns "
|
||||
"error %d\n", err);
|
||||
return err;
|
||||
err = generic_request(port, VD_OP_GET_DISKGEOM,
|
||||
&geom, sizeof(geom));
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR PFX "VD_OP_GET_DISKGEOM returns "
|
||||
"error %d\n", err);
|
||||
return err;
|
||||
}
|
||||
port->vdisk_size = ((u64)geom.num_cyl *
|
||||
(u64)geom.num_hd *
|
||||
(u64)geom.num_sec);
|
||||
}
|
||||
|
||||
port->vdisk_size = ((u64)port->geom.num_cyl *
|
||||
(u64)port->geom.num_hd *
|
||||
(u64)port->geom.num_sec);
|
||||
|
||||
q = blk_init_queue(do_vdc_request, &port->vio.lock);
|
||||
if (!q) {
|
||||
printk(KERN_ERR PFX "%s: Could not allocate queue.\n",
|
||||
@@ -691,6 +745,10 @@ static int probe_disk(struct vdc_port *port)
|
||||
|
||||
port->disk = g;
|
||||
|
||||
/* Each segment in a request is up to an aligned page in size. */
|
||||
blk_queue_segment_boundary(q, PAGE_SIZE - 1);
|
||||
blk_queue_max_segment_size(q, PAGE_SIZE);
|
||||
|
||||
blk_queue_max_segments(q, port->ring_cookies);
|
||||
blk_queue_max_hw_sectors(q, port->max_xfer_size);
|
||||
g->major = vdc_major;
|
||||
@@ -704,9 +762,32 @@ static int probe_disk(struct vdc_port *port)
|
||||
|
||||
set_capacity(g, port->vdisk_size);
|
||||
|
||||
printk(KERN_INFO PFX "%s: %u sectors (%u MB)\n",
|
||||
if (vdc_version_supported(port, 1, 1)) {
|
||||
switch (port->vdisk_mtype) {
|
||||
case VD_MEDIA_TYPE_CD:
|
||||
pr_info(PFX "Virtual CDROM %s\n", port->disk_name);
|
||||
g->flags |= GENHD_FL_CD;
|
||||
g->flags |= GENHD_FL_REMOVABLE;
|
||||
set_disk_ro(g, 1);
|
||||
break;
|
||||
|
||||
case VD_MEDIA_TYPE_DVD:
|
||||
pr_info(PFX "Virtual DVD %s\n", port->disk_name);
|
||||
g->flags |= GENHD_FL_CD;
|
||||
g->flags |= GENHD_FL_REMOVABLE;
|
||||
set_disk_ro(g, 1);
|
||||
break;
|
||||
|
||||
case VD_MEDIA_TYPE_FIXED:
|
||||
pr_info(PFX "Virtual Hard disk %s\n", port->disk_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pr_info(PFX "%s: %u sectors (%u MB) protocol %d.%d\n",
|
||||
g->disk_name,
|
||||
port->vdisk_size, (port->vdisk_size >> (20 - 9)));
|
||||
port->vdisk_size, (port->vdisk_size >> (20 - 9)),
|
||||
port->vio.ver.major, port->vio.ver.minor);
|
||||
|
||||
add_disk(g);
|
||||
|
||||
@@ -765,6 +846,7 @@ static int vdc_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
|
||||
else
|
||||
snprintf(port->disk_name, sizeof(port->disk_name),
|
||||
VDCBLK_NAME "%c", 'a' + ((int)vdev->dev_no % 26));
|
||||
port->vdisk_size = -1;
|
||||
|
||||
err = vio_driver_init(&port->vio, vdev, VDEV_DISK,
|
||||
vdc_versions, ARRAY_SIZE(vdc_versions),
|
||||
|
||||
@@ -1637,8 +1637,7 @@ static int dispatch_ioctl(struct client *client,
|
||||
_IOC_SIZE(cmd) > sizeof(buffer))
|
||||
return -ENOTTY;
|
||||
|
||||
if (_IOC_DIR(cmd) == _IOC_READ)
|
||||
memset(&buffer, 0, _IOC_SIZE(cmd));
|
||||
memset(&buffer, 0, sizeof(buffer));
|
||||
|
||||
if (_IOC_DIR(cmd) & _IOC_WRITE)
|
||||
if (copy_from_user(&buffer, arg, _IOC_SIZE(cmd)))
|
||||
|
||||
@@ -2379,6 +2379,7 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1);
|
||||
tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
|
||||
WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp);
|
||||
WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0);
|
||||
}
|
||||
} else {
|
||||
tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]);
|
||||
|
||||
@@ -873,7 +873,13 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
|
||||
{
|
||||
struct alps_data *priv = psmouse->private;
|
||||
|
||||
if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */
|
||||
/*
|
||||
* Check if we are dealing with a bare PS/2 packet, presumably from
|
||||
* a device connected to the external PS/2 port. Because bare PS/2
|
||||
* protocol does not have enough constant bits to self-synchronize
|
||||
* properly we only do this if the device is fully synchronized.
|
||||
*/
|
||||
if (!psmouse->out_of_sync_cnt && (psmouse->packet[0] & 0xc8) == 0x08) {
|
||||
if (psmouse->pktcnt == 3) {
|
||||
alps_report_bare_ps2_packet(psmouse, psmouse->packet,
|
||||
true);
|
||||
@@ -1816,6 +1822,9 @@ int alps_init(struct psmouse *psmouse)
|
||||
/* We are having trouble resyncing ALPS touchpads so disable it for now */
|
||||
psmouse->resync_time = 0;
|
||||
|
||||
/* Allow 2 invalid packets without resetting device */
|
||||
psmouse->resetafter = psmouse->pktsize * 2;
|
||||
|
||||
return 0;
|
||||
|
||||
init_fail:
|
||||
|
||||
@@ -785,8 +785,7 @@ struct dm_raid_superblock {
|
||||
__le32 layout;
|
||||
__le32 stripe_sectors;
|
||||
|
||||
__u8 pad[452]; /* Round struct to 512 bytes. */
|
||||
/* Always set to 0 when writing. */
|
||||
/* Remainder of a logical block is zero-filled when writing (see super_sync()). */
|
||||
} __packed;
|
||||
|
||||
static int read_disk_sb(struct md_rdev *rdev, int size)
|
||||
@@ -823,7 +822,7 @@ static void super_sync(struct mddev *mddev, struct md_rdev *rdev)
|
||||
test_bit(Faulty, &(rs->dev[i].rdev.flags)))
|
||||
failed_devices |= (1ULL << i);
|
||||
|
||||
memset(sb, 0, sizeof(*sb));
|
||||
memset(sb + 1, 0, rdev->sb_size - sizeof(*sb));
|
||||
|
||||
sb->magic = cpu_to_le32(DM_RAID_MAGIC);
|
||||
sb->features = cpu_to_le32(0); /* No features yet */
|
||||
@@ -858,7 +857,11 @@ static int super_load(struct md_rdev *rdev, struct md_rdev *refdev)
|
||||
uint64_t events_sb, events_refsb;
|
||||
|
||||
rdev->sb_start = 0;
|
||||
rdev->sb_size = sizeof(*sb);
|
||||
rdev->sb_size = bdev_logical_block_size(rdev->meta_bdev);
|
||||
if (rdev->sb_size < sizeof(*sb) || rdev->sb_size > PAGE_SIZE) {
|
||||
DMERR("superblock size of a logical block is no longer valid");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = read_disk_sb(rdev, rdev->sb_size);
|
||||
if (ret)
|
||||
|
||||
@@ -42,6 +42,12 @@ struct btree_node {
|
||||
} __packed;
|
||||
|
||||
|
||||
/*
|
||||
* Locks a block using the btree node validator.
|
||||
*/
|
||||
int bn_read_lock(struct dm_btree_info *info, dm_block_t b,
|
||||
struct dm_block **result);
|
||||
|
||||
void inc_children(struct dm_transaction_manager *tm, struct btree_node *n,
|
||||
struct dm_btree_value_type *vt);
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ struct dm_block_validator btree_node_validator = {
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
|
||||
static int bn_read_lock(struct dm_btree_info *info, dm_block_t b,
|
||||
int bn_read_lock(struct dm_btree_info *info, dm_block_t b,
|
||||
struct dm_block **result)
|
||||
{
|
||||
return dm_tm_read_lock(info->tm, b, &btree_node_validator, result);
|
||||
|
||||
@@ -812,22 +812,26 @@ EXPORT_SYMBOL_GPL(dm_btree_find_highest_key);
|
||||
* FIXME: We shouldn't use a recursive algorithm when we have limited stack
|
||||
* space. Also this only works for single level trees.
|
||||
*/
|
||||
static int walk_node(struct ro_spine *s, dm_block_t block,
|
||||
static int walk_node(struct dm_btree_info *info, dm_block_t block,
|
||||
int (*fn)(void *context, uint64_t *keys, void *leaf),
|
||||
void *context)
|
||||
{
|
||||
int r;
|
||||
unsigned i, nr;
|
||||
struct dm_block *node;
|
||||
struct btree_node *n;
|
||||
uint64_t keys;
|
||||
|
||||
r = ro_step(s, block);
|
||||
n = ro_node(s);
|
||||
r = bn_read_lock(info, block, &node);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
n = dm_block_data(node);
|
||||
|
||||
nr = le32_to_cpu(n->header.nr_entries);
|
||||
for (i = 0; i < nr; i++) {
|
||||
if (le32_to_cpu(n->header.flags) & INTERNAL_NODE) {
|
||||
r = walk_node(s, value64(n, i), fn, context);
|
||||
r = walk_node(info, value64(n, i), fn, context);
|
||||
if (r)
|
||||
goto out;
|
||||
} else {
|
||||
@@ -839,7 +843,7 @@ static int walk_node(struct ro_spine *s, dm_block_t block,
|
||||
}
|
||||
|
||||
out:
|
||||
ro_pop(s);
|
||||
dm_tm_unlock(info->tm, node);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -847,15 +851,7 @@ int dm_btree_walk(struct dm_btree_info *info, dm_block_t root,
|
||||
int (*fn)(void *context, uint64_t *keys, void *leaf),
|
||||
void *context)
|
||||
{
|
||||
int r;
|
||||
struct ro_spine spine;
|
||||
|
||||
BUG_ON(info->levels > 1);
|
||||
|
||||
init_ro_spine(&spine, info);
|
||||
r = walk_node(&spine, root, fn, context);
|
||||
exit_ro_spine(&spine);
|
||||
|
||||
return r;
|
||||
return walk_node(info, root, fn, context);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dm_btree_walk);
|
||||
|
||||
@@ -156,6 +156,9 @@ static int ttusbdecfe_dvbs_diseqc_send_master_cmd(struct dvb_frontend* fe, struc
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00 };
|
||||
|
||||
if (cmd->msg_len > sizeof(b) - 4)
|
||||
return -EINVAL;
|
||||
|
||||
memcpy(&b[4], cmd->msg, cmd->msg_len);
|
||||
|
||||
state->config->send_command(fe, 0x72,
|
||||
|
||||
@@ -71,7 +71,7 @@ static int mei_cl_device_probe(struct device *dev)
|
||||
|
||||
dev_dbg(dev, "Device probe\n");
|
||||
|
||||
strncpy(id.name, dev_name(dev), MEI_CL_NAME_SIZE);
|
||||
strlcpy(id.name, dev_name(dev), sizeof(id.name));
|
||||
|
||||
return driver->probe(device, &id);
|
||||
}
|
||||
|
||||
@@ -191,6 +191,39 @@ void mlx4_en_deactivate_tx_ring(struct mlx4_en_priv *priv,
|
||||
MLX4_QP_STATE_RST, NULL, 0, 0, &ring->qp);
|
||||
}
|
||||
|
||||
static void mlx4_en_stamp_wqe(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_tx_ring *ring, int index,
|
||||
u8 owner)
|
||||
{
|
||||
__be32 stamp = cpu_to_be32(STAMP_VAL | (!!owner << STAMP_SHIFT));
|
||||
struct mlx4_en_tx_desc *tx_desc = ring->buf + index * TXBB_SIZE;
|
||||
struct mlx4_en_tx_info *tx_info = &ring->tx_info[index];
|
||||
void *end = ring->buf + ring->buf_size;
|
||||
__be32 *ptr = (__be32 *)tx_desc;
|
||||
int i;
|
||||
|
||||
/* Optimize the common case when there are no wraparounds */
|
||||
if (likely((void *)tx_desc + tx_info->nr_txbb * TXBB_SIZE <= end)) {
|
||||
/* Stamp the freed descriptor */
|
||||
for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE;
|
||||
i += STAMP_STRIDE) {
|
||||
*ptr = stamp;
|
||||
ptr += STAMP_DWORDS;
|
||||
}
|
||||
} else {
|
||||
/* Stamp the freed descriptor */
|
||||
for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE;
|
||||
i += STAMP_STRIDE) {
|
||||
*ptr = stamp;
|
||||
ptr += STAMP_DWORDS;
|
||||
if ((void *)ptr >= end) {
|
||||
ptr = ring->buf;
|
||||
stamp ^= cpu_to_be32(0x80000000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_tx_ring *ring,
|
||||
@@ -205,8 +238,6 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
|
||||
void *end = ring->buf + ring->buf_size;
|
||||
int frags = skb_shinfo(skb)->nr_frags;
|
||||
int i;
|
||||
__be32 *ptr = (__be32 *)tx_desc;
|
||||
__be32 stamp = cpu_to_be32(STAMP_VAL | (!!owner << STAMP_SHIFT));
|
||||
struct skb_shared_hwtstamps hwts;
|
||||
|
||||
if (timestamp) {
|
||||
@@ -232,12 +263,6 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
|
||||
skb_frag_size(frag), PCI_DMA_TODEVICE);
|
||||
}
|
||||
}
|
||||
/* Stamp the freed descriptor */
|
||||
for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE; i += STAMP_STRIDE) {
|
||||
*ptr = stamp;
|
||||
ptr += STAMP_DWORDS;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!tx_info->inl) {
|
||||
if ((void *) data >= end) {
|
||||
@@ -263,16 +288,6 @@ static u32 mlx4_en_free_tx_desc(struct mlx4_en_priv *priv,
|
||||
++data;
|
||||
}
|
||||
}
|
||||
/* Stamp the freed descriptor */
|
||||
for (i = 0; i < tx_info->nr_txbb * TXBB_SIZE; i += STAMP_STRIDE) {
|
||||
*ptr = stamp;
|
||||
ptr += STAMP_DWORDS;
|
||||
if ((void *) ptr >= end) {
|
||||
ptr = ring->buf;
|
||||
stamp ^= cpu_to_be32(0x80000000);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
dev_kfree_skb_any(skb);
|
||||
return tx_info->nr_txbb;
|
||||
@@ -318,8 +333,9 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
|
||||
struct mlx4_en_tx_ring *ring = &priv->tx_ring[cq->ring];
|
||||
struct mlx4_cqe *cqe;
|
||||
u16 index;
|
||||
u16 new_index, ring_index;
|
||||
u16 new_index, ring_index, stamp_index;
|
||||
u32 txbbs_skipped = 0;
|
||||
u32 txbbs_stamp = 0;
|
||||
u32 cons_index = mcq->cons_index;
|
||||
int size = cq->size;
|
||||
u32 size_mask = ring->size_mask;
|
||||
@@ -335,6 +351,7 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
|
||||
index = cons_index & size_mask;
|
||||
cqe = &buf[(index << factor) + factor];
|
||||
ring_index = ring->cons & size_mask;
|
||||
stamp_index = ring_index;
|
||||
|
||||
/* Process all completed CQEs */
|
||||
while (XNOR(cqe->owner_sr_opcode & MLX4_CQE_OWNER_MASK,
|
||||
@@ -359,6 +376,12 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
|
||||
priv, ring, ring_index,
|
||||
!!((ring->cons + txbbs_skipped) &
|
||||
ring->size), timestamp);
|
||||
|
||||
mlx4_en_stamp_wqe(priv, ring, stamp_index,
|
||||
!!((ring->cons + txbbs_stamp) &
|
||||
ring->size));
|
||||
stamp_index = ring_index;
|
||||
txbbs_stamp = txbbs_skipped;
|
||||
packets++;
|
||||
bytes += ring->tx_info[ring_index].nr_bytes;
|
||||
} while (ring_index != new_index);
|
||||
|
||||
@@ -656,7 +656,7 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
spin_lock_irqsave(&port->vio.lock, flags);
|
||||
|
||||
dr = &port->vio.drings[VIO_DRIVER_TX_RING];
|
||||
if (unlikely(vnet_tx_dring_avail(dr) < 2)) {
|
||||
if (unlikely(vnet_tx_dring_avail(dr) < 1)) {
|
||||
if (!netif_queue_stopped(dev)) {
|
||||
netif_stop_queue(dev);
|
||||
|
||||
@@ -704,7 +704,7 @@ static int vnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
dev->stats.tx_bytes += skb->len;
|
||||
|
||||
dr->prod = (dr->prod + 1) & (VNET_TX_RING_SIZE - 1);
|
||||
if (unlikely(vnet_tx_dring_avail(dr) < 2)) {
|
||||
if (unlikely(vnet_tx_dring_avail(dr) < 1)) {
|
||||
netif_stop_queue(dev);
|
||||
if (vnet_tx_dring_avail(dr) > VNET_TX_WAKEUP_THRESH(dr))
|
||||
netif_wake_queue(dev);
|
||||
|
||||
@@ -625,6 +625,8 @@ static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb,
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||
vnet_hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
|
||||
vnet_hdr->csum_start = skb_checksum_start_offset(skb);
|
||||
if (vlan_tx_tag_present(skb))
|
||||
vnet_hdr->csum_start += VLAN_HLEN;
|
||||
vnet_hdr->csum_offset = skb->csum_offset;
|
||||
} else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
|
||||
vnet_hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID;
|
||||
|
||||
@@ -489,6 +489,7 @@ enum iwl_trans_state {
|
||||
* Set during transport allocation.
|
||||
* @hw_id_str: a string with info about HW ID. Set during transport allocation.
|
||||
* @pm_support: set to true in start_hw if link pm is supported
|
||||
* @ltr_enabled: set to true if the LTR is enabled
|
||||
* @dev_cmd_pool: pool for Tx cmd allocation - for internal use only.
|
||||
* The user should use iwl_trans_{alloc,free}_tx_cmd.
|
||||
* @dev_cmd_headroom: room needed for the transport's private use before the
|
||||
@@ -513,6 +514,7 @@ struct iwl_trans {
|
||||
u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size;
|
||||
|
||||
bool pm_support;
|
||||
bool ltr_enabled;
|
||||
|
||||
/* The following fields are internal only */
|
||||
struct kmem_cache *dev_cmd_pool;
|
||||
|
||||
@@ -67,7 +67,40 @@
|
||||
/* Power Management Commands, Responses, Notifications */
|
||||
|
||||
/**
|
||||
* enum iwl_scan_flags - masks for power table command flags
|
||||
* enum iwl_ltr_config_flags - masks for LTR config command flags
|
||||
* @LTR_CFG_FLAG_FEATURE_ENABLE: Feature operational status
|
||||
* @LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS: allow LTR change on shadow
|
||||
* memory access
|
||||
* @LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH: allow LTR msg send on ANY LTR
|
||||
* reg change
|
||||
* @LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3: allow LTR msg send on transition from
|
||||
* D0 to D3
|
||||
* @LTR_CFG_FLAG_SW_SET_SHORT: fixed static short LTR register
|
||||
* @LTR_CFG_FLAG_SW_SET_LONG: fixed static short LONG register
|
||||
* @LTR_CFG_FLAG_DENIE_C10_ON_PD: allow going into C10 on PD
|
||||
*/
|
||||
enum iwl_ltr_config_flags {
|
||||
LTR_CFG_FLAG_FEATURE_ENABLE = BIT(0),
|
||||
LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS = BIT(1),
|
||||
LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH = BIT(2),
|
||||
LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3 = BIT(3),
|
||||
LTR_CFG_FLAG_SW_SET_SHORT = BIT(4),
|
||||
LTR_CFG_FLAG_SW_SET_LONG = BIT(5),
|
||||
LTR_CFG_FLAG_DENIE_C10_ON_PD = BIT(6),
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_ltr_config_cmd - configures the LTR
|
||||
* @flags: See %enum iwl_ltr_config_flags
|
||||
*/
|
||||
struct iwl_ltr_config_cmd {
|
||||
__le32 flags;
|
||||
__le32 static_long;
|
||||
__le32 static_short;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* enum iwl_power_flags - masks for power table command flags
|
||||
* @POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off
|
||||
* receiver and transmitter. '0' - does not allow.
|
||||
* @POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK: '0' Driver disables power management,
|
||||
|
||||
@@ -138,6 +138,7 @@ enum {
|
||||
|
||||
/* Power */
|
||||
POWER_TABLE_CMD = 0x77,
|
||||
LTR_CONFIG = 0xee,
|
||||
|
||||
/* Scanning */
|
||||
SCAN_REQUEST_CMD = 0x80,
|
||||
|
||||
@@ -443,6 +443,15 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
if (mvm->trans->ltr_enabled) {
|
||||
struct iwl_ltr_config_cmd cmd = {
|
||||
.flags = cpu_to_le32(LTR_CFG_FLAG_FEATURE_ENABLE),
|
||||
};
|
||||
|
||||
WARN_ON(iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0,
|
||||
sizeof(cmd), &cmd));
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(mvm, "RT uCode started.\n");
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -293,6 +293,7 @@ static const char *iwl_mvm_cmd_strings[REPLY_MAX] = {
|
||||
CMD(BT_PROFILE_NOTIFICATION),
|
||||
CMD(BT_CONFIG),
|
||||
CMD(MCAST_FILTER_CMD),
|
||||
CMD(LTR_CONFIG),
|
||||
};
|
||||
#undef CMD
|
||||
|
||||
|
||||
@@ -116,11 +116,13 @@ static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux)
|
||||
|
||||
/* PCI registers */
|
||||
#define PCI_CFG_RETRY_TIMEOUT 0x041
|
||||
#define PCI_EXP_DEVCTL2_LTR_EN 0x0400
|
||||
|
||||
static void iwl_pcie_apm_config(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
u16 lctl;
|
||||
u16 cap;
|
||||
|
||||
/*
|
||||
* HW bug W/A for instability in PCIe bus L0S->L1 transition.
|
||||
@@ -131,16 +133,17 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans)
|
||||
* power savings, even without L1.
|
||||
*/
|
||||
pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl);
|
||||
if (lctl & PCI_EXP_LNKCTL_ASPM_L1) {
|
||||
/* L1-ASPM enabled; disable(!) L0S */
|
||||
if (lctl & PCI_EXP_LNKCTL_ASPM_L1)
|
||||
iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
|
||||
dev_info(trans->dev, "L1 Enabled; Disabling L0S\n");
|
||||
} else {
|
||||
/* L1-ASPM disabled; enable(!) L0S */
|
||||
else
|
||||
iwl_clear_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
|
||||
dev_info(trans->dev, "L1 Disabled; Enabling L0S\n");
|
||||
}
|
||||
trans->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S);
|
||||
|
||||
pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_DEVCTL2, &cap);
|
||||
trans->ltr_enabled = cap & PCI_EXP_DEVCTL2_LTR_EN;
|
||||
dev_info(trans->dev, "L1 %sabled - LTR %sabled\n",
|
||||
(lctl & PCI_EXP_LNKCTL_ASPM_L1) ? "En" : "Dis",
|
||||
trans->ltr_enabled ? "En" : "Dis");
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -163,18 +163,24 @@ static void dell_wmi_notify(u32 value, void *context)
|
||||
const struct key_entry *key;
|
||||
int reported_key;
|
||||
u16 *buffer_entry = (u16 *)obj->buffer.pointer;
|
||||
int buffer_size = obj->buffer.length/2;
|
||||
|
||||
if (dell_new_hk_type && (buffer_entry[1] != 0x10)) {
|
||||
if (buffer_size >= 2 && dell_new_hk_type && buffer_entry[1] != 0x10) {
|
||||
pr_info("Received unknown WMI event (0x%x)\n",
|
||||
buffer_entry[1]);
|
||||
kfree(obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (dell_new_hk_type || buffer_entry[1] == 0x0)
|
||||
if (buffer_size >= 3 && (dell_new_hk_type || buffer_entry[1] == 0x0))
|
||||
reported_key = (int)buffer_entry[2];
|
||||
else
|
||||
else if (buffer_size >= 2)
|
||||
reported_key = (int)buffer_entry[1] & 0xffff;
|
||||
else {
|
||||
pr_info("Received unknown WMI event\n");
|
||||
kfree(obj);
|
||||
return;
|
||||
}
|
||||
|
||||
key = sparse_keymap_entry_from_scancode(dell_wmi_input_dev,
|
||||
reported_key);
|
||||
|
||||
+2
-2
@@ -1206,8 +1206,8 @@ static void complete_scsi_command(struct CommandList *cp)
|
||||
scsi_set_resid(cmd, ei->ResidualCnt);
|
||||
|
||||
if (ei->CommandStatus == 0) {
|
||||
cmd->scsi_done(cmd);
|
||||
cmd_free(h, cp);
|
||||
cmd->scsi_done(cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1380,8 +1380,8 @@ static void complete_scsi_command(struct CommandList *cp)
|
||||
dev_warn(&h->pdev->dev, "cp %p returned unknown status %x\n",
|
||||
cp, ei->CommandStatus);
|
||||
}
|
||||
cmd->scsi_done(cmd);
|
||||
cmd_free(h, cp);
|
||||
cmd->scsi_done(cmd);
|
||||
}
|
||||
|
||||
static void hpsa_pci_unmap(struct pci_dev *pdev,
|
||||
|
||||
@@ -1689,8 +1689,10 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
|
||||
* is no point trying to lock the door of an off-line device.
|
||||
*/
|
||||
shost_for_each_device(sdev, shost) {
|
||||
if (scsi_device_online(sdev) && sdev->locked)
|
||||
if (scsi_device_online(sdev) && sdev->was_reset && sdev->locked) {
|
||||
scsi_eh_lock_door(sdev);
|
||||
sdev->was_reset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+8
-6
@@ -159,14 +159,16 @@ out:
|
||||
|
||||
int ioprio_best(unsigned short aprio, unsigned short bprio)
|
||||
{
|
||||
unsigned short aclass = IOPRIO_PRIO_CLASS(aprio);
|
||||
unsigned short bclass = IOPRIO_PRIO_CLASS(bprio);
|
||||
unsigned short aclass;
|
||||
unsigned short bclass;
|
||||
|
||||
if (aclass == IOPRIO_CLASS_NONE)
|
||||
aclass = IOPRIO_CLASS_BE;
|
||||
if (bclass == IOPRIO_CLASS_NONE)
|
||||
bclass = IOPRIO_CLASS_BE;
|
||||
if (!ioprio_valid(aprio))
|
||||
aprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, IOPRIO_NORM);
|
||||
if (!ioprio_valid(bprio))
|
||||
bprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, IOPRIO_NORM);
|
||||
|
||||
aclass = IOPRIO_PRIO_CLASS(aprio);
|
||||
bclass = IOPRIO_PRIO_CLASS(bprio);
|
||||
if (aclass == bclass)
|
||||
return min(aprio, bprio);
|
||||
if (aclass > bclass)
|
||||
|
||||
+23
-2
@@ -108,6 +108,8 @@ again:
|
||||
continue;
|
||||
if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
|
||||
continue;
|
||||
if (!nfs4_valid_open_stateid(state))
|
||||
continue;
|
||||
if (!nfs4_stateid_match(&state->stateid, stateid))
|
||||
continue;
|
||||
get_nfs_open_context(ctx);
|
||||
@@ -175,7 +177,11 @@ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid, issync);
|
||||
if (!test_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
|
||||
res = nfs4_proc_delegreturn(inode,
|
||||
delegation->cred,
|
||||
&delegation->stateid,
|
||||
issync);
|
||||
nfs_free_delegation(delegation);
|
||||
return res;
|
||||
}
|
||||
@@ -361,11 +367,13 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation
|
||||
{
|
||||
struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
|
||||
struct nfs_inode *nfsi = NFS_I(inode);
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
if (delegation == NULL)
|
||||
return 0;
|
||||
do {
|
||||
if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags))
|
||||
break;
|
||||
err = nfs_delegation_claim_opens(inode, &delegation->stateid);
|
||||
if (!issync || err != -EAGAIN)
|
||||
break;
|
||||
@@ -586,10 +594,23 @@ static void nfs_client_mark_return_unused_delegation_types(struct nfs_client *cl
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void nfs_revoke_delegation(struct inode *inode)
|
||||
{
|
||||
struct nfs_delegation *delegation;
|
||||
rcu_read_lock();
|
||||
delegation = rcu_dereference(NFS_I(inode)->delegation);
|
||||
if (delegation != NULL) {
|
||||
set_bit(NFS_DELEGATION_REVOKED, &delegation->flags);
|
||||
nfs_mark_return_delegation(NFS_SERVER(inode), delegation);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void nfs_remove_bad_delegation(struct inode *inode)
|
||||
{
|
||||
struct nfs_delegation *delegation;
|
||||
|
||||
nfs_revoke_delegation(inode);
|
||||
delegation = nfs_inode_detach_delegation(inode);
|
||||
if (delegation) {
|
||||
nfs_inode_find_state_and_recover(inode, &delegation->stateid);
|
||||
|
||||
@@ -31,6 +31,7 @@ enum {
|
||||
NFS_DELEGATION_RETURN_IF_CLOSED,
|
||||
NFS_DELEGATION_REFERENCED,
|
||||
NFS_DELEGATION_RETURNING,
|
||||
NFS_DELEGATION_REVOKED,
|
||||
};
|
||||
|
||||
int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
|
||||
|
||||
@@ -180,6 +180,7 @@ static void nfs_direct_req_free(struct kref *kref)
|
||||
{
|
||||
struct nfs_direct_req *dreq = container_of(kref, struct nfs_direct_req, kref);
|
||||
|
||||
nfs_free_pnfs_ds_cinfo(&dreq->ds_cinfo);
|
||||
if (dreq->l_ctx != NULL)
|
||||
nfs_put_lock_context(dreq->l_ctx);
|
||||
if (dreq->ctx != NULL)
|
||||
|
||||
+1
-1
@@ -519,7 +519,7 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME;
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
/* Flush out writes to the server in order to update c/mtime. */
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
|
||||
+24
-2
@@ -1416,7 +1416,7 @@ static int nfs4_handle_delegation_recall_error(struct nfs_server *server, struct
|
||||
nfs_inode_find_state_and_recover(state->inode,
|
||||
stateid);
|
||||
nfs4_schedule_stateid_recovery(server, state);
|
||||
return 0;
|
||||
return -EAGAIN;
|
||||
case -NFS4ERR_DELAY:
|
||||
case -NFS4ERR_GRACE:
|
||||
set_bit(NFS_DELEGATED_STATE, &state->flags);
|
||||
@@ -1845,6 +1845,28 @@ static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *sta
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void nfs_finish_clear_delegation_stateid(struct nfs4_state *state)
|
||||
{
|
||||
nfs_remove_bad_delegation(state->inode);
|
||||
write_seqlock(&state->seqlock);
|
||||
nfs4_stateid_copy(&state->stateid, &state->open_stateid);
|
||||
write_sequnlock(&state->seqlock);
|
||||
clear_bit(NFS_DELEGATED_STATE, &state->flags);
|
||||
}
|
||||
|
||||
static void nfs40_clear_delegation_stateid(struct nfs4_state *state)
|
||||
{
|
||||
if (rcu_access_pointer(NFS_I(state->inode)->delegation) != NULL)
|
||||
nfs_finish_clear_delegation_stateid(state);
|
||||
}
|
||||
|
||||
static int nfs40_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
|
||||
{
|
||||
/* NFSv4.0 doesn't allow for delegation recovery on open expire */
|
||||
nfs40_clear_delegation_stateid(state);
|
||||
return nfs4_open_expired(sp, state);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NFS_V4_1)
|
||||
static void nfs41_clear_delegation_stateid(struct nfs4_state *state)
|
||||
{
|
||||
@@ -6974,7 +6996,7 @@ static const struct nfs4_state_recovery_ops nfs41_reboot_recovery_ops = {
|
||||
static const struct nfs4_state_recovery_ops nfs40_nograce_recovery_ops = {
|
||||
.owner_flag_bit = NFS_OWNER_RECLAIM_NOGRACE,
|
||||
.state_flag_bit = NFS_STATE_RECLAIM_NOGRACE,
|
||||
.recover_open = nfs4_open_expired,
|
||||
.recover_open = nfs40_open_expired,
|
||||
.recover_lock = nfs4_lock_expired,
|
||||
.establish_clid = nfs4_init_clientid,
|
||||
.get_clid_cred = nfs4_get_setclientid_cred,
|
||||
|
||||
@@ -285,7 +285,7 @@ extern struct clocksource* clocksource_get_next(void);
|
||||
extern void clocksource_change_rating(struct clocksource *cs, int rating);
|
||||
extern void clocksource_suspend(void);
|
||||
extern void clocksource_resume(void);
|
||||
extern struct clocksource * __init __weak clocksource_default_clock(void);
|
||||
extern struct clocksource * __init clocksource_default_clock(void);
|
||||
extern void clocksource_mark_unstable(struct clocksource *cs);
|
||||
|
||||
extern void
|
||||
|
||||
@@ -283,7 +283,7 @@ struct kgdb_io {
|
||||
|
||||
extern struct kgdb_arch arch_kgdb_ops;
|
||||
|
||||
extern unsigned long __weak kgdb_arch_pc(int exception, struct pt_regs *regs);
|
||||
extern unsigned long kgdb_arch_pc(int exception, struct pt_regs *regs);
|
||||
|
||||
#ifdef CONFIG_SERIAL_KGDB_NMI
|
||||
extern int kgdb_register_nmi_console(void);
|
||||
|
||||
@@ -124,6 +124,25 @@ extern void mem_cgroup_print_oom_info(struct mem_cgroup *memcg,
|
||||
extern void mem_cgroup_replace_page_cache(struct page *oldpage,
|
||||
struct page *newpage);
|
||||
|
||||
static inline void mem_cgroup_oom_enable(void)
|
||||
{
|
||||
WARN_ON(current->memcg_oom.may_oom);
|
||||
current->memcg_oom.may_oom = 1;
|
||||
}
|
||||
|
||||
static inline void mem_cgroup_oom_disable(void)
|
||||
{
|
||||
WARN_ON(!current->memcg_oom.may_oom);
|
||||
current->memcg_oom.may_oom = 0;
|
||||
}
|
||||
|
||||
static inline bool task_in_memcg_oom(struct task_struct *p)
|
||||
{
|
||||
return p->memcg_oom.memcg;
|
||||
}
|
||||
|
||||
bool mem_cgroup_oom_synchronize(bool wait);
|
||||
|
||||
#ifdef CONFIG_MEMCG_SWAP
|
||||
extern int do_swap_account;
|
||||
#endif
|
||||
@@ -347,6 +366,24 @@ static inline void mem_cgroup_end_update_page_stat(struct page *page,
|
||||
{
|
||||
}
|
||||
|
||||
static inline void mem_cgroup_oom_enable(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void mem_cgroup_oom_disable(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline bool task_in_memcg_oom(struct task_struct *p)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool mem_cgroup_oom_synchronize(bool wait)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void mem_cgroup_inc_page_stat(struct page *page,
|
||||
enum mem_cgroup_page_stat_item idx)
|
||||
{
|
||||
|
||||
@@ -168,6 +168,7 @@ extern pgprot_t protection_map[16];
|
||||
#define FAULT_FLAG_RETRY_NOWAIT 0x10 /* Don't drop mmap_sem and wait when retrying */
|
||||
#define FAULT_FLAG_KILLABLE 0x20 /* The fault task is in SIGKILL killable region */
|
||||
#define FAULT_FLAG_TRIED 0x40 /* second try */
|
||||
#define FAULT_FLAG_USER 0x80 /* The fault originated in userspace */
|
||||
|
||||
/*
|
||||
* vm_fault is filled by the the pagefault handler and passed to the vma's
|
||||
|
||||
@@ -1184,11 +1184,22 @@ struct nfs41_free_stateid_res {
|
||||
unsigned int status;
|
||||
};
|
||||
|
||||
static inline void
|
||||
nfs_free_pnfs_ds_cinfo(struct pnfs_ds_commit_info *cinfo)
|
||||
{
|
||||
kfree(cinfo->buckets);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct pnfs_ds_commit_info {
|
||||
};
|
||||
|
||||
static inline void
|
||||
nfs_free_pnfs_ds_cinfo(struct pnfs_ds_commit_info *cinfo)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NFS_V4_1 */
|
||||
|
||||
struct nfs_page;
|
||||
|
||||
@@ -1526,6 +1526,12 @@ struct task_struct {
|
||||
unsigned long memsw_nr_pages; /* uncharged mem+swap usage */
|
||||
} memcg_batch;
|
||||
unsigned int memcg_kmem_skip_account;
|
||||
struct memcg_oom_info {
|
||||
struct mem_cgroup *memcg;
|
||||
gfp_t gfp_mask;
|
||||
int order;
|
||||
unsigned int may_oom:1;
|
||||
} memcg_oom;
|
||||
#endif
|
||||
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
||||
atomic_t ptrace_bp_refcnt;
|
||||
|
||||
@@ -540,6 +540,11 @@ static inline void sctp_assoc_pending_pmtu(struct sock *sk, struct sctp_associat
|
||||
asoc->pmtu_pending = 0;
|
||||
}
|
||||
|
||||
static inline bool sctp_chunk_pending(const struct sctp_chunk *chunk)
|
||||
{
|
||||
return !list_empty(&chunk->list);
|
||||
}
|
||||
|
||||
/* Walk through a list of TLV parameters. Don't trust the
|
||||
* individual parameter lengths and instead depend on
|
||||
* the chunk length to indicate when to stop. Make sure
|
||||
|
||||
@@ -255,9 +255,9 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *,
|
||||
int, __be16);
|
||||
struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
|
||||
union sctp_addr *addr);
|
||||
int sctp_verify_asconf(const struct sctp_association *asoc,
|
||||
struct sctp_paramhdr *param_hdr, void *chunk_end,
|
||||
struct sctp_paramhdr **errp);
|
||||
bool sctp_verify_asconf(const struct sctp_association *asoc,
|
||||
struct sctp_chunk *chunk, bool addr_param_needed,
|
||||
struct sctp_paramhdr **errp);
|
||||
struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
|
||||
struct sctp_chunk *asconf);
|
||||
int sctp_process_asconf_ack(struct sctp_association *asoc,
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
#define XT_BPF_MAX_NUM_INSTR 64
|
||||
|
||||
struct sk_filter;
|
||||
|
||||
struct xt_bpf_info {
|
||||
__u16 bpf_program_num_elem;
|
||||
struct sock_filter bpf_program[XT_BPF_MAX_NUM_INSTR];
|
||||
|
||||
+1
-2
@@ -123,7 +123,6 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct ctl_table ipc_table;
|
||||
size_t lenp_bef = *lenp;
|
||||
int oldval;
|
||||
int rc;
|
||||
|
||||
@@ -133,7 +132,7 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,
|
||||
|
||||
rc = proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
|
||||
|
||||
if (write && !rc && lenp_bef == *lenp) {
|
||||
if (write && !rc) {
|
||||
int newval = *((int *)(ipc_table.data));
|
||||
/*
|
||||
* The file "auto_msgmni" has correctly been set.
|
||||
|
||||
@@ -154,6 +154,7 @@ static struct audit_chunk *alloc_chunk(int count)
|
||||
chunk->owners[i].index = i;
|
||||
}
|
||||
fsnotify_init_mark(&chunk->mark, audit_tree_destroy_watch);
|
||||
chunk->mark.mask = FS_IN_IGNORED;
|
||||
return chunk;
|
||||
}
|
||||
|
||||
|
||||
+21
-1
@@ -39,6 +39,7 @@
|
||||
#include <linux/hw_breakpoint.h>
|
||||
#include <linux/mm_types.h>
|
||||
#include <linux/cgroup.h>
|
||||
#include <linux/compat.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
@@ -3497,6 +3498,25 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
static long perf_compat_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
switch (_IOC_NR(cmd)) {
|
||||
case _IOC_NR(PERF_EVENT_IOC_SET_FILTER):
|
||||
/* Fix up pointer size (usually 4 -> 8 in 32-on-64-bit case */
|
||||
if (_IOC_SIZE(cmd) == sizeof(compat_uptr_t)) {
|
||||
cmd &= ~IOCSIZE_MASK;
|
||||
cmd |= sizeof(void *) << IOCSIZE_SHIFT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return perf_ioctl(file, cmd, arg);
|
||||
}
|
||||
#else
|
||||
# define perf_compat_ioctl NULL
|
||||
#endif
|
||||
|
||||
int perf_event_task_enable(void)
|
||||
{
|
||||
struct perf_event *event;
|
||||
@@ -3968,7 +3988,7 @@ static const struct file_operations perf_fops = {
|
||||
.read = perf_read,
|
||||
.poll = perf_poll,
|
||||
.unlocked_ioctl = perf_ioctl,
|
||||
.compat_ioctl = perf_ioctl,
|
||||
.compat_ioctl = perf_compat_ioctl,
|
||||
.mmap = perf_mmap,
|
||||
.fasync = perf_fasync,
|
||||
};
|
||||
|
||||
+108
-76
@@ -302,6 +302,7 @@ struct mem_cgroup {
|
||||
|
||||
bool oom_lock;
|
||||
atomic_t under_oom;
|
||||
atomic_t oom_wakeups;
|
||||
|
||||
atomic_t refcnt;
|
||||
|
||||
@@ -2090,15 +2091,18 @@ static int mem_cgroup_soft_reclaim(struct mem_cgroup *root_memcg,
|
||||
return total;
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(memcg_oom_lock);
|
||||
|
||||
/*
|
||||
* Check OOM-Killer is already running under our hierarchy.
|
||||
* If someone is running, return false.
|
||||
* Has to be called with memcg_oom_lock
|
||||
*/
|
||||
static bool mem_cgroup_oom_lock(struct mem_cgroup *memcg)
|
||||
static bool mem_cgroup_oom_trylock(struct mem_cgroup *memcg)
|
||||
{
|
||||
struct mem_cgroup *iter, *failed = NULL;
|
||||
|
||||
spin_lock(&memcg_oom_lock);
|
||||
|
||||
for_each_mem_cgroup_tree(iter, memcg) {
|
||||
if (iter->oom_lock) {
|
||||
/*
|
||||
@@ -2112,33 +2116,33 @@ static bool mem_cgroup_oom_lock(struct mem_cgroup *memcg)
|
||||
iter->oom_lock = true;
|
||||
}
|
||||
|
||||
if (!failed)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* OK, we failed to lock the whole subtree so we have to clean up
|
||||
* what we set up to the failing subtree
|
||||
*/
|
||||
for_each_mem_cgroup_tree(iter, memcg) {
|
||||
if (iter == failed) {
|
||||
mem_cgroup_iter_break(memcg, iter);
|
||||
break;
|
||||
if (failed) {
|
||||
/*
|
||||
* OK, we failed to lock the whole subtree so we have
|
||||
* to clean up what we set up to the failing subtree
|
||||
*/
|
||||
for_each_mem_cgroup_tree(iter, memcg) {
|
||||
if (iter == failed) {
|
||||
mem_cgroup_iter_break(memcg, iter);
|
||||
break;
|
||||
}
|
||||
iter->oom_lock = false;
|
||||
}
|
||||
iter->oom_lock = false;
|
||||
}
|
||||
return false;
|
||||
|
||||
spin_unlock(&memcg_oom_lock);
|
||||
|
||||
return !failed;
|
||||
}
|
||||
|
||||
/*
|
||||
* Has to be called with memcg_oom_lock
|
||||
*/
|
||||
static int mem_cgroup_oom_unlock(struct mem_cgroup *memcg)
|
||||
static void mem_cgroup_oom_unlock(struct mem_cgroup *memcg)
|
||||
{
|
||||
struct mem_cgroup *iter;
|
||||
|
||||
spin_lock(&memcg_oom_lock);
|
||||
for_each_mem_cgroup_tree(iter, memcg)
|
||||
iter->oom_lock = false;
|
||||
return 0;
|
||||
spin_unlock(&memcg_oom_lock);
|
||||
}
|
||||
|
||||
static void mem_cgroup_mark_under_oom(struct mem_cgroup *memcg)
|
||||
@@ -2162,7 +2166,6 @@ static void mem_cgroup_unmark_under_oom(struct mem_cgroup *memcg)
|
||||
atomic_add_unless(&iter->under_oom, -1, 0);
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(memcg_oom_lock);
|
||||
static DECLARE_WAIT_QUEUE_HEAD(memcg_oom_waitq);
|
||||
|
||||
struct oom_wait_info {
|
||||
@@ -2192,6 +2195,7 @@ static int memcg_oom_wake_function(wait_queue_t *wait,
|
||||
|
||||
static void memcg_wakeup_oom(struct mem_cgroup *memcg)
|
||||
{
|
||||
atomic_inc(&memcg->oom_wakeups);
|
||||
/* for filtering, pass "memcg" as argument. */
|
||||
__wake_up(&memcg_oom_waitq, TASK_NORMAL, 0, memcg);
|
||||
}
|
||||
@@ -2202,57 +2206,97 @@ static void memcg_oom_recover(struct mem_cgroup *memcg)
|
||||
memcg_wakeup_oom(memcg);
|
||||
}
|
||||
|
||||
/*
|
||||
* try to call OOM killer. returns false if we should exit memory-reclaim loop.
|
||||
*/
|
||||
static bool mem_cgroup_handle_oom(struct mem_cgroup *memcg, gfp_t mask,
|
||||
int order)
|
||||
static void mem_cgroup_oom(struct mem_cgroup *memcg, gfp_t mask, int order)
|
||||
{
|
||||
if (!current->memcg_oom.may_oom)
|
||||
return;
|
||||
/*
|
||||
* We are in the middle of the charge context here, so we
|
||||
* don't want to block when potentially sitting on a callstack
|
||||
* that holds all kinds of filesystem and mm locks.
|
||||
*
|
||||
* Also, the caller may handle a failed allocation gracefully
|
||||
* (like optional page cache readahead) and so an OOM killer
|
||||
* invocation might not even be necessary.
|
||||
*
|
||||
* That's why we don't do anything here except remember the
|
||||
* OOM context and then deal with it at the end of the page
|
||||
* fault when the stack is unwound, the locks are released,
|
||||
* and when we know whether the fault was overall successful.
|
||||
*/
|
||||
css_get(&memcg->css);
|
||||
current->memcg_oom.memcg = memcg;
|
||||
current->memcg_oom.gfp_mask = mask;
|
||||
current->memcg_oom.order = order;
|
||||
}
|
||||
|
||||
/**
|
||||
* mem_cgroup_oom_synchronize - complete memcg OOM handling
|
||||
* @handle: actually kill/wait or just clean up the OOM state
|
||||
*
|
||||
* This has to be called at the end of a page fault if the memcg OOM
|
||||
* handler was enabled.
|
||||
*
|
||||
* Memcg supports userspace OOM handling where failed allocations must
|
||||
* sleep on a waitqueue until the userspace task resolves the
|
||||
* situation. Sleeping directly in the charge context with all kinds
|
||||
* of locks held is not a good idea, instead we remember an OOM state
|
||||
* in the task and mem_cgroup_oom_synchronize() has to be called at
|
||||
* the end of the page fault to complete the OOM handling.
|
||||
*
|
||||
* Returns %true if an ongoing memcg OOM situation was detected and
|
||||
* completed, %false otherwise.
|
||||
*/
|
||||
bool mem_cgroup_oom_synchronize(bool handle)
|
||||
{
|
||||
struct mem_cgroup *memcg = current->memcg_oom.memcg;
|
||||
struct oom_wait_info owait;
|
||||
bool locked, need_to_kill;
|
||||
bool locked;
|
||||
|
||||
/* OOM is global, do not handle */
|
||||
if (!memcg)
|
||||
return false;
|
||||
|
||||
if (!handle)
|
||||
goto cleanup;
|
||||
|
||||
owait.memcg = memcg;
|
||||
owait.wait.flags = 0;
|
||||
owait.wait.func = memcg_oom_wake_function;
|
||||
owait.wait.private = current;
|
||||
INIT_LIST_HEAD(&owait.wait.task_list);
|
||||
need_to_kill = true;
|
||||
|
||||
prepare_to_wait(&memcg_oom_waitq, &owait.wait, TASK_KILLABLE);
|
||||
mem_cgroup_mark_under_oom(memcg);
|
||||
|
||||
/* At first, try to OOM lock hierarchy under memcg.*/
|
||||
spin_lock(&memcg_oom_lock);
|
||||
locked = mem_cgroup_oom_lock(memcg);
|
||||
/*
|
||||
* Even if signal_pending(), we can't quit charge() loop without
|
||||
* accounting. So, UNINTERRUPTIBLE is appropriate. But SIGKILL
|
||||
* under OOM is always welcomed, use TASK_KILLABLE here.
|
||||
*/
|
||||
prepare_to_wait(&memcg_oom_waitq, &owait.wait, TASK_KILLABLE);
|
||||
if (!locked || memcg->oom_kill_disable)
|
||||
need_to_kill = false;
|
||||
locked = mem_cgroup_oom_trylock(memcg);
|
||||
|
||||
if (locked)
|
||||
mem_cgroup_oom_notify(memcg);
|
||||
spin_unlock(&memcg_oom_lock);
|
||||
|
||||
if (need_to_kill) {
|
||||
if (locked && !memcg->oom_kill_disable) {
|
||||
mem_cgroup_unmark_under_oom(memcg);
|
||||
finish_wait(&memcg_oom_waitq, &owait.wait);
|
||||
mem_cgroup_out_of_memory(memcg, mask, order);
|
||||
mem_cgroup_out_of_memory(memcg, current->memcg_oom.gfp_mask,
|
||||
current->memcg_oom.order);
|
||||
} else {
|
||||
schedule();
|
||||
mem_cgroup_unmark_under_oom(memcg);
|
||||
finish_wait(&memcg_oom_waitq, &owait.wait);
|
||||
}
|
||||
spin_lock(&memcg_oom_lock);
|
||||
if (locked)
|
||||
|
||||
if (locked) {
|
||||
mem_cgroup_oom_unlock(memcg);
|
||||
memcg_wakeup_oom(memcg);
|
||||
spin_unlock(&memcg_oom_lock);
|
||||
|
||||
mem_cgroup_unmark_under_oom(memcg);
|
||||
|
||||
if (test_thread_flag(TIF_MEMDIE) || fatal_signal_pending(current))
|
||||
return false;
|
||||
/* Give chance to dying process */
|
||||
schedule_timeout_uninterruptible(1);
|
||||
/*
|
||||
* There is no guarantee that an OOM-lock contender
|
||||
* sees the wakeups triggered by the OOM kill
|
||||
* uncharges. Wake any sleepers explicitely.
|
||||
*/
|
||||
memcg_oom_recover(memcg);
|
||||
}
|
||||
cleanup:
|
||||
current->memcg_oom.memcg = NULL;
|
||||
css_put(&memcg->css);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2565,12 +2609,11 @@ enum {
|
||||
CHARGE_RETRY, /* need to retry but retry is not bad */
|
||||
CHARGE_NOMEM, /* we can't do more. return -ENOMEM */
|
||||
CHARGE_WOULDBLOCK, /* GFP_WAIT wasn't set and no enough res. */
|
||||
CHARGE_OOM_DIE, /* the current is killed because of OOM */
|
||||
};
|
||||
|
||||
static int mem_cgroup_do_charge(struct mem_cgroup *memcg, gfp_t gfp_mask,
|
||||
unsigned int nr_pages, unsigned int min_pages,
|
||||
bool oom_check)
|
||||
bool invoke_oom)
|
||||
{
|
||||
unsigned long csize = nr_pages * PAGE_SIZE;
|
||||
struct mem_cgroup *mem_over_limit;
|
||||
@@ -2627,14 +2670,10 @@ static int mem_cgroup_do_charge(struct mem_cgroup *memcg, gfp_t gfp_mask,
|
||||
if (mem_cgroup_wait_acct_move(mem_over_limit))
|
||||
return CHARGE_RETRY;
|
||||
|
||||
/* If we don't need to call oom-killer at el, return immediately */
|
||||
if (!oom_check)
|
||||
return CHARGE_NOMEM;
|
||||
/* check OOM */
|
||||
if (!mem_cgroup_handle_oom(mem_over_limit, gfp_mask, get_order(csize)))
|
||||
return CHARGE_OOM_DIE;
|
||||
if (invoke_oom)
|
||||
mem_cgroup_oom(mem_over_limit, gfp_mask, get_order(csize));
|
||||
|
||||
return CHARGE_RETRY;
|
||||
return CHARGE_NOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2678,6 +2717,9 @@ static int __mem_cgroup_try_charge(struct mm_struct *mm,
|
||||
|| fatal_signal_pending(current)))
|
||||
goto bypass;
|
||||
|
||||
if (unlikely(task_in_memcg_oom(current)))
|
||||
goto bypass;
|
||||
|
||||
/*
|
||||
* We always charge the cgroup the mm_struct belongs to.
|
||||
* The mm_struct's mem_cgroup changes on task migration if the
|
||||
@@ -2737,7 +2779,7 @@ again:
|
||||
}
|
||||
|
||||
do {
|
||||
bool oom_check;
|
||||
bool invoke_oom = oom && !nr_oom_retries;
|
||||
|
||||
/* If killed, bypass charge */
|
||||
if (fatal_signal_pending(current)) {
|
||||
@@ -2745,14 +2787,8 @@ again:
|
||||
goto bypass;
|
||||
}
|
||||
|
||||
oom_check = false;
|
||||
if (oom && !nr_oom_retries) {
|
||||
oom_check = true;
|
||||
nr_oom_retries = MEM_CGROUP_RECLAIM_RETRIES;
|
||||
}
|
||||
|
||||
ret = mem_cgroup_do_charge(memcg, gfp_mask, batch, nr_pages,
|
||||
oom_check);
|
||||
ret = mem_cgroup_do_charge(memcg, gfp_mask, batch,
|
||||
nr_pages, invoke_oom);
|
||||
switch (ret) {
|
||||
case CHARGE_OK:
|
||||
break;
|
||||
@@ -2765,16 +2801,12 @@ again:
|
||||
css_put(&memcg->css);
|
||||
goto nomem;
|
||||
case CHARGE_NOMEM: /* OOM routine works */
|
||||
if (!oom) {
|
||||
if (!oom || invoke_oom) {
|
||||
css_put(&memcg->css);
|
||||
goto nomem;
|
||||
}
|
||||
/* If oom, we never return -ENOMEM */
|
||||
nr_oom_retries--;
|
||||
break;
|
||||
case CHARGE_OOM_DIE: /* Killed by OOM Killer */
|
||||
css_put(&memcg->css);
|
||||
goto bypass;
|
||||
}
|
||||
} while (ret != CHARGE_OK);
|
||||
|
||||
|
||||
+39
-10
@@ -3796,22 +3796,14 @@ unlock:
|
||||
/*
|
||||
* By the time we get here, we already hold the mm semaphore
|
||||
*/
|
||||
int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
unsigned long address, unsigned int flags)
|
||||
static int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
unsigned long address, unsigned int flags)
|
||||
{
|
||||
pgd_t *pgd;
|
||||
pud_t *pud;
|
||||
pmd_t *pmd;
|
||||
pte_t *pte;
|
||||
|
||||
__set_current_state(TASK_RUNNING);
|
||||
|
||||
count_vm_event(PGFAULT);
|
||||
mem_cgroup_count_vm_event(mm, PGFAULT);
|
||||
|
||||
/* do counter updates before entering really critical section. */
|
||||
check_sync_rss_stat(current);
|
||||
|
||||
if (unlikely(is_vm_hugetlb_page(vma)))
|
||||
return hugetlb_fault(mm, vma, address, flags);
|
||||
|
||||
@@ -3892,6 +3884,43 @@ retry:
|
||||
return handle_pte_fault(mm, vma, address, pte, pmd, flags);
|
||||
}
|
||||
|
||||
int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
|
||||
unsigned long address, unsigned int flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
__set_current_state(TASK_RUNNING);
|
||||
|
||||
count_vm_event(PGFAULT);
|
||||
mem_cgroup_count_vm_event(mm, PGFAULT);
|
||||
|
||||
/* do counter updates before entering really critical section. */
|
||||
check_sync_rss_stat(current);
|
||||
|
||||
/*
|
||||
* Enable the memcg OOM handling for faults triggered in user
|
||||
* space. Kernel faults are handled more gracefully.
|
||||
*/
|
||||
if (flags & FAULT_FLAG_USER)
|
||||
mem_cgroup_oom_enable();
|
||||
|
||||
ret = __handle_mm_fault(mm, vma, address, flags);
|
||||
|
||||
if (flags & FAULT_FLAG_USER) {
|
||||
mem_cgroup_oom_disable();
|
||||
/*
|
||||
* The task may have entered a memcg OOM situation but
|
||||
* if the allocation error was handled gracefully (no
|
||||
* VM_FAULT_OOM), there is no need to kill anything.
|
||||
* Just clean up the OOM state peacefully.
|
||||
*/
|
||||
if (task_in_memcg_oom(current) && !(ret & VM_FAULT_OOM))
|
||||
mem_cgroup_oom_synchronize(false);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef __PAGETABLE_PUD_FOLDED
|
||||
/*
|
||||
* Allocate page upper directory.
|
||||
|
||||
+5
-2
@@ -718,9 +718,12 @@ out:
|
||||
*/
|
||||
void pagefault_out_of_memory(void)
|
||||
{
|
||||
struct zonelist *zonelist = node_zonelist(first_online_node,
|
||||
GFP_KERNEL);
|
||||
struct zonelist *zonelist;
|
||||
|
||||
if (mem_cgroup_oom_synchronize(true))
|
||||
return;
|
||||
|
||||
zonelist = node_zonelist(first_online_node, GFP_KERNEL);
|
||||
if (try_set_zonelist_oom(zonelist, GFP_KERNEL)) {
|
||||
out_of_memory(NULL, 0, 0, NULL, false);
|
||||
clear_zonelist_oom(zonelist, GFP_KERNEL);
|
||||
|
||||
@@ -429,6 +429,16 @@ extern netdev_features_t br_features_recompute(struct net_bridge *br,
|
||||
extern int br_handle_frame_finish(struct sk_buff *skb);
|
||||
extern rx_handler_result_t br_handle_frame(struct sk_buff **pskb);
|
||||
|
||||
static inline bool br_rx_handler_check_rcu(const struct net_device *dev)
|
||||
{
|
||||
return rcu_dereference(dev->rx_handler) == br_handle_frame;
|
||||
}
|
||||
|
||||
static inline struct net_bridge_port *br_port_get_check_rcu(const struct net_device *dev)
|
||||
{
|
||||
return br_rx_handler_check_rcu(dev) ? br_port_get_rcu(dev) : NULL;
|
||||
}
|
||||
|
||||
/* br_ioctl.c */
|
||||
extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
|
||||
extern int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *arg);
|
||||
|
||||
@@ -153,7 +153,7 @@ void br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb,
|
||||
if (buf[0] != 0 || buf[1] != 0 || buf[2] != 0)
|
||||
goto err;
|
||||
|
||||
p = br_port_get_rcu(dev);
|
||||
p = br_port_get_check_rcu(dev);
|
||||
if (!p)
|
||||
goto err;
|
||||
|
||||
|
||||
+132
-37
@@ -89,11 +89,82 @@ static struct crypto_blkcipher *ceph_crypto_alloc_cipher(void)
|
||||
|
||||
static const u8 *aes_iv = (u8 *)CEPH_AES_IV;
|
||||
|
||||
/*
|
||||
* Should be used for buffers allocated with ceph_kvmalloc().
|
||||
* Currently these are encrypt out-buffer (ceph_buffer) and decrypt
|
||||
* in-buffer (msg front).
|
||||
*
|
||||
* Dispose of @sgt with teardown_sgtable().
|
||||
*
|
||||
* @prealloc_sg is to avoid memory allocation inside sg_alloc_table()
|
||||
* in cases where a single sg is sufficient. No attempt to reduce the
|
||||
* number of sgs by squeezing physically contiguous pages together is
|
||||
* made though, for simplicity.
|
||||
*/
|
||||
static int setup_sgtable(struct sg_table *sgt, struct scatterlist *prealloc_sg,
|
||||
const void *buf, unsigned int buf_len)
|
||||
{
|
||||
struct scatterlist *sg;
|
||||
const bool is_vmalloc = is_vmalloc_addr(buf);
|
||||
unsigned int off = offset_in_page(buf);
|
||||
unsigned int chunk_cnt = 1;
|
||||
unsigned int chunk_len = PAGE_ALIGN(off + buf_len);
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (buf_len == 0) {
|
||||
memset(sgt, 0, sizeof(*sgt));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (is_vmalloc) {
|
||||
chunk_cnt = chunk_len >> PAGE_SHIFT;
|
||||
chunk_len = PAGE_SIZE;
|
||||
}
|
||||
|
||||
if (chunk_cnt > 1) {
|
||||
ret = sg_alloc_table(sgt, chunk_cnt, GFP_NOFS);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
WARN_ON(chunk_cnt != 1);
|
||||
sg_init_table(prealloc_sg, 1);
|
||||
sgt->sgl = prealloc_sg;
|
||||
sgt->nents = sgt->orig_nents = 1;
|
||||
}
|
||||
|
||||
for_each_sg(sgt->sgl, sg, sgt->orig_nents, i) {
|
||||
struct page *page;
|
||||
unsigned int len = min(chunk_len - off, buf_len);
|
||||
|
||||
if (is_vmalloc)
|
||||
page = vmalloc_to_page(buf);
|
||||
else
|
||||
page = virt_to_page(buf);
|
||||
|
||||
sg_set_page(sg, page, len, off);
|
||||
|
||||
off = 0;
|
||||
buf += len;
|
||||
buf_len -= len;
|
||||
}
|
||||
WARN_ON(buf_len != 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void teardown_sgtable(struct sg_table *sgt)
|
||||
{
|
||||
if (sgt->orig_nents > 1)
|
||||
sg_free_table(sgt);
|
||||
}
|
||||
|
||||
static int ceph_aes_encrypt(const void *key, int key_len,
|
||||
void *dst, size_t *dst_len,
|
||||
const void *src, size_t src_len)
|
||||
{
|
||||
struct scatterlist sg_in[2], sg_out[1];
|
||||
struct scatterlist sg_in[2], prealloc_sg;
|
||||
struct sg_table sg_out;
|
||||
struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
|
||||
struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 };
|
||||
int ret;
|
||||
@@ -109,16 +180,18 @@ static int ceph_aes_encrypt(const void *key, int key_len,
|
||||
|
||||
*dst_len = src_len + zero_padding;
|
||||
|
||||
crypto_blkcipher_setkey((void *)tfm, key, key_len);
|
||||
sg_init_table(sg_in, 2);
|
||||
sg_set_buf(&sg_in[0], src, src_len);
|
||||
sg_set_buf(&sg_in[1], pad, zero_padding);
|
||||
sg_init_table(sg_out, 1);
|
||||
sg_set_buf(sg_out, dst, *dst_len);
|
||||
ret = setup_sgtable(&sg_out, &prealloc_sg, dst, *dst_len);
|
||||
if (ret)
|
||||
goto out_tfm;
|
||||
|
||||
crypto_blkcipher_setkey((void *)tfm, key, key_len);
|
||||
iv = crypto_blkcipher_crt(tfm)->iv;
|
||||
ivsize = crypto_blkcipher_ivsize(tfm);
|
||||
|
||||
memcpy(iv, aes_iv, ivsize);
|
||||
|
||||
/*
|
||||
print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1,
|
||||
key, key_len, 1);
|
||||
@@ -127,16 +200,22 @@ static int ceph_aes_encrypt(const void *key, int key_len,
|
||||
print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1,
|
||||
pad, zero_padding, 1);
|
||||
*/
|
||||
ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in,
|
||||
ret = crypto_blkcipher_encrypt(&desc, sg_out.sgl, sg_in,
|
||||
src_len + zero_padding);
|
||||
crypto_free_blkcipher(tfm);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
pr_err("ceph_aes_crypt failed %d\n", ret);
|
||||
goto out_sg;
|
||||
}
|
||||
/*
|
||||
print_hex_dump(KERN_ERR, "enc out: ", DUMP_PREFIX_NONE, 16, 1,
|
||||
dst, *dst_len, 1);
|
||||
*/
|
||||
return 0;
|
||||
|
||||
out_sg:
|
||||
teardown_sgtable(&sg_out);
|
||||
out_tfm:
|
||||
crypto_free_blkcipher(tfm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ceph_aes_encrypt2(const void *key, int key_len, void *dst,
|
||||
@@ -144,7 +223,8 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst,
|
||||
const void *src1, size_t src1_len,
|
||||
const void *src2, size_t src2_len)
|
||||
{
|
||||
struct scatterlist sg_in[3], sg_out[1];
|
||||
struct scatterlist sg_in[3], prealloc_sg;
|
||||
struct sg_table sg_out;
|
||||
struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
|
||||
struct blkcipher_desc desc = { .tfm = tfm, .flags = 0 };
|
||||
int ret;
|
||||
@@ -160,17 +240,19 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst,
|
||||
|
||||
*dst_len = src1_len + src2_len + zero_padding;
|
||||
|
||||
crypto_blkcipher_setkey((void *)tfm, key, key_len);
|
||||
sg_init_table(sg_in, 3);
|
||||
sg_set_buf(&sg_in[0], src1, src1_len);
|
||||
sg_set_buf(&sg_in[1], src2, src2_len);
|
||||
sg_set_buf(&sg_in[2], pad, zero_padding);
|
||||
sg_init_table(sg_out, 1);
|
||||
sg_set_buf(sg_out, dst, *dst_len);
|
||||
ret = setup_sgtable(&sg_out, &prealloc_sg, dst, *dst_len);
|
||||
if (ret)
|
||||
goto out_tfm;
|
||||
|
||||
crypto_blkcipher_setkey((void *)tfm, key, key_len);
|
||||
iv = crypto_blkcipher_crt(tfm)->iv;
|
||||
ivsize = crypto_blkcipher_ivsize(tfm);
|
||||
|
||||
memcpy(iv, aes_iv, ivsize);
|
||||
|
||||
/*
|
||||
print_hex_dump(KERN_ERR, "enc key: ", DUMP_PREFIX_NONE, 16, 1,
|
||||
key, key_len, 1);
|
||||
@@ -181,23 +263,30 @@ static int ceph_aes_encrypt2(const void *key, int key_len, void *dst,
|
||||
print_hex_dump(KERN_ERR, "enc pad: ", DUMP_PREFIX_NONE, 16, 1,
|
||||
pad, zero_padding, 1);
|
||||
*/
|
||||
ret = crypto_blkcipher_encrypt(&desc, sg_out, sg_in,
|
||||
ret = crypto_blkcipher_encrypt(&desc, sg_out.sgl, sg_in,
|
||||
src1_len + src2_len + zero_padding);
|
||||
crypto_free_blkcipher(tfm);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
pr_err("ceph_aes_crypt2 failed %d\n", ret);
|
||||
goto out_sg;
|
||||
}
|
||||
/*
|
||||
print_hex_dump(KERN_ERR, "enc out: ", DUMP_PREFIX_NONE, 16, 1,
|
||||
dst, *dst_len, 1);
|
||||
*/
|
||||
return 0;
|
||||
|
||||
out_sg:
|
||||
teardown_sgtable(&sg_out);
|
||||
out_tfm:
|
||||
crypto_free_blkcipher(tfm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ceph_aes_decrypt(const void *key, int key_len,
|
||||
void *dst, size_t *dst_len,
|
||||
const void *src, size_t src_len)
|
||||
{
|
||||
struct scatterlist sg_in[1], sg_out[2];
|
||||
struct sg_table sg_in;
|
||||
struct scatterlist sg_out[2], prealloc_sg;
|
||||
struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
|
||||
struct blkcipher_desc desc = { .tfm = tfm };
|
||||
char pad[16];
|
||||
@@ -209,16 +298,16 @@ static int ceph_aes_decrypt(const void *key, int key_len,
|
||||
if (IS_ERR(tfm))
|
||||
return PTR_ERR(tfm);
|
||||
|
||||
crypto_blkcipher_setkey((void *)tfm, key, key_len);
|
||||
sg_init_table(sg_in, 1);
|
||||
sg_init_table(sg_out, 2);
|
||||
sg_set_buf(sg_in, src, src_len);
|
||||
sg_set_buf(&sg_out[0], dst, *dst_len);
|
||||
sg_set_buf(&sg_out[1], pad, sizeof(pad));
|
||||
ret = setup_sgtable(&sg_in, &prealloc_sg, src, src_len);
|
||||
if (ret)
|
||||
goto out_tfm;
|
||||
|
||||
crypto_blkcipher_setkey((void *)tfm, key, key_len);
|
||||
iv = crypto_blkcipher_crt(tfm)->iv;
|
||||
ivsize = crypto_blkcipher_ivsize(tfm);
|
||||
|
||||
memcpy(iv, aes_iv, ivsize);
|
||||
|
||||
/*
|
||||
@@ -227,12 +316,10 @@ static int ceph_aes_decrypt(const void *key, int key_len,
|
||||
print_hex_dump(KERN_ERR, "dec in: ", DUMP_PREFIX_NONE, 16, 1,
|
||||
src, src_len, 1);
|
||||
*/
|
||||
|
||||
ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, src_len);
|
||||
crypto_free_blkcipher(tfm);
|
||||
ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in.sgl, src_len);
|
||||
if (ret < 0) {
|
||||
pr_err("ceph_aes_decrypt failed %d\n", ret);
|
||||
return ret;
|
||||
goto out_sg;
|
||||
}
|
||||
|
||||
if (src_len <= *dst_len)
|
||||
@@ -250,7 +337,12 @@ static int ceph_aes_decrypt(const void *key, int key_len,
|
||||
print_hex_dump(KERN_ERR, "dec out: ", DUMP_PREFIX_NONE, 16, 1,
|
||||
dst, *dst_len, 1);
|
||||
*/
|
||||
return 0;
|
||||
|
||||
out_sg:
|
||||
teardown_sgtable(&sg_in);
|
||||
out_tfm:
|
||||
crypto_free_blkcipher(tfm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ceph_aes_decrypt2(const void *key, int key_len,
|
||||
@@ -258,7 +350,8 @@ static int ceph_aes_decrypt2(const void *key, int key_len,
|
||||
void *dst2, size_t *dst2_len,
|
||||
const void *src, size_t src_len)
|
||||
{
|
||||
struct scatterlist sg_in[1], sg_out[3];
|
||||
struct sg_table sg_in;
|
||||
struct scatterlist sg_out[3], prealloc_sg;
|
||||
struct crypto_blkcipher *tfm = ceph_crypto_alloc_cipher();
|
||||
struct blkcipher_desc desc = { .tfm = tfm };
|
||||
char pad[16];
|
||||
@@ -270,17 +363,17 @@ static int ceph_aes_decrypt2(const void *key, int key_len,
|
||||
if (IS_ERR(tfm))
|
||||
return PTR_ERR(tfm);
|
||||
|
||||
sg_init_table(sg_in, 1);
|
||||
sg_set_buf(sg_in, src, src_len);
|
||||
sg_init_table(sg_out, 3);
|
||||
sg_set_buf(&sg_out[0], dst1, *dst1_len);
|
||||
sg_set_buf(&sg_out[1], dst2, *dst2_len);
|
||||
sg_set_buf(&sg_out[2], pad, sizeof(pad));
|
||||
ret = setup_sgtable(&sg_in, &prealloc_sg, src, src_len);
|
||||
if (ret)
|
||||
goto out_tfm;
|
||||
|
||||
crypto_blkcipher_setkey((void *)tfm, key, key_len);
|
||||
iv = crypto_blkcipher_crt(tfm)->iv;
|
||||
ivsize = crypto_blkcipher_ivsize(tfm);
|
||||
|
||||
memcpy(iv, aes_iv, ivsize);
|
||||
|
||||
/*
|
||||
@@ -289,12 +382,10 @@ static int ceph_aes_decrypt2(const void *key, int key_len,
|
||||
print_hex_dump(KERN_ERR, "dec in: ", DUMP_PREFIX_NONE, 16, 1,
|
||||
src, src_len, 1);
|
||||
*/
|
||||
|
||||
ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in, src_len);
|
||||
crypto_free_blkcipher(tfm);
|
||||
ret = crypto_blkcipher_decrypt(&desc, sg_out, sg_in.sgl, src_len);
|
||||
if (ret < 0) {
|
||||
pr_err("ceph_aes_decrypt failed %d\n", ret);
|
||||
return ret;
|
||||
goto out_sg;
|
||||
}
|
||||
|
||||
if (src_len <= *dst1_len)
|
||||
@@ -324,7 +415,11 @@ static int ceph_aes_decrypt2(const void *key, int key_len,
|
||||
dst2, *dst2_len, 1);
|
||||
*/
|
||||
|
||||
return 0;
|
||||
out_sg:
|
||||
teardown_sgtable(&sg_in);
|
||||
out_tfm:
|
||||
crypto_free_blkcipher(tfm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+4
-3
@@ -962,8 +962,6 @@ static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu)
|
||||
else
|
||||
dev->flags &= ~IFF_POINTOPOINT;
|
||||
|
||||
dev->iflink = p->link;
|
||||
|
||||
/* Precalculate GRE options length */
|
||||
if (t->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) {
|
||||
if (t->parms.o_flags&GRE_CSUM)
|
||||
@@ -1267,6 +1265,8 @@ static int ip6gre_tunnel_init(struct net_device *dev)
|
||||
if (!dev->tstats)
|
||||
return -ENOMEM;
|
||||
|
||||
dev->iflink = tunnel->parms.link;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1282,7 +1282,6 @@ static void ip6gre_fb_tunnel_init(struct net_device *dev)
|
||||
dev_hold(dev);
|
||||
}
|
||||
|
||||
|
||||
static struct inet6_protocol ip6gre_protocol __read_mostly = {
|
||||
.handler = ip6gre_rcv,
|
||||
.err_handler = ip6gre_err,
|
||||
@@ -1458,6 +1457,8 @@ static int ip6gre_tap_init(struct net_device *dev)
|
||||
if (!dev->tstats)
|
||||
return -ENOMEM;
|
||||
|
||||
dev->iflink = tunnel->parms.link;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -265,9 +265,6 @@ static int ip6_tnl_create2(struct net_device *dev)
|
||||
int err;
|
||||
|
||||
t = netdev_priv(dev);
|
||||
err = ip6_tnl_dev_init(dev);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
err = register_netdevice(dev);
|
||||
if (err < 0)
|
||||
@@ -1433,6 +1430,7 @@ ip6_tnl_change_mtu(struct net_device *dev, int new_mtu)
|
||||
|
||||
|
||||
static const struct net_device_ops ip6_tnl_netdev_ops = {
|
||||
.ndo_init = ip6_tnl_dev_init,
|
||||
.ndo_uninit = ip6_tnl_dev_uninit,
|
||||
.ndo_start_xmit = ip6_tnl_xmit,
|
||||
.ndo_do_ioctl = ip6_tnl_ioctl,
|
||||
@@ -1514,16 +1512,10 @@ static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev)
|
||||
struct ip6_tnl *t = netdev_priv(dev);
|
||||
struct net *net = dev_net(dev);
|
||||
struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
|
||||
int err = ip6_tnl_dev_init_gen(dev);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
t->parms.proto = IPPROTO_IPV6;
|
||||
dev_hold(dev);
|
||||
|
||||
ip6_tnl_link_config(t);
|
||||
|
||||
rcu_assign_pointer(ip6n->tnls_wc[0], t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+7
-7
@@ -1585,11 +1585,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
||||
sc = le16_to_cpu(hdr->seq_ctrl);
|
||||
frag = sc & IEEE80211_SCTL_FRAG;
|
||||
|
||||
if (likely((!ieee80211_has_morefrags(fc) && frag == 0) ||
|
||||
is_multicast_ether_addr(hdr->addr1))) {
|
||||
/* not fragmented */
|
||||
if (likely(!ieee80211_has_morefrags(fc) && frag == 0))
|
||||
goto out;
|
||||
|
||||
if (is_multicast_ether_addr(hdr->addr1)) {
|
||||
rx->local->dot11MulticastReceivedFrameCount++;
|
||||
goto out;
|
||||
}
|
||||
|
||||
I802_DEBUG_INC(rx->local->rx_handlers_fragments);
|
||||
|
||||
if (skb_linearize(rx->skb))
|
||||
@@ -1682,10 +1685,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
||||
out:
|
||||
if (rx->sta)
|
||||
rx->sta->rx_packets++;
|
||||
if (is_multicast_ether_addr(hdr->addr1))
|
||||
rx->local->dot11MulticastReceivedFrameCount++;
|
||||
else
|
||||
ieee80211_led_rx(rx->local);
|
||||
ieee80211_led_rx(rx->local);
|
||||
return RX_CONTINUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -487,6 +487,39 @@ static int nf_nat_proto_remove(struct nf_conn *i, void *data)
|
||||
return i->status & IPS_NAT_MASK ? 1 : 0;
|
||||
}
|
||||
|
||||
static int nf_nat_proto_clean(struct nf_conn *ct, void *data)
|
||||
{
|
||||
struct nf_conn_nat *nat = nfct_nat(ct);
|
||||
|
||||
if (nf_nat_proto_remove(ct, data))
|
||||
return 1;
|
||||
|
||||
if (!nat || !nat->ct)
|
||||
return 0;
|
||||
|
||||
/* This netns is being destroyed, and conntrack has nat null binding.
|
||||
* Remove it from bysource hash, as the table will be freed soon.
|
||||
*
|
||||
* Else, when the conntrack is destoyed, nf_nat_cleanup_conntrack()
|
||||
* will delete entry from already-freed table.
|
||||
*/
|
||||
if (!del_timer(&ct->timeout))
|
||||
return 1;
|
||||
|
||||
spin_lock_bh(&nf_nat_lock);
|
||||
hlist_del_rcu(&nat->bysource);
|
||||
ct->status &= ~IPS_NAT_DONE_MASK;
|
||||
nat->ct = NULL;
|
||||
spin_unlock_bh(&nf_nat_lock);
|
||||
|
||||
add_timer(&ct->timeout);
|
||||
|
||||
/* don't delete conntrack. Although that would make things a lot
|
||||
* simpler, we'd end up flushing all conntracks on nat rmmod.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nf_nat_l4proto_clean(u8 l3proto, u8 l4proto)
|
||||
{
|
||||
struct nf_nat_proto_clean clean = {
|
||||
@@ -749,7 +782,7 @@ static void __net_exit nf_nat_net_exit(struct net *net)
|
||||
{
|
||||
struct nf_nat_proto_clean clean = {};
|
||||
|
||||
nf_ct_iterate_cleanup(net, &nf_nat_proto_remove, &clean);
|
||||
nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean);
|
||||
synchronize_rcu();
|
||||
nf_ct_free_hashtable(net->ct.nat_bysource, net->ct.nat_htable_size);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user