Merge branch 'akpm' (patches from Andrew)
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 4 Feb 2020 07:24:48 +0000 (07:24 +0000)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 4 Feb 2020 07:24:48 +0000 (07:24 +0000)
Merge more updates from Andrew Morton:
 "The rest of MM and the rest of everything else: hotfixes, ipc, misc,
  procfs, lib, cleanups, arm"

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (67 commits)
  ARM: dma-api: fix max_pfn off-by-one error in __dma_supported()
  treewide: remove redundant IS_ERR() before error code check
  include/linux/cpumask.h: don't calculate length of the input string
  lib: new testcases for bitmap_parse{_user}
  lib: rework bitmap_parse()
  lib: make bitmap_parse_user a wrapper on bitmap_parse
  lib: add test for bitmap_parse()
  bitops: more BITS_TO_* macros
  lib/string: add strnchrnul()
  proc: convert everything to "struct proc_ops"
  proc: decouple proc from VFS with "struct proc_ops"
  asm-generic/tlb: provide MMU_GATHER_TABLE_FREE
  asm-generic/tlb: rename HAVE_MMU_GATHER_NO_GATHER
  asm-generic/tlb: rename HAVE_MMU_GATHER_PAGE_SIZE
  asm-generic/tlb: rename HAVE_RCU_TABLE_FREE
  asm-generic/tlb: add missing CONFIG symbol
  asm-gemeric/tlb: remove stray function declarations
  asm-generic/tlb: avoid potential double flush
  mm/mmu_gather: invalidate TLB correctly on batch allocation failure and flush
  powerpc/mmu_gather: enable RCU_TABLE_FREE even for !SMP case
  ...

214 files changed:
Documentation/memory-barriers.txt
arch/Kconfig
arch/alpha/kernel/srm_env.c
arch/arc/include/asm/pgtable.h
arch/arm/Kconfig
arch/arm/include/asm/pgtable-2level.h
arch/arm/include/asm/pgtable-3level.h
arch/arm/include/asm/tlb.h
arch/arm/kernel/atags_proc.c
arch/arm/mm/alignment.c
arch/arm/mm/dma-mapping.c
arch/arm64/Kconfig
arch/arm64/Kconfig.debug
arch/arm64/include/asm/pgtable.h
arch/arm64/include/asm/ptdump.h
arch/arm64/mm/Makefile
arch/arm64/mm/dump.c
arch/arm64/mm/mmu.c
arch/arm64/mm/ptdump_debugfs.c
arch/ia64/kernel/salinfo.c
arch/m68k/kernel/bootinfo_proc.c
arch/mips/include/asm/pgtable.h
arch/mips/lasat/picvue_proc.c
arch/powerpc/Kconfig
arch/powerpc/include/asm/book3s/32/pgalloc.h
arch/powerpc/include/asm/book3s/64/pgalloc.h
arch/powerpc/include/asm/book3s/64/pgtable.h
arch/powerpc/include/asm/nohash/pgalloc.h
arch/powerpc/include/asm/tlb.h
arch/powerpc/kernel/proc_powerpc.c
arch/powerpc/kernel/rtas-proc.c
arch/powerpc/kernel/rtas_flash.c
arch/powerpc/kernel/rtasd.c
arch/powerpc/mm/book3s64/pgtable.c
arch/powerpc/mm/numa.c
arch/powerpc/platforms/pseries/lpar.c
arch/powerpc/platforms/pseries/lparcfg.c
arch/powerpc/platforms/pseries/reconfig.c
arch/powerpc/platforms/pseries/scanlog.c
arch/riscv/include/asm/pgtable-64.h
arch/riscv/include/asm/pgtable.h
arch/s390/Kconfig
arch/s390/include/asm/pgtable.h
arch/sh/mm/alignment.c
arch/sparc/Kconfig
arch/sparc/include/asm/pgtable_64.h
arch/sparc/include/asm/tlb_64.h
arch/sparc/kernel/led.c
arch/um/drivers/mconsole_kern.c
arch/um/kernel/exitcode.c
arch/um/kernel/process.c
arch/x86/Kconfig
arch/x86/Kconfig.debug
arch/x86/include/asm/pgtable.h
arch/x86/include/asm/tlb.h
arch/x86/kernel/cpu/mtrr/if.c
arch/x86/mm/Makefile
arch/x86/mm/debug_pagetables.c
arch/x86/mm/dump_pagetables.c
arch/x86/platform/efi/efi_32.c
arch/x86/platform/efi/efi_64.c
arch/x86/platform/uv/tlb_uv.c
arch/xtensa/platforms/iss/simdisk.c
crypto/af_alg.c
drivers/acpi/battery.c
drivers/acpi/proc.c
drivers/acpi/scan.c
drivers/base/memory.c
drivers/block/null_blk_main.c
drivers/char/hw_random/bcm2835-rng.c
drivers/char/hw_random/omap-rng.c
drivers/clk/clk.c
drivers/dma/mv_xor_v2.c
drivers/firmware/efi/arm-runtime.c
drivers/gpio/gpiolib-devres.c
drivers/gpio/gpiolib-of.c
drivers/gpio/gpiolib.c
drivers/hwmon/dell-smm-hwmon.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-synquacer.c
drivers/ide/ide-proc.c
drivers/input/input.c
drivers/isdn/capi/kcapi_proc.c
drivers/macintosh/via-pmu.c
drivers/md/md.c
drivers/misc/sgi-gru/gruprocfs.c
drivers/mtd/ubi/build.c
drivers/net/wireless/cisco/airo.c
drivers/net/wireless/intel/ipw2x00/libipw_module.c
drivers/net/wireless/intersil/hostap/hostap_hw.c
drivers/net/wireless/intersil/hostap/hostap_proc.c
drivers/net/wireless/intersil/hostap/hostap_wlan.h
drivers/net/wireless/ray_cs.c
drivers/of/device.c
drivers/parisc/led.c
drivers/pci/controller/pci-tegra.c
drivers/pci/proc.c
drivers/phy/phy-core.c
drivers/pinctrl/pxa/pinctrl-pxa2xx.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/toshiba_acpi.c
drivers/pnp/isapnp/proc.c
drivers/pnp/pnpbios/proc.c
drivers/s390/block/dasd_proc.c
drivers/s390/cio/blacklist.c
drivers/s390/cio/css.c
drivers/scsi/esas2r/esas2r_main.c
drivers/scsi/scsi_devinfo.c
drivers/scsi/scsi_proc.c
drivers/scsi/sg.c
drivers/spi/spi-orion.c
drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
drivers/tty/sysrq.c
drivers/usb/gadget/function/rndis.c
drivers/video/fbdev/imxfb.c
drivers/video/fbdev/via/viafbdev.c
drivers/zorro/proc.c
fs/cifs/cifs_debug.c
fs/cifs/dfs_cache.c
fs/cifs/dfs_cache.h
fs/ext4/super.c
fs/f2fs/node.c
fs/fscache/internal.h
fs/fscache/object-list.c
fs/fscache/proc.c
fs/jbd2/journal.c
fs/jfs/jfs_debug.c
fs/lockd/procfs.c
fs/nfsd/nfsctl.c
fs/nfsd/stats.c
fs/ocfs2/file.c
fs/ocfs2/suballoc.c
fs/proc/cpuinfo.c
fs/proc/generic.c
fs/proc/inode.c
fs/proc/internal.h
fs/proc/kcore.c
fs/proc/kmsg.c
fs/proc/page.c
fs/proc/proc_net.c
fs/proc/proc_sysctl.c
fs/proc/root.c
fs/proc/stat.c
fs/proc/task_mmu.c
fs/proc/vmcore.c
fs/sysfs/group.c
include/asm-generic/pgtable.h
include/asm-generic/tlb.h
include/linux/bitmap.h
include/linux/bitops.h
include/linux/cpumask.h
include/linux/memory_hotplug.h
include/linux/mm.h
include/linux/mmzone.h
include/linux/pagewalk.h
include/linux/proc_fs.h
include/linux/ptdump.h [new file with mode: 0644]
include/linux/seq_file.h
include/linux/slab.h
include/linux/string.h
include/linux/sunrpc/stats.h
ipc/mqueue.c
ipc/msg.c
ipc/sem.c
ipc/util.c
kernel/configs.c
kernel/irq/proc.c
kernel/kallsyms.c
kernel/latencytop.c
kernel/locking/lockdep_proc.c
kernel/module.c
kernel/profile.c
kernel/sched/psi.c
lib/bitmap.c
lib/string.c
lib/test_bitmap.c
mm/Kconfig.debug
mm/Makefile
mm/gup.c
mm/hmm.c
mm/memory_hotplug.c
mm/memremap.c
mm/migrate.c
mm/mincore.c
mm/mmu_gather.c
mm/page_alloc.c
mm/pagewalk.c
mm/ptdump.c [new file with mode: 0644]
mm/slab_common.c
mm/sparse.c
mm/swapfile.c
net/atm/mpoa_proc.c
net/atm/proc.c
net/core/dev.c
net/core/filter.c
net/core/pktgen.c
net/ipv4/ipconfig.c
net/ipv4/netfilter/ipt_CLUSTERIP.c
net/ipv4/route.c
net/netfilter/xt_recent.c
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/cache.c
net/sunrpc/stats.c
net/xfrm/xfrm_policy.c
samples/kfifo/bytestream-example.c
samples/kfifo/inttype-example.c
samples/kfifo/record-example.c
scripts/coccinelle/free/devm_free.cocci
sound/core/info.c
sound/soc/codecs/ak4104.c
sound/soc/codecs/cs4270.c
sound/soc/codecs/tlv320aic32x4.c
sound/soc/sunxi/sun4i-spdif.c
tools/include/linux/bitops.h

index ec3b586..7146da0 100644 (file)
@@ -1868,12 +1868,16 @@ There are some more advanced barrier functions:
  (*) smp_mb__before_atomic();
  (*) smp_mb__after_atomic();
 
-     These are for use with atomic (such as add, subtract, increment and
-     decrement) functions that don't return a value, especially when used for
-     reference counting.  These functions do not imply memory barriers.
-
-     These are also used for atomic bitop functions that do not return a
-     value (such as set_bit and clear_bit).
+     These are for use with atomic RMW functions that do not imply memory
+     barriers, but where the code needs a memory barrier. Examples for atomic
+     RMW functions that do not imply are memory barrier are e.g. add,
+     subtract, (failed) conditional operations, _relaxed functions,
+     but not atomic_read or atomic_set. A common example where a memory
+     barrier may be required is when atomic ops are used for reference
+     counting.
+
+     These are also used for atomic RMW bitop functions that do not imply a
+     memory barrier (such as set_bit and clear_bit).
 
      As an example, consider a piece of code that marks an object as being dead
      and then decrements the object's reference count:
index 48b5e10..98de654 100644 (file)
@@ -393,18 +393,23 @@ config HAVE_ARCH_JUMP_LABEL
 config HAVE_ARCH_JUMP_LABEL_RELATIVE
        bool
 
-config HAVE_RCU_TABLE_FREE
+config MMU_GATHER_TABLE_FREE
        bool
 
-config HAVE_RCU_TABLE_NO_INVALIDATE
+config MMU_GATHER_RCU_TABLE_FREE
        bool
+       select MMU_GATHER_TABLE_FREE
 
-config HAVE_MMU_GATHER_PAGE_SIZE
+config MMU_GATHER_PAGE_SIZE
        bool
 
-config HAVE_MMU_GATHER_NO_GATHER
+config MMU_GATHER_NO_RANGE
        bool
 
+config MMU_GATHER_NO_GATHER
+       bool
+       depends on MMU_GATHER_TABLE_FREE
+
 config ARCH_HAVE_NMI_SAFE_CMPXCHG
        bool
 
index 7268222..528d2be 100644 (file)
@@ -119,13 +119,12 @@ static ssize_t srm_env_proc_write(struct file *file, const char __user *buffer,
        return res;
 }
 
-static const struct file_operations srm_env_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = srm_env_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = srm_env_proc_write,
+static const struct proc_ops srm_env_proc_ops = {
+       .proc_open      = srm_env_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = srm_env_proc_write,
 };
 
 static int __init
@@ -182,7 +181,7 @@ srm_env_init(void)
        entry = srm_named_entries;
        while (entry->name && entry->id) {
                if (!proc_create_data(entry->name, 0644, named_dir,
-                            &srm_env_proc_fops, (void *)entry->id))
+                            &srm_env_proc_ops, (void *)entry->id))
                        goto cleanup;
                entry++;
        }
@@ -194,7 +193,7 @@ srm_env_init(void)
                char name[4];
                sprintf(name, "%ld", var_num);
                if (!proc_create_data(name, 0644, numbered_dir,
-                            &srm_env_proc_fops, (void *)var_num))
+                            &srm_env_proc_ops, (void *)var_num))
                        goto cleanup;
        }
 
index 9019ed9..12be7e1 100644 (file)
@@ -273,6 +273,7 @@ static inline void pmd_set(pmd_t *pmdp, pte_t *ptep)
 #define pmd_none(x)                    (!pmd_val(x))
 #define        pmd_bad(x)                      ((pmd_val(x) & ~PAGE_MASK))
 #define pmd_present(x)                 (pmd_val(x))
+#define pmd_leaf(x)                    (pmd_val(x) & _PAGE_HW_SZ)
 #define pmd_clear(xp)                  do { pmd_val(*(xp)) = 0; } while (0)
 
 #define pte_page(pte)          pfn_to_page(pte_pfn(pte))
index 0b1b1c6..497e0e4 100644 (file)
@@ -102,7 +102,7 @@ config ARM
        select HAVE_PERF_EVENTS
        select HAVE_PERF_REGS
        select HAVE_PERF_USER_STACK_DUMP
-       select HAVE_RCU_TABLE_FREE if SMP && ARM_LPAE
+       select MMU_GATHER_RCU_TABLE_FREE if SMP && ARM_LPAE
        select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_RSEQ
        select HAVE_STACKPROTECTOR
index 51beec4..0d3ea35 100644 (file)
@@ -189,6 +189,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
 }
 
 #define pmd_large(pmd)         (pmd_val(pmd) & 2)
+#define pmd_leaf(pmd)          (pmd_val(pmd) & 2)
 #define pmd_bad(pmd)           (pmd_val(pmd) & 2)
 #define pmd_present(pmd)       (pmd_val(pmd))
 
index 5b18295..ad55ab0 100644 (file)
 #define pmd_sect(pmd)          ((pmd_val(pmd) & PMD_TYPE_MASK) == \
                                                 PMD_TYPE_SECT)
 #define pmd_large(pmd)         pmd_sect(pmd)
+#define pmd_leaf(pmd)          pmd_sect(pmd)
 
 #define pud_clear(pudp)                        \
        do {                            \
index 669474a..4d4e7b6 100644 (file)
@@ -37,10 +37,6 @@ static inline void __tlb_remove_table(void *_table)
 
 #include <asm-generic/tlb.h>
 
-#ifndef CONFIG_HAVE_RCU_TABLE_FREE
-#define tlb_remove_table(tlb, entry) tlb_remove_page(tlb, entry)
-#endif
-
 static inline void
 __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, unsigned long addr)
 {
index 312cb89..4247ebf 100644 (file)
@@ -17,9 +17,9 @@ static ssize_t atags_read(struct file *file, char __user *buf,
        return simple_read_from_buffer(buf, count, ppos, b->data, b->size);
 }
 
-static const struct file_operations atags_fops = {
-       .read = atags_read,
-       .llseek = default_llseek,
+static const struct proc_ops atags_proc_ops = {
+       .proc_read      = atags_read,
+       .proc_lseek     = default_llseek,
 };
 
 #define BOOT_PARAMS_SIZE 1536
@@ -61,7 +61,7 @@ static int __init init_atags_procfs(void)
        b->size = size;
        memcpy(b->data, atags_copy, size);
 
-       tags_entry = proc_create_data("atags", 0400, NULL, &atags_fops, b);
+       tags_entry = proc_create_data("atags", 0400, NULL, &atags_proc_ops, b);
        if (!tags_entry)
                goto nomem;
 
index 788c5cf..84718ed 100644 (file)
@@ -162,12 +162,12 @@ static ssize_t alignment_proc_write(struct file *file, const char __user *buffer
        return count;
 }
 
-static const struct file_operations alignment_proc_fops = {
-       .open           = alignment_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = alignment_proc_write,
+static const struct proc_ops alignment_proc_ops = {
+       .proc_open      = alignment_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = alignment_proc_write,
 };
 #endif /* CONFIG_PROC_FS */
 
@@ -1016,7 +1016,7 @@ static int __init alignment_init(void)
        struct proc_dir_entry *res;
 
        res = proc_create("cpu/alignment", S_IWUSR | S_IRUGO, NULL,
-                         &alignment_proc_fops);
+                         &alignment_proc_ops);
        if (!res)
                return -ENOMEM;
 #endif
index e822af0..9414d72 100644 (file)
@@ -221,7 +221,7 @@ EXPORT_SYMBOL(arm_coherent_dma_ops);
 
 static int __dma_supported(struct device *dev, u64 mask, bool warn)
 {
-       unsigned long max_dma_pfn = min(max_pfn, arm_dma_pfn_limit);
+       unsigned long max_dma_pfn = min(max_pfn - 1, arm_dma_pfn_limit);
 
        /*
         * Translate the device's DMA mask to a PFN limit.  This
index de238b5..0b30e88 100644 (file)
@@ -104,6 +104,7 @@ config ARM64
        select GENERIC_IRQ_SHOW
        select GENERIC_IRQ_SHOW_LEVEL
        select GENERIC_PCI_IOMAP
+       select GENERIC_PTDUMP
        select GENERIC_SCHED_CLOCK
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_STRNCPY_FROM_USER
@@ -164,7 +165,7 @@ config ARM64
        select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_FUNCTION_ARG_ACCESS_API
        select HAVE_FUTEX_CMPXCHG if FUTEX
-       select HAVE_RCU_TABLE_FREE
+       select MMU_GATHER_RCU_TABLE_FREE
        select HAVE_RSEQ
        select HAVE_STACKPROTECTOR
        select HAVE_SYSCALL_TRACEPOINTS
index cf09010..1c906d9 100644 (file)
@@ -1,22 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
-config ARM64_PTDUMP_CORE
-       def_bool n
-
-config ARM64_PTDUMP_DEBUGFS
-       bool "Export kernel pagetable layout to userspace via debugfs"
-       depends on DEBUG_KERNEL
-       select ARM64_PTDUMP_CORE
-       select DEBUG_FS
-        help
-         Say Y here if you want to show the kernel pagetable layout in a
-         debugfs file. This information is only useful for kernel developers
-         who are working in architecture specific areas of the kernel.
-         It is probably not a good idea to enable this feature in a production
-         kernel.
-
-         If in doubt, say N.
-
 config PID_IN_CONTEXTIDR
        bool "Write the current PID to the CONTEXTIDR register"
        help
@@ -42,7 +25,7 @@ config ARM64_RANDOMIZE_TEXT_OFFSET
 
 config DEBUG_WX
        bool "Warn on W+X mappings at boot"
-       select ARM64_PTDUMP_CORE
+       select PTDUMP_CORE
        ---help---
          Generate a warning if any W+X mappings are found at boot.
 
index cd5de0e..538c85e 100644 (file)
@@ -441,6 +441,7 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
                                 PMD_TYPE_TABLE)
 #define pmd_sect(pmd)          ((pmd_val(pmd) & PMD_TYPE_MASK) == \
                                 PMD_TYPE_SECT)
+#define pmd_leaf(pmd)          pmd_sect(pmd)
 
 #if defined(CONFIG_ARM64_64K_PAGES) || CONFIG_PGTABLE_LEVELS < 3
 static inline bool pud_sect(pud_t pud) { return false; }
@@ -525,6 +526,7 @@ static inline void pte_unmap(pte_t *pte) { }
 #define pud_none(pud)          (!pud_val(pud))
 #define pud_bad(pud)           (!(pud_val(pud) & PUD_TABLE_BIT))
 #define pud_present(pud)       pte_present(pud_pte(pud))
+#define pud_leaf(pud)          pud_sect(pud)
 #define pud_valid(pud)         pte_valid(pud_pte(pud))
 
 static inline void set_pud(pud_t *pudp, pud_t pud)
index 0b8e726..38187f7 100644 (file)
@@ -5,7 +5,7 @@
 #ifndef __ASM_PTDUMP_H
 #define __ASM_PTDUMP_H
 
-#ifdef CONFIG_ARM64_PTDUMP_CORE
+#ifdef CONFIG_PTDUMP_CORE
 
 #include <linux/mm_types.h>
 #include <linux/seq_file.h>
@@ -21,15 +21,15 @@ struct ptdump_info {
        unsigned long                   base_addr;
 };
 
-void ptdump_walk_pgd(struct seq_file *s, struct ptdump_info *info);
-#ifdef CONFIG_ARM64_PTDUMP_DEBUGFS
+void ptdump_walk(struct seq_file *s, struct ptdump_info *info);
+#ifdef CONFIG_PTDUMP_DEBUGFS
 void ptdump_debugfs_register(struct ptdump_info *info, const char *name);
 #else
 static inline void ptdump_debugfs_register(struct ptdump_info *info,
                                           const char *name) { }
 #endif
 void ptdump_check_wx(void);
-#endif /* CONFIG_ARM64_PTDUMP_CORE */
+#endif /* CONFIG_PTDUMP_CORE */
 
 #ifdef CONFIG_DEBUG_WX
 #define debug_checkwx()        ptdump_check_wx()
index 849c1df..d91030f 100644 (file)
@@ -4,8 +4,8 @@ obj-y                           := dma-mapping.o extable.o fault.o init.o \
                                   ioremap.o mmap.o pgd.o mmu.o \
                                   context.o proc.o pageattr.o
 obj-$(CONFIG_HUGETLB_PAGE)     += hugetlbpage.o
-obj-$(CONFIG_ARM64_PTDUMP_CORE)        += dump.o
-obj-$(CONFIG_ARM64_PTDUMP_DEBUGFS)     += ptdump_debugfs.o
+obj-$(CONFIG_PTDUMP_CORE)      += dump.o
+obj-$(CONFIG_PTDUMP_DEBUGFS)   += ptdump_debugfs.o
 obj-$(CONFIG_NUMA)             += numa.o
 obj-$(CONFIG_DEBUG_VIRTUAL)    += physaddr.o
 KASAN_SANITIZE_physaddr.o      += n
index 0a920b5..860c00e 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/io.h>
 #include <linux/init.h>
 #include <linux/mm.h>
+#include <linux/ptdump.h>
 #include <linux/sched.h>
 #include <linux/seq_file.h>
 
@@ -75,10 +76,11 @@ static struct addr_marker address_markers[] = {
  * dumps out a description of the range.
  */
 struct pg_state {
+       struct ptdump_state ptdump;
        struct seq_file *seq;
        const struct addr_marker *marker;
        unsigned long start_address;
-       unsigned level;
+       int level;
        u64 current_prot;
        bool check_wx;
        unsigned long wx_pages;
@@ -174,11 +176,14 @@ struct pg_level {
 };
 
 static struct pg_level pg_level[] = {
-       {
-       }, { /* pgd */
+       { /* pgd */
                .name   = "PGD",
                .bits   = pte_bits,
                .num    = ARRAY_SIZE(pte_bits),
+       }, { /* p4d */
+               .name   = "P4D",
+               .bits   = pte_bits,
+               .num    = ARRAY_SIZE(pte_bits),
        }, { /* pud */
                .name   = (CONFIG_PGTABLE_LEVELS > 3) ? "PUD" : "PGD",
                .bits   = pte_bits,
@@ -241,13 +246,17 @@ static void note_prot_wx(struct pg_state *st, unsigned long addr)
        st->wx_pages += (addr - st->start_address) / PAGE_SIZE;
 }
 
-static void note_page(struct pg_state *st, unsigned long addr, unsigned level,
-                               u64 val)
+static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
+                     unsigned long val)
 {
+       struct pg_state *st = container_of(pt_st, struct pg_state, ptdump);
        static const char units[] = "KMGTPE";
-       u64 prot = val & pg_level[level].mask;
+       u64 prot = 0;
+
+       if (level >= 0)
+               prot = val & pg_level[level].mask;
 
-       if (!st->level) {
+       if (st->level == -1) {
                st->level = level;
                st->current_prot = prot;
                st->start_address = addr;
@@ -260,21 +269,22 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level,
                if (st->current_prot) {
                        note_prot_uxn(st, addr);
                        note_prot_wx(st, addr);
-                       pt_dump_seq_printf(st->seq, "0x%016lx-0x%016lx   ",
+               }
+
+               pt_dump_seq_printf(st->seq, "0x%016lx-0x%016lx   ",
                                   st->start_address, addr);
 
-                       delta = (addr - st->start_address) >> 10;
-                       while (!(delta & 1023) && unit[1]) {
-                               delta >>= 10;
-                               unit++;
-                       }
-                       pt_dump_seq_printf(st->seq, "%9lu%c %s", delta, *unit,
-                                  pg_level[st->level].name);
-                       if (pg_level[st->level].bits)
-                               dump_prot(st, pg_level[st->level].bits,
-                                         pg_level[st->level].num);
-                       pt_dump_seq_puts(st->seq, "\n");
+               delta = (addr - st->start_address) >> 10;
+               while (!(delta & 1023) && unit[1]) {
+                       delta >>= 10;
+                       unit++;
                }
+               pt_dump_seq_printf(st->seq, "%9lu%c %s", delta, *unit,
+                                  pg_level[st->level].name);
+               if (st->current_prot && pg_level[st->level].bits)
+                       dump_prot(st, pg_level[st->level].bits,
+                                 pg_level[st->level].num);
+               pt_dump_seq_puts(st->seq, "\n");
 
                if (addr >= st->marker[1].start_address) {
                        st->marker++;
@@ -293,85 +303,27 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level,
 
 }
 
-static void walk_pte(struct pg_state *st, pmd_t *pmdp, unsigned long start,
-                    unsigned long end)
-{
-       unsigned long addr = start;
-       pte_t *ptep = pte_offset_kernel(pmdp, start);
-
-       do {
-               note_page(st, addr, 4, READ_ONCE(pte_val(*ptep)));
-       } while (ptep++, addr += PAGE_SIZE, addr != end);
-}
-
-static void walk_pmd(struct pg_state *st, pud_t *pudp, unsigned long start,
-                    unsigned long end)
-{
-       unsigned long next, addr = start;
-       pmd_t *pmdp = pmd_offset(pudp, start);
-
-       do {
-               pmd_t pmd = READ_ONCE(*pmdp);
-               next = pmd_addr_end(addr, end);
-
-               if (pmd_none(pmd) || pmd_sect(pmd)) {
-                       note_page(st, addr, 3, pmd_val(pmd));
-               } else {
-                       BUG_ON(pmd_bad(pmd));
-                       walk_pte(st, pmdp, addr, next);
-               }
-       } while (pmdp++, addr = next, addr != end);
-}
-
-static void walk_pud(struct pg_state *st, pgd_t *pgdp, unsigned long start,
-                    unsigned long end)
+void ptdump_walk(struct seq_file *s, struct ptdump_info *info)
 {
-       unsigned long next, addr = start;
-       pud_t *pudp = pud_offset(pgdp, start);
-
-       do {
-               pud_t pud = READ_ONCE(*pudp);
-               next = pud_addr_end(addr, end);
-
-               if (pud_none(pud) || pud_sect(pud)) {
-                       note_page(st, addr, 2, pud_val(pud));
-               } else {
-                       BUG_ON(pud_bad(pud));
-                       walk_pmd(st, pudp, addr, next);
-               }
-       } while (pudp++, addr = next, addr != end);
-}
+       unsigned long end = ~0UL;
+       struct pg_state st;
 
-static void walk_pgd(struct pg_state *st, struct mm_struct *mm,
-                    unsigned long start)
-{
-       unsigned long end = (start < TASK_SIZE_64) ? TASK_SIZE_64 : 0;
-       unsigned long next, addr = start;
-       pgd_t *pgdp = pgd_offset(mm, start);
-
-       do {
-               pgd_t pgd = READ_ONCE(*pgdp);
-               next = pgd_addr_end(addr, end);
-
-               if (pgd_none(pgd)) {
-                       note_page(st, addr, 1, pgd_val(pgd));
-               } else {
-                       BUG_ON(pgd_bad(pgd));
-                       walk_pud(st, pgdp, addr, next);
-               }
-       } while (pgdp++, addr = next, addr != end);
-}
+       if (info->base_addr < TASK_SIZE_64)
+               end = TASK_SIZE_64;
 
-void ptdump_walk_pgd(struct seq_file *m, struct ptdump_info *info)
-{
-       struct pg_state st = {
-               .seq = m,
+       st = (struct pg_state){
+               .seq = s,
                .marker = info->markers,
+               .ptdump = {
+                       .note_page = note_page,
+                       .range = (struct ptdump_range[]){
+                               {info->base_addr, end},
+                               {0, 0}
+                       }
+               }
        };
 
-       walk_pgd(&st, info->mm, info->base_addr);
-
-       note_page(&st, 0, 0, 0);
+       ptdump_walk_pgd(&st.ptdump, info->mm, NULL);
 }
 
 static void ptdump_initialize(void)
@@ -398,11 +350,19 @@ void ptdump_check_wx(void)
                        { 0, NULL},
                        { -1, NULL},
                },
+               .level = -1,
                .check_wx = true,
+               .ptdump = {
+                       .note_page = note_page,
+                       .range = (struct ptdump_range[]) {
+                               {PAGE_OFFSET, ~0UL},
+                               {0, 0}
+                       }
+               }
        };
 
-       walk_pgd(&st, &init_mm, PAGE_OFFSET);
-       note_page(&st, 0, 0, 0);
+       ptdump_walk_pgd(&st.ptdump, &init_mm, NULL);
+
        if (st.wx_pages || st.uxn_pages)
                pr_warn("Checked W+X mappings: FAILED, %lu W+X pages found, %lu non-UXN pages found\n",
                        st.wx_pages, st.uxn_pages);
index 40797cb..128f708 100644 (file)
@@ -943,13 +943,13 @@ int __init arch_ioremap_pud_supported(void)
         * SW table walks can't handle removal of intermediate entries.
         */
        return IS_ENABLED(CONFIG_ARM64_4K_PAGES) &&
-              !IS_ENABLED(CONFIG_ARM64_PTDUMP_DEBUGFS);
+              !IS_ENABLED(CONFIG_PTDUMP_DEBUGFS);
 }
 
 int __init arch_ioremap_pmd_supported(void)
 {
        /* See arch_ioremap_pud_supported() */
-       return !IS_ENABLED(CONFIG_ARM64_PTDUMP_DEBUGFS);
+       return !IS_ENABLED(CONFIG_PTDUMP_DEBUGFS);
 }
 
 int pud_set_huge(pud_t *pudp, phys_addr_t phys, pgprot_t prot)
index 064163f..1f2eae3 100644 (file)
@@ -7,7 +7,7 @@
 static int ptdump_show(struct seq_file *m, void *v)
 {
        struct ptdump_info *info = m->private;
-       ptdump_walk_pgd(m, info);
+       ptdump_walk(m, info);
        return 0;
 }
 DEFINE_SHOW_ATTRIBUTE(ptdump);
index b392c0a..a25ab9b 100644 (file)
@@ -331,10 +331,10 @@ retry:
        return size;
 }
 
-static const struct file_operations salinfo_event_fops = {
-       .open  = salinfo_event_open,
-       .read  = salinfo_event_read,
-       .llseek = noop_llseek,
+static const struct proc_ops salinfo_event_proc_ops = {
+       .proc_open      = salinfo_event_open,
+       .proc_read      = salinfo_event_read,
+       .proc_lseek     = noop_llseek,
 };
 
 static int
@@ -534,12 +534,12 @@ salinfo_log_write(struct file *file, const char __user *buffer, size_t count, lo
        return count;
 }
 
-static const struct file_operations salinfo_data_fops = {
-       .open    = salinfo_log_open,
-       .release = salinfo_log_release,
-       .read    = salinfo_log_read,
-       .write   = salinfo_log_write,
-       .llseek  = default_llseek,
+static const struct proc_ops salinfo_data_proc_ops = {
+       .proc_open      = salinfo_log_open,
+       .proc_release   = salinfo_log_release,
+       .proc_read      = salinfo_log_read,
+       .proc_write     = salinfo_log_write,
+       .proc_lseek     = default_llseek,
 };
 
 static int salinfo_cpu_online(unsigned int cpu)
@@ -617,13 +617,13 @@ salinfo_init(void)
                        continue;
 
                entry = proc_create_data("event", S_IRUSR, dir,
-                                        &salinfo_event_fops, data);
+                                        &salinfo_event_proc_ops, data);
                if (!entry)
                        continue;
                *sdir++ = entry;
 
                entry = proc_create_data("data", S_IRUSR | S_IWUSR, dir,
-                                        &salinfo_data_fops, data);
+                                        &salinfo_data_proc_ops, data);
                if (!entry)
                        continue;
                *sdir++ = entry;
index 3b9cab8..857fa2a 100644 (file)
@@ -26,9 +26,9 @@ static ssize_t bootinfo_read(struct file *file, char __user *buf,
                                       bootinfo_size);
 }
 
-static const struct file_operations bootinfo_fops = {
-       .read = bootinfo_read,
-       .llseek = default_llseek,
+static const struct proc_ops bootinfo_proc_ops = {
+       .proc_read      = bootinfo_read,
+       .proc_lseek     = default_llseek,
 };
 
 void __init save_bootinfo(const struct bi_record *bi)
@@ -67,7 +67,7 @@ static int __init init_bootinfo_procfs(void)
        if (!bootinfo_copy)
                return -ENOMEM;
 
-       pde = proc_create_data("bootinfo", 0400, NULL, &bootinfo_fops, NULL);
+       pde = proc_create_data("bootinfo", 0400, NULL, &bootinfo_proc_ops, NULL);
        if (!pde) {
                kfree(bootinfo_copy);
                return -ENOMEM;
index 91b89aa..aef5378 100644 (file)
@@ -639,6 +639,11 @@ static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
 
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
+#ifdef _PAGE_HUGE
+#define pmd_leaf(pmd)  ((pmd_val(pmd) & _PAGE_HUGE) != 0)
+#define pud_leaf(pud)  ((pud_val(pud) & _PAGE_HUGE) != 0)
+#endif
+
 #define gup_fast_permitted(start, end) (!cpu_has_dc_aliases)
 
 #include <asm-generic/pgtable.h>
index 8126f15..61c0334 100644 (file)
@@ -89,13 +89,12 @@ static ssize_t pvc_line_proc_write(struct file *file, const char __user *buf,
        return count;
 }
 
-static const struct file_operations pvc_line_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = pvc_line_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = pvc_line_proc_write,
+static const struct proc_ops pvc_line_proc_ops = {
+       .proc_open      = pvc_line_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = pvc_line_proc_write,
 };
 
 static ssize_t pvc_scroll_proc_write(struct file *file, const char __user *buf,
@@ -148,13 +147,12 @@ static int pvc_scroll_proc_open(struct inode *inode, struct file *file)
        return single_open(file, pvc_scroll_proc_show, NULL);
 }
 
-static const struct file_operations pvc_scroll_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = pvc_scroll_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = pvc_scroll_proc_write,
+static const struct proc_ops pvc_scroll_proc_ops = {
+       .proc_open      = pvc_scroll_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = pvc_scroll_proc_write,
 };
 
 void pvc_proc_timerfunc(struct timer_list *unused)
@@ -189,12 +187,11 @@ static int __init pvc_proc_init(void)
        }
        for (i = 0; i < PVC_NLINES; i++) {
                proc_entry = proc_create_data(pvc_linename[i], 0644, dir,
-                                       &pvc_line_proc_fops, &pvc_linedata[i]);
+                                       &pvc_line_proc_ops, &pvc_linedata[i]);
                if (proc_entry == NULL)
                        goto error;
        }
-       proc_entry = proc_create("scroll", 0644, dir,
-                                &pvc_scroll_proc_fops);
+       proc_entry = proc_create("scroll", 0644, dir, &pvc_scroll_proc_ops);
        if (proc_entry == NULL)
                goto error;
 
index c150a9d..bf2b538 100644 (file)
@@ -222,9 +222,8 @@ config PPC
        select HAVE_HARDLOCKUP_DETECTOR_PERF    if PERF_EVENTS && HAVE_PERF_EVENTS_NMI && !HAVE_HARDLOCKUP_DETECTOR_ARCH
        select HAVE_PERF_REGS
        select HAVE_PERF_USER_STACK_DUMP
-       select HAVE_RCU_TABLE_FREE              if SMP
-       select HAVE_RCU_TABLE_NO_INVALIDATE     if HAVE_RCU_TABLE_FREE
-       select HAVE_MMU_GATHER_PAGE_SIZE
+       select MMU_GATHER_RCU_TABLE_FREE
+       select MMU_GATHER_PAGE_SIZE
        select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_RELIABLE_STACKTRACE         if PPC_BOOK3S_64 && CPU_LITTLE_ENDIAN
        select HAVE_SYSCALL_TRACEPOINTS
index 9983177..dc5c039 100644 (file)
@@ -49,7 +49,6 @@ static inline void pgtable_free(void *table, unsigned index_size)
 
 #define get_hugepd_cache_index(x)  (x)
 
-#ifdef CONFIG_SMP
 static inline void pgtable_free_tlb(struct mmu_gather *tlb,
                                    void *table, int shift)
 {
@@ -66,13 +65,6 @@ static inline void __tlb_remove_table(void *_table)
 
        pgtable_free(table, shift);
 }
-#else
-static inline void pgtable_free_tlb(struct mmu_gather *tlb,
-                                   void *table, int shift)
-{
-       pgtable_free(table, shift);
-}
-#endif
 
 static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
                                  unsigned long address)
index f6968c8..a41e91b 100644 (file)
@@ -19,9 +19,7 @@ extern struct vmemmap_backing *vmemmap_list;
 extern pmd_t *pmd_fragment_alloc(struct mm_struct *, unsigned long);
 extern void pmd_fragment_free(unsigned long *);
 extern void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift);
-#ifdef CONFIG_SMP
 extern void __tlb_remove_table(void *_table);
-#endif
 void pte_frag_destroy(void *pte_frag);
 
 static inline pgd_t *radix__pgd_alloc(struct mm_struct *mm)
index b01624e..201a69e 100644 (file)
@@ -1355,18 +1355,21 @@ static inline bool is_pte_rw_upgrade(unsigned long old_val, unsigned long new_va
  * Like pmd_huge() and pmd_large(), but works regardless of config options
  */
 #define pmd_is_leaf pmd_is_leaf
+#define pmd_leaf pmd_is_leaf
 static inline bool pmd_is_leaf(pmd_t pmd)
 {
        return !!(pmd_raw(pmd) & cpu_to_be64(_PAGE_PTE));
 }
 
 #define pud_is_leaf pud_is_leaf
+#define pud_leaf pud_is_leaf
 static inline bool pud_is_leaf(pud_t pud)
 {
        return !!(pud_raw(pud) & cpu_to_be64(_PAGE_PTE));
 }
 
 #define pgd_is_leaf pgd_is_leaf
+#define pgd_leaf pgd_is_leaf
 static inline bool pgd_is_leaf(pgd_t pgd)
 {
        return !!(pgd_raw(pgd) & cpu_to_be64(_PAGE_PTE));
index 332b13b..29c4366 100644 (file)
@@ -46,7 +46,6 @@ static inline void pgtable_free(void *table, int shift)
 
 #define get_hugepd_cache_index(x)      (x)
 
-#ifdef CONFIG_SMP
 static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift)
 {
        unsigned long pgf = (unsigned long)table;
@@ -64,13 +63,6 @@ static inline void __tlb_remove_table(void *_table)
        pgtable_free(table, shift);
 }
 
-#else
-static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift)
-{
-       pgtable_free(table, shift);
-}
-#endif
-
 static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table,
                                  unsigned long address)
 {
index b2c0be9..7f3a8b9 100644 (file)
 
 #define tlb_flush tlb_flush
 extern void tlb_flush(struct mmu_gather *tlb);
+/*
+ * book3s:
+ * Hash does not use the linux page-tables, so we can avoid
+ * the TLB invalidate for page-table freeing, Radix otoh does use the
+ * page-tables and needs the TLBI.
+ *
+ * nohash:
+ * We still do TLB invalidate in the __pte_free_tlb routine before we
+ * add the page table pages to mmu gather table batch.
+ */
+#define tlb_needs_table_invalidate()   radix_enabled()
 
 /* Get the generic bits... */
 #include <asm-generic/tlb.h>
index be3758d..8778174 100644 (file)
@@ -39,10 +39,10 @@ static int page_map_mmap( struct file *file, struct vm_area_struct *vma )
        return 0;
 }
 
-static const struct file_operations page_map_fops = {
-       .llseek = page_map_seek,
-       .read   = page_map_read,
-       .mmap   = page_map_mmap
+static const struct proc_ops page_map_proc_ops = {
+       .proc_lseek     = page_map_seek,
+       .proc_read      = page_map_read,
+       .proc_mmap      = page_map_mmap,
 };
 
 
@@ -51,7 +51,7 @@ static int __init proc_ppc64_init(void)
        struct proc_dir_entry *pde;
 
        pde = proc_create_data("powerpc/systemcfg", S_IFREG | 0444, NULL,
-                              &page_map_fops, vdso_data);
+                              &page_map_proc_ops, vdso_data);
        if (!pde)
                return 1;
        proc_set_size(pde, PAGE_SIZE);
index 487dcd8..2d33f34 100644 (file)
@@ -159,12 +159,12 @@ static int poweron_open(struct inode *inode, struct file *file)
        return single_open(file, ppc_rtas_poweron_show, NULL);
 }
 
-static const struct file_operations ppc_rtas_poweron_operations = {
-       .open           = poweron_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .write          = ppc_rtas_poweron_write,
-       .release        = single_release,
+static const struct proc_ops ppc_rtas_poweron_proc_ops = {
+       .proc_open      = poweron_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_write     = ppc_rtas_poweron_write,
+       .proc_release   = single_release,
 };
 
 static int progress_open(struct inode *inode, struct file *file)
@@ -172,12 +172,12 @@ static int progress_open(struct inode *inode, struct file *file)
        return single_open(file, ppc_rtas_progress_show, NULL);
 }
 
-static const struct file_operations ppc_rtas_progress_operations = {
-       .open           = progress_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .write          = ppc_rtas_progress_write,
-       .release        = single_release,
+static const struct proc_ops ppc_rtas_progress_proc_ops = {
+       .proc_open      = progress_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_write     = ppc_rtas_progress_write,
+       .proc_release   = single_release,
 };
 
 static int clock_open(struct inode *inode, struct file *file)
@@ -185,12 +185,12 @@ static int clock_open(struct inode *inode, struct file *file)
        return single_open(file, ppc_rtas_clock_show, NULL);
 }
 
-static const struct file_operations ppc_rtas_clock_operations = {
-       .open           = clock_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .write          = ppc_rtas_clock_write,
-       .release        = single_release,
+static const struct proc_ops ppc_rtas_clock_proc_ops = {
+       .proc_open      = clock_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_write     = ppc_rtas_clock_write,
+       .proc_release   = single_release,
 };
 
 static int tone_freq_open(struct inode *inode, struct file *file)
@@ -198,12 +198,12 @@ static int tone_freq_open(struct inode *inode, struct file *file)
        return single_open(file, ppc_rtas_tone_freq_show, NULL);
 }
 
-static const struct file_operations ppc_rtas_tone_freq_operations = {
-       .open           = tone_freq_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .write          = ppc_rtas_tone_freq_write,
-       .release        = single_release,
+static const struct proc_ops ppc_rtas_tone_freq_proc_ops = {
+       .proc_open      = tone_freq_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_write     = ppc_rtas_tone_freq_write,
+       .proc_release   = single_release,
 };
 
 static int tone_volume_open(struct inode *inode, struct file *file)
@@ -211,12 +211,12 @@ static int tone_volume_open(struct inode *inode, struct file *file)
        return single_open(file, ppc_rtas_tone_volume_show, NULL);
 }
 
-static const struct file_operations ppc_rtas_tone_volume_operations = {
-       .open           = tone_volume_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .write          = ppc_rtas_tone_volume_write,
-       .release        = single_release,
+static const struct proc_ops ppc_rtas_tone_volume_proc_ops = {
+       .proc_open      = tone_volume_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_write     = ppc_rtas_tone_volume_write,
+       .proc_release   = single_release,
 };
 
 static int ppc_rtas_find_all_sensors(void);
@@ -238,17 +238,17 @@ static int __init proc_rtas_init(void)
                return -ENODEV;
 
        proc_create("powerpc/rtas/progress", 0644, NULL,
-                   &ppc_rtas_progress_operations);
+                   &ppc_rtas_progress_proc_ops);
        proc_create("powerpc/rtas/clock", 0644, NULL,
-                   &ppc_rtas_clock_operations);
+                   &ppc_rtas_clock_proc_ops);
        proc_create("powerpc/rtas/poweron", 0644, NULL,
-                   &ppc_rtas_poweron_operations);
+                   &ppc_rtas_poweron_proc_ops);
        proc_create_single("powerpc/rtas/sensors", 0444, NULL,
                        ppc_rtas_sensors_show);
        proc_create("powerpc/rtas/frequency", 0644, NULL,
-                   &ppc_rtas_tone_freq_operations);
+                   &ppc_rtas_tone_freq_proc_ops);
        proc_create("powerpc/rtas/volume", 0644, NULL,
-                   &ppc_rtas_tone_volume_operations);
+                   &ppc_rtas_tone_volume_proc_ops);
        proc_create_single("powerpc/rtas/rmo_buffer", 0400, NULL,
                        ppc_rtas_rmo_buf_show);
        return 0;
index 84f7947..a99179d 100644 (file)
@@ -655,7 +655,7 @@ struct rtas_flash_file {
        const char *filename;
        const char *rtas_call_name;
        int *status;
-       const struct file_operations fops;
+       const struct proc_ops ops;
 };
 
 static const struct rtas_flash_file rtas_flash_files[] = {
@@ -663,36 +663,36 @@ static const struct rtas_flash_file rtas_flash_files[] = {
                .filename       = "powerpc/rtas/" FIRMWARE_FLASH_NAME,
                .rtas_call_name = "ibm,update-flash-64-and-reboot",
                .status         = &rtas_update_flash_data.status,
-               .fops.read      = rtas_flash_read_msg,
-               .fops.write     = rtas_flash_write,
-               .fops.release   = rtas_flash_release,
-               .fops.llseek    = default_llseek,
+               .ops.proc_read  = rtas_flash_read_msg,
+               .ops.proc_write = rtas_flash_write,
+               .ops.proc_release = rtas_flash_release,
+               .ops.proc_lseek = default_llseek,
        },
        {
                .filename       = "powerpc/rtas/" FIRMWARE_UPDATE_NAME,
                .rtas_call_name = "ibm,update-flash-64-and-reboot",
                .status         = &rtas_update_flash_data.status,
-               .fops.read      = rtas_flash_read_num,
-               .fops.write     = rtas_flash_write,
-               .fops.release   = rtas_flash_release,
-               .fops.llseek    = default_llseek,
+               .ops.proc_read  = rtas_flash_read_num,
+               .ops.proc_write = rtas_flash_write,
+               .ops.proc_release = rtas_flash_release,
+               .ops.proc_lseek = default_llseek,
        },
        {
                .filename       = "powerpc/rtas/" VALIDATE_FLASH_NAME,
                .rtas_call_name = "ibm,validate-flash-image",
                .status         = &rtas_validate_flash_data.status,
-               .fops.read      = validate_flash_read,
-               .fops.write     = validate_flash_write,
-               .fops.release   = validate_flash_release,
-               .fops.llseek    = default_llseek,
+               .ops.proc_read  = validate_flash_read,
+               .ops.proc_write = validate_flash_write,
+               .ops.proc_release = validate_flash_release,
+               .ops.proc_lseek = default_llseek,
        },
        {
                .filename       = "powerpc/rtas/" MANAGE_FLASH_NAME,
                .rtas_call_name = "ibm,manage-flash-image",
                .status         = &rtas_manage_flash_data.status,
-               .fops.read      = manage_flash_read,
-               .fops.write     = manage_flash_write,
-               .fops.llseek    = default_llseek,
+               .ops.proc_read  = manage_flash_read,
+               .ops.proc_write = manage_flash_write,
+               .ops.proc_lseek = default_llseek,
        }
 };
 
@@ -723,7 +723,7 @@ static int __init rtas_flash_init(void)
                const struct rtas_flash_file *f = &rtas_flash_files[i];
                int token;
 
-               if (!proc_create(f->filename, 0600, NULL, &f->fops))
+               if (!proc_create(f->filename, 0600, NULL, &f->ops))
                        goto enomem;
 
                /*
index 8d02e04..89b798f 100644 (file)
@@ -385,12 +385,12 @@ static __poll_t rtas_log_poll(struct file *file, poll_table * wait)
        return 0;
 }
 
-static const struct file_operations proc_rtas_log_operations = {
-       .read =         rtas_log_read,
-       .poll =         rtas_log_poll,
-       .open =         rtas_log_open,
-       .release =      rtas_log_release,
-       .llseek =       noop_llseek,
+static const struct proc_ops rtas_log_proc_ops = {
+       .proc_read      = rtas_log_read,
+       .proc_poll      = rtas_log_poll,
+       .proc_open      = rtas_log_open,
+       .proc_release   = rtas_log_release,
+       .proc_lseek     = noop_llseek,
 };
 
 static int enable_surveillance(int timeout)
@@ -572,7 +572,7 @@ static int __init rtas_init(void)
                return -ENODEV;
 
        entry = proc_create("powerpc/rtas/error_log", 0400, NULL,
-                           &proc_rtas_log_operations);
+                           &rtas_log_proc_ops);
        if (!entry)
                printk(KERN_ERR "Failed to create error_log proc entry\n");
 
index 75483b4..2bf7e1b 100644 (file)
@@ -378,7 +378,6 @@ static inline void pgtable_free(void *table, int index)
        }
 }
 
-#ifdef CONFIG_SMP
 void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int index)
 {
        unsigned long pgf = (unsigned long)table;
@@ -395,12 +394,6 @@ void __tlb_remove_table(void *_table)
 
        return pgtable_free(table, index);
 }
-#else
-void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int index)
-{
-       return pgtable_free(table, index);
-}
-#endif
 
 #ifdef CONFIG_PROC_FS
 atomic_long_t direct_pages_count[MMU_PAGE_COUNT];
index 50d68d2..3c7dec7 100644 (file)
@@ -1616,11 +1616,11 @@ static ssize_t topology_write(struct file *file, const char __user *buf,
        return count;
 }
 
-static const struct file_operations topology_ops = {
-       .read = seq_read,
-       .write = topology_write,
-       .open = topology_open,
-       .release = single_release
+static const struct proc_ops topology_proc_ops = {
+       .proc_read      = seq_read,
+       .proc_write     = topology_write,
+       .proc_open      = topology_open,
+       .proc_release   = single_release,
 };
 
 static int topology_update_init(void)
@@ -1630,7 +1630,7 @@ static int topology_update_init(void)
        if (vphn_enabled)
                topology_schedule_update();
 
-       if (!proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops))
+       if (!proc_create("powerpc/topology_updates", 0644, NULL, &topology_proc_ops))
                return -ENOMEM;
 
        topology_inited = 1;
index 60cb29a..3c3da25 100644 (file)
@@ -582,12 +582,12 @@ static int vcpudispatch_stats_open(struct inode *inode, struct file *file)
        return single_open(file, vcpudispatch_stats_display, NULL);
 }
 
-static const struct file_operations vcpudispatch_stats_proc_ops = {
-       .open           = vcpudispatch_stats_open,
-       .read           = seq_read,
-       .write          = vcpudispatch_stats_write,
-       .llseek         = seq_lseek,
-       .release        = single_release,
+static const struct proc_ops vcpudispatch_stats_proc_ops = {
+       .proc_open      = vcpudispatch_stats_open,
+       .proc_read      = seq_read,
+       .proc_write     = vcpudispatch_stats_write,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
 };
 
 static ssize_t vcpudispatch_stats_freq_write(struct file *file,
@@ -626,12 +626,12 @@ static int vcpudispatch_stats_freq_open(struct inode *inode, struct file *file)
        return single_open(file, vcpudispatch_stats_freq_display, NULL);
 }
 
-static const struct file_operations vcpudispatch_stats_freq_proc_ops = {
-       .open           = vcpudispatch_stats_freq_open,
-       .read           = seq_read,
-       .write          = vcpudispatch_stats_freq_write,
-       .llseek         = seq_lseek,
-       .release        = single_release,
+static const struct proc_ops vcpudispatch_stats_freq_proc_ops = {
+       .proc_open      = vcpudispatch_stats_freq_open,
+       .proc_read      = seq_read,
+       .proc_write     = vcpudispatch_stats_freq_write,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
 };
 
 static int __init vcpudispatch_stats_procfs_init(void)
index e33e8bc..f43e778 100644 (file)
@@ -698,12 +698,12 @@ static int lparcfg_open(struct inode *inode, struct file *file)
        return single_open(file, lparcfg_data, NULL);
 }
 
-static const struct file_operations lparcfg_fops = {
-       .read           = seq_read,
-       .write          = lparcfg_write,
-       .open           = lparcfg_open,
-       .release        = single_release,
-       .llseek         = seq_lseek,
+static const struct proc_ops lparcfg_proc_ops = {
+       .proc_read      = seq_read,
+       .proc_write     = lparcfg_write,
+       .proc_open      = lparcfg_open,
+       .proc_release   = single_release,
+       .proc_lseek     = seq_lseek,
 };
 
 static int __init lparcfg_init(void)
@@ -714,7 +714,7 @@ static int __init lparcfg_init(void)
        if (firmware_has_feature(FW_FEATURE_SPLPAR))
                mode |= 0200;
 
-       if (!proc_create("powerpc/lparcfg", mode, NULL, &lparcfg_fops)) {
+       if (!proc_create("powerpc/lparcfg", mode, NULL, &lparcfg_proc_ops)) {
                printk(KERN_ERR "Failed to create powerpc/lparcfg\n");
                return -EIO;
        }
index 8a9c4fb..7f7369f 100644 (file)
@@ -391,9 +391,9 @@ out:
        return rv ? rv : count;
 }
 
-static const struct file_operations ofdt_fops = {
-       .write = ofdt_write,
-       .llseek = noop_llseek,
+static const struct proc_ops ofdt_proc_ops = {
+       .proc_write     = ofdt_write,
+       .proc_lseek     = noop_llseek,
 };
 
 /* create /proc/powerpc/ofdt write-only by root */
@@ -401,7 +401,7 @@ static int proc_ppc64_create_ofdt(void)
 {
        struct proc_dir_entry *ent;
 
-       ent = proc_create("powerpc/ofdt", 0200, NULL, &ofdt_fops);
+       ent = proc_create("powerpc/ofdt", 0200, NULL, &ofdt_proc_ops);
        if (ent)
                proc_set_size(ent, 0);
 
index a000128..2879c4f 100644 (file)
@@ -152,13 +152,12 @@ static int scanlog_release(struct inode * inode, struct file * file)
        return 0;
 }
 
-static const struct file_operations scanlog_fops = {
-       .owner          = THIS_MODULE,
-       .read           = scanlog_read,
-       .write          = scanlog_write,
-       .open           = scanlog_open,
-       .release        = scanlog_release,
-       .llseek         = noop_llseek,
+static const struct proc_ops scanlog_proc_ops = {
+       .proc_read      = scanlog_read,
+       .proc_write     = scanlog_write,
+       .proc_open      = scanlog_open,
+       .proc_release   = scanlog_release,
+       .proc_lseek     = noop_llseek,
 };
 
 static int __init scanlog_init(void)
@@ -176,7 +175,7 @@ static int __init scanlog_init(void)
                goto err;
 
        ent = proc_create("powerpc/rtas/scan-log-dump", 0400, NULL,
-                         &scanlog_fops);
+                         &scanlog_proc_ops);
        if (!ent)
                goto err;
        return 0;
index 36e638d..b15f70a 100644 (file)
@@ -43,6 +43,13 @@ static inline int pud_bad(pud_t pud)
        return !pud_present(pud);
 }
 
+#define pud_leaf       pud_leaf
+static inline int pud_leaf(pud_t pud)
+{
+       return pud_present(pud) &&
+              (pud_val(pud) & (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC));
+}
+
 static inline void set_pud(pud_t *pudp, pud_t pud)
 {
        *pudp = pud;
index f66b873..e430415 100644 (file)
@@ -130,6 +130,13 @@ static inline int pmd_bad(pmd_t pmd)
        return !pmd_present(pmd);
 }
 
+#define pmd_leaf       pmd_leaf
+static inline int pmd_leaf(pmd_t pmd)
+{
+       return pmd_present(pmd) &&
+              (pmd_val(pmd) & (_PAGE_READ | _PAGE_WRITE | _PAGE_EXEC));
+}
+
 static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
 {
        *pmdp = pmd;
index 287714d..7349967 100644 (file)
@@ -163,13 +163,13 @@ config S390
        select HAVE_PERF_USER_STACK_DUMP
        select HAVE_MEMBLOCK_NODE_MAP
        select HAVE_MEMBLOCK_PHYS_MAP
-       select HAVE_MMU_GATHER_NO_GATHER
+       select MMU_GATHER_NO_GATHER
        select HAVE_MOD_ARCH_SPECIFIC
        select HAVE_NOP_MCOUNT
        select HAVE_OPROFILE
        select HAVE_PCI
        select HAVE_PERF_EVENTS
-       select HAVE_RCU_TABLE_FREE
+       select MMU_GATHER_RCU_TABLE_FREE
        select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_RELIABLE_STACKTRACE
        select HAVE_RSEQ
index 7b03037..137a392 100644 (file)
@@ -673,6 +673,7 @@ static inline int pud_none(pud_t pud)
        return pud_val(pud) == _REGION3_ENTRY_EMPTY;
 }
 
+#define pud_leaf       pud_large
 static inline int pud_large(pud_t pud)
 {
        if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) != _REGION_ENTRY_TYPE_R3)
@@ -690,6 +691,7 @@ static inline unsigned long pud_pfn(pud_t pud)
        return (pud_val(pud) & origin_mask) >> PAGE_SHIFT;
 }
 
+#define pmd_leaf       pmd_large
 static inline int pmd_large(pmd_t pmd)
 {
        return (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) != 0;
index ec2b253..fb517b8 100644 (file)
@@ -152,13 +152,12 @@ static ssize_t alignment_proc_write(struct file *file,
        return count;
 }
 
-static const struct file_operations alignment_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = alignment_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = alignment_proc_write,
+static const struct proc_ops alignment_proc_ops = {
+       .proc_open      = alignment_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = alignment_proc_write,
 };
 
 /*
@@ -176,12 +175,12 @@ static int __init alignment_init(void)
                return -ENOMEM;
 
        res = proc_create_data("alignment", S_IWUSR | S_IRUGO, dir,
-                              &alignment_proc_fops, &se_usermode);
+                              &alignment_proc_ops, &se_usermode);
        if (!res)
                return -ENOMEM;
 
         res = proc_create_data("kernel_alignment", S_IWUSR | S_IRUGO, dir,
-                              &alignment_proc_fops, &se_kernmode_warn);
+                              &alignment_proc_ops, &se_kernmode_warn);
         if (!res)
                 return -ENOMEM;
 
index e8c3ea0..c1dd6dd 100644 (file)
@@ -64,8 +64,7 @@ config SPARC64
        select HAVE_FUNCTION_GRAPH_TRACER
        select HAVE_KRETPROBES
        select HAVE_KPROBES
-       select HAVE_RCU_TABLE_FREE if SMP
-       select HAVE_RCU_TABLE_NO_INVALIDATE if HAVE_RCU_TABLE_FREE
+       select MMU_GATHER_RCU_TABLE_FREE if SMP
        select HAVE_MEMBLOCK_NODE_MAP
        select HAVE_ARCH_TRANSPARENT_HUGEPAGE
        select HAVE_DYNAMIC_FTRACE
index 34ff3b4..65494c3 100644 (file)
@@ -683,6 +683,7 @@ static inline unsigned long pte_special(pte_t pte)
        return pte_val(pte) & _PAGE_SPECIAL;
 }
 
+#define pmd_leaf       pmd_large
 static inline unsigned long pmd_large(pmd_t pmd)
 {
        pte_t pte = __pte(pmd_val(pmd));
@@ -867,6 +868,7 @@ static inline unsigned long pud_page_vaddr(pud_t pud)
 /* only used by the stubbed out hugetlb gup code, should never be called */
 #define p4d_page(p4d)                  NULL
 
+#define pud_leaf       pud_large
 static inline unsigned long pud_large(pud_t pud)
 {
        pte_t pte = __pte(pud_val(pud));
index a2f3fa6..6820d35 100644 (file)
@@ -28,6 +28,15 @@ void flush_tlb_pending(void);
 #define __tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
 #define tlb_flush(tlb) flush_tlb_pending()
 
+/*
+ * SPARC64's hardware TLB fill does not use the Linux page-tables
+ * and therefore we don't need a TLBI when freeing page-table pages.
+ */
+
+#ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE
+#define tlb_needs_table_invalidate()   (false)
+#endif
+
 #include <asm-generic/tlb.h>
 
 #endif /* _SPARC64_TLB_H */
index a6292f8..bd48575 100644 (file)
@@ -104,13 +104,12 @@ static ssize_t led_proc_write(struct file *file, const char __user *buffer,
        return count;
 }
 
-static const struct file_operations led_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = led_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = led_proc_write,
+static const struct proc_ops led_proc_ops = {
+       .proc_open      = led_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = led_proc_write,
 };
 
 static struct proc_dir_entry *led;
@@ -121,7 +120,7 @@ static int __init led_init(void)
 {
        timer_setup(&led_blink_timer, led_blink, 0);
 
-       led = proc_create("led", 0, NULL, &led_proc_fops);
+       led = proc_create("led", 0, NULL, &led_proc_ops);
        if (!led)
                return -ENOMEM;
 
index 0117489..b80a1d6 100644 (file)
@@ -752,10 +752,9 @@ static ssize_t mconsole_proc_write(struct file *file,
        return count;
 }
 
-static const struct file_operations mconsole_proc_fops = {
-       .owner          = THIS_MODULE,
-       .write          = mconsole_proc_write,
-       .llseek         = noop_llseek,
+static const struct proc_ops mconsole_proc_ops = {
+       .proc_write     = mconsole_proc_write,
+       .proc_lseek     = noop_llseek,
 };
 
 static int create_proc_mconsole(void)
@@ -765,7 +764,7 @@ static int create_proc_mconsole(void)
        if (notify_socket == NULL)
                return 0;
 
-       ent = proc_create("mconsole", 0200, NULL, &mconsole_proc_fops);
+       ent = proc_create("mconsole", 0200, NULL, &mconsole_proc_ops);
        if (ent == NULL) {
                printk(KERN_INFO "create_proc_mconsole : proc_create failed\n");
                return 0;
index 369fd84..43edc2a 100644 (file)
@@ -55,20 +55,19 @@ static ssize_t exitcode_proc_write(struct file *file,
        return count;
 }
 
-static const struct file_operations exitcode_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = exitcode_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = exitcode_proc_write,
+static const struct proc_ops exitcode_proc_ops = {
+       .proc_open      = exitcode_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = exitcode_proc_write,
 };
 
 static int make_proc_exitcode(void)
 {
        struct proc_dir_entry *ent;
 
-       ent = proc_create("exitcode", 0600, NULL, &exitcode_proc_fops);
+       ent = proc_create("exitcode", 0600, NULL, &exitcode_proc_ops);
        if (ent == NULL) {
                printk(KERN_WARNING "make_proc_exitcode : Failed to register "
                       "/proc/exitcode\n");
index 17045e7..56a0941 100644 (file)
@@ -348,13 +348,12 @@ static ssize_t sysemu_proc_write(struct file *file, const char __user *buf,
        return count;
 }
 
-static const struct file_operations sysemu_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = sysemu_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = sysemu_proc_write,
+static const struct proc_ops sysemu_proc_ops = {
+       .proc_open      = sysemu_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = sysemu_proc_write,
 };
 
 int __init make_proc_sysemu(void)
@@ -363,7 +362,7 @@ int __init make_proc_sysemu(void)
        if (!sysemu_supported)
                return 0;
 
-       ent = proc_create("sysemu", 0600, NULL, &sysemu_proc_fops);
+       ent = proc_create("sysemu", 0600, NULL, &sysemu_proc_ops);
 
        if (ent == NULL)
        {
index 44d2796..beea770 100644 (file)
@@ -120,6 +120,7 @@ config X86
        select GENERIC_IRQ_RESERVATION_MODE
        select GENERIC_IRQ_SHOW
        select GENERIC_PENDING_IRQ              if SMP
+       select GENERIC_PTDUMP
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_STRNCPY_FROM_USER
        select GENERIC_STRNLEN_USER
@@ -202,7 +203,7 @@ config X86
        select HAVE_PCI
        select HAVE_PERF_REGS
        select HAVE_PERF_USER_STACK_DUMP
-       select HAVE_RCU_TABLE_FREE              if PARAVIRT
+       select MMU_GATHER_RCU_TABLE_FREE                if PARAVIRT
        select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_RELIABLE_STACKTRACE         if X86_64 && (UNWINDER_FRAME_POINTER || UNWINDER_ORC) && STACK_VALIDATION
        select HAVE_FUNCTION_ARG_ACCESS_API
index c4eab8e..2e74690 100644 (file)
@@ -62,26 +62,10 @@ config EARLY_PRINTK_USB_XDBC
 config MCSAFE_TEST
        def_bool n
 
-config X86_PTDUMP_CORE
-       def_bool n
-
-config X86_PTDUMP
-       tristate "Export kernel pagetable layout to userspace via debugfs"
-       depends on DEBUG_KERNEL
-       select DEBUG_FS
-       select X86_PTDUMP_CORE
-       ---help---
-         Say Y here if you want to show the kernel pagetable layout in a
-         debugfs file. This information is only useful for kernel developers
-         who are working in architecture specific areas of the kernel.
-         It is probably not a good idea to enable this feature in a production
-         kernel.
-         If in doubt, say "N"
-
 config EFI_PGT_DUMP
        bool "Dump the EFI pagetable"
        depends on EFI
-       select X86_PTDUMP_CORE
+       select PTDUMP_CORE
        ---help---
          Enable this if you want to dump the EFI page table before
          enabling virtual mode. This can be used to debug miscellaneous
@@ -90,7 +74,7 @@ config EFI_PGT_DUMP
 
 config DEBUG_WX
        bool "Warn on W+X mappings at boot"
-       select X86_PTDUMP_CORE
+       select PTDUMP_CORE
        ---help---
          Generate a warning if any W+X mappings are found at boot.
 
index ad97dc1..7e11866 100644 (file)
@@ -29,8 +29,9 @@
 extern pgd_t early_top_pgt[PTRS_PER_PGD];
 int __init __early_make_pgtable(unsigned long address, pmdval_t pmd);
 
-void ptdump_walk_pgd_level(struct seq_file *m, pgd_t *pgd);
-void ptdump_walk_pgd_level_debugfs(struct seq_file *m, pgd_t *pgd, bool user);
+void ptdump_walk_pgd_level(struct seq_file *m, struct mm_struct *mm);
+void ptdump_walk_pgd_level_debugfs(struct seq_file *m, struct mm_struct *mm,
+                                  bool user);
 void ptdump_walk_pgd_level_checkwx(void);
 void ptdump_walk_user_pgd_level_checkwx(void);
 
@@ -239,6 +240,7 @@ static inline unsigned long pgd_pfn(pgd_t pgd)
        return (pgd_val(pgd) & PTE_PFN_MASK) >> PAGE_SHIFT;
 }
 
+#define p4d_leaf       p4d_large
 static inline int p4d_large(p4d_t p4d)
 {
        /* No 512 GiB pages yet */
@@ -247,6 +249,7 @@ static inline int p4d_large(p4d_t p4d)
 
 #define pte_page(pte)  pfn_to_page(pte_pfn(pte))
 
+#define pmd_leaf       pmd_large
 static inline int pmd_large(pmd_t pte)
 {
        return pmd_flags(pte) & _PAGE_PSE;
@@ -874,6 +877,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
        return (pmd_t *)pud_page_vaddr(*pud) + pmd_index(address);
 }
 
+#define pud_leaf       pud_large
 static inline int pud_large(pud_t pud)
 {
        return (pud_val(pud) & (_PAGE_PSE | _PAGE_PRESENT)) ==
@@ -885,6 +889,7 @@ static inline int pud_bad(pud_t pud)
        return (pud_flags(pud) & ~(_KERNPG_TABLE | _PAGE_USER)) != 0;
 }
 #else
+#define pud_leaf       pud_large
 static inline int pud_large(pud_t pud)
 {
        return 0;
@@ -1233,6 +1238,7 @@ static inline bool pgdp_maps_userspace(void *__ptr)
        return (((ptr & ~PAGE_MASK) / sizeof(pgd_t)) < PGD_KERNEL_START);
 }
 
+#define pgd_leaf       pgd_large
 static inline int pgd_large(pgd_t pgd) { return 0; }
 
 #ifdef CONFIG_PAGE_TABLE_ISOLATION
index f23e7aa..820082b 100644 (file)
@@ -29,8 +29,8 @@ static inline void tlb_flush(struct mmu_gather *tlb)
  * shootdown, enablement code for several hypervisors overrides
  * .flush_tlb_others hook in pv_mmu_ops and implements it by issuing
  * a hypercall. To keep software pagetable walkers safe in this case we
- * switch to RCU based table free (HAVE_RCU_TABLE_FREE). See the comment
- * below 'ifdef CONFIG_HAVE_RCU_TABLE_FREE' in include/asm-generic/tlb.h
+ * switch to RCU based table free (MMU_GATHER_RCU_TABLE_FREE). See the comment
+ * below 'ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE' in include/asm-generic/tlb.h
  * for more details.
  */
 static inline void __tlb_remove_table(void *table)
index da532f6..a5c506f 100644 (file)
@@ -396,15 +396,16 @@ static int mtrr_open(struct inode *inode, struct file *file)
        return single_open(file, mtrr_seq_show, NULL);
 }
 
-static const struct file_operations mtrr_fops = {
-       .owner                  = THIS_MODULE,
-       .open                   = mtrr_open,
-       .read                   = seq_read,
-       .llseek                 = seq_lseek,
-       .write                  = mtrr_write,
-       .unlocked_ioctl         = mtrr_ioctl,
-       .compat_ioctl           = mtrr_ioctl,
-       .release                = mtrr_close,
+static const struct proc_ops mtrr_proc_ops = {
+       .proc_open              = mtrr_open,
+       .proc_read              = seq_read,
+       .proc_lseek             = seq_lseek,
+       .proc_write             = mtrr_write,
+       .proc_ioctl             = mtrr_ioctl,
+#ifdef CONFIG_COMPAT
+       .proc_compat_ioctl      = mtrr_ioctl,
+#endif
+       .proc_release           = mtrr_close,
 };
 
 static int __init mtrr_if_init(void)
@@ -417,7 +418,7 @@ static int __init mtrr_if_init(void)
            (!cpu_has(c, X86_FEATURE_CENTAUR_MCR)))
                return -ENODEV;
 
-       proc_create("mtrr", S_IWUSR | S_IRUGO, NULL, &mtrr_fops);
+       proc_create("mtrr", S_IWUSR | S_IRUGO, NULL, &mtrr_proc_ops);
        return 0;
 }
 arch_initcall(mtrr_if_init);
index 98aecb1..98f7c6f 100644 (file)
@@ -28,8 +28,8 @@ CFLAGS_fault.o := -I $(srctree)/$(src)/../include/asm/trace
 obj-$(CONFIG_X86_32)           += pgtable_32.o iomap_32.o
 
 obj-$(CONFIG_HUGETLB_PAGE)     += hugetlbpage.o
-obj-$(CONFIG_X86_PTDUMP_CORE)  += dump_pagetables.o
-obj-$(CONFIG_X86_PTDUMP)       += debug_pagetables.o
+obj-$(CONFIG_PTDUMP_CORE)      += dump_pagetables.o
+obj-$(CONFIG_PTDUMP_DEBUGFS)   += debug_pagetables.o
 
 obj-$(CONFIG_HIGHMEM)          += highmem_32.o
 
index 39001a4..4a3b62f 100644 (file)
@@ -7,7 +7,7 @@
 
 static int ptdump_show(struct seq_file *m, void *v)
 {
-       ptdump_walk_pgd_level_debugfs(m, NULL, false);
+       ptdump_walk_pgd_level_debugfs(m, &init_mm, false);
        return 0;
 }
 
@@ -15,11 +15,8 @@ DEFINE_SHOW_ATTRIBUTE(ptdump);
 
 static int ptdump_curknl_show(struct seq_file *m, void *v)
 {
-       if (current->mm->pgd) {
-               down_read(&current->mm->mmap_sem);
-               ptdump_walk_pgd_level_debugfs(m, current->mm->pgd, false);
-               up_read(&current->mm->mmap_sem);
-       }
+       if (current->mm->pgd)
+               ptdump_walk_pgd_level_debugfs(m, current->mm, false);
        return 0;
 }
 
@@ -28,11 +25,8 @@ DEFINE_SHOW_ATTRIBUTE(ptdump_curknl);
 #ifdef CONFIG_PAGE_TABLE_ISOLATION
 static int ptdump_curusr_show(struct seq_file *m, void *v)
 {
-       if (current->mm->pgd) {
-               down_read(&current->mm->mmap_sem);
-               ptdump_walk_pgd_level_debugfs(m, current->mm->pgd, true);
-               up_read(&current->mm->mmap_sem);
-       }
+       if (current->mm->pgd)
+               ptdump_walk_pgd_level_debugfs(m, current->mm, true);
        return 0;
 }
 
@@ -43,7 +37,7 @@ DEFINE_SHOW_ATTRIBUTE(ptdump_curusr);
 static int ptdump_efi_show(struct seq_file *m, void *v)
 {
        if (efi_mm.pgd)
-               ptdump_walk_pgd_level_debugfs(m, efi_mm.pgd, false);
+               ptdump_walk_pgd_level_debugfs(m, &efi_mm, false);
        return 0;
 }
 
index ab67822..64229da 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/seq_file.h>
 #include <linux/highmem.h>
 #include <linux/pci.h>
+#include <linux/ptdump.h>
 
 #include <asm/e820/types.h>
 #include <asm/pgtable.h>
  * when a "break" in the continuity is found.
  */
 struct pg_state {
+       struct ptdump_state ptdump;
        int level;
-       pgprot_t current_prot;
+       pgprotval_t current_prot;
        pgprotval_t effective_prot;
+       pgprotval_t prot_levels[5];
        unsigned long start_address;
-       unsigned long current_address;
        const struct addr_marker *marker;
        unsigned long lines;
        bool to_dmesg;
        bool check_wx;
        unsigned long wx_pages;
+       struct seq_file *seq;
 };
 
 struct addr_marker {
@@ -174,11 +177,10 @@ static struct addr_marker address_markers[] = {
 /*
  * Print a readable form of a pgprot_t to the seq_file
  */
-static void printk_prot(struct seq_file *m, pgprot_t prot, int level, bool dmsg)
+static void printk_prot(struct seq_file *m, pgprotval_t pr, int level, bool dmsg)
 {
-       pgprotval_t pr = pgprot_val(prot);
        static const char * const level_name[] =
-               { "cr3", "pgd", "p4d", "pud", "pmd", "pte" };
+               { "pgd", "p4d", "pud", "pmd", "pte" };
 
        if (!(pr & _PAGE_PRESENT)) {
                /* Not present */
@@ -202,12 +204,12 @@ static void printk_prot(struct seq_file *m, pgprot_t prot, int level, bool dmsg)
                        pt_dump_cont_printf(m, dmsg, "    ");
 
                /* Bit 7 has a different meaning on level 3 vs 4 */
-               if (level <= 4 && pr & _PAGE_PSE)
+               if (level <= 3 && pr & _PAGE_PSE)
                        pt_dump_cont_printf(m, dmsg, "PSE ");
                else
                        pt_dump_cont_printf(m, dmsg, "    ");
-               if ((level == 5 && pr & _PAGE_PAT) ||
-                   ((level == 4 || level == 3) && pr & _PAGE_PAT_LARGE))
+               if ((level == 4 && pr & _PAGE_PAT) ||
+                   ((level == 3 || level == 2) && pr & _PAGE_PAT_LARGE))
                        pt_dump_cont_printf(m, dmsg, "PAT ");
                else
                        pt_dump_cont_printf(m, dmsg, "    ");
@@ -223,24 +225,11 @@ static void printk_prot(struct seq_file *m, pgprot_t prot, int level, bool dmsg)
        pt_dump_cont_printf(m, dmsg, "%s\n", level_name[level]);
 }
 
-/*
- * On 64 bits, sign-extend the 48 bit address to 64 bit
- */
-static unsigned long normalize_addr(unsigned long u)
-{
-       int shift;
-       if (!IS_ENABLED(CONFIG_X86_64))
-               return u;
-
-       shift = 64 - (__VIRTUAL_MASK_SHIFT + 1);
-       return (signed long)(u << shift) >> shift;
-}
-
-static void note_wx(struct pg_state *st)
+static void note_wx(struct pg_state *st, unsigned long addr)
 {
        unsigned long npages;
 
-       npages = (st->current_address - st->start_address) / PAGE_SIZE;
+       npages = (addr - st->start_address) / PAGE_SIZE;
 
 #ifdef CONFIG_PCI_BIOS
        /*
@@ -248,7 +237,7 @@ static void note_wx(struct pg_state *st)
         * Inform about it, but avoid the warning.
         */
        if (pcibios_enabled && st->start_address >= PAGE_OFFSET + BIOS_BEGIN &&
-           st->current_address <= PAGE_OFFSET + BIOS_END) {
+           addr <= PAGE_OFFSET + BIOS_END) {
                pr_warn_once("x86/mm: PCI BIOS W+X mapping %lu pages\n", npages);
                return;
        }
@@ -260,27 +249,47 @@ static void note_wx(struct pg_state *st)
                  (void *)st->start_address);
 }
 
+static inline pgprotval_t effective_prot(pgprotval_t prot1, pgprotval_t prot2)
+{
+       return (prot1 & prot2 & (_PAGE_USER | _PAGE_RW)) |
+              ((prot1 | prot2) & _PAGE_NX);
+}
+
 /*
  * This function gets called on a break in a continuous series
  * of PTE entries; the next one is different so we need to
  * print what we collected so far.
  */
-static void note_page(struct seq_file *m, struct pg_state *st,
-                     pgprot_t new_prot, pgprotval_t new_eff, int level)
+static void note_page(struct ptdump_state *pt_st, unsigned long addr, int level,
+                     unsigned long val)
 {
-       pgprotval_t prot, cur, eff;
+       struct pg_state *st = container_of(pt_st, struct pg_state, ptdump);
+       pgprotval_t new_prot, new_eff;
+       pgprotval_t cur, eff;
        static const char units[] = "BKMGTPE";
+       struct seq_file *m = st->seq;
+
+       new_prot = val & PTE_FLAGS_MASK;
+
+       if (level > 0) {
+               new_eff = effective_prot(st->prot_levels[level - 1],
+                                        new_prot);
+       } else {
+               new_eff = new_prot;
+       }
+
+       if (level >= 0)
+               st->prot_levels[level] = new_eff;
 
        /*
         * If we have a "break" in the series, we need to flush the state that
         * we have now. "break" is either changing perms, levels or
         * address space marker.
         */
-       prot = pgprot_val(new_prot);
-       cur = pgprot_val(st->current_prot);
+       cur = st->current_prot;
        eff = st->effective_prot;
 
-       if (!st->level) {
+       if (st->level == -1) {
                /* First entry */
                st->current_prot = new_prot;
                st->effective_prot = new_eff;
@@ -289,14 +298,14 @@ static void note_page(struct seq_file *m, struct pg_state *st,
                st->lines = 0;
                pt_dump_seq_printf(m, st->to_dmesg, "---[ %s ]---\n",
                                   st->marker->name);
-       } else if (prot != cur || new_eff != eff || level != st->level ||
-                  st->current_address >= st->marker[1].start_address) {
+       } else if (new_prot != cur || new_eff != eff || level != st->level ||
+                  addr >= st->marker[1].start_address) {
                const char *unit = units;
                unsigned long delta;
                int width = sizeof(unsigned long) * 2;
 
                if (st->check_wx && (eff & _PAGE_RW) && !(eff & _PAGE_NX))
-                       note_wx(st);
+                       note_wx(st, addr);
 
                /*
                 * Now print the actual finished series
@@ -306,9 +315,9 @@ static void note_page(struct seq_file *m, struct pg_state *st,
                        pt_dump_seq_printf(m, st->to_dmesg,
                                           "0x%0*lx-0x%0*lx   ",
                                           width, st->start_address,
-                                          width, st->current_address);
+                                          width, addr);
 
-                       delta = st->current_address - st->start_address;
+                       delta = addr - st->start_address;
                        while (!(delta & 1023) && unit[1]) {
                                delta >>= 10;
                                unit++;
@@ -325,7 +334,7 @@ static void note_page(struct seq_file *m, struct pg_state *st,
                 * such as the start of vmalloc space etc.
                 * This helps in the interpretation.
                 */
-               if (st->current_address >= st->marker[1].start_address) {
+               if (addr >= st->marker[1].start_address) {
                        if (st->marker->max_lines &&
                            st->lines > st->marker->max_lines) {
                                unsigned long nskip =
@@ -341,222 +350,45 @@ static void note_page(struct seq_file *m, struct pg_state *st,
                                           st->marker->name);
                }
 
-               st->start_address = st->current_address;
+               st->start_address = addr;
                st->current_prot = new_prot;
                st->effective_prot = new_eff;
                st->level = level;
        }
 }
 
-static inline pgprotval_t effective_prot(pgprotval_t prot1, pgprotval_t prot2)
-{
-       return (prot1 & prot2 & (_PAGE_USER | _PAGE_RW)) |
-              ((prot1 | prot2) & _PAGE_NX);
-}
-
-static void walk_pte_level(struct seq_file *m, struct pg_state *st, pmd_t addr,
-                          pgprotval_t eff_in, unsigned long P)
-{
-       int i;
-       pte_t *pte;
-       pgprotval_t prot, eff;
-
-       for (i = 0; i < PTRS_PER_PTE; i++) {
-               st->current_address = normalize_addr(P + i * PTE_LEVEL_MULT);
-               pte = pte_offset_map(&addr, st->current_address);
-               prot = pte_flags(*pte);
-               eff = effective_prot(eff_in, prot);
-               note_page(m, st, __pgprot(prot), eff, 5);
-               pte_unmap(pte);
-       }
-}
-#ifdef CONFIG_KASAN
-
-/*
- * This is an optimization for KASAN=y case. Since all kasan page tables
- * eventually point to the kasan_early_shadow_page we could call note_page()
- * right away without walking through lower level page tables. This saves
- * us dozens of seconds (minutes for 5-level config) while checking for
- * W+X mapping or reading kernel_page_tables debugfs file.
- */
-static inline bool kasan_page_table(struct seq_file *m, struct pg_state *st,
-                               void *pt)
-{
-       if (__pa(pt) == __pa(kasan_early_shadow_pmd) ||
-           (pgtable_l5_enabled() &&
-                       __pa(pt) == __pa(kasan_early_shadow_p4d)) ||
-           __pa(pt) == __pa(kasan_early_shadow_pud)) {
-               pgprotval_t prot = pte_flags(kasan_early_shadow_pte[0]);
-               note_page(m, st, __pgprot(prot), 0, 5);
-               return true;
-       }
-       return false;
-}
-#else
-static inline bool kasan_page_table(struct seq_file *m, struct pg_state *st,
-                               void *pt)
-{
-       return false;
-}
-#endif
-
-#if PTRS_PER_PMD > 1
-
-static void walk_pmd_level(struct seq_file *m, struct pg_state *st, pud_t addr,
-                          pgprotval_t eff_in, unsigned long P)
-{
-       int i;
-       pmd_t *start, *pmd_start;
-       pgprotval_t prot, eff;
-
-       pmd_start = start = (pmd_t *)pud_page_vaddr(addr);
-       for (i = 0; i < PTRS_PER_PMD; i++) {
-               st->current_address = normalize_addr(P + i * PMD_LEVEL_MULT);
-               if (!pmd_none(*start)) {
-                       prot = pmd_flags(*start);
-                       eff = effective_prot(eff_in, prot);
-                       if (pmd_large(*start) || !pmd_present(*start)) {
-                               note_page(m, st, __pgprot(prot), eff, 4);
-                       } else if (!kasan_page_table(m, st, pmd_start)) {
-                               walk_pte_level(m, st, *start, eff,
-                                              P + i * PMD_LEVEL_MULT);
-                       }
-               } else
-                       note_page(m, st, __pgprot(0), 0, 4);
-               start++;
-       }
-}
-
-#else
-#define walk_pmd_level(m,s,a,e,p) walk_pte_level(m,s,__pmd(pud_val(a)),e,p)
-#define pud_large(a) pmd_large(__pmd(pud_val(a)))
-#define pud_none(a)  pmd_none(__pmd(pud_val(a)))
-#endif
-
-#if PTRS_PER_PUD > 1
-
-static void walk_pud_level(struct seq_file *m, struct pg_state *st, p4d_t addr,
-                          pgprotval_t eff_in, unsigned long P)
-{
-       int i;
-       pud_t *start, *pud_start;
-       pgprotval_t prot, eff;
-
-       pud_start = start = (pud_t *)p4d_page_vaddr(addr);
-
-       for (i = 0; i < PTRS_PER_PUD; i++) {
-               st->current_address = normalize_addr(P + i * PUD_LEVEL_MULT);
-               if (!pud_none(*start)) {
-                       prot = pud_flags(*start);
-                       eff = effective_prot(eff_in, prot);
-                       if (pud_large(*start) || !pud_present(*start)) {
-                               note_page(m, st, __pgprot(prot), eff, 3);
-                       } else if (!kasan_page_table(m, st, pud_start)) {
-                               walk_pmd_level(m, st, *start, eff,
-                                              P + i * PUD_LEVEL_MULT);
-                       }
-               } else
-                       note_page(m, st, __pgprot(0), 0, 3);
-
-               start++;
-       }
-}
-
-#else
-#define walk_pud_level(m,s,a,e,p) walk_pmd_level(m,s,__pud(p4d_val(a)),e,p)
-#define p4d_large(a) pud_large(__pud(p4d_val(a)))
-#define p4d_none(a)  pud_none(__pud(p4d_val(a)))
-#endif
-
-static void walk_p4d_level(struct seq_file *m, struct pg_state *st, pgd_t addr,
-                          pgprotval_t eff_in, unsigned long P)
-{
-       int i;
-       p4d_t *start, *p4d_start;
-       pgprotval_t prot, eff;
-
-       if (PTRS_PER_P4D == 1)
-               return walk_pud_level(m, st, __p4d(pgd_val(addr)), eff_in, P);
-
-       p4d_start = start = (p4d_t *)pgd_page_vaddr(addr);
-
-       for (i = 0; i < PTRS_PER_P4D; i++) {
-               st->current_address = normalize_addr(P + i * P4D_LEVEL_MULT);
-               if (!p4d_none(*start)) {
-                       prot = p4d_flags(*start);
-                       eff = effective_prot(eff_in, prot);
-                       if (p4d_large(*start) || !p4d_present(*start)) {
-                               note_page(m, st, __pgprot(prot), eff, 2);
-                       } else if (!kasan_page_table(m, st, p4d_start)) {
-                               walk_pud_level(m, st, *start, eff,
-                                              P + i * P4D_LEVEL_MULT);
-                       }
-               } else
-                       note_page(m, st, __pgprot(0), 0, 2);
-
-               start++;
-       }
-}
-
-#define pgd_large(a) (pgtable_l5_enabled() ? pgd_large(a) : p4d_large(__p4d(pgd_val(a))))
-#define pgd_none(a)  (pgtable_l5_enabled() ? pgd_none(a) : p4d_none(__p4d(pgd_val(a))))
-
-static inline bool is_hypervisor_range(int idx)
-{
-#ifdef CONFIG_X86_64
-       /*
-        * A hole in the beginning of kernel address space reserved
-        * for a hypervisor.
-        */
-       return  (idx >= pgd_index(GUARD_HOLE_BASE_ADDR)) &&
-               (idx <  pgd_index(GUARD_HOLE_END_ADDR));
-#else
-       return false;
-#endif
-}
-
-static void ptdump_walk_pgd_level_core(struct seq_file *m, pgd_t *pgd,
+static void ptdump_walk_pgd_level_core(struct seq_file *m,
+                                      struct mm_struct *mm, pgd_t *pgd,
                                       bool checkwx, bool dmesg)
 {
-       pgd_t *start = INIT_PGD;
-       pgprotval_t prot, eff;
-       int i;
-       struct pg_state st = {};
-
-       if (pgd) {
-               start = pgd;
-               st.to_dmesg = dmesg;
-       }
+       const struct ptdump_range ptdump_ranges[] = {
+#ifdef CONFIG_X86_64
 
-       st.check_wx = checkwx;
-       if (checkwx)
-               st.wx_pages = 0;
+#define normalize_addr_shift (64 - (__VIRTUAL_MASK_SHIFT + 1))
+#define normalize_addr(u) ((signed long)((u) << normalize_addr_shift) >> \
+                          normalize_addr_shift)
 
-       for (i = 0; i < PTRS_PER_PGD; i++) {
-               st.current_address = normalize_addr(i * PGD_LEVEL_MULT);
-               if (!pgd_none(*start) && !is_hypervisor_range(i)) {
-                       prot = pgd_flags(*start);
-#ifdef CONFIG_X86_PAE
-                       eff = _PAGE_USER | _PAGE_RW;
+       {0, PTRS_PER_PGD * PGD_LEVEL_MULT / 2},
+       {normalize_addr(PTRS_PER_PGD * PGD_LEVEL_MULT / 2), ~0UL},
 #else
-                       eff = prot;
+       {0, ~0UL},
 #endif
-                       if (pgd_large(*start) || !pgd_present(*start)) {
-                               note_page(m, &st, __pgprot(prot), eff, 1);
-                       } else {
-                               walk_p4d_level(m, &st, *start, eff,
-                                              i * PGD_LEVEL_MULT);
-                       }
-               } else
-                       note_page(m, &st, __pgprot(0), 0, 1);
+       {0, 0}
+};
 
-               cond_resched();
-               start++;
-       }
+       struct pg_state st = {
+               .ptdump = {
+                       .note_page      = note_page,
+                       .range          = ptdump_ranges
+               },
+               .level = -1,
+               .to_dmesg       = dmesg,
+               .check_wx       = checkwx,
+               .seq            = m
+       };
+
+       ptdump_walk_pgd(&st.ptdump, mm, pgd);
 
-       /* Flush out the last page */
-       st.current_address = normalize_addr(PTRS_PER_PGD*PGD_LEVEL_MULT);
-       note_page(m, &st, __pgprot(0), 0, 0);
        if (!checkwx)
                return;
        if (st.wx_pages)
@@ -566,18 +398,20 @@ static void ptdump_walk_pgd_level_core(struct seq_file *m, pgd_t *pgd,
                pr_info("x86/mm: Checked W+X mappings: passed, no W+X pages found.\n");
 }
 
-void ptdump_walk_pgd_level(struct seq_file *m, pgd_t *pgd)
+void ptdump_walk_pgd_level(struct seq_file *m, struct mm_struct *mm)
 {
-       ptdump_walk_pgd_level_core(m, pgd, false, true);
+       ptdump_walk_pgd_level_core(m, mm, mm->pgd, false, true);
 }
 
-void ptdump_walk_pgd_level_debugfs(struct seq_file *m, pgd_t *pgd, bool user)
+void ptdump_walk_pgd_level_debugfs(struct seq_file *m, struct mm_struct *mm,
+                                  bool user)
 {
+       pgd_t *pgd = mm->pgd;
 #ifdef CONFIG_PAGE_TABLE_ISOLATION
        if (user && boot_cpu_has(X86_FEATURE_PTI))
                pgd = kernel_to_user_pgdp(pgd);
 #endif
-       ptdump_walk_pgd_level_core(m, pgd, false, false);
+       ptdump_walk_pgd_level_core(m, mm, pgd, false, false);
 }
 EXPORT_SYMBOL_GPL(ptdump_walk_pgd_level_debugfs);
 
@@ -592,13 +426,13 @@ void ptdump_walk_user_pgd_level_checkwx(void)
 
        pr_info("x86/mm: Checking user space page tables\n");
        pgd = kernel_to_user_pgdp(pgd);
-       ptdump_walk_pgd_level_core(NULL, pgd, true, false);
+       ptdump_walk_pgd_level_core(NULL, &init_mm, pgd, true, false);
 #endif
 }
 
 void ptdump_walk_pgd_level_checkwx(void)
 {
-       ptdump_walk_pgd_level_core(NULL, NULL, true, false);
+       ptdump_walk_pgd_level_core(NULL, &init_mm, INIT_PGD, true, false);
 }
 
 static int __init pt_dump_init(void)
index 71dddd1..081d466 100644 (file)
@@ -49,7 +49,7 @@ void efi_sync_low_kernel_mappings(void) {}
 void __init efi_dump_pagetable(void)
 {
 #ifdef CONFIG_EFI_PGT_DUMP
-       ptdump_walk_pgd_level(NULL, swapper_pg_dir);
+       ptdump_walk_pgd_level(NULL, &init_mm);
 #endif
 }
 
index e2accfe..fa8506e 100644 (file)
@@ -471,9 +471,9 @@ void __init efi_dump_pagetable(void)
 {
 #ifdef CONFIG_EFI_PGT_DUMP
        if (efi_have_uv1_memmap())
-               ptdump_walk_pgd_level(NULL, swapper_pg_dir);
+               ptdump_walk_pgd_level(NULL, &init_mm);
        else
-               ptdump_walk_pgd_level(NULL, efi_mm.pgd);
+               ptdump_walk_pgd_level(NULL, &efi_mm);
 #endif
 }
 
index 5f0a96b..1fd321f 100644 (file)
@@ -1668,12 +1668,12 @@ static int tunables_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-static const struct file_operations proc_uv_ptc_operations = {
-       .open           = ptc_proc_open,
-       .read           = seq_read,
-       .write          = ptc_proc_write,
-       .llseek         = seq_lseek,
-       .release        = seq_release,
+static const struct proc_ops uv_ptc_proc_ops = {
+       .proc_open      = ptc_proc_open,
+       .proc_read      = seq_read,
+       .proc_write     = ptc_proc_write,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = seq_release,
 };
 
 static const struct file_operations tunables_fops = {
@@ -1691,7 +1691,7 @@ static int __init uv_ptc_init(void)
                return 0;
 
        proc_uv_ptc = proc_create(UV_PTC_BASENAME, 0444, NULL,
-                                 &proc_uv_ptc_operations);
+                                 &uv_ptc_proc_ops);
        if (!proc_uv_ptc) {
                pr_err("unable to create %s proc entry\n",
                       UV_PTC_BASENAME);
index f9cd458..8331098 100644 (file)
@@ -251,10 +251,10 @@ out_free:
        return err;
 }
 
-static const struct file_operations fops = {
-       .read = proc_read_simdisk,
-       .write = proc_write_simdisk,
-       .llseek = default_llseek,
+static const struct proc_ops simdisk_proc_ops = {
+       .proc_read      = proc_read_simdisk,
+       .proc_write     = proc_write_simdisk,
+       .proc_lseek     = default_llseek,
 };
 
 static int __init simdisk_setup(struct simdisk *dev, int which,
@@ -290,7 +290,7 @@ static int __init simdisk_setup(struct simdisk *dev, int which,
        set_capacity(dev->gd, 0);
        add_disk(dev->gd);
 
-       dev->procfile = proc_create_data(tmp, 0644, procdir, &fops, dev);
+       dev->procfile = proc_create_data(tmp, 0644, procdir, &simdisk_proc_ops, dev);
        return 0;
 
 out_alloc_disk:
index 3d8e530..439367a 100644 (file)
@@ -171,7 +171,7 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        sa->salg_name[sizeof(sa->salg_name) + addr_len - sizeof(*sa) - 1] = 0;
 
        type = alg_get_type(sa->salg_type);
-       if (IS_ERR(type) && PTR_ERR(type) == -ENOENT) {
+       if (PTR_ERR(type) == -ENOENT) {
                request_module("algif-%s", sa->salg_type);
                type = alg_get_type(sa->salg_type);
        }
index 15cc7d5..111a407 100644 (file)
@@ -1202,13 +1202,12 @@ static int acpi_battery_alarm_proc_open(struct inode *inode, struct file *file)
        return single_open(file, acpi_battery_alarm_proc_show, PDE_DATA(inode));
 }
 
-static const struct file_operations acpi_battery_alarm_fops = {
-       .owner          = THIS_MODULE,
-       .open           = acpi_battery_alarm_proc_open,
-       .read           = seq_read,
-       .write          = acpi_battery_write_alarm,
-       .llseek         = seq_lseek,
-       .release        = single_release,
+static const struct proc_ops acpi_battery_alarm_proc_ops = {
+       .proc_open      = acpi_battery_alarm_proc_open,
+       .proc_read      = seq_read,
+       .proc_write     = acpi_battery_write_alarm,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
 };
 
 static int acpi_battery_add_fs(struct acpi_device *device)
@@ -1228,7 +1227,7 @@ static int acpi_battery_add_fs(struct acpi_device *device)
                        acpi_battery_state_proc_show, acpi_driver_data(device)))
                return -ENODEV;
        if (!proc_create_data("alarm", S_IFREG | S_IRUGO | S_IWUSR,
-                       acpi_device_dir(device), &acpi_battery_alarm_fops,
+                       acpi_device_dir(device), &acpi_battery_alarm_proc_ops,
                        acpi_driver_data(device)))
                return -ENODEV;
        return 0;
index 652f19e..0e62ef2 100644 (file)
@@ -136,18 +136,17 @@ acpi_system_wakeup_device_open_fs(struct inode *inode, struct file *file)
                           PDE_DATA(inode));
 }
 
-static const struct file_operations acpi_system_wakeup_device_fops = {
-       .owner = THIS_MODULE,
-       .open = acpi_system_wakeup_device_open_fs,
-       .read = seq_read,
-       .write = acpi_system_write_wakeup_device,
-       .llseek = seq_lseek,
-       .release = single_release,
+static const struct proc_ops acpi_system_wakeup_device_proc_ops = {
+       .proc_open      = acpi_system_wakeup_device_open_fs,
+       .proc_read      = seq_read,
+       .proc_write     = acpi_system_write_wakeup_device,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
 };
 
 void __init acpi_sleep_proc_init(void)
 {
        /* 'wakeup device' [R/W] */
        proc_create("wakeup", S_IFREG | S_IRUGO | S_IWUSR,
-                   acpi_root_dir, &acpi_system_wakeup_device_fops);
+                   acpi_root_dir, &acpi_system_wakeup_device_proc_ops);
 }
index 915650b..6d34488 100644 (file)
@@ -1462,7 +1462,7 @@ int acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
        iort_dma_setup(dev, &dma_addr, &size);
 
        iommu = iort_iommu_configure(dev);
-       if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER)
+       if (PTR_ERR(iommu) == -EPROBE_DEFER)
                return -EPROBE_DEFER;
 
        arch_setup_dma_ops(dev, dma_addr, size,
index 1565930..b9f474c 100644 (file)
@@ -376,7 +376,6 @@ static ssize_t valid_zones_show(struct device *dev,
        struct memory_block *mem = to_memory_block(dev);
        unsigned long start_pfn = section_nr_to_pfn(mem->start_section_nr);
        unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
-       unsigned long valid_start_pfn, valid_end_pfn;
        struct zone *default_zone;
        int nid;
 
@@ -389,11 +388,11 @@ static ssize_t valid_zones_show(struct device *dev,
                 * The block contains more than one zone can not be offlined.
                 * This can happen e.g. for ZONE_DMA and ZONE_DMA32
                 */
-               if (!test_pages_in_a_zone(start_pfn, start_pfn + nr_pages,
-                                         &valid_start_pfn, &valid_end_pfn))
+               default_zone = test_pages_in_a_zone(start_pfn,
+                                                   start_pfn + nr_pages);
+               if (!default_zone)
                        return sprintf(buf, "none\n");
-               start_pfn = valid_start_pfn;
-               strcat(buf, page_zone(pfn_to_page(start_pfn))->name);
+               strcat(buf, default_zone->name);
                goto out;
        }
 
index ae8d4bc..1651079 100644 (file)
@@ -263,34 +263,34 @@ static ssize_t nullb_device_bool_attr_store(bool *val, const char *page,
 }
 
 /* The following macro should only be used with TYPE = {uint, ulong, bool}. */
-#define NULLB_DEVICE_ATTR(NAME, TYPE, APPLY)                                   \
-static ssize_t                                                                 \
-nullb_device_##NAME##_show(struct config_item *item, char *page)               \
-{                                                                              \
-       return nullb_device_##TYPE##_attr_show(                                 \
-                               to_nullb_device(item)->NAME, page);             \
-}                                                                              \
-static ssize_t                                                                 \
-nullb_device_##NAME##_store(struct config_item *item, const char *page,                \
-                           size_t count)                                       \
-{                                                                              \
-       int (*apply_fn)(struct nullb_device *dev, TYPE new_value) = APPLY;      \
-       struct nullb_device *dev = to_nullb_device(item);                       \
-       TYPE new_value;                                                         \
-       int ret;                                                                \
-                                                                               \
-       ret = nullb_device_##TYPE##_attr_store(&new_value, page, count);        \
-       if (ret < 0)                                                            \
-               return ret;                                                     \
-       if (apply_fn)                                                           \
-               ret = apply_fn(dev, new_value);                                 \
-       else if (test_bit(NULLB_DEV_FL_CONFIGURED, &dev->flags))                \
-               ret = -EBUSY;                                                   \
-       if (ret < 0)                                                            \
-               return ret;                                                     \
-       dev->NAME = new_value;                                                  \
-       return count;                                                           \
-}                                                                              \
+#define NULLB_DEVICE_ATTR(NAME, TYPE, APPLY)                           \
+static ssize_t                                                         \
+nullb_device_##NAME##_show(struct config_item *item, char *page)       \
+{                                                                      \
+       return nullb_device_##TYPE##_attr_show(                         \
+                               to_nullb_device(item)->NAME, page);     \
+}                                                                      \
+static ssize_t                                                         \
+nullb_device_##NAME##_store(struct config_item *item, const char *page,        \
+                           size_t count)                               \
+{                                                                      \
+       int (*apply_fn)(struct nullb_device *dev, TYPE new_value) = APPLY;\
+       struct nullb_device *dev = to_nullb_device(item);               \
+       TYPE uninitialized_var(new_value);                              \
+       int ret;                                                        \
+                                                                       \
+       ret = nullb_device_##TYPE##_attr_store(&new_value, page, count);\
+       if (ret < 0)                                                    \
+               return ret;                                             \
+       if (apply_fn)                                                   \
+               ret = apply_fn(dev, new_value);                         \
+       else if (test_bit(NULLB_DEV_FL_CONFIGURED, &dev->flags))        \
+               ret = -EBUSY;                                           \
+       if (ret < 0)                                                    \
+               return ret;                                             \
+       dev->NAME = new_value;                                          \
+       return count;                                                   \
+}                                                                      \
 CONFIGFS_ATTR(nullb_device_, NAME);
 
 static int nullb_apply_submit_queues(struct nullb_device *dev,
index d2a5791..cbf5eae 100644 (file)
@@ -157,7 +157,7 @@ static int bcm2835_rng_probe(struct platform_device *pdev)
 
        /* Clock is optional on most platforms */
        priv->clk = devm_clk_get(dev, NULL);
-       if (IS_ERR(priv->clk) && PTR_ERR(priv->clk) == -EPROBE_DEFER)
+       if (PTR_ERR(priv->clk) == -EPROBE_DEFER)
                return -EPROBE_DEFER;
 
        priv->rng.name = pdev->name;
index 0ed07d1..6595239 100644 (file)
@@ -476,7 +476,7 @@ static int omap_rng_probe(struct platform_device *pdev)
        }
 
        priv->clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(priv->clk) && PTR_ERR(priv->clk) == -EPROBE_DEFER)
+       if (PTR_ERR(priv->clk) == -EPROBE_DEFER)
                return -EPROBE_DEFER;
        if (!IS_ERR(priv->clk)) {
                ret = clk_prepare_enable(priv->clk);
@@ -488,7 +488,7 @@ static int omap_rng_probe(struct platform_device *pdev)
        }
 
        priv->clk_reg = devm_clk_get(&pdev->dev, "reg");
-       if (IS_ERR(priv->clk_reg) && PTR_ERR(priv->clk_reg) == -EPROBE_DEFER)
+       if (PTR_ERR(priv->clk_reg) == -EPROBE_DEFER)
                return -EPROBE_DEFER;
        if (!IS_ERR(priv->clk_reg)) {
                ret = clk_prepare_enable(priv->clk_reg);
index d529ad6..f0f2b59 100644 (file)
@@ -429,7 +429,7 @@ static void clk_core_fill_parent_index(struct clk_core *core, u8 index)
                        parent = ERR_PTR(-EPROBE_DEFER);
        } else {
                parent = clk_core_get(core, index);
-               if (IS_ERR(parent) && PTR_ERR(parent) == -ENOENT && entry->name)
+               if (PTR_ERR(parent) == -ENOENT && entry->name)
                        parent = clk_core_lookup(entry->name);
        }
 
index e3850f0..157c959 100644 (file)
@@ -750,7 +750,7 @@ static int mv_xor_v2_probe(struct platform_device *pdev)
        }
 
        xor_dev->clk = devm_clk_get(&pdev->dev, NULL);
-       if (IS_ERR(xor_dev->clk) && PTR_ERR(xor_dev->clk) == -EPROBE_DEFER) {
+       if (PTR_ERR(xor_dev->clk) == -EPROBE_DEFER) {
                ret = EPROBE_DEFER;
                goto disable_reg_clk;
        }
index 899b803..9dda260 100644 (file)
@@ -27,7 +27,7 @@
 
 extern u64 efi_system_table;
 
-#ifdef CONFIG_ARM64_PTDUMP_DEBUGFS
+#if defined(CONFIG_PTDUMP_DEBUGFS) && defined(CONFIG_ARM64)
 #include <asm/ptdump.h>
 
 static struct ptdump_info efi_ptdump_info = {
index 4421be0..72b6001 100644 (file)
@@ -308,7 +308,7 @@ devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
        struct gpio_descs *descs;
 
        descs = devm_gpiod_get_array(dev, con_id, flags);
-       if (IS_ERR(descs) && (PTR_ERR(descs) == -ENOENT))
+       if (PTR_ERR(descs) == -ENOENT)
                return NULL;
 
        return descs;
index 1b3f217..c6d30f7 100644 (file)
@@ -484,24 +484,24 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
                        break;
        }
 
-       if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) {
+       if (PTR_ERR(desc) == -ENOENT) {
                /* Special handling for SPI GPIOs if used */
                desc = of_find_spi_gpio(dev, con_id, &of_flags);
        }
 
-       if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) {
+       if (PTR_ERR(desc) == -ENOENT) {
                /* This quirk looks up flags and all */
                desc = of_find_spi_cs_gpio(dev, con_id, idx, flags);
                if (!IS_ERR(desc))
                        return desc;
        }
 
-       if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) {
+       if (PTR_ERR(desc) == -ENOENT) {
                /* Special handling for regulator GPIOs if used */
                desc = of_find_regulator_gpio(dev, con_id, &of_flags);
        }
 
-       if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT)
+       if (PTR_ERR(desc) == -ENOENT)
                desc = of_find_arizona_gpio(dev, con_id, &of_flags);
 
        if (IS_ERR(desc))
index 99ac27a..7532834 100644 (file)
@@ -5039,7 +5039,7 @@ struct gpio_descs *__must_check gpiod_get_array_optional(struct device *dev,
        struct gpio_descs *descs;
 
        descs = gpiod_get_array(dev, con_id, flags);
-       if (IS_ERR(descs) && (PTR_ERR(descs) == -ENOENT))
+       if (PTR_ERR(descs) == -ENOENT)
                return NULL;
 
        return descs;
index 17583bf..d4c8300 100644 (file)
@@ -595,19 +595,18 @@ static int i8k_open_fs(struct inode *inode, struct file *file)
        return single_open(file, i8k_proc_show, NULL);
 }
 
-static const struct file_operations i8k_fops = {
-       .owner          = THIS_MODULE,
-       .open           = i8k_open_fs,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .unlocked_ioctl = i8k_ioctl,
+static const struct proc_ops i8k_proc_ops = {
+       .proc_open      = i8k_open_fs,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_ioctl     = i8k_ioctl,
 };
 
 static void __init i8k_init_procfs(void)
 {
        /* Register the proc entry */
-       proc_create("i8k", 0, NULL, &i8k_fops);
+       proc_create("i8k", 0, NULL, &i8k_proc_ops);
 }
 
 static void __exit i8k_exit_procfs(void)
index a5a95ea..febb7c7 100644 (file)
@@ -901,14 +901,13 @@ mv64xxx_i2c_probe(struct platform_device *pd)
 
        /* Not all platforms have clocks */
        drv_data->clk = devm_clk_get(&pd->dev, NULL);
-       if (IS_ERR(drv_data->clk) && PTR_ERR(drv_data->clk) == -EPROBE_DEFER)
+       if (PTR_ERR(drv_data->clk) == -EPROBE_DEFER)
                return -EPROBE_DEFER;
        if (!IS_ERR(drv_data->clk))
                clk_prepare_enable(drv_data->clk);
 
        drv_data->reg_clk = devm_clk_get(&pd->dev, "reg");
-       if (IS_ERR(drv_data->reg_clk) &&
-           PTR_ERR(drv_data->reg_clk) == -EPROBE_DEFER)
+       if (PTR_ERR(drv_data->reg_clk) == -EPROBE_DEFER)
                return -EPROBE_DEFER;
        if (!IS_ERR(drv_data->reg_clk))
                clk_prepare_enable(drv_data->reg_clk);
index 39762f0..8602679 100644 (file)
@@ -553,7 +553,7 @@ static int synquacer_i2c_probe(struct platform_device *pdev)
                                 &i2c->pclkrate);
 
        i2c->pclk = devm_clk_get(&pdev->dev, "pclk");
-       if (IS_ERR(i2c->pclk) && PTR_ERR(i2c->pclk) == -EPROBE_DEFER)
+       if (PTR_ERR(i2c->pclk) == -EPROBE_DEFER)
                return -EPROBE_DEFER;
        if (!IS_ERR_OR_NULL(i2c->pclk)) {
                dev_dbg(&pdev->dev, "clock source %p\n", i2c->pclk);
index e73016c..15c17f3 100644 (file)
@@ -381,13 +381,12 @@ parse_error:
        return -EINVAL;
 }
 
-static const struct file_operations ide_settings_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = ide_settings_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = ide_settings_proc_write,
+static const struct proc_ops ide_settings_proc_ops = {
+       .proc_open      = ide_settings_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = ide_settings_proc_write,
 };
 
 int ide_capacity_proc_show(struct seq_file *m, void *v)
@@ -546,7 +545,7 @@ void ide_proc_port_register_devices(ide_hwif_t *hwif)
                if (drive->proc) {
                        ide_add_proc_entries(drive->proc, generic_drive_entries, drive);
                        proc_create_data("settings", S_IFREG|S_IRUSR|S_IWUSR,
-                                       drive->proc, &ide_settings_proc_fops,
+                                       drive->proc, &ide_settings_proc_ops,
                                        drive);
                }
                sprintf(name, "ide%d/%s", (drive->name[2]-'a')/2, drive->name);
@@ -615,7 +614,7 @@ static int ide_drivers_show(struct seq_file *s, void *p)
        return 0;
 }
 
-DEFINE_SHOW_ATTRIBUTE(ide_drivers);
+DEFINE_PROC_SHOW_ATTRIBUTE(ide_drivers);
 
 void proc_ide_create(void)
 {
@@ -624,7 +623,7 @@ void proc_ide_create(void)
        if (!proc_ide_root)
                return;
 
-       proc_create("drivers", 0, proc_ide_root, &ide_drivers_fops);
+       proc_create("drivers", 0, proc_ide_root, &ide_drivers_proc_ops);
 }
 
 void proc_ide_destroy(void)
index ee6c323..fce43e6 100644 (file)
@@ -1216,13 +1216,12 @@ static int input_proc_devices_open(struct inode *inode, struct file *file)
        return seq_open(file, &input_devices_seq_ops);
 }
 
-static const struct file_operations input_devices_fileops = {
-       .owner          = THIS_MODULE,
-       .open           = input_proc_devices_open,
-       .poll           = input_proc_devices_poll,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = seq_release,
+static const struct proc_ops input_devices_proc_ops = {
+       .proc_open      = input_proc_devices_open,
+       .proc_poll      = input_proc_devices_poll,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = seq_release,
 };
 
 static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos)
@@ -1280,12 +1279,11 @@ static int input_proc_handlers_open(struct inode *inode, struct file *file)
        return seq_open(file, &input_handlers_seq_ops);
 }
 
-static const struct file_operations input_handlers_fileops = {
-       .owner          = THIS_MODULE,
-       .open           = input_proc_handlers_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = seq_release,
+static const struct proc_ops input_handlers_proc_ops = {
+       .proc_open      = input_proc_handlers_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = seq_release,
 };
 
 static int __init input_proc_init(void)
@@ -1297,12 +1295,12 @@ static int __init input_proc_init(void)
                return -ENOMEM;
 
        entry = proc_create("devices", 0, proc_bus_input_dir,
-                           &input_devices_fileops);
+                           &input_devices_proc_ops);
        if (!entry)
                goto fail1;
 
        entry = proc_create("handlers", 0, proc_bus_input_dir,
-                           &input_handlers_fileops);
+                           &input_handlers_proc_ops);
        if (!entry)
                goto fail2;
 
index eadbe59..b5ed4ea 100644 (file)
@@ -199,8 +199,8 @@ static ssize_t empty_read(struct file *file, char __user *buf,
        return 0;
 }
 
-static const struct file_operations empty_fops = {
-       .read   = empty_read,
+static const struct proc_ops empty_proc_ops = {
+       .proc_read      = empty_read,
 };
 
 // ---------------------------------------------------------------------------
@@ -214,7 +214,7 @@ kcapi_proc_init(void)
        proc_create_seq("capi/contrstats",   0, NULL, &seq_contrstats_ops);
        proc_create_seq("capi/applications", 0, NULL, &seq_applications_ops);
        proc_create_seq("capi/applstats",    0, NULL, &seq_applstats_ops);
-       proc_create("capi/driver",           0, NULL, &empty_fops);
+       proc_create("capi/driver",           0, NULL, &empty_proc_ops);
 }
 
 void
index 21d532a..d38fb78 100644 (file)
@@ -212,7 +212,7 @@ static int pmu_info_proc_show(struct seq_file *m, void *v);
 static int pmu_irqstats_proc_show(struct seq_file *m, void *v);
 static int pmu_battery_proc_show(struct seq_file *m, void *v);
 static void pmu_pass_intr(unsigned char *data, int len);
-static const struct file_operations pmu_options_proc_fops;
+static const struct proc_ops pmu_options_proc_ops;
 
 #ifdef CONFIG_ADB
 const struct adb_driver via_pmu_driver = {
@@ -573,7 +573,7 @@ static int __init via_pmu_dev_init(void)
                proc_pmu_irqstats = proc_create_single("interrupts", 0,
                                proc_pmu_root, pmu_irqstats_proc_show);
                proc_pmu_options = proc_create("options", 0600, proc_pmu_root,
-                                               &pmu_options_proc_fops);
+                                               &pmu_options_proc_ops);
        }
        return 0;
 }
@@ -974,13 +974,12 @@ static ssize_t pmu_options_proc_write(struct file *file,
        return fcount;
 }
 
-static const struct file_operations pmu_options_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = pmu_options_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = pmu_options_proc_write,
+static const struct proc_ops pmu_options_proc_ops = {
+       .proc_open      = pmu_options_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = pmu_options_proc_write,
 };
 
 #ifdef CONFIG_ADB
index 4824d50..469f551 100644 (file)
@@ -8279,13 +8279,12 @@ static __poll_t mdstat_poll(struct file *filp, poll_table *wait)
        return mask;
 }
 
-static const struct file_operations md_seq_fops = {
-       .owner          = THIS_MODULE,
-       .open           = md_seq_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = seq_release,
-       .poll           = mdstat_poll,
+static const struct proc_ops mdstat_proc_ops = {
+       .proc_open      = md_seq_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = seq_release,
+       .proc_poll      = mdstat_poll,
 };
 
 int register_md_personality(struct md_personality *p)
@@ -9454,7 +9453,7 @@ static void md_geninit(void)
 {
        pr_debug("md: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t));
 
-       proc_create("mdstat", S_IRUGO, NULL, &md_seq_fops);
+       proc_create("mdstat", S_IRUGO, NULL, &mdstat_proc_ops);
 }
 
 static int __init md_init(void)
index 2817f47..97b8b38 100644 (file)
@@ -255,28 +255,28 @@ static int options_open(struct inode *inode, struct file *file)
 }
 
 /* *INDENT-OFF* */
-static const struct file_operations statistics_fops = {
-       .open           = statistics_open,
-       .read           = seq_read,
-       .write          = statistics_write,
-       .llseek         = seq_lseek,
-       .release        = single_release,
+static const struct proc_ops statistics_proc_ops = {
+       .proc_open      = statistics_open,
+       .proc_read      = seq_read,
+       .proc_write     = statistics_write,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
 };
 
-static const struct file_operations mcs_statistics_fops = {
-       .open           = mcs_statistics_open,
-       .read           = seq_read,
-       .write          = mcs_statistics_write,
-       .llseek         = seq_lseek,
-       .release        = single_release,
+static const struct proc_ops mcs_statistics_proc_ops = {
+       .proc_open      = mcs_statistics_open,
+       .proc_read      = seq_read,
+       .proc_write     = mcs_statistics_write,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
 };
 
-static const struct file_operations options_fops = {
-       .open           = options_open,
-       .read           = seq_read,
-       .write          = options_write,
-       .llseek         = seq_lseek,
-       .release        = single_release,
+static const struct proc_ops options_proc_ops = {
+       .proc_open      = options_open,
+       .proc_read      = seq_read,
+       .proc_write     = options_write,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
 };
 
 static struct proc_dir_entry *proc_gru __read_mostly;
@@ -286,11 +286,11 @@ int gru_proc_init(void)
        proc_gru = proc_mkdir("sgi_uv/gru", NULL);
        if (!proc_gru)
                return -1;
-       if (!proc_create("statistics", 0644, proc_gru, &statistics_fops))
+       if (!proc_create("statistics", 0644, proc_gru, &statistics_proc_ops))
                goto err;
-       if (!proc_create("mcs_statistics", 0644, proc_gru, &mcs_statistics_fops))
+       if (!proc_create("mcs_statistics", 0644, proc_gru, &mcs_statistics_proc_ops))
                goto err;
-       if (!proc_create("debug_options", 0644, proc_gru, &options_fops))
+       if (!proc_create("debug_options", 0644, proc_gru, &options_proc_ops))
                goto err;
        if (!proc_create_seq("cch_status", 0444, proc_gru, &cch_seq_ops))
                goto err;
index 25fb72b..2f93c25 100644 (file)
@@ -1180,7 +1180,7 @@ static struct mtd_info * __init open_mtd_device(const char *mtd_dev)
                 * MTD device name.
                 */
                mtd = get_mtd_device_nm(mtd_dev);
-               if (IS_ERR(mtd) && PTR_ERR(mtd) == -ENODEV)
+               if (PTR_ERR(mtd) == -ENODEV)
                        /* Probably this is an MTD character device node path */
                        mtd = open_mtd_by_chdev(mtd_dev);
        } else
index c4c8f1b..8363f91 100644 (file)
@@ -4420,73 +4420,65 @@ static int proc_BSSList_open( struct inode *inode, struct file *file );
 static int proc_config_open( struct inode *inode, struct file *file );
 static int proc_wepkey_open( struct inode *inode, struct file *file );
 
-static const struct file_operations proc_statsdelta_ops = {
-       .owner          = THIS_MODULE,
-       .read           = proc_read,
-       .open           = proc_statsdelta_open,
-       .release        = proc_close,
-       .llseek         = default_llseek,
+static const struct proc_ops proc_statsdelta_ops = {
+       .proc_read      = proc_read,
+       .proc_open      = proc_statsdelta_open,
+       .proc_release   = proc_close,
+       .proc_lseek     = default_llseek,
 };
 
-static const struct file_operations proc_stats_ops = {
-       .owner          = THIS_MODULE,
-       .read           = proc_read,
-       .open           = proc_stats_open,
-       .release        = proc_close,
-       .llseek         = default_llseek,
+static const struct proc_ops proc_stats_ops = {
+       .proc_read      = proc_read,
+       .proc_open      = proc_stats_open,
+       .proc_release   = proc_close,
+       .proc_lseek     = default_llseek,
 };
 
-static const struct file_operations proc_status_ops = {
-       .owner          = THIS_MODULE,
-       .read           = proc_read,
-       .open           = proc_status_open,
-       .release        = proc_close,
-       .llseek         = default_llseek,
+static const struct proc_ops proc_status_ops = {
+       .proc_read      = proc_read,
+       .proc_open      = proc_status_open,
+       .proc_release   = proc_close,
+       .proc_lseek     = default_llseek,
 };
 
-static const struct file_operations proc_SSID_ops = {
-       .owner          = THIS_MODULE,
-       .read           = proc_read,
-       .write          = proc_write,
-       .open           = proc_SSID_open,
-       .release        = proc_close,
-       .llseek         = default_llseek,
+static const struct proc_ops proc_SSID_ops = {
+       .proc_read      = proc_read,
+       .proc_write     = proc_write,
+       .proc_open      = proc_SSID_open,
+       .proc_release   = proc_close,
+       .proc_lseek     = default_llseek,
 };
 
-static const struct file_operations proc_BSSList_ops = {
-       .owner          = THIS_MODULE,
-       .read           = proc_read,
-       .write          = proc_write,
-       .open           = proc_BSSList_open,
-       .release        = proc_close,
-       .llseek         = default_llseek,
+static const struct proc_ops proc_BSSList_ops = {
+       .proc_read      = proc_read,
+       .proc_write     = proc_write,
+       .proc_open      = proc_BSSList_open,
+       .proc_release   = proc_close,
+       .proc_lseek     = default_llseek,
 };
 
-static const struct file_operations proc_APList_ops = {
-       .owner          = THIS_MODULE,
-       .read           = proc_read,
-       .write          = proc_write,
-       .open           = proc_APList_open,
-       .release        = proc_close,
-       .llseek         = default_llseek,
+static const struct proc_ops proc_APList_ops = {
+       .proc_read      = proc_read,
+       .proc_write     = proc_write,
+       .proc_open      = proc_APList_open,
+       .proc_release   = proc_close,
+       .proc_lseek     = default_llseek,
 };
 
-static const struct file_operations proc_config_ops = {
-       .owner          = THIS_MODULE,
-       .read           = proc_read,
-       .write          = proc_write,
-       .open           = proc_config_open,
-       .release        = proc_close,
-       .llseek         = default_llseek,
+static const struct proc_ops proc_config_ops = {
+       .proc_read      = proc_read,
+       .proc_write     = proc_write,
+       .proc_open      = proc_config_open,
+       .proc_release   = proc_close,
+       .proc_lseek     = default_llseek,
 };
 
-static const struct file_operations proc_wepkey_ops = {
-       .owner          = THIS_MODULE,
-       .read           = proc_read,
-       .write          = proc_write,
-       .open           = proc_wepkey_open,
-       .release        = proc_close,
-       .llseek         = default_llseek,
+static const struct proc_ops proc_wepkey_ops = {
+       .proc_read      = proc_read,
+       .proc_write     = proc_write,
+       .proc_open      = proc_wepkey_open,
+       .proc_release   = proc_close,
+       .proc_lseek     = default_llseek,
 };
 
 static struct proc_dir_entry *airo_entry;
index 436b819..43bab92 100644 (file)
@@ -240,13 +240,12 @@ static ssize_t debug_level_proc_write(struct file *file,
        return strnlen(buf, len);
 }
 
-static const struct file_operations debug_level_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = debug_level_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = debug_level_proc_write,
+static const struct proc_ops debug_level_proc_ops = {
+       .proc_open      = debug_level_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = debug_level_proc_write,
 };
 #endif                         /* CONFIG_LIBIPW_DEBUG */
 
@@ -263,7 +262,7 @@ static int __init libipw_init(void)
                return -EIO;
        }
        e = proc_create("debug_level", 0644, libipw_proc,
-                       &debug_level_proc_fops);
+                       &debug_level_proc_ops);
        if (!e) {
                remove_proc_entry(DRV_PROCNAME, init_net.proc_net);
                libipw_proc = NULL;
index e323e9a..58212c5 100644 (file)
@@ -126,7 +126,7 @@ static void prism2_check_sta_fw_version(local_info_t *local);
 
 #ifdef PRISM2_DOWNLOAD_SUPPORT
 /* hostap_download.c */
-static const struct file_operations prism2_download_aux_dump_proc_fops;
+static const struct proc_ops prism2_download_aux_dump_proc_ops;
 static u8 * prism2_read_pda(struct net_device *dev);
 static int prism2_download(local_info_t *local,
                           struct prism2_download_param *param);
@@ -3094,7 +3094,7 @@ prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx,
        local->func->reset_port = prism2_reset_port;
        local->func->schedule_reset = prism2_schedule_reset;
 #ifdef PRISM2_DOWNLOAD_SUPPORT
-       local->func->read_aux_fops = &prism2_download_aux_dump_proc_fops;
+       local->func->read_aux_proc_ops = &prism2_download_aux_dump_proc_ops;
        local->func->download = prism2_download;
 #endif /* PRISM2_DOWNLOAD_SUPPORT */
        local->func->tx = prism2_tx_80211;
index 6151d8d..a2ee469 100644 (file)
@@ -211,9 +211,9 @@ static ssize_t prism2_pda_proc_read(struct file *file, char __user *buf,
        return count;
 }
 
-static const struct file_operations prism2_pda_proc_fops = {
-       .read           = prism2_pda_proc_read,
-       .llseek         = generic_file_llseek,
+static const struct proc_ops prism2_pda_proc_ops = {
+       .proc_read      = prism2_pda_proc_read,
+       .proc_lseek     = generic_file_llseek,
 };
 
 
@@ -223,8 +223,8 @@ static ssize_t prism2_aux_dump_proc_no_read(struct file *file, char __user *buf,
        return 0;
 }
 
-static const struct file_operations prism2_aux_dump_proc_fops = {
-       .read           = prism2_aux_dump_proc_no_read,
+static const struct proc_ops prism2_aux_dump_proc_ops = {
+       .proc_read      = prism2_aux_dump_proc_no_read,
 };
 
 
@@ -379,9 +379,9 @@ void hostap_init_proc(local_info_t *local)
        proc_create_seq_data("wds", 0, local->proc,
                        &prism2_wds_proc_seqops, local);
        proc_create_data("pda", 0, local->proc,
-                        &prism2_pda_proc_fops, local);
+                        &prism2_pda_proc_ops, local);
        proc_create_data("aux_dump", 0, local->proc,
-                        local->func->read_aux_fops ?: &prism2_aux_dump_proc_fops,
+                        local->func->read_aux_proc_ops ?: &prism2_aux_dump_proc_ops,
                         local);
        proc_create_seq_data("bss_list", 0, local->proc,
                        &prism2_bss_list_proc_seqops, local);
index a8c4c1a..487883f 100644 (file)
@@ -599,7 +599,7 @@ struct prism2_helper_functions {
                        struct prism2_download_param *param);
        int (*tx)(struct sk_buff *skb, struct net_device *dev);
        int (*set_tim)(struct net_device *dev, int aid, int set);
-       const struct file_operations *read_aux_fops;
+       const struct proc_ops *read_aux_proc_ops;
 
        int need_tx_headroom; /* number of bytes of headroom needed before
                               * IEEE 802.11 header */
index cf37268..c1d542b 100644 (file)
@@ -2717,10 +2717,9 @@ static ssize_t ray_cs_essid_proc_write(struct file *file,
        return count;
 }
 
-static const struct file_operations ray_cs_essid_proc_fops = {
-       .owner          = THIS_MODULE,
-       .write          = ray_cs_essid_proc_write,
-       .llseek         = noop_llseek,
+static const struct proc_ops ray_cs_essid_proc_ops = {
+       .proc_write     = ray_cs_essid_proc_write,
+       .proc_lseek     = noop_llseek,
 };
 
 static ssize_t int_proc_write(struct file *file, const char __user *buffer,
@@ -2751,10 +2750,9 @@ static ssize_t int_proc_write(struct file *file, const char __user *buffer,
        return count;
 }
 
-static const struct file_operations int_proc_fops = {
-       .owner          = THIS_MODULE,
-       .write          = int_proc_write,
-       .llseek         = noop_llseek,
+static const struct proc_ops int_proc_ops = {
+       .proc_write     = int_proc_write,
+       .proc_lseek     = noop_llseek,
 };
 #endif
 
@@ -2790,10 +2788,10 @@ static int __init init_ray_cs(void)
        proc_mkdir("driver/ray_cs", NULL);
 
        proc_create_single("driver/ray_cs/ray_cs", 0, NULL, ray_cs_proc_show);
-       proc_create("driver/ray_cs/essid", 0200, NULL, &ray_cs_essid_proc_fops);
-       proc_create_data("driver/ray_cs/net_type", 0200, NULL, &int_proc_fops,
+       proc_create("driver/ray_cs/essid", 0200, NULL, &ray_cs_essid_proc_ops);
+       proc_create_data("driver/ray_cs/net_type", 0200, NULL, &int_proc_ops,
                         &net_type);
-       proc_create_data("driver/ray_cs/translate", 0200, NULL, &int_proc_fops,
+       proc_create_data("driver/ray_cs/translate", 0200, NULL, &int_proc_ops,
                         &translate);
 #endif
        if (translate != 0)
index e9127db..27203bf 100644 (file)
@@ -161,7 +161,7 @@ int of_dma_configure(struct device *dev, struct device_node *np, bool force_dma)
                coherent ? " " : " not ");
 
        iommu = of_iommu_configure(dev, np);
-       if (IS_ERR(iommu) && PTR_ERR(iommu) == -EPROBE_DEFER)
+       if (PTR_ERR(iommu) == -EPROBE_DEFER)
                return -EPROBE_DEFER;
 
        dev_dbg(dev, "device is%sbehind an iommu\n",
index 73e37bb..36c6613 100644 (file)
@@ -230,13 +230,12 @@ parse_error:
        return -EINVAL;
 }
 
-static const struct file_operations led_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = led_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = led_proc_write,
+static const struct proc_ops led_proc_ops = {
+       .proc_open      = led_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = led_proc_write,
 };
 
 static int __init led_create_procfs(void)
@@ -252,14 +251,14 @@ static int __init led_create_procfs(void)
        if (!lcd_no_led_support)
        {
                ent = proc_create_data("led", S_IRUGO|S_IWUSR, proc_pdc_root,
-                                       &led_proc_fops, (void *)LED_NOLCD); /* LED */
+                                       &led_proc_ops, (void *)LED_NOLCD); /* LED */
                if (!ent) return -1;
        }
 
        if (led_type == LED_HASLCD)
        {
                ent = proc_create_data("lcd", S_IRUGO|S_IWUSR, proc_pdc_root,
-                                       &led_proc_fops, (void *)LED_HASLCD); /* LCD */
+                                       &led_proc_ops, (void *)LED_HASLCD); /* LCD */
                if (!ent) return -1;
        }
 
index ac93f5a..0e03cef 100644 (file)
@@ -1406,7 +1406,7 @@ static struct phy *devm_of_phy_optional_get_index(struct device *dev,
        phy = devm_of_phy_get(dev, np, name);
        kfree(name);
 
-       if (IS_ERR(phy) && PTR_ERR(phy) == -ENODEV)
+       if (PTR_ERR(phy) == -ENODEV)
                phy = NULL;
 
        return phy;
index 6ef74bf..bd2b691 100644 (file)
@@ -306,19 +306,20 @@ static int proc_bus_pci_release(struct inode *inode, struct file *file)
 }
 #endif /* HAVE_PCI_MMAP */
 
-static const struct file_operations proc_bus_pci_operations = {
-       .owner          = THIS_MODULE,
-       .llseek         = proc_bus_pci_lseek,
-       .read           = proc_bus_pci_read,
-       .write          = proc_bus_pci_write,
-       .unlocked_ioctl = proc_bus_pci_ioctl,
-       .compat_ioctl   = proc_bus_pci_ioctl,
+static const struct proc_ops proc_bus_pci_ops = {
+       .proc_lseek     = proc_bus_pci_lseek,
+       .proc_read      = proc_bus_pci_read,
+       .proc_write     = proc_bus_pci_write,
+       .proc_ioctl     = proc_bus_pci_ioctl,
+#ifdef CONFIG_COMPAT
+       .proc_compat_ioctl = proc_bus_pci_ioctl,
+#endif
 #ifdef HAVE_PCI_MMAP
-       .open           = proc_bus_pci_open,
-       .release        = proc_bus_pci_release,
-       .mmap           = proc_bus_pci_mmap,
+       .proc_open      = proc_bus_pci_open,
+       .proc_release   = proc_bus_pci_release,
+       .proc_mmap      = proc_bus_pci_mmap,
 #ifdef HAVE_ARCH_PCI_GET_UNMAPPED_AREA
-       .get_unmapped_area = get_pci_unmapped_area,
+       .proc_get_unmapped_area = get_pci_unmapped_area,
 #endif /* HAVE_ARCH_PCI_GET_UNMAPPED_AREA */
 #endif /* HAVE_PCI_MMAP */
 };
@@ -424,7 +425,7 @@ int pci_proc_attach_device(struct pci_dev *dev)
 
        sprintf(name, "%02x.%x", PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
        e = proc_create_data(name, S_IFREG | S_IRUGO | S_IWUSR, bus->procdir,
-                            &proc_bus_pci_operations, dev);
+                            &proc_bus_pci_ops, dev);
        if (!e)
                return -ENOMEM;
        proc_set_size(e, dev->cfg_size);
index 2eb28cc..cd5a6c9 100644 (file)
@@ -712,7 +712,7 @@ struct phy *phy_optional_get(struct device *dev, const char *string)
 {
        struct phy *phy = phy_get(dev, string);
 
-       if (IS_ERR(phy) && (PTR_ERR(phy) == -ENODEV))
+       if (PTR_ERR(phy) == -ENODEV)
                phy = NULL;
 
        return phy;
@@ -766,7 +766,7 @@ struct phy *devm_phy_optional_get(struct device *dev, const char *string)
 {
        struct phy *phy = devm_phy_get(dev, string);
 
-       if (IS_ERR(phy) && (PTR_ERR(phy) == -ENODEV))
+       if (PTR_ERR(phy) == -ENODEV)
                phy = NULL;
 
        return phy;
index 21c370d..bddf2c5 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/module.h>
+#include <linux/pinctrl/machine.h>
 #include <linux/pinctrl/pinconf.h>
 #include <linux/pinctrl/pinconf-generic.h>
 #include <linux/pinctrl/pinmux.h>
index da794dc..8eaadba 100644 (file)
@@ -907,13 +907,12 @@ static ssize_t dispatch_proc_write(struct file *file,
        return ret;
 }
 
-static const struct file_operations dispatch_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = dispatch_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = dispatch_proc_write,
+static const struct proc_ops dispatch_proc_ops = {
+       .proc_open      = dispatch_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = dispatch_proc_write,
 };
 
 static char *next_cmd(char **cmds)
@@ -9984,7 +9983,7 @@ static int __init ibm_init(struct ibm_init_struct *iibm)
                if (ibm->write)
                        mode |= S_IWUSR;
                entry = proc_create_data(ibm->name, mode, proc_dir,
-                                        &dispatch_proc_fops, ibm);
+                                        &dispatch_proc_ops, ibm);
                if (!entry) {
                        pr_err("unable to create proc entry %s\n", ibm->name);
                        ret = -ENODEV;
index a1e6569..8089445 100644 (file)
@@ -1432,13 +1432,12 @@ static ssize_t lcd_proc_write(struct file *file, const char __user *buf,
        return count;
 }
 
-static const struct file_operations lcd_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = lcd_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = lcd_proc_write,
+static const struct proc_ops lcd_proc_ops = {
+       .proc_open      = lcd_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = lcd_proc_write,
 };
 
 /* Video-Out */
@@ -1539,13 +1538,12 @@ static ssize_t video_proc_write(struct file *file, const char __user *buf,
        return ret ? -EIO : count;
 }
 
-static const struct file_operations video_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = video_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = video_proc_write,
+static const struct proc_ops video_proc_ops = {
+       .proc_open      = video_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = video_proc_write,
 };
 
 /* Fan status */
@@ -1617,13 +1615,12 @@ static ssize_t fan_proc_write(struct file *file, const char __user *buf,
        return count;
 }
 
-static const struct file_operations fan_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = fan_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = fan_proc_write,
+static const struct proc_ops fan_proc_ops = {
+       .proc_open      = fan_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = fan_proc_write,
 };
 
 static int keys_proc_show(struct seq_file *m, void *v)
@@ -1662,13 +1659,12 @@ static ssize_t keys_proc_write(struct file *file, const char __user *buf,
        return count;
 }
 
-static const struct file_operations keys_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = keys_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = keys_proc_write,
+static const struct proc_ops keys_proc_ops = {
+       .proc_open      = keys_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = keys_proc_write,
 };
 
 static int __maybe_unused version_proc_show(struct seq_file *m, void *v)
@@ -1688,16 +1684,16 @@ static void create_toshiba_proc_entries(struct toshiba_acpi_dev *dev)
 {
        if (dev->backlight_dev)
                proc_create_data("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir,
-                                &lcd_proc_fops, dev);
+                                &lcd_proc_ops, dev);
        if (dev->video_supported)
                proc_create_data("video", S_IRUGO | S_IWUSR, toshiba_proc_dir,
-                                &video_proc_fops, dev);
+                                &video_proc_ops, dev);
        if (dev->fan_supported)
                proc_create_data("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir,
-                                &fan_proc_fops, dev);
+                                &fan_proc_ops, dev);
        if (dev->hotkey_dev)
                proc_create_data("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir,
-                                &keys_proc_fops, dev);
+                                &keys_proc_ops, dev);
        proc_create_single_data("version", S_IRUGO, toshiba_proc_dir,
                        version_proc_show, dev);
 }
index 3682097..785a796 100644 (file)
@@ -49,10 +49,9 @@ static ssize_t isapnp_proc_bus_read(struct file *file, char __user * buf,
        return nbytes;
 }
 
-static const struct file_operations isapnp_proc_bus_file_operations = {
-       .owner  = THIS_MODULE,
-       .llseek = isapnp_proc_bus_lseek,
-       .read = isapnp_proc_bus_read,
+static const struct proc_ops isapnp_proc_bus_proc_ops = {
+       .proc_lseek     = isapnp_proc_bus_lseek,
+       .proc_read      = isapnp_proc_bus_read,
 };
 
 static int isapnp_proc_attach_device(struct pnp_dev *dev)
@@ -69,7 +68,7 @@ static int isapnp_proc_attach_device(struct pnp_dev *dev)
        }
        sprintf(name, "%02x", dev->number);
        e = dev->procent = proc_create_data(name, S_IFREG | S_IRUGO, de,
-                       &isapnp_proc_bus_file_operations, dev);
+                                           &isapnp_proc_bus_proc_ops, dev);
        if (!e)
                return -ENOMEM;
        proc_set_size(e, 256);
index fe1c8f5..a806830 100644 (file)
@@ -210,13 +210,12 @@ out:
        return ret;
 }
 
-static const struct file_operations pnpbios_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = pnpbios_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = pnpbios_proc_write,
+static const struct proc_ops pnpbios_proc_ops = {
+       .proc_open      = pnpbios_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = pnpbios_proc_write,
 };
 
 int pnpbios_interface_attach_device(struct pnp_bios_node *node)
@@ -228,13 +227,13 @@ int pnpbios_interface_attach_device(struct pnp_bios_node *node)
        if (!proc_pnp)
                return -EIO;
        if (!pnpbios_dont_use_current_config) {
-               proc_create_data(name, 0644, proc_pnp, &pnpbios_proc_fops,
+               proc_create_data(name, 0644, proc_pnp, &pnpbios_proc_ops,
                                 (void *)(long)(node->handle));
        }
 
        if (!proc_pnp_boot)
                return -EIO;
-       if (proc_create_data(name, 0644, proc_pnp_boot, &pnpbios_proc_fops,
+       if (proc_create_data(name, 0644, proc_pnp_boot, &pnpbios_proc_ops,
                             (void *)(long)(node->handle + 0x100)))
                return 0;
        return -EIO;
index 8d4d69e..62a859e 100644 (file)
@@ -320,13 +320,12 @@ out_error:
 #endif                         /* CONFIG_DASD_PROFILE */
 }
 
-static const struct file_operations dasd_stats_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = dasd_stats_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = dasd_stats_proc_write,
+static const struct proc_ops dasd_stats_proc_ops = {
+       .proc_open      = dasd_stats_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = dasd_stats_proc_write,
 };
 
 /*
@@ -347,7 +346,7 @@ dasd_proc_init(void)
        dasd_statistics_entry = proc_create("statistics",
                                            S_IFREG | S_IRUGO | S_IWUSR,
                                            dasd_proc_root_entry,
-                                           &dasd_stats_proc_fops);
+                                           &dasd_stats_proc_ops);
        if (!dasd_statistics_entry)
                goto out_nostatistics;
        return 0;
index 2a3f874..da642e8 100644 (file)
@@ -398,12 +398,12 @@ cio_ignore_proc_open(struct inode *inode, struct file *file)
                                sizeof(struct ccwdev_iter));
 }
 
-static const struct file_operations cio_ignore_proc_fops = {
-       .open    = cio_ignore_proc_open,
-       .read    = seq_read,
-       .llseek  = seq_lseek,
-       .release = seq_release_private,
-       .write   = cio_ignore_write,
+static const struct proc_ops cio_ignore_proc_ops = {
+       .proc_open      = cio_ignore_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = seq_release_private,
+       .proc_write     = cio_ignore_write,
 };
 
 static int
@@ -412,7 +412,7 @@ cio_ignore_proc_init (void)
        struct proc_dir_entry *entry;
 
        entry = proc_create("cio_ignore", S_IFREG | S_IRUGO | S_IWUSR, NULL,
-                           &cio_ignore_proc_fops);
+                           &cio_ignore_proc_ops);
        if (!entry)
                return -ENOENT;
        return 0;
index 8318504..94edbb3 100644 (file)
@@ -1372,18 +1372,17 @@ static ssize_t cio_settle_write(struct file *file, const char __user *buf,
        return ret ? ret : count;
 }
 
-static const struct file_operations cio_settle_proc_fops = {
-       .open = nonseekable_open,
-       .write = cio_settle_write,
-       .llseek = no_llseek,
+static const struct proc_ops cio_settle_proc_ops = {
+       .proc_open      = nonseekable_open,
+       .proc_write     = cio_settle_write,
+       .proc_lseek     = no_llseek,
 };
 
 static int __init cio_settle_init(void)
 {
        struct proc_dir_entry *entry;
 
-       entry = proc_create("cio_settle", S_IWUSR, NULL,
-                           &cio_settle_proc_fops);
+       entry = proc_create("cio_settle", S_IWUSR, NULL, &cio_settle_proc_ops);
        if (!entry)
                return -ENOMEM;
        return 0;
index 80c5a23..7b49e2e 100644 (file)
@@ -617,6 +617,13 @@ static const struct file_operations esas2r_proc_fops = {
        .unlocked_ioctl = esas2r_proc_ioctl,
 };
 
+static const struct proc_ops esas2r_proc_ops = {
+       .proc_ioctl             = esas2r_proc_ioctl,
+#ifdef CONFIG_COMPAT
+       .proc_compat_ioctl      = compat_ptr_ioctl,
+#endif
+};
+
 static struct Scsi_Host *esas2r_proc_host;
 static int esas2r_proc_major;
 
@@ -728,7 +735,7 @@ const char *esas2r_info(struct Scsi_Host *sh)
 
                        pde = proc_create(ATTONODE_NAME, 0,
                                          sh->hostt->proc_dir,
-                                         &esas2r_proc_fops);
+                                         &esas2r_proc_ops);
 
                        if (!pde) {
                                esas2r_log_dev(ESAS2R_LOG_WARN,
index df14597..eed3102 100644 (file)
@@ -736,13 +736,12 @@ out:
        return err;
 }
 
-static const struct file_operations scsi_devinfo_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = proc_scsi_devinfo_open,
-       .read           = seq_read,
-       .write          = proc_scsi_devinfo_write,
-       .llseek         = seq_lseek,
-       .release        = seq_release,
+static const struct proc_ops scsi_devinfo_proc_ops = {
+       .proc_open      = proc_scsi_devinfo_open,
+       .proc_read      = seq_read,
+       .proc_write     = proc_scsi_devinfo_write,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = seq_release,
 };
 #endif /* CONFIG_SCSI_PROC_FS */
 
@@ -867,7 +866,7 @@ int __init scsi_init_devinfo(void)
        }
 
 #ifdef CONFIG_SCSI_PROC_FS
-       p = proc_create("scsi/device_info", 0, NULL, &scsi_devinfo_proc_fops);
+       p = proc_create("scsi/device_info", 0, NULL, &scsi_devinfo_proc_ops);
        if (!p) {
                error = -ENOMEM;
                goto out;
index 5b31322..d6982d3 100644 (file)
@@ -83,12 +83,12 @@ static int proc_scsi_host_open(struct inode *inode, struct file *file)
                                4 * PAGE_SIZE);
 }
 
-static const struct file_operations proc_scsi_fops = {
-       .open = proc_scsi_host_open,
-       .release = single_release,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .write = proc_scsi_host_write
+static const struct proc_ops proc_scsi_ops = {
+       .proc_open      = proc_scsi_host_open,
+       .proc_release   = single_release,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_write     = proc_scsi_host_write
 };
 
 /**
@@ -146,7 +146,7 @@ void scsi_proc_host_add(struct Scsi_Host *shost)
 
        sprintf(name,"%d", shost->host_no);
        p = proc_create_data(name, S_IRUGO | S_IWUSR,
-               sht->proc_dir, &proc_scsi_fops, shost);
+               sht->proc_dir, &proc_scsi_ops, shost);
        if (!p)
                printk(KERN_ERR "%s: Failed to register host %d in"
                       "%s\n", __func__, shost->host_no,
@@ -436,13 +436,12 @@ static int proc_scsi_open(struct inode *inode, struct file *file)
        return seq_open(file, &scsi_seq_ops);
 }
 
-static const struct file_operations proc_scsi_operations = {
-       .owner          = THIS_MODULE,
-       .open           = proc_scsi_open,
-       .read           = seq_read,
-       .write          = proc_scsi_write,
-       .llseek         = seq_lseek,
-       .release        = seq_release,
+static const struct proc_ops scsi_scsi_proc_ops = {
+       .proc_open      = proc_scsi_open,
+       .proc_read      = seq_read,
+       .proc_write     = proc_scsi_write,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = seq_release,
 };
 
 /**
@@ -456,7 +455,7 @@ int __init scsi_init_procfs(void)
        if (!proc_scsi)
                goto err1;
 
-       pde = proc_create("scsi/scsi", 0, NULL, &proc_scsi_operations);
+       pde = proc_create("scsi/scsi", 0, NULL, &scsi_scsi_proc_ops);
        if (!pde)
                goto err2;
 
index bafeaf7..4e6af59 100644 (file)
@@ -2322,25 +2322,23 @@ static int sg_proc_seq_show_int(struct seq_file *s, void *v);
 static int sg_proc_single_open_adio(struct inode *inode, struct file *file);
 static ssize_t sg_proc_write_adio(struct file *filp, const char __user *buffer,
                                  size_t count, loff_t *off);
-static const struct file_operations adio_fops = {
-       .owner = THIS_MODULE,
-       .open = sg_proc_single_open_adio,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .write = sg_proc_write_adio,
-       .release = single_release,
+static const struct proc_ops adio_proc_ops = {
+       .proc_open      = sg_proc_single_open_adio,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_write     = sg_proc_write_adio,
+       .proc_release   = single_release,
 };
 
 static int sg_proc_single_open_dressz(struct inode *inode, struct file *file);
 static ssize_t sg_proc_write_dressz(struct file *filp, 
                const char __user *buffer, size_t count, loff_t *off);
-static const struct file_operations dressz_fops = {
-       .owner = THIS_MODULE,
-       .open = sg_proc_single_open_dressz,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .write = sg_proc_write_dressz,
-       .release = single_release,
+static const struct proc_ops dressz_proc_ops = {
+       .proc_open      = sg_proc_single_open_dressz,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_write     = sg_proc_write_dressz,
+       .proc_release   = single_release,
 };
 
 static int sg_proc_seq_show_version(struct seq_file *s, void *v);
@@ -2381,9 +2379,9 @@ sg_proc_init(void)
        if (!p)
                return 1;
 
-       proc_create("allow_dio", S_IRUGO | S_IWUSR, p, &adio_fops);
+       proc_create("allow_dio", S_IRUGO | S_IWUSR, p, &adio_proc_ops);
        proc_create_seq("debug", S_IRUGO, p, &debug_seq_ops);
-       proc_create("def_reserved_size", S_IRUGO | S_IWUSR, p, &dressz_fops);
+       proc_create("def_reserved_size", S_IRUGO | S_IWUSR, p, &dressz_proc_ops);
        proc_create_single("device_hdr", S_IRUGO, p, sg_proc_seq_show_devhdr);
        proc_create_seq("devices", S_IRUGO, p, &dev_seq_ops);
        proc_create_seq("device_strs", S_IRUGO, p, &devstrs_seq_ops);
index c7266ef..1f59beb 100644 (file)
@@ -646,8 +646,7 @@ static int orion_spi_probe(struct platform_device *pdev)
 
        /* The following clock is only used by some SoCs */
        spi->axi_clk = devm_clk_get(&pdev->dev, "axi");
-       if (IS_ERR(spi->axi_clk) &&
-           PTR_ERR(spi->axi_clk) == -EPROBE_DEFER) {
+       if (PTR_ERR(spi->axi_clk) == -EPROBE_DEFER) {
                status = -EPROBE_DEFER;
                goto out_rel_clk;
        }
index 4a6c3f6..aa9dab8 100644 (file)
@@ -264,12 +264,12 @@ static int open_debug_level(struct inode *inode, struct file *file)
        return single_open(file, show_debug_level, NULL);
 }
 
-static const struct file_operations fops = {
-       .open = open_debug_level,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .write = write_debug_level,
-       .release = single_release,
+static const struct proc_ops debug_level_proc_ops = {
+       .proc_open      = open_debug_level,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_write     = write_debug_level,
+       .proc_release   = single_release,
 };
 
 int __init ieee80211_debug_init(void)
@@ -284,7 +284,7 @@ int __init ieee80211_debug_init(void)
                                " proc directory\n");
                return -EIO;
        }
-       e = proc_create("debug_level", 0644, ieee80211_proc, &fops);
+       e = proc_create("debug_level", 0644, ieee80211_proc, &debug_level_proc_ops);
        if (!e) {
                remove_proc_entry(DRV_NAME, init_net.proc_net);
                ieee80211_proc = NULL;
index 1d4f317..f724962 100644 (file)
@@ -1101,15 +1101,15 @@ static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
        return count;
 }
 
-static const struct file_operations proc_sysrq_trigger_operations = {
-       .write          = write_sysrq_trigger,
-       .llseek         = noop_llseek,
+static const struct proc_ops sysrq_trigger_proc_ops = {
+       .proc_write     = write_sysrq_trigger,
+       .proc_lseek     = noop_llseek,
 };
 
 static void sysrq_init_procfs(void)
 {
        if (!proc_create("sysrq-trigger", S_IWUSR, NULL,
-                        &proc_sysrq_trigger_operations))
+                        &sysrq_trigger_proc_ops))
                pr_err("Failed to register proc interface\n");
 }
 
index 04c142c..64de9f1 100644 (file)
@@ -72,7 +72,7 @@ static rndis_resp_t *rndis_add_response(struct rndis_params *params,
 
 #ifdef CONFIG_USB_GADGET_DEBUG_FILES
 
-static const struct file_operations rndis_proc_fops;
+static const struct proc_ops rndis_proc_ops;
 
 #endif /* CONFIG_USB_GADGET_DEBUG_FILES */
 
@@ -902,7 +902,7 @@ struct rndis_params *rndis_register(void (*resp_avail)(void *v), void *v)
 
                sprintf(name, NAME_TEMPLATE, i);
                proc_entry = proc_create_data(name, 0660, NULL,
-                                             &rndis_proc_fops, params);
+                                             &rndis_proc_ops, params);
                if (!proc_entry) {
                        kfree(params);
                        rndis_put_nr(i);
@@ -1164,13 +1164,12 @@ static int rndis_proc_open(struct inode *inode, struct file *file)
        return single_open(file, rndis_proc_show, PDE_DATA(inode));
 }
 
-static const struct file_operations rndis_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = rndis_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = rndis_proc_write,
+static const struct proc_ops rndis_proc_ops = {
+       .proc_open      = rndis_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = rndis_proc_write,
 };
 
 #define        NAME_TEMPLATE "driver/rndis-%03d"
index 08a17eb..370bf25 100644 (file)
@@ -1017,7 +1017,7 @@ static int imxfb_probe(struct platform_device *pdev)
        }
 
        fbi->lcd_pwr = devm_regulator_get(&pdev->dev, "lcd");
-       if (IS_ERR(fbi->lcd_pwr) && (PTR_ERR(fbi->lcd_pwr) == -EPROBE_DEFER)) {
+       if (PTR_ERR(fbi->lcd_pwr) == -EPROBE_DEFER) {
                ret = -EPROBE_DEFER;
                goto failed_lcd;
        }
index f815f98..852673c 100644 (file)
@@ -1173,13 +1173,12 @@ static ssize_t viafb_dvp0_proc_write(struct file *file,
        return count;
 }
 
-static const struct file_operations viafb_dvp0_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = viafb_dvp0_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = viafb_dvp0_proc_write,
+static const struct proc_ops viafb_dvp0_proc_ops = {
+       .proc_open      = viafb_dvp0_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = viafb_dvp0_proc_write,
 };
 
 static int viafb_dvp1_proc_show(struct seq_file *m, void *v)
@@ -1238,13 +1237,12 @@ static ssize_t viafb_dvp1_proc_write(struct file *file,
        return count;
 }
 
-static const struct file_operations viafb_dvp1_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = viafb_dvp1_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = viafb_dvp1_proc_write,
+static const struct proc_ops viafb_dvp1_proc_ops = {
+       .proc_open      = viafb_dvp1_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = viafb_dvp1_proc_write,
 };
 
 static int viafb_dfph_proc_show(struct seq_file *m, void *v)
@@ -1273,13 +1271,12 @@ static ssize_t viafb_dfph_proc_write(struct file *file,
        return count;
 }
 
-static const struct file_operations viafb_dfph_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = viafb_dfph_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = viafb_dfph_proc_write,
+static const struct proc_ops viafb_dfph_proc_ops = {
+       .proc_open      = viafb_dfph_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = viafb_dfph_proc_write,
 };
 
 static int viafb_dfpl_proc_show(struct seq_file *m, void *v)
@@ -1308,13 +1305,12 @@ static ssize_t viafb_dfpl_proc_write(struct file *file,
        return count;
 }
 
-static const struct file_operations viafb_dfpl_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = viafb_dfpl_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = viafb_dfpl_proc_write,
+static const struct proc_ops viafb_dfpl_proc_ops = {
+       .proc_open      = viafb_dfpl_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = viafb_dfpl_proc_write,
 };
 
 static int viafb_vt1636_proc_show(struct seq_file *m, void *v)
@@ -1444,13 +1440,12 @@ static ssize_t viafb_vt1636_proc_write(struct file *file,
        return count;
 }
 
-static const struct file_operations viafb_vt1636_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = viafb_vt1636_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = viafb_vt1636_proc_write,
+static const struct proc_ops viafb_vt1636_proc_ops = {
+       .proc_open      = viafb_vt1636_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = viafb_vt1636_proc_write,
 };
 
 #endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
@@ -1522,13 +1517,12 @@ static ssize_t viafb_iga1_odev_proc_write(struct file *file,
        return res;
 }
 
-static const struct file_operations viafb_iga1_odev_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = viafb_iga1_odev_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = viafb_iga1_odev_proc_write,
+static const struct proc_ops viafb_iga1_odev_proc_ops = {
+       .proc_open      = viafb_iga1_odev_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = viafb_iga1_odev_proc_write,
 };
 
 static int viafb_iga2_odev_proc_show(struct seq_file *m, void *v)
@@ -1562,13 +1556,12 @@ static ssize_t viafb_iga2_odev_proc_write(struct file *file,
        return res;
 }
 
-static const struct file_operations viafb_iga2_odev_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = viafb_iga2_odev_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = viafb_iga2_odev_proc_write,
+static const struct proc_ops viafb_iga2_odev_proc_ops = {
+       .proc_open      = viafb_iga2_odev_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = viafb_iga2_odev_proc_write,
 };
 
 #define IS_VT1636(lvds_chip)   ((lvds_chip).lvds_chip_name == VT1636_LVDS)
@@ -1580,14 +1573,14 @@ static void viafb_init_proc(struct viafb_shared *shared)
        shared->proc_entry = viafb_entry;
        if (viafb_entry) {
 #ifdef CONFIG_FB_VIA_DIRECT_PROCFS
-               proc_create("dvp0", 0, viafb_entry, &viafb_dvp0_proc_fops);
-               proc_create("dvp1", 0, viafb_entry, &viafb_dvp1_proc_fops);
-               proc_create("dfph", 0, viafb_entry, &viafb_dfph_proc_fops);
-               proc_create("dfpl", 0, viafb_entry, &viafb_dfpl_proc_fops);
+               proc_create("dvp0", 0, viafb_entry, &viafb_dvp0_proc_ops);
+               proc_create("dvp1", 0, viafb_entry, &viafb_dvp1_proc_ops);
+               proc_create("dfph", 0, viafb_entry, &viafb_dfph_proc_ops);
+               proc_create("dfpl", 0, viafb_entry, &viafb_dfpl_proc_ops);
                if (IS_VT1636(shared->chip_info.lvds_chip_info)
                        || IS_VT1636(shared->chip_info.lvds_chip_info2))
                        proc_create("vt1636", 0, viafb_entry,
-                               &viafb_vt1636_proc_fops);
+                                   &viafb_vt1636_proc_ops);
 #endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
 
                proc_create_single("supported_output_devices", 0, viafb_entry,
@@ -1595,11 +1588,11 @@ static void viafb_init_proc(struct viafb_shared *shared)
                iga1_entry = proc_mkdir("iga1", viafb_entry);
                shared->iga1_proc_entry = iga1_entry;
                proc_create("output_devices", 0, iga1_entry,
-                       &viafb_iga1_odev_proc_fops);
+                           &viafb_iga1_odev_proc_ops);
                iga2_entry = proc_mkdir("iga2", viafb_entry);
                shared->iga2_proc_entry = iga2_entry;
                proc_create("output_devices", 0, iga2_entry,
-                       &viafb_iga2_odev_proc_fops);
+                           &viafb_iga2_odev_proc_ops);
        }
 }
 static void viafb_remove_proc(struct viafb_shared *shared)
index 2e4ca4d..1c9ae08 100644 (file)
@@ -56,10 +56,9 @@ proc_bus_zorro_read(struct file *file, char __user *buf, size_t nbytes, loff_t *
        return nbytes;
 }
 
-static const struct file_operations proc_bus_zorro_operations = {
-       .owner          = THIS_MODULE,
-       .llseek         = proc_bus_zorro_lseek,
-       .read           = proc_bus_zorro_read,
+static const struct proc_ops bus_zorro_proc_ops = {
+       .proc_lseek     = proc_bus_zorro_lseek,
+       .proc_read      = proc_bus_zorro_read,
 };
 
 static void * zorro_seq_start(struct seq_file *m, loff_t *pos)
@@ -105,7 +104,7 @@ static int __init zorro_proc_attach_device(unsigned int slot)
 
        sprintf(name, "%02x", slot);
        entry = proc_create_data(name, 0, proc_bus_zorro_dir,
-                                &proc_bus_zorro_operations,
+                                &bus_zorro_proc_ops,
                                 &zorro_autocon[slot]);
        if (!entry)
                return -ENOMEM;
index 19f6e59..276e4b5 100644 (file)
@@ -611,12 +611,12 @@ static int cifs_stats_proc_open(struct inode *inode, struct file *file)
        return single_open(file, cifs_stats_proc_show, NULL);
 }
 
-static const struct file_operations cifs_stats_proc_fops = {
-       .open           = cifs_stats_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = cifs_stats_proc_write,
+static const struct proc_ops cifs_stats_proc_ops = {
+       .proc_open      = cifs_stats_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = cifs_stats_proc_write,
 };
 
 #ifdef CONFIG_CIFS_SMB_DIRECT
@@ -640,12 +640,12 @@ static int name##_open(struct inode *inode, struct file *file) \
        return single_open(file, name##_proc_show, NULL); \
 } \
 \
-static const struct file_operations cifs_##name##_proc_fops = { \
-       .open           = name##_open, \
-       .read           = seq_read, \
-       .llseek         = seq_lseek, \
-       .release        = single_release, \
-       .write          = name##_write, \
+static const struct proc_ops cifs_##name##_proc_fops = { \
+       .proc_open      = name##_open, \
+       .proc_read      = seq_read, \
+       .proc_lseek     = seq_lseek, \
+       .proc_release   = single_release, \
+       .proc_write     = name##_write, \
 }
 
 PROC_FILE_DEFINE(rdma_readwrite_threshold);
@@ -659,11 +659,11 @@ PROC_FILE_DEFINE(smbd_receive_credit_max);
 #endif
 
 static struct proc_dir_entry *proc_fs_cifs;
-static const struct file_operations cifsFYI_proc_fops;
-static const struct file_operations cifs_lookup_cache_proc_fops;
-static const struct file_operations traceSMB_proc_fops;
-static const struct file_operations cifs_security_flags_proc_fops;
-static const struct file_operations cifs_linux_ext_proc_fops;
+static const struct proc_ops cifsFYI_proc_ops;
+static const struct proc_ops cifs_lookup_cache_proc_ops;
+static const struct proc_ops traceSMB_proc_ops;
+static const struct proc_ops cifs_security_flags_proc_ops;
+static const struct proc_ops cifs_linux_ext_proc_ops;
 
 void
 cifs_proc_init(void)
@@ -678,18 +678,18 @@ cifs_proc_init(void)
        proc_create_single("open_files", 0400, proc_fs_cifs,
                        cifs_debug_files_proc_show);
 
-       proc_create("Stats", 0644, proc_fs_cifs, &cifs_stats_proc_fops);
-       proc_create("cifsFYI", 0644, proc_fs_cifs, &cifsFYI_proc_fops);
-       proc_create("traceSMB", 0644, proc_fs_cifs, &traceSMB_proc_fops);
+       proc_create("Stats", 0644, proc_fs_cifs, &cifs_stats_proc_ops);
+       proc_create("cifsFYI", 0644, proc_fs_cifs, &cifsFYI_proc_ops);
+       proc_create("traceSMB", 0644, proc_fs_cifs, &traceSMB_proc_ops);
        proc_create("LinuxExtensionsEnabled", 0644, proc_fs_cifs,
-                   &cifs_linux_ext_proc_fops);
+                   &cifs_linux_ext_proc_ops);
        proc_create("SecurityFlags", 0644, proc_fs_cifs,
-                   &cifs_security_flags_proc_fops);
+                   &cifs_security_flags_proc_ops);
        proc_create("LookupCacheEnabled", 0644, proc_fs_cifs,
-                   &cifs_lookup_cache_proc_fops);
+                   &cifs_lookup_cache_proc_ops);
 
 #ifdef CONFIG_CIFS_DFS_UPCALL
-       proc_create("dfscache", 0644, proc_fs_cifs, &dfscache_proc_fops);
+       proc_create("dfscache", 0644, proc_fs_cifs, &dfscache_proc_ops);
 #endif
 
 #ifdef CONFIG_CIFS_SMB_DIRECT
@@ -774,12 +774,12 @@ static ssize_t cifsFYI_proc_write(struct file *file, const char __user *buffer,
        return count;
 }
 
-static const struct file_operations cifsFYI_proc_fops = {
-       .open           = cifsFYI_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = cifsFYI_proc_write,
+static const struct proc_ops cifsFYI_proc_ops = {
+       .proc_open      = cifsFYI_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = cifsFYI_proc_write,
 };
 
 static int cifs_linux_ext_proc_show(struct seq_file *m, void *v)
@@ -805,12 +805,12 @@ static ssize_t cifs_linux_ext_proc_write(struct file *file,
        return count;
 }
 
-static const struct file_operations cifs_linux_ext_proc_fops = {
-       .open           = cifs_linux_ext_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = cifs_linux_ext_proc_write,
+static const struct proc_ops cifs_linux_ext_proc_ops = {
+       .proc_open      = cifs_linux_ext_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = cifs_linux_ext_proc_write,
 };
 
 static int cifs_lookup_cache_proc_show(struct seq_file *m, void *v)
@@ -836,12 +836,12 @@ static ssize_t cifs_lookup_cache_proc_write(struct file *file,
        return count;
 }
 
-static const struct file_operations cifs_lookup_cache_proc_fops = {
-       .open           = cifs_lookup_cache_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = cifs_lookup_cache_proc_write,
+static const struct proc_ops cifs_lookup_cache_proc_ops = {
+       .proc_open      = cifs_lookup_cache_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = cifs_lookup_cache_proc_write,
 };
 
 static int traceSMB_proc_show(struct seq_file *m, void *v)
@@ -867,12 +867,12 @@ static ssize_t traceSMB_proc_write(struct file *file, const char __user *buffer,
        return count;
 }
 
-static const struct file_operations traceSMB_proc_fops = {
-       .open           = traceSMB_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = traceSMB_proc_write,
+static const struct proc_ops traceSMB_proc_ops = {
+       .proc_open      = traceSMB_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = traceSMB_proc_write,
 };
 
 static int cifs_security_flags_proc_show(struct seq_file *m, void *v)
@@ -978,12 +978,12 @@ static ssize_t cifs_security_flags_proc_write(struct file *file,
        return count;
 }
 
-static const struct file_operations cifs_security_flags_proc_fops = {
-       .open           = cifs_security_flags_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = cifs_security_flags_proc_write,
+static const struct proc_ops cifs_security_flags_proc_ops = {
+       .proc_open      = cifs_security_flags_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = cifs_security_flags_proc_write,
 };
 #else
 inline void cifs_proc_init(void)
index 9a384d1..43c1b43 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/jhash.h>
 #include <linux/ktime.h>
 #include <linux/slab.h>
+#include <linux/proc_fs.h>
 #include <linux/nls.h>
 #include <linux/workqueue.h>
 #include "cifsglob.h"
@@ -211,12 +212,12 @@ static int dfscache_proc_open(struct inode *inode, struct file *file)
        return single_open(file, dfscache_proc_show, NULL);
 }
 
-const struct file_operations dfscache_proc_fops = {
-       .open           = dfscache_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = dfscache_proc_write,
+const struct proc_ops dfscache_proc_ops = {
+       .proc_open      = dfscache_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = dfscache_proc_write,
 };
 
 #ifdef CONFIG_CIFS_DEBUG2
index 76c7329..99ee44f 100644 (file)
@@ -24,7 +24,7 @@ struct dfs_cache_tgt_iterator {
 
 extern int dfs_cache_init(void);
 extern void dfs_cache_destroy(void);
-extern const struct file_operations dfscache_proc_fops;
+extern const struct proc_ops dfscache_proc_ops;
 
 extern int dfs_cache_find(const unsigned int xid, struct cifs_ses *ses,
                          const struct nls_table *nls_codepage, int remap,
index 88b213b..8434217 100644 (file)
@@ -6043,7 +6043,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
                bh = ext4_bread(handle, inode, blk,
                                EXT4_GET_BLOCKS_CREATE |
                                EXT4_GET_BLOCKS_METADATA_NOFAIL);
-       } while (IS_ERR(bh) && (PTR_ERR(bh) == -ENOSPC) &&
+       } while (PTR_ERR(bh) == -ENOSPC &&
                 ext4_should_retry_alloc(inode->i_sb, &retries));
        if (IS_ERR(bh))
                return PTR_ERR(bh);
index 3314a0f..9d02cdc 100644 (file)
@@ -875,7 +875,7 @@ static int truncate_dnode(struct dnode_of_data *dn)
 
        /* get direct node */
        page = f2fs_get_node_page(F2FS_I_SB(dn->inode), dn->nid);
-       if (IS_ERR(page) && PTR_ERR(page) == -ENOENT)
+       if (PTR_ERR(page) == -ENOENT)
                return 1;
        else if (IS_ERR(page))
                return PTR_ERR(page);
index 9616af3..08e91ef 100644 (file)
@@ -111,7 +111,7 @@ extern void fscache_enqueue_object(struct fscache_object *);
  * object-list.c
  */
 #ifdef CONFIG_FSCACHE_OBJECT_LIST
-extern const struct file_operations fscache_objlist_fops;
+extern const struct proc_ops fscache_objlist_proc_ops;
 
 extern void fscache_objlist_add(struct fscache_object *);
 extern void fscache_objlist_remove(struct fscache_object *);
index 72ebfe5..e106a1a 100644 (file)
@@ -7,6 +7,7 @@
 
 #define FSCACHE_DEBUG_LEVEL COOKIE
 #include <linux/module.h>
+#include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/key.h>
@@ -405,9 +406,9 @@ static int fscache_objlist_release(struct inode *inode, struct file *file)
        return seq_release(inode, file);
 }
 
-const struct file_operations fscache_objlist_fops = {
-       .open           = fscache_objlist_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = fscache_objlist_release,
+const struct proc_ops fscache_objlist_proc_ops = {
+       .proc_open      = fscache_objlist_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = fscache_objlist_release,
 };
index 5523446..90a7bc2 100644 (file)
@@ -35,7 +35,7 @@ int __init fscache_proc_init(void)
 
 #ifdef CONFIG_FSCACHE_OBJECT_LIST
        if (!proc_create("fs/fscache/objects", S_IFREG | 0444, NULL,
-                        &fscache_objlist_fops))
+                        &fscache_objlist_proc_ops))
                goto error_objects;
 #endif
 
index 60bf8ff..eb8ca44 100644 (file)
@@ -1074,12 +1074,11 @@ static int jbd2_seq_info_release(struct inode *inode, struct file *file)
        return seq_release(inode, file);
 }
 
-static const struct file_operations jbd2_seq_info_fops = {
-       .owner          = THIS_MODULE,
-       .open           = jbd2_seq_info_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = jbd2_seq_info_release,
+static const struct proc_ops jbd2_info_proc_ops = {
+       .proc_open      = jbd2_seq_info_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = jbd2_seq_info_release,
 };
 
 static struct proc_dir_entry *proc_jbd2_stats;
@@ -1089,7 +1088,7 @@ static void jbd2_stats_proc_init(journal_t *journal)
        journal->j_proc_entry = proc_mkdir(journal->j_devname, proc_jbd2_stats);
        if (journal->j_proc_entry) {
                proc_create_data("info", S_IRUGO, journal->j_proc_entry,
-                                &jbd2_seq_info_fops, journal);
+                                &jbd2_info_proc_ops, journal);
        }
 }
 
index 888cdd6..44b62b3 100644 (file)
@@ -43,12 +43,12 @@ static ssize_t jfs_loglevel_proc_write(struct file *file,
        return count;
 }
 
-static const struct file_operations jfs_loglevel_proc_fops = {
-       .open           = jfs_loglevel_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = jfs_loglevel_proc_write,
+static const struct proc_ops jfs_loglevel_proc_ops = {
+       .proc_open      = jfs_loglevel_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = jfs_loglevel_proc_write,
 };
 #endif
 
@@ -68,7 +68,7 @@ void jfs_proc_init(void)
 #endif
 #ifdef CONFIG_JFS_DEBUG
        proc_create_single("TxAnchor", 0, base, jfs_txanchor_proc_show);
-       proc_create("loglevel", 0, base, &jfs_loglevel_proc_fops);
+       proc_create("loglevel", 0, base, &jfs_loglevel_proc_ops);
 #endif
 }
 
index ca9228a..a01f08c 100644 (file)
@@ -60,11 +60,11 @@ nlm_end_grace_read(struct file *file, char __user *buf, size_t size,
        return simple_read_from_buffer(buf, size, pos, resp, sizeof(resp));
 }
 
-static const struct file_operations lockd_end_grace_operations = {
-       .write          = nlm_end_grace_write,
-       .read           = nlm_end_grace_read,
-       .llseek         = default_llseek,
-       .release        = simple_transaction_release,
+static const struct proc_ops lockd_end_grace_proc_ops = {
+       .proc_write     = nlm_end_grace_write,
+       .proc_read      = nlm_end_grace_read,
+       .proc_lseek     = default_llseek,
+       .proc_release   = simple_transaction_release,
 };
 
 int __init
@@ -76,7 +76,7 @@ lockd_create_procfs(void)
        if (!entry)
                return -ENOMEM;
        entry = proc_create("nlm_end_grace", S_IRUGO|S_IWUSR, entry,
-                                &lockd_end_grace_operations);
+                           &lockd_end_grace_proc_ops);
        if (!entry) {
                remove_proc_entry("fs/lockd", NULL);
                return -ENOMEM;
index 11b42c5..7eb919f 100644 (file)
@@ -157,11 +157,11 @@ static int exports_proc_open(struct inode *inode, struct file *file)
        return exports_net_open(current->nsproxy->net_ns, file);
 }
 
-static const struct file_operations exports_proc_operations = {
-       .open           = exports_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = seq_release,
+static const struct proc_ops exports_proc_ops = {
+       .proc_open      = exports_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = seq_release,
 };
 
 static int exports_nfsd_open(struct inode *inode, struct file *file)
@@ -1431,8 +1431,7 @@ static int create_proc_exports_entry(void)
        entry = proc_mkdir("fs/nfs", NULL);
        if (!entry)
                return -ENOMEM;
-       entry = proc_create("exports", 0, entry,
-                                &exports_proc_operations);
+       entry = proc_create("exports", 0, entry, &exports_proc_ops);
        if (!entry) {
                remove_proc_entry("fs/nfs", NULL);
                return -ENOMEM;
index 9bce3b9..b1bc582 100644 (file)
@@ -84,17 +84,17 @@ static int nfsd_proc_open(struct inode *inode, struct file *file)
        return single_open(file, nfsd_proc_show, NULL);
 }
 
-static const struct file_operations nfsd_proc_fops = {
-       .open = nfsd_proc_open,
-       .read  = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
+static const struct proc_ops nfsd_proc_ops = {
+       .proc_open      = nfsd_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
 };
 
 void
 nfsd_stat_init(void)
 {
-       svc_proc_register(&init_net, &nfsd_svcstats, &nfsd_proc_fops);
+       svc_proc_register(&init_net, &nfsd_svcstats, &nfsd_proc_ops);
 }
 
 void
index 9876db5..6cd5e49 100644 (file)
@@ -2101,17 +2101,15 @@ static int ocfs2_is_io_unaligned(struct inode *inode, size_t count, loff_t pos)
 static int ocfs2_inode_lock_for_extent_tree(struct inode *inode,
                                            struct buffer_head **di_bh,
                                            int meta_level,
-                                           int overwrite_io,
                                            int write_sem,
                                            int wait)
 {
        int ret = 0;
 
        if (wait)
-               ret = ocfs2_inode_lock(inode, NULL, meta_level);
+               ret = ocfs2_inode_lock(inode, di_bh, meta_level);
        else
-               ret = ocfs2_try_inode_lock(inode,
-                       overwrite_io ? NULL : di_bh, meta_level);
+               ret = ocfs2_try_inode_lock(inode, di_bh, meta_level);
        if (ret < 0)
                goto out;
 
@@ -2136,6 +2134,7 @@ static int ocfs2_inode_lock_for_extent_tree(struct inode *inode,
 
 out_unlock:
        brelse(*di_bh);
+       *di_bh = NULL;
        ocfs2_inode_unlock(inode, meta_level);
 out:
        return ret;
@@ -2177,7 +2176,6 @@ static int ocfs2_prepare_inode_for_write(struct file *file,
                ret = ocfs2_inode_lock_for_extent_tree(inode,
                                                       &di_bh,
                                                       meta_level,
-                                                      overwrite_io,
                                                       write_sem,
                                                       wait);
                if (ret < 0) {
@@ -2233,13 +2231,13 @@ static int ocfs2_prepare_inode_for_write(struct file *file,
                                                           &di_bh,
                                                           meta_level,
                                                           write_sem);
+                       meta_level = 1;
+                       write_sem = 1;
                        ret = ocfs2_inode_lock_for_extent_tree(inode,
                                                               &di_bh,
                                                               meta_level,
-                                                              overwrite_io,
-                                                              1,
+                                                              write_sem,
                                                               wait);
-                       write_sem = 1;
                        if (ret < 0) {
                                if (ret != -EAGAIN)
                                        mlog_errno(ret);
index 4180c3e..939df99 100644 (file)
@@ -696,7 +696,7 @@ static int ocfs2_block_group_alloc(struct ocfs2_super *osb,
 
        bg_bh = ocfs2_block_group_alloc_contig(osb, handle, alloc_inode,
                                               ac, cl);
-       if (IS_ERR(bg_bh) && (PTR_ERR(bg_bh) == -ENOSPC))
+       if (PTR_ERR(bg_bh) == -ENOSPC)
                bg_bh = ocfs2_block_group_alloc_discontig(handle,
                                                          alloc_inode,
                                                          ac, cl);
index 96f1087..c1dea9b 100644 (file)
@@ -16,16 +16,16 @@ static int cpuinfo_open(struct inode *inode, struct file *file)
        return seq_open(file, &cpuinfo_op);
 }
 
-static const struct file_operations proc_cpuinfo_operations = {
-       .open           = cpuinfo_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = seq_release,
+static const struct proc_ops cpuinfo_proc_ops = {
+       .proc_open      = cpuinfo_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = seq_release,
 };
 
 static int __init proc_cpuinfo_init(void)
 {
-       proc_create("cpuinfo", 0, NULL, &proc_cpuinfo_operations);
+       proc_create("cpuinfo", 0, NULL, &cpuinfo_proc_ops);
        return 0;
 }
 fs_initcall(proc_cpuinfo_init);
index 074e958..3faed94 100644 (file)
@@ -473,7 +473,7 @@ struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode,
        ent = __proc_create(&parent, name, S_IFDIR | mode, 2);
        if (ent) {
                ent->data = data;
-               ent->proc_fops = &proc_dir_operations;
+               ent->proc_dir_ops = &proc_dir_operations;
                ent->proc_iops = &proc_dir_inode_operations;
                ent = proc_register(parent, ent);
        }
@@ -503,7 +503,7 @@ struct proc_dir_entry *proc_create_mount_point(const char *name)
        ent = __proc_create(&parent, name, mode, 2);
        if (ent) {
                ent->data = NULL;
-               ent->proc_fops = NULL;
+               ent->proc_dir_ops = NULL;
                ent->proc_iops = NULL;
                ent = proc_register(parent, ent);
        }
@@ -533,25 +533,23 @@ struct proc_dir_entry *proc_create_reg(const char *name, umode_t mode,
 
 struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
                struct proc_dir_entry *parent,
-               const struct file_operations *proc_fops, void *data)
+               const struct proc_ops *proc_ops, void *data)
 {
        struct proc_dir_entry *p;
 
-       BUG_ON(proc_fops == NULL);
-
        p = proc_create_reg(name, mode, &parent, data);
        if (!p)
                return NULL;
-       p->proc_fops = proc_fops;
+       p->proc_ops = proc_ops;
        return proc_register(parent, p);
 }
 EXPORT_SYMBOL(proc_create_data);
  
 struct proc_dir_entry *proc_create(const char *name, umode_t mode,
                                   struct proc_dir_entry *parent,
-                                  const struct file_operations *proc_fops)
+                                  const struct proc_ops *proc_ops)
 {
-       return proc_create_data(name, mode, parent, proc_fops, NULL);
+       return proc_create_data(name, mode, parent, proc_ops, NULL);
 }
 EXPORT_SYMBOL(proc_create);
 
@@ -573,11 +571,11 @@ static int proc_seq_release(struct inode *inode, struct file *file)
        return seq_release(inode, file);
 }
 
-static const struct file_operations proc_seq_fops = {
-       .open           = proc_seq_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = proc_seq_release,
+static const struct proc_ops proc_seq_ops = {
+       .proc_open      = proc_seq_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = proc_seq_release,
 };
 
 struct proc_dir_entry *proc_create_seq_private(const char *name, umode_t mode,
@@ -589,7 +587,7 @@ struct proc_dir_entry *proc_create_seq_private(const char *name, umode_t mode,
        p = proc_create_reg(name, mode, &parent, data);
        if (!p)
                return NULL;
-       p->proc_fops = &proc_seq_fops;
+       p->proc_ops = &proc_seq_ops;
        p->seq_ops = ops;
        p->state_size = state_size;
        return proc_register(parent, p);
@@ -603,11 +601,11 @@ static int proc_single_open(struct inode *inode, struct file *file)
        return single_open(file, de->single_show, de->data);
 }
 
-static const struct file_operations proc_single_fops = {
-       .open           = proc_single_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
+static const struct proc_ops proc_single_ops = {
+       .proc_open      = proc_single_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
 };
 
 struct proc_dir_entry *proc_create_single_data(const char *name, umode_t mode,
@@ -619,7 +617,7 @@ struct proc_dir_entry *proc_create_single_data(const char *name, umode_t mode,
        p = proc_create_reg(name, mode, &parent, data);
        if (!p)
                return NULL;
-       p->proc_fops = &proc_single_fops;
+       p->proc_ops = &proc_single_ops;
        p->single_show = show;
        return proc_register(parent, p);
 }
index dbe43a5..6da1831 100644 (file)
@@ -163,7 +163,7 @@ static void close_pdeo(struct proc_dir_entry *pde, struct pde_opener *pdeo)
                pdeo->closing = true;
                spin_unlock(&pde->pde_unload_lock);
                file = pdeo->file;
-               pde->proc_fops->release(file_inode(file), file);
+               pde->proc_ops->proc_release(file_inode(file), file);
                spin_lock(&pde->pde_unload_lock);
                /* After ->release. */
                list_del(&pdeo->lh);
@@ -200,12 +200,12 @@ static loff_t proc_reg_llseek(struct file *file, loff_t offset, int whence)
        struct proc_dir_entry *pde = PDE(file_inode(file));
        loff_t rv = -EINVAL;
        if (use_pde(pde)) {
-               typeof_member(struct file_operations, llseek) llseek;
+               typeof_member(struct proc_ops, proc_lseek) lseek;
 
-               llseek = pde->proc_fops->llseek;
-               if (!llseek)
-                       llseek = default_llseek;
-               rv = llseek(file, offset, whence);
+               lseek = pde->proc_ops->proc_lseek;
+               if (!lseek)
+                       lseek = default_llseek;
+               rv = lseek(file, offset, whence);
                unuse_pde(pde);
        }
        return rv;
@@ -216,9 +216,9 @@ static ssize_t proc_reg_read(struct file *file, char __user *buf, size_t count,
        struct proc_dir_entry *pde = PDE(file_inode(file));
        ssize_t rv = -EIO;
        if (use_pde(pde)) {
-               typeof_member(struct file_operations, read) read;
+               typeof_member(struct proc_ops, proc_read) read;
 
-               read = pde->proc_fops->read;
+               read = pde->proc_ops->proc_read;
                if (read)
                        rv = read(file, buf, count, ppos);
                unuse_pde(pde);
@@ -231,9 +231,9 @@ static ssize_t proc_reg_write(struct file *file, const char __user *buf, size_t
        struct proc_dir_entry *pde = PDE(file_inode(file));
        ssize_t rv = -EIO;
        if (use_pde(pde)) {
-               typeof_member(struct file_operations, write) write;
+               typeof_member(struct proc_ops, proc_write) write;
 
-               write = pde->proc_fops->write;
+               write = pde->proc_ops->proc_write;
                if (write)
                        rv = write(file, buf, count, ppos);
                unuse_pde(pde);
@@ -246,9 +246,9 @@ static __poll_t proc_reg_poll(struct file *file, struct poll_table_struct *pts)
        struct proc_dir_entry *pde = PDE(file_inode(file));
        __poll_t rv = DEFAULT_POLLMASK;
        if (use_pde(pde)) {
-               typeof_member(struct file_operations, poll) poll;
+               typeof_member(struct proc_ops, proc_poll) poll;
 
-               poll = pde->proc_fops->poll;
+               poll = pde->proc_ops->proc_poll;
                if (poll)
                        rv = poll(file, pts);
                unuse_pde(pde);
@@ -261,9 +261,9 @@ static long proc_reg_unlocked_ioctl(struct file *file, unsigned int cmd, unsigne
        struct proc_dir_entry *pde = PDE(file_inode(file));
        long rv = -ENOTTY;
        if (use_pde(pde)) {
-               typeof_member(struct file_operations, unlocked_ioctl) ioctl;
+               typeof_member(struct proc_ops, proc_ioctl) ioctl;
 
-               ioctl = pde->proc_fops->unlocked_ioctl;
+               ioctl = pde->proc_ops->proc_ioctl;
                if (ioctl)
                        rv = ioctl(file, cmd, arg);
                unuse_pde(pde);
@@ -277,9 +277,9 @@ static long proc_reg_compat_ioctl(struct file *file, unsigned int cmd, unsigned
        struct proc_dir_entry *pde = PDE(file_inode(file));
        long rv = -ENOTTY;
        if (use_pde(pde)) {
-               typeof_member(struct file_operations, compat_ioctl) compat_ioctl;
+               typeof_member(struct proc_ops, proc_compat_ioctl) compat_ioctl;
 
-               compat_ioctl = pde->proc_fops->compat_ioctl;
+               compat_ioctl = pde->proc_ops->proc_compat_ioctl;
                if (compat_ioctl)
                        rv = compat_ioctl(file, cmd, arg);
                unuse_pde(pde);
@@ -293,9 +293,9 @@ static int proc_reg_mmap(struct file *file, struct vm_area_struct *vma)
        struct proc_dir_entry *pde = PDE(file_inode(file));
        int rv = -EIO;
        if (use_pde(pde)) {
-               typeof_member(struct file_operations, mmap) mmap;
+               typeof_member(struct proc_ops, proc_mmap) mmap;
 
-               mmap = pde->proc_fops->mmap;
+               mmap = pde->proc_ops->proc_mmap;
                if (mmap)
                        rv = mmap(file, vma);
                unuse_pde(pde);
@@ -312,9 +312,9 @@ proc_reg_get_unmapped_area(struct file *file, unsigned long orig_addr,
        unsigned long rv = -EIO;
 
        if (use_pde(pde)) {
-               typeof_member(struct file_operations, get_unmapped_area) get_area;
+               typeof_member(struct proc_ops, proc_get_unmapped_area) get_area;
 
-               get_area = pde->proc_fops->get_unmapped_area;
+               get_area = pde->proc_ops->proc_get_unmapped_area;
 #ifdef CONFIG_MMU
                if (!get_area)
                        get_area = current->mm->get_unmapped_area;
@@ -333,8 +333,8 @@ static int proc_reg_open(struct inode *inode, struct file *file)
 {
        struct proc_dir_entry *pde = PDE(inode);
        int rv = 0;
-       typeof_member(struct file_operations, open) open;
-       typeof_member(struct file_operations, release) release;
+       typeof_member(struct proc_ops, proc_open) open;
+       typeof_member(struct proc_ops, proc_release) release;
        struct pde_opener *pdeo;
 
        /*
@@ -351,7 +351,7 @@ static int proc_reg_open(struct inode *inode, struct file *file)
        if (!use_pde(pde))
                return -ENOENT;
 
-       release = pde->proc_fops->release;
+       release = pde->proc_ops->proc_release;
        if (release) {
                pdeo = kmem_cache_alloc(pde_opener_cache, GFP_KERNEL);
                if (!pdeo) {
@@ -360,7 +360,7 @@ static int proc_reg_open(struct inode *inode, struct file *file)
                }
        }
 
-       open = pde->proc_fops->open;
+       open = pde->proc_ops->proc_open;
        if (open)
                rv = open(inode, file);
 
@@ -468,21 +468,23 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
                        inode->i_size = de->size;
                if (de->nlink)
                        set_nlink(inode, de->nlink);
-               WARN_ON(!de->proc_iops);
-               inode->i_op = de->proc_iops;
-               if (de->proc_fops) {
-                       if (S_ISREG(inode->i_mode)) {
+
+               if (S_ISREG(inode->i_mode)) {
+                       inode->i_op = de->proc_iops;
+                       inode->i_fop = &proc_reg_file_ops;
 #ifdef CONFIG_COMPAT
-                               if (!de->proc_fops->compat_ioctl)
-                                       inode->i_fop =
-                                               &proc_reg_file_ops_no_compat;
-                               else
-#endif
-                                       inode->i_fop = &proc_reg_file_ops;
-                       } else {
-                               inode->i_fop = de->proc_fops;
+                       if (!de->proc_ops->proc_compat_ioctl) {
+                               inode->i_fop = &proc_reg_file_ops_no_compat;
                        }
-               }
+#endif
+               } else if (S_ISDIR(inode->i_mode)) {
+                       inode->i_op = de->proc_iops;
+                       inode->i_fop = de->proc_dir_ops;
+               } else if (S_ISLNK(inode->i_mode)) {
+                       inode->i_op = de->proc_iops;
+                       inode->i_fop = NULL;
+               } else
+                       BUG();
        } else
               pde_put(de);
        return inode;
index 0f3b557..4158727 100644 (file)
@@ -39,7 +39,10 @@ struct proc_dir_entry {
        spinlock_t pde_unload_lock;
        struct completion *pde_unload_completion;
        const struct inode_operations *proc_iops;
-       const struct file_operations *proc_fops;
+       union {
+               const struct proc_ops *proc_ops;
+               const struct file_operations *proc_dir_ops;
+       };
        const struct dentry_operations *proc_dops;
        union {
                const struct seq_operations *seq_ops;
index e2ed8e0..8ba492d 100644 (file)
@@ -574,11 +574,11 @@ static int release_kcore(struct inode *inode, struct file *file)
        return 0;
 }
 
-static const struct file_operations proc_kcore_operations = {
-       .read           = read_kcore,
-       .open           = open_kcore,
-       .release        = release_kcore,
-       .llseek         = default_llseek,
+static const struct proc_ops kcore_proc_ops = {
+       .proc_read      = read_kcore,
+       .proc_open      = open_kcore,
+       .proc_release   = release_kcore,
+       .proc_lseek     = default_llseek,
 };
 
 /* just remember that we have to update kcore */
@@ -637,8 +637,7 @@ static void __init add_modules_range(void)
 
 static int __init proc_kcore_init(void)
 {
-       proc_root_kcore = proc_create("kcore", S_IRUSR, NULL,
-                                     &proc_kcore_operations);
+       proc_root_kcore = proc_create("kcore", S_IRUSR, NULL, &kcore_proc_ops);
        if (!proc_root_kcore) {
                pr_err("couldn't create /proc/kcore\n");
                return 0; /* Always returns 0. */
index 4f4a2ab..ec1b7d2 100644 (file)
@@ -49,17 +49,17 @@ static __poll_t kmsg_poll(struct file *file, poll_table *wait)
 }
 
 
-static const struct file_operations proc_kmsg_operations = {
-       .read           = kmsg_read,
-       .poll           = kmsg_poll,
-       .open           = kmsg_open,
-       .release        = kmsg_release,
-       .llseek         = generic_file_llseek,
+static const struct proc_ops kmsg_proc_ops = {
+       .proc_read      = kmsg_read,
+       .proc_poll      = kmsg_poll,
+       .proc_open      = kmsg_open,
+       .proc_release   = kmsg_release,
+       .proc_lseek     = generic_file_llseek,
 };
 
 static int __init proc_kmsg_init(void)
 {
-       proc_create("kmsg", S_IRUSR, NULL, &proc_kmsg_operations);
+       proc_create("kmsg", S_IRUSR, NULL, &kmsg_proc_ops);
        return 0;
 }
 fs_initcall(proc_kmsg_init);
index 7c952ee..f909243 100644 (file)
 #define KPMMASK (KPMSIZE - 1)
 #define KPMBITS (KPMSIZE * BITS_PER_BYTE)
 
+static inline unsigned long get_max_dump_pfn(void)
+{
+#ifdef CONFIG_SPARSEMEM
+       /*
+        * The memmap of early sections is completely populated and marked
+        * online even if max_pfn does not fall on a section boundary -
+        * pfn_to_online_page() will succeed on all pages. Allow inspecting
+        * these memmaps.
+        */
+       return round_up(max_pfn, PAGES_PER_SECTION);
+#else
+       return max_pfn;
+#endif
+}
+
 /* /proc/kpagecount - an array exposing page counts
  *
  * Each entry is a u64 representing the corresponding
@@ -29,6 +44,7 @@
 static ssize_t kpagecount_read(struct file *file, char __user *buf,
                             size_t count, loff_t *ppos)
 {
+       const unsigned long max_dump_pfn = get_max_dump_pfn();
        u64 __user *out = (u64 __user *)buf;
        struct page *ppage;
        unsigned long src = *ppos;
@@ -37,9 +53,11 @@ static ssize_t kpagecount_read(struct file *file, char __user *buf,
        u64 pcount;
 
        pfn = src / KPMSIZE;
-       count = min_t(size_t, count, (max_pfn * KPMSIZE) - src);
        if (src & KPMMASK || count & KPMMASK)
                return -EINVAL;
+       if (src >= max_dump_pfn * KPMSIZE)
+               return 0;
+       count = min_t(unsigned long, count, (max_dump_pfn * KPMSIZE) - src);
 
        while (count > 0) {
                /*
@@ -71,9 +89,9 @@ static ssize_t kpagecount_read(struct file *file, char __user *buf,
        return ret;
 }
 
-static const struct file_operations proc_kpagecount_operations = {
-       .llseek = mem_lseek,
-       .read = kpagecount_read,
+static const struct proc_ops kpagecount_proc_ops = {
+       .proc_lseek     = mem_lseek,
+       .proc_read      = kpagecount_read,
 };
 
 /* /proc/kpageflags - an array exposing page flags
@@ -206,6 +224,7 @@ u64 stable_page_flags(struct page *page)
 static ssize_t kpageflags_read(struct file *file, char __user *buf,
                             size_t count, loff_t *ppos)
 {
+       const unsigned long max_dump_pfn = get_max_dump_pfn();
        u64 __user *out = (u64 __user *)buf;
        struct page *ppage;
        unsigned long src = *ppos;
@@ -213,9 +232,11 @@ static ssize_t kpageflags_read(struct file *file, char __user *buf,
        ssize_t ret = 0;
 
        pfn = src / KPMSIZE;
-       count = min_t(unsigned long, count, (max_pfn * KPMSIZE) - src);
        if (src & KPMMASK || count & KPMMASK)
                return -EINVAL;
+       if (src >= max_dump_pfn * KPMSIZE)
+               return 0;
+       count = min_t(unsigned long, count, (max_dump_pfn * KPMSIZE) - src);
 
        while (count > 0) {
                /*
@@ -242,15 +263,16 @@ static ssize_t kpageflags_read(struct file *file, char __user *buf,
        return ret;
 }
 
-static const struct file_operations proc_kpageflags_operations = {
-       .llseek = mem_lseek,
-       .read = kpageflags_read,
+static const struct proc_ops kpageflags_proc_ops = {
+       .proc_lseek     = mem_lseek,
+       .proc_read      = kpageflags_read,
 };
 
 #ifdef CONFIG_MEMCG
 static ssize_t kpagecgroup_read(struct file *file, char __user *buf,
                                size_t count, loff_t *ppos)
 {
+       const unsigned long max_dump_pfn = get_max_dump_pfn();
        u64 __user *out = (u64 __user *)buf;
        struct page *ppage;
        unsigned long src = *ppos;
@@ -259,9 +281,11 @@ static ssize_t kpagecgroup_read(struct file *file, char __user *buf,
        u64 ino;
 
        pfn = src / KPMSIZE;
-       count = min_t(unsigned long, count, (max_pfn * KPMSIZE) - src);
        if (src & KPMMASK || count & KPMMASK)
                return -EINVAL;
+       if (src >= max_dump_pfn * KPMSIZE)
+               return 0;
+       count = min_t(unsigned long, count, (max_dump_pfn * KPMSIZE) - src);
 
        while (count > 0) {
                /*
@@ -293,18 +317,18 @@ static ssize_t kpagecgroup_read(struct file *file, char __user *buf,
        return ret;
 }
 
-static const struct file_operations proc_kpagecgroup_operations = {
-       .llseek = mem_lseek,
-       .read = kpagecgroup_read,
+static const struct proc_ops kpagecgroup_proc_ops = {
+       .proc_lseek     = mem_lseek,
+       .proc_read      = kpagecgroup_read,
 };
 #endif /* CONFIG_MEMCG */
 
 static int __init proc_page_init(void)
 {
-       proc_create("kpagecount", S_IRUSR, NULL, &proc_kpagecount_operations);
-       proc_create("kpageflags", S_IRUSR, NULL, &proc_kpageflags_operations);
+       proc_create("kpagecount", S_IRUSR, NULL, &kpagecount_proc_ops);
+       proc_create("kpageflags", S_IRUSR, NULL, &kpageflags_proc_ops);
 #ifdef CONFIG_MEMCG
-       proc_create("kpagecgroup", S_IRUSR, NULL, &proc_kpagecgroup_operations);
+       proc_create("kpagecgroup", S_IRUSR, NULL, &kpagecgroup_proc_ops);
 #endif
        return 0;
 }
index 76ae278..4888c52 100644 (file)
@@ -90,12 +90,12 @@ static int seq_release_net(struct inode *ino, struct file *f)
        return 0;
 }
 
-static const struct file_operations proc_net_seq_fops = {
-       .open           = seq_open_net,
-       .read           = seq_read,
-       .write          = proc_simple_write,
-       .llseek         = seq_lseek,
-       .release        = seq_release_net,
+static const struct proc_ops proc_net_seq_ops = {
+       .proc_open      = seq_open_net,
+       .proc_read      = seq_read,
+       .proc_write     = proc_simple_write,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = seq_release_net,
 };
 
 struct proc_dir_entry *proc_create_net_data(const char *name, umode_t mode,
@@ -108,7 +108,7 @@ struct proc_dir_entry *proc_create_net_data(const char *name, umode_t mode,
        if (!p)
                return NULL;
        pde_force_lookup(p);
-       p->proc_fops = &proc_net_seq_fops;
+       p->proc_ops = &proc_net_seq_ops;
        p->seq_ops = ops;
        p->state_size = state_size;
        return proc_register(parent, p);
@@ -152,7 +152,7 @@ struct proc_dir_entry *proc_create_net_data_write(const char *name, umode_t mode
        if (!p)
                return NULL;
        pde_force_lookup(p);
-       p->proc_fops = &proc_net_seq_fops;
+       p->proc_ops = &proc_net_seq_ops;
        p->seq_ops = ops;
        p->state_size = state_size;
        p->write = write;
@@ -183,12 +183,12 @@ static int single_release_net(struct inode *ino, struct file *f)
        return single_release(ino, f);
 }
 
-static const struct file_operations proc_net_single_fops = {
-       .open           = single_open_net,
-       .read           = seq_read,
-       .write          = proc_simple_write,
-       .llseek         = seq_lseek,
-       .release        = single_release_net,
+static const struct proc_ops proc_net_single_ops = {
+       .proc_open      = single_open_net,
+       .proc_read      = seq_read,
+       .proc_write     = proc_simple_write,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release_net,
 };
 
 struct proc_dir_entry *proc_create_net_single(const char *name, umode_t mode,
@@ -201,7 +201,7 @@ struct proc_dir_entry *proc_create_net_single(const char *name, umode_t mode,
        if (!p)
                return NULL;
        pde_force_lookup(p);
-       p->proc_fops = &proc_net_single_fops;
+       p->proc_ops = &proc_net_single_ops;
        p->single_show = show;
        return proc_register(parent, p);
 }
@@ -244,7 +244,7 @@ struct proc_dir_entry *proc_create_net_single_write(const char *name, umode_t mo
        if (!p)
                return NULL;
        pde_force_lookup(p);
-       p->proc_fops = &proc_net_single_fops;
+       p->proc_ops = &proc_net_single_ops;
        p->single_show = show;
        p->write = write;
        return proc_register(parent, p);
index d80989b..c75bb46 100644 (file)
@@ -1720,7 +1720,7 @@ int __init proc_sys_init(void)
 
        proc_sys_root = proc_mkdir("sys", NULL);
        proc_sys_root->proc_iops = &proc_sys_dir_operations;
-       proc_sys_root->proc_fops = &proc_sys_dir_file_operations;
+       proc_sys_root->proc_dir_ops = &proc_sys_dir_file_operations;
        proc_sys_root->nlink = 0;
 
        return sysctl_init();
index 0b7c8df..72c07a3 100644 (file)
@@ -292,7 +292,7 @@ struct proc_dir_entry proc_root = {
        .nlink          = 2, 
        .refcnt         = REFCOUNT_INIT(1),
        .proc_iops      = &proc_root_inode_operations, 
-       .proc_fops      = &proc_root_operations,
+       .proc_dir_ops   = &proc_root_operations,
        .parent         = &proc_root,
        .subdir         = RB_ROOT,
        .name           = "/proc",
index fd931d3..0449edf 100644 (file)
@@ -223,16 +223,16 @@ static int stat_open(struct inode *inode, struct file *file)
        return single_open_size(file, show_stat, NULL, size);
 }
 
-static const struct file_operations proc_stat_operations = {
-       .open           = stat_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
+static const struct proc_ops stat_proc_ops = {
+       .proc_open      = stat_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
 };
 
 static int __init proc_stat_init(void)
 {
-       proc_create("stat", 0, NULL, &proc_stat_operations);
+       proc_create("stat", 0, NULL, &stat_proc_ops);
        return 0;
 }
 fs_initcall(proc_stat_init);
index 9442631..3ba9ae8 100644 (file)
@@ -505,7 +505,7 @@ static void smaps_account(struct mem_size_stats *mss, struct page *page,
 
 #ifdef CONFIG_SHMEM
 static int smaps_pte_hole(unsigned long addr, unsigned long end,
-               struct mm_walk *walk)
+                         __always_unused int depth, struct mm_walk *walk)
 {
        struct mem_size_stats *mss = walk->private;
 
@@ -1282,7 +1282,7 @@ static int add_to_pagemap(unsigned long addr, pagemap_entry_t *pme,
 }
 
 static int pagemap_pte_hole(unsigned long start, unsigned long end,
-                               struct mm_walk *walk)
+                           __always_unused int depth, struct mm_walk *walk)
 {
        struct pagemapread *pm = walk->private;
        unsigned long addr = start;
index 7b13988..7dc800c 100644 (file)
@@ -667,10 +667,10 @@ static int mmap_vmcore(struct file *file, struct vm_area_struct *vma)
 }
 #endif
 
-static const struct file_operations proc_vmcore_operations = {
-       .read           = read_vmcore,
-       .llseek         = default_llseek,
-       .mmap           = mmap_vmcore,
+static const struct proc_ops vmcore_proc_ops = {
+       .proc_read      = read_vmcore,
+       .proc_lseek     = default_llseek,
+       .proc_mmap      = mmap_vmcore,
 };
 
 static struct vmcore* __init get_new_element(void)
@@ -1555,7 +1555,7 @@ static int __init vmcore_init(void)
        elfcorehdr_free(elfcorehdr_addr);
        elfcorehdr_addr = ELFCORE_ADDR_ERR;
 
-       proc_vmcore = proc_create("vmcore", S_IRUSR, NULL, &proc_vmcore_operations);
+       proc_vmcore = proc_create("vmcore", S_IRUSR, NULL, &vmcore_proc_ops);
        if (proc_vmcore)
                proc_vmcore->size = vmcore_size;
        return 0;
index d41c21f..c4ab045 100644 (file)
@@ -449,7 +449,7 @@ int __compat_only_sysfs_link_entry_to_kobj(struct kobject *kobj,
        }
 
        link = kernfs_create_link(kobj->sd, target_name, entry);
-       if (IS_ERR(link) && PTR_ERR(link) == -EEXIST)
+       if (PTR_ERR(link) == -EEXIST)
                sysfs_warn_dup(kobj->sd, target_name);
 
        kernfs_put(entry);
index 798ea36..e2e2bef 100644 (file)
@@ -1238,4 +1238,24 @@ static inline bool arch_has_pfn_modify_check(void)
 #define mm_pmd_folded(mm)      __is_defined(__PAGETABLE_PMD_FOLDED)
 #endif
 
+/*
+ * p?d_leaf() - true if this entry is a final mapping to a physical address.
+ * This differs from p?d_huge() by the fact that they are always available (if
+ * the architecture supports large pages at the appropriate level) even
+ * if CONFIG_HUGETLB_PAGE is not defined.
+ * Only meaningful when called on a valid entry.
+ */
+#ifndef pgd_leaf
+#define pgd_leaf(x)    0
+#endif
+#ifndef p4d_leaf
+#define p4d_leaf(x)    0
+#endif
+#ifndef pud_leaf
+#define pud_leaf(x)    0
+#endif
+#ifndef pmd_leaf
+#define pmd_leaf(x)    0
+#endif
+
 #endif /* _ASM_GENERIC_PGTABLE_H */
index 2b10036..f391f6b 100644 (file)
  *    Defaults to flushing at tlb_end_vma() to reset the range; helps when
  *    there's large holes between the VMAs.
  *
+ *  - tlb_remove_table()
+ *
+ *    tlb_remove_table() is the basic primitive to free page-table directories
+ *    (__p*_free_tlb()).  In it's most primitive form it is an alias for
+ *    tlb_remove_page() below, for when page directories are pages and have no
+ *    additional constraints.
+ *
+ *    See also MMU_GATHER_TABLE_FREE and MMU_GATHER_RCU_TABLE_FREE.
+ *
  *  - tlb_remove_page() / __tlb_remove_page()
  *  - tlb_remove_page_size() / __tlb_remove_page_size()
  *
  *
  * Additionally there are a few opt-in features:
  *
- *  HAVE_MMU_GATHER_PAGE_SIZE
+ *  MMU_GATHER_PAGE_SIZE
  *
  *  This ensures we call tlb_flush() every time tlb_change_page_size() actually
  *  changes the size and provides mmu_gather::page_size to tlb_flush().
  *
- *  HAVE_RCU_TABLE_FREE
+ *  This might be useful if your architecture has size specific TLB
+ *  invalidation instructions.
+ *
+ *  MMU_GATHER_TABLE_FREE
  *
  *  This provides tlb_remove_table(), to be used instead of tlb_remove_page()
- *  for page directores (__p*_free_tlb()). This provides separate freeing of
- *  the page-table pages themselves in a semi-RCU fashion (see comment below).
- *  Useful if your architecture doesn't use IPIs for remote TLB invalidates
- *  and therefore doesn't naturally serialize with software page-table walkers.
+ *  for page directores (__p*_free_tlb()).
+ *
+ *  Useful if your architecture has non-page page directories.
  *
  *  When used, an architecture is expected to provide __tlb_remove_table()
  *  which does the actual freeing of these pages.
  *
- *  HAVE_RCU_TABLE_NO_INVALIDATE
+ *  MMU_GATHER_RCU_TABLE_FREE
  *
- *  This makes HAVE_RCU_TABLE_FREE avoid calling tlb_flush_mmu_tlbonly() before
- *  freeing the page-table pages. This can be avoided if you use
- *  HAVE_RCU_TABLE_FREE and your architecture does _NOT_ use the Linux
- *  page-tables natively.
+ *  Like MMU_GATHER_TABLE_FREE, and adds semi-RCU semantics to the free (see
+ *  comment below).
+ *
+ *  Useful if your architecture doesn't use IPIs for remote TLB invalidates
+ *  and therefore doesn't naturally serialize with software page-table walkers.
  *
  *  MMU_GATHER_NO_RANGE
  *
  *  Use this if your architecture lacks an efficient flush_tlb_range().
- */
-
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
-/*
- * Semi RCU freeing of the page directories.
- *
- * This is needed by some architectures to implement software pagetable walkers.
  *
- * gup_fast() and other software pagetable walkers do a lockless page-table
- * walk and therefore needs some synchronization with the freeing of the page
- * directories. The chosen means to accomplish that is by disabling IRQs over
- * the walk.
+ *  MMU_GATHER_NO_GATHER
  *
- * Architectures that use IPIs to flush TLBs will then automagically DTRT,
- * since we unlink the page, flush TLBs, free the page. Since the disabling of
- * IRQs delays the completion of the TLB flush we can never observe an already
- * freed page.
- *
- * Architectures that do not have this (PPC) need to delay the freeing by some
- * other means, this is that means.
- *
- * What we do is batch the freed directory pages (tables) and RCU free them.
- * We use the sched RCU variant, as that guarantees that IRQ/preempt disabling
- * holds off grace periods.
- *
- * However, in order to batch these pages we need to allocate storage, this
- * allocation is deep inside the MM code and can thus easily fail on memory
- * pressure. To guarantee progress we fall back to single table freeing, see
- * the implementation of tlb_remove_table_one().
+ *  If the option is set the mmu_gather will not track individual pages for
+ *  delayed page free anymore. A platform that enables the option needs to
+ *  provide its own implementation of the __tlb_remove_page_size() function to
+ *  free pages.
  *
+ *  This is useful if your architecture already flushes TLB entries in the
+ *  various ptep_get_and_clear() functions.
  */
+
+#ifdef CONFIG_MMU_GATHER_TABLE_FREE
+
 struct mmu_table_batch {
+#ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE
        struct rcu_head         rcu;
+#endif
        unsigned int            nr;
        void                    *tables[0];
 };
@@ -189,9 +186,35 @@ struct mmu_table_batch {
 
 extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
 
+#else /* !CONFIG_MMU_GATHER_HAVE_TABLE_FREE */
+
+/*
+ * Without MMU_GATHER_TABLE_FREE the architecture is assumed to have page based
+ * page directories and we can use the normal page batching to free them.
+ */
+#define tlb_remove_table(tlb, page) tlb_remove_page((tlb), (page))
+
+#endif /* CONFIG_MMU_GATHER_TABLE_FREE */
+
+#ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE
+/*
+ * This allows an architecture that does not use the linux page-tables for
+ * hardware to skip the TLBI when freeing page tables.
+ */
+#ifndef tlb_needs_table_invalidate
+#define tlb_needs_table_invalidate() (true)
 #endif
 
-#ifndef CONFIG_HAVE_MMU_GATHER_NO_GATHER
+#else
+
+#ifdef tlb_needs_table_invalidate
+#error tlb_needs_table_invalidate() requires MMU_GATHER_RCU_TABLE_FREE
+#endif
+
+#endif /* CONFIG_MMU_GATHER_RCU_TABLE_FREE */
+
+
+#ifndef CONFIG_MMU_GATHER_NO_GATHER
 /*
  * If we can't allocate a page to make a big batch of page pointers
  * to work on, then just handle a few from the on-stack structure.
@@ -227,7 +250,7 @@ extern bool __tlb_remove_page_size(struct mmu_gather *tlb, struct page *page,
 struct mmu_gather {
        struct mm_struct        *mm;
 
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
+#ifdef CONFIG_MMU_GATHER_TABLE_FREE
        struct mmu_table_batch  *batch;
 #endif
 
@@ -266,22 +289,18 @@ struct mmu_gather {
 
        unsigned int            batch_count;
 
-#ifndef CONFIG_HAVE_MMU_GATHER_NO_GATHER
+#ifndef CONFIG_MMU_GATHER_NO_GATHER
        struct mmu_gather_batch *active;
        struct mmu_gather_batch local;
        struct page             *__pages[MMU_GATHER_BUNDLE];
 
-#ifdef CONFIG_HAVE_MMU_GATHER_PAGE_SIZE
+#ifdef CONFIG_MMU_GATHER_PAGE_SIZE
        unsigned int page_size;
 #endif
 #endif
 };
 
-void arch_tlb_gather_mmu(struct mmu_gather *tlb,
-       struct mm_struct *mm, unsigned long start, unsigned long end);
 void tlb_flush_mmu(struct mmu_gather *tlb);
-void arch_tlb_finish_mmu(struct mmu_gather *tlb,
-                        unsigned long start, unsigned long end, bool force);
 
 static inline void __tlb_adjust_range(struct mmu_gather *tlb,
                                      unsigned long address,
@@ -394,7 +413,12 @@ tlb_update_vma_flags(struct mmu_gather *tlb, struct vm_area_struct *vma) { }
 
 static inline void tlb_flush_mmu_tlbonly(struct mmu_gather *tlb)
 {
-       if (!tlb->end)
+       /*
+        * Anything calling __tlb_adjust_range() also sets at least one of
+        * these bits.
+        */
+       if (!(tlb->freed_tables || tlb->cleared_ptes || tlb->cleared_pmds ||
+             tlb->cleared_puds || tlb->cleared_p4ds))
                return;
 
        tlb_flush(tlb);
@@ -426,7 +450,7 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
 static inline void tlb_change_page_size(struct mmu_gather *tlb,
                                                     unsigned int page_size)
 {
-#ifdef CONFIG_HAVE_MMU_GATHER_PAGE_SIZE
+#ifdef CONFIG_MMU_GATHER_PAGE_SIZE
        if (tlb->page_size && tlb->page_size != page_size) {
                if (!tlb->fullmm && !tlb->need_flush_all)
                        tlb_flush_mmu(tlb);
index 80ad521..e52ceb1 100644 (file)
@@ -186,7 +186,7 @@ bitmap_find_next_zero_area(unsigned long *map,
                                              align_mask, 0);
 }
 
-extern int __bitmap_parse(const char *buf, unsigned int buflen, int is_user,
+extern int bitmap_parse(const char *buf, unsigned int buflen,
                        unsigned long *dst, int nbits);
 extern int bitmap_parse_user(const char __user *ubuf, unsigned int ulen,
                        unsigned long *dst, int nbits);
@@ -454,12 +454,6 @@ static inline void bitmap_replace(unsigned long *dst,
                __bitmap_replace(dst, old, new, mask, nbits);
 }
 
-static inline int bitmap_parse(const char *buf, unsigned int buflen,
-                       unsigned long *maskp, int nmaskbits)
-{
-       return __bitmap_parse(buf, buflen, 0, maskp, nmaskbits);
-}
-
 static inline void bitmap_next_clear_region(unsigned long *bitmap,
                                            unsigned int *rs, unsigned int *re,
                                            unsigned int end)
index 6c7c413..47f54b4 100644 (file)
 #  define aligned_byte_mask(n) (~0xffUL << (BITS_PER_LONG - 8 - 8*(n)))
 #endif
 
-#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
+#define BITS_PER_TYPE(type)    (sizeof(type) * BITS_PER_BYTE)
 #define BITS_TO_LONGS(nr)      DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
+#define BITS_TO_U64(nr)                DIV_ROUND_UP(nr, BITS_PER_TYPE(u64))
+#define BITS_TO_U32(nr)                DIV_ROUND_UP(nr, BITS_PER_TYPE(u32))
 #define BITS_TO_BYTES(nr)      DIV_ROUND_UP(nr, BITS_PER_TYPE(char))
 
 extern unsigned int __sw_hweight8(unsigned int w);
index 78a73eb..d5cc885 100644 (file)
@@ -663,9 +663,7 @@ static inline int cpumask_parselist_user(const char __user *buf, int len,
  */
 static inline int cpumask_parse(const char *buf, struct cpumask *dstp)
 {
-       unsigned int len = strchrnul(buf, '\n') - buf;
-
-       return bitmap_parse(buf, len, cpumask_bits(dstp), nr_cpumask_bits);
+       return bitmap_parse(buf, UINT_MAX, cpumask_bits(dstp), nr_cpumask_bits);
 }
 
 /**
index ffa6ad1..f4d5915 100644 (file)
@@ -96,8 +96,8 @@ extern int add_one_highpage(struct page *page, int pfn, int bad_ppro);
 /* VM interface that may be used by firmware interface */
 extern int online_pages(unsigned long pfn, unsigned long nr_pages,
                        int online_type, int nid);
-extern int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
-       unsigned long *valid_start, unsigned long *valid_end);
+extern struct zone *test_pages_in_a_zone(unsigned long start_pfn,
+                                        unsigned long end_pfn);
 extern unsigned long __offline_isolated_pages(unsigned long start_pfn,
                                                unsigned long end_pfn);
 
index faa3bb5..52269e5 100644 (file)
@@ -2182,12 +2182,6 @@ extern int __meminit __early_pfn_to_nid(unsigned long pfn,
                                        struct mminit_pfnnid_cache *state);
 #endif
 
-#if !defined(CONFIG_FLAT_NODE_MEM_MAP)
-void zero_resv_unavail(void);
-#else
-static inline void zero_resv_unavail(void) {}
-#endif
-
 extern void set_dma_reserve(unsigned long new_dma_reserve);
 extern void memmap_init_zone(unsigned long, int, unsigned long, unsigned long,
                enum memmap_context, struct vmem_altmap *);
index c2bc309..462f687 100644 (file)
@@ -1379,6 +1379,16 @@ static inline int pfn_present(unsigned long pfn)
        return present_section(__nr_to_section(pfn_to_section_nr(pfn)));
 }
 
+static inline unsigned long next_present_section_nr(unsigned long section_nr)
+{
+       while (++section_nr <= __highest_present_section_nr) {
+               if (present_section_nr(section_nr))
+                       return section_nr;
+       }
+
+       return -1;
+}
+
 /*
  * These are _only_ used during initialisation, therefore they
  * can use __initdata ...  They could have names to indicate
index 6ec82e9..b1cb6b7 100644 (file)
@@ -8,16 +8,19 @@ struct mm_walk;
 
 /**
  * mm_walk_ops - callbacks for walk_page_range
- * @pud_entry:         if set, called for each non-empty PUD (2nd-level) entry
- *                     this handler should only handle pud_trans_huge() puds.
- *                     the pmd_entry or pte_entry callbacks will be used for
- *                     regular PUDs.
- * @pmd_entry:         if set, called for each non-empty PMD (3rd-level) entry
+ * @pgd_entry:         if set, called for each non-empty PGD (top-level) entry
+ * @p4d_entry:         if set, called for each non-empty P4D entry
+ * @pud_entry:         if set, called for each non-empty PUD entry
+ * @pmd_entry:         if set, called for each non-empty PMD entry
  *                     this handler is required to be able to handle
  *                     pmd_trans_huge() pmds.  They may simply choose to
  *                     split_huge_page() instead of handling it explicitly.
- * @pte_entry:         if set, called for each non-empty PTE (4th-level) entry
- * @pte_hole:          if set, called for each hole at all levels
+ * @pte_entry:         if set, called for each non-empty PTE (lowest-level)
+ *                     entry
+ * @pte_hole:          if set, called for each hole at all levels,
+ *                     depth is -1 if not known, 0:PGD, 1:P4D, 2:PUD, 3:PMD
+ *                     4:PTE. Any folded depths (where PTRS_PER_P?D is equal
+ *                     to 1) are skipped.
  * @hugetlb_entry:     if set, called for each hugetlb entry
  * @test_walk:         caller specific callback function to determine whether
  *                     we walk over the current vma or not. Returning 0 means
@@ -27,8 +30,15 @@ struct mm_walk;
  * @pre_vma:            if set, called before starting walk on a non-null vma.
  * @post_vma:           if set, called after a walk on a non-null vma, provided
  *                      that @pre_vma and the vma walk succeeded.
+ *
+ * p?d_entry callbacks are called even if those levels are folded on a
+ * particular architecture/configuration.
  */
 struct mm_walk_ops {
+       int (*pgd_entry)(pgd_t *pgd, unsigned long addr,
+                        unsigned long next, struct mm_walk *walk);
+       int (*p4d_entry)(p4d_t *p4d, unsigned long addr,
+                        unsigned long next, struct mm_walk *walk);
        int (*pud_entry)(pud_t *pud, unsigned long addr,
                         unsigned long next, struct mm_walk *walk);
        int (*pmd_entry)(pmd_t *pmd, unsigned long addr,
@@ -36,7 +46,7 @@ struct mm_walk_ops {
        int (*pte_entry)(pte_t *pte, unsigned long addr,
                         unsigned long next, struct mm_walk *walk);
        int (*pte_hole)(unsigned long addr, unsigned long next,
-                       struct mm_walk *walk);
+                       int depth, struct mm_walk *walk);
        int (*hugetlb_entry)(pte_t *pte, unsigned long hmask,
                             unsigned long addr, unsigned long next,
                             struct mm_walk *walk);
@@ -47,11 +57,27 @@ struct mm_walk_ops {
        void (*post_vma)(struct mm_walk *walk);
 };
 
+/*
+ * Action for pud_entry / pmd_entry callbacks.
+ * ACTION_SUBTREE is the default
+ */
+enum page_walk_action {
+       /* Descend to next level, splitting huge pages if needed and possible */
+       ACTION_SUBTREE = 0,
+       /* Continue to next entry at this level (ignoring any subtree) */
+       ACTION_CONTINUE = 1,
+       /* Call again for this entry */
+       ACTION_AGAIN = 2
+};
+
 /**
  * mm_walk - walk_page_range data
  * @ops:       operation to call during the walk
  * @mm:                mm_struct representing the target process of page table walk
+ * @pgd:       pointer to PGD; only valid with no_vma (otherwise set to NULL)
  * @vma:       vma currently walked (NULL if walking outside vmas)
+ * @action:    next action to perform (see enum page_walk_action)
+ * @no_vma:    walk ignoring vmas (vma will always be NULL)
  * @private:   private data for callbacks' usage
  *
  * (see the comment on walk_page_range() for more details)
@@ -59,13 +85,20 @@ struct mm_walk_ops {
 struct mm_walk {
        const struct mm_walk_ops *ops;
        struct mm_struct *mm;
+       pgd_t *pgd;
        struct vm_area_struct *vma;
+       enum page_walk_action action;
+       bool no_vma;
        void *private;
 };
 
 int walk_page_range(struct mm_struct *mm, unsigned long start,
                unsigned long end, const struct mm_walk_ops *ops,
                void *private);
+int walk_page_range_novma(struct mm_struct *mm, unsigned long start,
+                         unsigned long end, const struct mm_walk_ops *ops,
+                         pgd_t *pgd,
+                         void *private);
 int walk_page_vma(struct vm_area_struct *vma, const struct mm_walk_ops *ops,
                void *private);
 int walk_page_mapping(struct address_space *mapping, pgoff_t first_index,
index 0640be5..3dfa926 100644 (file)
@@ -12,6 +12,21 @@ struct proc_dir_entry;
 struct seq_file;
 struct seq_operations;
 
+struct proc_ops {
+       int     (*proc_open)(struct inode *, struct file *);
+       ssize_t (*proc_read)(struct file *, char __user *, size_t, loff_t *);
+       ssize_t (*proc_write)(struct file *, const char __user *, size_t, loff_t *);
+       loff_t  (*proc_lseek)(struct file *, loff_t, int);
+       int     (*proc_release)(struct inode *, struct file *);
+       __poll_t (*proc_poll)(struct file *, struct poll_table_struct *);
+       long    (*proc_ioctl)(struct file *, unsigned int, unsigned long);
+#ifdef CONFIG_COMPAT
+       long    (*proc_compat_ioctl)(struct file *, unsigned int, unsigned long);
+#endif
+       int     (*proc_mmap)(struct file *, struct vm_area_struct *);
+       unsigned long (*proc_get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
+};
+
 #ifdef CONFIG_PROC_FS
 
 typedef int (*proc_write_t)(struct file *, char *, size_t);
@@ -43,10 +58,10 @@ struct proc_dir_entry *proc_create_single_data(const char *name, umode_t mode,
  
 extern struct proc_dir_entry *proc_create_data(const char *, umode_t,
                                               struct proc_dir_entry *,
-                                              const struct file_operations *,
+                                              const struct proc_ops *,
                                               void *);
 
-struct proc_dir_entry *proc_create(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct file_operations *proc_fops);
+struct proc_dir_entry *proc_create(const char *name, umode_t mode, struct proc_dir_entry *parent, const struct proc_ops *proc_ops);
 extern void proc_set_size(struct proc_dir_entry *, loff_t);
 extern void proc_set_user(struct proc_dir_entry *, kuid_t, kgid_t);
 extern void *PDE_DATA(const struct inode *);
@@ -108,8 +123,8 @@ static inline struct proc_dir_entry *proc_mkdir_mode(const char *name,
 #define proc_create_seq(name, mode, parent, ops) ({NULL;})
 #define proc_create_single(name, mode, parent, show) ({NULL;})
 #define proc_create_single_data(name, mode, parent, show, data) ({NULL;})
-#define proc_create(name, mode, parent, proc_fops) ({NULL;})
-#define proc_create_data(name, mode, parent, proc_fops, data) ({NULL;})
+#define proc_create(name, mode, parent, proc_ops) ({NULL;})
+#define proc_create_data(name, mode, parent, proc_ops, data) ({NULL;})
 
 static inline void proc_set_size(struct proc_dir_entry *de, loff_t size) {}
 static inline void proc_set_user(struct proc_dir_entry *de, kuid_t uid, kgid_t gid) {}
diff --git a/include/linux/ptdump.h b/include/linux/ptdump.h
new file mode 100644 (file)
index 0000000..a67065c
--- /dev/null
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _LINUX_PTDUMP_H
+#define _LINUX_PTDUMP_H
+
+#include <linux/mm_types.h>
+
+struct ptdump_range {
+       unsigned long start;
+       unsigned long end;
+};
+
+struct ptdump_state {
+       /* level is 0:PGD to 4:PTE, or -1 if unknown */
+       void (*note_page)(struct ptdump_state *st, unsigned long addr,
+                         int level, unsigned long val);
+       const struct ptdump_range *range;
+};
+
+void ptdump_walk_pgd(struct ptdump_state *st, struct mm_struct *mm, pgd_t *pgd);
+
+#endif /* _LINUX_PTDUMP_H */
index 5998e1f..770c2bf 100644 (file)
@@ -160,6 +160,19 @@ static const struct file_operations __name ## _fops = {                    \
        .release        = single_release,                               \
 }
 
+#define DEFINE_PROC_SHOW_ATTRIBUTE(__name)                             \
+static int __name ## _open(struct inode *inode, struct file *file)     \
+{                                                                      \
+       return single_open(file, __name ## _show, inode->i_private);    \
+}                                                                      \
+                                                                       \
+static const struct proc_ops __name ## _proc_ops = {                   \
+       .proc_open      = __name ## _open,                              \
+       .proc_read      = seq_read,                                     \
+       .proc_lseek     = seq_lseek,                                    \
+       .proc_release   = single_release,                               \
+}
+
 static inline struct user_namespace *seq_user_ns(struct seq_file *seq)
 {
 #ifdef CONFIG_USER_NS
index 877a95c..03a3893 100644 (file)
@@ -184,7 +184,6 @@ void memcg_deactivate_kmem_caches(struct mem_cgroup *, struct mem_cgroup *);
 /*
  * Common kmalloc functions provided by all allocators
  */
-void * __must_check __krealloc(const void *, size_t, gfp_t);
 void * __must_check krealloc(const void *, size_t, gfp_t);
 void kfree(const void *);
 void kzfree(const void *);
index 02894e4..6dfbb2e 100644 (file)
@@ -62,6 +62,7 @@ extern char * strchr(const char *,int);
 #ifndef __HAVE_ARCH_STRCHRNUL
 extern char * strchrnul(const char *,int);
 #endif
+extern char * strnchrnul(const char *, size_t, int);
 #ifndef __HAVE_ARCH_STRNCHR
 extern char * strnchr(const char *, size_t, int);
 #endif
index 84b92b4..d94d4f4 100644 (file)
@@ -63,7 +63,7 @@ struct proc_dir_entry *       rpc_proc_register(struct net *,struct rpc_stat *);
 void                   rpc_proc_unregister(struct net *,const char *);
 void                   rpc_proc_zero(const struct rpc_program *);
 struct proc_dir_entry *        svc_proc_register(struct net *, struct svc_stat *,
-                                         const struct file_operations *);
+                                         const struct proc_ops *);
 void                   svc_proc_unregister(struct net *, const char *);
 
 void                   svc_seq_show(struct seq_file *,
@@ -75,7 +75,7 @@ static inline void rpc_proc_unregister(struct net *net, const char *p) {}
 static inline void rpc_proc_zero(const struct rpc_program *p) {}
 
 static inline struct proc_dir_entry *svc_proc_register(struct net *net, struct svc_stat *s,
-                                                      const struct file_operations *f) { return NULL; }
+                                                      const struct proc_ops *proc_ops) { return NULL; }
 static inline void svc_proc_unregister(struct net *net, const char *p) {}
 
 static inline void svc_seq_show(struct seq_file *seq,
index 3d920ff..49a05ba 100644 (file)
@@ -63,6 +63,66 @@ struct posix_msg_tree_node {
        int                     priority;
 };
 
+/*
+ * Locking:
+ *
+ * Accesses to a message queue are synchronized by acquiring info->lock.
+ *
+ * There are two notable exceptions:
+ * - The actual wakeup of a sleeping task is performed using the wake_q
+ *   framework. info->lock is already released when wake_up_q is called.
+ * - The exit codepaths after sleeping check ext_wait_queue->state without
+ *   any locks. If it is STATE_READY, then the syscall is completed without
+ *   acquiring info->lock.
+ *
+ * MQ_BARRIER:
+ * To achieve proper release/acquire memory barrier pairing, the state is set to
+ * STATE_READY with smp_store_release(), and it is read with READ_ONCE followed
+ * by smp_acquire__after_ctrl_dep(). In addition, wake_q_add_safe() is used.
+ *
+ * This prevents the following races:
+ *
+ * 1) With the simple wake_q_add(), the task could be gone already before
+ *    the increase of the reference happens
+ * Thread A
+ *                             Thread B
+ * WRITE_ONCE(wait.state, STATE_NONE);
+ * schedule_hrtimeout()
+ *                             wake_q_add(A)
+ *                             if (cmpxchg()) // success
+ *                                ->state = STATE_READY (reordered)
+ * <timeout returns>
+ * if (wait.state == STATE_READY) return;
+ * sysret to user space
+ * sys_exit()
+ *                             get_task_struct() // UaF
+ *
+ * Solution: Use wake_q_add_safe() and perform the get_task_struct() before
+ * the smp_store_release() that does ->state = STATE_READY.
+ *
+ * 2) Without proper _release/_acquire barriers, the woken up task
+ *    could read stale data
+ *
+ * Thread A
+ *                             Thread B
+ * do_mq_timedreceive
+ * WRITE_ONCE(wait.state, STATE_NONE);
+ * schedule_hrtimeout()
+ *                             state = STATE_READY;
+ * <timeout returns>
+ * if (wait.state == STATE_READY) return;
+ * msg_ptr = wait.msg;         // Access to stale data!
+ *                             receiver->msg = message; (reordered)
+ *
+ * Solution: use _release and _acquire barriers.
+ *
+ * 3) There is intentionally no barrier when setting current->state
+ *    to TASK_INTERRUPTIBLE: spin_unlock(&info->lock) provides the
+ *    release memory barrier, and the wakeup is triggered when holding
+ *    info->lock, i.e. spin_lock(&info->lock) provided a pairing
+ *    acquire memory barrier.
+ */
+
 struct ext_wait_queue {                /* queue of sleeping tasks */
        struct task_struct *task;
        struct list_head list;
@@ -646,18 +706,23 @@ static int wq_sleep(struct mqueue_inode_info *info, int sr,
        wq_add(info, sr, ewp);
 
        for (;;) {
+               /* memory barrier not required, we hold info->lock */
                __set_current_state(TASK_INTERRUPTIBLE);
 
                spin_unlock(&info->lock);
                time = schedule_hrtimeout_range_clock(timeout, 0,
                        HRTIMER_MODE_ABS, CLOCK_REALTIME);
 
-               if (ewp->state == STATE_READY) {
+               if (READ_ONCE(ewp->state) == STATE_READY) {
+                       /* see MQ_BARRIER for purpose/pairing */
+                       smp_acquire__after_ctrl_dep();
                        retval = 0;
                        goto out;
                }
                spin_lock(&info->lock);
-               if (ewp->state == STATE_READY) {
+
+               /* we hold info->lock, so no memory barrier required */
+               if (READ_ONCE(ewp->state) == STATE_READY) {
                        retval = 0;
                        goto out_unlock;
                }
@@ -918,6 +983,18 @@ out_name:
  * The same algorithm is used for senders.
  */
 
+static inline void __pipelined_op(struct wake_q_head *wake_q,
+                                 struct mqueue_inode_info *info,
+                                 struct ext_wait_queue *this)
+{
+       list_del(&this->list);
+       get_task_struct(this->task);
+
+       /* see MQ_BARRIER for purpose/pairing */
+       smp_store_release(&this->state, STATE_READY);
+       wake_q_add_safe(wake_q, this->task);
+}
+
 /* pipelined_send() - send a message directly to the task waiting in
  * sys_mq_timedreceive() (without inserting message into a queue).
  */
@@ -927,17 +1004,7 @@ static inline void pipelined_send(struct wake_q_head *wake_q,
                                  struct ext_wait_queue *receiver)
 {
        receiver->msg = message;
-       list_del(&receiver->list);
-       wake_q_add(wake_q, receiver->task);
-       /*
-        * Rely on the implicit cmpxchg barrier from wake_q_add such
-        * that we can ensure that updating receiver->state is the last
-        * write operation: As once set, the receiver can continue,
-        * and if we don't have the reference count from the wake_q,
-        * yet, at that point we can later have a use-after-free
-        * condition and bogus wakeup.
-        */
-       receiver->state = STATE_READY;
+       __pipelined_op(wake_q, info, receiver);
 }
 
 /* pipelined_receive() - if there is task waiting in sys_mq_timedsend()
@@ -955,9 +1022,7 @@ static inline void pipelined_receive(struct wake_q_head *wake_q,
        if (msg_insert(sender->msg, info))
                return;
 
-       list_del(&sender->list);
-       wake_q_add(wake_q, sender->task);
-       sender->state = STATE_READY;
+       __pipelined_op(wake_q, info, sender);
 }
 
 static int do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
@@ -1044,7 +1109,9 @@ static int do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
                } else {
                        wait.task = current;
                        wait.msg = (void *) msg_ptr;
-                       wait.state = STATE_NONE;
+
+                       /* memory barrier not required, we hold info->lock */
+                       WRITE_ONCE(wait.state, STATE_NONE);
                        ret = wq_sleep(info, SEND, timeout, &wait);
                        /*
                         * wq_sleep must be called with info->lock held, and
@@ -1147,7 +1214,9 @@ static int do_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
                        ret = -EAGAIN;
                } else {
                        wait.task = current;
-                       wait.state = STATE_NONE;
+
+                       /* memory barrier not required, we hold info->lock */
+                       WRITE_ONCE(wait.state, STATE_NONE);
                        ret = wq_sleep(info, RECV, timeout, &wait);
                        msg_ptr = wait.msg;
                }
index 8dec945..caca673 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -61,6 +61,16 @@ struct msg_queue {
        struct list_head q_senders;
 } __randomize_layout;
 
+/*
+ * MSG_BARRIER Locking:
+ *
+ * Similar to the optimization used in ipc/mqueue.c, one syscall return path
+ * does not acquire any locks when it sees that a message exists in
+ * msg_receiver.r_msg. Therefore r_msg is set using smp_store_release()
+ * and accessed using READ_ONCE()+smp_acquire__after_ctrl_dep(). In addition,
+ * wake_q_add_safe() is used. See ipc/mqueue.c for more details
+ */
+
 /* one msg_receiver structure for each sleeping receiver */
 struct msg_receiver {
        struct list_head        r_list;
@@ -184,6 +194,10 @@ static inline void ss_add(struct msg_queue *msq,
 {
        mss->tsk = current;
        mss->msgsz = msgsz;
+       /*
+        * No memory barrier required: we did ipc_lock_object(),
+        * and the waker obtains that lock before calling wake_q_add().
+        */
        __set_current_state(TASK_INTERRUPTIBLE);
        list_add_tail(&mss->list, &msq->q_senders);
 }
@@ -237,8 +251,11 @@ static void expunge_all(struct msg_queue *msq, int res,
        struct msg_receiver *msr, *t;
 
        list_for_each_entry_safe(msr, t, &msq->q_receivers, r_list) {
-               wake_q_add(wake_q, msr->r_tsk);
-               WRITE_ONCE(msr->r_msg, ERR_PTR(res));
+               get_task_struct(msr->r_tsk);
+
+               /* see MSG_BARRIER for purpose/pairing */
+               smp_store_release(&msr->r_msg, ERR_PTR(res));
+               wake_q_add_safe(wake_q, msr->r_tsk);
        }
 }
 
@@ -377,7 +394,7 @@ copy_msqid_from_user(struct msqid64_ds *out, void __user *buf, int version)
  * NOTE: no locks must be held, the rwsem is taken inside this function.
  */
 static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
-                       struct msqid64_ds *msqid64)
+                       struct ipc64_perm *perm, int msg_qbytes)
 {
        struct kern_ipc_perm *ipcp;
        struct msg_queue *msq;
@@ -387,7 +404,7 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
        rcu_read_lock();
 
        ipcp = ipcctl_obtain_check(ns, &msg_ids(ns), msqid, cmd,
-                                     &msqid64->msg_perm, msqid64->msg_qbytes);
+                                     perm, msg_qbytes);
        if (IS_ERR(ipcp)) {
                err = PTR_ERR(ipcp);
                goto out_unlock1;
@@ -409,18 +426,18 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
        {
                DEFINE_WAKE_Q(wake_q);
 
-               if (msqid64->msg_qbytes > ns->msg_ctlmnb &&
+               if (msg_qbytes > ns->msg_ctlmnb &&
                    !capable(CAP_SYS_RESOURCE)) {
                        err = -EPERM;
                        goto out_unlock1;
                }
 
                ipc_lock_object(&msq->q_perm);
-               err = ipc_update_perm(&msqid64->msg_perm, ipcp);
+               err = ipc_update_perm(perm, ipcp);
                if (err)
                        goto out_unlock0;
 
-               msq->q_qbytes = msqid64->msg_qbytes;
+               msq->q_qbytes = msg_qbytes;
 
                msq->q_ctime = ktime_get_real_seconds();
                /*
@@ -601,9 +618,10 @@ static long ksys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf, int ver
        case IPC_SET:
                if (copy_msqid_from_user(&msqid64, buf, version))
                        return -EFAULT;
-               /* fallthru */
+               return msgctl_down(ns, msqid, cmd, &msqid64.msg_perm,
+                                  msqid64.msg_qbytes);
        case IPC_RMID:
-               return msgctl_down(ns, msqid, cmd, &msqid64);
+               return msgctl_down(ns, msqid, cmd, NULL, 0);
        default:
                return  -EINVAL;
        }
@@ -735,9 +753,9 @@ static long compat_ksys_msgctl(int msqid, int cmd, void __user *uptr, int versio
        case IPC_SET:
                if (copy_compat_msqid_from_user(&msqid64, uptr, version))
                        return -EFAULT;
-               /* fallthru */
+               return msgctl_down(ns, msqid, cmd, &msqid64.msg_perm, msqid64.msg_qbytes);
        case IPC_RMID:
-               return msgctl_down(ns, msqid, cmd, &msqid64);
+               return msgctl_down(ns, msqid, cmd, NULL, 0);
        default:
                return -EINVAL;
        }
@@ -798,13 +816,17 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg,
                        list_del(&msr->r_list);
                        if (msr->r_maxsize < msg->m_ts) {
                                wake_q_add(wake_q, msr->r_tsk);
-                               WRITE_ONCE(msr->r_msg, ERR_PTR(-E2BIG));
+
+                               /* See expunge_all regarding memory barrier */
+                               smp_store_release(&msr->r_msg, ERR_PTR(-E2BIG));
                        } else {
                                ipc_update_pid(&msq->q_lrpid, task_pid(msr->r_tsk));
                                msq->q_rtime = ktime_get_real_seconds();
 
                                wake_q_add(wake_q, msr->r_tsk);
-                               WRITE_ONCE(msr->r_msg, msg);
+
+                               /* See expunge_all regarding memory barrier */
+                               smp_store_release(&msr->r_msg, msg);
                                return 1;
                        }
                }
@@ -1154,7 +1176,11 @@ static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, in
                        msr_d.r_maxsize = INT_MAX;
                else
                        msr_d.r_maxsize = bufsz;
-               msr_d.r_msg = ERR_PTR(-EAGAIN);
+
+               /* memory barrier not require due to ipc_lock_object() */
+               WRITE_ONCE(msr_d.r_msg, ERR_PTR(-EAGAIN));
+
+               /* memory barrier not required, we own ipc_lock_object() */
                __set_current_state(TASK_INTERRUPTIBLE);
 
                ipc_unlock_object(&msq->q_perm);
@@ -1183,8 +1209,12 @@ static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, in
                 * signal) it will either see the message and continue ...
                 */
                msg = READ_ONCE(msr_d.r_msg);
-               if (msg != ERR_PTR(-EAGAIN))
+               if (msg != ERR_PTR(-EAGAIN)) {
+                       /* see MSG_BARRIER for purpose/pairing */
+                       smp_acquire__after_ctrl_dep();
+
                        goto out_unlock1;
+               }
 
                 /*
                  * ... or see -EAGAIN, acquire the lock to check the message
@@ -1192,7 +1222,7 @@ static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, in
                  */
                ipc_lock_object(&msq->q_perm);
 
-               msg = msr_d.r_msg;
+               msg = READ_ONCE(msr_d.r_msg);
                if (msg != ERR_PTR(-EAGAIN))
                        goto out_unlock0;
 
index ec97a70..4f4303f 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -205,15 +205,38 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it);
  *
  * Memory ordering:
  * Most ordering is enforced by using spin_lock() and spin_unlock().
- * The special case is use_global_lock:
+ *
+ * Exceptions:
+ * 1) use_global_lock: (SEM_BARRIER_1)
  * Setting it from non-zero to 0 is a RELEASE, this is ensured by
- * using smp_store_release().
+ * using smp_store_release(): Immediately after setting it to 0,
+ * a simple op can start.
  * Testing if it is non-zero is an ACQUIRE, this is ensured by using
  * smp_load_acquire().
  * Setting it from 0 to non-zero must be ordered with regards to
  * this smp_load_acquire(), this is guaranteed because the smp_load_acquire()
  * is inside a spin_lock() and after a write from 0 to non-zero a
  * spin_lock()+spin_unlock() is done.
+ *
+ * 2) queue.status: (SEM_BARRIER_2)
+ * Initialization is done while holding sem_lock(), so no further barrier is
+ * required.
+ * Setting it to a result code is a RELEASE, this is ensured by both a
+ * smp_store_release() (for case a) and while holding sem_lock()
+ * (for case b).
+ * The AQUIRE when reading the result code without holding sem_lock() is
+ * achieved by using READ_ONCE() + smp_acquire__after_ctrl_dep().
+ * (case a above).
+ * Reading the result code while holding sem_lock() needs no further barriers,
+ * the locks inside sem_lock() enforce ordering (case b above)
+ *
+ * 3) current->state:
+ * current->state is set to TASK_INTERRUPTIBLE while holding sem_lock().
+ * The wakeup is handled using the wake_q infrastructure. wake_q wakeups may
+ * happen immediately after calling wake_q_add. As wake_q_add_safe() is called
+ * when holding sem_lock(), no further barriers are required.
+ *
+ * See also ipc/mqueue.c for more details on the covered races.
  */
 
 #define sc_semmsl      sem_ctls[0]
@@ -344,12 +367,8 @@ static void complexmode_tryleave(struct sem_array *sma)
                return;
        }
        if (sma->use_global_lock == 1) {
-               /*
-                * Immediately after setting use_global_lock to 0,
-                * a simple op can start. Thus: all memory writes
-                * performed by the current operation must be visible
-                * before we set use_global_lock to 0.
-                */
+
+               /* See SEM_BARRIER_1 for purpose/pairing */
                smp_store_release(&sma->use_global_lock, 0);
        } else {
                sma->use_global_lock--;
@@ -400,7 +419,7 @@ static inline int sem_lock(struct sem_array *sma, struct sembuf *sops,
                 */
                spin_lock(&sem->lock);
 
-               /* pairs with smp_store_release() */
+               /* see SEM_BARRIER_1 for purpose/pairing */
                if (!smp_load_acquire(&sma->use_global_lock)) {
                        /* fast path successful! */
                        return sops->sem_num;
@@ -766,15 +785,12 @@ would_block:
 static inline void wake_up_sem_queue_prepare(struct sem_queue *q, int error,
                                             struct wake_q_head *wake_q)
 {
-       wake_q_add(wake_q, q->sleeper);
-       /*
-        * Rely on the above implicit barrier, such that we can
-        * ensure that we hold reference to the task before setting
-        * q->status. Otherwise we could race with do_exit if the
-        * task is awoken by an external event before calling
-        * wake_up_process().
-        */
-       WRITE_ONCE(q->status, error);
+       get_task_struct(q->sleeper);
+
+       /* see SEM_BARRIER_2 for purpuse/pairing */
+       smp_store_release(&q->status, error);
+
+       wake_q_add_safe(wake_q, q->sleeper);
 }
 
 static void unlink_queue(struct sem_array *sma, struct sem_queue *q)
@@ -2148,9 +2164,11 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops,
        }
 
        do {
+               /* memory ordering ensured by the lock in sem_lock() */
                WRITE_ONCE(queue.status, -EINTR);
                queue.sleeper = current;
 
+               /* memory ordering is ensured by the lock in sem_lock() */
                __set_current_state(TASK_INTERRUPTIBLE);
                sem_unlock(sma, locknum);
                rcu_read_unlock();
@@ -2173,13 +2191,8 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops,
                 */
                error = READ_ONCE(queue.status);
                if (error != -EINTR) {
-                       /*
-                        * User space could assume that semop() is a memory
-                        * barrier: Without the mb(), the cpu could
-                        * speculatively read in userspace stale data that was
-                        * overwritten by the previous owner of the semaphore.
-                        */
-                       smp_mb();
+                       /* see SEM_BARRIER_2 for purpose/pairing */
+                       smp_acquire__after_ctrl_dep();
                        goto out_free;
                }
 
@@ -2189,6 +2202,9 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops,
                if (!ipc_valid_object(&sma->sem_perm))
                        goto out_unlock_free;
 
+               /*
+                * No necessity for any barrier: We are protect by sem_lock()
+                */
                error = READ_ONCE(queue.status);
 
                /*
index 915eacb..fe61df5 100644 (file)
@@ -126,7 +126,7 @@ void ipc_init_ids(struct ipc_ids *ids)
 }
 
 #ifdef CONFIG_PROC_FS
-static const struct file_operations sysvipc_proc_fops;
+static const struct proc_ops sysvipc_proc_ops;
 /**
  * ipc_init_proc_interface -  create a proc interface for sysipc types using a seq_file interface.
  * @path: Path in procfs
@@ -151,7 +151,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
        pde = proc_create_data(path,
                               S_IRUGO,        /* world readable */
                               NULL,           /* parent dir */
-                              &sysvipc_proc_fops,
+                              &sysvipc_proc_ops,
                               iface);
        if (!pde)
                kfree(iface);
@@ -884,10 +884,10 @@ static int sysvipc_proc_release(struct inode *inode, struct file *file)
        return seq_release_private(inode, file);
 }
 
-static const struct file_operations sysvipc_proc_fops = {
-       .open    = sysvipc_proc_open,
-       .read    = seq_read,
-       .llseek  = seq_lseek,
-       .release = sysvipc_proc_release,
+static const struct proc_ops sysvipc_proc_ops = {
+       .proc_open      = sysvipc_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = sysvipc_proc_release,
 };
 #endif /* CONFIG_PROC_FS */
index c09ea4c..a28c79c 100644 (file)
@@ -47,10 +47,9 @@ ikconfig_read_current(struct file *file, char __user *buf,
                                       &kernel_config_data);
 }
 
-static const struct file_operations ikconfig_file_ops = {
-       .owner = THIS_MODULE,
-       .read = ikconfig_read_current,
-       .llseek = default_llseek,
+static const struct proc_ops config_gz_proc_ops = {
+       .proc_read      = ikconfig_read_current,
+       .proc_lseek     = default_llseek,
 };
 
 static int __init ikconfig_init(void)
@@ -59,7 +58,7 @@ static int __init ikconfig_init(void)
 
        /* create the current config file */
        entry = proc_create("config.gz", S_IFREG | S_IRUGO, NULL,
-                           &ikconfig_file_ops);
+                           &config_gz_proc_ops);
        if (!entry)
                return -ENOMEM;
 
index cfc4f08..9e5783d 100644 (file)
@@ -176,20 +176,20 @@ static int irq_affinity_list_proc_open(struct inode *inode, struct file *file)
        return single_open(file, irq_affinity_list_proc_show, PDE_DATA(inode));
 }
 
-static const struct file_operations irq_affinity_proc_fops = {
-       .open           = irq_affinity_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = irq_affinity_proc_write,
+static const struct proc_ops irq_affinity_proc_ops = {
+       .proc_open      = irq_affinity_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = irq_affinity_proc_write,
 };
 
-static const struct file_operations irq_affinity_list_proc_fops = {
-       .open           = irq_affinity_list_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = irq_affinity_list_proc_write,
+static const struct proc_ops irq_affinity_list_proc_ops = {
+       .proc_open      = irq_affinity_list_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = irq_affinity_list_proc_write,
 };
 
 #ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK
@@ -246,12 +246,12 @@ static int default_affinity_open(struct inode *inode, struct file *file)
        return single_open(file, default_affinity_show, PDE_DATA(inode));
 }
 
-static const struct file_operations default_affinity_proc_fops = {
-       .open           = default_affinity_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = default_affinity_write,
+static const struct proc_ops default_affinity_proc_ops = {
+       .proc_open      = default_affinity_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = default_affinity_write,
 };
 
 static int irq_node_proc_show(struct seq_file *m, void *v)
@@ -342,7 +342,7 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc)
 #ifdef CONFIG_SMP
        /* create /proc/irq/<irq>/smp_affinity */
        proc_create_data("smp_affinity", 0644, desc->dir,
-                        &irq_affinity_proc_fops, irqp);
+                        &irq_affinity_proc_ops, irqp);
 
        /* create /proc/irq/<irq>/affinity_hint */
        proc_create_single_data("affinity_hint", 0444, desc->dir,
@@ -350,7 +350,7 @@ void register_irq_proc(unsigned int irq, struct irq_desc *desc)
 
        /* create /proc/irq/<irq>/smp_affinity_list */
        proc_create_data("smp_affinity_list", 0644, desc->dir,
-                        &irq_affinity_list_proc_fops, irqp);
+                        &irq_affinity_list_proc_ops, irqp);
 
        proc_create_single_data("node", 0444, desc->dir, irq_node_proc_show,
                        irqp);
@@ -401,7 +401,7 @@ static void register_default_affinity_proc(void)
 {
 #ifdef CONFIG_SMP
        proc_create("irq/default_smp_affinity", 0644, NULL,
-                   &default_affinity_proc_fops);
+                   &default_affinity_proc_ops);
 #endif
 }
 
index 136ce04..d812b90 100644 (file)
@@ -698,16 +698,16 @@ const char *kdb_walk_kallsyms(loff_t *pos)
 }
 #endif /* CONFIG_KGDB_KDB */
 
-static const struct file_operations kallsyms_operations = {
-       .open = kallsyms_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = seq_release_private,
+static const struct proc_ops kallsyms_proc_ops = {
+       .proc_open      = kallsyms_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = seq_release_private,
 };
 
 static int __init kallsyms_init(void)
 {
-       proc_create("kallsyms", 0444, NULL, &kallsyms_operations);
+       proc_create("kallsyms", 0444, NULL, &kallsyms_proc_ops);
        return 0;
 }
 device_initcall(kallsyms_init);
index e3acead..8d1c158 100644 (file)
@@ -255,17 +255,17 @@ static int lstats_open(struct inode *inode, struct file *filp)
        return single_open(filp, lstats_show, NULL);
 }
 
-static const struct file_operations lstats_fops = {
-       .open           = lstats_open,
-       .read           = seq_read,
-       .write          = lstats_write,
-       .llseek         = seq_lseek,
-       .release        = single_release,
+static const struct proc_ops lstats_proc_ops = {
+       .proc_open      = lstats_open,
+       .proc_read      = seq_read,
+       .proc_write     = lstats_write,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
 };
 
 static int __init init_lstats_procfs(void)
 {
-       proc_create("latency_stats", 0644, NULL, &lstats_fops);
+       proc_create("latency_stats", 0644, NULL, &lstats_proc_ops);
        return 0;
 }
 
index 9bb6d24..231684c 100644 (file)
@@ -643,12 +643,12 @@ static int lock_stat_release(struct inode *inode, struct file *file)
        return seq_release(inode, file);
 }
 
-static const struct file_operations proc_lock_stat_operations = {
-       .open           = lock_stat_open,
-       .write          = lock_stat_write,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = lock_stat_release,
+static const struct proc_ops lock_stat_proc_ops = {
+       .proc_open      = lock_stat_open,
+       .proc_write     = lock_stat_write,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = lock_stat_release,
 };
 #endif /* CONFIG_LOCK_STAT */
 
@@ -660,8 +660,7 @@ static int __init lockdep_proc_init(void)
 #endif
        proc_create_single("lockdep_stats", S_IRUSR, NULL, lockdep_stats_show);
 #ifdef CONFIG_LOCK_STAT
-       proc_create("lock_stat", S_IRUSR | S_IWUSR, NULL,
-                   &proc_lock_stat_operations);
+       proc_create("lock_stat", S_IRUSR | S_IWUSR, NULL, &lock_stat_proc_ops);
 #endif
 
        return 0;
index 90ec5ab..33569a0 100644 (file)
@@ -4354,16 +4354,16 @@ static int modules_open(struct inode *inode, struct file *file)
        return err;
 }
 
-static const struct file_operations proc_modules_operations = {
-       .open           = modules_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = seq_release,
+static const struct proc_ops modules_proc_ops = {
+       .proc_open      = modules_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = seq_release,
 };
 
 static int __init proc_modules_init(void)
 {
-       proc_create("modules", 0, NULL, &proc_modules_operations);
+       proc_create("modules", 0, NULL, &modules_proc_ops);
        return 0;
 }
 module_init(proc_modules_init);
index 4b144b0..6f69a41 100644 (file)
@@ -442,18 +442,18 @@ static ssize_t prof_cpu_mask_proc_write(struct file *file,
        return err;
 }
 
-static const struct file_operations prof_cpu_mask_proc_fops = {
-       .open           = prof_cpu_mask_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = prof_cpu_mask_proc_write,
+static const struct proc_ops prof_cpu_mask_proc_ops = {
+       .proc_open      = prof_cpu_mask_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
+       .proc_write     = prof_cpu_mask_proc_write,
 };
 
 void create_prof_cpu_mask(void)
 {
        /* create /proc/irq/prof_cpu_mask */
-       proc_create("irq/prof_cpu_mask", 0600, NULL, &prof_cpu_mask_proc_fops);
+       proc_create("irq/prof_cpu_mask", 0600, NULL, &prof_cpu_mask_proc_ops);
 }
 
 /*
@@ -517,10 +517,10 @@ static ssize_t write_profile(struct file *file, const char __user *buf,
        return count;
 }
 
-static const struct file_operations proc_profile_operations = {
-       .read           = read_profile,
-       .write          = write_profile,
-       .llseek         = default_llseek,
+static const struct proc_ops profile_proc_ops = {
+       .proc_read      = read_profile,
+       .proc_write     = write_profile,
+       .proc_lseek     = default_llseek,
 };
 
 int __ref create_proc_profile(void)
@@ -548,7 +548,7 @@ int __ref create_proc_profile(void)
        err = 0;
 #endif
        entry = proc_create("profile", S_IWUSR | S_IRUGO,
-                           NULL, &proc_profile_operations);
+                           NULL, &profile_proc_ops);
        if (!entry)
                goto err_state_onl;
        proc_set_size(entry, (1 + prof_len) * sizeof(atomic_t));
index db7b50b..ac4bd0c 100644 (file)
@@ -1251,40 +1251,40 @@ static int psi_fop_release(struct inode *inode, struct file *file)
        return single_release(inode, file);
 }
 
-static const struct file_operations psi_io_fops = {
-       .open           = psi_io_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .write          = psi_io_write,
-       .poll           = psi_fop_poll,
-       .release        = psi_fop_release,
+static const struct proc_ops psi_io_proc_ops = {
+       .proc_open      = psi_io_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_write     = psi_io_write,
+       .proc_poll      = psi_fop_poll,
+       .proc_release   = psi_fop_release,
 };
 
-static const struct file_operations psi_memory_fops = {
-       .open           = psi_memory_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .write          = psi_memory_write,
-       .poll           = psi_fop_poll,
-       .release        = psi_fop_release,
+static const struct proc_ops psi_memory_proc_ops = {
+       .proc_open      = psi_memory_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_write     = psi_memory_write,
+       .proc_poll      = psi_fop_poll,
+       .proc_release   = psi_fop_release,
 };
 
-static const struct file_operations psi_cpu_fops = {
-       .open           = psi_cpu_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .write          = psi_cpu_write,
-       .poll           = psi_fop_poll,
-       .release        = psi_fop_release,
+static const struct proc_ops psi_cpu_proc_ops = {
+       .proc_open      = psi_cpu_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_write     = psi_cpu_write,
+       .proc_poll      = psi_fop_poll,
+       .proc_release   = psi_fop_release,
 };
 
 static int __init psi_proc_init(void)
 {
        if (psi_enable) {
                proc_mkdir("pressure", NULL);
-               proc_create("pressure/io", 0, NULL, &psi_io_fops);
-               proc_create("pressure/memory", 0, NULL, &psi_memory_fops);
-               proc_create("pressure/cpu", 0, NULL, &psi_cpu_fops);
+               proc_create("pressure/io", 0, NULL, &psi_io_proc_ops);
+               proc_create("pressure/memory", 0, NULL, &psi_memory_proc_ops);
+               proc_create("pressure/cpu", 0, NULL, &psi_cpu_proc_ops);
        }
        return 0;
 }
index 6e175fb..89260aa 100644 (file)
@@ -431,97 +431,6 @@ EXPORT_SYMBOL(bitmap_find_next_zero_area_off);
  * second version by Paul Jackson, third by Joe Korty.
  */
 
-#define CHUNKSZ                                32
-#define nbits_to_hold_value(val)       fls(val)
-#define BASEDEC 10             /* fancier cpuset lists input in decimal */
-
-/**
- * __bitmap_parse - convert an ASCII hex string into a bitmap.
- * @buf: pointer to buffer containing string.
- * @buflen: buffer size in bytes.  If string is smaller than this
- *    then it must be terminated with a \0.
- * @is_user: location of buffer, 0 indicates kernel space
- * @maskp: pointer to bitmap array that will contain result.
- * @nmaskbits: size of bitmap, in bits.
- *
- * Commas group hex digits into chunks.  Each chunk defines exactly 32
- * bits of the resultant bitmask.  No chunk may specify a value larger
- * than 32 bits (%-EOVERFLOW), and if a chunk specifies a smaller value
- * then leading 0-bits are prepended.  %-EINVAL is returned for illegal
- * characters and for grouping errors such as "1,,5", ",44", "," and "".
- * Leading and trailing whitespace accepted, but not embedded whitespace.
- */
-int __bitmap_parse(const char *buf, unsigned int buflen,
-               int is_user, unsigned long *maskp,
-               int nmaskbits)
-{
-       int c, old_c, totaldigits, ndigits, nchunks, nbits;
-       u32 chunk;
-       const char __user __force *ubuf = (const char __user __force *)buf;
-
-       bitmap_zero(maskp, nmaskbits);
-
-       nchunks = nbits = totaldigits = c = 0;
-       do {
-               chunk = 0;
-               ndigits = totaldigits;
-
-               /* Get the next chunk of the bitmap */
-               while (buflen) {
-                       old_c = c;
-                       if (is_user) {
-                               if (__get_user(c, ubuf++))
-                                       return -EFAULT;
-                       }
-                       else
-                               c = *buf++;
-                       buflen--;
-                       if (isspace(c))
-                               continue;
-
-                       /*
-                        * If the last character was a space and the current
-                        * character isn't '\0', we've got embedded whitespace.
-                        * This is a no-no, so throw an error.
-                        */
-                       if (totaldigits && c && isspace(old_c))
-                               return -EINVAL;
-
-                       /* A '\0' or a ',' signal the end of the chunk */
-                       if (c == '\0' || c == ',')
-                               break;
-
-                       if (!isxdigit(c))
-                               return -EINVAL;
-
-                       /*
-                        * Make sure there are at least 4 free bits in 'chunk'.
-                        * If not, this hexdigit will overflow 'chunk', so
-                        * throw an error.
-                        */
-                       if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1))
-                               return -EOVERFLOW;
-
-                       chunk = (chunk << 4) | hex_to_bin(c);
-                       totaldigits++;
-               }
-               if (ndigits == totaldigits)
-                       return -EINVAL;
-               if (nchunks == 0 && chunk == 0)
-                       continue;
-
-               __bitmap_shift_left(maskp, maskp, CHUNKSZ, nmaskbits);
-               *maskp |= chunk;
-               nchunks++;
-               nbits += (nchunks == 1) ? nbits_to_hold_value(chunk) : CHUNKSZ;
-               if (nbits > nmaskbits)
-                       return -EOVERFLOW;
-       } while (buflen && c == ',');
-
-       return 0;
-}
-EXPORT_SYMBOL(__bitmap_parse);
-
 /**
  * bitmap_parse_user - convert an ASCII hex string in a user buffer into a bitmap
  *
@@ -530,22 +439,22 @@ EXPORT_SYMBOL(__bitmap_parse);
  *    then it must be terminated with a \0.
  * @maskp: pointer to bitmap array that will contain result.
  * @nmaskbits: size of bitmap, in bits.
- *
- * Wrapper for __bitmap_parse(), providing it with user buffer.
- *
- * We cannot have this as an inline function in bitmap.h because it needs
- * linux/uaccess.h to get the access_ok() declaration and this causes
- * cyclic dependencies.
  */
 int bitmap_parse_user(const char __user *ubuf,
                        unsigned int ulen, unsigned long *maskp,
                        int nmaskbits)
 {
-       if (!access_ok(ubuf, ulen))
-               return -EFAULT;
-       return __bitmap_parse((const char __force *)ubuf,
-                               ulen, 1, maskp, nmaskbits);
+       char *buf;
+       int ret;
 
+       buf = memdup_user_nul(ubuf, ulen);
+       if (IS_ERR(buf))
+               return PTR_ERR(buf);
+
+       ret = bitmap_parse(buf, UINT_MAX, maskp, nmaskbits);
+
+       kfree(buf);
+       return ret;
 }
 EXPORT_SYMBOL(bitmap_parse_user);
 
@@ -653,6 +562,14 @@ static const char *bitmap_find_region(const char *str)
        return end_of_str(*str) ? NULL : str;
 }
 
+static const char *bitmap_find_region_reverse(const char *start, const char *end)
+{
+       while (start <= end && __end_of_region(*end))
+               end--;
+
+       return end;
+}
+
 static const char *bitmap_parse_region(const char *str, struct region *r)
 {
        str = bitmap_getnum(str, &r->start);
@@ -776,6 +693,80 @@ int bitmap_parselist_user(const char __user *ubuf,
 }
 EXPORT_SYMBOL(bitmap_parselist_user);
 
+static const char *bitmap_get_x32_reverse(const char *start,
+                                       const char *end, u32 *num)
+{
+       u32 ret = 0;
+       int c, i;
+
+       for (i = 0; i < 32; i += 4) {
+               c = hex_to_bin(*end--);
+               if (c < 0)
+                       return ERR_PTR(-EINVAL);
+
+               ret |= c << i;
+
+               if (start > end || __end_of_region(*end))
+                       goto out;
+       }
+
+       if (hex_to_bin(*end--) >= 0)
+               return ERR_PTR(-EOVERFLOW);
+out:
+       *num = ret;
+       return end;
+}
+
+/**
+ * bitmap_parse - convert an ASCII hex string into a bitmap.
+ * @start: pointer to buffer containing string.
+ * @buflen: buffer size in bytes.  If string is smaller than this
+ *    then it must be terminated with a \0 or \n. In that case,
+ *    UINT_MAX may be provided instead of string length.
+ * @maskp: pointer to bitmap array that will contain result.
+ * @nmaskbits: size of bitmap, in bits.
+ *
+ * Commas group hex digits into chunks.  Each chunk defines exactly 32
+ * bits of the resultant bitmask.  No chunk may specify a value larger
+ * than 32 bits (%-EOVERFLOW), and if a chunk specifies a smaller value
+ * then leading 0-bits are prepended.  %-EINVAL is returned for illegal
+ * characters. Grouping such as "1,,5", ",44", "," or "" is allowed.
+ * Leading, embedded and trailing whitespace accepted.
+ */
+int bitmap_parse(const char *start, unsigned int buflen,
+               unsigned long *maskp, int nmaskbits)
+{
+       const char *end = strnchrnul(start, buflen, '\n') - 1;
+       int chunks = BITS_TO_U32(nmaskbits);
+       u32 *bitmap = (u32 *)maskp;
+       int unset_bit;
+
+       while (1) {
+               end = bitmap_find_region_reverse(start, end);
+               if (start > end)
+                       break;
+
+               if (!chunks--)
+                       return -EOVERFLOW;
+
+               end = bitmap_get_x32_reverse(start, end, bitmap++);
+               if (IS_ERR(end))
+                       return PTR_ERR(end);
+       }
+
+       unset_bit = (BITS_TO_U32(nmaskbits) - chunks) * 32;
+       if (unset_bit < nmaskbits) {
+               bitmap_clear(maskp, unset_bit, nmaskbits - unset_bit);
+               return 0;
+       }
+
+       if (find_next_bit(maskp, unset_bit, nmaskbits) != unset_bit)
+               return -EOVERFLOW;
+
+       return 0;
+}
+EXPORT_SYMBOL(bitmap_parse);
+
 
 #ifdef CONFIG_NUMA
 /**
index 08ec58c..f607b96 100644 (file)
@@ -434,6 +434,23 @@ char *strchrnul(const char *s, int c)
 EXPORT_SYMBOL(strchrnul);
 #endif
 
+/**
+ * strnchrnul - Find and return a character in a length limited string,
+ * or end of string
+ * @s: The string to be searched
+ * @count: The number of characters to be searched
+ * @c: The character to search for
+ *
+ * Returns pointer to the first occurrence of 'c' in s. If c is not found,
+ * then return a pointer to the last character of the string.
+ */
+char *strnchrnul(const char *s, size_t count, int c)
+{
+       while (count-- && *s && *s != (char)c)
+               s++;
+       return (char *)s;
+}
+
 #ifndef __HAVE_ARCH_STRRCHR
 /**
  * strrchr - Find the last occurrence of a character in a string
index 71ec3af..61ed71c 100644 (file)
@@ -295,7 +295,8 @@ static void __init test_replace(void)
        expect_eq_bitmap(bmap, exp3_1_0, nbits);
 }
 
-#define PARSE_TIME 0x1
+#define PARSE_TIME     0x1
+#define NO_LEN         0x2
 
 struct test_bitmap_parselist{
        const int errno;
@@ -349,7 +350,6 @@ static const struct test_bitmap_parselist parselist_tests[] __initconst = {
        {-EINVAL, "0-31:a/1", NULL, 8, 0},
        {-EINVAL, "0-\n", NULL, 8, 0},
 
-#undef step
 };
 
 static void __init __test_bitmap_parselist(int is_user)
@@ -401,6 +401,95 @@ static void __init __test_bitmap_parselist(int is_user)
        }
 }
 
+static const unsigned long parse_test[] __initconst = {
+       BITMAP_FROM_U64(0),
+       BITMAP_FROM_U64(1),
+       BITMAP_FROM_U64(0xdeadbeef),
+       BITMAP_FROM_U64(0x100000000ULL),
+};
+
+static const unsigned long parse_test2[] __initconst = {
+       BITMAP_FROM_U64(0x100000000ULL), BITMAP_FROM_U64(0xdeadbeef),
+       BITMAP_FROM_U64(0x100000000ULL), BITMAP_FROM_U64(0xbaadf00ddeadbeef),
+       BITMAP_FROM_U64(0x100000000ULL), BITMAP_FROM_U64(0x0badf00ddeadbeef),
+};
+
+static const struct test_bitmap_parselist parse_tests[] __initconst = {
+       {0, "",                         &parse_test[0 * step], 32, 0},
+       {0, " ",                        &parse_test[0 * step], 32, 0},
+       {0, "0",                        &parse_test[0 * step], 32, 0},
+       {0, "0\n",                      &parse_test[0 * step], 32, 0},
+       {0, "1",                        &parse_test[1 * step], 32, 0},
+       {0, "deadbeef",                 &parse_test[2 * step], 32, 0},
+       {0, "1,0",                      &parse_test[3 * step], 33, 0},
+       {0, "deadbeef,\n,0,1",          &parse_test[2 * step], 96, 0},
+
+       {0, "deadbeef,1,0",             &parse_test2[0 * 2 * step], 96, 0},
+       {0, "baadf00d,deadbeef,1,0",    &parse_test2[1 * 2 * step], 128, 0},
+       {0, "badf00d,deadbeef,1,0",     &parse_test2[2 * 2 * step], 124, 0},
+       {0, "badf00d,deadbeef,1,0",     &parse_test2[2 * 2 * step], 124, NO_LEN},
+       {0, "  badf00d,deadbeef,1,0  ", &parse_test2[2 * 2 * step], 124, 0},
+       {0, " , badf00d,deadbeef,1,0 , ",       &parse_test2[2 * 2 * step], 124, 0},
+       {0, " , badf00d, ,, ,,deadbeef,1,0 , ", &parse_test2[2 * 2 * step], 124, 0},
+
+       {-EINVAL,    "goodfood,deadbeef,1,0",   NULL, 128, 0},
+       {-EOVERFLOW, "3,0",                     NULL, 33, 0},
+       {-EOVERFLOW, "123badf00d,deadbeef,1,0", NULL, 128, 0},
+       {-EOVERFLOW, "badf00d,deadbeef,1,0",    NULL, 90, 0},
+       {-EOVERFLOW, "fbadf00d,deadbeef,1,0",   NULL, 95, 0},
+       {-EOVERFLOW, "badf00d,deadbeef,1,0",    NULL, 100, 0},
+#undef step
+};
+
+static void __init __test_bitmap_parse(int is_user)
+{
+       int i;
+       int err;
+       ktime_t time;
+       DECLARE_BITMAP(bmap, 2048);
+       char *mode = is_user ? "_user"  : "";
+
+       for (i = 0; i < ARRAY_SIZE(parse_tests); i++) {
+               struct test_bitmap_parselist test = parse_tests[i];
+
+               if (is_user) {
+                       size_t len = strlen(test.in);
+                       mm_segment_t orig_fs = get_fs();
+
+                       set_fs(KERNEL_DS);
+                       time = ktime_get();
+                       err = bitmap_parse_user((__force const char __user *)test.in, len,
+                                               bmap, test.nbits);
+                       time = ktime_get() - time;
+                       set_fs(orig_fs);
+               } else {
+                       size_t len = test.flags & NO_LEN ?
+                               UINT_MAX : strlen(test.in);
+                       time = ktime_get();
+                       err = bitmap_parse(test.in, len, bmap, test.nbits);
+                       time = ktime_get() - time;
+               }
+
+               if (err != test.errno) {
+                       pr_err("parse%s: %d: input is %s, errno is %d, expected %d\n",
+                                       mode, i, test.in, err, test.errno);
+                       continue;
+               }
+
+               if (!err && test.expected
+                        && !__bitmap_equal(bmap, test.expected, test.nbits)) {
+                       pr_err("parse%s: %d: input is %s, result is 0x%lx, expected 0x%lx\n",
+                                       mode, i, test.in, bmap[0],
+                                       *test.expected);
+                       continue;
+               }
+
+               if (test.flags & PARSE_TIME)
+                       pr_err("parse%s: %d: input is '%s' OK, Time: %llu\n",
+                                       mode, i, test.in, time);
+       }
+}
+
 static void __init test_bitmap_parselist(void)
 {
        __test_bitmap_parselist(0);
@@ -411,6 +500,16 @@ static void __init test_bitmap_parselist_user(void)
        __test_bitmap_parselist(1);
 }
 
+static void __init test_bitmap_parse(void)
+{
+       __test_bitmap_parse(0);
+}
+
+static void __init test_bitmap_parse_user(void)
+{
+       __test_bitmap_parse(1);
+}
+
 #define EXP1_IN_BITS   (sizeof(exp1) * 8)
 
 static void __init test_bitmap_arr32(void)
@@ -516,6 +615,8 @@ static void __init selftest(void)
        test_copy();
        test_replace();
        test_bitmap_arr32();
+       test_bitmap_parse();
+       test_bitmap_parse_user();
        test_bitmap_parselist();
        test_bitmap_parselist_user();
        test_mem_optimisations();
index 327b3eb..0271b22 100644 (file)
@@ -117,3 +117,24 @@ config DEBUG_RODATA_TEST
     depends on STRICT_KERNEL_RWX
     ---help---
       This option enables a testcase for the setting rodata read-only.
+
+config GENERIC_PTDUMP
+       bool
+
+config PTDUMP_CORE
+       bool
+
+config PTDUMP_DEBUGFS
+       bool "Export kernel pagetable layout to userspace via debugfs"
+       depends on DEBUG_KERNEL
+       depends on DEBUG_FS
+       depends on GENERIC_PTDUMP
+       select PTDUMP_CORE
+       help
+         Say Y here if you want to show the kernel pagetable layout in a
+         debugfs file. This information is only useful for kernel developers
+         who are working in architecture specific areas of the kernel.
+         It is probably not a good idea to enable this feature in a production
+         kernel.
+
+         If in doubt, say N.
index 32f08e2..272e660 100644 (file)
@@ -109,3 +109,4 @@ obj-$(CONFIG_ZONE_DEVICE) += memremap.o
 obj-$(CONFIG_HMM_MIRROR) += hmm.o
 obj-$(CONFIG_MEMFD_CREATE) += memfd.o
 obj-$(CONFIG_MAPPING_DIRTY_HELPERS) += mapping_dirty_helpers.o
+obj-$(CONFIG_PTDUMP_CORE) += ptdump.o
index e13f4d2..1b521e0 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -1792,7 +1792,7 @@ EXPORT_SYMBOL(get_user_pages_unlocked);
  * Before activating this code, please be aware that the following assumptions
  * are currently made:
  *
- *  *) Either HAVE_RCU_TABLE_FREE is enabled, and tlb_remove_table() is used to
+ *  *) Either MMU_GATHER_RCU_TABLE_FREE is enabled, and tlb_remove_table() is used to
  *  free pages containing page tables or TLB flushing requires IPI broadcast.
  *
  *  *) ptes can be read atomically by the architecture.
index d379cb6..72e5a6d 100644 (file)
--- a/mm/hmm.c
+++ b/mm/hmm.c
@@ -186,7 +186,7 @@ static void hmm_range_need_fault(const struct hmm_vma_walk *hmm_vma_walk,
 }
 
 static int hmm_vma_walk_hole(unsigned long addr, unsigned long end,
-                            struct mm_walk *walk)
+                            __always_unused int depth, struct mm_walk *walk)
 {
        struct hmm_vma_walk *hmm_vma_walk = walk->private;
        struct hmm_range *range = hmm_vma_walk->range;
@@ -380,7 +380,7 @@ static int hmm_vma_walk_pmd(pmd_t *pmdp,
 again:
        pmd = READ_ONCE(*pmdp);
        if (pmd_none(pmd))
-               return hmm_vma_walk_hole(start, end, walk);
+               return hmm_vma_walk_hole(start, end, -1, walk);
 
        if (thp_migration_supported() && is_pmd_migration_entry(pmd)) {
                bool fault, write_fault;
@@ -474,23 +474,32 @@ static int hmm_vma_walk_pud(pud_t *pudp, unsigned long start, unsigned long end,
 {
        struct hmm_vma_walk *hmm_vma_walk = walk->private;
        struct hmm_range *range = hmm_vma_walk->range;
-       unsigned long addr = start, next;
-       pmd_t *pmdp;
+       unsigned long addr = start;
        pud_t pud;
-       int ret;
+       int ret = 0;
+       spinlock_t *ptl = pud_trans_huge_lock(pudp, walk->vma);
+
+       if (!ptl)
+               return 0;
+
+       /* Normally we don't want to split the huge page */
+       walk->action = ACTION_CONTINUE;
 
-again:
        pud = READ_ONCE(*pudp);
-       if (pud_none(pud))
-               return hmm_vma_walk_hole(start, end, walk);
+       if (pud_none(pud)) {
+               ret = hmm_vma_walk_hole(start, end, -1, walk);
+               goto out_unlock;
+       }
 
        if (pud_huge(pud) && pud_devmap(pud)) {
                unsigned long i, npages, pfn;
                uint64_t *pfns, cpu_flags;
                bool fault, write_fault;
 
-               if (!pud_present(pud))
-                       return hmm_vma_walk_hole(start, end, walk);
+               if (!pud_present(pud)) {
+                       ret = hmm_vma_walk_hole(start, end, -1, walk);
+                       goto out_unlock;
+               }
 
                i = (addr - range->start) >> PAGE_SHIFT;
                npages = (end - addr) >> PAGE_SHIFT;
@@ -499,16 +508,20 @@ again:
                cpu_flags = pud_to_hmm_pfn_flags(range, pud);
                hmm_range_need_fault(hmm_vma_walk, pfns, npages,
                                     cpu_flags, &fault, &write_fault);
-               if (fault || write_fault)
-                       return hmm_vma_walk_hole_(addr, end, fault,
-                                               write_fault, walk);
+               if (fault || write_fault) {
+                       ret = hmm_vma_walk_hole_(addr, end, fault,
+                                                write_fault, walk);
+                       goto out_unlock;
+               }
 
                pfn = pud_pfn(pud) + ((addr & ~PUD_MASK) >> PAGE_SHIFT);
                for (i = 0; i < npages; ++i, ++pfn) {
                        hmm_vma_walk->pgmap = get_dev_pagemap(pfn,
                                              hmm_vma_walk->pgmap);
-                       if (unlikely(!hmm_vma_walk->pgmap))
-                               return -EBUSY;
+                       if (unlikely(!hmm_vma_walk->pgmap)) {
+                               ret = -EBUSY;
+                               goto out_unlock;
+                       }
                        pfns[i] = hmm_device_entry_from_pfn(range, pfn) |
                                  cpu_flags;
                }
@@ -517,22 +530,15 @@ again:
                        hmm_vma_walk->pgmap = NULL;
                }
                hmm_vma_walk->last = end;
-               return 0;
+               goto out_unlock;
        }
 
-       split_huge_pud(walk->vma, pudp, addr);
-       if (pud_none(*pudp))
-               goto again;
+       /* Ask for the PUD to be split */
+       walk->action = ACTION_SUBTREE;
 
-       pmdp = pmd_offset(pudp, addr);
-       do {
-               next = pmd_addr_end(addr, end);
-               ret = hmm_vma_walk_pmd(pmdp, addr, next, walk);
-               if (ret)
-                       return ret;
-       } while (pmdp++, addr = next, addr != end);
-
-       return 0;
+out_unlock:
+       spin_unlock(ptl);
+       return ret;
 }
 #else
 #define hmm_vma_walk_pud       NULL
index 36d8091..0a54ffa 100644 (file)
@@ -355,7 +355,7 @@ static unsigned long find_smallest_section_pfn(int nid, struct zone *zone,
                if (unlikely(pfn_to_nid(start_pfn) != nid))
                        continue;
 
-               if (zone && zone != page_zone(pfn_to_page(start_pfn)))
+               if (zone != page_zone(pfn_to_page(start_pfn)))
                        continue;
 
                return start_pfn;
@@ -380,7 +380,7 @@ static unsigned long find_biggest_section_pfn(int nid, struct zone *zone,
                if (unlikely(pfn_to_nid(pfn) != nid))
                        continue;
 
-               if (zone && zone != page_zone(pfn_to_page(pfn)))
+               if (zone != page_zone(pfn_to_page(pfn)))
                        continue;
 
                return pfn;
@@ -392,14 +392,11 @@ static unsigned long find_biggest_section_pfn(int nid, struct zone *zone,
 static void shrink_zone_span(struct zone *zone, unsigned long start_pfn,
                             unsigned long end_pfn)
 {
-       unsigned long zone_start_pfn = zone->zone_start_pfn;
-       unsigned long z = zone_end_pfn(zone); /* zone_end_pfn namespace clash */
-       unsigned long zone_end_pfn = z;
        unsigned long pfn;
        int nid = zone_to_nid(zone);
 
        zone_span_writelock(zone);
-       if (zone_start_pfn == start_pfn) {
+       if (zone->zone_start_pfn == start_pfn) {
                /*
                 * If the section is smallest section in the zone, it need
                 * shrink zone->zone_start_pfn and zone->zone_spanned_pages.
@@ -407,50 +404,30 @@ static void shrink_zone_span(struct zone *zone, unsigned long start_pfn,
                 * for shrinking zone.
                 */
                pfn = find_smallest_section_pfn(nid, zone, end_pfn,
-                                               zone_end_pfn);
+                                               zone_end_pfn(zone));
                if (pfn) {
+                       zone->spanned_pages = zone_end_pfn(zone) - pfn;
                        zone->zone_start_pfn = pfn;
-                       zone->spanned_pages = zone_end_pfn - pfn;
+               } else {
+                       zone->zone_start_pfn = 0;
+                       zone->spanned_pages = 0;
                }
-       } else if (zone_end_pfn == end_pfn) {
+       } else if (zone_end_pfn(zone) == end_pfn) {
                /*
                 * If the section is biggest section in the zone, it need
                 * shrink zone->spanned_pages.
                 * In this case, we find second biggest valid mem_section for
                 * shrinking zone.
                 */
-               pfn = find_biggest_section_pfn(nid, zone, zone_start_pfn,
+               pfn = find_biggest_section_pfn(nid, zone, zone->zone_start_pfn,
                                               start_pfn);
                if (pfn)
-                       zone->spanned_pages = pfn - zone_start_pfn + 1;
-       }
-
-       /*
-        * The section is not biggest or smallest mem_section in the zone, it
-        * only creates a hole in the zone. So in this case, we need not
-        * change the zone. But perhaps, the zone has only hole data. Thus
-        * it check the zone has only hole or not.
-        */
-       pfn = zone_start_pfn;
-       for (; pfn < zone_end_pfn; pfn += PAGES_PER_SUBSECTION) {
-               if (unlikely(!pfn_to_online_page(pfn)))
-                       continue;
-
-               if (page_zone(pfn_to_page(pfn)) != zone)
-                       continue;
-
-               /* Skip range to be removed */
-               if (pfn >= start_pfn && pfn < end_pfn)
-                       continue;
-
-               /* If we find valid section, we have nothing to do */
-               zone_span_writeunlock(zone);
-               return;
+                       zone->spanned_pages = pfn - zone->zone_start_pfn + 1;
+               else {
+                       zone->zone_start_pfn = 0;
+                       zone->spanned_pages = 0;
+               }
        }
-
-       /* The zone has no valid section */
-       zone->zone_start_pfn = 0;
-       zone->spanned_pages = 0;
        zone_span_writeunlock(zone);
 }
 
@@ -490,6 +467,9 @@ void __ref remove_pfn_range_from_zone(struct zone *zone,
        struct pglist_data *pgdat = zone->zone_pgdat;
        unsigned long flags;
 
+       /* Poison struct pages because they are now uninitialized again. */
+       page_init_poison(pfn_to_page(start_pfn), sizeof(struct page) * nr_pages);
+
 #ifdef CONFIG_ZONE_DEVICE
        /*
         * Zone shrinking code cannot properly deal with ZONE_DEVICE. So
@@ -536,25 +516,20 @@ static void __remove_section(unsigned long pfn, unsigned long nr_pages,
 void __remove_pages(unsigned long pfn, unsigned long nr_pages,
                    struct vmem_altmap *altmap)
 {
+       const unsigned long end_pfn = pfn + nr_pages;
+       unsigned long cur_nr_pages;
        unsigned long map_offset = 0;
-       unsigned long nr, start_sec, end_sec;
 
        map_offset = vmem_altmap_offset(altmap);
 
        if (check_pfn_span(pfn, nr_pages, "remove"))
                return;
 
-       start_sec = pfn_to_section_nr(pfn);
-       end_sec = pfn_to_section_nr(pfn + nr_pages - 1);
-       for (nr = start_sec; nr <= end_sec; nr++) {
-               unsigned long pfns;
-
+       for (; pfn < end_pfn; pfn += cur_nr_pages) {
                cond_resched();
-               pfns = min(nr_pages, PAGES_PER_SECTION
-                               - (pfn & ~PAGE_SECTION_MASK));
-               __remove_section(pfn, pfns, map_offset, altmap);
-               pfn += pfns;
-               nr_pages -= pfns;
+               /* Select all remaining pages up to the next section boundary */
+               cur_nr_pages = min(end_pfn - pfn, -(pfn | PAGE_SECTION_MASK));
+               __remove_section(pfn, cur_nr_pages, map_offset, altmap);
                map_offset = 0;
        }
 }
@@ -1197,14 +1172,13 @@ bool is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages)
 }
 
 /*
- * Confirm all pages in a range [start, end) belong to the same zone.
- * When true, return its valid [start, end).
+ * Confirm all pages in a range [start, end) belong to the same zone (skipping
+ * memory holes). When true, return the zone.
  */
-int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
-                        unsigned long *valid_start, unsigned long *valid_end)
+struct zone *test_pages_in_a_zone(unsigned long start_pfn,
+                                 unsigned long end_pfn)
 {
        unsigned long pfn, sec_end_pfn;
-       unsigned long start, end;
        struct zone *zone = NULL;
        struct page *page;
        int i;
@@ -1225,24 +1199,15 @@ int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
                                continue;
                        /* Check if we got outside of the zone */
                        if (zone && !zone_spans_pfn(zone, pfn + i))
-                               return 0;
+                               return NULL;
                        page = pfn_to_page(pfn + i);
                        if (zone && page_zone(page) != zone)
-                               return 0;
-                       if (!zone)
-                               start = pfn + i;
+                               return NULL;
                        zone = page_zone(page);
-                       end = pfn + MAX_ORDER_NR_PAGES;
                }
        }
 
-       if (zone) {
-               *valid_start = start;
-               *valid_end = min(end, end_pfn);
-               return 1;
-       } else {
-               return 0;
-       }
+       return zone;
 }
 
 /*
@@ -1487,7 +1452,6 @@ static int __ref __offline_pages(unsigned long start_pfn,
        unsigned long offlined_pages = 0;
        int ret, node, nr_isolate_pageblock;
        unsigned long flags;
-       unsigned long valid_start, valid_end;
        struct zone *zone;
        struct memory_notify arg;
        char *reason;
@@ -1512,14 +1476,12 @@ static int __ref __offline_pages(unsigned long start_pfn,
 
        /* This makes hotplug much easier...and readable.
           we assume this for now. .*/
-       if (!test_pages_in_a_zone(start_pfn, end_pfn, &valid_start,
-                                 &valid_end)) {
+       zone = test_pages_in_a_zone(start_pfn, end_pfn);
+       if (!zone) {
                ret = -EINVAL;
                reason = "multizone range";
                goto failed_removal;
        }
-
-       zone = page_zone(pfn_to_page(valid_start));
        node = zone_to_nid(zone);
 
        /* set above range as isolated */
index 4c723d2..09b5b7a 100644 (file)
@@ -120,6 +120,8 @@ void memunmap_pages(struct dev_pagemap *pgmap)
        nid = page_to_nid(first_page);
 
        mem_hotplug_begin();
+       remove_pfn_range_from_zone(page_zone(first_page), PHYS_PFN(res->start),
+                                  PHYS_PFN(resource_size(res)));
        if (pgmap->type == MEMORY_DEVICE_PRIVATE) {
                __remove_pages(PHYS_PFN(res->start),
                               PHYS_PFN(resource_size(res)), NULL);
index edf42ed..b109287 100644 (file)
@@ -2151,6 +2151,7 @@ out_unlock:
 #ifdef CONFIG_DEVICE_PRIVATE
 static int migrate_vma_collect_hole(unsigned long start,
                                    unsigned long end,
+                                   __always_unused int depth,
                                    struct mm_walk *walk)
 {
        struct migrate_vma *migrate = walk->private;
@@ -2195,7 +2196,7 @@ static int migrate_vma_collect_pmd(pmd_t *pmdp,
 
 again:
        if (pmd_none(*pmdp))
-               return migrate_vma_collect_hole(start, end, walk);
+               return migrate_vma_collect_hole(start, end, -1, walk);
 
        if (pmd_trans_huge(*pmdp)) {
                struct page *page;
@@ -2228,7 +2229,7 @@ again:
                                return migrate_vma_collect_skip(start, end,
                                                                walk);
                        if (pmd_none(*pmdp))
-                               return migrate_vma_collect_hole(start, end,
+                               return migrate_vma_collect_hole(start, end, -1,
                                                                walk);
                }
        }
index 49b6fa2..0e6dd99 100644 (file)
@@ -112,6 +112,7 @@ static int __mincore_unmapped_range(unsigned long addr, unsigned long end,
 }
 
 static int mincore_unmapped_range(unsigned long addr, unsigned long end,
+                                  __always_unused int depth,
                                   struct mm_walk *walk)
 {
        walk->private += __mincore_unmapped_range(addr, end,
index 7d70e5c..a3538cb 100644 (file)
@@ -11,7 +11,7 @@
 #include <asm/pgalloc.h>
 #include <asm/tlb.h>
 
-#ifndef CONFIG_HAVE_MMU_GATHER_NO_GATHER
+#ifndef CONFIG_MMU_GATHER_NO_GATHER
 
 static bool tlb_next_batch(struct mmu_gather *tlb)
 {
@@ -69,7 +69,7 @@ bool __tlb_remove_page_size(struct mmu_gather *tlb, struct page *page, int page_
 
        VM_BUG_ON(!tlb->end);
 
-#ifdef CONFIG_HAVE_MMU_GATHER_PAGE_SIZE
+#ifdef CONFIG_MMU_GATHER_PAGE_SIZE
        VM_WARN_ON(tlb->page_size != page_size);
 #endif
 
@@ -89,58 +89,108 @@ bool __tlb_remove_page_size(struct mmu_gather *tlb, struct page *page, int page_
        return false;
 }
 
-#endif /* HAVE_MMU_GATHER_NO_GATHER */
+#endif /* MMU_GATHER_NO_GATHER */
 
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
+#ifdef CONFIG_MMU_GATHER_TABLE_FREE
 
-/*
- * See the comment near struct mmu_table_batch.
- */
+static void __tlb_remove_table_free(struct mmu_table_batch *batch)
+{
+       int i;
+
+       for (i = 0; i < batch->nr; i++)
+               __tlb_remove_table(batch->tables[i]);
+
+       free_page((unsigned long)batch);
+}
+
+#ifdef CONFIG_MMU_GATHER_RCU_TABLE_FREE
 
 /*
- * If we want tlb_remove_table() to imply TLB invalidates.
+ * Semi RCU freeing of the page directories.
+ *
+ * This is needed by some architectures to implement software pagetable walkers.
+ *
+ * gup_fast() and other software pagetable walkers do a lockless page-table
+ * walk and therefore needs some synchronization with the freeing of the page
+ * directories. The chosen means to accomplish that is by disabling IRQs over
+ * the walk.
+ *
+ * Architectures that use IPIs to flush TLBs will then automagically DTRT,
+ * since we unlink the page, flush TLBs, free the page. Since the disabling of
+ * IRQs delays the completion of the TLB flush we can never observe an already
+ * freed page.
+ *
+ * Architectures that do not have this (PPC) need to delay the freeing by some
+ * other means, this is that means.
+ *
+ * What we do is batch the freed directory pages (tables) and RCU free them.
+ * We use the sched RCU variant, as that guarantees that IRQ/preempt disabling
+ * holds off grace periods.
+ *
+ * However, in order to batch these pages we need to allocate storage, this
+ * allocation is deep inside the MM code and can thus easily fail on memory
+ * pressure. To guarantee progress we fall back to single table freeing, see
+ * the implementation of tlb_remove_table_one().
+ *
  */
-static inline void tlb_table_invalidate(struct mmu_gather *tlb)
-{
-#ifndef CONFIG_HAVE_RCU_TABLE_NO_INVALIDATE
-       /*
-        * Invalidate page-table caches used by hardware walkers. Then we still
-        * need to RCU-sched wait while freeing the pages because software
-        * walkers can still be in-flight.
-        */
-       tlb_flush_mmu_tlbonly(tlb);
-#endif
-}
 
 static void tlb_remove_table_smp_sync(void *arg)
 {
        /* Simply deliver the interrupt */
 }
 
-static void tlb_remove_table_one(void *table)
+static void tlb_remove_table_sync_one(void)
 {
        /*
         * This isn't an RCU grace period and hence the page-tables cannot be
         * assumed to be actually RCU-freed.
         *
         * It is however sufficient for software page-table walkers that rely on
-        * IRQ disabling. See the comment near struct mmu_table_batch.
+        * IRQ disabling.
         */
        smp_call_function(tlb_remove_table_smp_sync, NULL, 1);
-       __tlb_remove_table(table);
 }
 
 static void tlb_remove_table_rcu(struct rcu_head *head)
 {
-       struct mmu_table_batch *batch;
-       int i;
+       __tlb_remove_table_free(container_of(head, struct mmu_table_batch, rcu));
+}
+
+static void tlb_remove_table_free(struct mmu_table_batch *batch)
+{
+       call_rcu(&batch->rcu, tlb_remove_table_rcu);
+}
 
-       batch = container_of(head, struct mmu_table_batch, rcu);
+#else /* !CONFIG_MMU_GATHER_RCU_TABLE_FREE */
 
-       for (i = 0; i < batch->nr; i++)
-               __tlb_remove_table(batch->tables[i]);
+static void tlb_remove_table_sync_one(void) { }
 
-       free_page((unsigned long)batch);
+static void tlb_remove_table_free(struct mmu_table_batch *batch)
+{
+       __tlb_remove_table_free(batch);
+}
+
+#endif /* CONFIG_MMU_GATHER_RCU_TABLE_FREE */
+
+/*
+ * If we want tlb_remove_table() to imply TLB invalidates.
+ */
+static inline void tlb_table_invalidate(struct mmu_gather *tlb)
+{
+       if (tlb_needs_table_invalidate()) {
+               /*
+                * Invalidate page-table caches used by hardware walkers. Then
+                * we still need to RCU-sched wait while freeing the pages
+                * because software walkers can still be in-flight.
+                */
+               tlb_flush_mmu_tlbonly(tlb);
+       }
+}
+
+static void tlb_remove_table_one(void *table)
+{
+       tlb_remove_table_sync_one();
+       __tlb_remove_table(table);
 }
 
 static void tlb_table_flush(struct mmu_gather *tlb)
@@ -149,7 +199,7 @@ static void tlb_table_flush(struct mmu_gather *tlb)
 
        if (*batch) {
                tlb_table_invalidate(tlb);
-               call_rcu(&(*batch)->rcu, tlb_remove_table_rcu);
+               tlb_remove_table_free(*batch);
                *batch = NULL;
        }
 }
@@ -173,14 +223,22 @@ void tlb_remove_table(struct mmu_gather *tlb, void *table)
                tlb_table_flush(tlb);
 }
 
-#endif /* CONFIG_HAVE_RCU_TABLE_FREE */
+static inline void tlb_table_init(struct mmu_gather *tlb)
+{
+       tlb->batch = NULL;
+}
+
+#else /* !CONFIG_MMU_GATHER_TABLE_FREE */
+
+static inline void tlb_table_flush(struct mmu_gather *tlb) { }
+static inline void tlb_table_init(struct mmu_gather *tlb) { }
+
+#endif /* CONFIG_MMU_GATHER_TABLE_FREE */
 
 static void tlb_flush_mmu_free(struct mmu_gather *tlb)
 {
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
        tlb_table_flush(tlb);
-#endif
-#ifndef CONFIG_HAVE_MMU_GATHER_NO_GATHER
+#ifndef CONFIG_MMU_GATHER_NO_GATHER
        tlb_batch_pages_flush(tlb);
 #endif
 }
@@ -211,7 +269,7 @@ void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm,
        /* Is it from 0 to ~0? */
        tlb->fullmm     = !(start | (end+1));
 
-#ifndef CONFIG_HAVE_MMU_GATHER_NO_GATHER
+#ifndef CONFIG_MMU_GATHER_NO_GATHER
        tlb->need_flush_all = 0;
        tlb->local.next = NULL;
        tlb->local.nr   = 0;
@@ -220,10 +278,8 @@ void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm,
        tlb->batch_count = 0;
 #endif
 
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
-       tlb->batch = NULL;
-#endif
-#ifdef CONFIG_HAVE_MMU_GATHER_PAGE_SIZE
+       tlb_table_init(tlb);
+#ifdef CONFIG_MMU_GATHER_PAGE_SIZE
        tlb->page_size = 0;
 #endif
 
@@ -271,7 +327,7 @@ void tlb_finish_mmu(struct mmu_gather *tlb,
 
        tlb_flush_mmu(tlb);
 
-#ifndef CONFIG_HAVE_MMU_GATHER_NO_GATHER
+#ifndef CONFIG_MMU_GATHER_NO_GATHER
        tlb_batch_list_free(tlb);
 #endif
        dec_tlb_flush_pending(tlb->mm);
index 15e908a..3c4eb75 100644 (file)
@@ -5852,18 +5852,11 @@ overlap_memmap_init(unsigned long zone, unsigned long *pfn)
 /* Skip PFNs that belong to non-present sections */
 static inline __meminit unsigned long next_pfn(unsigned long pfn)
 {
-       unsigned long section_nr;
+       const unsigned long section_nr = pfn_to_section_nr(++pfn);
 
-       section_nr = pfn_to_section_nr(++pfn);
        if (present_section_nr(section_nr))
                return pfn;
-
-       while (++section_nr <= __highest_present_section_nr) {
-               if (present_section_nr(section_nr))
-                       return section_nr_to_pfn(section_nr);
-       }
-
-       return -1;
+       return section_nr_to_pfn(next_present_section_nr(section_nr));
 }
 #else
 static inline __meminit unsigned long next_pfn(unsigned long pfn)
@@ -5905,18 +5898,20 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
        }
 #endif
 
-       for (pfn = start_pfn; pfn < end_pfn; pfn++) {
+       for (pfn = start_pfn; pfn < end_pfn; ) {
                /*
                 * There can be holes in boot-time mem_map[]s handed to this
                 * function.  They do not exist on hotplugged memory.
                 */
                if (context == MEMMAP_EARLY) {
                        if (!early_pfn_valid(pfn)) {
-                               pfn = next_pfn(pfn) - 1;
+                               pfn = next_pfn(pfn);
                                continue;
                        }
-                       if (!early_pfn_in_nid(pfn, nid))
+                       if (!early_pfn_in_nid(pfn, nid)) {
+                               pfn++;
                                continue;
+                       }
                        if (overlap_memmap_init(zone, &pfn))
                                continue;
                        if (defer_init(nid, pfn, end_pfn))
@@ -5944,16 +5939,17 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
                        set_pageblock_migratetype(page, MIGRATE_MOVABLE);
                        cond_resched();
                }
+               pfn++;
        }
 }
 
 #ifdef CONFIG_ZONE_DEVICE
 void __ref memmap_init_zone_device(struct zone *zone,
                                   unsigned long start_pfn,
-                                  unsigned long size,
+                                  unsigned long nr_pages,
                                   struct dev_pagemap *pgmap)
 {
-       unsigned long pfn, end_pfn = start_pfn + size;
+       unsigned long pfn, end_pfn = start_pfn + nr_pages;
        struct pglist_data *pgdat = zone->zone_pgdat;
        struct vmem_altmap *altmap = pgmap_altmap(pgmap);
        unsigned long zone_idx = zone_idx(zone);
@@ -5970,7 +5966,7 @@ void __ref memmap_init_zone_device(struct zone *zone,
         */
        if (altmap) {
                start_pfn = altmap->base_pfn + vmem_altmap_offset(altmap);
-               size = end_pfn - start_pfn;
+               nr_pages = end_pfn - start_pfn;
        }
 
        for (pfn = start_pfn; pfn < end_pfn; pfn++) {
@@ -6017,7 +6013,7 @@ void __ref memmap_init_zone_device(struct zone *zone,
        }
 
        pr_info("%s initialised %lu pages in %ums\n", __func__,
-               size, jiffies_to_msecs(jiffies - start));
+               nr_pages, jiffies_to_msecs(jiffies - start));
 }
 
 #endif
@@ -6916,10 +6912,10 @@ void __init free_area_init_node(int nid, unsigned long *zones_size,
 
 #if !defined(CONFIG_FLAT_NODE_MEM_MAP)
 /*
- * Zero all valid struct pages in range [spfn, epfn), return number of struct
- * pages zeroed
+ * Initialize all valid struct pages in the range [spfn, epfn) and mark them
+ * PageReserved(). Return the number of struct pages that were initialized.
  */
-static u64 zero_pfn_range(unsigned long spfn, unsigned long epfn)
+static u64 __init init_unavailable_range(unsigned long spfn, unsigned long epfn)
 {
        unsigned long pfn;
        u64 pgcnt = 0;
@@ -6930,7 +6926,13 @@ static u64 zero_pfn_range(unsigned long spfn, unsigned long epfn)
                                + pageblock_nr_pages - 1;
                        continue;
                }
-               mm_zero_struct_page(pfn_to_page(pfn));
+               /*
+                * Use a fake node/zone (0) for now. Some of these pages
+                * (in memblock.reserved but not in memblock.memory) will
+                * get re-initialized via reserve_bootmem_region() later.
+                */
+               __init_single_page(pfn_to_page(pfn), pfn, 0, 0);
+               __SetPageReserved(pfn_to_page(pfn));
                pgcnt++;
        }
 
@@ -6942,14 +6944,15 @@ static u64 zero_pfn_range(unsigned long spfn, unsigned long epfn)
  * initialized by going through __init_single_page(). But, there are some
  * struct pages which are reserved in memblock allocator and their fields
  * may be accessed (for example page_to_pfn() on some configuration accesses
- * flags). We must explicitly zero those struct pages.
+ * flags). We must explicitly initialize those struct pages.
  *
  * This function also addresses a similar issue where struct pages are left
  * uninitialized because the physical address range is not covered by
  * memblock.memory or memblock.reserved. That could happen when memblock
- * layout is manually configured via memmap=.
+ * layout is manually configured via memmap=, or when the highest physical
+ * address (max_pfn) does not end on a section boundary.
  */
-void __init zero_resv_unavail(void)
+static void __init init_unavailable_mem(void)
 {
        phys_addr_t start, end;
        u64 i, pgcnt;
@@ -6962,10 +6965,20 @@ void __init zero_resv_unavail(void)
        for_each_mem_range(i, &memblock.memory, NULL,
                        NUMA_NO_NODE, MEMBLOCK_NONE, &start, &end, NULL) {
                if (next < start)
-                       pgcnt += zero_pfn_range(PFN_DOWN(next), PFN_UP(start));
+                       pgcnt += init_unavailable_range(PFN_DOWN(next),
+                                                       PFN_UP(start));
                next = end;
        }
-       pgcnt += zero_pfn_range(PFN_DOWN(next), max_pfn);
+
+       /*
+        * Early sections always have a fully populated memmap for the whole
+        * section - see pfn_valid(). If the last section has holes at the
+        * end and that section is marked "online", the memmap will be
+        * considered initialized. Make sure that memmap has a well defined
+        * state.
+        */
+       pgcnt += init_unavailable_range(PFN_DOWN(next),
+                                       round_up(max_pfn, PAGES_PER_SECTION));
 
        /*
         * Struct pages that do not have backing memory. This could be because
@@ -6974,6 +6987,10 @@ void __init zero_resv_unavail(void)
        if (pgcnt)
                pr_info("Zeroed struct page in unavailable ranges: %lld pages", pgcnt);
 }
+#else
+static inline void __init init_unavailable_mem(void)
+{
+}
 #endif /* !CONFIG_FLAT_NODE_MEM_MAP */
 
 #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
@@ -7403,7 +7420,7 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn)
        /* Initialise every node */
        mminit_verify_pageflags_layout();
        setup_nr_node_ids();
-       zero_resv_unavail();
+       init_unavailable_mem();
        for_each_online_node(nid) {
                pg_data_t *pgdat = NODE_DATA(nid);
                free_area_init_node(nid, NULL,
@@ -7598,7 +7615,7 @@ void __init set_dma_reserve(unsigned long new_dma_reserve)
 
 void __init free_area_init(unsigned long *zones_size)
 {
-       zero_resv_unavail();
+       init_unavailable_mem();
        free_area_init_node(0, zones_size,
                        __pa(PAGE_OFFSET) >> PAGE_SHIFT, NULL);
 }
index ea0b9e6..928df16 100644 (file)
@@ -4,26 +4,57 @@
 #include <linux/sched.h>
 #include <linux/hugetlb.h>
 
-static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
-                         struct mm_walk *walk)
+/*
+ * We want to know the real level where a entry is located ignoring any
+ * folding of levels which may be happening. For example if p4d is folded then
+ * a missing entry found at level 1 (p4d) is actually at level 0 (pgd).
+ */
+static int real_depth(int depth)
+{
+       if (depth == 3 && PTRS_PER_PMD == 1)
+               depth = 2;
+       if (depth == 2 && PTRS_PER_PUD == 1)
+               depth = 1;
+       if (depth == 1 && PTRS_PER_P4D == 1)
+               depth = 0;
+       return depth;
+}
+
+static int walk_pte_range_inner(pte_t *pte, unsigned long addr,
+                               unsigned long end, struct mm_walk *walk)
 {
-       pte_t *pte;
-       int err = 0;
        const struct mm_walk_ops *ops = walk->ops;
-       spinlock_t *ptl;
+       int err = 0;
 
-       pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
        for (;;) {
                err = ops->pte_entry(pte, addr, addr + PAGE_SIZE, walk);
                if (err)
                       break;
-               addr += PAGE_SIZE;
-               if (addr == end)
+               if (addr >= end - PAGE_SIZE)
                        break;
+               addr += PAGE_SIZE;
                pte++;
        }
+       return err;
+}
+
+static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
+                         struct mm_walk *walk)
+{
+       pte_t *pte;
+       int err = 0;
+       spinlock_t *ptl;
+
+       if (walk->no_vma) {
+               pte = pte_offset_map(pmd, addr);
+               err = walk_pte_range_inner(pte, addr, end, walk);
+               pte_unmap(pte);
+       } else {
+               pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
+               err = walk_pte_range_inner(pte, addr, end, walk);
+               pte_unmap_unlock(pte, ptl);
+       }
 
-       pte_unmap_unlock(pte, ptl);
        return err;
 }
 
@@ -34,18 +65,22 @@ static int walk_pmd_range(pud_t *pud, unsigned long addr, unsigned long end,
        unsigned long next;
        const struct mm_walk_ops *ops = walk->ops;
        int err = 0;
+       int depth = real_depth(3);
 
        pmd = pmd_offset(pud, addr);
        do {
 again:
                next = pmd_addr_end(addr, end);
-               if (pmd_none(*pmd) || !walk->vma) {
+               if (pmd_none(*pmd) || (!walk->vma && !walk->no_vma)) {
                        if (ops->pte_hole)
-                               err = ops->pte_hole(addr, next, walk);
+                               err = ops->pte_hole(addr, next, depth, walk);
                        if (err)
                                break;
                        continue;
                }
+
+               walk->action = ACTION_SUBTREE;
+
                /*
                 * This implies that each ->pmd_entry() handler
                 * needs to know about pmd_trans_huge() pmds
@@ -55,16 +90,24 @@ again:
                if (err)
                        break;
 
+               if (walk->action == ACTION_AGAIN)
+                       goto again;
+
                /*
                 * Check this here so we only break down trans_huge
                 * pages when we _need_ to
                 */
-               if (!ops->pte_entry)
+               if ((!walk->vma && (pmd_leaf(*pmd) || !pmd_present(*pmd))) ||
+                   walk->action == ACTION_CONTINUE ||
+                   !(ops->pte_entry))
                        continue;
 
-               split_huge_pmd(walk->vma, pmd, addr);
-               if (pmd_trans_unstable(pmd))
-                       goto again;
+               if (walk->vma) {
+                       split_huge_pmd(walk->vma, pmd, addr);
+                       if (pmd_trans_unstable(pmd))
+                               goto again;
+               }
+
                err = walk_pte_range(pmd, addr, next, walk);
                if (err)
                        break;
@@ -80,37 +123,41 @@ static int walk_pud_range(p4d_t *p4d, unsigned long addr, unsigned long end,
        unsigned long next;
        const struct mm_walk_ops *ops = walk->ops;
        int err = 0;
+       int depth = real_depth(2);
 
        pud = pud_offset(p4d, addr);
        do {
  again:
                next = pud_addr_end(addr, end);
-               if (pud_none(*pud) || !walk->vma) {
+               if (pud_none(*pud) || (!walk->vma && !walk->no_vma)) {
                        if (ops->pte_hole)
-                               err = ops->pte_hole(addr, next, walk);
+                               err = ops->pte_hole(addr, next, depth, walk);
                        if (err)
                                break;
                        continue;
                }
 
-               if (ops->pud_entry) {
-                       spinlock_t *ptl = pud_trans_huge_lock(pud, walk->vma);
+               walk->action = ACTION_SUBTREE;
 
-                       if (ptl) {
-                               err = ops->pud_entry(pud, addr, next, walk);
-                               spin_unlock(ptl);
-                               if (err)
-                                       break;
-                               continue;
-                       }
-               }
+               if (ops->pud_entry)
+                       err = ops->pud_entry(pud, addr, next, walk);
+               if (err)
+                       break;
+
+               if (walk->action == ACTION_AGAIN)
+                       goto again;
 
-               split_huge_pud(walk->vma, pud, addr);
+               if ((!walk->vma && (pud_leaf(*pud) || !pud_present(*pud))) ||
+                   walk->action == ACTION_CONTINUE ||
+                   !(ops->pmd_entry || ops->pte_entry))
+                       continue;
+
+               if (walk->vma)
+                       split_huge_pud(walk->vma, pud, addr);
                if (pud_none(*pud))
                        goto again;
 
-               if (ops->pmd_entry || ops->pte_entry)
-                       err = walk_pmd_range(pud, addr, next, walk);
+               err = walk_pmd_range(pud, addr, next, walk);
                if (err)
                        break;
        } while (pud++, addr = next, addr != end);
@@ -125,18 +172,24 @@ static int walk_p4d_range(pgd_t *pgd, unsigned long addr, unsigned long end,
        unsigned long next;
        const struct mm_walk_ops *ops = walk->ops;
        int err = 0;
+       int depth = real_depth(1);
 
        p4d = p4d_offset(pgd, addr);
        do {
                next = p4d_addr_end(addr, end);
                if (p4d_none_or_clear_bad(p4d)) {
                        if (ops->pte_hole)
-                               err = ops->pte_hole(addr, next, walk);
+                               err = ops->pte_hole(addr, next, depth, walk);
                        if (err)
                                break;
                        continue;
                }
-               if (ops->pmd_entry || ops->pte_entry)
+               if (ops->p4d_entry) {
+                       err = ops->p4d_entry(p4d, addr, next, walk);
+                       if (err)
+                               break;
+               }
+               if (ops->pud_entry || ops->pmd_entry || ops->pte_entry)
                        err = walk_pud_range(p4d, addr, next, walk);
                if (err)
                        break;
@@ -153,17 +206,26 @@ static int walk_pgd_range(unsigned long addr, unsigned long end,
        const struct mm_walk_ops *ops = walk->ops;
        int err = 0;
 
-       pgd = pgd_offset(walk->mm, addr);
+       if (walk->pgd)
+               pgd = walk->pgd + pgd_index(addr);
+       else
+               pgd = pgd_offset(walk->mm, addr);
        do {
                next = pgd_addr_end(addr, end);
                if (pgd_none_or_clear_bad(pgd)) {
                        if (ops->pte_hole)
-                               err = ops->pte_hole(addr, next, walk);
+                               err = ops->pte_hole(addr, next, 0, walk);
                        if (err)
                                break;
                        continue;
                }
-               if (ops->pmd_entry || ops->pte_entry)
+               if (ops->pgd_entry) {
+                       err = ops->pgd_entry(pgd, addr, next, walk);
+                       if (err)
+                               break;
+               }
+               if (ops->p4d_entry || ops->pud_entry || ops->pmd_entry ||
+                   ops->pte_entry)
                        err = walk_p4d_range(pgd, addr, next, walk);
                if (err)
                        break;
@@ -199,7 +261,7 @@ static int walk_hugetlb_range(unsigned long addr, unsigned long end,
                if (pte)
                        err = ops->hugetlb_entry(pte, hmask, addr, next, walk);
                else if (ops->pte_hole)
-                       err = ops->pte_hole(addr, next, walk);
+                       err = ops->pte_hole(addr, next, -1, walk);
 
                if (err)
                        break;
@@ -243,7 +305,7 @@ static int walk_page_test(unsigned long start, unsigned long end,
        if (vma->vm_flags & VM_PFNMAP) {
                int err = 1;
                if (ops->pte_hole)
-                       err = ops->pte_hole(start, end, walk);
+                       err = ops->pte_hole(start, end, -1, walk);
                return err ? err : 1;
        }
        return 0;
@@ -369,6 +431,33 @@ int walk_page_range(struct mm_struct *mm, unsigned long start,
        return err;
 }
 
+/*
+ * Similar to walk_page_range() but can walk any page tables even if they are
+ * not backed by VMAs. Because 'unusual' entries may be walked this function
+ * will also not lock the PTEs for the pte_entry() callback. This is useful for
+ * walking the kernel pages tables or page tables for firmware.
+ */
+int walk_page_range_novma(struct mm_struct *mm, unsigned long start,
+                         unsigned long end, const struct mm_walk_ops *ops,
+                         pgd_t *pgd,
+                         void *private)
+{
+       struct mm_walk walk = {
+               .ops            = ops,
+               .mm             = mm,
+               .pgd            = pgd,
+               .private        = private,
+               .no_vma         = true
+       };
+
+       if (start >= end || !walk.mm)
+               return -EINVAL;
+
+       lockdep_assert_held(&walk.mm->mmap_sem);
+
+       return __walk_page_range(start, end, &walk);
+}
+
 int walk_page_vma(struct vm_area_struct *vma, const struct mm_walk_ops *ops,
                void *private)
 {
diff --git a/mm/ptdump.c b/mm/ptdump.c
new file mode 100644 (file)
index 0000000..26208d0
--- /dev/null
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/pagewalk.h>
+#include <linux/ptdump.h>
+#include <linux/kasan.h>
+
+#ifdef CONFIG_KASAN
+/*
+ * This is an optimization for KASAN=y case. Since all kasan page tables
+ * eventually point to the kasan_early_shadow_page we could call note_page()
+ * right away without walking through lower level page tables. This saves
+ * us dozens of seconds (minutes for 5-level config) while checking for
+ * W+X mapping or reading kernel_page_tables debugfs file.
+ */
+static inline int note_kasan_page_table(struct mm_walk *walk,
+                                       unsigned long addr)
+{
+       struct ptdump_state *st = walk->private;
+
+       st->note_page(st, addr, 4, pte_val(kasan_early_shadow_pte[0]));
+
+       walk->action = ACTION_CONTINUE;
+
+       return 0;
+}
+#endif
+
+static int ptdump_pgd_entry(pgd_t *pgd, unsigned long addr,
+                           unsigned long next, struct mm_walk *walk)
+{
+       struct ptdump_state *st = walk->private;
+       pgd_t val = READ_ONCE(*pgd);
+
+#if CONFIG_PGTABLE_LEVELS > 4 && defined(CONFIG_KASAN)
+       if (pgd_page(val) == virt_to_page(lm_alias(kasan_early_shadow_p4d)))
+               return note_kasan_page_table(walk, addr);
+#endif
+
+       if (pgd_leaf(val))
+               st->note_page(st, addr, 0, pgd_val(val));
+
+       return 0;
+}
+
+static int ptdump_p4d_entry(p4d_t *p4d, unsigned long addr,
+                           unsigned long next, struct mm_walk *walk)
+{
+       struct ptdump_state *st = walk->private;
+       p4d_t val = READ_ONCE(*p4d);
+
+#if CONFIG_PGTABLE_LEVELS > 3 && defined(CONFIG_KASAN)
+       if (p4d_page(val) == virt_to_page(lm_alias(kasan_early_shadow_pud)))
+               return note_kasan_page_table(walk, addr);
+#endif
+
+       if (p4d_leaf(val))
+               st->note_page(st, addr, 1, p4d_val(val));
+
+       return 0;
+}
+
+static int ptdump_pud_entry(pud_t *pud, unsigned long addr,
+                           unsigned long next, struct mm_walk *walk)
+{
+       struct ptdump_state *st = walk->private;
+       pud_t val = READ_ONCE(*pud);
+
+#if CONFIG_PGTABLE_LEVELS > 2 && defined(CONFIG_KASAN)
+       if (pud_page(val) == virt_to_page(lm_alias(kasan_early_shadow_pmd)))
+               return note_kasan_page_table(walk, addr);
+#endif
+
+       if (pud_leaf(val))
+               st->note_page(st, addr, 2, pud_val(val));
+
+       return 0;
+}
+
+static int ptdump_pmd_entry(pmd_t *pmd, unsigned long addr,
+                           unsigned long next, struct mm_walk *walk)
+{
+       struct ptdump_state *st = walk->private;
+       pmd_t val = READ_ONCE(*pmd);
+
+#if defined(CONFIG_KASAN)
+       if (pmd_page(val) == virt_to_page(lm_alias(kasan_early_shadow_pte)))
+               return note_kasan_page_table(walk, addr);
+#endif
+
+       if (pmd_leaf(val))
+               st->note_page(st, addr, 3, pmd_val(val));
+
+       return 0;
+}
+
+static int ptdump_pte_entry(pte_t *pte, unsigned long addr,
+                           unsigned long next, struct mm_walk *walk)
+{
+       struct ptdump_state *st = walk->private;
+
+       st->note_page(st, addr, 4, pte_val(READ_ONCE(*pte)));
+
+       return 0;
+}
+
+static int ptdump_hole(unsigned long addr, unsigned long next,
+                      int depth, struct mm_walk *walk)
+{
+       struct ptdump_state *st = walk->private;
+
+       st->note_page(st, addr, depth, 0);
+
+       return 0;
+}
+
+static const struct mm_walk_ops ptdump_ops = {
+       .pgd_entry      = ptdump_pgd_entry,
+       .p4d_entry      = ptdump_p4d_entry,
+       .pud_entry      = ptdump_pud_entry,
+       .pmd_entry      = ptdump_pmd_entry,
+       .pte_entry      = ptdump_pte_entry,
+       .pte_hole       = ptdump_hole,
+};
+
+void ptdump_walk_pgd(struct ptdump_state *st, struct mm_struct *mm, pgd_t *pgd)
+{
+       const struct ptdump_range *range = st->range;
+
+       down_read(&mm->mmap_sem);
+       while (range->start != range->end) {
+               walk_page_range_novma(mm, range->start, range->end,
+                                     &ptdump_ops, pgd, st);
+               range++;
+       }
+       up_read(&mm->mmap_sem);
+
+       /* Flush out the last page */
+       st->note_page(st, 0, -1, 0);
+}
index 0d95dde..1907cb2 100644 (file)
@@ -1580,18 +1580,17 @@ static int slabinfo_open(struct inode *inode, struct file *file)
        return seq_open(file, &slabinfo_op);
 }
 
-static const struct file_operations proc_slabinfo_operations = {
-       .open           = slabinfo_open,
-       .read           = seq_read,
-       .write          = slabinfo_write,
-       .llseek         = seq_lseek,
-       .release        = seq_release,
+static const struct proc_ops slabinfo_proc_ops = {
+       .proc_open      = slabinfo_open,
+       .proc_read      = seq_read,
+       .proc_write     = slabinfo_write,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = seq_release,
 };
 
 static int __init slab_proc_init(void)
 {
-       proc_create("slabinfo", SLABINFO_RIGHTS, NULL,
-                                               &proc_slabinfo_operations);
+       proc_create("slabinfo", SLABINFO_RIGHTS, NULL, &slabinfo_proc_ops);
        return 0;
 }
 module_init(slab_proc_init);
@@ -1676,28 +1675,6 @@ static __always_inline void *__do_krealloc(const void *p, size_t new_size,
        return ret;
 }
 
-/**
- * __krealloc - like krealloc() but don't free @p.
- * @p: object to reallocate memory for.
- * @new_size: how many bytes of memory are required.
- * @flags: the type of memory to allocate.
- *
- * This function is like krealloc() except it never frees the originally
- * allocated buffer. Use this if you don't want to free the buffer immediately
- * like, for example, with RCU.
- *
- * Return: pointer to the allocated memory or %NULL in case of error
- */
-void *__krealloc(const void *p, size_t new_size, gfp_t flags)
-{
-       if (unlikely(!new_size))
-               return ZERO_SIZE_PTR;
-
-       return __do_krealloc(p, new_size, flags);
-
-}
-EXPORT_SYMBOL(__krealloc);
-
 /**
  * krealloc - reallocate memory. The contents will remain unchanged.
  * @p: object to reallocate memory for.
index 3918fc3..c184b69 100644 (file)
@@ -198,16 +198,6 @@ static void section_mark_present(struct mem_section *ms)
        ms->section_mem_map |= SECTION_MARKED_PRESENT;
 }
 
-static inline unsigned long next_present_section_nr(unsigned long section_nr)
-{
-       do {
-               section_nr++;
-               if (present_section_nr(section_nr))
-                       return section_nr;
-       } while ((section_nr <= __highest_present_section_nr));
-
-       return -1;
-}
 #define for_each_present_section_nr(start, section_nr)         \
        for (section_nr = next_present_section_nr(start-1);     \
             ((section_nr != -1) &&                             \
index 6febae9..2c33ff4 100644 (file)
@@ -2796,17 +2796,17 @@ static int swaps_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-static const struct file_operations proc_swaps_operations = {
-       .open           = swaps_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = seq_release,
-       .poll           = swaps_poll,
+static const struct proc_ops swaps_proc_ops = {
+       .proc_open      = swaps_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = seq_release,
+       .proc_poll      = swaps_poll,
 };
 
 static int __init procswaps_init(void)
 {
-       proc_create("swaps", 0, NULL, &proc_swaps_operations);
+       proc_create("swaps", 0, NULL, &swaps_proc_ops);
        return 0;
 }
 __initcall(procswaps_init);
index 46d6cd9..829db9e 100644 (file)
@@ -53,15 +53,12 @@ static ssize_t proc_mpc_write(struct file *file, const char __user *buff,
 
 static int parse_qos(const char *buff);
 
-/*
- *   Define allowed FILE OPERATIONS
- */
-static const struct file_operations mpc_file_operations = {
-       .open =         proc_mpc_open,
-       .read =         seq_read,
-       .llseek =       seq_lseek,
-       .write =        proc_mpc_write,
-       .release =      seq_release,
+static const struct proc_ops mpc_proc_ops = {
+       .proc_open      = proc_mpc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_write     = proc_mpc_write,
+       .proc_release   = seq_release,
 };
 
 /*
@@ -290,7 +287,7 @@ int mpc_proc_init(void)
 {
        struct proc_dir_entry *p;
 
-       p = proc_create(STAT_FILE_NAME, 0, atm_proc_root, &mpc_file_operations);
+       p = proc_create(STAT_FILE_NAME, 0, atm_proc_root, &mpc_proc_ops);
        if (!p) {
                pr_err("Unable to initialize /proc/atm/%s\n", STAT_FILE_NAME);
                return -ENOMEM;
index c318967..4369ffa 100644 (file)
@@ -36,9 +36,9 @@
 static ssize_t proc_dev_atm_read(struct file *file, char __user *buf,
                                 size_t count, loff_t *pos);
 
-static const struct file_operations proc_atm_dev_ops = {
-       .read =         proc_dev_atm_read,
-       .llseek =       noop_llseek,
+static const struct proc_ops atm_dev_proc_ops = {
+       .proc_read      = proc_dev_atm_read,
+       .proc_lseek     = noop_llseek,
 };
 
 static void add_stats(struct seq_file *seq, const char *aal,
@@ -359,7 +359,7 @@ int atm_proc_dev_register(struct atm_dev *dev)
                goto err_out;
 
        dev->proc_entry = proc_create_data(dev->proc_name, 0, atm_proc_root,
-                                          &proc_atm_dev_ops, dev);
+                                          &atm_dev_proc_ops, dev);
        if (!dev->proc_entry)
                goto err_free_name;
        return 0;
index 17529d4..a69e8bd 100644 (file)
@@ -5792,7 +5792,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
        if (&ptype->list == head)
                goto normal;
 
-       if (IS_ERR(pp) && PTR_ERR(pp) == -EINPROGRESS) {
+       if (PTR_ERR(pp) == -EINPROGRESS) {
                ret = GRO_CONSUMED;
                goto ok;
        }
index 792e374..c180871 100644 (file)
@@ -1573,7 +1573,7 @@ int sk_reuseport_attach_bpf(u32 ufd, struct sock *sk)
                return -EPERM;
 
        prog = bpf_prog_get_type(ufd, BPF_PROG_TYPE_SOCKET_FILTER);
-       if (IS_ERR(prog) && PTR_ERR(prog) == -EINVAL)
+       if (PTR_ERR(prog) == -EINVAL)
                prog = bpf_prog_get_type(ufd, BPF_PROG_TYPE_SK_REUSEPORT);
        if (IS_ERR(prog))
                return PTR_ERR(prog);
index 294bfcf..acc849d 100644 (file)
@@ -535,12 +535,12 @@ static int pgctrl_open(struct inode *inode, struct file *file)
        return single_open(file, pgctrl_show, PDE_DATA(inode));
 }
 
-static const struct file_operations pktgen_fops = {
-       .open    = pgctrl_open,
-       .read    = seq_read,
-       .llseek  = seq_lseek,
-       .write   = pgctrl_write,
-       .release = single_release,
+static const struct proc_ops pktgen_proc_ops = {
+       .proc_open      = pgctrl_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_write     = pgctrl_write,
+       .proc_release   = single_release,
 };
 
 static int pktgen_if_show(struct seq_file *seq, void *v)
@@ -1707,12 +1707,12 @@ static int pktgen_if_open(struct inode *inode, struct file *file)
        return single_open(file, pktgen_if_show, PDE_DATA(inode));
 }
 
-static const struct file_operations pktgen_if_fops = {
-       .open    = pktgen_if_open,
-       .read    = seq_read,
-       .llseek  = seq_lseek,
-       .write   = pktgen_if_write,
-       .release = single_release,
+static const struct proc_ops pktgen_if_proc_ops = {
+       .proc_open      = pktgen_if_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_write     = pktgen_if_write,
+       .proc_release   = single_release,
 };
 
 static int pktgen_thread_show(struct seq_file *seq, void *v)
@@ -1844,12 +1844,12 @@ static int pktgen_thread_open(struct inode *inode, struct file *file)
        return single_open(file, pktgen_thread_show, PDE_DATA(inode));
 }
 
-static const struct file_operations pktgen_thread_fops = {
-       .open    = pktgen_thread_open,
-       .read    = seq_read,
-       .llseek  = seq_lseek,
-       .write   = pktgen_thread_write,
-       .release = single_release,
+static const struct proc_ops pktgen_thread_proc_ops = {
+       .proc_open      = pktgen_thread_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_write     = pktgen_thread_write,
+       .proc_release   = single_release,
 };
 
 /* Think find or remove for NN */
@@ -1926,7 +1926,7 @@ static void pktgen_change_name(const struct pktgen_net *pn, struct net_device *d
 
                        pkt_dev->entry = proc_create_data(dev->name, 0600,
                                                          pn->proc_dir,
-                                                         &pktgen_if_fops,
+                                                         &pktgen_if_proc_ops,
                                                          pkt_dev);
                        if (!pkt_dev->entry)
                                pr_err("can't move proc entry for '%s'\n",
@@ -3638,7 +3638,7 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
                pkt_dev->clone_skb = pg_clone_skb_d;
 
        pkt_dev->entry = proc_create_data(ifname, 0600, t->net->proc_dir,
-                                         &pktgen_if_fops, pkt_dev);
+                                         &pktgen_if_proc_ops, pkt_dev);
        if (!pkt_dev->entry) {
                pr_err("cannot create %s/%s procfs entry\n",
                       PG_PROC_DIR, ifname);
@@ -3708,7 +3708,7 @@ static int __net_init pktgen_create_thread(int cpu, struct pktgen_net *pn)
        t->tsk = p;
 
        pe = proc_create_data(t->tsk->comm, 0600, pn->proc_dir,
-                             &pktgen_thread_fops, t);
+                             &pktgen_thread_proc_ops, t);
        if (!pe) {
                pr_err("cannot create %s/%s procfs entry\n",
                       PG_PROC_DIR, t->tsk->comm);
@@ -3793,7 +3793,7 @@ static int __net_init pg_net_init(struct net *net)
                pr_warn("cannot create /proc/net/%s\n", PG_PROC_DIR);
                return -ENODEV;
        }
-       pe = proc_create(PGCTRL, 0600, pn->proc_dir, &pktgen_fops);
+       pe = proc_create(PGCTRL, 0600, pn->proc_dir, &pktgen_proc_ops);
        if (pe == NULL) {
                pr_err("cannot create %s procfs entry\n", PGCTRL);
                ret = -EINVAL;
index f35308f..4438f6b 100644 (file)
@@ -1334,7 +1334,7 @@ static int __init ipconfig_proc_net_init(void)
 
 /* Create a new file under /proc/net/ipconfig */
 static int ipconfig_proc_net_create(const char *name,
-                                   const struct file_operations *fops)
+                                   const struct proc_ops *proc_ops)
 {
        char *pname;
        struct proc_dir_entry *p;
@@ -1346,7 +1346,7 @@ static int ipconfig_proc_net_create(const char *name,
        if (!pname)
                return -ENOMEM;
 
-       p = proc_create(pname, 0444, init_net.proc_net, fops);
+       p = proc_create(pname, 0444, init_net.proc_net, proc_ops);
        kfree(pname);
        if (!p)
                return -ENOMEM;
@@ -1355,7 +1355,7 @@ static int ipconfig_proc_net_create(const char *name,
 }
 
 /* Write NTP server IP addresses to /proc/net/ipconfig/ntp_servers */
-static int ntp_servers_seq_show(struct seq_file *seq, void *v)
+static int ntp_servers_show(struct seq_file *seq, void *v)
 {
        int i;
 
@@ -1365,7 +1365,7 @@ static int ntp_servers_seq_show(struct seq_file *seq, void *v)
        }
        return 0;
 }
-DEFINE_SHOW_ATTRIBUTE(ntp_servers_seq);
+DEFINE_PROC_SHOW_ATTRIBUTE(ntp_servers);
 #endif /* CONFIG_PROC_FS */
 
 /*
@@ -1456,7 +1456,7 @@ static int __init ip_auto_config(void)
        proc_create_single("pnp", 0444, init_net.proc_net, pnp_seq_show);
 
        if (ipconfig_proc_net_init() == 0)
-               ipconfig_proc_net_create("ntp_servers", &ntp_servers_seq_fops);
+               ipconfig_proc_net_create("ntp_servers", &ntp_servers_proc_ops);
 #endif /* CONFIG_PROC_FS */
 
        if (!ic_enable)
index 6bdb1ab..f8755a4 100644 (file)
@@ -58,7 +58,7 @@ struct clusterip_config {
 };
 
 #ifdef CONFIG_PROC_FS
-static const struct file_operations clusterip_proc_fops;
+static const struct proc_ops clusterip_proc_ops;
 #endif
 
 struct clusterip_net {
@@ -280,7 +280,7 @@ clusterip_config_init(struct net *net, const struct ipt_clusterip_tgt_info *i,
                mutex_lock(&cn->mutex);
                c->pde = proc_create_data(buffer, 0600,
                                          cn->procdir,
-                                         &clusterip_proc_fops, c);
+                                         &clusterip_proc_ops, c);
                mutex_unlock(&cn->mutex);
                if (!c->pde) {
                        err = -ENOMEM;
@@ -804,12 +804,12 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input,
        return size;
 }
 
-static const struct file_operations clusterip_proc_fops = {
-       .open    = clusterip_proc_open,
-       .read    = seq_read,
-       .write   = clusterip_proc_write,
-       .llseek  = seq_lseek,
-       .release = clusterip_proc_release,
+static const struct proc_ops clusterip_proc_ops = {
+       .proc_open      = clusterip_proc_open,
+       .proc_read      = seq_read,
+       .proc_write     = clusterip_proc_write,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = clusterip_proc_release,
 };
 
 #endif /* CONFIG_PROC_FS */
index d5c57b3..ebe7060 100644 (file)
@@ -237,11 +237,11 @@ static int rt_cache_seq_open(struct inode *inode, struct file *file)
        return seq_open(file, &rt_cache_seq_ops);
 }
 
-static const struct file_operations rt_cache_seq_fops = {
-       .open    = rt_cache_seq_open,
-       .read    = seq_read,
-       .llseek  = seq_lseek,
-       .release = seq_release,
+static const struct proc_ops rt_cache_proc_ops = {
+       .proc_open      = rt_cache_seq_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = seq_release,
 };
 
 
@@ -328,11 +328,11 @@ static int rt_cpu_seq_open(struct inode *inode, struct file *file)
        return seq_open(file, &rt_cpu_seq_ops);
 }
 
-static const struct file_operations rt_cpu_seq_fops = {
-       .open    = rt_cpu_seq_open,
-       .read    = seq_read,
-       .llseek  = seq_lseek,
-       .release = seq_release,
+static const struct proc_ops rt_cpu_proc_ops = {
+       .proc_open      = rt_cpu_seq_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = seq_release,
 };
 
 #ifdef CONFIG_IP_ROUTE_CLASSID
@@ -366,12 +366,12 @@ static int __net_init ip_rt_do_proc_init(struct net *net)
        struct proc_dir_entry *pde;
 
        pde = proc_create("rt_cache", 0444, net->proc_net,
-                         &rt_cache_seq_fops);
+                         &rt_cache_proc_ops);
        if (!pde)
                goto err1;
 
        pde = proc_create("rt_cache", 0444,
-                         net->proc_net_stat, &rt_cpu_seq_fops);
+                         net->proc_net_stat, &rt_cpu_proc_ops);
        if (!pde)
                goto err2;
 
index 781e0b4..0a97080 100644 (file)
@@ -103,7 +103,7 @@ static DEFINE_SPINLOCK(recent_lock);
 static DEFINE_MUTEX(recent_mutex);
 
 #ifdef CONFIG_PROC_FS
-static const struct file_operations recent_mt_fops;
+static const struct proc_ops recent_mt_proc_ops;
 #endif
 
 static u_int32_t hash_rnd __read_mostly;
@@ -405,7 +405,7 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
                goto out;
        }
        pde = proc_create_data(t->name, ip_list_perms, recent_net->xt_recent,
-                 &recent_mt_fops, t);
+                              &recent_mt_proc_ops, t);
        if (pde == NULL) {
                recent_table_free(t);
                ret = -ENOMEM;
@@ -616,13 +616,12 @@ recent_mt_proc_write(struct file *file, const char __user *input,
        return size + 1;
 }
 
-static const struct file_operations recent_mt_fops = {
-       .open    = recent_seq_open,
-       .read    = seq_read,
-       .write   = recent_mt_proc_write,
-       .release = seq_release_private,
-       .owner   = THIS_MODULE,
-       .llseek = seq_lseek,
+static const struct proc_ops recent_mt_proc_ops = {
+       .proc_open      = recent_seq_open,
+       .proc_read      = seq_read,
+       .proc_write     = recent_mt_proc_write,
+       .proc_release   = seq_release_private,
+       .proc_lseek     = seq_lseek,
 };
 
 static int __net_init recent_proc_net_init(struct net *net)
index 3111817..7511a68 100644 (file)
@@ -1428,10 +1428,10 @@ static ssize_t read_gssp(struct file *file, char __user *buf,
        return len;
 }
 
-static const struct file_operations use_gss_proxy_ops = {
-       .open = nonseekable_open,
-       .write = write_gssp,
-       .read = read_gssp,
+static const struct proc_ops use_gss_proxy_proc_ops = {
+       .proc_open      = nonseekable_open,
+       .proc_write     = write_gssp,
+       .proc_read      = read_gssp,
 };
 
 static int create_use_gss_proxy_proc_entry(struct net *net)
@@ -1442,7 +1442,7 @@ static int create_use_gss_proxy_proc_entry(struct net *net)
        sn->use_gss_proxy = -1;
        *p = proc_create_data("use-gss-proxy", S_IFREG | 0600,
                              sn->proc_net_rpc,
-                             &use_gss_proxy_ops, net);
+                             &use_gss_proxy_proc_ops, net);
        if (!*p)
                return -ENOMEM;
        init_gssp_clnt(sn);
index d996bf8..375914c 100644 (file)
@@ -1571,15 +1571,14 @@ static int cache_release_procfs(struct inode *inode, struct file *filp)
        return cache_release(inode, filp, cd);
 }
 
-static const struct file_operations cache_file_operations_procfs = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .read           = cache_read_procfs,
-       .write          = cache_write_procfs,
-       .poll           = cache_poll_procfs,
-       .unlocked_ioctl = cache_ioctl_procfs, /* for FIONREAD */
-       .open           = cache_open_procfs,
-       .release        = cache_release_procfs,
+static const struct proc_ops cache_channel_proc_ops = {
+       .proc_lseek     = no_llseek,
+       .proc_read      = cache_read_procfs,
+       .proc_write     = cache_write_procfs,
+       .proc_poll      = cache_poll_procfs,
+       .proc_ioctl     = cache_ioctl_procfs, /* for FIONREAD */
+       .proc_open      = cache_open_procfs,
+       .proc_release   = cache_release_procfs,
 };
 
 static int content_open_procfs(struct inode *inode, struct file *filp)
@@ -1596,11 +1595,11 @@ static int content_release_procfs(struct inode *inode, struct file *filp)
        return content_release(inode, filp, cd);
 }
 
-static const struct file_operations content_file_operations_procfs = {
-       .open           = content_open_procfs,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = content_release_procfs,
+static const struct proc_ops content_proc_ops = {
+       .proc_open      = content_open_procfs,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = content_release_procfs,
 };
 
 static int open_flush_procfs(struct inode *inode, struct file *filp)
@@ -1634,12 +1633,12 @@ static ssize_t write_flush_procfs(struct file *filp,
        return write_flush(filp, buf, count, ppos, cd);
 }
 
-static const struct file_operations cache_flush_operations_procfs = {
-       .open           = open_flush_procfs,
-       .read           = read_flush_procfs,
-       .write          = write_flush_procfs,
-       .release        = release_flush_procfs,
-       .llseek         = no_llseek,
+static const struct proc_ops cache_flush_proc_ops = {
+       .proc_open      = open_flush_procfs,
+       .proc_read      = read_flush_procfs,
+       .proc_write     = write_flush_procfs,
+       .proc_release   = release_flush_procfs,
+       .proc_lseek     = no_llseek,
 };
 
 static void remove_cache_proc_entries(struct cache_detail *cd)
@@ -1662,19 +1661,19 @@ static int create_cache_proc_entries(struct cache_detail *cd, struct net *net)
                goto out_nomem;
 
        p = proc_create_data("flush", S_IFREG | 0600,
-                            cd->procfs, &cache_flush_operations_procfs, cd);
+                            cd->procfs, &cache_flush_proc_ops, cd);
        if (p == NULL)
                goto out_nomem;
 
        if (cd->cache_request || cd->cache_parse) {
                p = proc_create_data("channel", S_IFREG | 0600, cd->procfs,
-                                    &cache_file_operations_procfs, cd);
+                                    &cache_channel_proc_ops, cd);
                if (p == NULL)
                        goto out_nomem;
        }
        if (cd->cache_show) {
                p = proc_create_data("content", S_IFREG | 0400, cd->procfs,
-                                    &content_file_operations_procfs, cd);
+                                    &content_proc_ops, cd);
                if (p == NULL)
                        goto out_nomem;
        }
index 7c74197..c964b48 100644 (file)
@@ -69,12 +69,11 @@ static int rpc_proc_open(struct inode *inode, struct file *file)
        return single_open(file, rpc_proc_show, PDE_DATA(inode));
 }
 
-static const struct file_operations rpc_proc_fops = {
-       .owner = THIS_MODULE,
-       .open = rpc_proc_open,
-       .read  = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
+static const struct proc_ops rpc_proc_ops = {
+       .proc_open      = rpc_proc_open,
+       .proc_read      = seq_read,
+       .proc_lseek     = seq_lseek,
+       .proc_release   = single_release,
 };
 
 /*
@@ -281,19 +280,19 @@ EXPORT_SYMBOL_GPL(rpc_clnt_show_stats);
  */
 static inline struct proc_dir_entry *
 do_register(struct net *net, const char *name, void *data,
-           const struct file_operations *fops)
+           const struct proc_ops *proc_ops)
 {
        struct sunrpc_net *sn;
 
        dprintk("RPC:       registering /proc/net/rpc/%s\n", name);
        sn = net_generic(net, sunrpc_net_id);
-       return proc_create_data(name, 0, sn->proc_net_rpc, fops, data);
+       return proc_create_data(name, 0, sn->proc_net_rpc, proc_ops, data);
 }
 
 struct proc_dir_entry *
 rpc_proc_register(struct net *net, struct rpc_stat *statp)
 {
-       return do_register(net, statp->program->name, statp, &rpc_proc_fops);
+       return do_register(net, statp->program->name, statp, &rpc_proc_ops);
 }
 EXPORT_SYMBOL_GPL(rpc_proc_register);
 
@@ -308,9 +307,9 @@ rpc_proc_unregister(struct net *net, const char *name)
 EXPORT_SYMBOL_GPL(rpc_proc_unregister);
 
 struct proc_dir_entry *
-svc_proc_register(struct net *net, struct svc_stat *statp, const struct file_operations *fops)
+svc_proc_register(struct net *net, struct svc_stat *statp, const struct proc_ops *proc_ops)
 {
-       return do_register(net, statp->program->pg_name, statp, fops);
+       return do_register(net, statp->program->pg_name, statp, proc_ops);
 }
 EXPORT_SYMBOL_GPL(svc_proc_register);
 
index 297d1eb..dbda08e 100644 (file)
@@ -3189,7 +3189,7 @@ struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig,
                                            flags | XFRM_LOOKUP_QUEUE |
                                            XFRM_LOOKUP_KEEP_DST_REF);
 
-       if (IS_ERR(dst) && PTR_ERR(dst) == -EREMOTE)
+       if (PTR_ERR(dst) == -EREMOTE)
                return make_blackhole(net, dst_orig->ops->family, dst_orig);
 
        if (IS_ERR(dst))
index 9ca3e44..c406f03 100644 (file)
@@ -142,11 +142,10 @@ static ssize_t fifo_read(struct file *file, char __user *buf,
        return ret ? ret : copied;
 }
 
-static const struct file_operations fifo_fops = {
-       .owner          = THIS_MODULE,
-       .read           = fifo_read,
-       .write          = fifo_write,
-       .llseek         = noop_llseek,
+static const struct proc_ops fifo_proc_ops = {
+       .proc_read      = fifo_read,
+       .proc_write     = fifo_write,
+       .proc_lseek     = noop_llseek,
 };
 
 static int __init example_init(void)
@@ -169,7 +168,7 @@ static int __init example_init(void)
                return -EIO;
        }
 
-       if (proc_create(PROC_FIFO, 0, NULL, &fifo_fops) == NULL) {
+       if (proc_create(PROC_FIFO, 0, NULL, &fifo_proc_ops) == NULL) {
 #ifdef DYNAMIC
                kfifo_free(&test);
 #endif
index 6cdeb72..78977fc 100644 (file)
@@ -135,11 +135,10 @@ static ssize_t fifo_read(struct file *file, char __user *buf,
        return ret ? ret : copied;
 }
 
-static const struct file_operations fifo_fops = {
-       .owner          = THIS_MODULE,
-       .read           = fifo_read,
-       .write          = fifo_write,
-       .llseek         = noop_llseek,
+static const struct proc_ops fifo_proc_ops = {
+       .proc_read      = fifo_read,
+       .proc_write     = fifo_write,
+       .proc_lseek     = noop_llseek,
 };
 
 static int __init example_init(void)
@@ -160,7 +159,7 @@ static int __init example_init(void)
                return -EIO;
        }
 
-       if (proc_create(PROC_FIFO, 0, NULL, &fifo_fops) == NULL) {
+       if (proc_create(PROC_FIFO, 0, NULL, &fifo_proc_ops) == NULL) {
 #ifdef DYNAMIC
                kfifo_free(&test);
 #endif
index 79ae8bb..c507998 100644 (file)
@@ -149,11 +149,10 @@ static ssize_t fifo_read(struct file *file, char __user *buf,
        return ret ? ret : copied;
 }
 
-static const struct file_operations fifo_fops = {
-       .owner          = THIS_MODULE,
-       .read           = fifo_read,
-       .write          = fifo_write,
-       .llseek         = noop_llseek,
+static const struct proc_ops fifo_proc_ops = {
+       .proc_read      = fifo_read,
+       .proc_write     = fifo_write,
+       .proc_lseek     = noop_llseek,
 };
 
 static int __init example_init(void)
@@ -176,7 +175,7 @@ static int __init example_init(void)
                return -EIO;
        }
 
-       if (proc_create(PROC_FIFO, 0, NULL, &fifo_fops) == NULL) {
+       if (proc_create(PROC_FIFO, 0, NULL, &fifo_proc_ops) == NULL) {
 #ifdef DYNAMIC
                kfifo_free(&test);
 #endif
index 9330d42..3357bf4 100644 (file)
@@ -90,8 +90,6 @@ position p;
  kfree@p(x)
 |
  kzfree@p(x)
-|
- __krealloc@p(x, ...)
 |
  krealloc@p(x, ...)
 |
@@ -116,8 +114,6 @@ position p != safe.p;
 |
 * kzfree@p(x)
 |
-* __krealloc@p(x, ...)
-|
 * krealloc@p(x, ...)
 |
 * free_pages@p(x, ...)
index 6801d81..ca87ae4 100644 (file)
@@ -282,17 +282,16 @@ static int snd_info_entry_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static const struct file_operations snd_info_entry_operations =
-{
-       .owner =                THIS_MODULE,
-       .llseek =               snd_info_entry_llseek,
-       .read =                 snd_info_entry_read,
-       .write =                snd_info_entry_write,
-       .poll =                 snd_info_entry_poll,
-       .unlocked_ioctl =       snd_info_entry_ioctl,
-       .mmap =                 snd_info_entry_mmap,
-       .open =                 snd_info_entry_open,
-       .release =              snd_info_entry_release,
+static const struct proc_ops snd_info_entry_operations =
+{
+       .proc_lseek     = snd_info_entry_llseek,
+       .proc_read      = snd_info_entry_read,
+       .proc_write     = snd_info_entry_write,
+       .proc_poll      = snd_info_entry_poll,
+       .proc_ioctl     = snd_info_entry_ioctl,
+       .proc_mmap      = snd_info_entry_mmap,
+       .proc_open      = snd_info_entry_open,
+       .proc_release   = snd_info_entry_release,
 };
 
 /*
@@ -421,14 +420,13 @@ static int snd_info_text_entry_release(struct inode *inode, struct file *file)
        return 0;
 }
 
-static const struct file_operations snd_info_text_entry_ops =
+static const struct proc_ops snd_info_text_entry_ops =
 {
-       .owner =                THIS_MODULE,
-       .open =                 snd_info_text_entry_open,
-       .release =              snd_info_text_entry_release,
-       .write =                snd_info_text_entry_write,
-       .llseek =               seq_lseek,
-       .read =                 seq_read,
+       .proc_open      = snd_info_text_entry_open,
+       .proc_release   = snd_info_text_entry_release,
+       .proc_write     = snd_info_text_entry_write,
+       .proc_lseek     = seq_lseek,
+       .proc_read      = seq_read,
 };
 
 static struct snd_info_entry *create_subdir(struct module *mod,
@@ -810,7 +808,7 @@ static int __snd_info_register(struct snd_info_entry *entry)
                        return -ENOMEM;
                }
        } else {
-               const struct file_operations *ops;
+               const struct proc_ops *ops;
                if (entry->content == SNDRV_INFO_CONTENT_DATA)
                        ops = &snd_info_entry_operations;
                else
index e8c5fda..979cfb1 100644 (file)
@@ -295,8 +295,7 @@ static int ak4104_spi_probe(struct spi_device *spi)
 
        reset_gpiod = devm_gpiod_get_optional(&spi->dev, "reset",
                                              GPIOD_OUT_HIGH);
-       if (IS_ERR(reset_gpiod) &&
-           PTR_ERR(reset_gpiod) == -EPROBE_DEFER)
+       if (PTR_ERR(reset_gpiod) == -EPROBE_DEFER)
                return -EPROBE_DEFER;
 
        /* read the 'reserved' register - according to the datasheet, it
index 793a14d..5f25b9f 100644 (file)
@@ -681,8 +681,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
 
        reset_gpiod = devm_gpiod_get_optional(&i2c_client->dev, "reset",
                                              GPIOD_OUT_HIGH);
-       if (IS_ERR(reset_gpiod) &&
-           PTR_ERR(reset_gpiod) == -EPROBE_DEFER)
+       if (PTR_ERR(reset_gpiod) == -EPROBE_DEFER)
                return -EPROBE_DEFER;
 
        cs4270->regmap = devm_regmap_init_i2c(i2c_client, &cs4270_regmap);
index b4e9a6c..d087f3b 100644 (file)
@@ -1098,11 +1098,9 @@ static int aic32x4_setup_regulators(struct device *dev,
                        return PTR_ERR(aic32x4->supply_av);
                }
        } else {
-               if (IS_ERR(aic32x4->supply_dv) &&
-                               PTR_ERR(aic32x4->supply_dv) == -EPROBE_DEFER)
+               if (PTR_ERR(aic32x4->supply_dv) == -EPROBE_DEFER)
                        return -EPROBE_DEFER;
-               if (IS_ERR(aic32x4->supply_av) &&
-                               PTR_ERR(aic32x4->supply_av) == -EPROBE_DEFER)
+               if (PTR_ERR(aic32x4->supply_av) == -EPROBE_DEFER)
                        return -EPROBE_DEFER;
        }
 
index cbe598b..98a9fe6 100644 (file)
@@ -555,7 +555,7 @@ static int sun4i_spdif_probe(struct platform_device *pdev)
        if (quirks->has_reset) {
                host->rst = devm_reset_control_get_optional_exclusive(&pdev->dev,
                                                                      NULL);
-               if (IS_ERR(host->rst) && PTR_ERR(host->rst) == -EPROBE_DEFER) {
+               if (PTR_ERR(host->rst) == -EPROBE_DEFER) {
                        ret = -EPROBE_DEFER;
                        dev_err(&pdev->dev, "Failed to get reset: %d\n", ret);
                        return ret;
index 140c836..5fca38f 100644 (file)
 #include <linux/bits.h>
 #include <linux/compiler.h>
 
-#define BITS_TO_LONGS(nr)      DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
-#define BITS_TO_U64(nr)                DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
-#define BITS_TO_U32(nr)                DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
-#define BITS_TO_BYTES(nr)      DIV_ROUND_UP(nr, BITS_PER_BYTE)
+#define BITS_PER_TYPE(type)    (sizeof(type) * BITS_PER_BYTE)
+#define BITS_TO_LONGS(nr)      DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
+#define BITS_TO_U64(nr)                DIV_ROUND_UP(nr, BITS_PER_TYPE(u64))
+#define BITS_TO_U32(nr)                DIV_ROUND_UP(nr, BITS_PER_TYPE(u32))
+#define BITS_TO_BYTES(nr)      DIV_ROUND_UP(nr, BITS_PER_TYPE(char))
 
 extern unsigned int __sw_hweight8(unsigned int w);
 extern unsigned int __sw_hweight16(unsigned int w);