From dffa5e7a0820a3f2066bbc98bdf0c145b918ac6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Pe=C4=8Dovnik?= Date: Sat, 4 Jan 2020 18:24:37 +0100 Subject: [PATCH] Update AUFS on S5P6818 family and add upstream patch for XU4 (#1717) --- config/kernel/linux-odroidxu4-legacy.config | 4 +- config/kernel/linux-s5p6818-legacy.config | 2 +- .../odroidxu4-legacy/patch-4.14.161-162.patch | 3364 +++++++++++++++++ ...119.patch => 0001-aufs4.14-20190902.patch} | 909 ++--- 4 files changed, 3853 insertions(+), 426 deletions(-) create mode 100644 patch/kernel/odroidxu4-legacy/patch-4.14.161-162.patch rename patch/kernel/s5p6818-legacy/{0001-aufs4.14-20181119.patch => 0001-aufs4.14-20190902.patch} (98%) diff --git a/config/kernel/linux-odroidxu4-legacy.config b/config/kernel/linux-odroidxu4-legacy.config index 19cc158ad0..ab3476defd 100644 --- a/config/kernel/linux-odroidxu4-legacy.config +++ b/config/kernel/linux-odroidxu4-legacy.config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 4.14.161 Kernel Configuration +# Linux/arm 4.14.162 Kernel Configuration # CONFIG_ARM=y CONFIG_ARM_HAS_SG_CHAIN=y @@ -2143,7 +2143,7 @@ CONFIG_WLAN_VENDOR_TI=y # CONFIG_WLCORE is not set CONFIG_RTL8822BU=m CONFIG_RTL8188EU=m -CONFIG_RTL8821CU=m +# CONFIG_RTL8821CU is not set CONFIG_RTL8812AU=m CONFIG_WLAN_VENDOR_ZYDAS=y CONFIG_USB_ZD1201=m diff --git a/config/kernel/linux-s5p6818-legacy.config b/config/kernel/linux-s5p6818-legacy.config index 9bb7a5f967..9904670338 100644 --- a/config/kernel/linux-s5p6818-legacy.config +++ b/config/kernel/linux-s5p6818-legacy.config @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm64 4.14.160 Kernel Configuration +# Linux/arm64 4.14.162 Kernel Configuration # CONFIG_ARM64=y CONFIG_64BIT=y diff --git a/patch/kernel/odroidxu4-legacy/patch-4.14.161-162.patch b/patch/kernel/odroidxu4-legacy/patch-4.14.161-162.patch new file mode 100644 index 0000000000..d65225708e --- /dev/null +++ b/patch/kernel/odroidxu4-legacy/patch-4.14.161-162.patch @@ -0,0 +1,3364 @@ +diff --git a/Makefile b/Makefile +index 6b4528888a75..cb57b5c58e2b 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 4 + PATCHLEVEL = 14 +-SUBLEVEL = 161 ++SUBLEVEL = 162 + EXTRAVERSION = + NAME = Petit Gorille + +diff --git a/arch/arm/boot/compressed/libfdt_env.h b/arch/arm/boot/compressed/libfdt_env.h +index b36c0289a308..6a0f1f524466 100644 +--- a/arch/arm/boot/compressed/libfdt_env.h ++++ b/arch/arm/boot/compressed/libfdt_env.h +@@ -2,11 +2,13 @@ + #ifndef _ARM_LIBFDT_ENV_H + #define _ARM_LIBFDT_ENV_H + ++#include + #include + #include + #include + +-#define INT_MAX ((int)(~0U>>1)) ++#define INT32_MAX S32_MAX ++#define UINT32_MAX U32_MAX + + typedef __be16 fdt16_t; + typedef __be32 fdt32_t; +diff --git a/arch/powerpc/boot/libfdt_env.h b/arch/powerpc/boot/libfdt_env.h +index 39155d3b2cef..ac5d3c947e04 100644 +--- a/arch/powerpc/boot/libfdt_env.h ++++ b/arch/powerpc/boot/libfdt_env.h +@@ -6,6 +6,8 @@ + #include + + #define INT_MAX ((int)(~0U>>1)) ++#define UINT32_MAX ((u32)~0U) ++#define INT32_MAX ((s32)(UINT32_MAX >> 1)) + + #include "of.h" + +diff --git a/arch/powerpc/kernel/security.c b/arch/powerpc/kernel/security.c +index f5d6541bf8c2..b3f540c9f410 100644 +--- a/arch/powerpc/kernel/security.c ++++ b/arch/powerpc/kernel/security.c +@@ -134,32 +134,33 @@ ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, cha + + thread_priv = security_ftr_enabled(SEC_FTR_L1D_THREAD_PRIV); + +- if (rfi_flush || thread_priv) { ++ if (rfi_flush) { + struct seq_buf s; + seq_buf_init(&s, buf, PAGE_SIZE - 1); + +- seq_buf_printf(&s, "Mitigation: "); +- +- if (rfi_flush) +- seq_buf_printf(&s, "RFI Flush"); +- +- if (rfi_flush && thread_priv) +- seq_buf_printf(&s, ", "); +- ++ seq_buf_printf(&s, "Mitigation: RFI Flush"); + if (thread_priv) +- seq_buf_printf(&s, "L1D private per thread"); ++ seq_buf_printf(&s, ", L1D private per thread"); + + seq_buf_printf(&s, "\n"); + + return s.len; + } + ++ if (thread_priv) ++ return sprintf(buf, "Vulnerable: L1D private per thread\n"); ++ + if (!security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) && + !security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR)) + return sprintf(buf, "Not affected\n"); + + return sprintf(buf, "Vulnerable\n"); + } ++ ++ssize_t cpu_show_l1tf(struct device *dev, struct device_attribute *attr, char *buf) ++{ ++ return cpu_show_meltdown(dev, attr, buf); ++} + #endif + + ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr, char *buf) +diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c +index 14f3f28a089e..66a9987dc0f8 100644 +--- a/arch/powerpc/kernel/time.c ++++ b/arch/powerpc/kernel/time.c +@@ -241,7 +241,7 @@ static u64 scan_dispatch_log(u64 stop_tb) + * Accumulate stolen time by scanning the dispatch trace log. + * Called on entry from user mode. + */ +-void accumulate_stolen_time(void) ++void notrace accumulate_stolen_time(void) + { + u64 sst, ust; + u8 save_soft_enabled = local_paca->soft_enabled; +diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c +index 58c14749bb0c..387600ecea60 100644 +--- a/arch/powerpc/mm/hash_utils_64.c ++++ b/arch/powerpc/mm/hash_utils_64.c +@@ -292,10 +292,18 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, + ret = mmu_hash_ops.hpte_insert(hpteg, vpn, paddr, tprot, + HPTE_V_BOLTED, psize, psize, + ssize); +- ++ if (ret == -1) { ++ /* Try to remove a non bolted entry */ ++ ret = mmu_hash_ops.hpte_remove(hpteg); ++ if (ret != -1) ++ ret = mmu_hash_ops.hpte_insert(hpteg, vpn, paddr, tprot, ++ HPTE_V_BOLTED, psize, psize, ++ ssize); ++ } + if (ret < 0) + break; + ++ cond_resched(); + #ifdef CONFIG_DEBUG_PAGEALLOC + if (debug_pagealloc_enabled() && + (paddr >> PAGE_SHIFT) < linear_map_hash_count) +diff --git a/arch/powerpc/platforms/pseries/cmm.c b/arch/powerpc/platforms/pseries/cmm.c +index 4ac419c7eb4c..25224c9e1dc0 100644 +--- a/arch/powerpc/platforms/pseries/cmm.c ++++ b/arch/powerpc/platforms/pseries/cmm.c +@@ -425,6 +425,10 @@ static struct bus_type cmm_subsys = { + .dev_name = "cmm", + }; + ++static void cmm_release_device(struct device *dev) ++{ ++} ++ + /** + * cmm_sysfs_register - Register with sysfs + * +@@ -440,6 +444,7 @@ static int cmm_sysfs_register(struct device *dev) + + dev->id = 0; + dev->bus = &cmm_subsys; ++ dev->release = cmm_release_device; + + if ((rc = device_register(dev))) + goto subsys_unregister; +diff --git a/arch/powerpc/tools/relocs_check.sh b/arch/powerpc/tools/relocs_check.sh +index ec2d5c835170..d6c16e7faa38 100755 +--- a/arch/powerpc/tools/relocs_check.sh ++++ b/arch/powerpc/tools/relocs_check.sh +@@ -23,7 +23,7 @@ objdump="$1" + vmlinux="$2" + + bad_relocs=$( +-"$objdump" -R "$vmlinux" | ++$objdump -R "$vmlinux" | + # Only look at relocation lines. + grep -E '\:' | + awk '{print $1}' + ) + + BRANCHES=$( +-"$objdump" -R "$vmlinux" -D --start-address=0xc000000000000000 \ ++$objdump -R "$vmlinux" -D --start-address=0xc000000000000000 \ + --stop-address=${end_intr} | + grep -e "^c[0-9a-f]*:[[:space:]]*\([0-9a-f][0-9a-f][[:space:]]\)\{4\}[[:space:]]*b" | + grep -v '\<__start_initialization_multiplatform>' | +diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c +index 2e2fd9535f86..45304085b6ee 100644 +--- a/arch/s390/kernel/perf_cpum_sf.c ++++ b/arch/s390/kernel/perf_cpum_sf.c +@@ -185,7 +185,7 @@ static int realloc_sampling_buffer(struct sf_buffer *sfb, + unsigned long num_sdb, gfp_t gfp_flags) + { + int i, rc; +- unsigned long *new, *tail; ++ unsigned long *new, *tail, *tail_prev = NULL; + + if (!sfb->sdbt || !sfb->tail) + return -EINVAL; +@@ -224,6 +224,7 @@ static int realloc_sampling_buffer(struct sf_buffer *sfb, + sfb->num_sdbt++; + /* Link current page to tail of chain */ + *tail = (unsigned long)(void *) new + 1; ++ tail_prev = tail; + tail = new; + } + +@@ -233,10 +234,22 @@ static int realloc_sampling_buffer(struct sf_buffer *sfb, + * issue, a new realloc call (if required) might succeed. + */ + rc = alloc_sample_data_block(tail, gfp_flags); +- if (rc) ++ if (rc) { ++ /* Undo last SDBT. An SDBT with no SDB at its first ++ * entry but with an SDBT entry instead can not be ++ * handled by the interrupt handler code. ++ * Avoid this situation. ++ */ ++ if (tail_prev) { ++ sfb->num_sdbt--; ++ free_page((unsigned long) new); ++ tail = tail_prev; ++ } + break; ++ } + sfb->num_sdb++; + tail++; ++ tail_prev = new = NULL; /* Allocated at least one SBD */ + } + + /* Link sampling buffer to its origin */ +diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c +index c7bd2e549a6a..0b0e44f85393 100644 +--- a/arch/x86/kernel/cpu/mcheck/mce.c ++++ b/arch/x86/kernel/cpu/mcheck/mce.c +@@ -802,8 +802,8 @@ static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp, + if (quirk_no_way_out) + quirk_no_way_out(i, m, regs); + ++ m->bank = i; + if (mce_severity(m, mca_cfg.tolerant, &tmp, true) >= MCE_PANIC_SEVERITY) { +- m->bank = i; + mce_read_aux(m, i); + *msg = tmp; + return 1; +diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c +index 90dd8e7291da..1c90da4af94f 100644 +--- a/drivers/cdrom/cdrom.c ++++ b/drivers/cdrom/cdrom.c +@@ -995,6 +995,12 @@ static void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype *tracks) + tracks->xa = 0; + tracks->error = 0; + cd_dbg(CD_COUNT_TRACKS, "entering cdrom_count_tracks\n"); ++ ++ if (!CDROM_CAN(CDC_PLAY_AUDIO)) { ++ tracks->error = CDS_NO_INFO; ++ return; ++ } ++ + /* Grab the TOC header so we can see how many tracks there are */ + ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header); + if (ret) { +@@ -1161,7 +1167,8 @@ int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, + ret = open_for_data(cdi); + if (ret) + goto err; +- cdrom_mmc3_profile(cdi); ++ if (CDROM_CAN(CDC_GENERIC_PACKET)) ++ cdrom_mmc3_profile(cdi); + if (mode & FMODE_WRITE) { + ret = -EROFS; + if (cdrom_open_write(cdi)) +@@ -2878,6 +2885,9 @@ int cdrom_get_last_written(struct cdrom_device_info *cdi, long *last_written) + it doesn't give enough information or fails. then we return + the toc contents. */ + use_toc: ++ if (!CDROM_CAN(CDC_PLAY_AUDIO)) ++ return -ENOSYS; ++ + toc.cdte_format = CDROM_MSF; + toc.cdte_track = CDROM_LEADOUT; + if ((ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &toc))) +diff --git a/drivers/clk/pxa/clk-pxa27x.c b/drivers/clk/pxa/clk-pxa27x.c +index 25a30194d27a..b67ea86ff156 100644 +--- a/drivers/clk/pxa/clk-pxa27x.c ++++ b/drivers/clk/pxa/clk-pxa27x.c +@@ -462,6 +462,7 @@ struct dummy_clk { + }; + static struct dummy_clk dummy_clks[] __initdata = { + DUMMY_CLK(NULL, "pxa27x-gpio", "osc_32_768khz"), ++ DUMMY_CLK(NULL, "pxa-rtc", "osc_32_768khz"), + DUMMY_CLK(NULL, "sa1100-rtc", "osc_32_768khz"), + DUMMY_CLK("UARTCLK", "pxa2xx-ir", "STUART"), + }; +diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c +index 1a0985ae20d2..a93439242565 100644 +--- a/drivers/clk/qcom/clk-rcg2.c ++++ b/drivers/clk/qcom/clk-rcg2.c +@@ -212,6 +212,8 @@ static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f, + p = clk_hw_get_parent_by_index(hw, index); + if (clk_flags & CLK_SET_RATE_PARENT) { + if (f->pre_div) { ++ if (!rate) ++ rate = req->rate; + rate /= 2; + rate *= f->pre_div + 1; + } +diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c +index 28ceaf1e9937..ae9352f7706d 100644 +--- a/drivers/clk/qcom/common.c ++++ b/drivers/clk/qcom/common.c +@@ -37,6 +37,9 @@ struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate) + if (!f) + return NULL; + ++ if (!f->freq) ++ return f; ++ + for (; f->freq; f++) + if (rate <= f->freq) + return f; +diff --git a/drivers/clocksource/asm9260_timer.c b/drivers/clocksource/asm9260_timer.c +index 38cd2feb87c4..0ce760776406 100644 +--- a/drivers/clocksource/asm9260_timer.c ++++ b/drivers/clocksource/asm9260_timer.c +@@ -198,6 +198,10 @@ static int __init asm9260_timer_init(struct device_node *np) + } + + clk = of_clk_get(np, 0); ++ if (IS_ERR(clk)) { ++ pr_err("Failed to get clk!\n"); ++ return PTR_ERR(clk); ++ } + + ret = clk_prepare_enable(clk); + if (ret) { +diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c +index 8c93dec498fa..e7783b852d69 100644 +--- a/drivers/gpio/gpio-mpc8xxx.c ++++ b/drivers/gpio/gpio-mpc8xxx.c +@@ -337,7 +337,8 @@ static int mpc8xxx_probe(struct platform_device *pdev) + * It's assumed that only a single type of gpio controller is available + * on the current machine, so overwriting global data is fine. + */ +- mpc8xxx_irq_chip.irq_set_type = devtype->irq_set_type; ++ if (devtype->irq_set_type) ++ mpc8xxx_irq_chip.irq_set_type = devtype->irq_set_type; + + if (devtype->gpio_dir_out) + gc->direction_output = devtype->gpio_dir_out; +diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c +index 0c547bf841f4..6a04b56d161b 100644 +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -760,6 +760,10 @@ static void hid_scan_feature_usage(struct hid_parser *parser, u32 usage) + if (usage == 0xff0000c5 && parser->global.report_count == 256 && + parser->global.report_size == 8) + parser->scan_flags |= HID_SCAN_FLAG_MT_WIN_8; ++ ++ if (usage == 0xff0000c6 && parser->global.report_count == 1 && ++ parser->global.report_size == 8) ++ parser->scan_flags |= HID_SCAN_FLAG_MT_WIN_8; + } + + static void hid_scan_collection(struct hid_parser *parser, unsigned type) +diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c +index 4706fb852eaf..6ad776b4711b 100644 +--- a/drivers/hid/hid-logitech-hidpp.c ++++ b/drivers/hid/hid-logitech-hidpp.c +@@ -978,6 +978,9 @@ static int hidpp20_batterylevel_get_battery_capacity(struct hidpp_device *hidpp, + ret = hidpp_send_fap_command_sync(hidpp, feature_index, + CMD_BATTERY_LEVEL_STATUS_GET_BATTERY_LEVEL_STATUS, + NULL, 0, &response); ++ /* Ignore these intermittent errors */ ++ if (ret == HIDPP_ERROR_RESOURCE_ERROR) ++ return -EIO; + if (ret > 0) { + hid_err(hidpp->hid_dev, "%s: received protocol error 0x%02x\n", + __func__, ret); +diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c +index 59aaac43db91..138d1f3b12b2 100644 +--- a/drivers/input/touchscreen/atmel_mxt_ts.c ++++ b/drivers/input/touchscreen/atmel_mxt_ts.c +@@ -3257,6 +3257,8 @@ static int __maybe_unused mxt_suspend(struct device *dev) + + mutex_unlock(&input_dev->mutex); + ++ disable_irq(data->irq); ++ + return 0; + } + +@@ -3269,6 +3271,8 @@ static int __maybe_unused mxt_resume(struct device *dev) + if (!input_dev) + return 0; + ++ enable_irq(data->irq); ++ + mutex_lock(&input_dev->mutex); + + if (input_dev->users) +diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c +index 40eb8138546a..848dac3e4580 100644 +--- a/drivers/iommu/tegra-smmu.c ++++ b/drivers/iommu/tegra-smmu.c +@@ -156,9 +156,9 @@ static bool smmu_dma_addr_valid(struct tegra_smmu *smmu, dma_addr_t addr) + return (addr & smmu->pfn_mask) == addr; + } + +-static dma_addr_t smmu_pde_to_dma(u32 pde) ++static dma_addr_t smmu_pde_to_dma(struct tegra_smmu *smmu, u32 pde) + { +- return pde << 12; ++ return (dma_addr_t)(pde & smmu->pfn_mask) << 12; + } + + static void smmu_flush_ptc_all(struct tegra_smmu *smmu) +@@ -543,6 +543,7 @@ static u32 *tegra_smmu_pte_lookup(struct tegra_smmu_as *as, unsigned long iova, + dma_addr_t *dmap) + { + unsigned int pd_index = iova_pd_index(iova); ++ struct tegra_smmu *smmu = as->smmu; + struct page *pt_page; + u32 *pd; + +@@ -551,7 +552,7 @@ static u32 *tegra_smmu_pte_lookup(struct tegra_smmu_as *as, unsigned long iova, + return NULL; + + pd = page_address(as->pd); +- *dmap = smmu_pde_to_dma(pd[pd_index]); ++ *dmap = smmu_pde_to_dma(smmu, pd[pd_index]); + + return tegra_smmu_pte_offset(pt_page, iova); + } +@@ -593,7 +594,7 @@ static u32 *as_get_pte(struct tegra_smmu_as *as, dma_addr_t iova, + } else { + u32 *pd = page_address(as->pd); + +- *dmap = smmu_pde_to_dma(pd[pde]); ++ *dmap = smmu_pde_to_dma(smmu, pd[pde]); + } + + return tegra_smmu_pte_offset(as->pts[pde], iova); +@@ -618,7 +619,7 @@ static void tegra_smmu_pte_put_use(struct tegra_smmu_as *as, unsigned long iova) + if (--as->count[pde] == 0) { + struct tegra_smmu *smmu = as->smmu; + u32 *pd = page_address(as->pd); +- dma_addr_t pte_dma = smmu_pde_to_dma(pd[pde]); ++ dma_addr_t pte_dma = smmu_pde_to_dma(smmu, pd[pde]); + + tegra_smmu_set_pde(as, iova, 0); + +diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c +index 0b9a8b709abf..b32988cac80c 100644 +--- a/drivers/irqchip/irq-bcm7038-l1.c ++++ b/drivers/irqchip/irq-bcm7038-l1.c +@@ -284,6 +284,10 @@ static int __init bcm7038_l1_init_one(struct device_node *dn, + pr_err("failed to map parent interrupt %d\n", parent_irq); + return -EINVAL; + } ++ ++ if (of_property_read_bool(dn, "brcm,irq-can-wake")) ++ enable_irq_wake(parent_irq); ++ + irq_set_chained_handler_and_data(parent_irq, bcm7038_l1_irq_handle, + intc); + +diff --git a/drivers/irqchip/irq-ingenic.c b/drivers/irqchip/irq-ingenic.c +index fc5953dea509..b2e16dca76a6 100644 +--- a/drivers/irqchip/irq-ingenic.c ++++ b/drivers/irqchip/irq-ingenic.c +@@ -117,6 +117,14 @@ static int __init ingenic_intc_of_init(struct device_node *node, + goto out_unmap_irq; + } + ++ domain = irq_domain_add_legacy(node, num_chips * 32, ++ JZ4740_IRQ_BASE, 0, ++ &irq_domain_simple_ops, NULL); ++ if (!domain) { ++ err = -ENOMEM; ++ goto out_unmap_base; ++ } ++ + for (i = 0; i < num_chips; i++) { + /* Mask all irqs */ + writel(0xffffffff, intc->base + (i * CHIP_SIZE) + +@@ -143,14 +151,11 @@ static int __init ingenic_intc_of_init(struct device_node *node, + IRQ_NOPROBE | IRQ_LEVEL); + } + +- domain = irq_domain_add_legacy(node, num_chips * 32, JZ4740_IRQ_BASE, 0, +- &irq_domain_simple_ops, NULL); +- if (!domain) +- pr_warn("unable to register IRQ domain\n"); +- + setup_irq(parent_irq, &intc_cascade_action); + return 0; + ++out_unmap_base: ++ iounmap(intc->base); + out_unmap_irq: + irq_dispose_mapping(parent_irq); + out_free: +diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c +index 9406326216f1..96a6583e7b52 100644 +--- a/drivers/md/bcache/btree.c ++++ b/drivers/md/bcache/btree.c +@@ -685,6 +685,8 @@ static unsigned long bch_mca_scan(struct shrinker *shrink, + * IO can always make forward progress: + */ + nr /= c->btree_pages; ++ if (nr == 0) ++ nr = 1; + nr = min_t(unsigned long, nr, mca_can_free(c)); + + i = 0; +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 5f6602cb191f..fef599eb822b 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -2186,9 +2186,6 @@ static void bond_miimon_commit(struct bonding *bond) + } else if (BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) { + /* make it immediately active */ + bond_set_active_slave(slave); +- } else if (slave != primary) { +- /* prevent it from being the active one */ +- bond_set_backup_slave(slave); + } + + netdev_info(bond->dev, "link status definitely up for interface %s, %u Mbps %s duplex\n", +diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c +index db6f6a877f63..d22b138c2b09 100644 +--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c ++++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c +@@ -1196,8 +1196,8 @@ static int ena_io_poll(struct napi_struct *napi, int budget) + struct ena_napi *ena_napi = container_of(napi, struct ena_napi, napi); + struct ena_ring *tx_ring, *rx_ring; + +- u32 tx_work_done; +- u32 rx_work_done; ++ int tx_work_done; ++ int rx_work_done = 0; + int tx_budget; + int napi_comp_call = 0; + int ret; +@@ -1214,7 +1214,11 @@ static int ena_io_poll(struct napi_struct *napi, int budget) + } + + tx_work_done = ena_clean_tx_irq(tx_ring, tx_budget); +- rx_work_done = ena_clean_rx_irq(rx_ring, napi, budget); ++ /* On netpoll the budget is zero and the handler should only clean the ++ * tx completions. ++ */ ++ if (likely(budget)) ++ rx_work_done = ena_clean_rx_irq(rx_ring, napi, budget); + + /* If the device is about to reset or down, avoid unmask + * the interrupt and return 0 so NAPI won't reschedule +diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.c b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.c +index 993cb5ba934e..b99169a386eb 100644 +--- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.c ++++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.c +@@ -37,6 +37,7 @@ + #include + #include + #include ++#include + #include + #include "mlxfw_mfa2.h" + #include "mlxfw_mfa2_file.h" +@@ -579,7 +580,7 @@ mlxfw_mfa2_file_component_get(const struct mlxfw_mfa2_file *mfa2_file, + comp_size = be32_to_cpu(comp->size); + comp_buf_size = comp_size + mlxfw_mfa2_comp_magic_len; + +- comp_data = kmalloc(sizeof(*comp_data) + comp_buf_size, GFP_KERNEL); ++ comp_data = vzalloc(sizeof(*comp_data) + comp_buf_size); + if (!comp_data) + return ERR_PTR(-ENOMEM); + comp_data->comp.data_size = comp_size; +@@ -601,7 +602,7 @@ mlxfw_mfa2_file_component_get(const struct mlxfw_mfa2_file *mfa2_file, + comp_data->comp.data = comp_data->buff + mlxfw_mfa2_comp_magic_len; + return &comp_data->comp; + err_out: +- kfree(comp_data); ++ vfree(comp_data); + return ERR_PTR(err); + } + +@@ -610,7 +611,7 @@ void mlxfw_mfa2_file_component_put(struct mlxfw_mfa2_component *comp) + const struct mlxfw_mfa2_comp_data *comp_data; + + comp_data = container_of(comp, struct mlxfw_mfa2_comp_data, comp); +- kfree(comp_data); ++ vfree(comp_data); + } + + void mlxfw_mfa2_file_fini(struct mlxfw_mfa2_file *mfa2_file) +diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c +index 5de4053774b8..35905e9ee9ec 100644 +--- a/drivers/net/gtp.c ++++ b/drivers/net/gtp.c +@@ -42,7 +42,6 @@ struct pdp_ctx { + struct hlist_node hlist_addr; + + union { +- u64 tid; + struct { + u64 tid; + u16 flow; +@@ -545,7 +544,7 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, + mtu = dst_mtu(&rt->dst); + } + +- rt->dst.ops->update_pmtu(&rt->dst, NULL, skb, mtu); ++ rt->dst.ops->update_pmtu(&rt->dst, NULL, skb, mtu, false); + + if (!skb_is_gso(skb) && (iph->frag_off & htons(IP_DF)) && + mtu < ntohs(iph->tot_len)) { +@@ -645,9 +644,16 @@ static void gtp_link_setup(struct net_device *dev) + } + + static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize); +-static void gtp_hashtable_free(struct gtp_dev *gtp); + static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[]); + ++static void gtp_destructor(struct net_device *dev) ++{ ++ struct gtp_dev *gtp = netdev_priv(dev); ++ ++ kfree(gtp->addr_hash); ++ kfree(gtp->tid_hash); ++} ++ + static int gtp_newlink(struct net *src_net, struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[], + struct netlink_ext_ack *extack) +@@ -665,10 +671,13 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, + if (err < 0) + return err; + +- if (!data[IFLA_GTP_PDP_HASHSIZE]) ++ if (!data[IFLA_GTP_PDP_HASHSIZE]) { + hashsize = 1024; +- else ++ } else { + hashsize = nla_get_u32(data[IFLA_GTP_PDP_HASHSIZE]); ++ if (!hashsize) ++ hashsize = 1024; ++ } + + err = gtp_hashtable_new(gtp, hashsize); + if (err < 0) +@@ -682,13 +691,15 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, + + gn = net_generic(dev_net(dev), gtp_net_id); + list_add_rcu(>p->list, &gn->gtp_dev_list); ++ dev->priv_destructor = gtp_destructor; + + netdev_dbg(dev, "registered new GTP interface\n"); + + return 0; + + out_hashtable: +- gtp_hashtable_free(gtp); ++ kfree(gtp->addr_hash); ++ kfree(gtp->tid_hash); + out_encap: + gtp_encap_disable(gtp); + return err; +@@ -697,9 +708,14 @@ out_encap: + static void gtp_dellink(struct net_device *dev, struct list_head *head) + { + struct gtp_dev *gtp = netdev_priv(dev); ++ struct pdp_ctx *pctx; ++ int i; ++ ++ for (i = 0; i < gtp->hash_size; i++) ++ hlist_for_each_entry_rcu(pctx, >p->tid_hash[i], hlist_tid) ++ pdp_context_delete(pctx); + + gtp_encap_disable(gtp); +- gtp_hashtable_free(gtp); + list_del_rcu(>p->list); + unregister_netdevice_queue(dev, head); + } +@@ -775,20 +791,6 @@ err1: + return -ENOMEM; + } + +-static void gtp_hashtable_free(struct gtp_dev *gtp) +-{ +- struct pdp_ctx *pctx; +- int i; +- +- for (i = 0; i < gtp->hash_size; i++) +- hlist_for_each_entry_rcu(pctx, >p->tid_hash[i], hlist_tid) +- pdp_context_delete(pctx); +- +- synchronize_rcu(); +- kfree(gtp->addr_hash); +- kfree(gtp->tid_hash); +-} +- + static struct sock *gtp_encap_enable_socket(int fd, int type, + struct gtp_dev *gtp) + { +@@ -929,24 +931,31 @@ static void ipv4_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info) + } + } + +-static int ipv4_pdp_add(struct gtp_dev *gtp, struct sock *sk, +- struct genl_info *info) ++static int gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk, ++ struct genl_info *info) + { ++ struct pdp_ctx *pctx, *pctx_tid = NULL; + struct net_device *dev = gtp->dev; + u32 hash_ms, hash_tid = 0; +- struct pdp_ctx *pctx; ++ unsigned int version; + bool found = false; + __be32 ms_addr; + + ms_addr = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]); + hash_ms = ipv4_hashfn(ms_addr) % gtp->hash_size; ++ version = nla_get_u32(info->attrs[GTPA_VERSION]); + +- hlist_for_each_entry_rcu(pctx, >p->addr_hash[hash_ms], hlist_addr) { +- if (pctx->ms_addr_ip4.s_addr == ms_addr) { +- found = true; +- break; +- } +- } ++ pctx = ipv4_pdp_find(gtp, ms_addr); ++ if (pctx) ++ found = true; ++ if (version == GTP_V0) ++ pctx_tid = gtp0_pdp_find(gtp, ++ nla_get_u64(info->attrs[GTPA_TID])); ++ else if (version == GTP_V1) ++ pctx_tid = gtp1_pdp_find(gtp, ++ nla_get_u32(info->attrs[GTPA_I_TEI])); ++ if (pctx_tid) ++ found = true; + + if (found) { + if (info->nlhdr->nlmsg_flags & NLM_F_EXCL) +@@ -954,6 +963,11 @@ static int ipv4_pdp_add(struct gtp_dev *gtp, struct sock *sk, + if (info->nlhdr->nlmsg_flags & NLM_F_REPLACE) + return -EOPNOTSUPP; + ++ if (pctx && pctx_tid) ++ return -EEXIST; ++ if (!pctx) ++ pctx = pctx_tid; ++ + ipv4_pdp_fill(pctx, info); + + if (pctx->gtp_version == GTP_V0) +@@ -1077,7 +1091,7 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info) + goto out_unlock; + } + +- err = ipv4_pdp_add(gtp, sk, info); ++ err = gtp_pdp_add(gtp, sk, info); + + out_unlock: + rcu_read_unlock(); +@@ -1235,43 +1249,46 @@ static int gtp_genl_dump_pdp(struct sk_buff *skb, + struct netlink_callback *cb) + { + struct gtp_dev *last_gtp = (struct gtp_dev *)cb->args[2], *gtp; ++ int i, j, bucket = cb->args[0], skip = cb->args[1]; + struct net *net = sock_net(skb->sk); +- struct gtp_net *gn = net_generic(net, gtp_net_id); +- unsigned long tid = cb->args[1]; +- int i, k = cb->args[0], ret; + struct pdp_ctx *pctx; ++ struct gtp_net *gn; ++ ++ gn = net_generic(net, gtp_net_id); + + if (cb->args[4]) + return 0; + ++ rcu_read_lock(); + list_for_each_entry_rcu(gtp, &gn->gtp_dev_list, list) { + if (last_gtp && last_gtp != gtp) + continue; + else + last_gtp = NULL; + +- for (i = k; i < gtp->hash_size; i++) { +- hlist_for_each_entry_rcu(pctx, >p->tid_hash[i], hlist_tid) { +- if (tid && tid != pctx->u.tid) +- continue; +- else +- tid = 0; +- +- ret = gtp_genl_fill_info(skb, +- NETLINK_CB(cb->skb).portid, +- cb->nlh->nlmsg_seq, +- cb->nlh->nlmsg_type, pctx); +- if (ret < 0) { ++ for (i = bucket; i < gtp->hash_size; i++) { ++ j = 0; ++ hlist_for_each_entry_rcu(pctx, >p->tid_hash[i], ++ hlist_tid) { ++ if (j >= skip && ++ gtp_genl_fill_info(skb, ++ NETLINK_CB(cb->skb).portid, ++ cb->nlh->nlmsg_seq, ++ cb->nlh->nlmsg_type, pctx)) { + cb->args[0] = i; +- cb->args[1] = pctx->u.tid; ++ cb->args[1] = j; + cb->args[2] = (unsigned long)gtp; + goto out; + } ++ j++; + } ++ skip = 0; + } ++ bucket = 0; + } + cb->args[4] = 1; + out: ++ rcu_read_unlock(); + return skb->len; + } + +diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c +index 021a8ec411ab..6d4742d10a78 100644 +--- a/drivers/net/hamradio/6pack.c ++++ b/drivers/net/hamradio/6pack.c +@@ -665,10 +665,10 @@ static void sixpack_close(struct tty_struct *tty) + { + struct sixpack *sp; + +- write_lock_bh(&disc_data_lock); ++ write_lock_irq(&disc_data_lock); + sp = tty->disc_data; + tty->disc_data = NULL; +- write_unlock_bh(&disc_data_lock); ++ write_unlock_irq(&disc_data_lock); + if (!sp) + return; + +diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c +index aec6c26563cf..9fd7dab42a53 100644 +--- a/drivers/net/hamradio/mkiss.c ++++ b/drivers/net/hamradio/mkiss.c +@@ -783,10 +783,10 @@ static void mkiss_close(struct tty_struct *tty) + { + struct mkiss *ax; + +- write_lock_bh(&disc_data_lock); ++ write_lock_irq(&disc_data_lock); + ax = tty->disc_data; + tty->disc_data = NULL; +- write_unlock_bh(&disc_data_lock); ++ write_unlock_irq(&disc_data_lock); + + if (!ax) + return; +diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c +index b2feda35966b..471498469d0a 100644 +--- a/drivers/nvdimm/btt.c ++++ b/drivers/nvdimm/btt.c +@@ -1259,11 +1259,11 @@ static int btt_read_pg(struct btt *btt, struct bio_integrity_payload *bip, + + ret = btt_data_read(arena, page, off, postmap, cur_len); + if (ret) { +- int rc; +- + /* Media error - set the e_flag */ +- rc = btt_map_write(arena, premap, postmap, 0, 1, +- NVDIMM_IO_ATOMIC); ++ if (btt_map_write(arena, premap, postmap, 0, 1, NVDIMM_IO_ATOMIC)) ++ dev_warn_ratelimited(to_dev(arena), ++ "Error persistently tracking bad blocks at %#x\n", ++ premap); + goto out_rtt; + } + +diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c +index beeb7cbb5015..9df5d29d708d 100644 +--- a/drivers/pinctrl/intel/pinctrl-baytrail.c ++++ b/drivers/pinctrl/intel/pinctrl-baytrail.c +@@ -204,7 +204,6 @@ struct byt_gpio { + struct platform_device *pdev; + struct pinctrl_dev *pctl_dev; + struct pinctrl_desc pctl_desc; +- raw_spinlock_t lock; + const struct byt_pinctrl_soc_data *soc_data; + struct byt_community *communities_copy; + struct byt_gpio_pin_context *saved_context; +@@ -715,6 +714,8 @@ static const struct byt_pinctrl_soc_data *byt_soc_data[] = { + NULL, + }; + ++static DEFINE_RAW_SPINLOCK(byt_lock); ++ + static struct byt_community *byt_get_community(struct byt_gpio *vg, + unsigned int pin) + { +@@ -856,7 +857,7 @@ static void byt_set_group_simple_mux(struct byt_gpio *vg, + unsigned long flags; + int i; + +- raw_spin_lock_irqsave(&vg->lock, flags); ++ raw_spin_lock_irqsave(&byt_lock, flags); + + for (i = 0; i < group.npins; i++) { + void __iomem *padcfg0; +@@ -876,7 +877,7 @@ static void byt_set_group_simple_mux(struct byt_gpio *vg, + writel(value, padcfg0); + } + +- raw_spin_unlock_irqrestore(&vg->lock, flags); ++ raw_spin_unlock_irqrestore(&byt_lock, flags); + } + + static void byt_set_group_mixed_mux(struct byt_gpio *vg, +@@ -886,7 +887,7 @@ static void byt_set_group_mixed_mux(struct byt_gpio *vg, + unsigned long flags; + int i; + +- raw_spin_lock_irqsave(&vg->lock, flags); ++ raw_spin_lock_irqsave(&byt_lock, flags); + + for (i = 0; i < group.npins; i++) { + void __iomem *padcfg0; +@@ -906,7 +907,7 @@ static void byt_set_group_mixed_mux(struct byt_gpio *vg, + writel(value, padcfg0); + } + +- raw_spin_unlock_irqrestore(&vg->lock, flags); ++ raw_spin_unlock_irqrestore(&byt_lock, flags); + } + + static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector, +@@ -955,11 +956,11 @@ static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned int offset) + unsigned long flags; + u32 value; + +- raw_spin_lock_irqsave(&vg->lock, flags); ++ raw_spin_lock_irqsave(&byt_lock, flags); + value = readl(reg); + value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL); + writel(value, reg); +- raw_spin_unlock_irqrestore(&vg->lock, flags); ++ raw_spin_unlock_irqrestore(&byt_lock, flags); + } + + static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev, +@@ -971,7 +972,7 @@ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev, + u32 value, gpio_mux; + unsigned long flags; + +- raw_spin_lock_irqsave(&vg->lock, flags); ++ raw_spin_lock_irqsave(&byt_lock, flags); + + /* + * In most cases, func pin mux 000 means GPIO function. +@@ -993,7 +994,7 @@ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev, + "pin %u forcibly re-configured as GPIO\n", offset); + } + +- raw_spin_unlock_irqrestore(&vg->lock, flags); ++ raw_spin_unlock_irqrestore(&byt_lock, flags); + + pm_runtime_get(&vg->pdev->dev); + +@@ -1021,7 +1022,7 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev, + unsigned long flags; + u32 value; + +- raw_spin_lock_irqsave(&vg->lock, flags); ++ raw_spin_lock_irqsave(&byt_lock, flags); + + value = readl(val_reg); + value &= ~BYT_DIR_MASK; +@@ -1038,7 +1039,7 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev, + "Potential Error: Setting GPIO with direct_irq_en to output"); + writel(value, val_reg); + +- raw_spin_unlock_irqrestore(&vg->lock, flags); ++ raw_spin_unlock_irqrestore(&byt_lock, flags); + + return 0; + } +@@ -1107,11 +1108,11 @@ static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset, + u32 conf, pull, val, debounce; + u16 arg = 0; + +- raw_spin_lock_irqsave(&vg->lock, flags); ++ raw_spin_lock_irqsave(&byt_lock, flags); + conf = readl(conf_reg); + pull = conf & BYT_PULL_ASSIGN_MASK; + val = readl(val_reg); +- raw_spin_unlock_irqrestore(&vg->lock, flags); ++ raw_spin_unlock_irqrestore(&byt_lock, flags); + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: +@@ -1138,9 +1139,9 @@ static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset, + if (!(conf & BYT_DEBOUNCE_EN)) + return -EINVAL; + +- raw_spin_lock_irqsave(&vg->lock, flags); ++ raw_spin_lock_irqsave(&byt_lock, flags); + debounce = readl(db_reg); +- raw_spin_unlock_irqrestore(&vg->lock, flags); ++ raw_spin_unlock_irqrestore(&byt_lock, flags); + + switch (debounce & BYT_DEBOUNCE_PULSE_MASK) { + case BYT_DEBOUNCE_PULSE_375US: +@@ -1192,7 +1193,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev, + u32 conf, val, debounce; + int i, ret = 0; + +- raw_spin_lock_irqsave(&vg->lock, flags); ++ raw_spin_lock_irqsave(&byt_lock, flags); + + conf = readl(conf_reg); + val = readl(val_reg); +@@ -1300,7 +1301,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev, + if (!ret) + writel(conf, conf_reg); + +- raw_spin_unlock_irqrestore(&vg->lock, flags); ++ raw_spin_unlock_irqrestore(&byt_lock, flags); + + return ret; + } +@@ -1325,9 +1326,9 @@ static int byt_gpio_get(struct gpio_chip *chip, unsigned offset) + unsigned long flags; + u32 val; + +- raw_spin_lock_irqsave(&vg->lock, flags); ++ raw_spin_lock_irqsave(&byt_lock, flags); + val = readl(reg); +- raw_spin_unlock_irqrestore(&vg->lock, flags); ++ raw_spin_unlock_irqrestore(&byt_lock, flags); + + return !!(val & BYT_LEVEL); + } +@@ -1342,13 +1343,13 @@ static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value) + if (!reg) + return; + +- raw_spin_lock_irqsave(&vg->lock, flags); ++ raw_spin_lock_irqsave(&byt_lock, flags); + old_val = readl(reg); + if (value) + writel(old_val | BYT_LEVEL, reg); + else + writel(old_val & ~BYT_LEVEL, reg); +- raw_spin_unlock_irqrestore(&vg->lock, flags); ++ raw_spin_unlock_irqrestore(&byt_lock, flags); + } + + static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) +@@ -1361,9 +1362,9 @@ static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) + if (!reg) + return -EINVAL; + +- raw_spin_lock_irqsave(&vg->lock, flags); ++ raw_spin_lock_irqsave(&byt_lock, flags); + value = readl(reg); +- raw_spin_unlock_irqrestore(&vg->lock, flags); ++ raw_spin_unlock_irqrestore(&byt_lock, flags); + + if (!(value & BYT_OUTPUT_EN)) + return GPIOF_DIR_OUT; +@@ -1406,14 +1407,14 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) + const char *label; + unsigned int pin; + +- raw_spin_lock_irqsave(&vg->lock, flags); ++ raw_spin_lock_irqsave(&byt_lock, flags); + pin = vg->soc_data->pins[i].number; + reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG); + if (!reg) { + seq_printf(s, + "Could not retrieve pin %i conf0 reg\n", + pin); +- raw_spin_unlock_irqrestore(&vg->lock, flags); ++ raw_spin_unlock_irqrestore(&byt_lock, flags); + continue; + } + conf0 = readl(reg); +@@ -1422,11 +1423,11 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) + if (!reg) { + seq_printf(s, + "Could not retrieve pin %i val reg\n", pin); +- raw_spin_unlock_irqrestore(&vg->lock, flags); ++ raw_spin_unlock_irqrestore(&byt_lock, flags); + continue; + } + val = readl(reg); +- raw_spin_unlock_irqrestore(&vg->lock, flags); ++ raw_spin_unlock_irqrestore(&byt_lock, flags); + + comm = byt_get_community(vg, pin); + if (!comm) { +@@ -1510,9 +1511,9 @@ static void byt_irq_ack(struct irq_data *d) + if (!reg) + return; + +- raw_spin_lock(&vg->lock); ++ raw_spin_lock(&byt_lock); + writel(BIT(offset % 32), reg); +- raw_spin_unlock(&vg->lock); ++ raw_spin_unlock(&byt_lock); + } + + static void byt_irq_mask(struct irq_data *d) +@@ -1536,7 +1537,7 @@ static void byt_irq_unmask(struct irq_data *d) + if (!reg) + return; + +- raw_spin_lock_irqsave(&vg->lock, flags); ++ raw_spin_lock_irqsave(&byt_lock, flags); + value = readl(reg); + + switch (irqd_get_trigger_type(d)) { +@@ -1557,7 +1558,7 @@ static void byt_irq_unmask(struct irq_data *d) + + writel(value, reg); + +- raw_spin_unlock_irqrestore(&vg->lock, flags); ++ raw_spin_unlock_irqrestore(&byt_lock, flags); + } + + static int byt_irq_type(struct irq_data *d, unsigned int type) +@@ -1571,7 +1572,7 @@ static int byt_irq_type(struct irq_data *d, unsigned int type) + if (!reg || offset >= vg->chip.ngpio) + return -EINVAL; + +- raw_spin_lock_irqsave(&vg->lock, flags); ++ raw_spin_lock_irqsave(&byt_lock, flags); + value = readl(reg); + + WARN(value & BYT_DIRECT_IRQ_EN, +@@ -1593,7 +1594,7 @@ static int byt_irq_type(struct irq_data *d, unsigned int type) + else if (type & IRQ_TYPE_LEVEL_MASK) + irq_set_handler_locked(d, handle_level_irq); + +- raw_spin_unlock_irqrestore(&vg->lock, flags); ++ raw_spin_unlock_irqrestore(&byt_lock, flags); + + return 0; + } +@@ -1629,9 +1630,9 @@ static void byt_gpio_irq_handler(struct irq_desc *desc) + continue; + } + +- raw_spin_lock(&vg->lock); ++ raw_spin_lock(&byt_lock); + pending = readl(reg); +- raw_spin_unlock(&vg->lock); ++ raw_spin_unlock(&byt_lock); + for_each_set_bit(pin, &pending, 32) { + virq = irq_find_mapping(vg->chip.irqdomain, base + pin); + generic_handle_irq(virq); +@@ -1833,8 +1834,6 @@ static int byt_pinctrl_probe(struct platform_device *pdev) + return PTR_ERR(vg->pctl_dev); + } + +- raw_spin_lock_init(&vg->lock); +- + ret = byt_gpio_probe(vg); + if (ret) + return ret; +@@ -1850,8 +1849,11 @@ static int byt_gpio_suspend(struct device *dev) + { + struct platform_device *pdev = to_platform_device(dev); + struct byt_gpio *vg = platform_get_drvdata(pdev); ++ unsigned long flags; + int i; + ++ raw_spin_lock_irqsave(&byt_lock, flags); ++ + for (i = 0; i < vg->soc_data->npins; i++) { + void __iomem *reg; + u32 value; +@@ -1872,6 +1874,7 @@ static int byt_gpio_suspend(struct device *dev) + vg->saved_context[i].val = value; + } + ++ raw_spin_unlock_irqrestore(&byt_lock, flags); + return 0; + } + +@@ -1879,8 +1882,11 @@ static int byt_gpio_resume(struct device *dev) + { + struct platform_device *pdev = to_platform_device(dev); + struct byt_gpio *vg = platform_get_drvdata(pdev); ++ unsigned long flags; + int i; + ++ raw_spin_lock_irqsave(&byt_lock, flags); ++ + for (i = 0; i < vg->soc_data->npins; i++) { + void __iomem *reg; + u32 value; +@@ -1918,6 +1924,7 @@ static int byt_gpio_resume(struct device *dev) + } + } + ++ raw_spin_unlock_irqrestore(&byt_lock, flags); + return 0; + } + #endif +diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c +index c64903a5978f..b818f65480c1 100644 +--- a/drivers/ptp/ptp_clock.c ++++ b/drivers/ptp/ptp_clock.c +@@ -175,9 +175,9 @@ static struct posix_clock_operations ptp_clock_ops = { + .read = ptp_read, + }; + +-static void delete_ptp_clock(struct posix_clock *pc) ++static void ptp_clock_release(struct device *dev) + { +- struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock); ++ struct ptp_clock *ptp = container_of(dev, struct ptp_clock, dev); + + mutex_destroy(&ptp->tsevq_mux); + mutex_destroy(&ptp->pincfg_mux); +@@ -222,7 +222,6 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info, + } + + ptp->clock.ops = ptp_clock_ops; +- ptp->clock.release = delete_ptp_clock; + ptp->info = info; + ptp->devid = MKDEV(major, index); + ptp->index = index; +@@ -249,15 +248,6 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info, + if (err) + goto no_pin_groups; + +- /* Create a new device in our class. */ +- ptp->dev = device_create_with_groups(ptp_class, parent, ptp->devid, +- ptp, ptp->pin_attr_groups, +- "ptp%d", ptp->index); +- if (IS_ERR(ptp->dev)) { +- err = PTR_ERR(ptp->dev); +- goto no_device; +- } +- + /* Register a new PPS source. */ + if (info->pps) { + struct pps_source_info pps; +@@ -273,8 +263,18 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info, + } + } + +- /* Create a posix clock. */ +- err = posix_clock_register(&ptp->clock, ptp->devid); ++ /* Initialize a new device of our class in our clock structure. */ ++ device_initialize(&ptp->dev); ++ ptp->dev.devt = ptp->devid; ++ ptp->dev.class = ptp_class; ++ ptp->dev.parent = parent; ++ ptp->dev.groups = ptp->pin_attr_groups; ++ ptp->dev.release = ptp_clock_release; ++ dev_set_drvdata(&ptp->dev, ptp); ++ dev_set_name(&ptp->dev, "ptp%d", ptp->index); ++ ++ /* Create a posix clock and link it to the device. */ ++ err = posix_clock_register(&ptp->clock, &ptp->dev); + if (err) { + pr_err("failed to create posix clock\n"); + goto no_clock; +@@ -286,8 +286,6 @@ no_clock: + if (ptp->pps_source) + pps_unregister_source(ptp->pps_source); + no_pps: +- device_destroy(ptp_class, ptp->devid); +-no_device: + ptp_cleanup_pin_groups(ptp); + no_pin_groups: + if (ptp->kworker) +@@ -317,7 +315,6 @@ int ptp_clock_unregister(struct ptp_clock *ptp) + if (ptp->pps_source) + pps_unregister_source(ptp->pps_source); + +- device_destroy(ptp_class, ptp->devid); + ptp_cleanup_pin_groups(ptp); + + posix_clock_unregister(&ptp->clock); +diff --git a/drivers/ptp/ptp_private.h b/drivers/ptp/ptp_private.h +index b86f1bfecd6f..45ed9e172bb4 100644 +--- a/drivers/ptp/ptp_private.h ++++ b/drivers/ptp/ptp_private.h +@@ -41,7 +41,7 @@ struct timestamp_event_queue { + + struct ptp_clock { + struct posix_clock clock; +- struct device *dev; ++ struct device dev; + struct ptp_clock_info *info; + dev_t devid; + int index; /* index into clocks.map */ +diff --git a/drivers/s390/crypto/zcrypt_error.h b/drivers/s390/crypto/zcrypt_error.h +index 9499cd3a05f8..02a936db0092 100644 +--- a/drivers/s390/crypto/zcrypt_error.h ++++ b/drivers/s390/crypto/zcrypt_error.h +@@ -75,6 +75,7 @@ struct error_hdr { + #define REP82_ERROR_EVEN_MOD_IN_OPND 0x85 + #define REP82_ERROR_RESERVED_FIELD 0x88 + #define REP82_ERROR_INVALID_DOMAIN_PENDING 0x8A ++#define REP82_ERROR_FILTERED_BY_HYPERVISOR 0x8B + #define REP82_ERROR_TRANSPORT_FAIL 0x90 + #define REP82_ERROR_PACKET_TRUNCATED 0xA0 + #define REP82_ERROR_ZERO_BUFFER_LEN 0xB0 +@@ -105,6 +106,7 @@ static inline int convert_error(struct zcrypt_queue *zq, + case REP82_ERROR_INVALID_DOMAIN_PRECHECK: + case REP82_ERROR_INVALID_DOMAIN_PENDING: + case REP82_ERROR_INVALID_SPECIAL_CMD: ++ case REP82_ERROR_FILTERED_BY_HYPERVISOR: + // REP88_ERROR_INVALID_KEY // '82' CEX2A + // REP88_ERROR_OPERAND // '84' CEX2A + // REP88_ERROR_OPERAND_EVEN_MOD // '85' CEX2A +diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c +index 21377ac71168..79b0b4eece19 100644 +--- a/drivers/scsi/NCR5380.c ++++ b/drivers/scsi/NCR5380.c +@@ -129,6 +129,9 @@ + #define NCR5380_release_dma_irq(x) + #endif + ++static unsigned int disconnect_mask = ~0; ++module_param(disconnect_mask, int, 0444); ++ + static int do_abort(struct Scsi_Host *); + static void do_reset(struct Scsi_Host *); + static void bus_reset_cleanup(struct Scsi_Host *); +@@ -946,7 +949,8 @@ static bool NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) + int err; + bool ret = true; + bool can_disconnect = instance->irq != NO_IRQ && +- cmd->cmnd[0] != REQUEST_SENSE; ++ cmd->cmnd[0] != REQUEST_SENSE && ++ (disconnect_mask & BIT(scmd_id(cmd))); + + NCR5380_dprint(NDEBUG_ARBITRATION, instance); + dsprintk(NDEBUG_ARBITRATION, instance, "starting arbitration, id = %d\n", +diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c +index 89f5154c40b6..764c46d7333e 100644 +--- a/drivers/scsi/atari_scsi.c ++++ b/drivers/scsi/atari_scsi.c +@@ -742,7 +742,7 @@ static int __init atari_scsi_probe(struct platform_device *pdev) + atari_scsi_template.sg_tablesize = SG_ALL; + } else { + atari_scsi_template.can_queue = 1; +- atari_scsi_template.sg_tablesize = SG_NONE; ++ atari_scsi_template.sg_tablesize = 1; + } + + if (setup_can_queue > 0) +@@ -751,8 +751,8 @@ static int __init atari_scsi_probe(struct platform_device *pdev) + if (setup_cmd_per_lun > 0) + atari_scsi_template.cmd_per_lun = setup_cmd_per_lun; + +- /* Leave sg_tablesize at 0 on a Falcon! */ +- if (ATARIHW_PRESENT(TT_SCSI) && setup_sg_tablesize >= 0) ++ /* Don't increase sg_tablesize on Falcon! */ ++ if (ATARIHW_PRESENT(TT_SCSI) && setup_sg_tablesize > 0) + atari_scsi_template.sg_tablesize = setup_sg_tablesize; + + if (setup_hostid >= 0) { +diff --git a/drivers/scsi/csiostor/csio_lnode.c b/drivers/scsi/csiostor/csio_lnode.c +index be5ee2d37815..957767d38361 100644 +--- a/drivers/scsi/csiostor/csio_lnode.c ++++ b/drivers/scsi/csiostor/csio_lnode.c +@@ -301,6 +301,7 @@ csio_ln_fdmi_rhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req) + struct fc_fdmi_port_name *port_name; + uint8_t buf[64]; + uint8_t *fc4_type; ++ unsigned long flags; + + if (fdmi_req->wr_status != FW_SUCCESS) { + csio_ln_dbg(ln, "WR error:%x in processing fdmi rhba cmd\n", +@@ -377,13 +378,13 @@ csio_ln_fdmi_rhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req) + len = (uint32_t)(pld - (uint8_t *)cmd); + + /* Submit FDMI RPA request */ +- spin_lock_irq(&hw->lock); ++ spin_lock_irqsave(&hw->lock, flags); + if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_done, + FCOE_CT, &fdmi_req->dma_buf, len)) { + CSIO_INC_STATS(ln, n_fdmi_err); + csio_ln_dbg(ln, "Failed to issue fdmi rpa req\n"); + } +- spin_unlock_irq(&hw->lock); ++ spin_unlock_irqrestore(&hw->lock, flags); + } + + /* +@@ -404,6 +405,7 @@ csio_ln_fdmi_dprt_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req) + struct fc_fdmi_rpl *reg_pl; + struct fs_fdmi_attrs *attrib_blk; + uint8_t buf[64]; ++ unsigned long flags; + + if (fdmi_req->wr_status != FW_SUCCESS) { + csio_ln_dbg(ln, "WR error:%x in processing fdmi dprt cmd\n", +@@ -483,13 +485,13 @@ csio_ln_fdmi_dprt_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req) + attrib_blk->numattrs = htonl(numattrs); + + /* Submit FDMI RHBA request */ +- spin_lock_irq(&hw->lock); ++ spin_lock_irqsave(&hw->lock, flags); + if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_rhba_cbfn, + FCOE_CT, &fdmi_req->dma_buf, len)) { + CSIO_INC_STATS(ln, n_fdmi_err); + csio_ln_dbg(ln, "Failed to issue fdmi rhba req\n"); + } +- spin_unlock_irq(&hw->lock); ++ spin_unlock_irqrestore(&hw->lock, flags); + } + + /* +@@ -504,6 +506,7 @@ csio_ln_fdmi_dhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req) + void *cmd; + struct fc_fdmi_port_name *port_name; + uint32_t len; ++ unsigned long flags; + + if (fdmi_req->wr_status != FW_SUCCESS) { + csio_ln_dbg(ln, "WR error:%x in processing fdmi dhba cmd\n", +@@ -534,13 +537,13 @@ csio_ln_fdmi_dhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req) + len += sizeof(*port_name); + + /* Submit FDMI request */ +- spin_lock_irq(&hw->lock); ++ spin_lock_irqsave(&hw->lock, flags); + if (csio_ln_mgmt_submit_req(fdmi_req, csio_ln_fdmi_dprt_cbfn, + FCOE_CT, &fdmi_req->dma_buf, len)) { + CSIO_INC_STATS(ln, n_fdmi_err); + csio_ln_dbg(ln, "Failed to issue fdmi dprt req\n"); + } +- spin_unlock_irq(&hw->lock); ++ spin_unlock_irqrestore(&hw->lock, flags); + } + + /** +diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c +index 045207b5560e..7e3a77d3c6f0 100644 +--- a/drivers/scsi/iscsi_tcp.c ++++ b/drivers/scsi/iscsi_tcp.c +@@ -372,8 +372,16 @@ static int iscsi_sw_tcp_pdu_xmit(struct iscsi_task *task) + { + struct iscsi_conn *conn = task->conn; + unsigned int noreclaim_flag; ++ struct iscsi_tcp_conn *tcp_conn = conn->dd_data; ++ struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data; + int rc = 0; + ++ if (!tcp_sw_conn->sock) { ++ iscsi_conn_printk(KERN_ERR, conn, ++ "Transport not bound to socket!\n"); ++ return -EINVAL; ++ } ++ + noreclaim_flag = memalloc_noreclaim_save(); + + while (iscsi_sw_tcp_xmit_qlen(conn)) { +diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c +index c851fd14ff3e..4c84c2ae1112 100644 +--- a/drivers/scsi/lpfc/lpfc_els.c ++++ b/drivers/scsi/lpfc/lpfc_els.c +@@ -4102,7 +4102,7 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, + mempool_free(mbox, phba->mbox_mem_pool); + } + out: +- if (ndlp && NLP_CHK_NODE_ACT(ndlp)) { ++ if (ndlp && NLP_CHK_NODE_ACT(ndlp) && shost) { + spin_lock_irq(shost->host_lock); + ndlp->nlp_flag &= ~(NLP_ACC_REGLOGIN | NLP_RM_DFLT_RPI); + spin_unlock_irq(shost->host_lock); +diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c +index 3f88f3d79622..4a0889dd4c1d 100644 +--- a/drivers/scsi/lpfc/lpfc_hbadisc.c ++++ b/drivers/scsi/lpfc/lpfc_hbadisc.c +@@ -5220,9 +5220,14 @@ lpfc_setup_disc_node(struct lpfc_vport *vport, uint32_t did) + /* If we've already received a PLOGI from this NPort + * we don't need to try to discover it again. + */ +- if (ndlp->nlp_flag & NLP_RCV_PLOGI) ++ if (ndlp->nlp_flag & NLP_RCV_PLOGI && ++ !(ndlp->nlp_type & ++ (NLP_FCP_TARGET | NLP_NVME_TARGET))) + return NULL; + ++ ndlp->nlp_prev_state = ndlp->nlp_state; ++ lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); ++ + spin_lock_irq(shost->host_lock); + ndlp->nlp_flag |= NLP_NPR_2B_DISC; + spin_unlock_irq(shost->host_lock); +diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c +index 043bca6449cd..96411754aa43 100644 +--- a/drivers/scsi/lpfc/lpfc_nportdisc.c ++++ b/drivers/scsi/lpfc/lpfc_nportdisc.c +@@ -483,8 +483,10 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, + * single discovery thread, this will cause a huge delay in + * discovery. Also this will cause multiple state machines + * running in parallel for this node. ++ * This only applies to a fabric environment. + */ +- if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) { ++ if ((ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) && ++ (vport->fc_flag & FC_FABRIC)) { + /* software abort outstanding PLOGI */ + lpfc_els_abort(phba, ndlp); + } +diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c +index d3bad0dbfaf7..d8e0ba68879c 100644 +--- a/drivers/scsi/lpfc/lpfc_sli.c ++++ b/drivers/scsi/lpfc/lpfc_sli.c +@@ -12689,13 +12689,19 @@ send_current_mbox: + phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE; + /* Setting active mailbox pointer need to be in sync to flag clear */ + phba->sli.mbox_active = NULL; ++ if (bf_get(lpfc_trailer_consumed, mcqe)) ++ lpfc_sli4_mq_release(phba->sli4_hba.mbx_wq); + spin_unlock_irqrestore(&phba->hbalock, iflags); + /* Wake up worker thread to post the next pending mailbox command */ + lpfc_worker_wake_up(phba); ++ return workposted; ++ + out_no_mqe_complete: ++ spin_lock_irqsave(&phba->hbalock, iflags); + if (bf_get(lpfc_trailer_consumed, mcqe)) + lpfc_sli4_mq_release(phba->sli4_hba.mbx_wq); +- return workposted; ++ spin_unlock_irqrestore(&phba->hbalock, iflags); ++ return false; + } + + /** +@@ -17486,6 +17492,13 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) + static void + __lpfc_sli4_free_rpi(struct lpfc_hba *phba, int rpi) + { ++ /* ++ * if the rpi value indicates a prior unreg has already ++ * been done, skip the unreg. ++ */ ++ if (rpi == LPFC_RPI_ALLOC_ERROR) ++ return; ++ + if (test_and_clear_bit(rpi, phba->sli4_hba.rpi_bmask)) { + phba->sli4_hba.rpi_count--; + phba->sli4_hba.max_cfg_param.rpi_used--; +diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c +index 643321fc152d..b5050c2ede00 100644 +--- a/drivers/scsi/mac_scsi.c ++++ b/drivers/scsi/mac_scsi.c +@@ -429,7 +429,7 @@ static int __init mac_scsi_probe(struct platform_device *pdev) + mac_scsi_template.can_queue = setup_can_queue; + if (setup_cmd_per_lun > 0) + mac_scsi_template.cmd_per_lun = setup_cmd_per_lun; +- if (setup_sg_tablesize >= 0) ++ if (setup_sg_tablesize > 0) + mac_scsi_template.sg_tablesize = setup_sg_tablesize; + if (setup_hostid >= 0) + mac_scsi_template.this_id = setup_hostid & 7; +diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c +index bdffb692bded..622dcf2984a9 100644 +--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c ++++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c +@@ -1502,7 +1502,8 @@ _ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc, + " for diag buffers, requested size(%d)\n", + ioc->name, __func__, request_data_sz); + mpt3sas_base_free_smid(ioc, smid); +- return -ENOMEM; ++ rc = -ENOMEM; ++ goto out; + } + ioc->diag_buffer[buffer_type] = request_data; + ioc->diag_buffer_sz[buffer_type] = request_data_sz; +diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c +index 9edd61c063a1..df5f0bc29587 100644 +--- a/drivers/scsi/pm8001/pm80xx_hwi.c ++++ b/drivers/scsi/pm8001/pm80xx_hwi.c +@@ -2368,6 +2368,8 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) + pm8001_printk("task 0x%p done with io_status 0x%x" + " resp 0x%x stat 0x%x but aborted by upper layer!\n", + t, status, ts->resp, ts->stat)); ++ if (t->slow_task) ++ complete(&t->slow_task->completion); + pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); + } else { + spin_unlock_irqrestore(&t->task_state_lock, flags); +diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c +index 92bc5b2d24ae..ac936b5ca74e 100644 +--- a/drivers/scsi/scsi_debug.c ++++ b/drivers/scsi/scsi_debug.c +@@ -4960,6 +4960,11 @@ static int __init scsi_debug_init(void) + return -EINVAL; + } + ++ if (sdebug_num_tgts < 0) { ++ pr_err("num_tgts must be >= 0\n"); ++ return -EINVAL; ++ } ++ + if (sdebug_guard > 1) { + pr_err("guard must be 0 or 1\n"); + return -EINVAL; +diff --git a/drivers/scsi/scsi_trace.c b/drivers/scsi/scsi_trace.c +index 0ff083bbf5b1..617a60737590 100644 +--- a/drivers/scsi/scsi_trace.c ++++ b/drivers/scsi/scsi_trace.c +@@ -30,15 +30,18 @@ static const char * + scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len) + { + const char *ret = trace_seq_buffer_ptr(p); +- sector_t lba = 0, txlen = 0; ++ u32 lba = 0, txlen; + + lba |= ((cdb[1] & 0x1F) << 16); + lba |= (cdb[2] << 8); + lba |= cdb[3]; +- txlen = cdb[4]; ++ /* ++ * From SBC-2: a TRANSFER LENGTH field set to zero specifies that 256 ++ * logical blocks shall be read (READ(6)) or written (WRITE(6)). ++ */ ++ txlen = cdb[4] ? cdb[4] : 256; + +- trace_seq_printf(p, "lba=%llu txlen=%llu", +- (unsigned long long)lba, (unsigned long long)txlen); ++ trace_seq_printf(p, "lba=%u txlen=%u", lba, txlen); + trace_seq_putc(p, 0); + + return ret; +diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c +index 9492638296c8..af8a7ef9c858 100644 +--- a/drivers/scsi/sun3_scsi.c ++++ b/drivers/scsi/sun3_scsi.c +@@ -498,7 +498,7 @@ static struct scsi_host_template sun3_scsi_template = { + .eh_host_reset_handler = sun3scsi_host_reset, + .can_queue = 16, + .this_id = 7, +- .sg_tablesize = SG_NONE, ++ .sg_tablesize = 1, + .cmd_per_lun = 2, + .use_clustering = DISABLE_CLUSTERING, + .cmd_size = NCR5380_CMD_SIZE, +@@ -520,7 +520,7 @@ static int __init sun3_scsi_probe(struct platform_device *pdev) + sun3_scsi_template.can_queue = setup_can_queue; + if (setup_cmd_per_lun > 0) + sun3_scsi_template.cmd_per_lun = setup_cmd_per_lun; +- if (setup_sg_tablesize >= 0) ++ if (setup_sg_tablesize > 0) + sun3_scsi_template.sg_tablesize = setup_sg_tablesize; + if (setup_hostid >= 0) + sun3_scsi_template.this_id = setup_hostid & 7; +diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c +index 07cae5ea608c..d25082e573e0 100644 +--- a/drivers/scsi/ufs/ufshcd.c ++++ b/drivers/scsi/ufs/ufshcd.c +@@ -2867,10 +2867,10 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba, + goto out_unlock; + } + +- hba->dev_cmd.query.descriptor = NULL; + *buf_len = be16_to_cpu(response->upiu_res.length); + + out_unlock: ++ hba->dev_cmd.query.descriptor = NULL; + mutex_unlock(&hba->dev_cmd.lock); + out: + ufshcd_release(hba); +@@ -3684,15 +3684,24 @@ static int __ufshcd_uic_hibern8_enter(struct ufs_hba *hba) + ktime_to_us(ktime_sub(ktime_get(), start)), ret); + + if (ret) { ++ int err; ++ + dev_err(hba->dev, "%s: hibern8 enter failed. ret = %d\n", + __func__, ret); + + /* +- * If link recovery fails then return error so that caller +- * don't retry the hibern8 enter again. ++ * If link recovery fails then return error code returned from ++ * ufshcd_link_recovery(). ++ * If link recovery succeeds then return -EAGAIN to attempt ++ * hibern8 enter retry again. + */ +- if (ufshcd_link_recovery(hba)) +- ret = -ENOLINK; ++ err = ufshcd_link_recovery(hba); ++ if (err) { ++ dev_err(hba->dev, "%s: link recovery failed", __func__); ++ ret = err; ++ } else { ++ ret = -EAGAIN; ++ } + } else + ufshcd_vops_hibern8_notify(hba, UIC_CMD_DME_HIBER_ENTER, + POST_CHANGE); +@@ -3706,7 +3715,7 @@ static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba) + + for (retries = UIC_HIBERN8_ENTER_RETRIES; retries > 0; retries--) { + ret = __ufshcd_uic_hibern8_enter(hba); +- if (!ret || ret == -ENOLINK) ++ if (!ret) + goto out; + } + out: +diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c +index 8f2e97857e8b..8b79e36fab21 100644 +--- a/drivers/spi/spi-fsl-spi.c ++++ b/drivers/spi/spi-fsl-spi.c +@@ -832,9 +832,9 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) + if (ret) + goto err; + +- irq = irq_of_parse_and_map(np, 0); +- if (!irq) { +- ret = -EINVAL; ++ irq = platform_get_irq(ofdev, 0); ++ if (irq < 0) { ++ ret = irq; + goto err; + } + +@@ -847,7 +847,6 @@ static int of_fsl_spi_probe(struct platform_device *ofdev) + return 0; + + err: +- irq_dispose_mapping(irq); + if (type == TYPE_FSL) + of_fsl_spi_free_chipselects(dev); + return ret; +diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c +index fb7bd422e2e1..21ce92ee1652 100644 +--- a/drivers/target/iscsi/iscsi_target.c ++++ b/drivers/target/iscsi/iscsi_target.c +@@ -1158,7 +1158,9 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, + hdr->cmdsn, be32_to_cpu(hdr->data_length), payload_length, + conn->cid); + +- target_get_sess_cmd(&cmd->se_cmd, true); ++ if (target_get_sess_cmd(&cmd->se_cmd, true) < 0) ++ return iscsit_add_reject_cmd(cmd, ++ ISCSI_REASON_WAITING_FOR_LOGOUT, buf); + + cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd, + scsilun_to_int(&hdr->lun)); +@@ -2004,7 +2006,9 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, + conn->sess->se_sess, 0, DMA_NONE, + TCM_SIMPLE_TAG, cmd->sense_buffer + 2); + +- target_get_sess_cmd(&cmd->se_cmd, true); ++ if (target_get_sess_cmd(&cmd->se_cmd, true) < 0) ++ return iscsit_add_reject_cmd(cmd, ++ ISCSI_REASON_WAITING_FOR_LOGOUT, buf); + + /* + * TASK_REASSIGN for ERL=2 / connection stays inside of +@@ -4236,6 +4240,8 @@ int iscsit_close_connection( + * must wait until they have completed. + */ + iscsit_check_conn_usage_count(conn); ++ target_sess_cmd_list_set_waiting(sess->se_sess); ++ target_wait_for_sess_cmds(sess->se_sess); + + ahash_request_free(conn->conn_tx_hash); + if (conn->conn_rx_hash) { +diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c +index e2fa3a3bc81d..b6bf605fa5c1 100644 +--- a/drivers/target/iscsi/iscsi_target_auth.c ++++ b/drivers/target/iscsi/iscsi_target_auth.c +@@ -78,7 +78,7 @@ static int chap_check_algorithm(const char *a_str) + if (!token) + goto out; + +- if (!strncmp(token, "5", 1)) { ++ if (!strcmp(token, "5")) { + pr_debug("Selected MD5 Algorithm\n"); + kfree(orig); + return CHAP_DIGEST_MD5; +diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c +index 9ee41ba0e55b..367ce812743e 100644 +--- a/drivers/tty/serial/atmel_serial.c ++++ b/drivers/tty/serial/atmel_serial.c +@@ -2183,27 +2183,6 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, + mode |= ATMEL_US_USMODE_NORMAL; + } + +- /* set the mode, clock divisor, parity, stop bits and data size */ +- atmel_uart_writel(port, ATMEL_US_MR, mode); +- +- /* +- * when switching the mode, set the RTS line state according to the +- * new mode, otherwise keep the former state +- */ +- if ((old_mode & ATMEL_US_USMODE) != (mode & ATMEL_US_USMODE)) { +- unsigned int rts_state; +- +- if ((mode & ATMEL_US_USMODE) == ATMEL_US_USMODE_HWHS) { +- /* let the hardware control the RTS line */ +- rts_state = ATMEL_US_RTSDIS; +- } else { +- /* force RTS line to low level */ +- rts_state = ATMEL_US_RTSEN; +- } +- +- atmel_uart_writel(port, ATMEL_US_CR, rts_state); +- } +- + /* + * Set the baud rate: + * Fractional baudrate allows to setup output frequency more +@@ -2229,6 +2208,28 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, + quot = cd | fp << ATMEL_US_FP_OFFSET; + + atmel_uart_writel(port, ATMEL_US_BRGR, quot); ++ ++ /* set the mode, clock divisor, parity, stop bits and data size */ ++ atmel_uart_writel(port, ATMEL_US_MR, mode); ++ ++ /* ++ * when switching the mode, set the RTS line state according to the ++ * new mode, otherwise keep the former state ++ */ ++ if ((old_mode & ATMEL_US_USMODE) != (mode & ATMEL_US_USMODE)) { ++ unsigned int rts_state; ++ ++ if ((mode & ATMEL_US_USMODE) == ATMEL_US_USMODE_HWHS) { ++ /* let the hardware control the RTS line */ ++ rts_state = ATMEL_US_RTSDIS; ++ } else { ++ /* force RTS line to low level */ ++ rts_state = ATMEL_US_RTSEN; ++ } ++ ++ atmel_uart_writel(port, ATMEL_US_CR, rts_state); ++ } ++ + atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); + atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN); + +diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c +index 491de830b8d9..6391dc5b0ebe 100644 +--- a/drivers/vhost/vsock.c ++++ b/drivers/vhost/vsock.c +@@ -436,7 +436,9 @@ static void vhost_vsock_handle_tx_kick(struct vhost_work *work) + virtio_transport_deliver_tap_pkt(pkt); + + /* Only accept correctly addressed packets */ +- if (le64_to_cpu(pkt->hdr.src_cid) == vsock->guest_cid) ++ if (le64_to_cpu(pkt->hdr.src_cid) == vsock->guest_cid && ++ le64_to_cpu(pkt->hdr.dst_cid) == ++ vhost_transport_get_local_cid()) + virtio_transport_recv_pkt(pkt); + else + virtio_transport_free_pkt(pkt); +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index c2920cbfa3bf..a91b8404d3dc 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -3796,7 +3796,13 @@ static ssize_t ext4_direct_IO_read(struct kiocb *iocb, struct iov_iter *iter) + * writes & truncates and since we take care of writing back page cache, + * we are protected against page writeback as well. + */ +- inode_lock_shared(inode); ++ if (iocb->ki_flags & IOCB_NOWAIT) { ++ if (!inode_trylock_shared(inode)) ++ return -EAGAIN; ++ } else { ++ inode_lock_shared(inode); ++ } ++ + ret = filemap_write_and_wait_range(mapping, iocb->ki_pos, + iocb->ki_pos + count - 1); + if (ret) +diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c +index b80e7db3b55b..b13383948fca 100644 +--- a/fs/f2fs/namei.c ++++ b/fs/f2fs/namei.c +@@ -862,7 +862,8 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, + if (!old_dir_entry || whiteout) + file_lost_pino(old_inode); + else +- F2FS_I(old_inode)->i_pino = new_dir->i_ino; ++ /* adjust dir's i_pino to pass fsck check */ ++ f2fs_i_pino_write(old_inode, new_dir->i_ino); + up_write(&F2FS_I(old_inode)->i_sem); + + old_inode->i_ctime = current_time(old_inode); +@@ -1027,7 +1028,11 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry, + f2fs_set_link(old_dir, old_entry, old_page, new_inode); + + down_write(&F2FS_I(old_inode)->i_sem); +- file_lost_pino(old_inode); ++ if (!old_dir_entry) ++ file_lost_pino(old_inode); ++ else ++ /* adjust dir's i_pino to pass fsck check */ ++ f2fs_i_pino_write(old_inode, new_dir->i_ino); + up_write(&F2FS_I(old_inode)->i_sem); + + old_dir->i_ctime = current_time(old_dir); +@@ -1042,7 +1047,11 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry, + f2fs_set_link(new_dir, new_entry, new_page, old_inode); + + down_write(&F2FS_I(new_inode)->i_sem); +- file_lost_pino(new_inode); ++ if (!new_dir_entry) ++ file_lost_pino(new_inode); ++ else ++ /* adjust dir's i_pino to pass fsck check */ ++ f2fs_i_pino_write(new_inode, old_dir->i_ino); + up_write(&F2FS_I(new_inode)->i_sem); + + new_dir->i_ctime = current_time(new_dir); +diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c +index 0567b17a970c..7dd613392592 100644 +--- a/fs/jbd2/commit.c ++++ b/fs/jbd2/commit.c +@@ -726,7 +726,6 @@ start_journal_io: + submit_bh(REQ_OP_WRITE, REQ_SYNC, bh); + } + cond_resched(); +- stats.run.rs_blocks_logged += bufs; + + /* Force a new descriptor to be generated next + time round the loop. */ +@@ -813,6 +812,7 @@ start_journal_io: + if (unlikely(!buffer_uptodate(bh))) + err = -EIO; + jbd2_unfile_log_bh(bh); ++ stats.run.rs_blocks_logged++; + + /* + * The list contains temporary buffer heads created by +@@ -858,6 +858,7 @@ start_journal_io: + BUFFER_TRACE(bh, "ph5: control buffer writeout done: unfile"); + clear_buffer_jwrite(bh); + jbd2_unfile_log_bh(bh); ++ stats.run.rs_blocks_logged++; + __brelse(bh); /* One for getblk */ + /* AKPM: bforget here */ + } +@@ -879,6 +880,7 @@ start_journal_io: + } + if (cbh) + err = journal_wait_on_commit_record(journal, cbh); ++ stats.run.rs_blocks_logged++; + if (jbd2_has_feature_async_commit(journal) && + journal->j_flags & JBD2_BARRIER) { + blkdev_issue_flush(journal->j_dev, GFP_NOFS, NULL); +diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c +index 917fadca8a7b..b73b78771915 100644 +--- a/fs/ocfs2/acl.c ++++ b/fs/ocfs2/acl.c +@@ -335,8 +335,8 @@ int ocfs2_acl_chmod(struct inode *inode, struct buffer_head *bh) + down_read(&OCFS2_I(inode)->ip_xattr_sem); + acl = ocfs2_get_acl_nolock(inode, ACL_TYPE_ACCESS, bh); + up_read(&OCFS2_I(inode)->ip_xattr_sem); +- if (IS_ERR(acl) || !acl) +- return PTR_ERR(acl); ++ if (IS_ERR_OR_NULL(acl)) ++ return PTR_ERR_OR_ZERO(acl); + ret = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode); + if (ret) + return ret; +diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c +index 3254c90fd899..3fdbdd29702b 100644 +--- a/fs/quota/dquot.c ++++ b/fs/quota/dquot.c +@@ -2849,68 +2849,73 @@ EXPORT_SYMBOL(dquot_quotactl_sysfile_ops); + static int do_proc_dqstats(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) + { +- unsigned int type = (int *)table->data - dqstats.stat; ++ unsigned int type = (unsigned long *)table->data - dqstats.stat; ++ s64 value = percpu_counter_sum(&dqstats.counter[type]); ++ ++ /* Filter negative values for non-monotonic counters */ ++ if (value < 0 && (type == DQST_ALLOC_DQUOTS || ++ type == DQST_FREE_DQUOTS)) ++ value = 0; + + /* Update global table */ +- dqstats.stat[type] = +- percpu_counter_sum_positive(&dqstats.counter[type]); +- return proc_dointvec(table, write, buffer, lenp, ppos); ++ dqstats.stat[type] = value; ++ return proc_doulongvec_minmax(table, write, buffer, lenp, ppos); + } + + static struct ctl_table fs_dqstats_table[] = { + { + .procname = "lookups", + .data = &dqstats.stat[DQST_LOOKUPS], +- .maxlen = sizeof(int), ++ .maxlen = sizeof(unsigned long), + .mode = 0444, + .proc_handler = do_proc_dqstats, + }, + { + .procname = "drops", + .data = &dqstats.stat[DQST_DROPS], +- .maxlen = sizeof(int), ++ .maxlen = sizeof(unsigned long), + .mode = 0444, + .proc_handler = do_proc_dqstats, + }, + { + .procname = "reads", + .data = &dqstats.stat[DQST_READS], +- .maxlen = sizeof(int), ++ .maxlen = sizeof(unsigned long), + .mode = 0444, + .proc_handler = do_proc_dqstats, + }, + { + .procname = "writes", + .data = &dqstats.stat[DQST_WRITES], +- .maxlen = sizeof(int), ++ .maxlen = sizeof(unsigned long), + .mode = 0444, + .proc_handler = do_proc_dqstats, + }, + { + .procname = "cache_hits", + .data = &dqstats.stat[DQST_CACHE_HITS], +- .maxlen = sizeof(int), ++ .maxlen = sizeof(unsigned long), + .mode = 0444, + .proc_handler = do_proc_dqstats, + }, + { + .procname = "allocated_dquots", + .data = &dqstats.stat[DQST_ALLOC_DQUOTS], +- .maxlen = sizeof(int), ++ .maxlen = sizeof(unsigned long), + .mode = 0444, + .proc_handler = do_proc_dqstats, + }, + { + .procname = "free_dquots", + .data = &dqstats.stat[DQST_FREE_DQUOTS], +- .maxlen = sizeof(int), ++ .maxlen = sizeof(unsigned long), + .mode = 0444, + .proc_handler = do_proc_dqstats, + }, + { + .procname = "syncs", + .data = &dqstats.stat[DQST_SYNCS], +- .maxlen = sizeof(int), ++ .maxlen = sizeof(unsigned long), + .mode = 0444, + .proc_handler = do_proc_dqstats, + }, +diff --git a/fs/readdir.c b/fs/readdir.c +index d336db65a33e..0c357663e33a 100644 +--- a/fs/readdir.c ++++ b/fs/readdir.c +@@ -65,6 +65,40 @@ out: + } + EXPORT_SYMBOL(iterate_dir); + ++/* ++ * POSIX says that a dirent name cannot contain NULL or a '/'. ++ * ++ * It's not 100% clear what we should really do in this case. ++ * The filesystem is clearly corrupted, but returning a hard ++ * error means that you now don't see any of the other names ++ * either, so that isn't a perfect alternative. ++ * ++ * And if you return an error, what error do you use? Several ++ * filesystems seem to have decided on EUCLEAN being the error ++ * code for EFSCORRUPTED, and that may be the error to use. Or ++ * just EIO, which is perhaps more obvious to users. ++ * ++ * In order to see the other file names in the directory, the ++ * caller might want to make this a "soft" error: skip the ++ * entry, and return the error at the end instead. ++ * ++ * Note that this should likely do a "memchr(name, 0, len)" ++ * check too, since that would be filesystem corruption as ++ * well. However, that case can't actually confuse user space, ++ * which has to do a strlen() on the name anyway to find the ++ * filename length, and the above "soft error" worry means ++ * that it's probably better left alone until we have that ++ * issue clarified. ++ */ ++static int verify_dirent_name(const char *name, int len) ++{ ++ if (!len) ++ return -EIO; ++ if (memchr(name, '/', len)) ++ return -EIO; ++ return 0; ++} ++ + /* + * Traditional linux readdir() handling.. + * +@@ -174,6 +208,9 @@ static int filldir(struct dir_context *ctx, const char *name, int namlen, + int reclen = ALIGN(offsetof(struct linux_dirent, d_name) + namlen + 2, + sizeof(long)); + ++ buf->error = verify_dirent_name(name, namlen); ++ if (unlikely(buf->error)) ++ return buf->error; + buf->error = -EINVAL; /* only used if we fail.. */ + if (reclen > buf->count) + return -EINVAL; +@@ -260,6 +297,9 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen, + int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1, + sizeof(u64)); + ++ buf->error = verify_dirent_name(name, namlen); ++ if (unlikely(buf->error)) ++ return buf->error; + buf->error = -EINVAL; /* only used if we fail.. */ + if (reclen > buf->count) + return -EINVAL; +diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c +index a609d480606d..e2b2196fd942 100644 +--- a/fs/userfaultfd.c ++++ b/fs/userfaultfd.c +@@ -1807,13 +1807,12 @@ static int userfaultfd_api(struct userfaultfd_ctx *ctx, + if (copy_from_user(&uffdio_api, buf, sizeof(uffdio_api))) + goto out; + features = uffdio_api.features; +- if (uffdio_api.api != UFFD_API || (features & ~UFFD_API_FEATURES)) { +- memset(&uffdio_api, 0, sizeof(uffdio_api)); +- if (copy_to_user(buf, &uffdio_api, sizeof(uffdio_api))) +- goto out; +- ret = -EINVAL; +- goto out; +- } ++ ret = -EINVAL; ++ if (uffdio_api.api != UFFD_API || (features & ~UFFD_API_FEATURES)) ++ goto err_out; ++ ret = -EPERM; ++ if ((features & UFFD_FEATURE_EVENT_FORK) && !capable(CAP_SYS_PTRACE)) ++ goto err_out; + /* report all available features and ioctls to userland */ + uffdio_api.features = UFFD_API_FEATURES; + uffdio_api.ioctls = UFFD_API_IOCTLS; +@@ -1826,6 +1825,11 @@ static int userfaultfd_api(struct userfaultfd_ctx *ctx, + ret = 0; + out: + return ret; ++err_out: ++ memset(&uffdio_api, 0, sizeof(uffdio_api)); ++ if (copy_to_user(buf, &uffdio_api, sizeof(uffdio_api))) ++ ret = -EFAULT; ++ goto out; + } + + static long userfaultfd_ioctl(struct file *file, unsigned cmd, +diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h +index 012c37fdb688..5511dc963dd5 100644 +--- a/include/linux/hrtimer.h ++++ b/include/linux/hrtimer.h +@@ -408,12 +408,18 @@ extern u64 hrtimer_get_next_event(void); + + extern bool hrtimer_active(const struct hrtimer *timer); + +-/* +- * Helper function to check, whether the timer is on one of the queues ++/** ++ * hrtimer_is_queued = check, whether the timer is on one of the queues ++ * @timer: Timer to check ++ * ++ * Returns: True if the timer is queued, false otherwise ++ * ++ * The function can be used lockless, but it gives only a current snapshot. + */ +-static inline int hrtimer_is_queued(struct hrtimer *timer) ++static inline bool hrtimer_is_queued(struct hrtimer *timer) + { +- return timer->state & HRTIMER_STATE_ENQUEUED; ++ /* The READ_ONCE pairs with the update functions of timer->state */ ++ return !!(READ_ONCE(timer->state) & HRTIMER_STATE_ENQUEUED); + } + + /* +diff --git a/include/linux/libfdt_env.h b/include/linux/libfdt_env.h +index 1aa707ab19bb..8b54c591678e 100644 +--- a/include/linux/libfdt_env.h ++++ b/include/linux/libfdt_env.h +@@ -7,6 +7,9 @@ + + #include + ++#define INT32_MAX S32_MAX ++#define UINT32_MAX U32_MAX ++ + typedef __be16 fdt16_t; + typedef __be32 fdt32_t; + typedef __be64 fdt64_t; +diff --git a/include/linux/posix-clock.h b/include/linux/posix-clock.h +index 38d8225510f1..3097b08c55cb 100644 +--- a/include/linux/posix-clock.h ++++ b/include/linux/posix-clock.h +@@ -82,29 +82,32 @@ struct posix_clock_operations { + * + * @ops: Functional interface to the clock + * @cdev: Character device instance for this clock +- * @kref: Reference count. ++ * @dev: Pointer to the clock's device. + * @rwsem: Protects the 'zombie' field from concurrent access. + * @zombie: If 'zombie' is true, then the hardware has disappeared. +- * @release: A function to free the structure when the reference count reaches +- * zero. May be NULL if structure is statically allocated. + * + * Drivers should embed their struct posix_clock within a private + * structure, obtaining a reference to it during callbacks using + * container_of(). ++ * ++ * Drivers should supply an initialized but not exposed struct device ++ * to posix_clock_register(). It is used to manage lifetime of the ++ * driver's private structure. It's 'release' field should be set to ++ * a release function for this private structure. + */ + struct posix_clock { + struct posix_clock_operations ops; + struct cdev cdev; +- struct kref kref; ++ struct device *dev; + struct rw_semaphore rwsem; + bool zombie; +- void (*release)(struct posix_clock *clk); + }; + + /** + * posix_clock_register() - register a new clock +- * @clk: Pointer to the clock. Caller must provide 'ops' and 'release' +- * @devid: Allocated device id ++ * @clk: Pointer to the clock. Caller must provide 'ops' field ++ * @dev: Pointer to the initialized device. Caller must provide ++ * 'release' field + * + * A clock driver calls this function to register itself with the + * clock device subsystem. If 'clk' points to dynamically allocated +@@ -113,7 +116,7 @@ struct posix_clock { + * + * Returns zero on success, non-zero otherwise. + */ +-int posix_clock_register(struct posix_clock *clk, dev_t devid); ++int posix_clock_register(struct posix_clock *clk, struct device *dev); + + /** + * posix_clock_unregister() - unregister a clock +diff --git a/include/linux/quota.h b/include/linux/quota.h +index 5ac9de4fcd6f..aa9a42eceab0 100644 +--- a/include/linux/quota.h ++++ b/include/linux/quota.h +@@ -263,7 +263,7 @@ enum { + }; + + struct dqstats { +- int stat[_DQST_DQSTAT_LAST]; ++ unsigned long stat[_DQST_DQSTAT_LAST]; + struct percpu_counter counter[_DQST_DQSTAT_LAST]; + }; + +diff --git a/include/linux/rculist_nulls.h b/include/linux/rculist_nulls.h +index e4b257ff881b..a10da545b3f6 100644 +--- a/include/linux/rculist_nulls.h ++++ b/include/linux/rculist_nulls.h +@@ -100,6 +100,43 @@ static inline void hlist_nulls_add_head_rcu(struct hlist_nulls_node *n, + first->pprev = &n->next; + } + ++/** ++ * hlist_nulls_add_tail_rcu ++ * @n: the element to add to the hash list. ++ * @h: the list to add to. ++ * ++ * Description: ++ * Adds the specified element to the specified hlist_nulls, ++ * while permitting racing traversals. ++ * ++ * The caller must take whatever precautions are necessary ++ * (such as holding appropriate locks) to avoid racing ++ * with another list-mutation primitive, such as hlist_nulls_add_head_rcu() ++ * or hlist_nulls_del_rcu(), running on this same list. ++ * However, it is perfectly legal to run concurrently with ++ * the _rcu list-traversal primitives, such as ++ * hlist_nulls_for_each_entry_rcu(), used to prevent memory-consistency ++ * problems on Alpha CPUs. Regardless of the type of CPU, the ++ * list-traversal primitive must be guarded by rcu_read_lock(). ++ */ ++static inline void hlist_nulls_add_tail_rcu(struct hlist_nulls_node *n, ++ struct hlist_nulls_head *h) ++{ ++ struct hlist_nulls_node *i, *last = NULL; ++ ++ /* Note: write side code, so rcu accessors are not needed. */ ++ for (i = h->first; !is_a_nulls(i); i = i->next) ++ last = i; ++ ++ if (last) { ++ n->next = last->next; ++ n->pprev = &last->next; ++ rcu_assign_pointer(hlist_next_rcu(last), n); ++ } else { ++ hlist_nulls_add_head_rcu(n, h); ++ } ++} ++ + /** + * hlist_nulls_for_each_entry_rcu - iterate over rcu list of given type + * @tpos: the type * to use as a loop cursor. +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index ec00d9264e5c..a9a764a17c28 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -1655,7 +1655,7 @@ static inline struct sk_buff *skb_peek_next(struct sk_buff *skb, + */ + static inline struct sk_buff *skb_peek_tail(const struct sk_buff_head *list_) + { +- struct sk_buff *skb = list_->prev; ++ struct sk_buff *skb = READ_ONCE(list_->prev); + + if (skb == (struct sk_buff *)list_) + skb = NULL; +@@ -1723,7 +1723,9 @@ static inline void __skb_insert(struct sk_buff *newsk, + struct sk_buff *prev, struct sk_buff *next, + struct sk_buff_head *list) + { +- /* see skb_queue_empty_lockless() for the opposite READ_ONCE() */ ++ /* See skb_queue_empty_lockless() and skb_peek_tail() ++ * for the opposite READ_ONCE() ++ */ + WRITE_ONCE(newsk->next, next); + WRITE_ONCE(newsk->prev, prev); + WRITE_ONCE(next->prev, newsk); +diff --git a/include/net/dst.h b/include/net/dst.h +index fe230dd62c28..5ebc7356a381 100644 +--- a/include/net/dst.h ++++ b/include/net/dst.h +@@ -528,7 +528,16 @@ static inline void skb_dst_update_pmtu(struct sk_buff *skb, u32 mtu) + struct dst_entry *dst = skb_dst(skb); + + if (dst && dst->ops->update_pmtu) +- dst->ops->update_pmtu(dst, NULL, skb, mtu); ++ dst->ops->update_pmtu(dst, NULL, skb, mtu, true); ++} ++ ++/* update dst pmtu but not do neighbor confirm */ ++static inline void skb_dst_update_pmtu_no_confirm(struct sk_buff *skb, u32 mtu) ++{ ++ struct dst_entry *dst = skb_dst(skb); ++ ++ if (dst && dst->ops->update_pmtu) ++ dst->ops->update_pmtu(dst, NULL, skb, mtu, false); + } + + #endif /* _NET_DST_H */ +diff --git a/include/net/dst_ops.h b/include/net/dst_ops.h +index 5ec645f27ee3..443863c7b8da 100644 +--- a/include/net/dst_ops.h ++++ b/include/net/dst_ops.h +@@ -27,7 +27,8 @@ struct dst_ops { + struct dst_entry * (*negative_advice)(struct dst_entry *); + void (*link_failure)(struct sk_buff *); + void (*update_pmtu)(struct dst_entry *dst, struct sock *sk, +- struct sk_buff *skb, u32 mtu); ++ struct sk_buff *skb, u32 mtu, ++ bool confirm_neigh); + void (*redirect)(struct dst_entry *dst, struct sock *sk, + struct sk_buff *skb); + int (*local_out)(struct net *net, struct sock *sk, struct sk_buff *skb); +diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h +index 2dbbbff5e1e3..573ab110c9ec 100644 +--- a/include/net/inet_hashtables.h ++++ b/include/net/inet_hashtables.h +@@ -106,12 +106,18 @@ struct inet_bind_hashbucket { + struct hlist_head chain; + }; + +-/* +- * Sockets can be hashed in established or listening table ++/* Sockets can be hashed in established or listening table. ++ * We must use different 'nulls' end-of-chain value for all hash buckets : ++ * A socket might transition from ESTABLISH to LISTEN state without ++ * RCU grace period. A lookup in ehash table needs to handle this case. + */ ++#define LISTENING_NULLS_BASE (1U << 29) + struct inet_listen_hashbucket { + spinlock_t lock; +- struct hlist_head head; ++ union { ++ struct hlist_head head; ++ struct hlist_nulls_head nulls_head; ++ }; + }; + + /* This is for listening sockets, thus all sockets which possess wildcards. */ +diff --git a/include/net/sock.h b/include/net/sock.h +index 0af46cbd3649..c6a003bc4737 100644 +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -693,6 +693,11 @@ static inline void __sk_nulls_add_node_rcu(struct sock *sk, struct hlist_nulls_h + hlist_nulls_add_head_rcu(&sk->sk_nulls_node, list); + } + ++static inline void __sk_nulls_add_node_tail_rcu(struct sock *sk, struct hlist_nulls_head *list) ++{ ++ hlist_nulls_add_tail_rcu(&sk->sk_nulls_node, list); ++} ++ + static inline void sk_nulls_add_node_rcu(struct sock *sk, struct hlist_nulls_head *list) + { + sock_hold(sk); +diff --git a/include/scsi/iscsi_proto.h b/include/scsi/iscsi_proto.h +index df156f1d50b2..f0a01a54bd15 100644 +--- a/include/scsi/iscsi_proto.h ++++ b/include/scsi/iscsi_proto.h +@@ -638,6 +638,7 @@ struct iscsi_reject { + #define ISCSI_REASON_BOOKMARK_INVALID 9 + #define ISCSI_REASON_BOOKMARK_NO_RESOURCES 10 + #define ISCSI_REASON_NEGOTIATION_RESET 11 ++#define ISCSI_REASON_WAITING_FOR_LOGOUT 12 + + /* Max. number of Key=Value pairs in a text message */ + #define MAX_KEY_VALUE_PAIRS 8192 +diff --git a/kernel/sysctl.c b/kernel/sysctl.c +index cfc2c0d1369a..74fc3a9d1923 100644 +--- a/kernel/sysctl.c ++++ b/kernel/sysctl.c +@@ -1397,7 +1397,7 @@ static struct ctl_table vm_table[] = { + .procname = "drop_caches", + .data = &sysctl_drop_caches, + .maxlen = sizeof(int), +- .mode = 0644, ++ .mode = 0200, + .proc_handler = drop_caches_sysctl_handler, + .extra1 = &one, + .extra2 = &four, +diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c +index d00e85ac10d6..ecce9122343b 100644 +--- a/kernel/time/hrtimer.c ++++ b/kernel/time/hrtimer.c +@@ -845,7 +845,8 @@ static int enqueue_hrtimer(struct hrtimer *timer, + + base->cpu_base->active_bases |= 1 << base->index; + +- timer->state = HRTIMER_STATE_ENQUEUED; ++ /* Pairs with the lockless read in hrtimer_is_queued() */ ++ WRITE_ONCE(timer->state, HRTIMER_STATE_ENQUEUED); + + return timerqueue_add(&base->active, &timer->node); + } +@@ -867,7 +868,8 @@ static void __remove_hrtimer(struct hrtimer *timer, + struct hrtimer_cpu_base *cpu_base = base->cpu_base; + u8 state = timer->state; + +- timer->state = newstate; ++ /* Pairs with the lockless read in hrtimer_is_queued() */ ++ WRITE_ONCE(timer->state, newstate); + if (!(state & HRTIMER_STATE_ENQUEUED)) + return; + +@@ -894,8 +896,9 @@ static void __remove_hrtimer(struct hrtimer *timer, + static inline int + remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, bool restart) + { +- if (hrtimer_is_queued(timer)) { +- u8 state = timer->state; ++ u8 state = timer->state; ++ ++ if (state & HRTIMER_STATE_ENQUEUED) { + int reprogram; + + /* +diff --git a/kernel/time/posix-clock.c b/kernel/time/posix-clock.c +index 17cdc554c9fe..e5706a826c1f 100644 +--- a/kernel/time/posix-clock.c ++++ b/kernel/time/posix-clock.c +@@ -27,8 +27,6 @@ + + #include "posix-timers.h" + +-static void delete_clock(struct kref *kref); +- + /* + * Returns NULL if the posix_clock instance attached to 'fp' is old and stale. + */ +@@ -138,7 +136,7 @@ static int posix_clock_open(struct inode *inode, struct file *fp) + err = 0; + + if (!err) { +- kref_get(&clk->kref); ++ get_device(clk->dev); + fp->private_data = clk; + } + out: +@@ -154,7 +152,7 @@ static int posix_clock_release(struct inode *inode, struct file *fp) + if (clk->ops.release) + err = clk->ops.release(clk); + +- kref_put(&clk->kref, delete_clock); ++ put_device(clk->dev); + + fp->private_data = NULL; + +@@ -174,38 +172,35 @@ static const struct file_operations posix_clock_file_operations = { + #endif + }; + +-int posix_clock_register(struct posix_clock *clk, dev_t devid) ++int posix_clock_register(struct posix_clock *clk, struct device *dev) + { + int err; + +- kref_init(&clk->kref); + init_rwsem(&clk->rwsem); + + cdev_init(&clk->cdev, &posix_clock_file_operations); ++ err = cdev_device_add(&clk->cdev, dev); ++ if (err) { ++ pr_err("%s unable to add device %d:%d\n", ++ dev_name(dev), MAJOR(dev->devt), MINOR(dev->devt)); ++ return err; ++ } + clk->cdev.owner = clk->ops.owner; +- err = cdev_add(&clk->cdev, devid, 1); ++ clk->dev = dev; + +- return err; ++ return 0; + } + EXPORT_SYMBOL_GPL(posix_clock_register); + +-static void delete_clock(struct kref *kref) +-{ +- struct posix_clock *clk = container_of(kref, struct posix_clock, kref); +- +- if (clk->release) +- clk->release(clk); +-} +- + void posix_clock_unregister(struct posix_clock *clk) + { +- cdev_del(&clk->cdev); ++ cdev_device_del(&clk->cdev, clk->dev); + + down_write(&clk->rwsem); + clk->zombie = true; + up_write(&clk->rwsem); + +- kref_put(&clk->kref, delete_clock); ++ put_device(clk->dev); + } + EXPORT_SYMBOL_GPL(posix_clock_unregister); + +diff --git a/lib/dma-debug.c b/lib/dma-debug.c +index ea4cc3dde4f1..61e7240947f5 100644 +--- a/lib/dma-debug.c ++++ b/lib/dma-debug.c +@@ -437,6 +437,7 @@ void debug_dma_dump_mappings(struct device *dev) + } + + spin_unlock_irqrestore(&bucket->lock, flags); ++ cond_resched(); + } + } + EXPORT_SYMBOL(debug_dma_dump_mappings); +diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c +index 89936e0d55c9..6feab2279143 100644 +--- a/net/bridge/br_netfilter_hooks.c ++++ b/net/bridge/br_netfilter_hooks.c +@@ -643,6 +643,9 @@ static unsigned int br_nf_forward_arp(void *priv, + nf_bridge_pull_encap_header(skb); + } + ++ if (unlikely(!pskb_may_pull(skb, sizeof(struct arphdr)))) ++ return NF_DROP; ++ + if (arp_hdr(skb)->ar_pln != 4) { + if (IS_VLAN_ARP(skb)) + nf_bridge_push_encap_header(skb); +diff --git a/net/bridge/br_nf_core.c b/net/bridge/br_nf_core.c +index 20cbb727df4d..c217276bd76a 100644 +--- a/net/bridge/br_nf_core.c ++++ b/net/bridge/br_nf_core.c +@@ -26,7 +26,8 @@ + #endif + + static void fake_update_pmtu(struct dst_entry *dst, struct sock *sk, +- struct sk_buff *skb, u32 mtu) ++ struct sk_buff *skb, u32 mtu, ++ bool confirm_neigh) + { + } + +diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c +index 100b4f88179a..35a670ec9077 100644 +--- a/net/bridge/netfilter/ebtables.c ++++ b/net/bridge/netfilter/ebtables.c +@@ -1876,7 +1876,7 @@ static int ebt_buf_count(struct ebt_entries_buf_state *state, unsigned int sz) + } + + static int ebt_buf_add(struct ebt_entries_buf_state *state, +- void *data, unsigned int sz) ++ const void *data, unsigned int sz) + { + if (state->buf_kern_start == NULL) + goto count_only; +@@ -1910,7 +1910,7 @@ enum compat_mwt { + EBT_COMPAT_TARGET, + }; + +-static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, ++static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt, + enum compat_mwt compat_mwt, + struct ebt_entries_buf_state *state, + const unsigned char *base) +@@ -1986,22 +1986,23 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, + /* return size of all matches, watchers or target, including necessary + * alignment and padding. + */ +-static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32, ++static int ebt_size_mwt(const struct compat_ebt_entry_mwt *match32, + unsigned int size_left, enum compat_mwt type, + struct ebt_entries_buf_state *state, const void *base) + { ++ const char *buf = (const char *)match32; + int growth = 0; +- char *buf; + + if (size_left == 0) + return 0; + +- buf = (char *) match32; +- +- while (size_left >= sizeof(*match32)) { ++ do { + struct ebt_entry_match *match_kern; + int ret; + ++ if (size_left < sizeof(*match32)) ++ return -EINVAL; ++ + match_kern = (struct ebt_entry_match *) state->buf_kern_start; + if (match_kern) { + char *tmp; +@@ -2038,22 +2039,18 @@ static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32, + if (match_kern) + match_kern->match_size = ret; + +- /* rule should have no remaining data after target */ +- if (type == EBT_COMPAT_TARGET && size_left) +- return -EINVAL; +- + match32 = (struct compat_ebt_entry_mwt *) buf; +- } ++ } while (size_left); + + return growth; + } + + /* called for all ebt_entry structures. */ +-static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, ++static int size_entry_mwt(const struct ebt_entry *entry, const unsigned char *base, + unsigned int *total, + struct ebt_entries_buf_state *state) + { +- unsigned int i, j, startoff, new_offset = 0; ++ unsigned int i, j, startoff, next_expected_off, new_offset = 0; + /* stores match/watchers/targets & offset of next struct ebt_entry: */ + unsigned int offsets[4]; + unsigned int *offsets_update = NULL; +@@ -2140,11 +2137,13 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, + return ret; + } + +- startoff = state->buf_user_offset - startoff; ++ next_expected_off = state->buf_user_offset - startoff; ++ if (next_expected_off != entry->next_offset) ++ return -EINVAL; + +- if (WARN_ON(*total < startoff)) ++ if (*total < entry->next_offset) + return -EINVAL; +- *total -= startoff; ++ *total -= entry->next_offset; + return 0; + } + +diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c +index 144cd1acd7e3..069e3c4fcc44 100644 +--- a/net/core/sysctl_net_core.c ++++ b/net/core/sysctl_net_core.c +@@ -274,6 +274,7 @@ static int proc_dointvec_minmax_bpf_enable(struct ctl_table *table, int write, + return ret; + } + ++# ifdef CONFIG_HAVE_EBPF_JIT + static int + proc_dointvec_minmax_bpf_restricted(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, +@@ -284,6 +285,7 @@ proc_dointvec_minmax_bpf_restricted(struct ctl_table *table, int write, + + return proc_dointvec_minmax(table, write, buffer, lenp, ppos); + } ++# endif /* CONFIG_HAVE_EBPF_JIT */ + + static int + proc_dolongvec_minmax_bpf_restricted(struct ctl_table *table, int write, +diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c +index 0bd3afd01dd2..ccc189bc3617 100644 +--- a/net/decnet/dn_route.c ++++ b/net/decnet/dn_route.c +@@ -118,7 +118,8 @@ static void dn_dst_ifdown(struct dst_entry *, struct net_device *dev, int how); + static struct dst_entry *dn_dst_negative_advice(struct dst_entry *); + static void dn_dst_link_failure(struct sk_buff *); + static void dn_dst_update_pmtu(struct dst_entry *dst, struct sock *sk, +- struct sk_buff *skb , u32 mtu); ++ struct sk_buff *skb , u32 mtu, ++ bool confirm_neigh); + static void dn_dst_redirect(struct dst_entry *dst, struct sock *sk, + struct sk_buff *skb); + static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst, +@@ -259,7 +260,8 @@ static int dn_dst_gc(struct dst_ops *ops) + * advertise to the other end). + */ + static void dn_dst_update_pmtu(struct dst_entry *dst, struct sock *sk, +- struct sk_buff *skb, u32 mtu) ++ struct sk_buff *skb, u32 mtu, ++ bool confirm_neigh) + { + struct dn_route *rt = (struct dn_route *) dst; + struct neighbour *n = rt->n; +diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c +index f9d790b058d2..995ef3d23368 100644 +--- a/net/ipv4/icmp.c ++++ b/net/ipv4/icmp.c +@@ -254,10 +254,11 @@ bool icmp_global_allow(void) + bool rc = false; + + /* Check if token bucket is empty and cannot be refilled +- * without taking the spinlock. ++ * without taking the spinlock. The READ_ONCE() are paired ++ * with the following WRITE_ONCE() in this same function. + */ +- if (!icmp_global.credit) { +- delta = min_t(u32, now - icmp_global.stamp, HZ); ++ if (!READ_ONCE(icmp_global.credit)) { ++ delta = min_t(u32, now - READ_ONCE(icmp_global.stamp), HZ); + if (delta < HZ / 50) + return false; + } +@@ -267,14 +268,14 @@ bool icmp_global_allow(void) + if (delta >= HZ / 50) { + incr = sysctl_icmp_msgs_per_sec * delta / HZ ; + if (incr) +- icmp_global.stamp = now; ++ WRITE_ONCE(icmp_global.stamp, now); + } + credit = min_t(u32, icmp_global.credit + incr, sysctl_icmp_msgs_burst); + if (credit) { + credit--; + rc = true; + } +- icmp_global.credit = credit; ++ WRITE_ONCE(icmp_global.credit, credit); + spin_unlock(&icmp_global.lock); + return rc; + } +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index 9d6b172caf6c..f7224c4fc30f 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -1088,7 +1088,7 @@ struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu) + if (!dst) + goto out; + } +- dst->ops->update_pmtu(dst, sk, NULL, mtu); ++ dst->ops->update_pmtu(dst, sk, NULL, mtu, true); + + dst = __sk_dst_check(sk, 0); + if (!dst) +diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c +index 33edccfebc30..eb158badebc4 100644 +--- a/net/ipv4/inet_diag.c ++++ b/net/ipv4/inet_diag.c +@@ -911,11 +911,12 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb, + + for (i = s_i; i < INET_LHTABLE_SIZE; i++) { + struct inet_listen_hashbucket *ilb; ++ struct hlist_nulls_node *node; + + num = 0; + ilb = &hashinfo->listening_hash[i]; + spin_lock(&ilb->lock); +- sk_for_each(sk, &ilb->head) { ++ sk_nulls_for_each(sk, node, &ilb->nulls_head) { + struct inet_sock *inet = inet_sk(sk); + + if (!net_eq(sock_net(sk), net)) +diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c +index 1f26627c7fad..0af13f5bdc9a 100644 +--- a/net/ipv4/inet_hashtables.c ++++ b/net/ipv4/inet_hashtables.c +@@ -219,9 +219,10 @@ struct sock *__inet_lookup_listener(struct net *net, + int score, hiscore = 0, matches = 0, reuseport = 0; + bool exact_dif = inet_exact_dif_match(net, skb); + struct sock *sk, *result = NULL; ++ struct hlist_nulls_node *node; + u32 phash = 0; + +- sk_for_each_rcu(sk, &ilb->head) { ++ sk_nulls_for_each_rcu(sk, node, &ilb->nulls_head) { + score = compute_score(sk, net, hnum, daddr, + dif, sdif, exact_dif); + if (score > hiscore) { +@@ -442,10 +443,11 @@ static int inet_reuseport_add_sock(struct sock *sk, + struct inet_listen_hashbucket *ilb) + { + struct inet_bind_bucket *tb = inet_csk(sk)->icsk_bind_hash; ++ const struct hlist_nulls_node *node; + struct sock *sk2; + kuid_t uid = sock_i_uid(sk); + +- sk_for_each_rcu(sk2, &ilb->head) { ++ sk_nulls_for_each_rcu(sk2, node, &ilb->nulls_head) { + if (sk2 != sk && + sk2->sk_family == sk->sk_family && + ipv6_only_sock(sk2) == ipv6_only_sock(sk) && +@@ -480,9 +482,9 @@ int __inet_hash(struct sock *sk, struct sock *osk) + } + if (IS_ENABLED(CONFIG_IPV6) && sk->sk_reuseport && + sk->sk_family == AF_INET6) +- hlist_add_tail_rcu(&sk->sk_node, &ilb->head); ++ __sk_nulls_add_node_tail_rcu(sk, &ilb->nulls_head); + else +- hlist_add_head_rcu(&sk->sk_node, &ilb->head); ++ __sk_nulls_add_node_rcu(sk, &ilb->nulls_head); + sock_set_flag(sk, SOCK_RCU_FREE); + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); + unlock: +@@ -525,10 +527,7 @@ void inet_unhash(struct sock *sk) + spin_lock_bh(lock); + if (rcu_access_pointer(sk->sk_reuseport_cb)) + reuseport_detach_sock(sk); +- if (listener) +- done = __sk_del_node_init(sk); +- else +- done = __sk_nulls_del_node_init_rcu(sk); ++ done = __sk_nulls_del_node_init_rcu(sk); + if (done) + sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); + spin_unlock_bh(lock); +@@ -664,7 +663,8 @@ void inet_hashinfo_init(struct inet_hashinfo *h) + + for (i = 0; i < INET_LHTABLE_SIZE; i++) { + spin_lock_init(&h->listening_hash[i].lock); +- INIT_HLIST_HEAD(&h->listening_hash[i].head); ++ INIT_HLIST_NULLS_HEAD(&h->listening_hash[i].nulls_head, ++ i + LISTENING_NULLS_BASE); + } + } + EXPORT_SYMBOL_GPL(inet_hashinfo_init); +diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c +index f9cef27907ed..f94881412d5b 100644 +--- a/net/ipv4/inetpeer.c ++++ b/net/ipv4/inetpeer.c +@@ -159,7 +159,12 @@ static void inet_peer_gc(struct inet_peer_base *base, + base->total / inet_peer_threshold * HZ; + for (i = 0; i < gc_cnt; i++) { + p = gc_stack[i]; +- delta = (__u32)jiffies - p->dtime; ++ ++ /* The READ_ONCE() pairs with the WRITE_ONCE() ++ * in inet_putpeer() ++ */ ++ delta = (__u32)jiffies - READ_ONCE(p->dtime); ++ + if (delta < ttl || !refcount_dec_if_one(&p->refcnt)) + gc_stack[i] = NULL; + } +@@ -236,7 +241,10 @@ EXPORT_SYMBOL_GPL(inet_getpeer); + + void inet_putpeer(struct inet_peer *p) + { +- p->dtime = (__u32)jiffies; ++ /* The WRITE_ONCE() pairs with itself (we run lockless) ++ * and the READ_ONCE() in inet_peer_gc() ++ */ ++ WRITE_ONCE(p->dtime, (__u32)jiffies); + + if (refcount_dec_and_test(&p->refcnt)) + call_rcu(&p->rcu, inetpeer_free_rcu); +diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c +index 7a31287ff123..f1784162acc2 100644 +--- a/net/ipv4/ip_tunnel.c ++++ b/net/ipv4/ip_tunnel.c +@@ -521,7 +521,7 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb, + else + mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; + +- skb_dst_update_pmtu(skb, mtu); ++ skb_dst_update_pmtu_no_confirm(skb, mtu); + + if (skb->protocol == htons(ETH_P_IP)) { + if (!skb_is_gso(skb) && +diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c +index c07065b7e3b0..08c15dd42d93 100644 +--- a/net/ipv4/ip_vti.c ++++ b/net/ipv4/ip_vti.c +@@ -244,7 +244,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, + + mtu = dst_mtu(dst); + if (skb->len > mtu) { +- skb_dst_update_pmtu(skb, mtu); ++ skb_dst_update_pmtu_no_confirm(skb, mtu); + if (skb->protocol == htons(ETH_P_IP)) { + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, + htonl(mtu)); +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index de7f955ffd0a..8b855d3eec9e 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -145,7 +145,8 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst); + static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst); + static void ipv4_link_failure(struct sk_buff *skb); + static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, +- struct sk_buff *skb, u32 mtu); ++ struct sk_buff *skb, u32 mtu, ++ bool confirm_neigh); + static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, + struct sk_buff *skb); + static void ipv4_dst_destroy(struct dst_entry *dst); +@@ -1042,7 +1043,8 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) + } + + static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, +- struct sk_buff *skb, u32 mtu) ++ struct sk_buff *skb, u32 mtu, ++ bool confirm_neigh) + { + struct rtable *rt = (struct rtable *) dst; + struct flowi4 fl4; +@@ -2529,7 +2531,8 @@ static unsigned int ipv4_blackhole_mtu(const struct dst_entry *dst) + } + + static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, struct sock *sk, +- struct sk_buff *skb, u32 mtu) ++ struct sk_buff *skb, u32 mtu, ++ bool confirm_neigh) + { + } + +diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c +index 44a41ac2b0ca..b4f0fc34b0ed 100644 +--- a/net/ipv4/tcp_ipv4.c ++++ b/net/ipv4/tcp_ipv4.c +@@ -1936,13 +1936,14 @@ static void *listening_get_next(struct seq_file *seq, void *cur) + struct tcp_iter_state *st = seq->private; + struct net *net = seq_file_net(seq); + struct inet_listen_hashbucket *ilb; ++ struct hlist_nulls_node *node; + struct sock *sk = cur; + + if (!sk) { + get_head: + ilb = &tcp_hashinfo.listening_hash[st->bucket]; + spin_lock(&ilb->lock); +- sk = sk_head(&ilb->head); ++ sk = sk_nulls_head(&ilb->nulls_head); + st->offset = 0; + goto get_sk; + } +@@ -1950,9 +1951,9 @@ get_head: + ++st->num; + ++st->offset; + +- sk = sk_next(sk); ++ sk = sk_nulls_next(sk); + get_sk: +- sk_for_each_from(sk) { ++ sk_nulls_for_each_from(sk, node) { + if (!net_eq(sock_net(sk), net)) + continue; + if (sk->sk_family == st->family) +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index e3b28140c10b..e1eb56e21dd5 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -2380,6 +2380,14 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, + if (tcp_small_queue_check(sk, skb, 0)) + break; + ++ /* Argh, we hit an empty skb(), presumably a thread ++ * is sleeping in sendmsg()/sk_stream_wait_memory(). ++ * We do not want to send a pure-ack packet and have ++ * a strange looking rtx queue with empty packet(s). ++ */ ++ if (TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq) ++ break; ++ + if (unlikely(tcp_transmit_skb(sk, skb, 1, gfp))) + break; + +diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c +index ab3f272a0884..e33258d69246 100644 +--- a/net/ipv4/udp.c ++++ b/net/ipv4/udp.c +@@ -1338,7 +1338,7 @@ int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb) + * queue contains some other skb + */ + rmem = atomic_add_return(size, &sk->sk_rmem_alloc); +- if (rmem > (size + sk->sk_rcvbuf)) ++ if (rmem > (size + (unsigned int)sk->sk_rcvbuf)) + goto uncharge_drop; + + spin_lock(&list->lock); +diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c +index 5952dca98e6b..08f00225ed1b 100644 +--- a/net/ipv4/xfrm4_policy.c ++++ b/net/ipv4/xfrm4_policy.c +@@ -222,12 +222,13 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) + } + + static void xfrm4_update_pmtu(struct dst_entry *dst, struct sock *sk, +- struct sk_buff *skb, u32 mtu) ++ struct sk_buff *skb, u32 mtu, ++ bool confirm_neigh) + { + struct xfrm_dst *xdst = (struct xfrm_dst *)dst; + struct dst_entry *path = xdst->route; + +- path->ops->update_pmtu(path, sk, skb, mtu); ++ path->ops->update_pmtu(path, sk, skb, mtu, confirm_neigh); + } + + static void xfrm4_redirect(struct dst_entry *dst, struct sock *sk, +diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c +index 9a31d13bf180..890adadcda16 100644 +--- a/net/ipv6/inet6_connection_sock.c ++++ b/net/ipv6/inet6_connection_sock.c +@@ -150,7 +150,7 @@ struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu) + + if (IS_ERR(dst)) + return NULL; +- dst->ops->update_pmtu(dst, sk, NULL, mtu); ++ dst->ops->update_pmtu(dst, sk, NULL, mtu, true); + + dst = inet6_csk_route_socket(sk, &fl6); + return IS_ERR(dst) ? NULL : dst; +diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c +index 228983a5531b..24a21979d7df 100644 +--- a/net/ipv6/inet6_hashtables.c ++++ b/net/ipv6/inet6_hashtables.c +@@ -137,9 +137,10 @@ struct sock *inet6_lookup_listener(struct net *net, + int score, hiscore = 0, matches = 0, reuseport = 0; + bool exact_dif = inet6_exact_dif_match(net, skb); + struct sock *sk, *result = NULL; ++ struct hlist_nulls_node *node; + u32 phash = 0; + +- sk_for_each(sk, &ilb->head) { ++ sk_nulls_for_each(sk, node, &ilb->nulls_head) { + score = compute_score(sk, net, hnum, daddr, dif, sdif, exact_dif); + if (score > hiscore) { + reuseport = sk->sk_reuseport; +diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c +index 4228f3b2f347..726ba41133a3 100644 +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -527,7 +527,7 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb, + + /* TooBig packet may have updated dst->dev's mtu */ + if (dst && dst_mtu(dst) > dst->dev->mtu) +- dst->ops->update_pmtu(dst, NULL, skb, dst->dev->mtu); ++ dst->ops->update_pmtu(dst, NULL, skb, dst->dev->mtu, false); + + return ip6_tnl_xmit(skb, dev, dsfield, fl6, encap_limit, pmtu, + NEXTHDR_GRE); +diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c +index 067fc78cc529..5bc2788e6ba4 100644 +--- a/net/ipv6/ip6_tunnel.c ++++ b/net/ipv6/ip6_tunnel.c +@@ -652,7 +652,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + if (rel_info > dst_mtu(skb_dst(skb2))) + goto out; + +- skb_dst_update_pmtu(skb2, rel_info); ++ skb_dst_update_pmtu_no_confirm(skb2, rel_info); + } + if (rel_type == ICMP_REDIRECT) + skb_dst(skb2)->ops->redirect(skb_dst(skb2), NULL, skb2); +@@ -1138,7 +1138,7 @@ route_lookup: + mtu = max(mtu, skb->protocol == htons(ETH_P_IPV6) ? + IPV6_MIN_MTU : IPV4_MIN_MTU); + +- skb_dst_update_pmtu(skb, mtu); ++ skb_dst_update_pmtu_no_confirm(skb, mtu); + if (skb->len - t->tun_hlen - eth_hlen > mtu && !skb_is_gso(skb)) { + *pmtu = mtu; + err = -EMSGSIZE; +diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c +index 6b2416b4a53e..557fe3880a3f 100644 +--- a/net/ipv6/ip6_vti.c ++++ b/net/ipv6/ip6_vti.c +@@ -483,7 +483,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) + + mtu = dst_mtu(dst); + if (skb->len > mtu) { +- skb_dst_update_pmtu(skb, mtu); ++ skb_dst_update_pmtu_no_confirm(skb, mtu); + + if (skb->protocol == htons(ETH_P_IPV6)) { + if (mtu < IPV6_MIN_MTU) +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 00f8fe8cebd5..b81522bcf223 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -93,7 +93,8 @@ static int ip6_pkt_prohibit(struct sk_buff *skb); + static int ip6_pkt_prohibit_out(struct net *net, struct sock *sk, struct sk_buff *skb); + static void ip6_link_failure(struct sk_buff *skb); + static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, +- struct sk_buff *skb, u32 mtu); ++ struct sk_buff *skb, u32 mtu, ++ bool confirm_neigh); + static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, + struct sk_buff *skb); + static void rt6_dst_from_metrics_check(struct rt6_info *rt); +@@ -264,7 +265,8 @@ static unsigned int ip6_blackhole_mtu(const struct dst_entry *dst) + } + + static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, struct sock *sk, +- struct sk_buff *skb, u32 mtu) ++ struct sk_buff *skb, u32 mtu, ++ bool confirm_neigh) + { + } + +@@ -1471,7 +1473,8 @@ static bool rt6_cache_allowed_for_pmtu(const struct rt6_info *rt) + } + + static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk, +- const struct ipv6hdr *iph, u32 mtu) ++ const struct ipv6hdr *iph, u32 mtu, ++ bool confirm_neigh) + { + const struct in6_addr *daddr, *saddr; + struct rt6_info *rt6 = (struct rt6_info *)dst; +@@ -1489,7 +1492,10 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk, + daddr = NULL; + saddr = NULL; + } +- dst_confirm_neigh(dst, daddr); ++ ++ if (confirm_neigh) ++ dst_confirm_neigh(dst, daddr); ++ + mtu = max_t(u32, mtu, IPV6_MIN_MTU); + if (mtu >= dst_mtu(dst)) + return; +@@ -1518,9 +1524,11 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk, + } + + static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, +- struct sk_buff *skb, u32 mtu) ++ struct sk_buff *skb, u32 mtu, ++ bool confirm_neigh) + { +- __ip6_rt_update_pmtu(dst, sk, skb ? ipv6_hdr(skb) : NULL, mtu); ++ __ip6_rt_update_pmtu(dst, sk, skb ? ipv6_hdr(skb) : NULL, mtu, ++ confirm_neigh); + } + + void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, +@@ -1540,7 +1548,7 @@ void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, + + dst = ip6_route_output(net, NULL, &fl6); + if (!dst->error) +- __ip6_rt_update_pmtu(dst, NULL, iph, ntohl(mtu)); ++ __ip6_rt_update_pmtu(dst, NULL, iph, ntohl(mtu), true); + dst_release(dst); + } + EXPORT_SYMBOL_GPL(ip6_update_pmtu); +diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c +index d2529c38e7e4..fb3f917db57a 100644 +--- a/net/ipv6/sit.c ++++ b/net/ipv6/sit.c +@@ -932,7 +932,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, + } + + if (tunnel->parms.iph.daddr) +- skb_dst_update_pmtu(skb, mtu); ++ skb_dst_update_pmtu_no_confirm(skb, mtu); + + if (skb->len > mtu && !skb_is_gso(skb)) { + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); +diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c +index d6b012295b45..b0d80cef7c2b 100644 +--- a/net/ipv6/xfrm6_policy.c ++++ b/net/ipv6/xfrm6_policy.c +@@ -219,12 +219,13 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) + } + + static void xfrm6_update_pmtu(struct dst_entry *dst, struct sock *sk, +- struct sk_buff *skb, u32 mtu) ++ struct sk_buff *skb, u32 mtu, ++ bool confirm_neigh) + { + struct xfrm_dst *xdst = (struct xfrm_dst *)dst; + struct dst_entry *path = xdst->route; + +- path->ops->update_pmtu(path, sk, skb, mtu); ++ path->ops->update_pmtu(path, sk, skb, mtu, confirm_neigh); + } + + static void xfrm6_redirect(struct dst_entry *dst, struct sock *sk, +diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c +index 4527921b1c3a..97d411033f8a 100644 +--- a/net/netfilter/ipvs/ip_vs_xmit.c ++++ b/net/netfilter/ipvs/ip_vs_xmit.c +@@ -209,7 +209,7 @@ static inline void maybe_update_pmtu(int skb_af, struct sk_buff *skb, int mtu) + struct rtable *ort = skb_rtable(skb); + + if (!skb->dev && sk && sk_fullsock(sk)) +- ort->dst.ops->update_pmtu(&ort->dst, sk, NULL, mtu); ++ ort->dst.ops->update_pmtu(&ort->dst, sk, NULL, mtu, true); + } + + static inline bool ensure_mtu_is_adequate(struct netns_ipvs *ipvs, int skb_af, +diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c +index 37efcc1c8887..b06ef4c62522 100644 +--- a/net/netfilter/nf_queue.c ++++ b/net/netfilter/nf_queue.c +@@ -138,7 +138,7 @@ static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state, + goto err; + } + +- if (!skb_dst_force(skb) && state->hook != NF_INET_PRE_ROUTING) { ++ if (skb_dst(skb) && !skb_dst_force(skb)) { + status = -ENETDOWN; + goto err; + } +diff --git a/net/sctp/transport.c b/net/sctp/transport.c +index 274df899e7bf..4c55b759a58e 100644 +--- a/net/sctp/transport.c ++++ b/net/sctp/transport.c +@@ -272,7 +272,7 @@ bool sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu) + + pf->af->from_sk(&addr, sk); + pf->to_sk_daddr(&t->ipaddr, sk); +- dst->ops->update_pmtu(dst, sk, NULL, pmtu); ++ dst->ops->update_pmtu(dst, sk, NULL, pmtu, true); + pf->to_sk_daddr(&addr, sk); + + dst = sctp_transport_dst_check(t); +diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c +index b471022c8162..b43531899648 100644 +--- a/scripts/kallsyms.c ++++ b/scripts/kallsyms.c +@@ -510,6 +510,8 @@ static void build_initial_tok_table(void) + table[pos] = table[i]; + learn_symbol(table[pos].sym, table[pos].len); + pos++; ++ } else { ++ free(table[i].sym); + } + } + table_cnt = pos; +diff --git a/security/apparmor/label.c b/security/apparmor/label.c +index c5b99b954580..ea63710442ae 100644 +--- a/security/apparmor/label.c ++++ b/security/apparmor/label.c +@@ -1463,11 +1463,13 @@ static inline bool use_label_hname(struct aa_ns *ns, struct aa_label *label, + /* helper macro for snprint routines */ + #define update_for_len(total, len, size, str) \ + do { \ ++ size_t ulen = len; \ ++ \ + AA_BUG(len < 0); \ +- total += len; \ +- len = min(len, size); \ +- size -= len; \ +- str += len; \ ++ total += ulen; \ ++ ulen = min(ulen, size); \ ++ size -= ulen; \ ++ str += ulen; \ + } while (0) + + /** +@@ -1602,7 +1604,7 @@ int aa_label_snxprint(char *str, size_t size, struct aa_ns *ns, + struct aa_ns *prev_ns = NULL; + struct label_it i; + int count = 0, total = 0; +- size_t len; ++ ssize_t len; + + AA_BUG(!str && size != 0); + AA_BUG(!label); +diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c +index 8fcb421193e0..fa261b27d858 100644 +--- a/sound/pci/hda/hda_controller.c ++++ b/sound/pci/hda/hda_controller.c +@@ -883,7 +883,7 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr, + return -EAGAIN; /* give a chance to retry */ + } + +- dev_WARN(chip->card->dev, ++ dev_err(chip->card->dev, + "azx_get_response timeout, switching to single_cmd mode: last cmd=0x%08x\n", + bus->last_cmd[addr]); + chip->single_cmd = 1; +diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c +index 76789523429a..09c4380bc225 100644 +--- a/tools/perf/builtin-script.c ++++ b/tools/perf/builtin-script.c +@@ -355,7 +355,7 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel, + "selected. Hence, no address to lookup the source line number.\n"); + return -EINVAL; + } +- if (PRINT_FIELD(BRSTACKINSN) && ++ if (PRINT_FIELD(BRSTACKINSN) && !allow_user_set && + !(perf_evlist__combined_branch_type(session->evlist) & + PERF_SAMPLE_BRANCH_ANY)) { + pr_err("Display of branch stack assembler requested, but non all-branch filter set\n" +diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h +index c9319f8d17a6..f732e3af2bd4 100644 +--- a/tools/perf/util/perf_regs.h ++++ b/tools/perf/util/perf_regs.h +@@ -34,7 +34,7 @@ int perf_reg_value(u64 *valp, struct regs_dump *regs, int id); + + static inline const char *perf_reg_name(int id __maybe_unused) + { +- return NULL; ++ return "unknown"; + } + + static inline int perf_reg_value(u64 *valp __maybe_unused, +diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c +index 9005fbe0780e..23092fd6451d 100644 +--- a/tools/perf/util/strbuf.c ++++ b/tools/perf/util/strbuf.c +@@ -109,7 +109,6 @@ static int strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap) + return ret; + } + len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved); +- va_end(ap_saved); + if (len > strbuf_avail(sb)) { + pr_debug("this should not happen, your vsnprintf is broken"); + va_end(ap_saved); diff --git a/patch/kernel/s5p6818-legacy/0001-aufs4.14-20181119.patch b/patch/kernel/s5p6818-legacy/0001-aufs4.14-20190902.patch similarity index 98% rename from patch/kernel/s5p6818-legacy/0001-aufs4.14-20181119.patch rename to patch/kernel/s5p6818-legacy/0001-aufs4.14-20190902.patch index c8f021a476..8e10b67207 100644 --- a/patch/kernel/s5p6818-legacy/0001-aufs4.14-20181119.patch +++ b/patch/kernel/s5p6818-legacy/0001-aufs4.14-20190902.patch @@ -1,6 +1,6 @@ diff --git a/Documentation/ABI/testing/debugfs-aufs b/Documentation/ABI/testing/debugfs-aufs new file mode 100644 -index 00000000..4a669419 +index 000000000..4a6694194 --- /dev/null +++ b/Documentation/ABI/testing/debugfs-aufs @@ -0,0 +1,55 @@ @@ -61,7 +61,7 @@ index 00000000..4a669419 + will be empty. About XINO files, see the aufs manual. diff --git a/Documentation/ABI/testing/sysfs-aufs b/Documentation/ABI/testing/sysfs-aufs new file mode 100644 -index 00000000..82f95184 +index 000000000..82f951849 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-aufs @@ -0,0 +1,31 @@ @@ -98,10 +98,10 @@ index 00000000..82f95184 + will be empty. About XINO files, see the aufs manual. diff --git a/Documentation/filesystems/aufs/README b/Documentation/filesystems/aufs/README new file mode 100644 -index 00000000..fb05e3b7 +index 000000000..029c3e5df --- /dev/null +++ b/Documentation/filesystems/aufs/README -@@ -0,0 +1,395 @@ +@@ -0,0 +1,402 @@ + +Aufs4 -- advanced multi layered unification filesystem version 4.x +http://aufs.sf.net @@ -356,6 +356,13 @@ index 00000000..fb05e3b7 + Supports a nested loopback mount in a branch-fs. This patch is + unnecessary until aufs produces a message like "you may want to try + another patch for loopback file". ++- proc_mounts.patch ++ When there are many mountpoints and many mount(2)/umount(2) are ++ running, then /proc/mounts may not show the all mountpoints. This ++ patch makes /proc/mounts always show the full mountpoints list. ++ If you don't want to apply this patch and meet such problem, then you ++ need to increase the value of 'ProcMounts_Times' make-variable in ++ aufs-util.git as a second best solution. +- vfs-ino.patch + Modifies a system global kernel internal function get_next_ino() in + order to stop assigning 0 for an inode-number. Not directly related to @@ -499,12 +506,12 @@ index 00000000..fb05e3b7 +# End: ; diff --git a/Documentation/filesystems/aufs/design/01intro.txt b/Documentation/filesystems/aufs/design/01intro.txt new file mode 100644 -index 00000000..aa105298 +index 000000000..609bf0e9b --- /dev/null +++ b/Documentation/filesystems/aufs/design/01intro.txt @@ -0,0 +1,171 @@ + -+# Copyright (C) 2005-2018 Junjiro R. Okajima ++# Copyright (C) 2005-2019 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -676,12 +683,12 @@ index 00000000..aa105298 +about it. But currently I have implemented it in kernel space. diff --git a/Documentation/filesystems/aufs/design/02struct.txt b/Documentation/filesystems/aufs/design/02struct.txt new file mode 100644 -index 00000000..f5fb6a8a +index 000000000..2467788c7 --- /dev/null +++ b/Documentation/filesystems/aufs/design/02struct.txt @@ -0,0 +1,258 @@ + -+# Copyright (C) 2005-2018 Junjiro R. Okajima ++# Copyright (C) 2005-2019 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -940,12 +947,12 @@ index 00000000..f5fb6a8a +For this purpose, use "aumvdown" command in aufs-util.git. diff --git a/Documentation/filesystems/aufs/design/03atomic_open.txt b/Documentation/filesystems/aufs/design/03atomic_open.txt new file mode 100644 -index 00000000..1b0699f8 +index 000000000..9f16ac1e0 --- /dev/null +++ b/Documentation/filesystems/aufs/design/03atomic_open.txt @@ -0,0 +1,85 @@ + -+# Copyright (C) 2015-2018 Junjiro R. Okajima ++# Copyright (C) 2015-2019 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -1031,12 +1038,12 @@ index 00000000..1b0699f8 + be implemented in aufs, but not all I am afraid. diff --git a/Documentation/filesystems/aufs/design/03lookup.txt b/Documentation/filesystems/aufs/design/03lookup.txt new file mode 100644 -index 00000000..80ae63bc +index 000000000..08b443d94 --- /dev/null +++ b/Documentation/filesystems/aufs/design/03lookup.txt @@ -0,0 +1,113 @@ + -+# Copyright (C) 2005-2018 Junjiro R. Okajima ++# Copyright (C) 2005-2019 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -1150,12 +1157,12 @@ index 00000000..80ae63bc + by over-mounting something (or another method). diff --git a/Documentation/filesystems/aufs/design/04branch.txt b/Documentation/filesystems/aufs/design/04branch.txt new file mode 100644 -index 00000000..0c128973 +index 000000000..3ab3682a4 --- /dev/null +++ b/Documentation/filesystems/aufs/design/04branch.txt @@ -0,0 +1,74 @@ + -+# Copyright (C) 2005-2018 Junjiro R. Okajima ++# Copyright (C) 2005-2019 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -1230,12 +1237,12 @@ index 00000000..0c128973 + same named entry on the upper branch. diff --git a/Documentation/filesystems/aufs/design/05wbr_policy.txt b/Documentation/filesystems/aufs/design/05wbr_policy.txt new file mode 100644 -index 00000000..cc5b7979 +index 000000000..1f9b86bc6 --- /dev/null +++ b/Documentation/filesystems/aufs/design/05wbr_policy.txt @@ -0,0 +1,64 @@ + -+# Copyright (C) 2005-2018 Junjiro R. Okajima ++# Copyright (C) 2005-2019 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -1300,7 +1307,7 @@ index 00000000..cc5b7979 + copyup policy. diff --git a/Documentation/filesystems/aufs/design/06dirren.dot b/Documentation/filesystems/aufs/design/06dirren.dot new file mode 100644 -index 00000000..2d62bb6d +index 000000000..2d62bb6dd --- /dev/null +++ b/Documentation/filesystems/aufs/design/06dirren.dot @@ -0,0 +1,31 @@ @@ -1337,12 +1344,12 @@ index 00000000..2d62bb6d +} diff --git a/Documentation/filesystems/aufs/design/06dirren.txt b/Documentation/filesystems/aufs/design/06dirren.txt new file mode 100644 -index 00000000..1f3cb86d +index 000000000..3b80f8659 --- /dev/null +++ b/Documentation/filesystems/aufs/design/06dirren.txt @@ -0,0 +1,102 @@ + -+# Copyright (C) 2017-2018 Junjiro R. Okajima ++# Copyright (C) 2017-2019 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -1445,12 +1452,12 @@ index 00000000..1f3cb86d +equivalen to udba=reval case. diff --git a/Documentation/filesystems/aufs/design/06fhsm.txt b/Documentation/filesystems/aufs/design/06fhsm.txt new file mode 100644 -index 00000000..ddfebecd +index 000000000..8b498d0af --- /dev/null +++ b/Documentation/filesystems/aufs/design/06fhsm.txt @@ -0,0 +1,120 @@ + -+# Copyright (C) 2011-2018 Junjiro R. Okajima ++# Copyright (C) 2011-2019 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -1571,12 +1578,12 @@ index 00000000..ddfebecd +should restore the original file state after an error happens. diff --git a/Documentation/filesystems/aufs/design/06mmap.txt b/Documentation/filesystems/aufs/design/06mmap.txt new file mode 100644 -index 00000000..9a0a096b +index 000000000..cdd84ea77 --- /dev/null +++ b/Documentation/filesystems/aufs/design/06mmap.txt @@ -0,0 +1,72 @@ + -+# Copyright (C) 2005-2018 Junjiro R. Okajima ++# Copyright (C) 2005-2019 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -1649,12 +1656,12 @@ index 00000000..9a0a096b +I have to give up this "looks-smater" approach. diff --git a/Documentation/filesystems/aufs/design/06xattr.txt b/Documentation/filesystems/aufs/design/06xattr.txt new file mode 100644 -index 00000000..be441e8d +index 000000000..edd7553f3 --- /dev/null +++ b/Documentation/filesystems/aufs/design/06xattr.txt @@ -0,0 +1,96 @@ + -+# Copyright (C) 2014-2018 Junjiro R. Okajima ++# Copyright (C) 2014-2019 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -1751,12 +1758,12 @@ index 00000000..be441e8d +now, aufs implements the branch attributes to ignore the error. diff --git a/Documentation/filesystems/aufs/design/07export.txt b/Documentation/filesystems/aufs/design/07export.txt new file mode 100644 -index 00000000..bb700cb1 +index 000000000..9b983f3dd --- /dev/null +++ b/Documentation/filesystems/aufs/design/07export.txt @@ -0,0 +1,58 @@ + -+# Copyright (C) 2005-2018 Junjiro R. Okajima ++# Copyright (C) 2005-2019 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -1815,12 +1822,12 @@ index 00000000..bb700cb1 + lookup_one_len(), vfs_getattr(), encode_fh() and others. diff --git a/Documentation/filesystems/aufs/design/08shwh.txt b/Documentation/filesystems/aufs/design/08shwh.txt new file mode 100644 -index 00000000..1dad573f +index 000000000..647a86a65 --- /dev/null +++ b/Documentation/filesystems/aufs/design/08shwh.txt @@ -0,0 +1,52 @@ + -+# Copyright (C) 2005-2018 Junjiro R. Okajima ++# Copyright (C) 2005-2019 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -1873,12 +1880,12 @@ index 00000000..1dad573f +initramfs will use it to replace the old one at the next boot. diff --git a/Documentation/filesystems/aufs/design/10dynop.txt b/Documentation/filesystems/aufs/design/10dynop.txt new file mode 100644 -index 00000000..710313c0 +index 000000000..13e8583f2 --- /dev/null +++ b/Documentation/filesystems/aufs/design/10dynop.txt @@ -0,0 +1,47 @@ + -+# Copyright (C) 2010-2018 Junjiro R. Okajima ++# Copyright (C) 2010-2019 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -1925,7 +1932,7 @@ index 00000000..710313c0 +Currently this approach is applied to address_space_operations for +regular files only. diff --git a/MAINTAINERS b/MAINTAINERS -index 546beb6b..c413f03f 100644 +index 029f96c43..4b98496c4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2465,6 +2465,19 @@ F: include/linux/audit.h @@ -1934,8 +1941,8 @@ index 546beb6b..c413f03f 100644 +AUFS (advanced multi layered unification filesystem) FILESYSTEM +M: "J. R. Okajima" -+L: linux-unionfs@vger.kernel.org +L: aufs-users@lists.sourceforge.net (members only) ++L: linux-unionfs@vger.kernel.org +W: http://aufs.sourceforge.net +T: git://github.com/sfjro/aufs4-linux.git +S: Supported @@ -1949,10 +1956,10 @@ index 546beb6b..c413f03f 100644 M: Miguel Ojeda Sandonis W: http://miguelojeda.es/auxdisplay.htm diff --git a/drivers/block/loop.c b/drivers/block/loop.c -index 6d61633a..1d92600c 100644 +index 453e3728e..023376f3b 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c -@@ -710,6 +710,24 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, +@@ -720,6 +720,24 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, return error; } @@ -1978,7 +1985,7 @@ index 6d61633a..1d92600c 100644 static ssize_t loop_attr_show(struct device *dev, char *page, diff --git a/fs/Kconfig b/fs/Kconfig -index 7aee6d69..ec920312 100644 +index 7aee6d699..ec9203120 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -248,6 +248,7 @@ source "fs/pstore/Kconfig" @@ -1990,7 +1997,7 @@ index 7aee6d69..ec920312 100644 endif # MISC_FILESYSTEMS diff --git a/fs/Makefile b/fs/Makefile -index ef772f1e..51779e68 100644 +index ef772f1ea..51779e68c 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -129,3 +129,4 @@ obj-y += exofs/ # Multiple modules @@ -2000,7 +2007,7 @@ index ef772f1e..51779e68 100644 +obj-$(CONFIG_AUFS_FS) += aufs/ diff --git a/fs/aufs/Kconfig b/fs/aufs/Kconfig new file mode 100644 -index 00000000..9f436425 +index 000000000..9f4364257 --- /dev/null +++ b/fs/aufs/Kconfig @@ -0,0 +1,199 @@ @@ -2205,7 +2212,7 @@ index 00000000..9f436425 +endif diff --git a/fs/aufs/Makefile b/fs/aufs/Makefile new file mode 100644 -index 00000000..2c819a64 +index 000000000..2c819a649 --- /dev/null +++ b/fs/aufs/Makefile @@ -0,0 +1,46 @@ @@ -2257,13 +2264,13 @@ index 00000000..2c819a64 +aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o diff --git a/fs/aufs/aufs.h b/fs/aufs/aufs.h new file mode 100644 -index 00000000..24569174 +index 000000000..a62a85211 --- /dev/null +++ b/fs/aufs/aufs.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -2325,13 +2332,13 @@ index 00000000..24569174 +#endif /* __AUFS_H__ */ diff --git a/fs/aufs/branch.c b/fs/aufs/branch.c new file mode 100644 -index 00000000..2fc6dc1e +index 000000000..598cf370a --- /dev/null +++ b/fs/aufs/branch.c @@ -0,0 +1,1422 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -2384,7 +2391,7 @@ index 00000000..2fc6dc1e + + if (br->br_fhsm) { + au_br_fhsm_fin(br->br_fhsm); -+ kfree(br->br_fhsm); ++ au_kfree_try_rcu(br->br_fhsm); + } + + key = br->br_dykey; @@ -2399,12 +2406,12 @@ index 00000000..2fc6dc1e + lockdep_off(); + path_put(&br->br_path); + lockdep_on(); -+ kfree(wbr); ++ au_kfree_rcu(wbr); + au_lcnt_wait_for_fin(&br->br_nfiles); + au_lcnt_wait_for_fin(&br->br_count); + /* I don't know why, but percpu_refcount requires this */ + /* synchronize_rcu(); */ -+ kfree(br); ++ au_kfree_rcu(br); +} + +/* @@ -2505,13 +2512,13 @@ index 00000000..2fc6dc1e + return add_branch; /* success */ + +out_wbr: -+ kfree(add_branch->br_wbr); ++ au_kfree_rcu(add_branch->br_wbr); +out_hnotify: + au_hnotify_fin_br(add_branch); +out_xino: + au_xino_put(add_branch); +out_br: -+ kfree(add_branch); ++ au_kfree_rcu(add_branch); +out: + return ERR_PTR(err); +} @@ -2677,7 +2684,7 @@ index 00000000..2fc6dc1e + br->br_perm = old_perm; + + if (!err && wbr && !au_br_writable(new_perm)) { -+ kfree(wbr); ++ au_kfree_rcu(wbr); + br->br_wbr = NULL; + } + @@ -3704,7 +3711,7 @@ index 00000000..2fc6dc1e + if (br->br_wbr) { + err = au_wbr_init(br, sb, mod->perm); + if (unlikely(err)) { -+ kfree(br->br_wbr); ++ au_kfree_rcu(br->br_wbr); + br->br_wbr = NULL; + } + } @@ -3716,7 +3723,7 @@ index 00000000..2fc6dc1e + if (!au_br_fhsm(mod->perm)) { + /* fhsm --> non-fhsm */ + au_br_fhsm_fin(br->br_fhsm); -+ kfree(br->br_fhsm); ++ au_kfree_rcu(br->br_fhsm); + br->br_fhsm = NULL; + } + } else if (au_br_fhsm(mod->perm)) @@ -3728,7 +3735,7 @@ index 00000000..2fc6dc1e + goto out; /* success */ + +out_bf: -+ kfree(bf); ++ au_kfree_try_rcu(bf); +out: + AuTraceErr(err); + return err; @@ -3753,13 +3760,13 @@ index 00000000..2fc6dc1e +} diff --git a/fs/aufs/branch.h b/fs/aufs/branch.h new file mode 100644 -index 00000000..3a551cec +index 000000000..012459ad5 --- /dev/null +++ b/fs/aufs/branch.h -@@ -0,0 +1,365 @@ +@@ -0,0 +1,366 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -3984,7 +3991,8 @@ index 00000000..3a551cec +static const loff_t au_loff_max = LLONG_MAX; + +aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry); -+struct file *au_xino_create(struct super_block *sb, char *fpath, int silent); ++struct file *au_xino_create(struct super_block *sb, char *fpath, int silent, ++ int wbrtop); +struct file *au_xino_create2(struct super_block *sb, struct path *base, + struct file *copy_src); +struct au_xi_new { @@ -4124,7 +4132,7 @@ index 00000000..3a551cec +#endif /* __AUFS_BRANCH_H__ */ diff --git a/fs/aufs/conf.mk b/fs/aufs/conf.mk new file mode 100644 -index 00000000..12782f8e +index 000000000..12782f8e0 --- /dev/null +++ b/fs/aufs/conf.mk @@ -0,0 +1,40 @@ @@ -4170,13 +4178,13 @@ index 00000000..12782f8e +-include ${srctree}/${src}/conf_priv.mk diff --git a/fs/aufs/cpup.c b/fs/aufs/cpup.c new file mode 100644 -index 00000000..f094f7e6 +index 000000000..8fdaf6329 --- /dev/null +++ b/fs/aufs/cpup.c -@@ -0,0 +1,1446 @@ +@@ -0,0 +1,1449 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -4513,9 +4521,11 @@ index 00000000..f094f7e6 + unsigned long blksize; + unsigned char do_kfree; + char *buf; ++ struct super_block *h_sb; + + err = -ENOMEM; -+ blksize = dst->f_path.dentry->d_sb->s_blocksize; ++ h_sb = file_inode(dst)->i_sb; ++ blksize = h_sb->s_blocksize; + if (!blksize || PAGE_SIZE < blksize) + blksize = PAGE_SIZE; + AuDbg("blksize %lu\n", blksize); @@ -4533,9 +4543,10 @@ index 00000000..f094f7e6 + src->f_pos = 0; + dst->f_pos = 0; + err = au_do_copy_file(dst, src, len, buf, blksize); -+ if (do_kfree) -+ kfree(buf); -+ else ++ if (do_kfree) { ++ AuDebugOn(!au_kfree_do_sz_test(blksize)); ++ au_kfree_do_rcu(buf); ++ } else + free_page((unsigned long)buf); + +out: @@ -5129,7 +5140,7 @@ index 00000000..f094f7e6 + } +out_parent: + dput(dst_parent); -+ kfree(a); ++ au_kfree_rcu(a); +out: + return err; +} @@ -5622,13 +5633,13 @@ index 00000000..f094f7e6 +} diff --git a/fs/aufs/cpup.h b/fs/aufs/cpup.h new file mode 100644 -index 00000000..ce764a09 +index 000000000..c932e6b60 --- /dev/null +++ b/fs/aufs/cpup.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -5728,13 +5739,13 @@ index 00000000..ce764a09 +#endif /* __AUFS_CPUP_H__ */ diff --git a/fs/aufs/dbgaufs.c b/fs/aufs/dbgaufs.c new file mode 100644 -index 00000000..13872925 +index 000000000..e32d91d1f --- /dev/null +++ b/fs/aufs/dbgaufs.c -@@ -0,0 +1,519 @@ +@@ -0,0 +1,526 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -5776,7 +5787,14 @@ index 00000000..13872925 +static int dbgaufs_xi_release(struct inode *inode __maybe_unused, + struct file *file) +{ -+ kfree(file->private_data); ++ void *p; ++ ++ p = file->private_data; ++ if (p) { ++ /* this is struct dbgaufs_arg */ ++ AuDebugOn(!au_kfree_sz_test(p)); ++ au_kfree_do_rcu(p); ++ } + return 0; +} + @@ -6253,13 +6271,13 @@ index 00000000..13872925 +} diff --git a/fs/aufs/dbgaufs.h b/fs/aufs/dbgaufs.h new file mode 100644 -index 00000000..59d7b9d0 +index 000000000..1ea241bf0 --- /dev/null +++ b/fs/aufs/dbgaufs.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -6312,13 +6330,13 @@ index 00000000..59d7b9d0 +#endif /* __DBGAUFS_H__ */ diff --git a/fs/aufs/dcsub.c b/fs/aufs/dcsub.c new file mode 100644 -index 00000000..c850ed1a +index 000000000..ec5e2bbac --- /dev/null +++ b/fs/aufs/dcsub.c @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -6371,7 +6389,7 @@ index 00000000..c850ed1a + return 0; /* success */ + +out_dpages: -+ kfree(dpages->dpages); ++ au_kfree_try_rcu(dpages->dpages); +out: + return err; +} @@ -6384,7 +6402,7 @@ index 00000000..c850ed1a + p = dpages->dpages; + for (i = 0; i < dpages->ndpage; i++) + au_dpage_free(p++); -+ kfree(dpages->dpages); ++ au_kfree_try_rcu(dpages->dpages); +} + +static int au_dpages_append(struct au_dcsub_pages *dpages, @@ -6544,13 +6562,13 @@ index 00000000..c850ed1a +} diff --git a/fs/aufs/dcsub.h b/fs/aufs/dcsub.h new file mode 100644 -index 00000000..c610133d +index 000000000..5e578995c --- /dev/null +++ b/fs/aufs/dcsub.h @@ -0,0 +1,137 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -6687,13 +6705,13 @@ index 00000000..c610133d +#endif /* __AUFS_DCSUB_H__ */ diff --git a/fs/aufs/debug.c b/fs/aufs/debug.c new file mode 100644 -index 00000000..f1074919 +index 000000000..e8b122e35 --- /dev/null +++ b/fs/aufs/debug.c @@ -0,0 +1,440 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -7029,7 +7047,7 @@ index 00000000..f1074919 + a->mnt.mnt_sb = sb; + a->fake.br_path.mnt = &a->mnt; + err = do_pri_br(-1, &a->fake); -+ kfree(a); ++ au_kfree_rcu(a); + dpri("dev 0x%x\n", sb->s_dev); + if (err || !au_test_aufs(sb)) + return; @@ -7133,13 +7151,13 @@ index 00000000..f1074919 +} diff --git a/fs/aufs/debug.h b/fs/aufs/debug.h new file mode 100644 -index 00000000..b80bb5a9 +index 000000000..9c52470a6 --- /dev/null +++ b/fs/aufs/debug.h @@ -0,0 +1,226 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -7365,13 +7383,13 @@ index 00000000..b80bb5a9 +#endif /* __AUFS_DEBUG_H__ */ diff --git a/fs/aufs/dentry.c b/fs/aufs/dentry.c new file mode 100644 -index 00000000..2ee5c296 +index 000000000..55bb0dad2 --- /dev/null +++ b/fs/aufs/dentry.c @@ -0,0 +1,1153 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -7605,7 +7623,7 @@ index 00000000..2ee5c296 + +out_parent: + dput(parent); -+ kfree(args.whname.name); ++ au_kfree_try_rcu(args.whname.name); + if (dirren) + au_dr_lkup_fin(&args); +out: @@ -8524,13 +8542,13 @@ index 00000000..2ee5c296 +}; diff --git a/fs/aufs/dentry.h b/fs/aufs/dentry.h new file mode 100644 -index 00000000..adc2ac99 +index 000000000..3b443fc7e --- /dev/null +++ b/fs/aufs/dentry.h -@@ -0,0 +1,267 @@ +@@ -0,0 +1,268 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -8571,6 +8589,7 @@ index 00000000..adc2ac99 + aufs_bindex_t di_btop, di_bbot, di_bwh, di_bdiropq; + unsigned char di_tmpfile; /* to allow the different name */ + struct au_hdentry *di_hdentry; ++ struct rcu_head rcu; +} ____cacheline_aligned_in_smp; + +/* ---------------------------------------------------------------------- */ @@ -8797,13 +8816,13 @@ index 00000000..adc2ac99 +#endif /* __AUFS_DENTRY_H__ */ diff --git a/fs/aufs/dinfo.c b/fs/aufs/dinfo.c new file mode 100644 -index 00000000..7e56fe74 +index 000000000..86140548f --- /dev/null +++ b/fs/aufs/dinfo.c @@ -0,0 +1,554 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -8877,7 +8896,7 @@ index 00000000..7e56fe74 + while (bindex++ <= bbot) + au_hdput(p++); + } -+ kfree(dinfo->di_hdentry); ++ au_kfree_try_rcu(dinfo->di_hdentry); + au_cache_free_dinfo(dinfo); +} + @@ -9357,13 +9376,13 @@ index 00000000..7e56fe74 +} diff --git a/fs/aufs/dir.c b/fs/aufs/dir.c new file mode 100644 -index 00000000..af2c0640 +index 000000000..ab117dfd4 --- /dev/null +++ b/fs/aufs/dir.c @@ -0,0 +1,762 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -9520,7 +9539,7 @@ index 00000000..af2c0640 +out: + dput(a->dentry); + au_nwt_done(&au_sbi(sb)->si_nowait); -+ kfree(arg); ++ au_kfree_try_rcu(arg); +} + +void au_dir_ts(struct inode *dir, aufs_bindex_t bindex) @@ -9556,7 +9575,7 @@ index 00000000..af2c0640 + if (unlikely(wkq_err)) { + pr_err("wkq %d\n", wkq_err); + dput(dentry); -+ kfree(arg); ++ au_kfree_try_rcu(arg); + } + +out: @@ -9675,7 +9694,7 @@ index 00000000..af2c0640 + }; + err = au_do_open(file, &args); + if (unlikely(err)) -+ kfree(fidir); ++ au_kfree_rcu(fidir); + } + si_read_unlock(sb); + return err; @@ -9711,7 +9730,7 @@ index 00000000..af2c0640 + if (hf->hf_file) + au_hfput(hf, /*execed*/0); + } -+ kfree(fidir); ++ au_kfree_rcu(fidir); + finfo->fi_hdir = NULL; + } + au_finfo_fin(file); @@ -10125,13 +10144,13 @@ index 00000000..af2c0640 +}; diff --git a/fs/aufs/dir.h b/fs/aufs/dir.h new file mode 100644 -index 00000000..ce6b9091 +index 000000000..ff578fc5e --- /dev/null +++ b/fs/aufs/dir.h -@@ -0,0 +1,132 @@ +@@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -10175,6 +10194,7 @@ index 00000000..ce6b9091 +struct au_vdir_dehstr { + struct hlist_node hash; + struct au_vdir_destr *str; ++ struct rcu_head rcu; +} ____cacheline_aligned_in_smp; + +struct au_vdir_de { @@ -10212,7 +10232,8 @@ index 00000000..ce6b9091 + + unsigned long vd_version; + unsigned int vd_deblk_sz; -+ unsigned long vd_jiffy; ++ unsigned long vd_jiffy; ++ struct rcu_head rcu; +} ____cacheline_aligned_in_smp; + +/* ---------------------------------------------------------------------- */ @@ -10263,13 +10284,13 @@ index 00000000..ce6b9091 +#endif /* __AUFS_DIR_H__ */ diff --git a/fs/aufs/dirren.c b/fs/aufs/dirren.c new file mode 100644 -index 00000000..aa97c275 +index 000000000..0c19b9c73 --- /dev/null +++ b/fs/aufs/dirren.c @@ -0,0 +1,1316 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2017-2018 Junjiro R. Okajima ++ * Copyright (C) 2017-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -10387,7 +10408,7 @@ index 00000000..aa97c275 + hbl = dr->dr_h_ino + i; + /* no spinlock since sbinfo must be write-locked */ + hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode) -+ kfree(ent); ++ au_kfree_rcu(ent); + INIT_HLIST_BL_HEAD(hbl); + } +} @@ -10829,7 +10850,7 @@ index 00000000..aa97c275 + *ret = *drinfo; + ssz = vfsub_read_k(file, (void *)ret->oldname, len, &pos); + if (unlikely(ssz != len)) { -+ kfree(ret); ++ au_kfree_rcu(ret); + ret = ERR_PTR(-EIO); + AuIOErr("ssz %zd, %u, %pD2\n", ssz, len, file); + goto out; @@ -11025,7 +11046,7 @@ index 00000000..aa97c275 + +static void au_drinfo_store_work_fin(struct au_drinfo_store *w) +{ -+ kfree(w->fdata); ++ au_kfree_rcu(w->fdata); +} + +static void au_drinfo_store_rev(struct au_drinfo_rev *rev, @@ -11062,7 +11083,7 @@ index 00000000..aa97c275 + elm->info_last->oldname, + elm->info_last->oldnamelen); + err = au_drinfo_store_sio(w, /*elm*/NULL); -+ kfree(elm->info_last); ++ au_kfree_rcu(elm->info_last); + } + if (unlikely(err)) + AuIOErr("%d, %s\n", err, w->whname); @@ -11138,7 +11159,7 @@ index 00000000..aa97c275 + if (unlikely(err)) { + /* revert all drinfo */ + au_drinfo_store_rev(rev, &work); -+ kfree(rev); ++ au_kfree_try_rcu(rev); + *p = NULL; + } + au_hn_inode_unlock(hdir); @@ -11194,7 +11215,7 @@ index 00000000..aa97c275 + /* revert */ + if (!already) + au_dr_hino_del(dr, ent); -+ kfree(ent); ++ au_kfree_rcu(ent); + +out: + AuTraceErr(err); @@ -11211,9 +11232,9 @@ index 00000000..aa97c275 + elm = rev->elm; + for (nelm = rev->nelm; nelm > 0; nelm--, elm++) { + dput(elm->info_dentry); -+ kfree(elm->info_last); ++ au_kfree_rcu(elm->info_last); + } -+ kfree(rev); ++ au_kfree_try_rcu(rev); +} + +void au_dr_rename_rev(struct dentry *src, aufs_bindex_t btgt, void *_rev) @@ -11245,10 +11266,10 @@ index 00000000..aa97c275 + ent = au_dr_hino_find(dr, h_inode->i_ino); + BUG_ON(!ent); + au_dr_hino_del(dr, ent); -+ kfree(ent); ++ au_kfree_rcu(ent); + +out: -+ kfree(rev); ++ au_kfree_try_rcu(rev); + if (unlikely(err)) + pr_err("failed to remove dirren info\n"); +} @@ -11373,7 +11394,7 @@ index 00000000..aa97c275 + oldname.name = drinfo->oldname; + if (au_qstreq(w->qname, &oldname)) { + /* the name is renamed back */ -+ kfree(drinfo); ++ au_kfree_rcu(drinfo); + drinfo = NULL; + + infopath.dentry = info_dentry; @@ -11388,7 +11409,7 @@ index 00000000..aa97c275 + if (unlikely(e == -EWOULDBLOCK)) + iput(delegated); + } -+ kfree(w->drinfo[bindex]); ++ au_kfree_rcu(w->drinfo[bindex]); + w->drinfo[bindex] = drinfo; + dput(info_dentry); + @@ -11404,8 +11425,8 @@ index 00000000..aa97c275 + struct au_drinfo **p = drinfo; + + while (n-- > 0) -+ kfree(*drinfo++); -+ kfree(p); ++ au_kfree_rcu(*drinfo++); ++ au_kfree_try_rcu(p); +} + +int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry, @@ -11458,7 +11479,7 @@ index 00000000..aa97c275 + ent = au_dr_hino_find(&br->br_dirren, h_dir->i_ino); + AuDebugOn(!ent); + au_dr_hino_del(&br->br_dirren, ent); -+ kfree(ent); ++ au_kfree_rcu(ent); + } + goto out; /* success */ + @@ -11489,7 +11510,7 @@ index 00000000..aa97c275 + if (!drinfo) + goto out; + -+ kfree(lkup->whname.name); ++ au_kfree_try_rcu(lkup->whname.name); + lkup->whname.name = NULL; + lkup->dirren.dr_name.len = drinfo->oldnamelen; + lkup->dirren.dr_name.name = drinfo->oldname; @@ -11585,13 +11606,13 @@ index 00000000..aa97c275 +} diff --git a/fs/aufs/dirren.h b/fs/aufs/dirren.h new file mode 100644 -index 00000000..f5139a30 +index 000000000..a98673646 --- /dev/null +++ b/fs/aufs/dirren.h @@ -0,0 +1,140 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2017-2018 Junjiro R. Okajima ++ * Copyright (C) 2017-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -11731,13 +11752,13 @@ index 00000000..f5139a30 +#endif /* __AUFS_DIRREN_H__ */ diff --git a/fs/aufs/dynop.c b/fs/aufs/dynop.c new file mode 100644 -index 00000000..f2ff9f3a +index 000000000..7c7d8432d --- /dev/null +++ b/fs/aufs/dynop.c @@ -0,0 +1,370 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2010-2018 Junjiro R. Okajima ++ * Copyright (C) 2010-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -11777,8 +11798,8 @@ index 00000000..f2ff9f3a + hlist_bl_lock(hbl); + hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode) + if (tmp->dk_op.dy_hop == h_op) { -+ key = tmp; -+ kref_get(&key->dk_kref); ++ if (kref_get_unless_zero(&tmp->dk_kref)) ++ key = tmp; + break; + } + hlist_bl_unlock(hbl); @@ -11832,8 +11853,8 @@ index 00000000..f2ff9f3a + hlist_bl_lock(hbl); + hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode) + if (tmp->dk_op.dy_hop == h_op) { -+ kref_get(&tmp->dk_kref); -+ found = tmp; ++ if (kref_get_unless_zero(&tmp->dk_kref)) ++ found = tmp; + break; + } + if (!found) @@ -11979,7 +12000,7 @@ index 00000000..f2ff9f3a + p->set(key, op->dy_hop, au_br_sb(br)); + old = dy_gadd(hbl, key); + if (old) { -+ kfree(key); ++ au_kfree_rcu(key); + key = old; + } + @@ -12107,13 +12128,13 @@ index 00000000..f2ff9f3a +} diff --git a/fs/aufs/dynop.h b/fs/aufs/dynop.h new file mode 100644 -index 00000000..d4015351 +index 000000000..f3301c2a6 --- /dev/null +++ b/fs/aufs/dynop.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2010-2018 Junjiro R. Okajima ++ * Copyright (C) 2010-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -12188,13 +12209,13 @@ index 00000000..d4015351 +#endif /* __AUFS_DYNOP_H__ */ diff --git a/fs/aufs/export.c b/fs/aufs/export.c new file mode 100644 -index 00000000..0358fbec +index 000000000..1da2ca0a9 --- /dev/null +++ b/fs/aufs/export.c @@ -0,0 +1,838 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -13032,13 +13053,13 @@ index 00000000..0358fbec +} diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c new file mode 100644 -index 00000000..0733ae8a +index 000000000..5254b5cd3 --- /dev/null +++ b/fs/aufs/f_op.c @@ -0,0 +1,819 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -13857,13 +13878,13 @@ index 00000000..0733ae8a +}; diff --git a/fs/aufs/fhsm.c b/fs/aufs/fhsm.c new file mode 100644 -index 00000000..79a328e0 +index 000000000..d5fca9596 --- /dev/null +++ b/fs/aufs/fhsm.c @@ -0,0 +1,428 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2011-2018 Junjiro R. Okajima ++ * Copyright (C) 2011-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -14291,13 +14312,13 @@ index 00000000..79a328e0 +} diff --git a/fs/aufs/file.c b/fs/aufs/file.c new file mode 100644 -index 00000000..c01b9879 +index 000000000..dbb33855d --- /dev/null +++ b/fs/aufs/file.c @@ -0,0 +1,863 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -15160,13 +15181,13 @@ index 00000000..c01b9879 +}; diff --git a/fs/aufs/file.h b/fs/aufs/file.h new file mode 100644 -index 00000000..b6a10058 +index 000000000..4ee95dde0 --- /dev/null +++ b/fs/aufs/file.h -@@ -0,0 +1,341 @@ +@@ -0,0 +1,342 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -15232,6 +15253,7 @@ index 00000000..b6a10058 + + struct hlist_bl_node fi_hlist; + struct file *fi_file; /* very ugly */ ++ struct rcu_head rcu; +} ____cacheline_aligned_in_smp; + +/* ---------------------------------------------------------------------- */ @@ -15507,13 +15529,13 @@ index 00000000..b6a10058 +#endif /* __AUFS_FILE_H__ */ diff --git a/fs/aufs/finfo.c b/fs/aufs/finfo.c new file mode 100644 -index 00000000..44636ce6 +index 000000000..448c5e9cd --- /dev/null +++ b/fs/aufs/finfo.c @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -15662,13 +15684,13 @@ index 00000000..44636ce6 +} diff --git a/fs/aufs/fstype.h b/fs/aufs/fstype.h new file mode 100644 -index 00000000..5c9d5c83 +index 000000000..88cfefac7 --- /dev/null +++ b/fs/aufs/fstype.h @@ -0,0 +1,401 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -16069,13 +16091,13 @@ index 00000000..5c9d5c83 +#endif /* __AUFS_FSTYPE_H__ */ diff --git a/fs/aufs/hbl.h b/fs/aufs/hbl.h new file mode 100644 -index 00000000..265d7ab6 +index 000000000..6db65b16b --- /dev/null +++ b/fs/aufs/hbl.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2017-2018 Junjiro R. Okajima ++ * Copyright (C) 2017-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -16140,13 +16162,13 @@ index 00000000..265d7ab6 +#endif /* __AUFS_HBL_H__ */ diff --git a/fs/aufs/hfsnotify.c b/fs/aufs/hfsnotify.c new file mode 100644 -index 00000000..a0db252a +index 000000000..e92d73141 --- /dev/null +++ b/fs/aufs/hfsnotify.c @@ -0,0 +1,290 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -16303,7 +16325,7 @@ index 00000000..a0db252a + struct au_br_hfsnotify *hfsn = group->private; + + /* AuDbg("here\n"); */ -+ kfree(hfsn); ++ au_kfree_try_rcu(hfsn); +} + +static int au_hfsn_handle_event(struct fsnotify_group *group, @@ -16399,7 +16421,7 @@ index 00000000..a0db252a + goto out; /* success */ + +out_hfsn: -+ kfree(hfsn); ++ au_kfree_try_rcu(hfsn); +out: + return err; +} @@ -16436,13 +16458,13 @@ index 00000000..a0db252a +}; diff --git a/fs/aufs/hfsplus.c b/fs/aufs/hfsplus.c new file mode 100644 -index 00000000..b1f59970 +index 000000000..3bd869a69 --- /dev/null +++ b/fs/aufs/hfsplus.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2010-2018 Junjiro R. Okajima ++ * Copyright (C) 2010-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -16502,13 +16524,13 @@ index 00000000..b1f59970 +} diff --git a/fs/aufs/hnotify.c b/fs/aufs/hnotify.c new file mode 100644 -index 00000000..187a9750 +index 000000000..af35561f3 --- /dev/null +++ b/fs/aufs/hnotify.c @@ -0,0 +1,720 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -17049,7 +17071,7 @@ index 00000000..187a9750 + iput(a->dir); + si_write_unlock(sb); + au_nwt_done(&sbinfo->si_nowait); -+ kfree(a); ++ au_kfree_rcu(a); +} + +/* ---------------------------------------------------------------------- */ @@ -17155,7 +17177,7 @@ index 00000000..187a9750 + iput(args->h_child_inode); + iput(args->h_dir); + iput(args->dir); -+ kfree(args); ++ au_kfree_rcu(args); + } + +out: @@ -17228,13 +17250,13 @@ index 00000000..187a9750 +} diff --git a/fs/aufs/i_op.c b/fs/aufs/i_op.c new file mode 100644 -index 00000000..5a8131db +index 000000000..14cbe48ee --- /dev/null +++ b/fs/aufs/i_op.c @@ -0,0 +1,1508 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -18293,7 +18315,7 @@ index 00000000..5a8131db +out_si: + si_read_unlock(sb); +out_kfree: -+ kfree(a); ++ au_kfree_rcu(a); +out: + AuTraceErr(err); + return err; @@ -18384,7 +18406,7 @@ index 00000000..5a8131db + di_write_unlock(dentry); + si_read_unlock(sb); +out_kfree: -+ kfree(a); ++ au_kfree_rcu(a); +out: + AuTraceErr(err); + return err; @@ -18742,13 +18764,13 @@ index 00000000..5a8131db +}; diff --git a/fs/aufs/i_op_add.c b/fs/aufs/i_op_add.c new file mode 100644 -index 00000000..9ad5d523 +index 000000000..f8c0724c8 --- /dev/null +++ b/fs/aufs/i_op_add.c @@ -0,0 +1,934 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -19107,7 +19129,7 @@ index 00000000..9ad5d523 + if (!try_aopen) + aufs_read_unlock(dentry, AuLock_DW); +out_free: -+ kfree(a); ++ au_kfree_rcu(a); +out: + return err; +} @@ -19567,7 +19589,7 @@ index 00000000..9ad5d523 + } + aufs_read_and_write_unlock2(dentry, src_dentry); +out_kfree: -+ kfree(a); ++ au_kfree_rcu(a); +out: + AuTraceErr(err); + return err; @@ -19676,19 +19698,19 @@ index 00000000..9ad5d523 + } + aufs_read_unlock(dentry, AuLock_DW); +out_free: -+ kfree(a); ++ au_kfree_rcu(a); +out: + return err; +} diff --git a/fs/aufs/i_op_del.c b/fs/aufs/i_op_del.c new file mode 100644 -index 00000000..af85e999 +index 000000000..f4e2ef352 --- /dev/null +++ b/fs/aufs/i_op_del.c @@ -0,0 +1,512 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -20083,7 +20105,7 @@ index 00000000..af85e999 +out_unlock: + aufs_read_unlock(dentry, AuLock_DW); +out_free: -+ kfree(a); ++ au_kfree_rcu(a); +out: + return err; +} @@ -20193,20 +20215,20 @@ index 00000000..af85e999 +out_unlock: + aufs_read_unlock(dentry, AuLock_DW); +out_free: -+ kfree(a); ++ au_kfree_rcu(a); +out: + AuTraceErr(err); + return err; +} diff --git a/fs/aufs/i_op_ren.c b/fs/aufs/i_op_ren.c new file mode 100644 -index 00000000..5d9baeb7 +index 000000000..8524b0852 --- /dev/null +++ b/fs/aufs/i_op_ren.c @@ -0,0 +1,1249 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -21448,20 +21470,20 @@ index 00000000..5d9baeb7 + iput(a->dst_inode); + if (a->thargs) + au_whtmp_rmdir_free(a->thargs); -+ kfree(a); ++ au_kfree_rcu(a); +out: + AuTraceErr(err); + return err; +} diff --git a/fs/aufs/iinfo.c b/fs/aufs/iinfo.c new file mode 100644 -index 00000000..f6c512d9 +index 000000000..098fd1150 --- /dev/null +++ b/fs/aufs/iinfo.c @@ -0,0 +1,286 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -21742,18 +21764,18 @@ index 00000000..f6c512d9 + hi++; + } + } -+ kfree(iinfo->ii_hinode); ++ au_kfree_rcu(iinfo->ii_hinode); + AuRwDestroy(&iinfo->ii_rwsem); +} diff --git a/fs/aufs/inode.c b/fs/aufs/inode.c new file mode 100644 -index 00000000..af1092b7 +index 000000000..2db13c0aa --- /dev/null +++ b/fs/aufs/inode.c @@ -0,0 +1,528 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -22281,13 +22303,13 @@ index 00000000..af1092b7 +} diff --git a/fs/aufs/inode.h b/fs/aufs/inode.h new file mode 100644 -index 00000000..340d4908 +index 000000000..741b5b835 --- /dev/null +++ b/fs/aufs/inode.h -@@ -0,0 +1,696 @@ +@@ -0,0 +1,698 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -22324,6 +22346,7 @@ index 00000000..340d4908 + struct fsnotify_mark hn_mark; +#endif + struct inode *hn_aufs_inode; /* no get/put */ ++ struct rcu_head rcu; +#endif +} ____cacheline_aligned_in_smp; + @@ -22364,9 +22387,10 @@ index 00000000..340d4908 +}; + +struct au_icntnr { -+ struct au_iinfo iinfo; -+ struct inode vfs_inode; -+ struct hlist_bl_node plink; ++ struct au_iinfo iinfo; ++ struct inode vfs_inode; ++ struct hlist_bl_node plink; ++ struct rcu_head rcu; +} ____cacheline_aligned_in_smp; + +/* au_pin flags */ @@ -22983,13 +23007,13 @@ index 00000000..340d4908 +#endif /* __AUFS_INODE_H__ */ diff --git a/fs/aufs/ioctl.c b/fs/aufs/ioctl.c new file mode 100644 -index 00000000..279bd749 +index 000000000..fb2fb7582 --- /dev/null +++ b/fs/aufs/ioctl.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -23209,13 +23233,13 @@ index 00000000..279bd749 +#endif diff --git a/fs/aufs/lcnt.h b/fs/aufs/lcnt.h new file mode 100644 -index 00000000..5e089c93 +index 000000000..d8508f875 --- /dev/null +++ b/fs/aufs/lcnt.h @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2018 Junjiro R. Okajima ++ * Copyright (C) 2018-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -23401,13 +23425,13 @@ index 00000000..5e089c93 +#endif /* __AUFS_LCNT_H__ */ diff --git a/fs/aufs/loop.c b/fs/aufs/loop.c new file mode 100644 -index 00000000..0c6af623 +index 000000000..cef7d9636 --- /dev/null +++ b/fs/aufs/loop.c @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -23551,17 +23575,17 @@ index 00000000..0c6af623 +{ + if (backing_file_func) + symbol_put(loop_backing_file); -+ kfree(au_warn_loopback_array); ++ au_kfree_try_rcu(au_warn_loopback_array); +} diff --git a/fs/aufs/loop.h b/fs/aufs/loop.h new file mode 100644 -index 00000000..048a6504 +index 000000000..7fc394e72 --- /dev/null +++ b/fs/aufs/loop.h -@@ -0,0 +1,53 @@ +@@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -23601,6 +23625,8 @@ index 00000000..048a6504 +int au_loopback_init(void); +void au_loopback_fin(void); +#else ++AuStub(struct file *, loop_backing_file, return NULL, struct super_block *sb) ++ +AuStubInt0(au_test_loopback_overlap, struct super_block *sb, + struct dentry *h_adding) +AuStubInt0(au_test_loopback_kthread, void) @@ -23614,7 +23640,7 @@ index 00000000..048a6504 +#endif /* __AUFS_LOOP_H__ */ diff --git a/fs/aufs/magic.mk b/fs/aufs/magic.mk new file mode 100644 -index 00000000..7bc9eef3 +index 000000000..7bc9eef3f --- /dev/null +++ b/fs/aufs/magic.mk @@ -0,0 +1,31 @@ @@ -23651,13 +23677,13 @@ index 00000000..7bc9eef3 +endif diff --git a/fs/aufs/module.c b/fs/aufs/module.c new file mode 100644 -index 00000000..5f5f67e6 +index 000000000..295736adf --- /dev/null +++ b/fs/aufs/module.c @@ -0,0 +1,273 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -23692,7 +23718,7 @@ index 00000000..5f5f67e6 + if (p) { +#if 0 /* unused */ + if (!new_sz) { -+ kfree(p); ++ au_kfree_rcu(p); + p = NULL; + goto out; + } @@ -23716,7 +23742,7 @@ index 00000000..5f5f67e6 + if (q) { + if (p) { + memcpy(q, p, new_sz); -+ kfree(p); ++ au_kfree_try_rcu(p); + } + p = q; + } else @@ -23930,13 +23956,13 @@ index 00000000..5f5f67e6 +module_exit(aufs_exit); diff --git a/fs/aufs/module.h b/fs/aufs/module.h new file mode 100644 -index 00000000..00076104 +index 000000000..3036754b9 --- /dev/null +++ b/fs/aufs/module.h -@@ -0,0 +1,102 @@ +@@ -0,0 +1,166 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -23962,6 +23988,11 @@ index 00000000..00076104 +#ifdef __KERNEL__ + +#include ++#include "debug.h" ++#include "dentry.h" ++#include "dir.h" ++#include "file.h" ++#include "inode.h" + +struct path; +struct seq_file; @@ -23978,6 +24009,53 @@ index 00000000..00076104 +void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp, + int may_shrink); + ++/* ++ * Comparing the size of the object with sizeof(struct rcu_head) ++ * case 1: object is always larger ++ * --> au_kfree_rcu() or au_kfree_do_rcu() ++ * case 2: object is always smaller ++ * --> au_kfree_small() ++ * case 3: object can be any size ++ * --> au_kfree_try_rcu() ++ */ ++ ++static inline void au_kfree_do_rcu(const void *p) ++{ ++ struct { ++ struct rcu_head rcu; ++ } *a = (void *)p; ++ ++ kfree_rcu(a, rcu); ++} ++ ++#define au_kfree_rcu(_p) do { \ ++ typeof(_p) p = (_p); \ ++ BUILD_BUG_ON(sizeof(*p) < sizeof(struct rcu_head)); \ ++ if (p) \ ++ au_kfree_do_rcu(p); \ ++ } while (0) ++ ++#define au_kfree_do_sz_test(sz) (sz >= sizeof(struct rcu_head)) ++#define au_kfree_sz_test(p) (p && au_kfree_do_sz_test(ksize(p))) ++ ++static inline void au_kfree_try_rcu(const void *p) ++{ ++ if (!p) ++ return; ++ if (au_kfree_sz_test(p)) ++ au_kfree_do_rcu(p); ++ else ++ kfree(p); ++} ++ ++static inline void au_kfree_small(const void *p) ++{ ++ if (!p) ++ return; ++ AuDebugOn(au_kfree_sz_test(p)); ++ kfree(p); ++} ++ +static inline int au_kmidx_sub(size_t sz, size_t new_sz) +{ +#ifndef CONFIG_SLOB @@ -24019,11 +24097,23 @@ index 00000000..00076104 + kmem_cache_create(#type, sizeof(struct type), \ + __alignof__(struct type), AuCacheFlags, ctor) + -+#define AuCacheFuncs(name, index) \ -+static inline struct au_##name *au_cache_alloc_##name(void) \ -+{ return kmem_cache_alloc(au_cache[AuCache_##index], GFP_NOFS); } \ -+static inline void au_cache_free_##name(struct au_##name *p) \ -+{ kmem_cache_free(au_cache[AuCache_##index], p); } ++#define AuCacheFuncs(name, index) \ ++ static inline struct au_##name *au_cache_alloc_##name(void) \ ++ { return kmem_cache_alloc(au_cache[AuCache_##index], GFP_NOFS); } \ ++ static inline void au_cache_free_##name##_norcu(struct au_##name *p) \ ++ { kmem_cache_free(au_cache[AuCache_##index], p); } \ ++ \ ++ static inline void au_cache_free_##name##_rcu_cb(struct rcu_head *rcu) \ ++ { void *p = rcu; \ ++ p -= offsetof(struct au_##name, rcu); \ ++ kmem_cache_free(au_cache[AuCache_##index], p); } \ ++ static inline void au_cache_free_##name##_rcu(struct au_##name *p) \ ++ { BUILD_BUG_ON(sizeof(struct au_##name) < sizeof(struct rcu_head)); \ ++ call_rcu(&p->rcu, au_cache_free_##name##_rcu_cb); } \ ++ \ ++ static inline void au_cache_free_##name(struct au_##name *p) \ ++ { /* au_cache_free_##name##_norcu(p); */ \ ++ au_cache_free_##name##_rcu(p); } + +AuCacheFuncs(dinfo, DINFO); +AuCacheFuncs(icntnr, ICNTNR); @@ -24038,13 +24128,13 @@ index 00000000..00076104 +#endif /* __AUFS_MODULE_H__ */ diff --git a/fs/aufs/mvdown.c b/fs/aufs/mvdown.c new file mode 100644 -index 00000000..9603ef73 +index 000000000..59ce2d700 --- /dev/null +++ b/fs/aufs/mvdown.c @@ -0,0 +1,705 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2011-2018 Junjiro R. Okajima ++ * Copyright (C) 2011-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -24742,20 +24832,20 @@ index 00000000..9603ef73 + e = copy_to_user(uarg, &args->mvdown, sizeof(args->mvdown)); + if (unlikely(e)) + err = -EFAULT; -+ kfree(args); ++ au_kfree_rcu(args); +out: + AuTraceErr(err); + return err; +} diff --git a/fs/aufs/opts.c b/fs/aufs/opts.c new file mode 100644 -index 00000000..341f2a56 +index 000000000..1663e7901 --- /dev/null +++ b/fs/aufs/opts.c -@@ -0,0 +1,1877 @@ +@@ -0,0 +1,1880 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -25673,7 +25763,7 @@ index 00000000..341f2a56 + int err; + struct file *file; + -+ file = au_xino_create(sb, args[0].from, /*silent*/0); ++ file = au_xino_create(sb, args[0].from, /*silent*/0, /*wbrtop*/0); + err = PTR_ERR(file); + if (IS_ERR(file)) + goto out; @@ -26015,7 +26105,7 @@ index 00000000..341f2a56 + } + } + -+ kfree(a); ++ au_kfree_rcu(a); + dump_opts(opts); + if (unlikely(err)) + au_opts_free(opts); @@ -26141,6 +26231,7 @@ index 00000000..341f2a56 + case Opt_wsum: + au_opt_clr(sbinfo->si_mntflags, SUM); + au_opt_set(sbinfo->si_mntflags, SUM_W); ++ break; + case Opt_nosum: + au_opt_clr(sbinfo->si_mntflags, SUM); + au_opt_clr(sbinfo->si_mntflags, SUM_W); @@ -26266,8 +26357,10 @@ index 00000000..341f2a56 + if (opt->add.bindex < 0) + opt->add.bindex = 0; + goto add; ++ /* Always goto add, not fallthrough */ + case Opt_prepend: + opt->add.bindex = 0; ++ /* fallthrough */ + add: /* indented label */ + case Opt_add: + err = au_br_add(sb, &opt->add, @@ -26445,7 +26538,7 @@ index 00000000..341f2a56 + au_hn_inode_unlock(hdir); + + if (!err && do_free) { -+ kfree(wbr); ++ au_kfree_rcu(wbr); + br->br_wbr = NULL; + } + } @@ -26632,13 +26725,13 @@ index 00000000..341f2a56 +} diff --git a/fs/aufs/opts.h b/fs/aufs/opts.h new file mode 100644 -index 00000000..fd167bd0 +index 000000000..6326b5434 --- /dev/null +++ b/fs/aufs/opts.h @@ -0,0 +1,225 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -26684,7 +26777,7 @@ index 00000000..fd167bd0 +#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */ +#define AuOpt_SUM_W (1 << 11) /* unimplemented */ +#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */ -+#define AuOpt_VERBOSE (1 << 13) /* busy inode when del-branch */ ++#define AuOpt_VERBOSE (1 << 13) /* print the cause of error */ +#define AuOpt_DIO (1 << 14) /* direct io */ +#define AuOpt_DIRREN (1 << 15) /* directory rename */ + @@ -26863,13 +26956,13 @@ index 00000000..fd167bd0 +#endif /* __AUFS_OPTS_H__ */ diff --git a/fs/aufs/plink.c b/fs/aufs/plink.c new file mode 100644 -index 00000000..ef51ffa6 +index 000000000..8a3bf96b6 --- /dev/null +++ b/fs/aufs/plink.c @@ -0,0 +1,516 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -27385,13 +27478,13 @@ index 00000000..ef51ffa6 +} diff --git a/fs/aufs/poll.c b/fs/aufs/poll.c new file mode 100644 -index 00000000..82c859ce +index 000000000..d25202722 --- /dev/null +++ b/fs/aufs/poll.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -27445,13 +27538,13 @@ index 00000000..82c859ce +} diff --git a/fs/aufs/posix_acl.c b/fs/aufs/posix_acl.c new file mode 100644 -index 00000000..b851a3bb +index 000000000..64c504002 --- /dev/null +++ b/fs/aufs/posix_acl.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2014-2018 Junjiro R. Okajima ++ * Copyright (C) 2014-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -27554,13 +27647,13 @@ index 00000000..b851a3bb +} diff --git a/fs/aufs/procfs.c b/fs/aufs/procfs.c new file mode 100644 -index 00000000..100dbcfe +index 000000000..582dd486f --- /dev/null +++ b/fs/aufs/procfs.c @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2010-2018 Junjiro R. Okajima ++ * Copyright (C) 2010-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -27621,8 +27714,8 @@ index 00000000..100dbcfe + hlist_bl_lock(&au_sbilist); + hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list) + if (id == sysaufs_si_id(sbinfo)) { -+ kobject_get(&sbinfo->si_kobj); -+ sb = sbinfo->si_sb; ++ if (kobject_get_unless_zero(&sbinfo->si_kobj)) ++ sb = sbinfo->si_sb; + break; + } + hlist_bl_unlock(&au_sbilist); @@ -27731,13 +27824,13 @@ index 00000000..100dbcfe +} diff --git a/fs/aufs/rdu.c b/fs/aufs/rdu.c new file mode 100644 -index 00000000..60f4957b +index 000000000..bf0233a28 --- /dev/null +++ b/fs/aufs/rdu.c @@ -0,0 +1,382 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -28119,13 +28212,13 @@ index 00000000..60f4957b +#endif diff --git a/fs/aufs/rwsem.h b/fs/aufs/rwsem.h new file mode 100644 -index 00000000..bcb538ee +index 000000000..2f8988fa1 --- /dev/null +++ b/fs/aufs/rwsem.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -28198,13 +28291,13 @@ index 00000000..bcb538ee +#endif /* __AUFS_RWSEM_H__ */ diff --git a/fs/aufs/sbinfo.c b/fs/aufs/sbinfo.c new file mode 100644 -index 00000000..1a65676e +index 000000000..7318df0fe --- /dev/null +++ b/fs/aufs/sbinfo.c @@ -0,0 +1,313 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -28250,13 +28343,13 @@ index 00000000..1a65676e + au_br_free(sbinfo); + au_rw_write_unlock(&sbinfo->si_rwsem); + -+ kfree(sbinfo->si_branch); ++ au_kfree_try_rcu(sbinfo->si_branch); + mutex_destroy(&sbinfo->si_xib_mtx); + AuRwDestroy(&sbinfo->si_rwsem); + + au_lcnt_wait_for_fin(&sbinfo->si_ninodes); + /* si_nfiles is waited too */ -+ kfree(sbinfo); ++ au_kfree_rcu(sbinfo); +} + +int au_si_alloc(struct super_block *sb) @@ -28332,9 +28425,9 @@ index 00000000..1a65676e + return 0; /* success */ + +out_br: -+ kfree(sbinfo->si_branch); ++ au_kfree_try_rcu(sbinfo->si_branch); +out_sbinfo: -+ kfree(sbinfo); ++ au_kfree_rcu(sbinfo); +out: + return err; +} @@ -28517,13 +28610,13 @@ index 00000000..1a65676e +} diff --git a/fs/aufs/super.c b/fs/aufs/super.c new file mode 100644 -index 00000000..e3ea1f35 +index 000000000..25d8b27ec --- /dev/null +++ b/fs/aufs/super.c @@ -0,0 +1,1043 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -29566,13 +29659,13 @@ index 00000000..e3ea1f35 +}; diff --git a/fs/aufs/super.h b/fs/aufs/super.h new file mode 100644 -index 00000000..79e47da4 +index 000000000..74571acf3 --- /dev/null +++ b/fs/aufs/super.h @@ -0,0 +1,589 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -30161,13 +30254,13 @@ index 00000000..79e47da4 +#endif /* __AUFS_SUPER_H__ */ diff --git a/fs/aufs/sysaufs.c b/fs/aufs/sysaufs.c new file mode 100644 -index 00000000..cb34a53f +index 000000000..32a0811c5 --- /dev/null +++ b/fs/aufs/sysaufs.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -30260,13 +30353,13 @@ index 00000000..cb34a53f +} diff --git a/fs/aufs/sysaufs.h b/fs/aufs/sysaufs.h new file mode 100644 -index 00000000..9a64191c +index 000000000..195fe279b --- /dev/null +++ b/fs/aufs/sysaufs.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -30368,13 +30461,13 @@ index 00000000..9a64191c +#endif /* __SYSAUFS_H__ */ diff --git a/fs/aufs/sysfs.c b/fs/aufs/sysfs.c new file mode 100644 -index 00000000..89a4cbf6 +index 000000000..927f6b252 --- /dev/null +++ b/fs/aufs/sysfs.c @@ -0,0 +1,373 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -30584,7 +30677,7 @@ index 00000000..89a4cbf6 + if (unlikely(err == PAGE_SIZE)) + err = -EFBIG; + } -+ kfree(seq); ++ au_kfree_rcu(seq); +out_unlock: + si_read_unlock(sb); +out: @@ -30655,7 +30748,7 @@ index 00000000..89a4cbf6 + err = -EFAULT; + +out_seq: -+ kfree(seq); ++ au_kfree_rcu(seq); +out_buf: + free_page((unsigned long)buf); +out: @@ -30747,13 +30840,13 @@ index 00000000..89a4cbf6 +} diff --git a/fs/aufs/sysrq.c b/fs/aufs/sysrq.c new file mode 100644 -index 00000000..2dbf2374 +index 000000000..db10ec528 --- /dev/null +++ b/fs/aufs/sysrq.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -30913,13 +31006,13 @@ index 00000000..2dbf2374 +} diff --git a/fs/aufs/vdir.c b/fs/aufs/vdir.c new file mode 100644 -index 00000000..8606ed77 +index 000000000..13ec60bb4 --- /dev/null +++ b/fs/aufs/vdir.c @@ -0,0 +1,895 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -31030,7 +31123,7 @@ index 00000000..8606ed77 + struct hlist_node *node; + + hlist_for_each_entry_safe(pos, node, head, wh_hash) -+ kfree(pos); ++ au_kfree_rcu(pos); +} + +static void au_nhash_de_do_free(struct hlist_head *head) @@ -31057,7 +31150,7 @@ index 00000000..8606ed77 + nhash_count(head); + free(head++); + } -+ kfree(nhash->nh_head); ++ au_kfree_try_rcu(nhash->nh_head); +} + +void au_nhash_wh_free(struct au_nhash *whlist) @@ -31276,8 +31369,8 @@ index 00000000..8606ed77 + + deblk = vdir->vd_deblk; + while (vdir->vd_nblk--) -+ kfree(*deblk++); -+ kfree(vdir->vd_deblk); ++ au_kfree_try_rcu(*deblk++); ++ au_kfree_try_rcu(vdir->vd_deblk); + au_cache_free_vdir(vdir); +} + @@ -31312,7 +31405,7 @@ index 00000000..8606ed77 + if (!err) + return vdir; /* success */ + -+ kfree(vdir->vd_deblk); ++ au_kfree_try_rcu(vdir->vd_deblk); + +out_free: + au_cache_free_vdir(vdir); @@ -31327,7 +31420,7 @@ index 00000000..8606ed77 + union au_vdir_deblk_p p, deblk_end; + + while (vdir->vd_nblk > 1) { -+ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]); ++ au_kfree_try_rcu(vdir->vd_deblk[vdir->vd_nblk - 1]); + /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */ + vdir->vd_nblk--; + } @@ -31814,13 +31907,13 @@ index 00000000..8606ed77 +} diff --git a/fs/aufs/vfsub.c b/fs/aufs/vfsub.c new file mode 100644 -index 00000000..9386eb48 +index 000000000..a9074da42 --- /dev/null +++ b/fs/aufs/vfsub.c @@ -0,0 +1,903 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -32723,13 +32816,13 @@ index 00000000..9386eb48 +} diff --git a/fs/aufs/vfsub.h b/fs/aufs/vfsub.h new file mode 100644 -index 00000000..7f36a164 +index 000000000..2953aa410 --- /dev/null +++ b/fs/aufs/vfsub.h @@ -0,0 +1,362 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -33091,13 +33184,13 @@ index 00000000..7f36a164 +#endif /* __AUFS_VFSUB_H__ */ diff --git a/fs/aufs/wbr_policy.c b/fs/aufs/wbr_policy.c new file mode 100644 -index 00000000..6e97c806 +index 000000000..64954145c --- /dev/null +++ b/fs/aufs/wbr_policy.c @@ -0,0 +1,830 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -33558,7 +33651,7 @@ index 00000000..6e97c806 + + mfs->mfsrr_bytes = bavail; + AuDbg("b%d\n", mfs->mfs_bindex); -+ kfree(st); ++ au_kfree_rcu(st); +} + +static int au_wbr_create_mfs(struct dentry *dentry, unsigned int flags) @@ -33927,13 +34020,13 @@ index 00000000..6e97c806 +}; diff --git a/fs/aufs/whout.c b/fs/aufs/whout.c new file mode 100644 -index 00000000..2325c2ee +index 000000000..6c9c85015 --- /dev/null +++ b/fs/aufs/whout.c @@ -0,0 +1,1062 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -34096,7 +34189,7 @@ index 00000000..2325c2ee + +out_name: + if (name != defname) -+ kfree(name); ++ au_kfree_try_rcu(name); +out: + AuTraceErrPtr(dentry); + return dentry; @@ -34536,7 +34629,7 @@ index 00000000..2325c2ee + au_lcnt_dec(&a->br->br_count); + si_write_unlock(a->sb); + au_nwt_done(&au_sbi(a->sb)->si_nowait); -+ kfree(arg); ++ au_kfree_rcu(a); + if (unlikely(err)) + AuIOErr("err %d\n", err); +} @@ -34564,7 +34657,7 @@ index 00000000..2325c2ee + if (unlikely(wkq_err)) { + atomic_dec(&br->br_wbr->wbr_wh_running); + au_lcnt_dec(&br->br_count); -+ kfree(arg); ++ au_kfree_rcu(arg); + } + do_dec = 0; + } @@ -34723,7 +34816,7 @@ index 00000000..2325c2ee + wh_dentry = ERR_PTR(err); + if (!err) { + wh_dentry = vfsub_lkup_one(&wh_name, h_parent); -+ kfree(wh_name.name); ++ au_kfree_try_rcu(wh_name.name); + } + return wh_dentry; +} @@ -34841,7 +34934,7 @@ index 00000000..2325c2ee + rdhash = AUFS_RDHASH_DEF; + err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp); + if (unlikely(err)) { -+ kfree(whtmp); ++ au_kfree_rcu(whtmp); + whtmp = ERR_PTR(err); + } + @@ -34856,7 +34949,7 @@ index 00000000..2325c2ee + dput(whtmp->wh_dentry); + iput(whtmp->dir); + au_nhash_wh_free(&whtmp->whlist); -+ kfree(whtmp); ++ au_kfree_rcu(whtmp); +} + +/* @@ -34995,13 +35088,13 @@ index 00000000..2325c2ee +} diff --git a/fs/aufs/whout.h b/fs/aufs/whout.h new file mode 100644 -index 00000000..2bbc38ba +index 000000000..06f69b24e --- /dev/null +++ b/fs/aufs/whout.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -35087,13 +35180,13 @@ index 00000000..2bbc38ba +#endif /* __AUFS_WHOUT_H__ */ diff --git a/fs/aufs/wkq.c b/fs/aufs/wkq.c new file mode 100644 -index 00000000..55fab985 +index 000000000..b0dd8df4e --- /dev/null +++ b/fs/aufs/wkq.c @@ -0,0 +1,392 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -35265,7 +35358,7 @@ index 00000000..55fab985 + +static void au_wkq_lockdep_free(struct au_wkinfo *wkinfo) +{ -+ kfree(wkinfo->hlock); ++ au_kfree_try_rcu(wkinfo->hlock); +} + +static void au_wkq_lockdep_pre(struct au_wkinfo *wkinfo) @@ -35317,7 +35410,7 @@ index 00000000..55fab985 + else { + kobject_put(wkinfo->kobj); + module_put(THIS_MODULE); /* todo: ?? */ -+ kfree(wkinfo); ++ au_kfree_rcu(wkinfo); + } +} + @@ -35340,7 +35433,7 @@ index 00000000..55fab985 + +static void au_wkq_comp_free(struct completion *comp) +{ -+ kfree(comp); ++ au_kfree_rcu(comp); +} + +#else @@ -35485,13 +35578,13 @@ index 00000000..55fab985 +} diff --git a/fs/aufs/wkq.h b/fs/aufs/wkq.h new file mode 100644 -index 00000000..2e50ed83 +index 000000000..235370d91 --- /dev/null +++ b/fs/aufs/wkq.h @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -35580,13 +35673,13 @@ index 00000000..2e50ed83 +#endif /* __AUFS_WKQ_H__ */ diff --git a/fs/aufs/xattr.c b/fs/aufs/xattr.c new file mode 100644 -index 00000000..a31b57e4 +index 000000000..4b25f2f14 --- /dev/null +++ b/fs/aufs/xattr.c @@ -0,0 +1,356 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2014-2018 Junjiro R. Okajima ++ * Copyright (C) 2014-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -35765,10 +35858,10 @@ index 00000000..a31b57e4 + AuTraceErr(err); + } + -+ kfree(value); ++ au_kfree_try_rcu(value); + +out_free: -+ kfree(o); ++ au_kfree_try_rcu(o); +out: + if (!unlocked) + inode_unlock_shared(h_isrc); @@ -35942,13 +36035,13 @@ index 00000000..a31b57e4 +} diff --git a/fs/aufs/xino.c b/fs/aufs/xino.c new file mode 100644 -index 00000000..c5fca81b +index 000000000..35ea33469 --- /dev/null +++ b/fs/aufs/xino.c -@@ -0,0 +1,1956 @@ +@@ -0,0 +1,1965 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -36108,22 +36201,28 @@ index 00000000..c5fca81b +/* + * create and set a new xino file + */ -+struct file *au_xino_create(struct super_block *sb, char *fpath, int silent) ++struct file *au_xino_create(struct super_block *sb, char *fpath, int silent, ++ int wbrtop) +{ + struct file *file; + struct dentry *h_parent, *d; + struct inode *h_dir, *inode; + int err; ++ static DEFINE_MUTEX(mtx); + + /* + * at mount-time, and the xino file is the default path, + * hnotify is disabled so we have no notify events to ignore. + * when a user specified the xino, we cannot get au_hdir to be ignored. + */ ++ if (!wbrtop) ++ mutex_lock(&mtx); + file = vfsub_filp_open(fpath, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE + /* | __FMODE_NONOTIFY */, + 0666); + if (IS_ERR(file)) { ++ if (!wbrtop) ++ mutex_unlock(&mtx); + if (!silent) + pr_err("open %s(%ld)\n", fpath, PTR_ERR(file)); + return file; @@ -36133,6 +36232,8 @@ index 00000000..c5fca81b + err = 0; + d = file->f_path.dentry; + h_parent = au_dget_parent_lock(d, AuLsc_I_PARENT); ++ if (!wbrtop) ++ mutex_unlock(&mtx); + /* mnt_want_write() is unnecessary here */ + h_dir = d_inode(h_parent); + inode = file_inode(file); @@ -36420,7 +36521,7 @@ index 00000000..c5fca81b + au_sbi(sb)->si_xino_jiffy = jiffy; + +out_st: -+ kfree(st); ++ au_kfree_rcu(st); +out: + return err; +} @@ -36457,7 +36558,7 @@ index 00000000..c5fca81b + au_lcnt_dec(&br->br_count); + si_write_unlock(sb); + au_nwt_done(&au_sbi(sb)->si_nowait); -+ kfree(args); ++ au_kfree_rcu(args); +} + +/* @@ -36529,7 +36630,7 @@ index 00000000..c5fca81b + + pr_err("wkq %d\n", wkq_err); + au_lcnt_dec(&br->br_count); -+ kfree(args); ++ au_kfree_rcu(args); + +out: + atomic_dec(&br->br_xino->xi_truncating); @@ -36648,14 +36749,14 @@ index 00000000..c5fca81b + } + } + hlist_bl_unlock(hbl); -+ kfree(del); ++ au_kfree_rcu(del); + +out: + au_lcnt_dec(&br->br_count); + ii_read_unlock(root); + si_read_unlock(sb); + au_nwt_done(&sbi->si_nowait); -+ kfree(args); ++ au_kfree_rcu(a); +} + +/* @@ -36681,7 +36782,7 @@ index 00000000..c5fca81b + if (unlikely(err)) { + pr_err("wkq %d\n", err); + au_lcnt_dec(&br->br_count); -+ kfree(arg); ++ au_kfree_rcu(arg); + } + +out: @@ -37244,9 +37345,9 @@ index 00000000..c5fca81b + goto out; /* success */ + +out_file: -+ kfree(xi->xi_file); ++ au_kfree_try_rcu(xi->xi_file); +out_free: -+ kfree(xi); ++ au_kfree_rcu(xi); + xi = NULL; +out: + return xi; @@ -37297,13 +37398,13 @@ index 00000000..c5fca81b + hlist_bl_lock(hbl); + hlist_bl_for_each_entry_safe (p, pos, n, hbl, node) { + hlist_bl_del(&p->node); -+ kfree(p); ++ au_kfree_rcu(p); + } + hlist_bl_unlock(hbl); + } -+ kfree(xi->xi_file); -+ kfree(xi->xi_nondir.array); -+ kfree(xi); ++ au_kfree_try_rcu(xi->xi_file); ++ au_kfree_try_rcu(xi->xi_nondir.array); ++ au_kfree_rcu(xi); +} + +int au_xino_put(struct au_branch *br) @@ -37615,11 +37716,12 @@ index 00000000..c5fca81b + if (!IS_ERR(p)) { + strcat(p, "/" AUFS_XINO_FNAME); + AuDbg("%s\n", p); -+ file = au_xino_create(sb, p, /*silent*/0); ++ file = au_xino_create(sb, p, /*silent*/0, /*wbrtop*/1); + } + free_page((unsigned long)page); + } else { -+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0); ++ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0, ++ /*wbrtop*/0); + if (IS_ERR(file)) + goto out; + h_sb = file->f_path.dentry->d_sb; @@ -37903,10 +38005,10 @@ index 00000000..c5fca81b + return err; +} diff --git a/fs/dcache.c b/fs/dcache.c -index 28b2e770..d514ed23 100644 +index 9ac1290ae..c4fe6f8db 100644 --- a/fs/dcache.c +++ b/fs/dcache.c -@@ -1221,7 +1221,7 @@ enum d_walk_ret { +@@ -1217,7 +1217,7 @@ enum d_walk_ret { * * The @enter() and @finish() callbacks are called with d_lock held. */ @@ -37915,7 +38017,7 @@ index 28b2e770..d514ed23 100644 enum d_walk_ret (*enter)(void *, struct dentry *), void (*finish)(void *)) { -@@ -1329,6 +1329,7 @@ static void d_walk(struct dentry *parent, void *data, +@@ -1325,6 +1325,7 @@ static void d_walk(struct dentry *parent, void *data, seq = 1; goto again; } @@ -37923,7 +38025,7 @@ index 28b2e770..d514ed23 100644 struct check_mount { struct vfsmount *mnt; -@@ -2954,6 +2955,7 @@ void d_exchange(struct dentry *dentry1, struct dentry *dentry2) +@@ -2950,6 +2951,7 @@ void d_exchange(struct dentry *dentry1, struct dentry *dentry2) write_sequnlock(&rename_lock); } @@ -37932,7 +38034,7 @@ index 28b2e770..d514ed23 100644 /** * d_ancestor - search for an ancestor diff --git a/fs/exec.c b/fs/exec.c -index 0da4d748..5c94194b 100644 +index 7def97f6a..20c38005d 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -109,6 +109,7 @@ bool path_noexec(const struct path *path) @@ -37944,7 +38046,7 @@ index 0da4d748..5c94194b 100644 #ifdef CONFIG_USELIB /* diff --git a/fs/fcntl.c b/fs/fcntl.c -index 0345a46b..e8c9dc38 100644 +index 0345a46b8..e8c9dc38c 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -32,7 +32,7 @@ @@ -37974,7 +38076,7 @@ index 0345a46b..e8c9dc38 100644 static void f_modown(struct file *filp, struct pid *pid, enum pid_type type, int force) diff --git a/fs/file_table.c b/fs/file_table.c -index 61517f57..c6bab39c 100644 +index 61517f57f..c6bab39c1 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -148,6 +148,7 @@ struct file *get_empty_filp(void) @@ -38010,7 +38112,7 @@ index 61517f57..c6bab39c 100644 void __init files_init(void) { diff --git a/fs/inode.c b/fs/inode.c -index cfc36d11..8ca32869 100644 +index 76f7535fe..5e0542f25 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1656,7 +1656,7 @@ EXPORT_SYMBOL(generic_update_time); @@ -38031,7 +38133,7 @@ index cfc36d11..8ca32869 100644 /** * touch_atime - update the access time diff --git a/fs/namespace.c b/fs/namespace.c -index 9dc146e7..902c99ca 100644 +index e9c13eedd..3e03d3633 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -517,6 +517,7 @@ void __mnt_drop_write(struct vfsmount *mnt) @@ -38056,7 +38158,7 @@ index 9dc146e7..902c99ca 100644 /* * vfsmount lock must be held for write */ -@@ -1906,6 +1914,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg, +@@ -1918,6 +1926,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg, } return 0; } @@ -38065,18 +38167,10 @@ index 9dc146e7..902c99ca 100644 static void cleanup_group_ids(struct mount *mnt, struct mount *end) { diff --git a/fs/notify/group.c b/fs/notify/group.c -index 32357534..14a2d48f 100644 +index 32357534d..952690873 100644 --- a/fs/notify/group.c +++ b/fs/notify/group.c -@@ -22,6 +22,7 @@ - #include - #include - #include -+#include - - #include - #include "fsnotify.h" -@@ -109,6 +110,7 @@ void fsnotify_get_group(struct fsnotify_group *group) +@@ -109,6 +109,7 @@ void fsnotify_get_group(struct fsnotify_group *group) { atomic_inc(&group->refcnt); } @@ -38084,7 +38178,7 @@ index 32357534..14a2d48f 100644 /* * Drop a reference to a group. Free it if it's through. -@@ -118,6 +120,7 @@ void fsnotify_put_group(struct fsnotify_group *group) +@@ -118,6 +119,7 @@ void fsnotify_put_group(struct fsnotify_group *group) if (atomic_dec_and_test(&group->refcnt)) fsnotify_final_destroy_group(group); } @@ -38092,7 +38186,7 @@ index 32357534..14a2d48f 100644 /* * Create a new fsnotify_group and hold a reference for the group returned. -@@ -147,6 +150,7 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops) +@@ -147,6 +149,7 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops) return group; } @@ -38101,7 +38195,7 @@ index 32357534..14a2d48f 100644 int fsnotify_fasync(int fd, struct file *file, int on) { diff --git a/fs/notify/mark.c b/fs/notify/mark.c -index 258d9908..cd0dd398 100644 +index 258d99087..cd0dd398f 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c @@ -245,6 +245,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark) @@ -38137,7 +38231,7 @@ index 258d9908..cd0dd398 100644 /* * Destroy all marks in destroy_list, waits for SRCU period to finish before diff --git a/fs/open.c b/fs/open.c -index 7ea11847..6e2e2418 100644 +index 29a2cdcbc..41d8c00fb 100644 --- a/fs/open.c +++ b/fs/open.c @@ -64,6 +64,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, @@ -38148,7 +38242,7 @@ index 7ea11847..6e2e2418 100644 long vfs_truncate(const struct path *path, loff_t length) { -@@ -691,6 +692,7 @@ int open_check_o_direct(struct file *f) +@@ -710,6 +711,7 @@ int open_check_o_direct(struct file *f) } return 0; } @@ -38157,10 +38251,10 @@ index 7ea11847..6e2e2418 100644 static int do_dentry_open(struct file *f, struct inode *inode, diff --git a/fs/proc/base.c b/fs/proc/base.c -index 9063738f..47f3fd3b 100644 +index 64695dcf8..eeaad0f45 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c -@@ -2035,7 +2035,7 @@ static int map_files_get_link(struct dentry *dentry, struct path *path) +@@ -2031,7 +2031,7 @@ static int map_files_get_link(struct dentry *dentry, struct path *path) down_read(&mm->mmap_sem); vma = find_exact_vma(mm, vm_start, vm_end); if (vma && vma->vm_file) { @@ -38170,7 +38264,7 @@ index 9063738f..47f3fd3b 100644 rc = 0; } diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c -index 75634379..7c0dc0ff 100644 +index 75634379f..7c0dc0ff4 100644 --- a/fs/proc/nommu.c +++ b/fs/proc/nommu.c @@ -45,7 +45,10 @@ static int nommu_region_show(struct seq_file *m, struct vm_region *region) @@ -38186,7 +38280,7 @@ index 75634379..7c0dc0ff 100644 ino = inode->i_ino; } diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c -index 2b47757c..912f287d 100644 +index 309d24118..c6288e71e 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -310,7 +310,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid) @@ -38201,7 +38295,7 @@ index 2b47757c..912f287d 100644 dev = inode->i_sb->s_dev; ino = inode->i_ino; pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT; -@@ -1751,7 +1754,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid) +@@ -1775,7 +1778,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid) struct proc_maps_private *proc_priv = &numa_priv->proc_maps; struct vm_area_struct *vma = v; struct numa_maps *md = &numa_priv->md; @@ -38211,7 +38305,7 @@ index 2b47757c..912f287d 100644 struct mm_walk walk = { .hugetlb_entry = gather_hugetlb_stats, diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c -index 5b62f57b..dfb4a3bd 100644 +index 5b62f57bd..dfb4a3bd0 100644 --- a/fs/proc/task_nommu.c +++ b/fs/proc/task_nommu.c @@ -156,7 +156,10 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma, @@ -38227,7 +38321,7 @@ index 5b62f57b..dfb4a3bd 100644 ino = inode->i_ino; pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT; diff --git a/fs/read_write.c b/fs/read_write.c -index 57a00ef8..1221dda3 100644 +index e8136a72c..bdb1d223a 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -454,6 +454,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) @@ -38278,7 +38372,7 @@ index 57a00ef8..1221dda3 100644 static inline loff_t file_pos_read(struct file *file) { diff --git a/fs/splice.c b/fs/splice.c -index f3084cce..7ab89d23 100644 +index c84ac7e97..3724bd22e 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -837,8 +837,8 @@ EXPORT_SYMBOL(generic_splice_sendpage); @@ -38319,7 +38413,7 @@ index f3084cce..7ab89d23 100644 /** * splice_direct_to_actor - splices data directly between two non-pipes diff --git a/fs/sync.c b/fs/sync.c -index 83ac79a9..e3386eab 100644 +index 83ac79a96..e3386eabb 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -28,7 +28,7 @@ @@ -38340,7 +38434,7 @@ index 83ac79a9..e3386eab 100644 /* * Write out and wait upon all dirty data associated with this diff --git a/fs/xattr.c b/fs/xattr.c -index 50029811..ee34b725 100644 +index 50029811f..ee34b7256 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -297,6 +297,7 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value, @@ -38352,7 +38446,7 @@ index 50029811..ee34b725 100644 ssize_t __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name, diff --git a/include/linux/file.h b/include/linux/file.h -index 279720db..76e38ead 100644 +index 279720db9..76e38eade 100644 --- a/include/linux/file.h +++ b/include/linux/file.h @@ -20,6 +20,7 @@ struct dentry; @@ -38364,10 +38458,10 @@ index 279720db..76e38ead 100644 static inline void fput_light(struct file *file, int fput_needed) { diff --git a/include/linux/fs.h b/include/linux/fs.h -index 7374639f..48520a1c 100644 +index f0fddf4ea..85ac9197c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h -@@ -1265,6 +1265,7 @@ extern void fasync_free(struct fasync_struct *); +@@ -1270,6 +1270,7 @@ extern void fasync_free(struct fasync_struct *); /* can be called from interrupts */ extern void kill_fasync(struct fasync_struct **, int, int); @@ -38375,7 +38469,7 @@ index 7374639f..48520a1c 100644 extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int force); extern int f_setown(struct file *filp, unsigned long arg, int force); extern void f_delown(struct file *filp); -@@ -1712,6 +1713,7 @@ struct file_operations { +@@ -1717,6 +1718,7 @@ struct file_operations { ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); int (*check_flags)(int); @@ -38383,7 +38477,7 @@ index 7374639f..48520a1c 100644 int (*flock) (struct file *, int, struct file_lock *); ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); -@@ -1782,6 +1784,12 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, +@@ -1787,6 +1789,12 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, struct iovec *fast_pointer, struct iovec **ret_pointer); @@ -38396,7 +38490,7 @@ index 7374639f..48520a1c 100644 extern ssize_t __vfs_read(struct file *, char __user *, size_t, loff_t *); extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *); extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *); -@@ -2186,6 +2194,7 @@ extern int current_umask(void); +@@ -2191,6 +2199,7 @@ extern int current_umask(void); extern void ihold(struct inode * inode); extern void iput(struct inode *); extern int generic_update_time(struct inode *, struct timespec *, int); @@ -38404,7 +38498,7 @@ index 7374639f..48520a1c 100644 /* /sys/fs */ extern struct kobject *fs_kobj; -@@ -2466,6 +2475,7 @@ static inline bool sb_is_blkdev_sb(struct super_block *sb) +@@ -2471,6 +2480,7 @@ static inline bool sb_is_blkdev_sb(struct super_block *sb) return false; } #endif @@ -38413,7 +38507,7 @@ index 7374639f..48520a1c 100644 extern const struct file_operations def_blk_fops; extern const struct file_operations def_chr_fops; diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h -index f301d31b..c26f5b42 100644 +index f301d31b4..c26f5b420 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h @@ -406,6 +406,8 @@ static inline int lockdep_match_key(struct lockdep_map *lock, @@ -38434,10 +38528,10 @@ index f301d31b..c26f5b42 100644 #define lockdep_assert_held(l) do { (void)(l); } while (0) diff --git a/include/linux/mm.h b/include/linux/mm.h -index 58f2263d..e8b2d404 100644 +index 858ce84ac..977676601 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h -@@ -1350,6 +1350,28 @@ static inline int fixup_user_fault(struct task_struct *tsk, +@@ -1358,6 +1358,28 @@ static inline int fixup_user_fault(struct task_struct *tsk, } #endif @@ -38467,10 +38561,10 @@ index 58f2263d..e8b2d404 100644 unsigned int gup_flags); extern int access_remote_vm(struct mm_struct *mm, unsigned long addr, diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h -index e41ef532..bf258a4e 100644 +index be5d445ba..dca97e717 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h -@@ -253,6 +253,7 @@ struct vm_region { +@@ -258,6 +258,7 @@ struct vm_region { unsigned long vm_top; /* region allocated to here */ unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */ struct file *vm_file; /* the backing file or NULL */ @@ -38478,7 +38572,7 @@ index e41ef532..bf258a4e 100644 int vm_usage; /* region usage count (access under nommu_region_sem) */ bool vm_icache_flushed : 1; /* true if the icache has been flushed for -@@ -327,6 +328,7 @@ struct vm_area_struct { +@@ -332,6 +333,7 @@ struct vm_area_struct { unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE units */ struct file * vm_file; /* File we map to (can be NULL). */ @@ -38487,7 +38581,7 @@ index e41ef532..bf258a4e 100644 atomic_long_t swap_readahead_info; diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h -index 35942084..24f5fd1a 100644 +index 35942084c..24f5fd1a7 100644 --- a/include/linux/mnt_namespace.h +++ b/include/linux/mnt_namespace.h @@ -6,11 +6,14 @@ @@ -38506,7 +38600,7 @@ index 35942084..24f5fd1a 100644 extern const struct file_operations proc_mountinfo_operations; extern const struct file_operations proc_mountstats_operations; diff --git a/include/linux/splice.h b/include/linux/splice.h -index 74b4911a..19789fbe 100644 +index 74b4911ac..19789fbea 100644 --- a/include/linux/splice.h +++ b/include/linux/splice.h @@ -87,4 +87,10 @@ extern void splice_shrink_spd(struct splice_pipe_desc *); @@ -38522,13 +38616,13 @@ index 74b4911a..19789fbe 100644 #endif diff --git a/include/uapi/linux/aufs_type.h b/include/uapi/linux/aufs_type.h new file mode 100644 -index 00000000..06a75451 +index 000000000..d8e39df98 --- /dev/null +++ b/include/uapi/linux/aufs_type.h -@@ -0,0 +1,448 @@ +@@ -0,0 +1,452 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2018 Junjiro R. Okajima ++ * Copyright (C) 2005-2019 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -38568,7 +38662,7 @@ index 00000000..06a75451 + +#include + -+#define AUFS_VERSION "4.14.73+-20181119" ++#define AUFS_VERSION "4.14.73+-20190902" + +/* todo? move this to linux-2.6.19/include/magic.h */ +#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's') @@ -38782,7 +38876,11 @@ index 00000000..06a75451 + +/* borrowed from linux/include/linux/kernel.h */ +#ifndef ALIGN ++#ifdef _GNU_SOURCE +#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) ++#else ++#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) ++#endif +#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask)) +#endif + @@ -38975,10 +39073,10 @@ index 00000000..06a75451 + +#endif /* __AUFS_TYPE_H__ */ diff --git a/kernel/fork.c b/kernel/fork.c -index 6a219fea..a19ee252 100644 +index 0a328cf0c..dc9ce1b30 100644 --- a/kernel/fork.c +++ b/kernel/fork.c -@@ -675,7 +675,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, +@@ -670,7 +670,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, struct inode *inode = file_inode(file); struct address_space *mapping = file->f_mapping; @@ -38988,7 +39086,7 @@ index 6a219fea..a19ee252 100644 atomic_dec(&inode->i_writecount); i_mmap_lock_write(mapping); diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c -index bf694c70..28e6c758 100644 +index 90a3469a7..6d8e312df 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -143,7 +143,7 @@ static struct lock_list list_entries[MAX_LOCKDEP_ENTRIES]; @@ -39010,7 +39108,7 @@ index bf694c70..28e6c758 100644 #ifdef CONFIG_LOCK_STAT static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], cpu_lock_stats); diff --git a/kernel/task_work.c b/kernel/task_work.c -index 0fef3956..83fb1ecf 100644 +index 0fef39566..83fb1ecfc 100644 --- a/kernel/task_work.c +++ b/kernel/task_work.c @@ -116,3 +116,4 @@ void task_work_run(void) @@ -39019,7 +39117,7 @@ index 0fef3956..83fb1ecf 100644 } +EXPORT_SYMBOL_GPL(task_work_run); diff --git a/mm/Makefile b/mm/Makefile -index e7ebd176..d6bcfb01 100644 +index e7ebd176f..d6bcfb01b 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -39,7 +39,7 @@ obj-y := filemap.o mempool.o oom_kill.o \ @@ -39032,10 +39130,10 @@ index e7ebd176..d6bcfb01 100644 obj-y += init-mm.o diff --git a/mm/filemap.c b/mm/filemap.c -index e2e738cc..2a410810 100644 +index a30dbf93d..c1fdca33d 100644 --- a/mm/filemap.c +++ b/mm/filemap.c -@@ -2589,7 +2589,7 @@ int filemap_page_mkwrite(struct vm_fault *vmf) +@@ -2612,7 +2612,7 @@ int filemap_page_mkwrite(struct vm_fault *vmf) int ret = VM_FAULT_LOCKED; sb_start_pagefault(inode->i_sb); @@ -39045,10 +39143,10 @@ index e2e738cc..2a410810 100644 if (page->mapping != inode->i_mapping) { unlock_page(page); diff --git a/mm/mmap.c b/mm/mmap.c -index 23987761..753b6329 100644 +index db0e29239..60bf78943 100644 --- a/mm/mmap.c +++ b/mm/mmap.c -@@ -171,7 +171,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma) +@@ -172,7 +172,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma) if (vma->vm_ops && vma->vm_ops->close) vma->vm_ops->close(vma); if (vma->vm_file) @@ -39057,7 +39155,7 @@ index 23987761..753b6329 100644 mpol_put(vma_policy(vma)); kmem_cache_free(vm_area_cachep, vma); return next; -@@ -896,7 +896,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, +@@ -897,7 +897,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, if (remove_next) { if (file) { uprobe_munmap(next, next->vm_start, next->vm_end); @@ -39066,7 +39164,7 @@ index 23987761..753b6329 100644 } if (next->anon_vma) anon_vma_merge(vma, next); -@@ -1778,8 +1778,8 @@ unsigned long mmap_region(struct file *file, unsigned long addr, +@@ -1747,8 +1747,8 @@ unsigned long mmap_region(struct file *file, unsigned long addr, return addr; unmap_and_free_vma: @@ -39076,7 +39174,7 @@ index 23987761..753b6329 100644 /* Undo any partial mapping done by a device driver. */ unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end); -@@ -2603,7 +2603,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -2575,7 +2575,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, goto out_free_mpol; if (new->vm_file) @@ -39085,7 +39183,7 @@ index 23987761..753b6329 100644 if (new->vm_ops && new->vm_ops->open) new->vm_ops->open(new); -@@ -2622,7 +2622,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -2594,7 +2594,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, if (new->vm_ops && new->vm_ops->close) new->vm_ops->close(new); if (new->vm_file) @@ -39094,7 +39192,7 @@ index 23987761..753b6329 100644 unlink_anon_vmas(new); out_free_mpol: mpol_put(vma_policy(new)); -@@ -2784,7 +2784,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, +@@ -2756,7 +2756,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, struct vm_area_struct *vma; unsigned long populate = 0; unsigned long ret = -EINVAL; @@ -39103,7 +39201,7 @@ index 23987761..753b6329 100644 pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/vm/remap_file_pages.txt.\n", current->comm, current->pid); -@@ -2859,10 +2859,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, +@@ -2831,10 +2831,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, } } @@ -39132,7 +39230,7 @@ index 23987761..753b6329 100644 out: up_write(&mm->mmap_sem); if (populate) -@@ -3173,7 +3190,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, +@@ -3145,7 +3162,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, if (anon_vma_clone(new_vma, vma)) goto out_free_mempol; if (new_vma->vm_file) @@ -39142,7 +39240,7 @@ index 23987761..753b6329 100644 new_vma->vm_ops->open(new_vma); vma_link(mm, new_vma, prev, rb_link, rb_parent); diff --git a/mm/nommu.c b/mm/nommu.c -index 17c00d93..4bcdf944 100644 +index 17c00d93d..4bcdf9448 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -641,7 +641,7 @@ static void __put_nommu_region(struct vm_region *region) @@ -39187,7 +39285,7 @@ index 17c00d93..4bcdf944 100644 diff --git a/mm/prfile.c b/mm/prfile.c new file mode 100644 -index 00000000..a27ac368 +index 000000000..024cdcfae --- /dev/null +++ b/mm/prfile.c @@ -0,0 +1,86 @@ @@ -39199,7 +39297,7 @@ index 00000000..a27ac368 + * + * See Documentation/filesystems/aufs/design/06mmap.txt + * -+ * Copyright (c) 2014-2018 Junjro R. Okajima ++ * Copyright (c) 2014-2019 Junjro R. Okajima + * Copyright (c) 2014 Ian Campbell + */ + @@ -39277,38 +39375,11 @@ index 00000000..a27ac368 + fput(pr); +} +#endif /* !CONFIG_MMU */ -diff --git a/security/commoncap.c b/security/commoncap.c -index ae26ef00..19cffd0b 100644 ---- a/security/commoncap.c -+++ b/security/commoncap.c -@@ -1269,12 +1269,14 @@ int cap_mmap_addr(unsigned long addr) - } - return ret; - } -+EXPORT_SYMBOL_GPL(cap_mmap_addr); - - int cap_mmap_file(struct file *file, unsigned long reqprot, - unsigned long prot, unsigned long flags) - { - return 0; - } -+EXPORT_SYMBOL_GPL(cap_mmap_file); - - #ifdef CONFIG_SECURITY - diff --git a/security/device_cgroup.c b/security/device_cgroup.c -index 5ef7e524..e2e959dc 100644 +index ea014df89..92120f60e 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c -@@ -8,6 +8,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -850,6 +851,7 @@ int __devcgroup_inode_permission(struct inode *inode, int mask) +@@ -850,6 +850,7 @@ int __devcgroup_inode_permission(struct inode *inode, int mask) return __devcgroup_check_permission(type, imajor(inode), iminor(inode), access); } @@ -39317,7 +39388,7 @@ index 5ef7e524..e2e959dc 100644 int devcgroup_inode_mknod(int mode, dev_t dev) { diff --git a/security/security.c b/security/security.c -index 95a1a0f5..1627a963 100644 +index 4fbe4e495..640687ed1 100644 --- a/security/security.c +++ b/security/security.c @@ -532,6 +532,7 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry) @@ -39368,15 +39439,7 @@ index 95a1a0f5..1627a963 100644 int security_path_chroot(const struct path *path) { -@@ -682,6 +688,7 @@ int security_inode_readlink(struct dentry *dentry) - return 0; - return call_int_hook(inode_readlink, 0, dentry); - } -+EXPORT_SYMBOL_GPL(security_inode_readlink); - - int security_inode_follow_link(struct dentry *dentry, struct inode *inode, - bool rcu) -@@ -697,6 +704,7 @@ int security_inode_permission(struct inode *inode, int mask) +@@ -697,6 +703,7 @@ int security_inode_permission(struct inode *inode, int mask) return 0; return call_int_hook(inode_permission, 0, inode, mask); } @@ -39384,7 +39447,7 @@ index 95a1a0f5..1627a963 100644 int security_inode_setattr(struct dentry *dentry, struct iattr *attr) { -@@ -868,6 +876,7 @@ int security_file_permission(struct file *file, int mask) +@@ -868,6 +875,7 @@ int security_file_permission(struct file *file, int mask) return fsnotify_perm(file, mask); } @@ -39392,7 +39455,7 @@ index 95a1a0f5..1627a963 100644 int security_file_alloc(struct file *file) { -@@ -927,6 +936,7 @@ int security_mmap_file(struct file *file, unsigned long prot, +@@ -927,6 +935,7 @@ int security_mmap_file(struct file *file, unsigned long prot, return ret; return ima_file_mmap(file, prot); }