]> Git Repo - J-linux.git/commitdiff
Merge tag 'sysctl-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof...
authorLinus Torvalds <[email protected]>
Thu, 11 Jan 2024 01:44:36 +0000 (17:44 -0800)
committerLinus Torvalds <[email protected]>
Thu, 11 Jan 2024 01:44:36 +0000 (17:44 -0800)
Pull sysctl updates from Luis Chamberlain:
 "To help make the move of sysctls out of kernel/sysctl.c not incur a
  size penalty sysctl has been changed to allow us to not require the
  sentinel, the final empty element on the sysctl array. Joel Granados
  has been doing all this work.

  In the v6.6 kernel we got the major infrastructure changes required to
  support this. For v6.7 we had all arch/ and drivers/ modified to
  remove the sentinel. For v6.8-rc1 we get a few more updates for fs/
  directory only.

  The kernel/ directory is left but we'll save that for v6.9-rc1 as
  those patches are still being reviewed. After that we then can expect
  also the removal of the no longer needed check for procname == NULL.

  Let us recap the purpose of this work:

   - this helps reduce the overall build time size of the kernel and run
     time memory consumed by the kernel by about ~64 bytes per array

   - the extra 64-byte penalty is no longer inncurred now when we move
     sysctls out from kernel/sysctl.c to their own files

  Thomas Weißschuh also sent a few cleanups, for v6.9-rc1 we expect to
  see further work by Thomas Weißschuh with the constificatin of the
  struct ctl_table.

  Due to Joel Granados's work, and to help bring in new blood, I have
  suggested for him to become a maintainer and he's accepted. So for
  v6.9-rc1 I look forward to seeing him sent you a pull request for
  further sysctl changes. This also removes Iurii Zaikin as a maintainer
  as he has moved on to other projects and has had no time to help at
  all"

* tag 'sysctl-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux:
  sysctl: remove struct ctl_path
  sysctl: delete unused define SYSCTL_PERM_EMPTY_DIR
  coda: Remove the now superfluous sentinel elements from ctl_table array
  sysctl: Remove the now superfluous sentinel elements from ctl_table array
  fs: Remove the now superfluous sentinel elements from ctl_table array
  cachefiles: Remove the now superfluous sentinel element from ctl_table array
  sysclt: Clarify the results of selftest run
  sysctl: Add a selftest for handling empty dirs
  sysctl: Fix out of bounds access for empty sysctl registers
  MAINTAINERS: Add Joel Granados as co-maintainer for proc sysctl
  MAINTAINERS: remove Iurii Zaikin from proc sysctl

13 files changed:
1  2 
MAINTAINERS
fs/aio.c
fs/dcache.c
fs/exec.c
fs/file_table.c
fs/inode.c
fs/lockd/svc.c
fs/namei.c
fs/namespace.c
fs/notify/fanotify/fanotify_user.c
fs/pipe.c
fs/quota/dquot.c
fs/userfaultfd.c

diff --combined MAINTAINERS
index 40f7ad688a627a94e9ed5bb11022dd86d5a32691,75fee7791e4f4689f0f9c1890c7fa9d72ab752c2..cc92b10a4cadaa0ebbc419678d751c5fc45961dc
@@@ -3339,17 -3339,13 +3339,17 @@@ M:   Eric Paris <[email protected]
  L:    [email protected]
  S:    Supported
  W:    https://github.com/linux-audit
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit.git
 +Q:    https://patchwork.kernel.org/project/audit/list
 +B:    mailto:[email protected]
 +P:    https://github.com/linux-audit/audit-kernel/blob/main/README.md
 +T:    git https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit.git
  F:    include/asm-generic/audit_*.h
  F:    include/linux/audit.h
  F:    include/linux/audit_arch.h
  F:    include/uapi/linux/audit.h
  F:    kernel/audit*
  F:    lib/*audit.c
 +K:    \baudit_[a-z_0-9]\+\b
  
  AUXILIARY BUS DRIVER
  M:    Greg Kroah-Hartman <[email protected]>
@@@ -3408,16 -3404,6 +3408,16 @@@ W:    https://ez.analog.com/linux-software
  F:    Documentation/devicetree/bindings/hwmon/adi,axi-fan-control.yaml
  F:    drivers/hwmon/axi-fan-control.c
  
 +AXI SPI ENGINE
 +M:    Michael Hennerich <[email protected]>
 +M:    Nuno Sá <[email protected]>
 +R:    David Lechner <[email protected]>
 +L:    [email protected]
 +S:    Supported
 +W:    https://ez.analog.com/linux-software-drivers
 +F:    Documentation/devicetree/bindings/spi/adi,axi-spi-engine.yaml
 +F:    drivers/spi/spi-axi-spi-engine.c
 +
  AXXIA I2C CONTROLLER
  M:    Krzysztof Adamski <[email protected]>
  L:    [email protected]
@@@ -3502,7 -3488,7 +3502,7 @@@ F:      drivers/net/hamradio/baycom
  
  BCACHE (BLOCK LAYER CACHE)
  M:    Coly Li <[email protected]>
 -M:    Kent Overstreet <kent.overstreet@gmail.com>
 +M:    Kent Overstreet <kent.overstreet@linux.dev>
  L:    [email protected]
  S:    Maintained
  W:    http://bcache.evilpiepirate.org
@@@ -4141,6 -4127,7 +4141,6 @@@ M:      Franky Lin <[email protected]
  M:    Hante Meuleman <[email protected]>
  L:    [email protected]
  L:    [email protected]
 -L:    [email protected]
  S:    Supported
  F:    drivers/net/wireless/broadcom/brcm80211/
  
@@@ -5353,7 -5340,6 +5353,7 @@@ L:      [email protected]
  S:    Maintained
  F:    mm/memcontrol.c
  F:    mm/swap_cgroup.c
 +F:    samples/cgroup/*
  F:    tools/testing/selftests/cgroup/memcg_protection.m
  F:    tools/testing/selftests/cgroup/test_hugetlb_memcg.c
  F:    tools/testing/selftests/cgroup/test_kmem.c
@@@ -5538,12 -5524,6 +5538,12 @@@ F:    include/crypto
  F:    include/linux/crypto*
  F:    lib/crypto/
  
 +CRYPTO SPEED TEST COMPARE
 +M:    Wang Jinchao <[email protected]>
 +L:    [email protected]
 +S:    Maintained
 +F:    tools/crypto/tcrypt/tcrypt_speed_compare.py
 +
  CRYPTOGRAPHIC RANDOM NUMBER GENERATOR
  M:    Neil Horman <[email protected]>
  L:    [email protected]
@@@ -6922,8 -6902,8 +6922,8 @@@ T:      git git://anongit.freedesktop.org/dr
  F:    drivers/gpu/drm/vboxvideo/
  
  DRM DRIVER FOR VMWARE VIRTUAL GPU
 -M:    Zack Rusin <zackr@vmware.com>
 -R:    VMware Graphics Reviewers <linux-graphics-maintainer@vmware.com>
 +M:    Zack Rusin <zack.rusin@broadcom.com>
 +R:    Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
  L:    [email protected]
  S:    Supported
  T:    git git://anongit.freedesktop.org/drm/drm-misc
@@@ -7946,7 -7926,6 +7946,7 @@@ F:      include/uapi/linux/ext4.
  
  Extended Verification Module (EVM)
  M:    Mimi Zohar <[email protected]>
 +M:    Roberto Sassu <[email protected]>
  L:    [email protected]
  S:    Supported
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git
@@@ -8125,7 -8104,6 +8125,7 @@@ F:      include/trace/events/fs_dax.
  FILESYSTEMS (VFS and infrastructure)
  M:    Alexander Viro <[email protected]>
  M:    Christian Brauner <[email protected]>
 +R:    Jan Kara <[email protected]>
  L:    [email protected]
  S:    Maintained
  F:    fs/*
@@@ -8146,16 -8124,6 +8146,16 @@@ F:    fs/exportfs
  F:    fs/fhandle.c
  F:    include/linux/exportfs.h
  
 +FILESYSTEMS [IDMAPPED MOUNTS]
 +M:    Christian Brauner <[email protected]>
 +M:    Seth Forshee <[email protected]>
 +L:    [email protected]
 +S:    Maintained
 +F:    Documentation/filesystems/idmappings.rst
 +F:    fs/mnt_idmapping.c
 +F:    include/linux/mnt_idmapping.*
 +F:    tools/testing/selftests/mount_setattr/
 +
  FILESYSTEMS [IOMAP]
  M:    Christian Brauner <[email protected]>
  R:    Darrick J. Wong <[email protected]>
@@@ -8165,15 -8133,6 +8165,15 @@@ S:    Supporte
  F:    fs/iomap/
  F:    include/linux/iomap.h
  
 +FILESYSTEMS [STACKABLE]
 +M:    Miklos Szeredi <[email protected]>
 +M:    Amir Goldstein <[email protected]>
 +L:    [email protected]
 +L:    [email protected]
 +S:    Maintained
 +F:    fs/backing-file.c
 +F:    include/linux/backing-file.h
 +
  FINTEK F75375S HARDWARE MONITOR AND FAN CONTROLLER DRIVER
  M:    Riku Voipio <[email protected]>
  L:    [email protected]
@@@ -9032,7 -8991,7 +9032,7 @@@ F:      drivers/gpio/gpio-mockup.
  F:    tools/testing/selftests/gpio/
  
  GPIO REGMAP
 -M:    Michael Walle <m[email protected]>
 +M:    Michael Walle <m[email protected]>
  S:    Maintained
  F:    drivers/gpio/gpio-regmap.c
  F:    include/linux/gpio/regmap.h
@@@ -9041,9 -9000,12 +9041,9 @@@ K:     (devm_)?gpio_regmap_(un)?registe
  GPIO SUBSYSTEM
  M:    Linus Walleij <[email protected]>
  M:    Bartosz Golaszewski <[email protected]>
 -R:    Andy Shevchenko <[email protected]>
  L:    [email protected]
  S:    Maintained
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux.git
 -F:    Documentation/ABI/obsolete/sysfs-gpio
 -F:    Documentation/ABI/testing/gpio-cdev
  F:    Documentation/admin-guide/gpio/
  F:    Documentation/devicetree/bindings/gpio/
  F:    Documentation/driver-api/gpio/
@@@ -9052,16 -9014,6 +9052,16 @@@ F:    include/dt-bindings/gpio
  F:    include/linux/gpio.h
  F:    include/linux/gpio/
  F:    include/linux/of_gpio.h
 +
 +GPIO UAPI
 +M:    Bartosz Golaszewski <[email protected]>
 +R:    Kent Gibson <[email protected]>
 +L:    [email protected]
 +S:    Maintained
 +T:    git git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux.git
 +F:    Documentation/ABI/obsolete/sysfs-gpio
 +F:    Documentation/ABI/testing/gpio-cdev
 +F:    drivers/gpio/gpiolib-cdev.c
  F:    include/uapi/linux/gpio.h
  F:    tools/gpio/
  
@@@ -9304,6 -9256,7 +9304,6 @@@ F:      drivers/char/hw_random
  F:    include/linux/hw_random.h
  
  HARDWARE SPINLOCK CORE
 -M:    Ohad Ben-Cohen <[email protected]>
  M:    Bjorn Andersson <[email protected]>
  R:    Baolin Wang <[email protected]>
  L:    [email protected]
@@@ -9532,7 -9485,6 +9532,7 @@@ F:      Documentation/devicetree/bindings/gp
  F:    drivers/gpio/gpio-hisi.c
  
  HISILICON HIGH PERFORMANCE RSA ENGINE DRIVER (HPRE)
 +M:    Zhiqi Song <[email protected]>
  M:    Longfang Liu <[email protected]>
  L:    [email protected]
  S:    Maintained
@@@ -9635,6 -9587,7 +9635,6 @@@ F:      Documentation/devicetree/bindings/sc
  F:    drivers/scsi/hisi_sas/
  
  HISILICON SECURITY ENGINE V2 DRIVER (SEC2)
 -M:    Kai Ye <[email protected]>
  M:    Longfang Liu <[email protected]>
  L:    [email protected]
  S:    Maintained
@@@ -9808,6 -9761,7 +9808,6 @@@ F:      Documentation/networking/device_driv
  F:    drivers/net/ethernet/huawei/hinic/
  
  HUGETLB SUBSYSTEM
 -M:    Mike Kravetz <[email protected]>
  M:    Muchun Song <[email protected]>
  L:    [email protected]
  S:    Maintained
@@@ -9831,8 -9785,8 +9831,8 @@@ T:      git git://linuxtv.org/media_tree.gi
  F:    drivers/media/platform/st/sti/hva
  
  HWPOISON MEMORY FAILURE HANDLING
 -M:    Naoya Horiguchi <naoya.horiguchi@nec.com>
 -R:    Miaohe Lin <linmiaohe@huawei.com>
 +M:    Miaohe Lin <linmiaohe@huawei.com>
 +R:    Naoya Horiguchi <naoya.horiguchi@nec.com>
  L:    [email protected]
  S:    Maintained
  F:    mm/hwpoison-inject.c
@@@ -10243,6 -10197,16 +10243,6 @@@ S:  Maintaine
  W:    https://github.com/o2genum/ideapad-slidebar
  F:    drivers/input/misc/ideapad_slidebar.c
  
 -IDMAPPED MOUNTS
 -M:    Christian Brauner <[email protected]>
 -M:    Seth Forshee <[email protected]>
 -L:    [email protected]
 -S:    Maintained
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/vfs/idmapping.git
 -F:    Documentation/filesystems/idmappings.rst
 -F:    include/linux/mnt_idmapping.*
 -F:    tools/testing/selftests/mount_setattr/
 -
  IDT VersaClock 5 CLOCK DRIVER
  M:    Luca Ceresoli <[email protected]>
  S:    Maintained
@@@ -10535,9 -10499,7 +10535,9 @@@ F:   drivers/crypto/inside-secure
  
  INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
  M:    Mimi Zohar <[email protected]>
 +M:    Roberto Sassu <[email protected]>
  M:    Dmitry Kasatkin <[email protected]>
 +R:    Eric Snowberg <[email protected]>
  L:    [email protected]
  S:    Supported
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git
@@@ -10677,7 -10639,6 +10677,7 @@@ F:   drivers/gpio/gpio-pch.
  F:    drivers/gpio/gpio-sch.c
  F:    drivers/gpio/gpio-sodaville.c
  F:    drivers/gpio/gpio-tangier.c
 +F:    drivers/gpio/gpio-tangier.h
  
  INTEL GVT-g DRIVERS (Intel GPU Virtualization)
  M:    Zhenyu Wang <[email protected]>
@@@ -10703,13 -10664,6 +10703,13 @@@ S: Supporte
  Q:    https://patchwork.kernel.org/project/linux-dmaengine/list/
  F:    drivers/dma/ioat*
  
 +INTEL IAA CRYPTO DRIVER
 +M:    Tom Zanussi <[email protected]>
 +L:    [email protected]
 +S:    Supported
 +F:    Documentation/driver-api/crypto/iaa/iaa-crypto.rst
 +F:    drivers/crypto/intel/iaa/*
 +
  INTEL IDLE DRIVER
  M:    Jacob Pan <[email protected]>
  M:    Len Brown <[email protected]>
@@@ -11515,7 -11469,6 +11515,7 @@@ F:   scripts/*vmlinux
  F:    scripts/Kbuild*
  F:    scripts/Makefile*
  F:    scripts/basic/
 +F:    scripts/clang-tools/
  F:    scripts/dummy-tools/
  F:    scripts/mk*
  F:    scripts/mod/
@@@ -12282,21 -12235,21 +12282,21 @@@ S:        Orpha
  F:    arch/powerpc/platforms/40x/
  F:    arch/powerpc/platforms/44x/
  
 -LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX
 +LINUX FOR POWERPC EMBEDDED PPC85XX
  M:    Scott Wood <[email protected]>
  L:    [email protected]
  S:    Odd fixes
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/scottwood/linux.git
  F:    Documentation/devicetree/bindings/cache/freescale-l2cache.txt
  F:    Documentation/devicetree/bindings/powerpc/fsl/
 -F:    arch/powerpc/platforms/83xx/
  F:    arch/powerpc/platforms/85xx/
  
 -LINUX FOR POWERPC EMBEDDED PPC8XX
 +LINUX FOR POWERPC EMBEDDED PPC8XX AND PPC83XX
  M:    Christophe Leroy <[email protected]>
  L:    [email protected]
  S:    Maintained
  F:    arch/powerpc/platforms/8xx/
 +F:    arch/powerpc/platforms/83xx/
  
  LINUX KERNEL DUMP TEST MODULE (LKDTM)
  M:    Kees Cook <[email protected]>
@@@ -12443,12 -12396,6 +12443,12 @@@ T: git git://git.kernel.org/pub/scm/lin
  F:    Documentation/admin-guide/LSM/LoadPin.rst
  F:    security/loadpin/
  
 +LOCKDOWN SECURITY MODULE
 +L:    [email protected]
 +S:    Odd Fixes
 +T:    git https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm.git
 +F:    security/lockdown/
 +
  LOCKING PRIMITIVES
  M:    Peter Zijlstra <[email protected]>
  M:    Ingo Molnar <[email protected]>
@@@ -12460,7 -12407,7 +12460,7 @@@ S:   Maintaine
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git locking/core
  F:    Documentation/locking/
  F:    arch/*/include/asm/spinlock*.h
 -F:    include/linux/lockdep.h
 +F:    include/linux/lockdep*.h
  F:    include/linux/mutex*.h
  F:    include/linux/rwlock*.h
  F:    include/linux/rwsem*.h
@@@ -12868,7 -12815,7 +12868,7 @@@ S:   Maintaine
  F:    drivers/net/ethernet/marvell/mvneta.*
  
  MARVELL MVPP2 ETHERNET DRIVER
 -M:    Marcin Wojtas <mw@semihalf.com>
 +M:    Marcin Wojtas <marcin.s.wojtas@gmail.com>
  M:    Russell King <[email protected]>
  L:    [email protected]
  S:    Maintained
@@@ -15131,7 -15078,6 +15131,7 @@@ K:   \bmdo
  NETWORKING [MPTCP]
  M:    Matthieu Baerts <[email protected]>
  M:    Mat Martineau <[email protected]>
 +R:    Geliang Tang <[email protected]>
  L:    [email protected]
  L:    [email protected]
  S:    Maintained
@@@ -15479,7 -15425,7 +15479,7 @@@ F:   Documentation/devicetree/bindings/ne
  F:    drivers/bluetooth/btnxpuart.c
  
  NXP C45 TJA11XX PHY DRIVER
 -M:    Radu Pirea <radu-nicolae.pire[email protected]>
 +M:    Andrei Botila <andrei.botil[email protected]>
  L:    [email protected]
  S:    Maintained
  F:    drivers/net/phy/nxp-c45-tja11xx.c
@@@ -15750,8 -15696,9 +15750,8 @@@ F:   Documentation/devicetree/bindings/gp
  F:    drivers/gpio/gpio-omap.c
  
  OMAP HARDWARE SPINLOCK SUPPORT
 -M:    Ohad Ben-Cohen <[email protected]>
  L:    [email protected]
 -S:    Maintained
 +S:    Orphan
  F:    drivers/hwspinlock/omap_hwspinlock.c
  
  OMAP HS MMC SUPPORT
@@@ -16502,10 -16449,11 +16502,10 @@@ F:        Documentation/devicetree/bindings/pc
  F:    drivers/pci/controller/dwc/pcie-armada8k.c
  
  PCI DRIVER FOR CADENCE PCIE IP
 -M:    Tom Joseph <[email protected]>
  L:    [email protected]
 -S:    Maintained
 +S:    Orphan
  F:    Documentation/devicetree/bindings/pci/cdns,*
 -F:    drivers/pci/controller/cadence/
 +F:    drivers/pci/controller/cadence/*cadence*
  
  PCI DRIVER FOR FREESCALE LAYERSCAPE
  M:    Minghuan Lian <[email protected]>
@@@ -17412,7 -17360,7 +17412,7 @@@ F:   tools/testing/selftests/proc
  PROC SYSCTL
  M:    Luis Chamberlain <[email protected]>
  M:    Kees Cook <[email protected]>
- M:    Iurii Zaikin <yzaikin@google.com>
+ M:    Joel Granados <j.granados@samsung.com>
  L:    [email protected]
  L:    [email protected]
  S:    Maintained
@@@ -19487,29 -19435,22 +19487,29 @@@ SECURITY SUBSYSTE
  M:    Paul Moore <[email protected]>
  M:    James Morris <[email protected]>
  M:    "Serge E. Hallyn" <[email protected]>
 -L:    [email protected] (suggested Cc:)
 +L:    [email protected]
  S:    Supported
 -W:    http://kernsec.org/
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm.git
 +Q:    https://patchwork.kernel.org/project/linux-security-module/list
 +B:    mailto:[email protected]
 +P:    https://github.com/LinuxSecurityModule/kernel/blob/main/README.md
 +T:    git https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm.git
 +F:    include/uapi/linux/lsm.h
  F:    security/
 +F:    tools/testing/selftests/lsm/
  X:    security/selinux/
 +K:    \bsecurity_[a-z_0-9]\+\b
  
  SELINUX SECURITY MODULE
  M:    Paul Moore <[email protected]>
  M:    Stephen Smalley <[email protected]>
 -M:    Eric Paris <[email protected]>
 +R:    Ondrej Mosnacek <[email protected]>
  L:    [email protected]
  S:    Supported
 -W:    https://selinuxproject.org
  W:    https://github.com/SELinuxProject
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
 +Q:    https://patchwork.kernel.org/project/selinux/list
 +B:    mailto:[email protected]
 +P:    https://github.com/SELinuxProject/selinux-kernel/blob/main/README.md
 +T:    git https://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
  F:    Documentation/ABI/removed/sysfs-selinux-checkreqprot
  F:    Documentation/ABI/removed/sysfs-selinux-disable
  F:    Documentation/admin-guide/LSM/SELinux.rst
@@@ -19881,7 -19822,7 +19881,7 @@@ W:   http://www.winischhofer.at/linuxsisu
  F:    drivers/usb/misc/sisusbvga/
  
  SL28 CPLD MFD DRIVER
 -M:    Michael Walle <m[email protected]>
 +M:    Michael Walle <m[email protected]>
  S:    Maintained
  F:    Documentation/devicetree/bindings/gpio/kontron,sl28cpld-gpio.yaml
  F:    Documentation/devicetree/bindings/hwmon/kontron,sl28cpld-hwmon.yaml
@@@ -19896,7 -19837,7 +19896,7 @@@ F:   drivers/pwm/pwm-sl28cpld.
  F:    drivers/watchdog/sl28cpld_wdt.c
  
  SL28 VPD NVMEM LAYOUT DRIVER
 -M:    Michael Walle <m[email protected]>
 +M:    Michael Walle <m[email protected]>
  S:    Maintained
  F:    Documentation/devicetree/bindings/nvmem/layouts/kontron,sl28-vpd.yaml
  F:    drivers/nvmem/layouts/sl28vpd.c
@@@ -20406,7 -20347,7 +20406,7 @@@ F:   drivers/pinctrl/spear
  SPI NOR SUBSYSTEM
  M:    Tudor Ambarus <[email protected]>
  M:    Pratyush Yadav <[email protected]>
 -R:    Michael Walle <[email protected]>
 +M:    Michael Walle <[email protected]>
  L:    [email protected]
  S:    Maintained
  W:    http://www.linux-mtd.infradead.org/
  S:    Maintained
  F:    drivers/mmc/host/dw_mmc*
  
 +SYNOPSYS DESIGNWARE PCIE PMU DRIVER
 +M:    Shuai Xue <[email protected]>
 +M:    Jing Zhang <[email protected]>
 +S:    Supported
 +F:    Documentation/admin-guide/perf/dwc_pcie_pmu.rst
 +F:    drivers/perf/dwc_pcie_pmu.c
 +
  SYNOPSYS HSDK RESET CONTROLLER DRIVER
  M:    Eugeniy Paltsev <[email protected]>
  S:    Supported
@@@ -22283,7 -22217,7 +22283,7 @@@ F:   drivers/usb/common/ulpi.
  F:    include/linux/ulpi/
  
  UNICODE SUBSYSTEM
 -M:    Gabriel Krisman Bertazi <krisman@collabora.com>
 +M:    Gabriel Krisman Bertazi <krisman@kernel.org>
  L:    [email protected]
  S:    Supported
  F:    fs/unicode/
@@@ -23273,8 -23207,9 +23273,8 @@@ F:   drivers/misc/vmw_vmci
  F:    include/linux/vmw_vmci*
  
  VMWARE VMMOUSE SUBDRIVER
 -M:    Zack Rusin <[email protected]>
 -R:    VMware Graphics Reviewers <[email protected]>
 -R:    VMware PV-Drivers Reviewers <[email protected]>
 +M:    Zack Rusin <[email protected]>
 +R:    Broadcom internal kernel review list <[email protected]>
  L:    [email protected]
  S:    Supported
  F:    drivers/input/mouse/vmmouse.c
@@@ -23648,6 -23583,15 +23648,6 @@@ F:  drivers/platform/olpc
  F:    drivers/platform/x86/
  F:    include/linux/platform_data/x86/
  
 -X86 PLATFORM DRIVERS - ARCH
 -R:    Darren Hart <[email protected]>
 -R:    Andy Shevchenko <[email protected]>
 -L:    [email protected]
 -L:    [email protected]
 -S:    Maintained
 -T:    git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/core
 -F:    arch/x86/platform
 -
  X86 PLATFORM UV HPE SUPERDOME FLEX
  M:    Steve Wahl <[email protected]>
  R:    Justin Ernst <[email protected]>
@@@ -23859,10 -23803,10 +23859,10 @@@ S:        Supporte
  W:    http://xfs.org/
  C:    irc://irc.oftc.net/xfs
  T:    git git://git.kernel.org/pub/scm/fs/xfs/xfs-linux.git
 -P:    Documentation/filesystems/xfs-maintainer-entry-profile.rst
 +P:    Documentation/filesystems/xfs/xfs-maintainer-entry-profile.rst
  F:    Documentation/ABI/testing/sysfs-fs-xfs
  F:    Documentation/admin-guide/xfs.rst
 -F:    Documentation/filesystems/xfs-*
 +F:    Documentation/filesystems/xfs/*
  F:    fs/xfs/
  F:    include/uapi/linux/dqblk_xfs.h
  F:    include/uapi/linux/fsmap.h
diff --combined fs/aio.c
index ffe65c1aab4e58770480d35a7a30d20ae0252f23,ec8fdac7f9b64c4c3bb634962ed1033044c4911c..bb2ff48991f35ed59479a004641e1452c7bad3ea
+++ b/fs/aio.c
@@@ -239,7 -239,6 +239,6 @@@ static struct ctl_table aio_sysctls[] 
                .mode           = 0644,
                .proc_handler   = proc_doulongvec_minmax,
        },
-       {}
  };
  
  static void __init aio_sysctl_init(void)
@@@ -266,7 -265,7 +265,7 @@@ static struct file *aio_private_file(st
                return ERR_CAST(inode);
  
        inode->i_mapping->a_ops = &aio_ctx_aops;
 -      inode->i_mapping->private_data = ctx;
 +      inode->i_mapping->i_private_data = ctx;
        inode->i_size = PAGE_SIZE * nr_pages;
  
        file = alloc_file_pseudo(inode, aio_mnt, "[aio]",
@@@ -316,10 -315,10 +315,10 @@@ static void put_aio_ring_file(struct ki
  
                /* Prevent further access to the kioctx from migratepages */
                i_mapping = aio_ring_file->f_mapping;
 -              spin_lock(&i_mapping->private_lock);
 -              i_mapping->private_data = NULL;
 +              spin_lock(&i_mapping->i_private_lock);
 +              i_mapping->i_private_data = NULL;
                ctx->aio_ring_file = NULL;
 -              spin_unlock(&i_mapping->private_lock);
 +              spin_unlock(&i_mapping->i_private_lock);
  
                fput(aio_ring_file);
        }
@@@ -422,9 -421,9 +421,9 @@@ static int aio_migrate_folio(struct add
  
        rc = 0;
  
 -      /* mapping->private_lock here protects against the kioctx teardown.  */
 -      spin_lock(&mapping->private_lock);
 -      ctx = mapping->private_data;
 +      /* mapping->i_private_lock here protects against the kioctx teardown.  */
 +      spin_lock(&mapping->i_private_lock);
 +      ctx = mapping->i_private_data;
        if (!ctx) {
                rc = -EINVAL;
                goto out;
  out_unlock:
        mutex_unlock(&ctx->ring_lock);
  out:
 -      spin_unlock(&mapping->private_lock);
 +      spin_unlock(&mapping->i_private_lock);
        return rc;
  }
  #else
@@@ -1106,11 -1105,6 +1105,11 @@@ static inline void iocb_destroy(struct 
        kmem_cache_free(kiocb_cachep, iocb);
  }
  
 +struct aio_waiter {
 +      struct wait_queue_entry w;
 +      size_t                  min_nr;
 +};
 +
  /* aio_complete
   *    Called when the io request on the given iocb is complete.
   */
@@@ -1119,7 -1113,7 +1118,7 @@@ static void aio_complete(struct aio_kio
        struct kioctx   *ctx = iocb->ki_ctx;
        struct aio_ring *ring;
        struct io_event *ev_page, *event;
 -      unsigned tail, pos, head;
 +      unsigned tail, pos, head, avail;
        unsigned long   flags;
  
        /*
        ctx->completed_events++;
        if (ctx->completed_events > 1)
                refill_reqs_available(ctx, head, tail);
 +
 +      avail = tail > head
 +              ? tail - head
 +              : tail + ctx->nr_events - head;
        spin_unlock_irqrestore(&ctx->completion_lock, flags);
  
        pr_debug("added to ring %p at [%u]\n", iocb, tail);
         * from IRQ context.
         */
        if (iocb->ki_eventfd)
 -              eventfd_signal(iocb->ki_eventfd, 1);
 +              eventfd_signal(iocb->ki_eventfd);
  
        /*
         * We have to order our ring_info tail store above and test
         */
        smp_mb();
  
 -      if (waitqueue_active(&ctx->wait))
 -              wake_up(&ctx->wait);
 +      if (waitqueue_active(&ctx->wait)) {
 +              struct aio_waiter *curr, *next;
 +              unsigned long flags;
 +
 +              spin_lock_irqsave(&ctx->wait.lock, flags);
 +              list_for_each_entry_safe(curr, next, &ctx->wait.head, w.entry)
 +                      if (avail >= curr->min_nr) {
 +                              list_del_init_careful(&curr->w.entry);
 +                              wake_up_process(curr->w.private);
 +                      }
 +              spin_unlock_irqrestore(&ctx->wait.lock, flags);
 +      }
  }
  
  static inline void iocb_put(struct aio_kiocb *iocb)
@@@ -1309,9 -1289,7 +1308,9 @@@ static long read_events(struct kioctx *
                        struct io_event __user *event,
                        ktime_t until)
  {
 -      long ret = 0;
 +      struct hrtimer_sleeper  t;
 +      struct aio_waiter       w;
 +      long ret = 0, ret2 = 0;
  
        /*
         * Note that aio_read_events() is being called as the conditional - i.e.
         * the ringbuffer empty. So in practice we should be ok, but it's
         * something to be aware of when touching this code.
         */
 -      if (until == 0)
 -              aio_read_events(ctx, min_nr, nr, event, &ret);
 -      else
 -              wait_event_interruptible_hrtimeout(ctx->wait,
 -                              aio_read_events(ctx, min_nr, nr, event, &ret),
 -                              until);
 +      aio_read_events(ctx, min_nr, nr, event, &ret);
 +      if (until == 0 || ret < 0 || ret >= min_nr)
 +              return ret;
 +
 +      hrtimer_init_sleeper_on_stack(&t, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 +      if (until != KTIME_MAX) {
 +              hrtimer_set_expires_range_ns(&t.timer, until, current->timer_slack_ns);
 +              hrtimer_sleeper_start_expires(&t, HRTIMER_MODE_REL);
 +      }
 +
 +      init_wait(&w.w);
 +
 +      while (1) {
 +              unsigned long nr_got = ret;
 +
 +              w.min_nr = min_nr - ret;
 +
 +              ret2 = prepare_to_wait_event(&ctx->wait, &w.w, TASK_INTERRUPTIBLE);
 +              if (!ret2 && !t.task)
 +                      ret2 = -ETIME;
 +
 +              if (aio_read_events(ctx, min_nr, nr, event, &ret) || ret2)
 +                      break;
 +
 +              if (nr_got == ret)
 +                      schedule();
 +      }
 +
 +      finish_wait(&ctx->wait, &w.w);
 +      hrtimer_cancel(&t.timer);
 +      destroy_hrtimer_on_stack(&t.timer);
 +
        return ret;
  }
  
@@@ -1545,7 -1497,7 +1544,7 @@@ static ssize_t aio_setup_rw(int rw, con
        size_t len = iocb->aio_nbytes;
  
        if (!vectored) {
 -              ssize_t ret = import_single_range(rw, buf, len, *iovec, iter);
 +              ssize_t ret = import_ubuf(rw, buf, len, iter);
                *iovec = NULL;
                return ret;
        }
diff --combined fs/dcache.c
index 2ba37643b9c5e8049cd9a0a45a20df1dce98cab0,0bcfdc66823e28770b956d3f364abd5bcb1b3abb..df49d29ca15453399f822ea4db0c8179be42446a
@@@ -191,7 -191,6 +191,6 @@@ static struct ctl_table fs_dcache_sysct
                .mode           = 0444,
                .proc_handler   = proc_nr_dentry,
        },
-       { }
  };
  
  static int __init init_fs_dcache_sysctls(void)
@@@ -428,8 -427,7 +427,8 @@@ static void d_lru_add(struct dentry *de
        this_cpu_inc(nr_dentry_unused);
        if (d_is_negative(dentry))
                this_cpu_inc(nr_dentry_negative);
 -      WARN_ON_ONCE(!list_lru_add(&dentry->d_sb->s_dentry_lru, &dentry->d_lru));
 +      WARN_ON_ONCE(!list_lru_add_obj(
 +                      &dentry->d_sb->s_dentry_lru, &dentry->d_lru));
  }
  
  static void d_lru_del(struct dentry *dentry)
        this_cpu_dec(nr_dentry_unused);
        if (d_is_negative(dentry))
                this_cpu_dec(nr_dentry_negative);
 -      WARN_ON_ONCE(!list_lru_del(&dentry->d_sb->s_dentry_lru, &dentry->d_lru));
 +      WARN_ON_ONCE(!list_lru_del_obj(
 +                      &dentry->d_sb->s_dentry_lru, &dentry->d_lru));
  }
  
  static void d_shrink_del(struct dentry *dentry)
@@@ -1242,7 -1239,7 +1241,7 @@@ static enum lru_status dentry_lru_isola
                 *
                 * This is guaranteed by the fact that all LRU management
                 * functions are intermediated by the LRU API calls like
 -               * list_lru_add and list_lru_del. List movement in this file
 +               * list_lru_add_obj and list_lru_del_obj. List movement in this file
                 * only ever occur through this functions or through callbacks
                 * like this one, that are called from the LRU API.
                 *
diff --combined fs/exec.c
index 88ce7d9ceff5884b03573a6fb6b0227decf4fe85,dc7e5d66b3fa99782fdd065c2b28a665a3da08a9..73e4045df271d148377340a40c77271ee36b2161
+++ b/fs/exec.c
@@@ -66,7 -66,6 +66,7 @@@
  #include <linux/coredump.h>
  #include <linux/time_namespace.h>
  #include <linux/user_events.h>
 +#include <linux/rseq.h>
  
  #include <linux/uaccess.h>
  #include <asm/mmu_context.h>
@@@ -1579,10 -1578,11 +1579,10 @@@ static void check_unsafe_exec(struct li
         * will be able to manipulate the current directory, etc.
         * It would be nice to force an unshare instead...
         */
 -      t = p;
        n_fs = 1;
        spin_lock(&p->fs->lock);
        rcu_read_lock();
 -      while_each_thread(p, t) {
 +      for_other_threads(p, t) {
                if (t->fs == p->fs)
                        n_fs++;
        }
@@@ -2165,7 -2165,6 +2165,6 @@@ static struct ctl_table fs_exec_sysctls
                .extra1         = SYSCTL_ZERO,
                .extra2         = SYSCTL_TWO,
        },
-       { }
  };
  
  static int __init init_fs_exec_sysctls(void)
diff --combined fs/file_table.c
index 3ba764d73fc9b97ded9c8782717cb4baf6971be0,d3af9feb4ad59743df43d9f8f24c82e6e15de7c9..c5ac2cc051356afeada8e8eeeddaf666454ce67d
@@@ -75,6 -75,18 +75,6 @@@ static inline void file_free(struct fil
        }
  }
  
 -void release_empty_file(struct file *f)
 -{
 -      WARN_ON_ONCE(f->f_mode & (FMODE_BACKING | FMODE_OPENED));
 -      if (atomic_long_dec_and_test(&f->f_count)) {
 -              security_file_free(f);
 -              put_cred(f->f_cred);
 -              if (likely(!(f->f_mode & FMODE_NOACCOUNT)))
 -                      percpu_counter_dec(&nr_files);
 -              kmem_cache_free(filp_cachep, f);
 -      }
 -}
 -
  /*
   * Return the total number of open files in the system
   */
@@@ -130,7 -142,6 +130,6 @@@ static struct ctl_table fs_stat_sysctls
                .extra1         = &sysctl_nr_open_min,
                .extra2         = &sysctl_nr_open_max,
        },
-       { }
  };
  
  static int __init init_fs_stat_sysctls(void)
@@@ -407,7 -418,7 +406,7 @@@ static void delayed_fput(struct work_st
  
  static void ____fput(struct callback_head *work)
  {
 -      __fput(container_of(work, struct file, f_rcuhead));
 +      __fput(container_of(work, struct file, f_task_work));
  }
  
  /*
@@@ -433,13 -444,9 +432,13 @@@ void fput(struct file *file
        if (atomic_long_dec_and_test(&file->f_count)) {
                struct task_struct *task = current;
  
 +              if (unlikely(!(file->f_mode & (FMODE_BACKING | FMODE_OPENED)))) {
 +                      file_free(file);
 +                      return;
 +              }
                if (likely(!in_interrupt() && !(task->flags & PF_KTHREAD))) {
 -                      init_task_work(&file->f_rcuhead, ____fput);
 -                      if (!task_work_add(task, &file->f_rcuhead, TWA_RESUME))
 +                      init_task_work(&file->f_task_work, ____fput);
 +                      if (!task_work_add(task, &file->f_task_work, TWA_RESUME))
                                return;
                        /*
                         * After this task has run exit_task_work(),
diff --combined fs/inode.c
index 99d8754a74a30b1d365a1b1aded4a46f7dd53792,0a9dd0c3e03fec55e86986a6e92ea085214d0cc6..d23362a671ddae34101ea5d112274ae951de6a8a
@@@ -129,7 -129,6 +129,6 @@@ static struct ctl_table inodes_sysctls[
                .mode           = 0444,
                .proc_handler   = proc_nr_inodes,
        },
-       { }
  };
  
  static int __init init_fs_inode_sysctls(void)
@@@ -209,7 -208,7 +208,7 @@@ int inode_init_always(struct super_bloc
        atomic_set(&mapping->nr_thps, 0);
  #endif
        mapping_set_gfp_mask(mapping, GFP_HIGHUSER_MOVABLE);
 -      mapping->private_data = NULL;
 +      mapping->i_private_data = NULL;
        mapping->writeback_index = 0;
        init_rwsem(&mapping->invalidate_lock);
        lockdep_set_class_and_name(&mapping->invalidate_lock,
@@@ -398,8 -397,8 +397,8 @@@ static void __address_space_init_once(s
  {
        xa_init_flags(&mapping->i_pages, XA_FLAGS_LOCK_IRQ | XA_FLAGS_ACCOUNT);
        init_rwsem(&mapping->i_mmap_rwsem);
 -      INIT_LIST_HEAD(&mapping->private_list);
 -      spin_lock_init(&mapping->private_lock);
 +      INIT_LIST_HEAD(&mapping->i_private_list);
 +      spin_lock_init(&mapping->i_private_lock);
        mapping->i_mmap = RB_ROOT_CACHED;
  }
  
@@@ -464,7 -463,7 +463,7 @@@ static void __inode_add_lru(struct inod
        if (!mapping_shrinkable(&inode->i_data))
                return;
  
 -      if (list_lru_add(&inode->i_sb->s_inode_lru, &inode->i_lru))
 +      if (list_lru_add_obj(&inode->i_sb->s_inode_lru, &inode->i_lru))
                this_cpu_inc(nr_unused);
        else if (rotate)
                inode->i_state |= I_REFERENCED;
@@@ -482,7 -481,7 +481,7 @@@ void inode_add_lru(struct inode *inode
  
  static void inode_lru_list_del(struct inode *inode)
  {
 -      if (list_lru_del(&inode->i_sb->s_inode_lru, &inode->i_lru))
 +      if (list_lru_del_obj(&inode->i_sb->s_inode_lru, &inode->i_lru))
                this_cpu_dec(nr_unused);
  }
  
@@@ -620,7 -619,7 +619,7 @@@ void clear_inode(struct inode *inode
         * nor even WARN_ON(!mapping_empty).
         */
        xa_unlock_irq(&inode->i_data.i_pages);
 -      BUG_ON(!list_empty(&inode->i_data.private_list));
 +      BUG_ON(!list_empty(&inode->i_data.i_private_list));
        BUG_ON(!(inode->i_state & I_FREEING));
        BUG_ON(inode->i_state & I_CLEAR);
        BUG_ON(!list_empty(&inode->i_wb_list));
@@@ -1836,37 -1835,37 +1835,37 @@@ EXPORT_SYMBOL(bmap)
   * earlier than or equal to either the ctime or mtime,
   * or if at least a day has passed since the last atime update.
   */
 -static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
 +static bool relatime_need_update(struct vfsmount *mnt, struct inode *inode,
                             struct timespec64 now)
  {
        struct timespec64 atime, mtime, ctime;
  
        if (!(mnt->mnt_flags & MNT_RELATIME))
 -              return 1;
 +              return true;
        /*
         * Is mtime younger than or equal to atime? If yes, update atime:
         */
        atime = inode_get_atime(inode);
        mtime = inode_get_mtime(inode);
        if (timespec64_compare(&mtime, &atime) >= 0)
 -              return 1;
 +              return true;
        /*
         * Is ctime younger than or equal to atime? If yes, update atime:
         */
        ctime = inode_get_ctime(inode);
        if (timespec64_compare(&ctime, &atime) >= 0)
 -              return 1;
 +              return true;
  
        /*
         * Is the previous atime value older than a day? If yes,
         * update atime:
         */
        if ((long)(now.tv_sec - atime.tv_sec) >= 24*60*60)
 -              return 1;
 +              return true;
        /*
         * Good, we can skip the atime update:
         */
 -      return 0;
 +      return false;
  }
  
  /**
@@@ -2404,7 -2403,7 +2403,7 @@@ EXPORT_SYMBOL(inode_init_owner)
   * the vfsmount must be passed through @idmap. This function will then take
   * care to map the inode according to @idmap before checking permissions.
   * On non-idmapped mounts or if permission checking is to be performed on the
 - * raw inode simply passs @nop_mnt_idmap.
 + * raw inode simply pass @nop_mnt_idmap.
   */
  bool inode_owner_or_capable(struct mnt_idmap *idmap,
                            const struct inode *inode)
diff --combined fs/lockd/svc.c
index 0d6cb3fdc0e16eef619d6d5f78de2acd93b18926,96dc040656aefa3e05795493021cc62d9729acc5..ce5862482097a1ef8b0b7d1e1adbb0bc0af328e3
@@@ -345,10 -345,10 +345,10 @@@ static int lockd_get(void
  
        serv->sv_maxconn = nlm_max_connections;
        error = svc_set_num_threads(serv, NULL, 1);
 -      /* The thread now holds the only reference */
 -      svc_put(serv);
 -      if (error < 0)
 +      if (error < 0) {
 +              svc_destroy(&serv);
                return error;
 +      }
  
        nlmsvc_serv = serv;
        register_inetaddr_notifier(&lockd_inetaddr_notifier);
@@@ -372,9 -372,11 +372,9 @@@ static void lockd_put(void
        unregister_inet6addr_notifier(&lockd_inet6addr_notifier);
  #endif
  
 -      svc_get(nlmsvc_serv);
        svc_set_num_threads(nlmsvc_serv, NULL, 0);
 -      svc_put(nlmsvc_serv);
        timer_delete_sync(&nlmsvc_retry);
 -      nlmsvc_serv = NULL;
 +      svc_destroy(&nlmsvc_serv);
        dprintk("lockd_down: service destroyed\n");
  }
  
@@@ -473,7 -475,6 +473,6 @@@ static struct ctl_table nlm_sysctls[] 
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
        },
-       { }
  };
  
  #endif        /* CONFIG_SYSCTL */
diff --combined fs/namei.c
index faae721e4d637c7eb9de679740044862f4d997c8,03660a29664fd47d7096a578cfbc6e4d38493322..963576e67f6279c64d33b04f08c6fd8f84033691
@@@ -289,7 -289,7 +289,7 @@@ EXPORT_SYMBOL(putname)
   * the vfsmount must be passed through @idmap. This function will then take
   * care to map the inode according to @idmap before checking permissions.
   * On non-idmapped mounts or if permission checking is to be performed on the
 - * raw inode simply passs @nop_mnt_idmap.
 + * raw inode simply pass @nop_mnt_idmap.
   */
  static int check_acl(struct mnt_idmap *idmap,
                     struct inode *inode, int mask)
   * the vfsmount must be passed through @idmap. This function will then take
   * care to map the inode according to @idmap before checking permissions.
   * On non-idmapped mounts or if permission checking is to be performed on the
 - * raw inode simply passs @nop_mnt_idmap.
 + * raw inode simply pass @nop_mnt_idmap.
   */
  static int acl_permission_check(struct mnt_idmap *idmap,
                                struct inode *inode, int mask)
   * the vfsmount must be passed through @idmap. This function will then take
   * care to map the inode according to @idmap before checking permissions.
   * On non-idmapped mounts or if permission checking is to be performed on the
 - * raw inode simply passs @nop_mnt_idmap.
 + * raw inode simply pass @nop_mnt_idmap.
   */
  int generic_permission(struct mnt_idmap *idmap, struct inode *inode,
                       int mask)
@@@ -1071,7 -1071,6 +1071,6 @@@ static struct ctl_table namei_sysctls[
                .extra1         = SYSCTL_ZERO,
                .extra2         = SYSCTL_TWO,
        },
-       { }
  };
  
  static int __init init_fs_namei_sysctls(void)
@@@ -2467,7 -2466,7 +2466,7 @@@ static int handle_lookup_down(struct na
        return PTR_ERR(step_into(nd, WALK_NOFOLLOW, nd->path.dentry));
  }
  
 -/* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
 +/* Returns 0 and nd will be valid on success; Returns error, otherwise. */
  static int path_lookupat(struct nameidata *nd, unsigned flags, struct path *path)
  {
        const char *s = path_init(nd, flags);
@@@ -2522,7 -2521,7 +2521,7 @@@ int filename_lookup(int dfd, struct fil
        return retval;
  }
  
 -/* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
 +/* Returns 0 and nd will be valid on success; Returns error, otherwise. */
  static int path_parentat(struct nameidata *nd, unsigned flags,
                                struct path *parent)
  {
@@@ -3158,7 -3157,7 +3157,7 @@@ static inline umode_t vfs_prepare_mode(
   * the vfsmount must be passed through @idmap. This function will then take
   * care to map the inode according to @idmap before checking permissions.
   * On non-idmapped mounts or if permission checking is to be performed on the
 - * raw inode simply passs @nop_mnt_idmap.
 + * raw inode simply pass @nop_mnt_idmap.
   */
  int vfs_create(struct mnt_idmap *idmap, struct inode *dir,
               struct dentry *dentry, umode_t mode, bool want_excl)
@@@ -3646,7 -3645,7 +3645,7 @@@ static int do_open(struct nameidata *nd
   * the vfsmount must be passed through @idmap. This function will then take
   * care to map the inode according to @idmap before checking permissions.
   * On non-idmapped mounts or if permission checking is to be performed on the
 - * raw inode simply passs @nop_mnt_idmap.
 + * raw inode simply pass @nop_mnt_idmap.
   */
  static int vfs_tmpfile(struct mnt_idmap *idmap,
                       const struct path *parentpath,
@@@ -3785,7 -3784,10 +3784,7 @@@ static struct file *path_openat(struct 
                WARN_ON(1);
                error = -EINVAL;
        }
 -      if (unlikely(file->f_mode & FMODE_OPENED))
 -              fput(file);
 -      else
 -              release_empty_file(file);
 +      fput(file);
        if (error == -EOPENSTALE) {
                if (flags & LOOKUP_RCU)
                        error = -ECHILD;
@@@ -3951,7 -3953,7 +3950,7 @@@ EXPORT_SYMBOL(user_path_create)
   * the vfsmount must be passed through @idmap. This function will then take
   * care to map the inode according to @idmap before checking permissions.
   * On non-idmapped mounts or if permission checking is to be performed on the
 - * raw inode simply passs @nop_mnt_idmap.
 + * raw inode simply pass @nop_mnt_idmap.
   */
  int vfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
              struct dentry *dentry, umode_t mode, dev_t dev)
@@@ -4077,7 -4079,7 +4076,7 @@@ SYSCALL_DEFINE3(mknod, const char __use
   * the vfsmount must be passed through @idmap. This function will then take
   * care to map the inode according to @idmap before checking permissions.
   * On non-idmapped mounts or if permission checking is to be performed on the
 - * raw inode simply passs @nop_mnt_idmap.
 + * raw inode simply pass @nop_mnt_idmap.
   */
  int vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
              struct dentry *dentry, umode_t mode)
@@@ -4158,7 -4160,7 +4157,7 @@@ SYSCALL_DEFINE2(mkdir, const char __use
   * the vfsmount must be passed through @idmap. This function will then take
   * care to map the inode according to @idmap before checking permissions.
   * On non-idmapped mounts or if permission checking is to be performed on the
 - * raw inode simply passs @nop_mnt_idmap.
 + * raw inode simply pass @nop_mnt_idmap.
   */
  int vfs_rmdir(struct mnt_idmap *idmap, struct inode *dir,
                     struct dentry *dentry)
@@@ -4287,7 -4289,7 +4286,7 @@@ SYSCALL_DEFINE1(rmdir, const char __use
   * the vfsmount must be passed through @idmap. This function will then take
   * care to map the inode according to @idmap before checking permissions.
   * On non-idmapped mounts or if permission checking is to be performed on the
 - * raw inode simply passs @nop_mnt_idmap.
 + * raw inode simply pass @nop_mnt_idmap.
   */
  int vfs_unlink(struct mnt_idmap *idmap, struct inode *dir,
               struct dentry *dentry, struct inode **delegated_inode)
@@@ -4440,7 -4442,7 +4439,7 @@@ SYSCALL_DEFINE1(unlink, const char __us
   * the vfsmount must be passed through @idmap. This function will then take
   * care to map the inode according to @idmap before checking permissions.
   * On non-idmapped mounts or if permission checking is to be performed on the
 - * raw inode simply passs @nop_mnt_idmap.
 + * raw inode simply pass @nop_mnt_idmap.
   */
  int vfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
                struct dentry *dentry, const char *oldname)
@@@ -4532,7 -4534,7 +4531,7 @@@ SYSCALL_DEFINE2(symlink, const char __u
   * the vfsmount must be passed through @idmap. This function will then take
   * care to map the inode according to @idmap before checking permissions.
   * On non-idmapped mounts or if permission checking is to be performed on the
 - * raw inode simply passs @nop_mnt_idmap.
 + * raw inode simply pass @nop_mnt_idmap.
   */
  int vfs_link(struct dentry *old_dentry, struct mnt_idmap *idmap,
             struct inode *dir, struct dentry *new_dentry,
diff --combined fs/namespace.c
index 95b2fff91f6730db8e2da9d9b3f2125c9f9ca098,91ca4693f905f39c1a138a493c3ab2e4876dd8f8..ef1fd6829814cdf9f97ddf10968a11fc7b91a3c9
@@@ -32,7 -32,6 +32,7 @@@
  #include <linux/fs_context.h>
  #include <linux/shmem_fs.h>
  #include <linux/mnt_idmapping.h>
 +#include <linux/nospec.h>
  
  #include "pnode.h"
  #include "internal.h"
@@@ -69,9 -68,6 +69,9 @@@ static u64 event
  static DEFINE_IDA(mnt_id_ida);
  static DEFINE_IDA(mnt_group_ida);
  
 +/* Don't allow confusion with old 32bit mount ID */
 +static atomic64_t mnt_id_ctr = ATOMIC64_INIT(1ULL << 32);
 +
  static struct hlist_head *mount_hashtable __ro_after_init;
  static struct hlist_head *mountpoint_hashtable __ro_after_init;
  static struct kmem_cache *mnt_cache __ro_after_init;
@@@ -135,7 -131,6 +135,7 @@@ static int mnt_alloc_id(struct mount *m
        if (res < 0)
                return res;
        mnt->mnt_id = res;
 +      mnt->mnt_id_unique = atomic64_inc_return(&mnt_id_ctr);
        return 0;
  }
  
@@@ -735,6 -730,21 +735,6 @@@ struct vfsmount *lookup_mnt(const struc
        return m;
  }
  
 -static inline void lock_ns_list(struct mnt_namespace *ns)
 -{
 -      spin_lock(&ns->ns_lock);
 -}
 -
 -static inline void unlock_ns_list(struct mnt_namespace *ns)
 -{
 -      spin_unlock(&ns->ns_lock);
 -}
 -
 -static inline bool mnt_is_cursor(struct mount *mnt)
 -{
 -      return mnt->mnt.mnt_flags & MNT_CURSOR;
 -}
 -
  /*
   * __is_local_mountpoint - Test to see if dentry is a mountpoint in the
   *                         current mount namespace.
  bool __is_local_mountpoint(struct dentry *dentry)
  {
        struct mnt_namespace *ns = current->nsproxy->mnt_ns;
 -      struct mount *mnt;
 +      struct mount *mnt, *n;
        bool is_covered = false;
  
        down_read(&namespace_sem);
 -      lock_ns_list(ns);
 -      list_for_each_entry(mnt, &ns->list, mnt_list) {
 -              if (mnt_is_cursor(mnt))
 -                      continue;
 +      rbtree_postorder_for_each_entry_safe(mnt, n, &ns->mounts, mnt_node) {
                is_covered = (mnt->mnt_mountpoint == dentry);
                if (is_covered)
                        break;
        }
 -      unlock_ns_list(ns);
        up_read(&namespace_sem);
  
        return is_covered;
@@@ -1008,30 -1022,6 +1008,30 @@@ void mnt_change_mountpoint(struct moun
        mnt_add_count(old_parent, -1);
  }
  
 +static inline struct mount *node_to_mount(struct rb_node *node)
 +{
 +      return node ? rb_entry(node, struct mount, mnt_node) : NULL;
 +}
 +
 +static void mnt_add_to_ns(struct mnt_namespace *ns, struct mount *mnt)
 +{
 +      struct rb_node **link = &ns->mounts.rb_node;
 +      struct rb_node *parent = NULL;
 +
 +      WARN_ON(mnt->mnt.mnt_flags & MNT_ONRB);
 +      mnt->mnt_ns = ns;
 +      while (*link) {
 +              parent = *link;
 +              if (mnt->mnt_id_unique < node_to_mount(parent)->mnt_id_unique)
 +                      link = &parent->rb_left;
 +              else
 +                      link = &parent->rb_right;
 +      }
 +      rb_link_node(&mnt->mnt_node, parent, link);
 +      rb_insert_color(&mnt->mnt_node, &ns->mounts);
 +      mnt->mnt.mnt_flags |= MNT_ONRB;
 +}
 +
  /*
   * vfsmount lock must be held for write
   */
@@@ -1045,13 -1035,12 +1045,13 @@@ static void commit_tree(struct mount *m
        BUG_ON(parent == mnt);
  
        list_add_tail(&head, &mnt->mnt_list);
 -      list_for_each_entry(m, &head, mnt_list)
 -              m->mnt_ns = n;
 +      while (!list_empty(&head)) {
 +              m = list_first_entry(&head, typeof(*m), mnt_list);
 +              list_del(&m->mnt_list);
  
 -      list_splice(&head, n->list.prev);
 -
 -      n->mounts += n->pending_mounts;
 +              mnt_add_to_ns(n, m);
 +      }
 +      n->nr_mounts += n->pending_mounts;
        n->pending_mounts = 0;
  
        __attach_mnt(mnt, parent);
@@@ -1199,7 -1188,7 +1199,7 @@@ static struct mount *clone_mnt(struct m
        }
  
        mnt->mnt.mnt_flags = old->mnt.mnt_flags;
 -      mnt->mnt.mnt_flags &= ~(MNT_WRITE_HOLD|MNT_MARKED|MNT_INTERNAL);
 +      mnt->mnt.mnt_flags &= ~(MNT_WRITE_HOLD|MNT_MARKED|MNT_INTERNAL|MNT_ONRB);
  
        atomic_inc(&sb->s_active);
        mnt->mnt.mnt_idmap = mnt_idmap_get(mnt_idmap(&old->mnt));
@@@ -1424,57 -1413,65 +1424,57 @@@ struct vfsmount *mnt_clone_internal(con
        return &p->mnt;
  }
  
 -#ifdef CONFIG_PROC_FS
 -static struct mount *mnt_list_next(struct mnt_namespace *ns,
 -                                 struct list_head *p)
 +/*
 + * Returns the mount which either has the specified mnt_id, or has the next
 + * smallest id afer the specified one.
 + */
 +static struct mount *mnt_find_id_at(struct mnt_namespace *ns, u64 mnt_id)
  {
 -      struct mount *mnt, *ret = NULL;
 +      struct rb_node *node = ns->mounts.rb_node;
 +      struct mount *ret = NULL;
  
 -      lock_ns_list(ns);
 -      list_for_each_continue(p, &ns->list) {
 -              mnt = list_entry(p, typeof(*mnt), mnt_list);
 -              if (!mnt_is_cursor(mnt)) {
 -                      ret = mnt;
 -                      break;
 +      while (node) {
 +              struct mount *m = node_to_mount(node);
 +
 +              if (mnt_id <= m->mnt_id_unique) {
 +                      ret = node_to_mount(node);
 +                      if (mnt_id == m->mnt_id_unique)
 +                              break;
 +                      node = node->rb_left;
 +              } else {
 +                      node = node->rb_right;
                }
        }
 -      unlock_ns_list(ns);
 -
        return ret;
  }
  
 +#ifdef CONFIG_PROC_FS
 +
  /* iterator; we want it to have access to namespace_sem, thus here... */
  static void *m_start(struct seq_file *m, loff_t *pos)
  {
        struct proc_mounts *p = m->private;
 -      struct list_head *prev;
  
        down_read(&namespace_sem);
 -      if (!*pos) {
 -              prev = &p->ns->list;
 -      } else {
 -              prev = &p->cursor.mnt_list;
 -
 -              /* Read after we'd reached the end? */
 -              if (list_empty(prev))
 -                      return NULL;
 -      }
  
 -      return mnt_list_next(p->ns, prev);
 +      return mnt_find_id_at(p->ns, *pos);
  }
  
  static void *m_next(struct seq_file *m, void *v, loff_t *pos)
  {
 -      struct proc_mounts *p = m->private;
 -      struct mount *mnt = v;
 +      struct mount *next = NULL, *mnt = v;
 +      struct rb_node *node = rb_next(&mnt->mnt_node);
  
        ++*pos;
 -      return mnt_list_next(p->ns, &mnt->mnt_list);
 +      if (node) {
 +              next = node_to_mount(node);
 +              *pos = next->mnt_id_unique;
 +      }
 +      return next;
  }
  
  static void m_stop(struct seq_file *m, void *v)
  {
 -      struct proc_mounts *p = m->private;
 -      struct mount *mnt = v;
 -
 -      lock_ns_list(p->ns);
 -      if (mnt)
 -              list_move_tail(&p->cursor.mnt_list, &mnt->mnt_list);
 -      else
 -              list_del_init(&p->cursor.mnt_list);
 -      unlock_ns_list(p->ns);
        up_read(&namespace_sem);
  }
  
@@@ -1492,6 -1489,14 +1492,6 @@@ const struct seq_operations mounts_op 
        .show   = m_show,
  };
  
 -void mnt_cursor_del(struct mnt_namespace *ns, struct mount *cursor)
 -{
 -      down_read(&namespace_sem);
 -      lock_ns_list(ns);
 -      list_del(&cursor->mnt_list);
 -      unlock_ns_list(ns);
 -      up_read(&namespace_sem);
 -}
  #endif  /* CONFIG_PROC_FS */
  
  /**
@@@ -1633,10 -1638,7 +1633,10 @@@ static void umount_tree(struct mount *m
        /* Gather the mounts to umount */
        for (p = mnt; p; p = next_mnt(p, mnt)) {
                p->mnt.mnt_flags |= MNT_UMOUNT;
 -              list_move(&p->mnt_list, &tmp_list);
 +              if (p->mnt.mnt_flags & MNT_ONRB)
 +                      move_from_ns(p, &tmp_list);
 +              else
 +                      list_move(&p->mnt_list, &tmp_list);
        }
  
        /* Hide the mounts from mnt_mounts */
                list_del_init(&p->mnt_list);
                ns = p->mnt_ns;
                if (ns) {
 -                      ns->mounts--;
 +                      ns->nr_mounts--;
                        __touch_mnt_namespace(ns);
                }
                p->mnt_ns = NULL;
@@@ -1782,16 -1784,14 +1782,16 @@@ static int do_umount(struct mount *mnt
  
        event++;
        if (flags & MNT_DETACH) {
 -              if (!list_empty(&mnt->mnt_list))
 +              if (mnt->mnt.mnt_flags & MNT_ONRB ||
 +                  !list_empty(&mnt->mnt_list))
                        umount_tree(mnt, UMOUNT_PROPAGATE);
                retval = 0;
        } else {
                shrink_submounts(mnt);
                retval = -EBUSY;
                if (!propagate_mount_busy(mnt, 2)) {
 -                      if (!list_empty(&mnt->mnt_list))
 +                      if (mnt->mnt.mnt_flags & MNT_ONRB ||
 +                          !list_empty(&mnt->mnt_list))
                                umount_tree(mnt, UMOUNT_PROPAGATE|UMOUNT_SYNC);
                        retval = 0;
                }
@@@ -2209,9 -2209,9 +2209,9 @@@ int count_mounts(struct mnt_namespace *
        unsigned int mounts = 0;
        struct mount *p;
  
 -      if (ns->mounts >= max)
 +      if (ns->nr_mounts >= max)
                return -ENOSPC;
 -      max -= ns->mounts;
 +      max -= ns->nr_mounts;
        if (ns->pending_mounts >= max)
                return -ENOSPC;
        max -= ns->pending_mounts;
@@@ -2355,12 -2355,8 +2355,12 @@@ static int attach_recursive_mnt(struct 
                touch_mnt_namespace(source_mnt->mnt_ns);
        } else {
                if (source_mnt->mnt_ns) {
 +                      LIST_HEAD(head);
 +
                        /* move from anon - the caller will destroy */
 -                      list_del_init(&source_mnt->mnt_ns->list);
 +                      for (p = source_mnt; p; p = next_mnt(p, source_mnt))
 +                              move_from_ns(p, &head);
 +                      list_del_init(&head);
                }
                if (beneath)
                        mnt_set_mountpoint_beneath(source_mnt, top_mnt, smp);
@@@ -2671,10 -2667,11 +2671,10 @@@ static struct file *open_detached_copy(
  
        lock_mount_hash();
        for (p = mnt; p; p = next_mnt(p, mnt)) {
 -              p->mnt_ns = ns;
 -              ns->mounts++;
 +              mnt_add_to_ns(ns, p);
 +              ns->nr_mounts++;
        }
        ns->root = mnt;
 -      list_add_tail(&ns->list, &mnt->mnt_list);
        mntget(&mnt->mnt);
        unlock_mount_hash();
        namespace_unlock();
@@@ -2878,12 -2875,7 +2878,12 @@@ static int do_remount(struct path *path
        if (IS_ERR(fc))
                return PTR_ERR(fc);
  
 +      /*
 +       * Indicate to the filesystem that the remount request is coming
 +       * from the legacy mount system call.
 +       */
        fc->oldapi = true;
 +
        err = parse_monolithic_mount_data(fc, data);
        if (!err) {
                down_write(&sb->s_umount);
@@@ -3034,7 -3026,6 +3034,7 @@@ static inline bool path_overmounted(con
   * can_move_mount_beneath - check that we can mount beneath the top mount
   * @from: mount to mount beneath
   * @to:   mount under which to mount
 + * @mp:   mountpoint of @to
   *
   * - Make sure that @to->dentry is actually the root of a mount under
   *   which we can mount another mount.
@@@ -3333,12 -3324,6 +3333,12 @@@ static int do_new_mount(struct path *pa
        if (IS_ERR(fc))
                return PTR_ERR(fc);
  
 +      /*
 +       * Indicate to the filesystem that the mount request is coming
 +       * from the legacy mount system call.
 +       */
 +      fc->oldapi = true;
 +
        if (subtype)
                err = vfs_parse_fs_string(fc, "subtype",
                                          subtype, strlen(subtype));
@@@ -3749,8 -3734,9 +3749,8 @@@ static struct mnt_namespace *alloc_mnt_
        if (!anon)
                new_ns->seq = atomic64_add_return(1, &mnt_ns_seq);
        refcount_set(&new_ns->ns.count, 1);
 -      INIT_LIST_HEAD(&new_ns->list);
 +      new_ns->mounts = RB_ROOT;
        init_waitqueue_head(&new_ns->poll);
 -      spin_lock_init(&new_ns->ns_lock);
        new_ns->user_ns = get_user_ns(user_ns);
        new_ns->ucounts = ucounts;
        return new_ns;
@@@ -3797,6 -3783,7 +3797,6 @@@ struct mnt_namespace *copy_mnt_ns(unsig
                unlock_mount_hash();
        }
        new_ns->root = new;
 -      list_add_tail(&new_ns->list, &new->mnt_list);
  
        /*
         * Second pass: switch the tsk->fs->* elements and mark new vfsmounts
        p = old;
        q = new;
        while (p) {
 -              q->mnt_ns = new_ns;
 -              new_ns->mounts++;
 +              mnt_add_to_ns(new_ns, q);
 +              new_ns->nr_mounts++;
                if (new_fs) {
                        if (&p->mnt == new_fs->root.mnt) {
                                new_fs->root.mnt = mntget(&q->mnt);
@@@ -3849,9 -3836,10 +3849,9 @@@ struct dentry *mount_subtree(struct vfs
                mntput(m);
                return ERR_CAST(ns);
        }
 -      mnt->mnt_ns = ns;
        ns->root = mnt;
 -      ns->mounts++;
 -      list_add(&mnt->mnt_list, &ns->list);
 +      ns->nr_mounts++;
 +      mnt_add_to_ns(ns, mnt);
  
        err = vfs_path_lookup(m->mnt_root, m,
                        name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path);
@@@ -4029,9 -4017,10 +4029,9 @@@ SYSCALL_DEFINE3(fsmount, int, fs_fd, un
                goto err_path;
        }
        mnt = real_mount(newmount.mnt);
 -      mnt->mnt_ns = ns;
        ns->root = mnt;
 -      ns->mounts = 1;
 -      list_add(&mnt->mnt_list, &ns->list);
 +      ns->nr_mounts = 1;
 +      mnt_add_to_ns(ns, mnt);
        mntget(newmount.mnt);
  
        /* Attach to an apparent O_PATH fd with a note that we need to unmount
@@@ -4299,7 -4288,7 +4299,7 @@@ static int can_idmap_mount(const struc
         * Creating an idmapped mount with the filesystem wide idmapping
         * doesn't make sense so block that. We don't allow mushy semantics.
         */
 -      if (!check_fsmapping(kattr->mnt_idmap, m->mnt_sb))
 +      if (kattr->mnt_userns == m->mnt_sb->s_user_ns)
                return -EINVAL;
  
        /*
@@@ -4687,438 -4676,6 +4687,438 @@@ SYSCALL_DEFINE5(mount_setattr, int, dfd
        return err;
  }
  
 +int show_path(struct seq_file *m, struct dentry *root)
 +{
 +      if (root->d_sb->s_op->show_path)
 +              return root->d_sb->s_op->show_path(m, root);
 +
 +      seq_dentry(m, root, " \t\n\\");
 +      return 0;
 +}
 +
 +static struct vfsmount *lookup_mnt_in_ns(u64 id, struct mnt_namespace *ns)
 +{
 +      struct mount *mnt = mnt_find_id_at(ns, id);
 +
 +      if (!mnt || mnt->mnt_id_unique != id)
 +              return NULL;
 +
 +      return &mnt->mnt;
 +}
 +
 +struct kstatmount {
 +      struct statmount __user *buf;
 +      size_t bufsize;
 +      struct vfsmount *mnt;
 +      u64 mask;
 +      struct path root;
 +      struct statmount sm;
 +      struct seq_file seq;
 +};
 +
 +static u64 mnt_to_attr_flags(struct vfsmount *mnt)
 +{
 +      unsigned int mnt_flags = READ_ONCE(mnt->mnt_flags);
 +      u64 attr_flags = 0;
 +
 +      if (mnt_flags & MNT_READONLY)
 +              attr_flags |= MOUNT_ATTR_RDONLY;
 +      if (mnt_flags & MNT_NOSUID)
 +              attr_flags |= MOUNT_ATTR_NOSUID;
 +      if (mnt_flags & MNT_NODEV)
 +              attr_flags |= MOUNT_ATTR_NODEV;
 +      if (mnt_flags & MNT_NOEXEC)
 +              attr_flags |= MOUNT_ATTR_NOEXEC;
 +      if (mnt_flags & MNT_NODIRATIME)
 +              attr_flags |= MOUNT_ATTR_NODIRATIME;
 +      if (mnt_flags & MNT_NOSYMFOLLOW)
 +              attr_flags |= MOUNT_ATTR_NOSYMFOLLOW;
 +
 +      if (mnt_flags & MNT_NOATIME)
 +              attr_flags |= MOUNT_ATTR_NOATIME;
 +      else if (mnt_flags & MNT_RELATIME)
 +              attr_flags |= MOUNT_ATTR_RELATIME;
 +      else
 +              attr_flags |= MOUNT_ATTR_STRICTATIME;
 +
 +      if (is_idmapped_mnt(mnt))
 +              attr_flags |= MOUNT_ATTR_IDMAP;
 +
 +      return attr_flags;
 +}
 +
 +static u64 mnt_to_propagation_flags(struct mount *m)
 +{
 +      u64 propagation = 0;
 +
 +      if (IS_MNT_SHARED(m))
 +              propagation |= MS_SHARED;
 +      if (IS_MNT_SLAVE(m))
 +              propagation |= MS_SLAVE;
 +      if (IS_MNT_UNBINDABLE(m))
 +              propagation |= MS_UNBINDABLE;
 +      if (!propagation)
 +              propagation |= MS_PRIVATE;
 +
 +      return propagation;
 +}
 +
 +static void statmount_sb_basic(struct kstatmount *s)
 +{
 +      struct super_block *sb = s->mnt->mnt_sb;
 +
 +      s->sm.mask |= STATMOUNT_SB_BASIC;
 +      s->sm.sb_dev_major = MAJOR(sb->s_dev);
 +      s->sm.sb_dev_minor = MINOR(sb->s_dev);
 +      s->sm.sb_magic = sb->s_magic;
 +      s->sm.sb_flags = sb->s_flags & (SB_RDONLY|SB_SYNCHRONOUS|SB_DIRSYNC|SB_LAZYTIME);
 +}
 +
 +static void statmount_mnt_basic(struct kstatmount *s)
 +{
 +      struct mount *m = real_mount(s->mnt);
 +
 +      s->sm.mask |= STATMOUNT_MNT_BASIC;
 +      s->sm.mnt_id = m->mnt_id_unique;
 +      s->sm.mnt_parent_id = m->mnt_parent->mnt_id_unique;
 +      s->sm.mnt_id_old = m->mnt_id;
 +      s->sm.mnt_parent_id_old = m->mnt_parent->mnt_id;
 +      s->sm.mnt_attr = mnt_to_attr_flags(&m->mnt);
 +      s->sm.mnt_propagation = mnt_to_propagation_flags(m);
 +      s->sm.mnt_peer_group = IS_MNT_SHARED(m) ? m->mnt_group_id : 0;
 +      s->sm.mnt_master = IS_MNT_SLAVE(m) ? m->mnt_master->mnt_group_id : 0;
 +}
 +
 +static void statmount_propagate_from(struct kstatmount *s)
 +{
 +      struct mount *m = real_mount(s->mnt);
 +
 +      s->sm.mask |= STATMOUNT_PROPAGATE_FROM;
 +      if (IS_MNT_SLAVE(m))
 +              s->sm.propagate_from = get_dominating_id(m, &current->fs->root);
 +}
 +
 +static int statmount_mnt_root(struct kstatmount *s, struct seq_file *seq)
 +{
 +      int ret;
 +      size_t start = seq->count;
 +
 +      ret = show_path(seq, s->mnt->mnt_root);
 +      if (ret)
 +              return ret;
 +
 +      if (unlikely(seq_has_overflowed(seq)))
 +              return -EAGAIN;
 +
 +      /*
 +         * Unescape the result. It would be better if supplied string was not
 +         * escaped in the first place, but that's a pretty invasive change.
 +         */
 +      seq->buf[seq->count] = '\0';
 +      seq->count = start;
 +      seq_commit(seq, string_unescape_inplace(seq->buf + start, UNESCAPE_OCTAL));
 +      return 0;
 +}
 +
 +static int statmount_mnt_point(struct kstatmount *s, struct seq_file *seq)
 +{
 +      struct vfsmount *mnt = s->mnt;
 +      struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
 +      int err;
 +
 +      err = seq_path_root(seq, &mnt_path, &s->root, "");
 +      return err == SEQ_SKIP ? 0 : err;
 +}
 +
 +static int statmount_fs_type(struct kstatmount *s, struct seq_file *seq)
 +{
 +      struct super_block *sb = s->mnt->mnt_sb;
 +
 +      seq_puts(seq, sb->s_type->name);
 +      return 0;
 +}
 +
 +static int statmount_string(struct kstatmount *s, u64 flag)
 +{
 +      int ret;
 +      size_t kbufsize;
 +      struct seq_file *seq = &s->seq;
 +      struct statmount *sm = &s->sm;
 +
 +      switch (flag) {
 +      case STATMOUNT_FS_TYPE:
 +              sm->fs_type = seq->count;
 +              ret = statmount_fs_type(s, seq);
 +              break;
 +      case STATMOUNT_MNT_ROOT:
 +              sm->mnt_root = seq->count;
 +              ret = statmount_mnt_root(s, seq);
 +              break;
 +      case STATMOUNT_MNT_POINT:
 +              sm->mnt_point = seq->count;
 +              ret = statmount_mnt_point(s, seq);
 +              break;
 +      default:
 +              WARN_ON_ONCE(true);
 +              return -EINVAL;
 +      }
 +
 +      if (unlikely(check_add_overflow(sizeof(*sm), seq->count, &kbufsize)))
 +              return -EOVERFLOW;
 +      if (kbufsize >= s->bufsize)
 +              return -EOVERFLOW;
 +
 +      /* signal a retry */
 +      if (unlikely(seq_has_overflowed(seq)))
 +              return -EAGAIN;
 +
 +      if (ret)
 +              return ret;
 +
 +      seq->buf[seq->count++] = '\0';
 +      sm->mask |= flag;
 +      return 0;
 +}
 +
 +static int copy_statmount_to_user(struct kstatmount *s)
 +{
 +      struct statmount *sm = &s->sm;
 +      struct seq_file *seq = &s->seq;
 +      char __user *str = ((char __user *)s->buf) + sizeof(*sm);
 +      size_t copysize = min_t(size_t, s->bufsize, sizeof(*sm));
 +
 +      if (seq->count && copy_to_user(str, seq->buf, seq->count))
 +              return -EFAULT;
 +
 +      /* Return the number of bytes copied to the buffer */
 +      sm->size = copysize + seq->count;
 +      if (copy_to_user(s->buf, sm, copysize))
 +              return -EFAULT;
 +
 +      return 0;
 +}
 +
 +static int do_statmount(struct kstatmount *s)
 +{
 +      struct mount *m = real_mount(s->mnt);
 +      int err;
 +
 +      /*
 +       * Don't trigger audit denials. We just want to determine what
 +       * mounts to show users.
 +       */
 +      if (!is_path_reachable(m, m->mnt.mnt_root, &s->root) &&
 +          !ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN))
 +              return -EPERM;
 +
 +      err = security_sb_statfs(s->mnt->mnt_root);
 +      if (err)
 +              return err;
 +
 +      if (s->mask & STATMOUNT_SB_BASIC)
 +              statmount_sb_basic(s);
 +
 +      if (s->mask & STATMOUNT_MNT_BASIC)
 +              statmount_mnt_basic(s);
 +
 +      if (s->mask & STATMOUNT_PROPAGATE_FROM)
 +              statmount_propagate_from(s);
 +
 +      if (s->mask & STATMOUNT_FS_TYPE)
 +              err = statmount_string(s, STATMOUNT_FS_TYPE);
 +
 +      if (!err && s->mask & STATMOUNT_MNT_ROOT)
 +              err = statmount_string(s, STATMOUNT_MNT_ROOT);
 +
 +      if (!err && s->mask & STATMOUNT_MNT_POINT)
 +              err = statmount_string(s, STATMOUNT_MNT_POINT);
 +
 +      if (err)
 +              return err;
 +
 +      return 0;
 +}
 +
 +static inline bool retry_statmount(const long ret, size_t *seq_size)
 +{
 +      if (likely(ret != -EAGAIN))
 +              return false;
 +      if (unlikely(check_mul_overflow(*seq_size, 2, seq_size)))
 +              return false;
 +      if (unlikely(*seq_size > MAX_RW_COUNT))
 +              return false;
 +      return true;
 +}
 +
 +static int prepare_kstatmount(struct kstatmount *ks, struct mnt_id_req *kreq,
 +                            struct statmount __user *buf, size_t bufsize,
 +                            size_t seq_size)
 +{
 +      if (!access_ok(buf, bufsize))
 +              return -EFAULT;
 +
 +      memset(ks, 0, sizeof(*ks));
 +      ks->mask = kreq->param;
 +      ks->buf = buf;
 +      ks->bufsize = bufsize;
 +      ks->seq.size = seq_size;
 +      ks->seq.buf = kvmalloc(seq_size, GFP_KERNEL_ACCOUNT);
 +      if (!ks->seq.buf)
 +              return -ENOMEM;
 +      return 0;
 +}
 +
 +static int copy_mnt_id_req(const struct mnt_id_req __user *req,
 +                         struct mnt_id_req *kreq)
 +{
 +      int ret;
 +      size_t usize;
 +
 +      BUILD_BUG_ON(sizeof(struct mnt_id_req) != MNT_ID_REQ_SIZE_VER0);
 +
 +      ret = get_user(usize, &req->size);
 +      if (ret)
 +              return -EFAULT;
 +      if (unlikely(usize > PAGE_SIZE))
 +              return -E2BIG;
 +      if (unlikely(usize < MNT_ID_REQ_SIZE_VER0))
 +              return -EINVAL;
 +      memset(kreq, 0, sizeof(*kreq));
 +      ret = copy_struct_from_user(kreq, sizeof(*kreq), req, usize);
 +      if (ret)
 +              return ret;
 +      if (kreq->spare != 0)
 +              return -EINVAL;
 +      return 0;
 +}
 +
 +SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req,
 +              struct statmount __user *, buf, size_t, bufsize,
 +              unsigned int, flags)
 +{
 +      struct vfsmount *mnt;
 +      struct mnt_id_req kreq;
 +      struct kstatmount ks;
 +      /* We currently support retrieval of 3 strings. */
 +      size_t seq_size = 3 * PATH_MAX;
 +      int ret;
 +
 +      if (flags)
 +              return -EINVAL;
 +
 +      ret = copy_mnt_id_req(req, &kreq);
 +      if (ret)
 +              return ret;
 +
 +retry:
 +      ret = prepare_kstatmount(&ks, &kreq, buf, bufsize, seq_size);
 +      if (ret)
 +              return ret;
 +
 +      down_read(&namespace_sem);
 +      mnt = lookup_mnt_in_ns(kreq.mnt_id, current->nsproxy->mnt_ns);
 +      if (!mnt) {
 +              up_read(&namespace_sem);
 +              kvfree(ks.seq.buf);
 +              return -ENOENT;
 +      }
 +
 +      ks.mnt = mnt;
 +      get_fs_root(current->fs, &ks.root);
 +      ret = do_statmount(&ks);
 +      path_put(&ks.root);
 +      up_read(&namespace_sem);
 +
 +      if (!ret)
 +              ret = copy_statmount_to_user(&ks);
 +      kvfree(ks.seq.buf);
 +      if (retry_statmount(ret, &seq_size))
 +              goto retry;
 +      return ret;
 +}
 +
 +static struct mount *listmnt_next(struct mount *curr)
 +{
 +      return node_to_mount(rb_next(&curr->mnt_node));
 +}
 +
 +static ssize_t do_listmount(struct mount *first, struct path *orig, u64 mnt_id,
 +                          u64 __user *buf, size_t bufsize,
 +                          const struct path *root)
 +{
 +      struct mount *r;
 +      ssize_t ctr;
 +      int err;
 +
 +      /*
 +       * Don't trigger audit denials. We just want to determine what
 +       * mounts to show users.
 +       */
 +      if (!is_path_reachable(real_mount(orig->mnt), orig->dentry, root) &&
 +          !ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN))
 +              return -EPERM;
 +
 +      err = security_sb_statfs(orig->dentry);
 +      if (err)
 +              return err;
 +
 +      for (ctr = 0, r = first; r && ctr < bufsize; r = listmnt_next(r)) {
 +              if (r->mnt_id_unique == mnt_id)
 +                      continue;
 +              if (!is_path_reachable(r, r->mnt.mnt_root, orig))
 +                      continue;
 +              ctr = array_index_nospec(ctr, bufsize);
 +              if (put_user(r->mnt_id_unique, buf + ctr))
 +                      return -EFAULT;
 +              if (check_add_overflow(ctr, 1, &ctr))
 +                      return -ERANGE;
 +      }
 +      return ctr;
 +}
 +
 +SYSCALL_DEFINE4(listmount, const struct mnt_id_req __user *, req,
 +              u64 __user *, buf, size_t, bufsize, unsigned int, flags)
 +{
 +      struct mnt_namespace *ns = current->nsproxy->mnt_ns;
 +      struct mnt_id_req kreq;
 +      struct mount *first;
 +      struct path root, orig;
 +      u64 mnt_id, last_mnt_id;
 +      ssize_t ret;
 +
 +      if (flags)
 +              return -EINVAL;
 +
 +      ret = copy_mnt_id_req(req, &kreq);
 +      if (ret)
 +              return ret;
 +      mnt_id = kreq.mnt_id;
 +      last_mnt_id = kreq.param;
 +
 +      down_read(&namespace_sem);
 +      get_fs_root(current->fs, &root);
 +      if (mnt_id == LSMT_ROOT) {
 +              orig = root;
 +      } else {
 +              ret = -ENOENT;
 +              orig.mnt  = lookup_mnt_in_ns(mnt_id, ns);
 +              if (!orig.mnt)
 +                      goto err;
 +              orig.dentry = orig.mnt->mnt_root;
 +      }
 +      if (!last_mnt_id)
 +              first = node_to_mount(rb_first(&ns->mounts));
 +      else
 +              first = mnt_find_id_at(ns, last_mnt_id + 1);
 +
 +      ret = do_listmount(first, &orig, mnt_id, buf, bufsize, &root);
 +err:
 +      path_put(&root);
 +      up_read(&namespace_sem);
 +      return ret;
 +}
 +
 +
  static void __init init_mount_tree(void)
  {
        struct vfsmount *mnt;
        if (IS_ERR(ns))
                panic("Can't allocate initial namespace");
        m = real_mount(mnt);
 -      m->mnt_ns = ns;
        ns->root = m;
 -      ns->mounts = 1;
 -      list_add(&m->mnt_list, &ns->list);
 +      ns->nr_mounts = 1;
 +      mnt_add_to_ns(ns, m);
        init_task.nsproxy->mnt_ns = ns;
        get_mnt_ns(ns);
  
@@@ -5263,14 -4821,18 +5263,14 @@@ static bool mnt_already_visible(struct 
                                int *new_mnt_flags)
  {
        int new_flags = *new_mnt_flags;
 -      struct mount *mnt;
 +      struct mount *mnt, *n;
        bool visible = false;
  
        down_read(&namespace_sem);
 -      lock_ns_list(ns);
 -      list_for_each_entry(mnt, &ns->list, mnt_list) {
 +      rbtree_postorder_for_each_entry_safe(mnt, n, &ns->mounts, mnt_node) {
                struct mount *child;
                int mnt_flags;
  
 -              if (mnt_is_cursor(mnt))
 -                      continue;
 -
                if (mnt->mnt.mnt_sb->s_type != sb->s_type)
                        continue;
  
        next:   ;
        }
  found:
 -      unlock_ns_list(ns);
        up_read(&namespace_sem);
        return visible;
  }
@@@ -5447,7 -5010,6 +5447,6 @@@ static struct ctl_table fs_namespace_sy
                .proc_handler   = proc_dointvec_minmax,
                .extra1         = SYSCTL_ONE,
        },
-       { }
  };
  
  static int __init init_fs_namespace_sysctls(void)
index f83e7cc5ccf23a93406ee22c899922f16db57c5c,f902c0f58537bab056e2dbc4a318bcd14b86052d..fbdc63cc10d9216eaaf747709a616c278892c77c
@@@ -23,7 -23,7 +23,7 @@@
  
  #include <asm/ioctls.h>
  
 -#include "../../mount.h"
 +#include "../fsnotify.h"
  #include "../fdinfo.h"
  #include "fanotify.h"
  
@@@ -86,7 -86,6 +86,6 @@@ static struct ctl_table fanotify_table[
                .proc_handler   = proc_dointvec_minmax,
                .extra1         = SYSCTL_ZERO
        },
-       { }
  };
  
  static void __init fanotify_sysctls_init(void)
@@@ -1192,71 -1191,13 +1191,71 @@@ static bool fanotify_mark_add_to_mask(s
        return recalc;
  }
  
 +struct fan_fsid {
 +      struct super_block *sb;
 +      __kernel_fsid_t id;
 +      bool weak;
 +};
 +
 +static int fanotify_set_mark_fsid(struct fsnotify_group *group,
 +                                struct fsnotify_mark *mark,
 +                                struct fan_fsid *fsid)
 +{
 +      struct fsnotify_mark_connector *conn;
 +      struct fsnotify_mark *old;
 +      struct super_block *old_sb = NULL;
 +
 +      FANOTIFY_MARK(mark)->fsid = fsid->id;
 +      mark->flags |= FSNOTIFY_MARK_FLAG_HAS_FSID;
 +      if (fsid->weak)
 +              mark->flags |= FSNOTIFY_MARK_FLAG_WEAK_FSID;
 +
 +      /* First mark added will determine if group is single or multi fsid */
 +      if (list_empty(&group->marks_list))
 +              return 0;
 +
 +      /* Find sb of an existing mark */
 +      list_for_each_entry(old, &group->marks_list, g_list) {
 +              conn = READ_ONCE(old->connector);
 +              if (!conn)
 +                      continue;
 +              old_sb = fsnotify_connector_sb(conn);
 +              if (old_sb)
 +                      break;
 +      }
 +
 +      /* Only detached marks left? */
 +      if (!old_sb)
 +              return 0;
 +
 +      /* Do not allow mixing of marks with weak and strong fsid */
 +      if ((mark->flags ^ old->flags) & FSNOTIFY_MARK_FLAG_WEAK_FSID)
 +              return -EXDEV;
 +
 +      /* Allow mixing of marks with strong fsid from different fs */
 +      if (!fsid->weak)
 +              return 0;
 +
 +      /* Do not allow mixing marks with weak fsid from different fs */
 +      if (old_sb != fsid->sb)
 +              return -EXDEV;
 +
 +      /* Do not allow mixing marks from different btrfs sub-volumes */
 +      if (!fanotify_fsid_equal(&FANOTIFY_MARK(old)->fsid,
 +                               &FANOTIFY_MARK(mark)->fsid))
 +              return -EXDEV;
 +
 +      return 0;
 +}
 +
  static struct fsnotify_mark *fanotify_add_new_mark(struct fsnotify_group *group,
                                                   fsnotify_connp_t *connp,
                                                   unsigned int obj_type,
                                                   unsigned int fan_flags,
 -                                                 __kernel_fsid_t *fsid)
 +                                                 struct fan_fsid *fsid)
  {
        struct ucounts *ucounts = group->fanotify_data.ucounts;
 +      struct fanotify_mark *fan_mark;
        struct fsnotify_mark *mark;
        int ret;
  
            !inc_ucount(ucounts->ns, ucounts->uid, UCOUNT_FANOTIFY_MARKS))
                return ERR_PTR(-ENOSPC);
  
 -      mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL);
 -      if (!mark) {
 +      fan_mark = kmem_cache_alloc(fanotify_mark_cache, GFP_KERNEL);
 +      if (!fan_mark) {
                ret = -ENOMEM;
                goto out_dec_ucounts;
        }
  
 +      mark = &fan_mark->fsn_mark;
        fsnotify_init_mark(mark, group);
        if (fan_flags & FAN_MARK_EVICTABLE)
                mark->flags |= FSNOTIFY_MARK_FLAG_NO_IREF;
  
 -      ret = fsnotify_add_mark_locked(mark, connp, obj_type, 0, fsid);
 -      if (ret) {
 -              fsnotify_put_mark(mark);
 -              goto out_dec_ucounts;
 +      /* Cache fsid of filesystem containing the marked object */
 +      if (fsid) {
 +              ret = fanotify_set_mark_fsid(group, mark, fsid);
 +              if (ret)
 +                      goto out_put_mark;
 +      } else {
 +              fan_mark->fsid.val[0] = fan_mark->fsid.val[1] = 0;
        }
  
 +      ret = fsnotify_add_mark_locked(mark, connp, obj_type, 0);
 +      if (ret)
 +              goto out_put_mark;
 +
        return mark;
  
 +out_put_mark:
 +      fsnotify_put_mark(mark);
  out_dec_ucounts:
        if (!FAN_GROUP_FLAG(group, FAN_UNLIMITED_MARKS))
                dec_ucount(ucounts, UCOUNT_FANOTIFY_MARKS);
@@@ -1347,7 -1278,7 +1346,7 @@@ static int fanotify_may_update_existing
  static int fanotify_add_mark(struct fsnotify_group *group,
                             fsnotify_connp_t *connp, unsigned int obj_type,
                             __u32 mask, unsigned int fan_flags,
 -                           __kernel_fsid_t *fsid)
 +                           struct fan_fsid *fsid)
  {
        struct fsnotify_mark *fsn_mark;
        bool recalc;
@@@ -1395,7 -1326,7 +1394,7 @@@ out
  
  static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
                                      struct vfsmount *mnt, __u32 mask,
 -                                    unsigned int flags, __kernel_fsid_t *fsid)
 +                                    unsigned int flags, struct fan_fsid *fsid)
  {
        return fanotify_add_mark(group, &real_mount(mnt)->mnt_fsnotify_marks,
                                 FSNOTIFY_OBJ_TYPE_VFSMOUNT, mask, flags, fsid);
  
  static int fanotify_add_sb_mark(struct fsnotify_group *group,
                                struct super_block *sb, __u32 mask,
 -                              unsigned int flags, __kernel_fsid_t *fsid)
 +                              unsigned int flags, struct fan_fsid *fsid)
  {
        return fanotify_add_mark(group, &sb->s_fsnotify_marks,
                                 FSNOTIFY_OBJ_TYPE_SB, mask, flags, fsid);
  
  static int fanotify_add_inode_mark(struct fsnotify_group *group,
                                   struct inode *inode, __u32 mask,
 -                                 unsigned int flags, __kernel_fsid_t *fsid)
 +                                 unsigned int flags, struct fan_fsid *fsid)
  {
        pr_debug("%s: group=%p inode=%p\n", __func__, group, inode);
  
@@@ -1622,25 -1553,20 +1621,25 @@@ out_destroy_group
        return fd;
  }
  
 -static int fanotify_test_fsid(struct dentry *dentry, __kernel_fsid_t *fsid)
 +static int fanotify_test_fsid(struct dentry *dentry, unsigned int flags,
 +                            struct fan_fsid *fsid)
  {
 +      unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS;
        __kernel_fsid_t root_fsid;
        int err;
  
        /*
         * Make sure dentry is not of a filesystem with zero fsid (e.g. fuse).
         */
 -      err = vfs_get_fsid(dentry, fsid);
 +      err = vfs_get_fsid(dentry, &fsid->id);
        if (err)
                return err;
  
 -      if (!fsid->val[0] && !fsid->val[1])
 -              return -ENODEV;
 +      fsid->sb = dentry->d_sb;
 +      if (!fsid->id.val[0] && !fsid->id.val[1]) {
 +              err = -ENODEV;
 +              goto weak;
 +      }
  
        /*
         * Make sure dentry is not of a filesystem subvolume (e.g. btrfs)
        if (err)
                return err;
  
 -      if (root_fsid.val[0] != fsid->val[0] ||
 -          root_fsid.val[1] != fsid->val[1])
 -              return -EXDEV;
 +      if (!fanotify_fsid_equal(&root_fsid, &fsid->id)) {
 +              err = -EXDEV;
 +              goto weak;
 +      }
  
 +      fsid->weak = false;
        return 0;
 +
 +weak:
 +      /* Allow weak fsid when marking inodes */
 +      fsid->weak = true;
 +      return (mark_type == FAN_MARK_INODE) ? 0 : err;
  }
  
  /* Check if filesystem can encode a unique fid */
@@@ -1745,7 -1664,7 +1744,7 @@@ static int do_fanotify_mark(int fanotif
        struct fsnotify_group *group;
        struct fd f;
        struct path path;
 -      __kernel_fsid_t __fsid, *fsid = NULL;
 +      struct fan_fsid __fsid, *fsid = NULL;
        u32 valid_mask = FANOTIFY_EVENTS | FANOTIFY_EVENT_FLAGS;
        unsigned int mark_type = flags & FANOTIFY_MARK_TYPE_BITS;
        unsigned int mark_cmd = flags & FANOTIFY_MARK_CMD_BITS;
        }
  
        if (fid_mode) {
 -              ret = fanotify_test_fsid(path.dentry, &__fsid);
 +              ret = fanotify_test_fsid(path.dentry, flags, &__fsid);
                if (ret)
                        goto path_put_and_out;
  
@@@ -2015,7 -1934,7 +2014,7 @@@ static int __init fanotify_user_setup(v
        BUILD_BUG_ON(HWEIGHT32(FANOTIFY_INIT_FLAGS) != 12);
        BUILD_BUG_ON(HWEIGHT32(FANOTIFY_MARK_FLAGS) != 11);
  
 -      fanotify_mark_cache = KMEM_CACHE(fsnotify_mark,
 +      fanotify_mark_cache = KMEM_CACHE(fanotify_mark,
                                         SLAB_PANIC|SLAB_ACCOUNT);
        fanotify_fid_event_cachep = KMEM_CACHE(fanotify_fid_event,
                                               SLAB_PANIC);
diff --combined fs/pipe.c
index 8d9286a1f2e8506041bd53065495fdf4e19f889b,4ed752910c6c7aa9152dbd1d444967e0438aabe9..f1adbfe743d4a7cce8c6270963f5ba45357964cd
+++ b/fs/pipe.c
@@@ -446,18 -446,6 +446,18 @@@ pipe_write(struct kiocb *iocb, struct i
        bool was_empty = false;
        bool wake_next_writer = false;
  
 +      /*
 +       * Reject writing to watch queue pipes before the point where we lock
 +       * the pipe.
 +       * Otherwise, lockdep would be unhappy if the caller already has another
 +       * pipe locked.
 +       * If we had to support locking a normal pipe and a notification pipe at
 +       * the same time, we could set up lockdep annotations for that, but
 +       * since we don't actually need that, it's simpler to just bail here.
 +       */
 +      if (pipe_has_watch_queue(pipe))
 +              return -EXDEV;
 +
        /* Null write succeeds. */
        if (unlikely(total_len == 0))
                return 0;
                goto out;
        }
  
 -      if (pipe_has_watch_queue(pipe)) {
 -              ret = -EXDEV;
 -              goto out;
 -      }
 -
        /*
         * If it wasn't empty we try to merge new data into
         * the last buffer.
@@@ -1324,11 -1317,6 +1324,11 @@@ int pipe_resize_ring(struct pipe_inode_
        pipe->tail = tail;
        pipe->head = head;
  
 +      if (!pipe_has_watch_queue(pipe)) {
 +              pipe->max_usage = nr_slots;
 +              pipe->nr_accounted = nr_slots;
 +      }
 +
        spin_unlock_irq(&pipe->rd_wait.lock);
  
        /* This might have made more room for writers */
@@@ -1380,6 -1368,8 +1380,6 @@@ static long pipe_set_size(struct pipe_i
        if (ret < 0)
                goto out_revert_acct;
  
 -      pipe->max_usage = nr_slots;
 -      pipe->nr_accounted = nr_slots;
        return pipe->max_usage * PAGE_SIZE;
  
  out_revert_acct:
@@@ -1507,7 -1497,6 +1507,6 @@@ static struct ctl_table fs_pipe_sysctls
                .mode           = 0644,
                .proc_handler   = proc_doulongvec_minmax,
        },
-       { }
  };
  #endif
  
diff --combined fs/quota/dquot.c
index 44ff2813ae512919b8ca2ba6f69360741dc90000,6ad4140bca9ca53d8443cad5d9d4d9181fd76150..1f0c754416b64ca0df5584a0b4bd3ad24b380aa7
@@@ -1787,7 -1787,7 +1787,7 @@@ EXPORT_SYMBOL(dquot_alloc_inode)
  /*
   * Convert in-memory reserved quotas to real consumed quotas
   */
 -int dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
 +void dquot_claim_space_nodirty(struct inode *inode, qsize_t number)
  {
        struct dquot **dquots;
        int cnt, index;
                *inode_reserved_space(inode) -= number;
                __inode_add_bytes(inode, number);
                spin_unlock(&inode->i_lock);
 -              return 0;
 +              return;
        }
  
        dquots = i_dquot(inode);
        spin_unlock(&inode->i_lock);
        mark_all_dquot_dirty(dquots);
        srcu_read_unlock(&dquot_srcu, index);
 -      return 0;
 +      return;
  }
  EXPORT_SYMBOL(dquot_claim_space_nodirty);
  
@@@ -2969,7 -2969,6 +2969,6 @@@ static struct ctl_table fs_dqstats_tabl
                .proc_handler   = proc_dointvec,
        },
  #endif
-       { },
  };
  
  static int __init dquot_init(void)
diff --combined fs/userfaultfd.c
index 6e2a4d6a0d8f192e8c32dd69120823ce90b927fd,1d642d1d28c659abc57ebeae786f0b790a857c69..4fcefe5ef7cb5265cc56088157f8ba1418659be1
@@@ -45,7 -45,6 +45,6 @@@ static struct ctl_table vm_userfaultfd_
                .extra1         = SYSCTL_ZERO,
                .extra2         = SYSCTL_ONE,
        },
-       { }
  };
  #endif
  
@@@ -2005,75 -2004,6 +2004,75 @@@ static inline unsigned int uffd_ctx_fea
        return (unsigned int)user_features | UFFD_FEATURE_INITIALIZED;
  }
  
 +static int userfaultfd_move(struct userfaultfd_ctx *ctx,
 +                          unsigned long arg)
 +{
 +      __s64 ret;
 +      struct uffdio_move uffdio_move;
 +      struct uffdio_move __user *user_uffdio_move;
 +      struct userfaultfd_wake_range range;
 +      struct mm_struct *mm = ctx->mm;
 +
 +      user_uffdio_move = (struct uffdio_move __user *) arg;
 +
 +      if (atomic_read(&ctx->mmap_changing))
 +              return -EAGAIN;
 +
 +      if (copy_from_user(&uffdio_move, user_uffdio_move,
 +                         /* don't copy "move" last field */
 +                         sizeof(uffdio_move)-sizeof(__s64)))
 +              return -EFAULT;
 +
 +      /* Do not allow cross-mm moves. */
 +      if (mm != current->mm)
 +              return -EINVAL;
 +
 +      ret = validate_range(mm, uffdio_move.dst, uffdio_move.len);
 +      if (ret)
 +              return ret;
 +
 +      ret = validate_range(mm, uffdio_move.src, uffdio_move.len);
 +      if (ret)
 +              return ret;
 +
 +      if (uffdio_move.mode & ~(UFFDIO_MOVE_MODE_ALLOW_SRC_HOLES|
 +                                UFFDIO_MOVE_MODE_DONTWAKE))
 +              return -EINVAL;
 +
 +      if (mmget_not_zero(mm)) {
 +              mmap_read_lock(mm);
 +
 +              /* Re-check after taking mmap_lock */
 +              if (likely(!atomic_read(&ctx->mmap_changing)))
 +                      ret = move_pages(ctx, mm, uffdio_move.dst, uffdio_move.src,
 +                                       uffdio_move.len, uffdio_move.mode);
 +              else
 +                      ret = -EINVAL;
 +
 +              mmap_read_unlock(mm);
 +              mmput(mm);
 +      } else {
 +              return -ESRCH;
 +      }
 +
 +      if (unlikely(put_user(ret, &user_uffdio_move->move)))
 +              return -EFAULT;
 +      if (ret < 0)
 +              goto out;
 +
 +      /* len == 0 would wake all */
 +      VM_WARN_ON(!ret);
 +      range.len = ret;
 +      if (!(uffdio_move.mode & UFFDIO_MOVE_MODE_DONTWAKE)) {
 +              range.start = uffdio_move.dst;
 +              wake_userfault(ctx, &range);
 +      }
 +      ret = range.len == uffdio_move.len ? 0 : -EAGAIN;
 +
 +out:
 +      return ret;
 +}
 +
  /*
   * userland asks for a certain API version and we return which bits
   * and ioctl commands are implemented in this kernel for such API
@@@ -2166,9 -2096,6 +2165,9 @@@ static long userfaultfd_ioctl(struct fi
        case UFFDIO_ZEROPAGE:
                ret = userfaultfd_zeropage(ctx, arg);
                break;
 +      case UFFDIO_MOVE:
 +              ret = userfaultfd_move(ctx, arg);
 +              break;
        case UFFDIO_WRITEPROTECT:
                ret = userfaultfd_writeprotect(ctx, arg);
                break;
This page took 0.232227 seconds and 4 git commands to generate.