diff options
-rw-r--r-- | 0000_README | 4 | ||||
-rw-r--r-- | 1082_linux-3.10.83.patch | 1734 |
2 files changed, 1738 insertions, 0 deletions
diff --git a/0000_README b/0000_README index 5e458310..1cfdd1d4 100644 --- a/0000_README +++ b/0000_README @@ -370,6 +370,10 @@ Patch: 1081_linux-3.10.82.patch From: http://www.kernel.org Desc: Linux 3.10.82 +Patch: 1082_linux-3.10.83.patch +From: http://www.kernel.org +Desc: Linux 3.10.83 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1082_linux-3.10.83.patch b/1082_linux-3.10.83.patch new file mode 100644 index 00000000..187a86e5 --- /dev/null +++ b/1082_linux-3.10.83.patch @@ -0,0 +1,1734 @@ +diff --git a/Makefile b/Makefile +index 5e3e665a10b7..21529dbcc11d 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,6 +1,6 @@ + VERSION = 3 + PATCHLEVEL = 10 +-SUBLEVEL = 82 ++SUBLEVEL = 83 + EXTRAVERSION = + NAME = TOSSUG Baby Fish + +diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c +index e2b5da031f96..8d4f5dc56910 100644 +--- a/arch/arm/mach-dove/common.c ++++ b/arch/arm/mach-dove/common.c +@@ -226,7 +226,7 @@ void __init dove_init_early(void) + orion_time_set_base(TIMER_VIRT_BASE); + mvebu_mbus_init("marvell,dove-mbus", + BRIDGE_WINS_BASE, BRIDGE_WINS_SZ, +- DOVE_MC_WINS_BASE, DOVE_MC_WINS_SZ); ++ DOVE_MC_WINS_BASE, DOVE_MC_WINS_SZ, 0); + } + + static int __init dove_find_tclk(void) +diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c +index 2acaded8025d..ed00c9e3bfc6 100644 +--- a/arch/arm/mach-imx/clk-imx6q.c ++++ b/arch/arm/mach-imx/clk-imx6q.c +@@ -515,7 +515,7 @@ int __init mx6q_clocks_init(void) + clk[gpmi_io] = imx_clk_gate2("gpmi_io", "enfc", base + 0x78, 28); + clk[gpmi_apb] = imx_clk_gate2("gpmi_apb", "usdhc3", base + 0x78, 30); + clk[rom] = imx_clk_gate2("rom", "ahb", base + 0x7c, 0); +- clk[sata] = imx_clk_gate2("sata", "ipg", base + 0x7c, 4); ++ clk[sata] = imx_clk_gate2("sata", "ahb", base + 0x7c, 4); + clk[sdma] = imx_clk_gate2("sdma", "ahb", base + 0x7c, 6); + clk[spba] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12); + clk[ssi1_ipg] = imx_clk_gate2("ssi1_ipg", "ipg", base + 0x7c, 18); +diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c +index f38922897563..4f6831ea88c5 100644 +--- a/arch/arm/mach-kirkwood/common.c ++++ b/arch/arm/mach-kirkwood/common.c +@@ -530,7 +530,7 @@ void __init kirkwood_init_early(void) + + mvebu_mbus_init("marvell,kirkwood-mbus", + BRIDGE_WINS_BASE, BRIDGE_WINS_SZ, +- DDR_WINDOW_CPU_BASE, DDR_WINDOW_CPU_SZ); ++ DDR_WINDOW_CPU_BASE, DDR_WINDOW_CPU_SZ, 0); + } + + int kirkwood_tclk; +diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c +index 749a7f8c4992..4722c98dc1bb 100644 +--- a/arch/arm/mach-mv78xx0/common.c ++++ b/arch/arm/mach-mv78xx0/common.c +@@ -337,11 +337,11 @@ void __init mv78xx0_init_early(void) + if (mv78xx0_core_index() == 0) + mvebu_mbus_init("marvell,mv78xx0-mbus", + BRIDGE_WINS_CPU0_BASE, BRIDGE_WINS_SZ, +- DDR_WINDOW_CPU0_BASE, DDR_WINDOW_CPU_SZ); ++ DDR_WINDOW_CPU0_BASE, DDR_WINDOW_CPU_SZ, 0); + else + mvebu_mbus_init("marvell,mv78xx0-mbus", + BRIDGE_WINS_CPU1_BASE, BRIDGE_WINS_SZ, +- DDR_WINDOW_CPU1_BASE, DDR_WINDOW_CPU_SZ); ++ DDR_WINDOW_CPU1_BASE, DDR_WINDOW_CPU_SZ, 0); + } + + void __init_refok mv78xx0_timer_init(void) +diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c +index 1c48890bb72b..4377c3484a62 100644 +--- a/arch/arm/mach-mvebu/armada-370-xp.c ++++ b/arch/arm/mach-mvebu/armada-370-xp.c +@@ -66,7 +66,8 @@ void __init armada_370_xp_init_early(void) + ARMADA_370_XP_MBUS_WINS_BASE, + ARMADA_370_XP_MBUS_WINS_SIZE, + ARMADA_370_XP_SDRAM_WINS_BASE, +- ARMADA_370_XP_SDRAM_WINS_SIZE); ++ ARMADA_370_XP_SDRAM_WINS_SIZE, ++ coherency_available()); + + #ifdef CONFIG_CACHE_L2X0 + l2x0_of_init(0, ~0UL); +diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c +index 3ee701f1d38e..ea26ebb5bb5a 100644 +--- a/arch/arm/mach-mvebu/coherency.c ++++ b/arch/arm/mach-mvebu/coherency.c +@@ -137,6 +137,20 @@ static struct notifier_block mvebu_hwcc_platform_nb = { + .notifier_call = mvebu_hwcc_platform_notifier, + }; + ++/* ++ * Keep track of whether we have IO hardware coherency enabled or not. ++ * On Armada 370's we will not be using it for example. We need to make ++ * that available [through coherency_available()] so the mbus controller ++ * doesn't enable the IO coherency bit in the attribute bits of the ++ * chip selects. ++ */ ++static int coherency_enabled; ++ ++int coherency_available(void) ++{ ++ return coherency_enabled; ++} ++ + int __init coherency_init(void) + { + struct device_node *np; +@@ -170,6 +184,7 @@ int __init coherency_init(void) + coherency_base = of_iomap(np, 0); + coherency_cpu_base = of_iomap(np, 1); + set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0); ++ coherency_enabled = 1; + bus_register_notifier(&platform_bus_type, + &mvebu_hwcc_platform_nb); + } +diff --git a/arch/arm/mach-mvebu/coherency.h b/arch/arm/mach-mvebu/coherency.h +index 2f428137f6fe..1501a4e5eea0 100644 +--- a/arch/arm/mach-mvebu/coherency.h ++++ b/arch/arm/mach-mvebu/coherency.h +@@ -19,6 +19,7 @@ int coherency_get_cpu_count(void); + #endif + + int set_cpu_coherent(int cpu_id, int smp_group_id); ++int coherency_available(void); + int coherency_init(void); + + #endif /* __MACH_370_XP_COHERENCY_H */ +diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c +index f8a6db9239bf..048773926ad4 100644 +--- a/arch/arm/mach-orion5x/common.c ++++ b/arch/arm/mach-orion5x/common.c +@@ -213,7 +213,7 @@ void __init orion5x_init_early(void) + mbus_soc_name = NULL; + mvebu_mbus_init(mbus_soc_name, ORION5X_BRIDGE_WINS_BASE, + ORION5X_BRIDGE_WINS_SZ, +- ORION5X_DDR_WINS_BASE, ORION5X_DDR_WINS_SZ); ++ ORION5X_DDR_WINS_BASE, ORION5X_DDR_WINS_SZ, 0); + } + + void orion5x_setup_wins(void) +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index 4e5b80d883c8..105ae30a176b 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -154,7 +154,7 @@ config SBUS + + config NEED_DMA_MAP_STATE + def_bool y +- depends on X86_64 || INTEL_IOMMU || DMA_API_DEBUG ++ depends on X86_64 || INTEL_IOMMU || DMA_API_DEBUG || SWIOTLB + + config NEED_SG_DMA_LENGTH + def_bool y +diff --git a/arch/x86/kernel/microcode_intel_early.c b/arch/x86/kernel/microcode_intel_early.c +index 2e9e12871c2b..a883942aee44 100644 +--- a/arch/x86/kernel/microcode_intel_early.c ++++ b/arch/x86/kernel/microcode_intel_early.c +@@ -321,7 +321,7 @@ get_matching_model_microcode(int cpu, unsigned long start, + unsigned int mc_saved_count = mc_saved_data->mc_saved_count; + int i; + +- while (leftover) { ++ while (leftover && mc_saved_count < ARRAY_SIZE(mc_saved_tmp)) { + mc_header = (struct microcode_header_intel *)ucode_ptr; + + mc_size = get_totalsize(mc_header); +diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c +index 8bf40a243d75..224d2ef754cc 100644 +--- a/arch/x86/kvm/svm.c ++++ b/arch/x86/kvm/svm.c +@@ -495,8 +495,10 @@ static void skip_emulated_instruction(struct kvm_vcpu *vcpu) + { + struct vcpu_svm *svm = to_svm(vcpu); + +- if (svm->vmcb->control.next_rip != 0) ++ if (svm->vmcb->control.next_rip != 0) { ++ WARN_ON(!static_cpu_has(X86_FEATURE_NRIPS)); + svm->next_rip = svm->vmcb->control.next_rip; ++ } + + if (!svm->next_rip) { + if (emulate_instruction(vcpu, EMULTYPE_SKIP) != +@@ -4229,7 +4231,9 @@ static int svm_check_intercept(struct kvm_vcpu *vcpu, + break; + } + +- vmcb->control.next_rip = info->next_rip; ++ /* TODO: Advertise NRIPS to guest hypervisor unconditionally */ ++ if (static_cpu_has(X86_FEATURE_NRIPS)) ++ vmcb->control.next_rip = info->next_rip; + vmcb->control.exit_code = icpt_info.exit_code; + vmexit = nested_svm_exit_handled(svm); + +diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h +index 53666bd9193d..32b0bf32364a 100644 +--- a/drivers/acpi/acpica/acmacros.h ++++ b/drivers/acpi/acpica/acmacros.h +@@ -63,19 +63,15 @@ + #define ACPI_SET64(ptr, val) (*ACPI_CAST64 (ptr) = (u64) (val)) + + /* +- * printf() format helpers ++ * printf() format helper. This macros is a workaround for the difficulties ++ * with emitting 64-bit integers and 64-bit pointers with the same code ++ * for both 32-bit and 64-bit hosts. + */ + + /* Split 64-bit integer into two 32-bit values. Use with %8.8X%8.8X */ + + #define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i), ACPI_LODWORD(i) + +-#if ACPI_MACHINE_WIDTH == 64 +-#define ACPI_FORMAT_NATIVE_UINT(i) ACPI_FORMAT_UINT64(i) +-#else +-#define ACPI_FORMAT_NATIVE_UINT(i) 0, (i) +-#endif +- + /* + * Macros for moving data around to/from buffers that are possibly unaligned. + * If the hardware supports the transfer of unaligned data, just do the store. +diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c +index e9b13b92ba1e..46a37aeaedae 100644 +--- a/drivers/acpi/acpica/dsopcode.c ++++ b/drivers/acpi/acpica/dsopcode.c +@@ -446,7 +446,7 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", + obj_desc, +- ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), ++ ACPI_FORMAT_UINT64(obj_desc->region.address), + obj_desc->region.length)); + + /* Now the address and length are valid for this opregion */ +@@ -544,7 +544,7 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", + obj_desc, +- ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), ++ ACPI_FORMAT_UINT64(obj_desc->region.address), + obj_desc->region.length)); + + /* Now the address and length are valid for this opregion */ +diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c +index 8fab9262d98a..ad698893e829 100644 +--- a/drivers/acpi/acpica/evregion.c ++++ b/drivers/acpi/acpica/evregion.c +@@ -276,7 +276,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, + ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, + "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", + ®ion_obj->region.handler->address_space, handler, +- ACPI_FORMAT_NATIVE_UINT(address), ++ ACPI_FORMAT_UINT64(address), + acpi_ut_get_region_name(region_obj->region. + space_id))); + +diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c +index e5a3c249f7fa..7e6a56fe1d6e 100644 +--- a/drivers/acpi/acpica/exdump.c ++++ b/drivers/acpi/acpica/exdump.c +@@ -621,8 +621,8 @@ void acpi_ex_dump_operand(union acpi_operand_object *obj_desc, u32 depth) + acpi_os_printf("\n"); + } else { + acpi_os_printf(" base %8.8X%8.8X Length %X\n", +- ACPI_FORMAT_NATIVE_UINT(obj_desc->region. +- address), ++ ACPI_FORMAT_UINT64(obj_desc->region. ++ address), + obj_desc->region.length); + } + break; +diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c +index c84ee956fa4c..dc210c379277 100644 +--- a/drivers/acpi/acpica/exfldio.c ++++ b/drivers/acpi/acpica/exfldio.c +@@ -269,17 +269,15 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, + } + + ACPI_DEBUG_PRINT_RAW((ACPI_DB_BFIELD, +- " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %p\n", ++ " Region [%s:%X], Width %X, ByteBase %X, Offset %X at %8.8X%8.8X\n", + acpi_ut_get_region_name(rgn_desc->region. + space_id), + rgn_desc->region.space_id, + obj_desc->common_field.access_byte_width, + obj_desc->common_field.base_byte_offset, +- field_datum_byte_offset, ACPI_CAST_PTR(void, +- (rgn_desc-> +- region. +- address + +- region_offset)))); ++ field_datum_byte_offset, ++ ACPI_FORMAT_UINT64(rgn_desc->region.address + ++ region_offset))); + + /* Invoke the appropriate address_space/op_region handler */ + +diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c +index 182abaf045e1..e90c59d35a16 100644 +--- a/drivers/acpi/acpica/exregion.c ++++ b/drivers/acpi/acpica/exregion.c +@@ -176,7 +176,7 @@ acpi_ex_system_memory_space_handler(u32 function, + if (!mem_info->mapped_logical_address) { + ACPI_ERROR((AE_INFO, + "Could not map memory at 0x%8.8X%8.8X, size %u", +- ACPI_FORMAT_NATIVE_UINT(address), ++ ACPI_FORMAT_UINT64(address), + (u32) map_length)); + mem_info->mapped_length = 0; + return_ACPI_STATUS(AE_NO_MEMORY); +@@ -197,8 +197,7 @@ acpi_ex_system_memory_space_handler(u32 function, + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n", +- bit_width, function, +- ACPI_FORMAT_NATIVE_UINT(address))); ++ bit_width, function, ACPI_FORMAT_UINT64(address))); + + /* + * Perform the memory read or write +@@ -300,8 +299,7 @@ acpi_ex_system_io_space_handler(u32 function, + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "System-IO (width %u) R/W %u Address=%8.8X%8.8X\n", +- bit_width, function, +- ACPI_FORMAT_NATIVE_UINT(address))); ++ bit_width, function, ACPI_FORMAT_UINT64(address))); + + /* Decode the function parameter */ + +diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c +index eab70d58852a..fae57584a182 100644 +--- a/drivers/acpi/acpica/hwvalid.c ++++ b/drivers/acpi/acpica/hwvalid.c +@@ -142,17 +142,17 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width) + byte_width = ACPI_DIV_8(bit_width); + last_address = address + byte_width - 1; + +- ACPI_DEBUG_PRINT((ACPI_DB_IO, "Address %p LastAddress %p Length %X", +- ACPI_CAST_PTR(void, address), ACPI_CAST_PTR(void, +- last_address), +- byte_width)); ++ ACPI_DEBUG_PRINT((ACPI_DB_IO, ++ "Address %8.8X%8.8X LastAddress %8.8X%8.8X Length %X", ++ ACPI_FORMAT_UINT64(address), ++ ACPI_FORMAT_UINT64(last_address), byte_width)); + + /* Maximum 16-bit address in I/O space */ + + if (last_address > ACPI_UINT16_MAX) { + ACPI_ERROR((AE_INFO, +- "Illegal I/O port address/length above 64K: %p/0x%X", +- ACPI_CAST_PTR(void, address), byte_width)); ++ "Illegal I/O port address/length above 64K: %8.8X%8.8X/0x%X", ++ ACPI_FORMAT_UINT64(address), byte_width)); + return_ACPI_STATUS(AE_LIMIT); + } + +@@ -181,8 +181,8 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width) + + if (acpi_gbl_osi_data >= port_info->osi_dependency) { + ACPI_DEBUG_PRINT((ACPI_DB_IO, +- "Denied AML access to port 0x%p/%X (%s 0x%.4X-0x%.4X)", +- ACPI_CAST_PTR(void, address), ++ "Denied AML access to port 0x%8.8X%8.8X/%X (%s 0x%.4X-0x%.4X)", ++ ACPI_FORMAT_UINT64(address), + byte_width, port_info->name, + port_info->start, + port_info->end)); +diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c +index ce6e97326205..20ae5b9bb9f2 100644 +--- a/drivers/acpi/acpica/nsdump.c ++++ b/drivers/acpi/acpica/nsdump.c +@@ -258,12 +258,11 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, + switch (type) { + case ACPI_TYPE_PROCESSOR: + +- acpi_os_printf("ID %02X Len %02X Addr %p\n", ++ acpi_os_printf("ID %02X Len %02X Addr %8.8X%8.8X\n", + obj_desc->processor.proc_id, + obj_desc->processor.length, +- ACPI_CAST_PTR(void, +- obj_desc->processor. +- address)); ++ ACPI_FORMAT_UINT64(obj_desc->processor. ++ address)); + break; + + case ACPI_TYPE_DEVICE: +@@ -334,8 +333,9 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, + space_id)); + if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { + acpi_os_printf(" Addr %8.8X%8.8X Len %.4X\n", +- ACPI_FORMAT_NATIVE_UINT +- (obj_desc->region.address), ++ ACPI_FORMAT_UINT64(obj_desc-> ++ region. ++ address), + obj_desc->region.length); + } else { + acpi_os_printf +diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c +index ce3d5db39a9c..5c67b2840c58 100644 +--- a/drivers/acpi/acpica/tbutils.c ++++ b/drivers/acpi/acpica/tbutils.c +@@ -246,16 +246,12 @@ acpi_tb_print_table_header(acpi_physical_address address, + { + struct acpi_table_header local_header; + +- /* +- * The reason that the Address is cast to a void pointer is so that we +- * can use %p which will work properly on both 32-bit and 64-bit hosts. +- */ + if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) { + + /* FACS only has signature and length fields */ + +- ACPI_INFO((AE_INFO, "%4.4s %p %05X", +- header->signature, ACPI_CAST_PTR(void, address), ++ ACPI_INFO((AE_INFO, "%4.4s 0x%8.8X%8.8X %05X", ++ header->signature, ACPI_FORMAT_UINT64(address), + header->length)); + } else if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_RSDP)) { + +@@ -266,8 +262,8 @@ acpi_tb_print_table_header(acpi_physical_address address, + header)->oem_id, ACPI_OEM_ID_SIZE); + acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE); + +- ACPI_INFO((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)", +- ACPI_CAST_PTR (void, address), ++ ACPI_INFO((AE_INFO, "RSDP 0x%8.8X%8.8X %05X (v%.2d %6.6s)", ++ ACPI_FORMAT_UINT64(address), + (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> + revision > + 0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, +@@ -281,8 +277,8 @@ acpi_tb_print_table_header(acpi_physical_address address, + acpi_tb_cleanup_table_header(&local_header, header); + + ACPI_INFO((AE_INFO, +- "%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", +- local_header.signature, ACPI_CAST_PTR(void, address), ++ "%-4.4s 0x%8.8X%8.8X %05X (v%.2d %-6.6s %-8.8s %08X %-4.4s %08X)", ++ local_header.signature, ACPI_FORMAT_UINT64(address), + local_header.length, local_header.revision, + local_header.oem_id, local_header.oem_table_id, + local_header.oem_revision, +@@ -474,8 +470,8 @@ acpi_tb_install_table(acpi_physical_address address, + table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); + if (!table) { + ACPI_ERROR((AE_INFO, +- "Could not map memory for table [%s] at %p", +- signature, ACPI_CAST_PTR(void, address))); ++ "Could not map memory for table [%s] at %8.8X%8.8X", ++ signature, ACPI_FORMAT_UINT64(address))); + return; + } + +diff --git a/drivers/acpi/acpica/utaddress.c b/drivers/acpi/acpica/utaddress.c +index e0a2e2779c2e..3c7770d75773 100644 +--- a/drivers/acpi/acpica/utaddress.c ++++ b/drivers/acpi/acpica/utaddress.c +@@ -107,10 +107,10 @@ acpi_ut_add_address_range(acpi_adr_space_type space_id, + acpi_gbl_address_range_list[space_id] = range_info; + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, +- "\nAdded [%4.4s] address range: 0x%p-0x%p\n", ++ "\nAdded [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n", + acpi_ut_get_node_name(range_info->region_node), +- ACPI_CAST_PTR(void, address), +- ACPI_CAST_PTR(void, range_info->end_address))); ++ ACPI_FORMAT_UINT64(address), ++ ACPI_FORMAT_UINT64(range_info->end_address))); + + (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); + return_ACPI_STATUS(AE_OK); +@@ -160,15 +160,13 @@ acpi_ut_remove_address_range(acpi_adr_space_type space_id, + } + + ACPI_DEBUG_PRINT((ACPI_DB_NAMES, +- "\nRemoved [%4.4s] address range: 0x%p-0x%p\n", ++ "\nRemoved [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n", + acpi_ut_get_node_name(range_info-> + region_node), +- ACPI_CAST_PTR(void, +- range_info-> +- start_address), +- ACPI_CAST_PTR(void, +- range_info-> +- end_address))); ++ ACPI_FORMAT_UINT64(range_info-> ++ start_address), ++ ACPI_FORMAT_UINT64(range_info-> ++ end_address))); + + ACPI_FREE(range_info); + return_VOID; +@@ -244,9 +242,9 @@ acpi_ut_check_address_range(acpi_adr_space_type space_id, + region_node); + + ACPI_WARNING((AE_INFO, +- "0x%p-0x%p %s conflicts with Region %s %d", +- ACPI_CAST_PTR(void, address), +- ACPI_CAST_PTR(void, end_address), ++ "0x%8.8X%8.8X-0x%8.8X%8.8X %s conflicts with Region %s %d", ++ ACPI_FORMAT_UINT64(address), ++ ACPI_FORMAT_UINT64(end_address), + acpi_ut_get_region_name(space_id), + pathname, overlap_count)); + ACPI_FREE(pathname); +diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c +index 711dcf4a0313..7c437826c2f9 100644 +--- a/drivers/bus/mvebu-mbus.c ++++ b/drivers/bus/mvebu-mbus.c +@@ -838,7 +838,7 @@ fs_initcall(mvebu_mbus_debugfs_init); + int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base, + size_t mbuswins_size, + phys_addr_t sdramwins_phys_base, +- size_t sdramwins_size) ++ size_t sdramwins_size, int is_coherent) + { + struct mvebu_mbus_state *mbus = &mbus_state; + const struct of_device_id *of_id; +@@ -865,8 +865,7 @@ int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base, + return -ENOMEM; + } + +- if (of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric")) +- mbus->hw_io_coherency = 1; ++ mbus->hw_io_coherency = is_coherent; + + for (win = 0; win < mbus->soc->num_wins; win++) + mvebu_mbus_disable_window(mbus, win); +diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c +index f505e4ca6d58..3bdefbfb4377 100644 +--- a/drivers/edac/sb_edac.c ++++ b/drivers/edac/sb_edac.c +@@ -623,7 +623,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + u32 reg; + u64 limit, prv = 0; + u64 tmp_mb; +- u32 mb, kb; ++ u32 gb, mb; + u32 rir_way; + + /* +@@ -636,8 +636,9 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + pvt->tolm = GET_TOLM(reg); + tmp_mb = (1 + pvt->tolm) >> 20; + +- mb = div_u64_rem(tmp_mb, 1000, &kb); +- edac_dbg(0, "TOLM: %u.%03u GB (0x%016Lx)\n", mb, kb, (u64)pvt->tolm); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); ++ edac_dbg(0, "TOLM: %u.%03u GB (0x%016Lx)\n", ++ gb, (mb*1000)/1024, (u64)pvt->tolm); + + /* Address range is already 45:25 */ + pci_read_config_dword(pvt->pci_sad1, TOHM, +@@ -645,8 +646,9 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + pvt->tohm = GET_TOHM(reg); + tmp_mb = (1 + pvt->tohm) >> 20; + +- mb = div_u64_rem(tmp_mb, 1000, &kb); +- edac_dbg(0, "TOHM: %u.%03u GB (0x%016Lx)\n", mb, kb, (u64)pvt->tohm); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); ++ edac_dbg(0, "TOHM: %u.%03u GB (0x%016Lx)\n", ++ gb, (mb*1000)/1024, (u64)pvt->tohm); + + /* + * Step 2) Get SAD range and SAD Interleave list +@@ -668,11 +670,11 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + break; + + tmp_mb = (limit + 1) >> 20; +- mb = div_u64_rem(tmp_mb, 1000, &kb); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); + edac_dbg(0, "SAD#%d %s up to %u.%03u GB (0x%016Lx) Interleave: %s reg=0x%08x\n", + n_sads, + get_dram_attr(reg), +- mb, kb, ++ gb, (mb*1000)/1024, + ((u64)tmp_mb) << 20L, + INTERLEAVE_MODE(reg) ? "8:6" : "[8:6]XOR[18:16]", + reg); +@@ -702,9 +704,9 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + break; + tmp_mb = (limit + 1) >> 20; + +- mb = div_u64_rem(tmp_mb, 1000, &kb); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); + edac_dbg(0, "TAD#%d: up to %u.%03u GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n", +- n_tads, mb, kb, ++ n_tads, gb, (mb*1000)/1024, + ((u64)tmp_mb) << 20L, + (u32)TAD_SOCK(reg), + (u32)TAD_CH(reg), +@@ -727,10 +729,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + tad_ch_nilv_offset[j], + ®); + tmp_mb = TAD_OFFSET(reg) >> 20; +- mb = div_u64_rem(tmp_mb, 1000, &kb); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); + edac_dbg(0, "TAD CH#%d, offset #%d: %u.%03u GB (0x%016Lx), reg=0x%08x\n", + i, j, +- mb, kb, ++ gb, (mb*1000)/1024, + ((u64)tmp_mb) << 20L, + reg); + } +@@ -752,10 +754,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + + tmp_mb = RIR_LIMIT(reg) >> 20; + rir_way = 1 << RIR_WAY(reg); +- mb = div_u64_rem(tmp_mb, 1000, &kb); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); + edac_dbg(0, "CH#%d RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d, reg=0x%08x\n", + i, j, +- mb, kb, ++ gb, (mb*1000)/1024, + ((u64)tmp_mb) << 20L, + rir_way, + reg); +@@ -766,10 +768,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci) + ®); + tmp_mb = RIR_OFFSET(reg) << 6; + +- mb = div_u64_rem(tmp_mb, 1000, &kb); ++ gb = div_u64_rem(tmp_mb, 1024, &mb); + edac_dbg(0, "CH#%d RIR#%d INTL#%d, offset %u.%03u GB (0x%016Lx), tgt: %d, reg=0x%08x\n", + i, j, k, +- mb, kb, ++ gb, (mb*1000)/1024, + ((u64)tmp_mb) << 20L, + (u32)RIR_RNK_TGT(reg), + reg); +@@ -806,7 +808,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci, + u8 ch_way,sck_way; + u32 tad_offset; + u32 rir_way; +- u32 mb, kb; ++ u32 mb, gb; + u64 ch_addr, offset, limit, prv = 0; + + +@@ -1022,10 +1024,10 @@ static int get_memory_error_data(struct mem_ctl_info *mci, + continue; + + limit = RIR_LIMIT(reg); +- mb = div_u64_rem(limit >> 20, 1000, &kb); ++ gb = div_u64_rem(limit >> 20, 1024, &mb); + edac_dbg(0, "RIR#%d, limit: %u.%03u GB (0x%016Lx), way: %d\n", + n_rir, +- mb, kb, ++ gb, (mb*1000)/1024, + limit, + 1 << RIR_WAY(reg)); + if (ch_addr <= limit) +diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c +index 62ed744bbe06..a6cdf17e27dc 100644 +--- a/drivers/scsi/hpsa.c ++++ b/drivers/scsi/hpsa.c +@@ -3898,10 +3898,6 @@ static int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev) + + /* Save the PCI command register */ + pci_read_config_word(pdev, 4, &command_register); +- /* Turn the board off. This is so that later pci_restore_state() +- * won't turn the board on before the rest of config space is ready. +- */ +- pci_disable_device(pdev); + pci_save_state(pdev); + + /* find the first memory BAR, so we can find the cfg table */ +@@ -3949,11 +3945,6 @@ static int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev) + goto unmap_cfgtable; + + pci_restore_state(pdev); +- rc = pci_enable_device(pdev); +- if (rc) { +- dev_warn(&pdev->dev, "failed to enable device.\n"); +- goto unmap_cfgtable; +- } + pci_write_config_word(pdev, 4, command_register); + + /* Some devices (notably the HP Smart Array 5i Controller) +@@ -4448,6 +4439,23 @@ static int hpsa_init_reset_devices(struct pci_dev *pdev) + if (!reset_devices) + return 0; + ++ /* kdump kernel is loading, we don't know in which state is ++ * the pci interface. The dev->enable_cnt is equal zero ++ * so we call enable+disable, wait a while and switch it on. ++ */ ++ rc = pci_enable_device(pdev); ++ if (rc) { ++ dev_warn(&pdev->dev, "Failed to enable PCI device\n"); ++ return -ENODEV; ++ } ++ pci_disable_device(pdev); ++ msleep(260); /* a randomly chosen number */ ++ rc = pci_enable_device(pdev); ++ if (rc) { ++ dev_warn(&pdev->dev, "failed to enable device.\n"); ++ return -ENODEV; ++ } ++ pci_set_master(pdev); + /* Reset the controller with a PCI power-cycle or via doorbell */ + rc = hpsa_kdump_hard_reset_controller(pdev); + +@@ -4456,10 +4464,11 @@ static int hpsa_init_reset_devices(struct pci_dev *pdev) + * "performant mode". Or, it might be 640x, which can't reset + * due to concerns about shared bbwc between 6402/6404 pair. + */ +- if (rc == -ENOTSUPP) +- return rc; /* just try to do the kdump anyhow. */ +- if (rc) +- return -ENODEV; ++ if (rc) { ++ if (rc != -ENOTSUPP) /* just try to do the kdump anyhow. */ ++ rc = -ENODEV; ++ goto out_disable; ++ } + + /* Now try to get the controller to respond to a no-op */ + dev_warn(&pdev->dev, "Waiting for controller to respond to no-op\n"); +@@ -4470,7 +4479,11 @@ static int hpsa_init_reset_devices(struct pci_dev *pdev) + dev_warn(&pdev->dev, "no-op failed%s\n", + (i < 11 ? "; re-trying" : "")); + } +- return 0; ++ ++out_disable: ++ ++ pci_disable_device(pdev); ++ return rc; + } + + static int hpsa_allocate_cmd_pool(struct ctlr_info *h) +@@ -4613,6 +4626,7 @@ static void hpsa_undo_allocations_after_kdump_soft_reset(struct ctlr_info *h) + iounmap(h->transtable); + if (h->cfgtable) + iounmap(h->cfgtable); ++ pci_disable_device(h->pdev); + pci_release_regions(h->pdev); + kfree(h); + } +diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c +index 7fb054ba1b60..82f14a1da542 100644 +--- a/fs/btrfs/ctree.c ++++ b/fs/btrfs/ctree.c +@@ -2769,7 +2769,7 @@ done: + */ + if (!p->leave_spinning) + btrfs_set_path_blocking(p); +- if (ret < 0) ++ if (ret < 0 && !p->skip_release_on_error) + btrfs_release_path(p); + return ret; + } +diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h +index d6dd49b51ba8..c19444e412be 100644 +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -586,6 +586,7 @@ struct btrfs_path { + unsigned int skip_locking:1; + unsigned int leave_spinning:1; + unsigned int search_commit_root:1; ++ unsigned int skip_release_on_error:1; + }; + + /* +@@ -3406,6 +3407,10 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, + int verify_dir_item(struct btrfs_root *root, + struct extent_buffer *leaf, + struct btrfs_dir_item *dir_item); ++struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, ++ struct btrfs_path *path, ++ const char *name, ++ int name_len); + + /* orphan.c */ + int btrfs_insert_orphan_item(struct btrfs_trans_handle *trans, +diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c +index 79e594e341c7..6f61b9b1526f 100644 +--- a/fs/btrfs/dir-item.c ++++ b/fs/btrfs/dir-item.c +@@ -21,10 +21,6 @@ + #include "hash.h" + #include "transaction.h" + +-static struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, +- struct btrfs_path *path, +- const char *name, int name_len); +- + /* + * insert a name into a directory, doing overflow properly if there is a hash + * collision. data_size indicates how big the item inserted should be. On +@@ -383,9 +379,9 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans, + * this walks through all the entries in a dir item and finds one + * for a specific name. + */ +-static struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, +- struct btrfs_path *path, +- const char *name, int name_len) ++struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, ++ struct btrfs_path *path, ++ const char *name, int name_len) + { + struct btrfs_dir_item *dir_item; + unsigned long name_ptr; +diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c +index 05740b9789e4..9cf20d63cc99 100644 +--- a/fs/btrfs/xattr.c ++++ b/fs/btrfs/xattr.c +@@ -27,6 +27,7 @@ + #include "transaction.h" + #include "xattr.h" + #include "disk-io.h" ++#include "locking.h" + + + ssize_t __btrfs_getxattr(struct inode *inode, const char *name, +@@ -89,7 +90,7 @@ static int do_setxattr(struct btrfs_trans_handle *trans, + struct inode *inode, const char *name, + const void *value, size_t size, int flags) + { +- struct btrfs_dir_item *di; ++ struct btrfs_dir_item *di = NULL; + struct btrfs_root *root = BTRFS_I(inode)->root; + struct btrfs_path *path; + size_t name_len = strlen(name); +@@ -101,84 +102,128 @@ static int do_setxattr(struct btrfs_trans_handle *trans, + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; ++ path->skip_release_on_error = 1; ++ ++ if (!value) { ++ di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), ++ name, name_len, -1); ++ if (!di && (flags & XATTR_REPLACE)) ++ ret = -ENODATA; ++ else if (di) ++ ret = btrfs_delete_one_dir_name(trans, root, path, di); ++ goto out; ++ } + ++ /* ++ * For a replace we can't just do the insert blindly. ++ * Do a lookup first (read-only btrfs_search_slot), and return if xattr ++ * doesn't exist. If it exists, fall down below to the insert/replace ++ * path - we can't race with a concurrent xattr delete, because the VFS ++ * locks the inode's i_mutex before calling setxattr or removexattr. ++ */ + if (flags & XATTR_REPLACE) { +- di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), name, +- name_len, -1); +- if (IS_ERR(di)) { +- ret = PTR_ERR(di); +- goto out; +- } else if (!di) { ++ if(!mutex_is_locked(&inode->i_mutex)) { ++ pr_err("BTRFS: assertion failed: %s, file: %s, line: %d", ++ "mutex_is_locked(&inode->i_mutex)", __FILE__, ++ __LINE__); ++ BUG(); ++ } ++ di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(inode), ++ name, name_len, 0); ++ if (!di) { + ret = -ENODATA; + goto out; + } +- ret = btrfs_delete_one_dir_name(trans, root, path, di); +- if (ret) +- goto out; + btrfs_release_path(path); ++ di = NULL; ++ } + ++ ret = btrfs_insert_xattr_item(trans, root, path, btrfs_ino(inode), ++ name, name_len, value, size); ++ if (ret == -EOVERFLOW) { + /* +- * remove the attribute ++ * We have an existing item in a leaf, split_leaf couldn't ++ * expand it. That item might have or not a dir_item that ++ * matches our target xattr, so lets check. + */ +- if (!value) +- goto out; +- } else { +- di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(inode), +- name, name_len, 0); +- if (IS_ERR(di)) { +- ret = PTR_ERR(di); ++ ret = 0; ++ btrfs_assert_tree_locked(path->nodes[0]); ++ di = btrfs_match_dir_item_name(root, path, name, name_len); ++ if (!di && !(flags & XATTR_REPLACE)) { ++ ret = -ENOSPC; + goto out; + } +- if (!di && !value) +- goto out; +- btrfs_release_path(path); ++ } else if (ret == -EEXIST) { ++ ret = 0; ++ di = btrfs_match_dir_item_name(root, path, name, name_len); ++ if(!di) { /* logic error */ ++ pr_err("BTRFS: assertion failed: %s, file: %s, line: %d", ++ "di", __FILE__, __LINE__); ++ BUG(); ++ } ++ } else if (ret) { ++ goto out; + } + +-again: +- ret = btrfs_insert_xattr_item(trans, root, path, btrfs_ino(inode), +- name, name_len, value, size); +- /* +- * If we're setting an xattr to a new value but the new value is say +- * exactly BTRFS_MAX_XATTR_SIZE, we could end up with EOVERFLOW getting +- * back from split_leaf. This is because it thinks we'll be extending +- * the existing item size, but we're asking for enough space to add the +- * item itself. So if we get EOVERFLOW just set ret to EEXIST and let +- * the rest of the function figure it out. +- */ +- if (ret == -EOVERFLOW) ++ if (di && (flags & XATTR_CREATE)) { + ret = -EEXIST; ++ goto out; ++ } + +- if (ret == -EEXIST) { +- if (flags & XATTR_CREATE) +- goto out; ++ if (di) { + /* +- * We can't use the path we already have since we won't have the +- * proper locking for a delete, so release the path and +- * re-lookup to delete the thing. ++ * We're doing a replace, and it must be atomic, that is, at ++ * any point in time we have either the old or the new xattr ++ * value in the tree. We don't want readers (getxattr and ++ * listxattrs) to miss a value, this is specially important ++ * for ACLs. + */ +- btrfs_release_path(path); +- di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), +- name, name_len, -1); +- if (IS_ERR(di)) { +- ret = PTR_ERR(di); +- goto out; +- } else if (!di) { +- /* Shouldn't happen but just in case... */ +- btrfs_release_path(path); +- goto again; ++ const int slot = path->slots[0]; ++ struct extent_buffer *leaf = path->nodes[0]; ++ const u16 old_data_len = btrfs_dir_data_len(leaf, di); ++ const u32 item_size = btrfs_item_size_nr(leaf, slot); ++ const u32 data_size = sizeof(*di) + name_len + size; ++ struct btrfs_item *item; ++ unsigned long data_ptr; ++ char *ptr; ++ ++ if (size > old_data_len) { ++ if (btrfs_leaf_free_space(root, leaf) < ++ (size - old_data_len)) { ++ ret = -ENOSPC; ++ goto out; ++ } + } + +- ret = btrfs_delete_one_dir_name(trans, root, path, di); +- if (ret) +- goto out; ++ if (old_data_len + name_len + sizeof(*di) == item_size) { ++ /* No other xattrs packed in the same leaf item. */ ++ if (size > old_data_len) ++ btrfs_extend_item(root, path, ++ size - old_data_len); ++ else if (size < old_data_len) ++ btrfs_truncate_item(root, path, data_size, 1); ++ } else { ++ /* There are other xattrs packed in the same item. */ ++ ret = btrfs_delete_one_dir_name(trans, root, path, di); ++ if (ret) ++ goto out; ++ btrfs_extend_item(root, path, data_size); ++ } + ++ item = btrfs_item_nr(NULL, slot); ++ ptr = btrfs_item_ptr(leaf, slot, char); ++ ptr += btrfs_item_size(leaf, item) - data_size; ++ di = (struct btrfs_dir_item *)ptr; ++ btrfs_set_dir_data_len(leaf, di, size); ++ data_ptr = ((unsigned long)(di + 1)) + name_len; ++ write_extent_buffer(leaf, value, data_ptr, size); ++ btrfs_mark_buffer_dirty(leaf); ++ } else { + /* +- * We have a value to set, so go back and try to insert it now. ++ * Insert, and we had space for the xattr, so path->slots[0] is ++ * where our xattr dir_item is and btrfs_insert_xattr_item() ++ * filled it. + */ +- if (value) { +- btrfs_release_path(path); +- goto again; +- } + } + out: + btrfs_free_path(path); +diff --git a/fs/dcache.c b/fs/dcache.c +index e2800926ae05..38c4a302fab4 100644 +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -1053,13 +1053,13 @@ ascend: + /* might go back up the wrong parent if we have had a rename. */ + if (!locked && read_seqretry(&rename_lock, seq)) + goto rename_retry; +- next = child->d_child.next; +- while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)) { ++ /* go into the first sibling still alive */ ++ do { ++ next = child->d_child.next; + if (next == &this_parent->d_subdirs) + goto ascend; + child = list_entry(next, struct dentry, d_child); +- next = next->next; +- } ++ } while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)); + rcu_read_unlock(); + goto resume; + } +@@ -2977,13 +2977,13 @@ ascend: + /* might go back up the wrong parent if we have had a rename. */ + if (!locked && read_seqretry(&rename_lock, seq)) + goto rename_retry; +- next = child->d_child.next; +- while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)) { ++ /* go into the first sibling still alive */ ++ do { ++ next = child->d_child.next; + if (next == &this_parent->d_subdirs) + goto ascend; + child = list_entry(next, struct dentry, d_child); +- next = next->next; +- } ++ } while (unlikely(child->d_flags & DCACHE_DENTRY_KILLED)); + rcu_read_unlock(); + goto resume; + } +diff --git a/fs/exec.c b/fs/exec.c +index dd6aa61c8548..acbd7ac2deda 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -1265,6 +1265,53 @@ static int check_unsafe_exec(struct linux_binprm *bprm) + return res; + } + ++static void bprm_fill_uid(struct linux_binprm *bprm) ++{ ++ struct inode *inode; ++ unsigned int mode; ++ kuid_t uid; ++ kgid_t gid; ++ ++ /* clear any previous set[ug]id data from a previous binary */ ++ bprm->cred->euid = current_euid(); ++ bprm->cred->egid = current_egid(); ++ ++ if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) ++ return; ++ ++ if (current->no_new_privs) ++ return; ++ ++ inode = file_inode(bprm->file); ++ mode = ACCESS_ONCE(inode->i_mode); ++ if (!(mode & (S_ISUID|S_ISGID))) ++ return; ++ ++ /* Be careful if suid/sgid is set */ ++ mutex_lock(&inode->i_mutex); ++ ++ /* reload atomically mode/uid/gid now that lock held */ ++ mode = inode->i_mode; ++ uid = inode->i_uid; ++ gid = inode->i_gid; ++ mutex_unlock(&inode->i_mutex); ++ ++ /* We ignore suid/sgid if there are no mappings for them in the ns */ ++ if (!kuid_has_mapping(bprm->cred->user_ns, uid) || ++ !kgid_has_mapping(bprm->cred->user_ns, gid)) ++ return; ++ ++ if (mode & S_ISUID) { ++ bprm->per_clear |= PER_CLEAR_ON_SETID; ++ bprm->cred->euid = uid; ++ } ++ ++ if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { ++ bprm->per_clear |= PER_CLEAR_ON_SETID; ++ bprm->cred->egid = gid; ++ } ++} ++ + /* + * Fill the binprm structure from the inode. + * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes +@@ -1273,39 +1320,12 @@ static int check_unsafe_exec(struct linux_binprm *bprm) + */ + int prepare_binprm(struct linux_binprm *bprm) + { +- umode_t mode; +- struct inode * inode = file_inode(bprm->file); + int retval; + +- mode = inode->i_mode; + if (bprm->file->f_op == NULL) + return -EACCES; + +- /* clear any previous set[ug]id data from a previous binary */ +- bprm->cred->euid = current_euid(); +- bprm->cred->egid = current_egid(); +- +- if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) && +- !current->no_new_privs && +- kuid_has_mapping(bprm->cred->user_ns, inode->i_uid) && +- kgid_has_mapping(bprm->cred->user_ns, inode->i_gid)) { +- /* Set-uid? */ +- if (mode & S_ISUID) { +- bprm->per_clear |= PER_CLEAR_ON_SETID; +- bprm->cred->euid = inode->i_uid; +- } +- +- /* Set-gid? */ +- /* +- * If setgid is set but no group execute bit then this +- * is a candidate for mandatory locking, not a setgid +- * executable. +- */ +- if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { +- bprm->per_clear |= PER_CLEAR_ON_SETID; +- bprm->cred->egid = inode->i_gid; +- } +- } ++ bprm_fill_uid(bprm); + + /* fill in binprm security blob */ + retval = security_bprm_set_creds(bprm); +diff --git a/fs/file_table.c b/fs/file_table.c +index 54a34be444f9..28f02a7cbba1 100644 +--- a/fs/file_table.c ++++ b/fs/file_table.c +@@ -36,8 +36,6 @@ struct files_stat_struct files_stat = { + .max_files = NR_FILE + }; + +-DEFINE_STATIC_LGLOCK(files_lglock); +- + /* SLAB cache for file structures */ + static struct kmem_cache *filp_cachep __read_mostly; + +@@ -134,7 +132,6 @@ struct file *get_empty_filp(void) + return ERR_PTR(error); + } + +- INIT_LIST_HEAD(&f->f_u.fu_list); + atomic_long_set(&f->f_count, 1); + rwlock_init(&f->f_owner.lock); + spin_lock_init(&f->f_lock); +@@ -265,18 +262,15 @@ static void __fput(struct file *file) + mntput(mnt); + } + +-static DEFINE_SPINLOCK(delayed_fput_lock); +-static LIST_HEAD(delayed_fput_list); ++static LLIST_HEAD(delayed_fput_list); + static void delayed_fput(struct work_struct *unused) + { +- LIST_HEAD(head); +- spin_lock_irq(&delayed_fput_lock); +- list_splice_init(&delayed_fput_list, &head); +- spin_unlock_irq(&delayed_fput_lock); +- while (!list_empty(&head)) { +- struct file *f = list_first_entry(&head, struct file, f_u.fu_list); +- list_del_init(&f->f_u.fu_list); +- __fput(f); ++ struct llist_node *node = llist_del_all(&delayed_fput_list); ++ struct llist_node *next; ++ ++ for (; node; node = next) { ++ next = llist_next(node); ++ __fput(llist_entry(node, struct file, f_u.fu_llist)); + } + } + +@@ -306,18 +300,15 @@ void fput(struct file *file) + { + if (atomic_long_dec_and_test(&file->f_count)) { + struct task_struct *task = current; +- unsigned long flags; + +- file_sb_list_del(file); + if (likely(!in_interrupt() && !(task->flags & PF_KTHREAD))) { + init_task_work(&file->f_u.fu_rcuhead, ____fput); + if (!task_work_add(task, &file->f_u.fu_rcuhead, true)) + return; + } +- spin_lock_irqsave(&delayed_fput_lock, flags); +- list_add(&file->f_u.fu_list, &delayed_fput_list); +- schedule_work(&delayed_fput_work); +- spin_unlock_irqrestore(&delayed_fput_lock, flags); ++ ++ if (llist_add(&file->f_u.fu_llist, &delayed_fput_list)) ++ schedule_work(&delayed_fput_work); + } + } + +@@ -333,7 +324,6 @@ void __fput_sync(struct file *file) + { + if (atomic_long_dec_and_test(&file->f_count)) { + struct task_struct *task = current; +- file_sb_list_del(file); + BUG_ON(!(task->flags & PF_KTHREAD)); + __fput(file); + } +@@ -345,127 +335,10 @@ void put_filp(struct file *file) + { + if (atomic_long_dec_and_test(&file->f_count)) { + security_file_free(file); +- file_sb_list_del(file); + file_free(file); + } + } + +-static inline int file_list_cpu(struct file *file) +-{ +-#ifdef CONFIG_SMP +- return file->f_sb_list_cpu; +-#else +- return smp_processor_id(); +-#endif +-} +- +-/* helper for file_sb_list_add to reduce ifdefs */ +-static inline void __file_sb_list_add(struct file *file, struct super_block *sb) +-{ +- struct list_head *list; +-#ifdef CONFIG_SMP +- int cpu; +- cpu = smp_processor_id(); +- file->f_sb_list_cpu = cpu; +- list = per_cpu_ptr(sb->s_files, cpu); +-#else +- list = &sb->s_files; +-#endif +- list_add(&file->f_u.fu_list, list); +-} +- +-/** +- * file_sb_list_add - add a file to the sb's file list +- * @file: file to add +- * @sb: sb to add it to +- * +- * Use this function to associate a file with the superblock of the inode it +- * refers to. +- */ +-void file_sb_list_add(struct file *file, struct super_block *sb) +-{ +- lg_local_lock(&files_lglock); +- __file_sb_list_add(file, sb); +- lg_local_unlock(&files_lglock); +-} +- +-/** +- * file_sb_list_del - remove a file from the sb's file list +- * @file: file to remove +- * @sb: sb to remove it from +- * +- * Use this function to remove a file from its superblock. +- */ +-void file_sb_list_del(struct file *file) +-{ +- if (!list_empty(&file->f_u.fu_list)) { +- lg_local_lock_cpu(&files_lglock, file_list_cpu(file)); +- list_del_init(&file->f_u.fu_list); +- lg_local_unlock_cpu(&files_lglock, file_list_cpu(file)); +- } +-} +- +-#ifdef CONFIG_SMP +- +-/* +- * These macros iterate all files on all CPUs for a given superblock. +- * files_lglock must be held globally. +- */ +-#define do_file_list_for_each_entry(__sb, __file) \ +-{ \ +- int i; \ +- for_each_possible_cpu(i) { \ +- struct list_head *list; \ +- list = per_cpu_ptr((__sb)->s_files, i); \ +- list_for_each_entry((__file), list, f_u.fu_list) +- +-#define while_file_list_for_each_entry \ +- } \ +-} +- +-#else +- +-#define do_file_list_for_each_entry(__sb, __file) \ +-{ \ +- struct list_head *list; \ +- list = &(sb)->s_files; \ +- list_for_each_entry((__file), list, f_u.fu_list) +- +-#define while_file_list_for_each_entry \ +-} +- +-#endif +- +-/** +- * mark_files_ro - mark all files read-only +- * @sb: superblock in question +- * +- * All files are marked read-only. We don't care about pending +- * delete files so this should be used in 'force' mode only. +- */ +-void mark_files_ro(struct super_block *sb) +-{ +- struct file *f; +- +- lg_global_lock(&files_lglock); +- do_file_list_for_each_entry(sb, f) { +- if (!S_ISREG(file_inode(f)->i_mode)) +- continue; +- if (!file_count(f)) +- continue; +- if (!(f->f_mode & FMODE_WRITE)) +- continue; +- spin_lock(&f->f_lock); +- f->f_mode &= ~FMODE_WRITE; +- spin_unlock(&f->f_lock); +- if (file_check_writeable(f) != 0) +- continue; +- __mnt_drop_write(f->f_path.mnt); +- file_release_write(f); +- } while_file_list_for_each_entry; +- lg_global_unlock(&files_lglock); +-} +- + void __init files_init(unsigned long mempages) + { + unsigned long n; +@@ -481,6 +354,5 @@ void __init files_init(unsigned long mempages) + n = (mempages * (PAGE_SIZE / 1024)) / 10; + files_stat.max_files = max_t(unsigned long, n, NR_FILE); + files_defer_init(); +- lg_lock_init(&files_lglock, "files_lglock"); + percpu_counter_init(&nr_files, 0); + } +diff --git a/fs/internal.h b/fs/internal.h +index 68121584ae37..2ffa65a36ca0 100644 +--- a/fs/internal.h ++++ b/fs/internal.h +@@ -74,9 +74,6 @@ extern void chroot_fs_refs(const struct path *, const struct path *); + /* + * file_table.c + */ +-extern void file_sb_list_add(struct file *f, struct super_block *sb); +-extern void file_sb_list_del(struct file *f); +-extern void mark_files_ro(struct super_block *); + extern struct file *get_empty_filp(void); + + /* +diff --git a/fs/open.c b/fs/open.c +index 86092bde31f4..5f129683b7d7 100644 +--- a/fs/open.c ++++ b/fs/open.c +@@ -674,7 +674,6 @@ static int do_dentry_open(struct file *f, + } + + f->f_mapping = inode->i_mapping; +- file_sb_list_add(f, inode->i_sb); + + if (unlikely(f->f_mode & FMODE_PATH)) { + f->f_op = &empty_fops; +@@ -709,7 +708,6 @@ static int do_dentry_open(struct file *f, + + cleanup_all: + fops_put(f->f_op); +- file_sb_list_del(f); + if (f->f_mode & FMODE_WRITE) { + if (!special_file(inode->i_mode)) { + /* +diff --git a/fs/super.c b/fs/super.c +index e028b508db25..97280e76179c 100644 +--- a/fs/super.c ++++ b/fs/super.c +@@ -163,19 +163,6 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags) + s = NULL; + goto out; + } +-#ifdef CONFIG_SMP +- s->s_files = alloc_percpu(struct list_head); +- if (!s->s_files) +- goto err_out; +- else { +- int i; +- +- for_each_possible_cpu(i) +- INIT_LIST_HEAD(per_cpu_ptr(s->s_files, i)); +- } +-#else +- INIT_LIST_HEAD(&s->s_files); +-#endif + if (init_sb_writers(s, type)) + goto err_out; + s->s_flags = flags; +@@ -225,10 +212,6 @@ out: + return s; + err_out: + security_sb_free(s); +-#ifdef CONFIG_SMP +- if (s->s_files) +- free_percpu(s->s_files); +-#endif + destroy_sb_writers(s); + kfree(s); + s = NULL; +@@ -243,9 +226,6 @@ err_out: + */ + static inline void destroy_super(struct super_block *s) + { +-#ifdef CONFIG_SMP +- free_percpu(s->s_files); +-#endif + destroy_sb_writers(s); + security_sb_free(s); + WARN_ON(!list_empty(&s->s_mounts)); +@@ -727,7 +707,8 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) + make sure there are no rw files opened */ + if (remount_ro) { + if (force) { +- mark_files_ro(sb); ++ sb->s_readonly_remount = 1; ++ smp_wmb(); + } else { + retval = sb_prepare_remount_readonly(sb); + if (retval) +diff --git a/include/linux/fs.h b/include/linux/fs.h +index d57bc5df7225..5c9dc8471da5 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -10,6 +10,7 @@ + #include <linux/stat.h> + #include <linux/cache.h> + #include <linux/list.h> ++#include <linux/llist.h> + #include <linux/radix-tree.h> + #include <linux/rbtree.h> + #include <linux/init.h> +@@ -761,12 +762,8 @@ static inline int ra_has_index(struct file_ra_state *ra, pgoff_t index) + #define FILE_MNT_WRITE_RELEASED 2 + + struct file { +- /* +- * fu_list becomes invalid after file_free is called and queued via +- * fu_rcuhead for RCU freeing +- */ + union { +- struct list_head fu_list; ++ struct llist_node fu_llist; + struct rcu_head fu_rcuhead; + } f_u; + struct path f_path; +@@ -779,9 +776,6 @@ struct file { + * Must not be taken from IRQ context. + */ + spinlock_t f_lock; +-#ifdef CONFIG_SMP +- int f_sb_list_cpu; +-#endif + atomic_long_t f_count; + unsigned int f_flags; + fmode_t f_mode; +@@ -1257,11 +1251,6 @@ struct super_block { + + struct list_head s_inodes; /* all inodes */ + struct hlist_bl_head s_anon; /* anonymous dentries for (nfs) exporting */ +-#ifdef CONFIG_SMP +- struct list_head __percpu *s_files; +-#else +- struct list_head s_files; +-#endif + struct list_head s_mounts; /* list of mounts; _not_ for fs use */ + /* s_dentry_lru, s_nr_dentry_unused protected by dcache.c lru locks */ + struct list_head s_dentry_lru; /* unused dentry lru */ +diff --git a/include/linux/mbus.h b/include/linux/mbus.h +index dba482e31a13..e80b9c7ec8da 100644 +--- a/include/linux/mbus.h ++++ b/include/linux/mbus.h +@@ -67,6 +67,6 @@ int mvebu_mbus_add_window(const char *devname, phys_addr_t base, + int mvebu_mbus_del_window(phys_addr_t base, size_t size); + int mvebu_mbus_init(const char *soc, phys_addr_t mbus_phys_base, + size_t mbus_size, phys_addr_t sdram_phys_base, +- size_t sdram_size); ++ size_t sdram_size, int is_coherent); + + #endif /* __LINUX_MBUS_H */ +diff --git a/include/linux/sched.h b/include/linux/sched.h +index 00c1d4f45072..7cf305d036db 100644 +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -2203,15 +2203,15 @@ static inline bool thread_group_leader(struct task_struct *p) + * all we care about is that we have a task with the appropriate + * pid, we don't actually care if we have the right task. + */ +-static inline int has_group_leader_pid(struct task_struct *p) ++static inline bool has_group_leader_pid(struct task_struct *p) + { +- return p->pid == p->tgid; ++ return task_pid(p) == p->signal->leader_pid; + } + + static inline +-int same_thread_group(struct task_struct *p1, struct task_struct *p2) ++bool same_thread_group(struct task_struct *p1, struct task_struct *p2) + { +- return p1->tgid == p2->tgid; ++ return p1->signal == p2->signal; + } + + static inline struct task_struct *next_thread(const struct task_struct *p) +diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h +index 665e0cee59bd..5e661a979694 100644 +--- a/include/net/ip6_fib.h ++++ b/include/net/ip6_fib.h +@@ -301,7 +301,7 @@ extern void inet6_rt_notify(int event, struct rt6_info *rt, + struct nl_info *info); + + extern void fib6_run_gc(unsigned long expires, +- struct net *net); ++ struct net *net, bool force); + + extern void fib6_gc_cleanup(void); + +diff --git a/kernel/ptrace.c b/kernel/ptrace.c +index 118323bc8529..30ab20623bca 100644 +--- a/kernel/ptrace.c ++++ b/kernel/ptrace.c +@@ -236,7 +236,7 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode) + */ + int dumpable = 0; + /* Don't let security modules deny introspection */ +- if (task == current) ++ if (same_thread_group(task, current)) + return 0; + rcu_read_lock(); + tcred = __task_cred(task); +diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c +index 9a459be24af7..9b5b5ddf8cd4 100644 +--- a/net/ipv4/xfrm4_policy.c ++++ b/net/ipv4/xfrm4_policy.c +@@ -235,7 +235,7 @@ static struct dst_ops xfrm4_dst_ops = { + .destroy = xfrm4_dst_destroy, + .ifdown = xfrm4_dst_ifdown, + .local_out = __ip_local_out, +- .gc_thresh = 1024, ++ .gc_thresh = 32768, + }; + + static struct xfrm_policy_afinfo xfrm4_policy_afinfo = { +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index ceeb9458bb60..46458ee31939 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -1648,27 +1648,28 @@ static int fib6_age(struct rt6_info *rt, void *arg) + + static DEFINE_SPINLOCK(fib6_gc_lock); + +-void fib6_run_gc(unsigned long expires, struct net *net) ++void fib6_run_gc(unsigned long expires, struct net *net, bool force) + { +- if (expires != ~0UL) { ++ unsigned long now; ++ ++ if (force) { + spin_lock_bh(&fib6_gc_lock); +- gc_args.timeout = expires ? (int)expires : +- net->ipv6.sysctl.ip6_rt_gc_interval; +- } else { +- if (!spin_trylock_bh(&fib6_gc_lock)) { +- mod_timer(&net->ipv6.ip6_fib_timer, jiffies + HZ); +- return; +- } +- gc_args.timeout = net->ipv6.sysctl.ip6_rt_gc_interval; ++ } else if (!spin_trylock_bh(&fib6_gc_lock)) { ++ mod_timer(&net->ipv6.ip6_fib_timer, jiffies + HZ); ++ return; + } ++ gc_args.timeout = expires ? (int)expires : ++ net->ipv6.sysctl.ip6_rt_gc_interval; + + gc_args.more = icmp6_dst_gc(); + + fib6_clean_all(net, fib6_age, 0, NULL); ++ now = jiffies; ++ net->ipv6.ip6_rt_last_gc = now; + + if (gc_args.more) + mod_timer(&net->ipv6.ip6_fib_timer, +- round_jiffies(jiffies ++ round_jiffies(now + + net->ipv6.sysctl.ip6_rt_gc_interval)); + else + del_timer(&net->ipv6.ip6_fib_timer); +@@ -1677,7 +1678,7 @@ void fib6_run_gc(unsigned long expires, struct net *net) + + static void fib6_gc_timer_cb(unsigned long arg) + { +- fib6_run_gc(0, (struct net *)arg); ++ fib6_run_gc(0, (struct net *)arg, true); + } + + static int __net_init fib6_net_init(struct net *net) +diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c +index 05f361338c2e..deedf7ddbc6e 100644 +--- a/net/ipv6/ndisc.c ++++ b/net/ipv6/ndisc.c +@@ -1584,7 +1584,7 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, + switch (event) { + case NETDEV_CHANGEADDR: + neigh_changeaddr(&nd_tbl, dev); +- fib6_run_gc(~0UL, net); ++ fib6_run_gc(0, net, false); + idev = in6_dev_get(dev); + if (!idev) + break; +@@ -1594,7 +1594,7 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, + break; + case NETDEV_DOWN: + neigh_ifdown(&nd_tbl, dev); +- fib6_run_gc(~0UL, net); ++ fib6_run_gc(0, net, false); + break; + case NETDEV_NOTIFY_PEERS: + ndisc_send_unsol_na(dev); +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index d94d224f7e68..6ebefd46f718 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -1334,7 +1334,6 @@ static void icmp6_clean_all(int (*func)(struct rt6_info *rt, void *arg), + + static int ip6_dst_gc(struct dst_ops *ops) + { +- unsigned long now = jiffies; + struct net *net = container_of(ops, struct net, ipv6.ip6_dst_ops); + int rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval; + int rt_max_size = net->ipv6.sysctl.ip6_rt_max_size; +@@ -1344,13 +1343,12 @@ static int ip6_dst_gc(struct dst_ops *ops) + int entries; + + entries = dst_entries_get_fast(ops); +- if (time_after(rt_last_gc + rt_min_interval, now) && ++ if (time_after(rt_last_gc + rt_min_interval, jiffies) && + entries <= rt_max_size) + goto out; + + net->ipv6.ip6_rt_gc_expire++; +- fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net); +- net->ipv6.ip6_rt_last_gc = now; ++ fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net, entries > rt_max_size); + entries = dst_entries_get_slow(ops); + if (entries < ops->gc_thresh) + net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1; +@@ -2849,7 +2847,7 @@ int ipv6_sysctl_rtcache_flush(ctl_table *ctl, int write, + net = (struct net *)ctl->extra1; + delay = net->ipv6.sysctl.flush_delay; + proc_dointvec(ctl, write, buffer, lenp, ppos); +- fib6_run_gc(delay <= 0 ? ~0UL : (unsigned long)delay, net); ++ fib6_run_gc(delay <= 0 ? 0 : (unsigned long)delay, net, delay > 0); + return 0; + } + +diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c +index 23ed03d786c8..1c2e0c9ba8a1 100644 +--- a/net/ipv6/xfrm6_policy.c ++++ b/net/ipv6/xfrm6_policy.c +@@ -284,7 +284,7 @@ static struct dst_ops xfrm6_dst_ops = { + .destroy = xfrm6_dst_destroy, + .ifdown = xfrm6_dst_ifdown, + .local_out = __ip6_local_out, +- .gc_thresh = 1024, ++ .gc_thresh = 32768, + }; + + static struct xfrm_policy_afinfo xfrm6_policy_afinfo = { +diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c +index a191b6db657e..3b283edec027 100644 +--- a/net/netfilter/nfnetlink_cthelper.c ++++ b/net/netfilter/nfnetlink_cthelper.c +@@ -74,6 +74,9 @@ nfnl_cthelper_parse_tuple(struct nf_conntrack_tuple *tuple, + if (!tb[NFCTH_TUPLE_L3PROTONUM] || !tb[NFCTH_TUPLE_L4PROTONUM]) + return -EINVAL; + ++ /* Not all fields are initialized so first zero the tuple */ ++ memset(tuple, 0, sizeof(struct nf_conntrack_tuple)); ++ + tuple->src.l3num = ntohs(nla_get_be16(tb[NFCTH_TUPLE_L3PROTONUM])); + tuple->dst.protonum = nla_get_u8(tb[NFCTH_TUPLE_L4PROTONUM]); + +@@ -83,7 +86,7 @@ nfnl_cthelper_parse_tuple(struct nf_conntrack_tuple *tuple, + static int + nfnl_cthelper_from_nlattr(struct nlattr *attr, struct nf_conn *ct) + { +- const struct nf_conn_help *help = nfct_help(ct); ++ struct nf_conn_help *help = nfct_help(ct); + + if (attr == NULL) + return -EINVAL; +@@ -91,7 +94,7 @@ nfnl_cthelper_from_nlattr(struct nlattr *attr, struct nf_conn *ct) + if (help->helper->data_len == 0) + return -EINVAL; + +- memcpy(&help->data, nla_data(attr), help->helper->data_len); ++ memcpy(help->data, nla_data(attr), help->helper->data_len); + return 0; + } + |