aboutsummaryrefslogtreecommitdiffstats
path: root/features
diff options
context:
space:
mode:
Diffstat (limited to 'features')
-rw-r--r--features/apparmor/apparmor.cfg1
-rw-r--r--features/apparmor/apparmor.scc1
-rw-r--r--features/apparmor/apparmor_on_boot.cfg2
-rw-r--r--features/aufs/aufs-adjust-for-v6.9.patch48
-rw-r--r--features/aufs/aufs-disable.cfg8
-rw-r--r--features/aufs/aufs-fix-v6.7-kernel-build-compilation.patch144
-rw-r--r--features/aufs/aufs-i_op-Add-handling-for-au_pin_hdir_set_owner-wit.patch39
-rw-r--r--features/aufs/aufs-update-remove_page-to-remove_folio.patch56
-rw-r--r--features/aufs/aufs.scc20
-rw-r--r--features/aufs/aufs5-base.patch343
-rw-r--r--features/aufs/aufs5-standalone.patch334
-rw-r--r--features/aufs/aufs6-adapt-to-v6.6-i_op-ctime-changes.patch146
-rw-r--r--features/aufs/aufs6-adapt-to-v6.6.patch40
-rw-r--r--features/aufs/aufs6-base.patch230
-rw-r--r--features/aufs/aufs6-core.patch (renamed from features/aufs/aufs5-core.patch)5059
-rw-r--r--features/aufs/aufs6-correct-do_splice_from-prototype.patch26
-rw-r--r--features/aufs/aufs6-fix-magic.mk-include-path.patch37
-rw-r--r--features/aufs/aufs6-kbuild.patch (renamed from features/aufs/aufs5-kbuild.patch)22
-rw-r--r--features/aufs/aufs6-mmap.patch (renamed from features/aufs/aufs5-mmap.patch)250
-rw-r--r--features/aufs/aufs6-standalone.patch266
-rw-r--r--features/bluetooth/bluetooth-vhci.cfg (renamed from features/random/random.cfg)2
-rw-r--r--features/bluetooth/bluetooth-vhci.scc7
-rw-r--r--features/bluetooth/bluetooth.cfg2
-rw-r--r--features/bpf/bpf.cfg1
-rw-r--r--features/can/can.cfg2
-rw-r--r--features/can/m_can.cfg5
-rw-r--r--features/can/m_can.scc5
-rw-r--r--features/cgroups/cgroups.cfg6
-rw-r--r--features/clear_warn_once/clear_warn_once-add-a-clear_warn_once-boot-parameter.patch75
-rw-r--r--features/clear_warn_once/clear_warn_once-bind-a-timer-to-written-reset-value.patch104
-rw-r--r--features/clear_warn_once/clear_warn_once-expand-debugfs-to-include-read-suppo.patch77
-rw-r--r--features/clear_warn_once/clear_warn_once.scc4
-rw-r--r--features/clear_warn_once/sched-isolation-really-align-nohz_full-with-rcu_nocb.patch88
-rw-r--r--features/debug/debug-btf.cfg3
-rw-r--r--features/debug/debug-btf.scc6
-rw-r--r--features/debug/debug-kernel.cfg2
-rw-r--r--features/debug/debug-runtime.cfg6
-rw-r--r--features/debug/debug-runtime.scc6
-rw-r--r--features/debug/printk.cfg3
-rw-r--r--features/device-mapper/dm-verity.cfg2
-rw-r--r--features/docker/docker.scc6
-rw-r--r--features/drm-bochs/drm-bochs.cfg4
-rw-r--r--features/drm-emgd/drm-emgd.cfg3
-rw-r--r--features/drm-gma500/drm-gma500.cfg4
-rw-r--r--features/drm-psb/drm-psb.cfg3
-rw-r--r--features/edac/edac.cfg8
-rw-r--r--features/edf/edf.cfg2
-rw-r--r--features/eg20t/eg20t.cfg1
-rw-r--r--features/f2fs/f2fs.cfg8
-rw-r--r--features/f2fs/f2fs.scc2
-rw-r--r--features/firewire/firewire.cfg14
-rw-r--r--features/firmware/firmware.cfg5
-rw-r--r--features/ftrace/ftrace-function-tracer-disable.cfg6
-rw-r--r--features/full_nohz/full_nohz.cfg2
-rw-r--r--features/gpio/mockup.cfg3
-rw-r--r--features/gpio/mockup.scc5
-rw-r--r--features/gpio/sim.cfg4
-rw-r--r--features/gpio/sim.scc6
-rw-r--r--features/gre/gre.cfg2
-rw-r--r--features/grsec/grsec.cfg34
-rw-r--r--features/grsec/pax.cfg6
-rw-r--r--features/hid/hid.cfg4
-rw-r--r--features/hid/hid.scc5
-rw-r--r--features/hostapd/hostapd.scc2
-rw-r--r--features/i3c/i3c.cfg6
-rw-r--r--features/i3c/i3c.scc5
-rw-r--r--features/i915/i915.cfg5
-rw-r--r--features/ice/ice.cfg1
-rw-r--r--features/ice/ice.scc4
-rw-r--r--features/ieee802154/ieee802154-hwsim.cfg8
-rw-r--r--features/ieee802154/ieee802154-hwsim.scc5
-rw-r--r--features/igc/igc.cfg (renamed from features/inline/inline.cfg)2
-rw-r--r--features/igc/igc.scc5
-rw-r--r--features/ima/ima.cfg41
-rw-r--r--features/ima/ima_evm_root_ca.cfg2
-rw-r--r--features/initramfs/initramfs-add-wrapper.patch22
-rw-r--r--features/inline/inline.scc5
-rw-r--r--features/intel-dptf/intel-dptf.cfg2
-rw-r--r--features/intel-dptf/intel-dptf.scc4
-rw-r--r--features/intel-idxd/intel-idxd.cfg2
-rw-r--r--features/intel-idxd/intel-idxd.scc4
-rw-r--r--features/intel-npu/intel-npu.cfg3
-rw-r--r--features/intel-npu/intel-npu.scc4
-rw-r--r--features/intel-persistent-memory/intel-x86-64-dax.cfg1
-rw-r--r--features/intel-persistent-memory/intel-x86-64-pmem.cfg1
-rw-r--r--features/intel-pinctrl/intel-pinctrl.cfg4
-rw-r--r--features/intel-sgx/intel-sgx.cfg2
-rw-r--r--features/intel-sgx/intel-sgx.scc4
-rw-r--r--features/intel-sst/intel-sst.cfg2
-rw-r--r--features/intel-sst/intel-sst.scc4
-rw-r--r--features/intel-tco/intel-tco.cfg2
-rw-r--r--features/intel-th/intel-th.cfg8
-rw-r--r--features/intel-th/intel-th.scc4
-rw-r--r--features/intel-uncore-frequency/intel-uncore-frequency.cfg2
-rw-r--r--features/intel-uncore-frequency/intel-uncore-frequency.scc4
-rw-r--r--features/iommu/iommu.cfg2
-rw-r--r--features/iscsi/iscsi.cfg3
-rw-r--r--features/iscsi/iscsi.scc4
-rw-r--r--features/kfence/kfence.cfg2
-rw-r--r--features/kfence/kfence.scc5
-rw-r--r--features/kmemcheck/kmemcheck.cfg4
-rw-r--r--features/landlock/landlock.cfg3
-rw-r--r--features/landlock/landlock.scc6
-rw-r--r--features/leds/leds.cfg1
-rw-r--r--features/lto/lto-disable.cfg10
-rw-r--r--features/lxc/lxc-enable.scc2
-rw-r--r--features/lxc/lxc.cfg4
-rw-r--r--features/mac80211/mac80211-hwsim.cfg6
-rw-r--r--features/mac80211/mac80211-hwsim.scc5
-rw-r--r--features/mac80211/mac80211.scc2
-rw-r--r--features/media/media-dvb-frontends.cfg5
-rw-r--r--features/media/media-i2c.cfg3
-rw-r--r--features/media/media-pci-capture.cfg15
-rw-r--r--features/media/media-platform.cfg1
-rw-r--r--features/media/media-radio.cfg2
-rw-r--r--features/media/media-usb-tv.cfg5
-rw-r--r--features/media/media-usb-webcams.cfg7
-rw-r--r--features/media/media.cfg11
-rw-r--r--features/mei/amt.cfg1
-rw-r--r--features/minnow-io/minnow-io.cfg1
-rw-r--r--features/misc/bosch-pressure-sensor-i2c.cfg2
-rw-r--r--features/net/net.scc1
-rw-r--r--features/net/netfilter-Fix-remainder-of-pseudo-header-protocol-0.patch92
-rw-r--r--features/net/xdp/xdp.cfg1
-rw-r--r--features/net/xdp/xdp.scc1
-rw-r--r--features/net_sched/net_sched.cfg9
-rw-r--r--features/netfilter/netfilter.cfg10
-rw-r--r--features/nf_tables/nf_tables.cfg26
-rw-r--r--features/nf_tables/nft_test.cfg13
-rw-r--r--features/nf_tables/nft_test.scc5
-rw-r--r--features/nfsd/nfsd.cfg4
-rw-r--r--features/numa/numa.cfg4
-rw-r--r--features/ocicontainer/cgroup.scc4
-rw-r--r--features/ocicontainer/ebtables.cfg2
-rw-r--r--features/ocicontainer/ebtables.scc4
-rw-r--r--features/ocicontainer/ocicontainer.scc7
-rw-r--r--features/ocicontainer/xt-checksum.cfg1
-rw-r--r--features/ocicontainer/xt-checksum.scc4
-rw-r--r--features/optee/optee.cfg3
-rw-r--r--features/optee/optee.scc4
-rw-r--r--features/pci/pci-of-generic.cfg3
-rw-r--r--features/pci/pci-of-generic.scc5
-rw-r--r--features/pci/pci.cfg6
-rw-r--r--features/perf/libbpf-Fix-build-warning-on-ref_ctr_off.patch46
-rw-r--r--features/perf/perf-perf-can-not-parser-the-backtrace-of-app-in-the.patch33
-rw-r--r--features/perf/perf.scc3
-rw-r--r--features/perf/tools-Remove-some-options-from-CLANG_CROSS_FLAGS.patch37
-rw-r--r--features/profiling/profiling.cfg1
-rw-r--r--features/qat/qat.cfg2
-rw-r--r--features/qat/y_or_m_enabled.cfg3
-rw-r--r--features/random/random.scc5
-rw-r--r--features/reproducibility/reproducibility.cfg2
-rw-r--r--features/reproducibility/reproducibility.scc5
-rw-r--r--features/rt/rt.scc2
-rw-r--r--features/scsi/scsi-debug.cfg1
-rw-r--r--features/scsi/scsi-debug.scc1
-rw-r--r--features/security/security-arm64.cfg29
-rw-r--r--features/security/security-x86_64.cfg3
-rw-r--r--features/security/security.cfg29
-rw-r--r--features/security/security.scc8
-rw-r--r--features/soc/baytrail/baytrail.cfg1
-rw-r--r--features/soc/broxton/broxton.cfg3
-rw-r--r--features/soc/skylake/skylake.cfg1
-rw-r--r--features/sound/intel-snd-sof.cfg12
-rw-r--r--features/sound/intel-snd-sof.scc4
-rw-r--r--features/stm/stm.cfg7
-rw-r--r--features/stm/stm.scc4
-rw-r--r--features/telemetry/intel-telemetry.cfg4
-rw-r--r--features/thermal/coretemp-x86_64.cfg4
-rw-r--r--features/thermal/coretemp.cfg4
-rw-r--r--features/thermal/coretemp.scc4
-rw-r--r--features/thunderbolt/thunderbolt.cfg4
-rw-r--r--features/tpm/tpm-1.2.cfg11
-rw-r--r--features/tpm/tpm-1.2.scc7
-rw-r--r--features/tpm/tpm-2.0-crb.cfg3
-rw-r--r--features/tpm/tpm-2.0-crb.scc7
-rw-r--r--features/tpm/tpm-2.0.cfg4
-rw-r--r--features/tpm/tpm-2.0.scc7
-rw-r--r--features/tpm/tpm-common.cfg7
-rw-r--r--features/tpm/tpm-common.scc5
-rw-r--r--features/tpm/tpm.cfg20
-rw-r--r--features/tpm/tpm.scc8
-rw-r--r--features/tpm/vtpm.cfg3
-rw-r--r--features/tpm/vtpm.scc7
-rw-r--r--features/transparent-hugepage/transparent-hugepage.cfg6
-rw-r--r--features/transparent-hugepage/transparent-hugepage.scc4
-rw-r--r--features/tsn/tsn.cfg5
-rw-r--r--features/tsn/tsn.scc3
-rw-r--r--features/tun/tun.cfg5
-rw-r--r--features/tun/tun.scc5
-rw-r--r--features/uptime/uptime-allow-the-optional-limiting-of-kernel-runtime.patch251
-rw-r--r--features/uptime/uptime.scc2
-rw-r--r--features/usb/usb-dummy-hcd.cfg2
-rw-r--r--features/usb/usb-dummy-hcd.scc7
-rw-r--r--features/usb/usb-raw-gadget.cfg5
-rw-r--r--features/usb/usb-raw-gadget.scc7
-rw-r--r--features/usb/usb-typec.cfg4
-rw-r--r--features/vdso/vdso.cfg2
-rw-r--r--features/vfat/fat-Replace-prandom_u32-with-get_random_u32.patch40
-rw-r--r--features/vfat/vfat.scc1
-rw-r--r--features/vfio/vfio.cfg1
-rw-r--r--features/vswitch/vswitch.cfg5
-rw-r--r--features/vswitch/vswitch.scc5
-rw-r--r--features/wifi/ralink-pci.cfg6
-rw-r--r--features/x2apic/x2apic.cfg2
-rw-r--r--features/xen/xen-x86.cfg11
-rw-r--r--features/xen/xen.cfg38
-rw-r--r--features/xen/xen.scc8
-rw-r--r--features/xilinx/hdmi-module/hdmi-module.cfg224
-rw-r--r--features/xilinx/hdmi-module/hdmi-module.scc6
-rw-r--r--features/xilinx/overlay_of/overlay_of.cfg4
-rw-r--r--features/xilinx/overlay_of/overlay_of.scc5
-rw-r--r--features/xilinx/v4l2/v4l2.cfg23
-rw-r--r--features/xilinx/v4l2/v4l2.scc5
-rw-r--r--features/yaffs2/0001-yaffs2-convert-read_page-readfolio.patch76
-rw-r--r--features/yaffs2/0001-yaffs2-replace-bdevname-call-with-sprintf.patch34
-rw-r--r--features/yaffs2/0001-yaffs2-update-VFS-ctime-operations-to-6.6.patch64
-rw-r--r--features/yaffs2/0001-yaffs2-v5.12-build-fixups-not-runtime-tested.patch105
-rw-r--r--features/yaffs2/yaffs-fix-Wstringop-overread-compile-warning-in-yaff.patch44
-rw-r--r--features/yaffs2/yaffs-fix-misplaced-variable-declaration.patch40
-rw-r--r--features/yaffs2/yaffs-fix-mtime-itime-field-access.patch65
-rw-r--r--features/yaffs2/yaffs-include-blkdev.h.patch28
-rw-r--r--features/yaffs2/yaffs-replace-IS_ERR-with-IS_ERR_OR_NULL-to-check-bo.patch49
-rw-r--r--features/yaffs2/yaffs2-Fix-miscalculation-of-devname-buffer-length.patch65
-rw-r--r--features/yaffs2/yaffs2-convert-user_namespace-to-mnt_idmap.patch96
-rw-r--r--features/yaffs2/yaffs2-fix-memory-leak-when-proc-yaffs-is-read.patch38
-rw-r--r--features/yaffs2/yaffs2-import-git-revision-b4ce1bb-jan-2020.patch491
-rw-r--r--features/yaffs2/yaffs2-v5.6-build-fixups.patch50
-rw-r--r--features/yaffs2/yaffs2-v6.5-fixups.patch26
-rw-r--r--features/yaffs2/yaffs2.scc14
-rw-r--r--features/zram/zram.cfg23
-rw-r--r--features/zram/zram.scc5
232 files changed, 6229 insertions, 4233 deletions
diff --git a/features/apparmor/apparmor.cfg b/features/apparmor/apparmor.cfg
index 1a656fb0..0fe87377 100644
--- a/features/apparmor/apparmor.cfg
+++ b/features/apparmor/apparmor.cfg
@@ -5,4 +5,3 @@ CONFIG_SECURITY_PATH=y
CONFIG_SECURITY_APPARMOR=y
CONFIG_SECURITY_APPARMOR_HASH=y
CONFIG_SECURITY_APPARMOR_HASH_DEFAULT=y
-CONFIG_DEFAULT_SECURITY_APPARMOR=y
diff --git a/features/apparmor/apparmor.scc b/features/apparmor/apparmor.scc
index 235551ce..39548733 100644
--- a/features/apparmor/apparmor.scc
+++ b/features/apparmor/apparmor.scc
@@ -3,4 +3,3 @@ define KFEATURE_DESCRIPTION "Enable/disable configurations for apparmor security
define KFEATURE_COMPATIBILITY all
kconf non-hardware apparmor.cfg
-kconf non-hardware apparmor_on_boot.cfg
diff --git a/features/apparmor/apparmor_on_boot.cfg b/features/apparmor/apparmor_on_boot.cfg
deleted file mode 100644
index 1b496516..00000000
--- a/features/apparmor/apparmor_on_boot.cfg
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: MIT
-CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1
diff --git a/features/aufs/aufs-adjust-for-v6.9.patch b/features/aufs/aufs-adjust-for-v6.9.patch
new file mode 100644
index 00000000..82e5bfd0
--- /dev/null
+++ b/features/aufs/aufs-adjust-for-v6.9.patch
@@ -0,0 +1,48 @@
+From 252dbed4c82524c20b3564f560422633aa6cb369 Mon Sep 17 00:00:00 2001
+From: Bruce Ashfield <bruce.ashfield@gmail.com>
+Date: Wed, 3 Apr 2024 10:15:47 -0400
+Subject: [PATCH] aufs: adjust for v6.9+
+
+The following commit drops SLAB_MEM_SPREAD, so we remove it
+from aufs.
+
+commit cdeeaaba174886aa6c1ff4c0c5449c5066dbe82f
+Author: Vlastimil Babka <vbabka@suse.cz>
+Date: Fri Feb 23 19:27:17 2024 +0100
+
+ mm, slab: deprecate SLAB_MEM_SPREAD flag
+
+ The SLAB_MEM_SPREAD flag used to be implemented in SLAB, which was
+ removed. SLUB instead relies on the page allocator's NUMA policies.
+ Change the flag's value to 0 to free up the value it had, and mark it
+ for full removal once all users are gone.
+
+ Reported-by: Steven Rostedt <rostedt@goodmis.org>
+ Closes: https://lore.kernel.org/all/20240131172027.10f64405@gandalf.local.home/
+ Reviewed-and-tested-by: Xiongwei Song <xiongwei.song@windriver.com>
+ Reviewed-by: Chengming Zhou <chengming.zhou@linux.dev>
+ Reviewed-by: Roman Gushchin <roman.gushchin@linux.dev>
+ Acked-by: David Rientjes <rientjes@google.com>
+ Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
+
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/aufs/module.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/aufs/module.h b/fs/aufs/module.h
+index a9d21d3e5414..784c830d084d 100644
+--- a/fs/aufs/module.h
++++ b/fs/aufs/module.h
+@@ -129,7 +129,7 @@ enum {
+
+ extern struct kmem_cache *au_cache[AuCache_Last];
+
+-#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
++#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT)
+ #define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
+ #define AuCacheCtor(type, ctor) \
+ kmem_cache_create(#type, sizeof(struct type), \
+--
+2.39.2
+
diff --git a/features/aufs/aufs-disable.cfg b/features/aufs/aufs-disable.cfg
index e276863f..b58d21a8 100644
--- a/features/aufs/aufs-disable.cfg
+++ b/features/aufs/aufs-disable.cfg
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: MIT
-# CONFIG_AUFS_FS is not set
-# CONFIG_AUFS_BRANCH_MAX_127 is not set
-# CONFIG_AUFS_SBILIST is not set
-# CONFIG_AUFS_BDEV_LOOP is not set
+CONFIG_AUFS_FS=n
+CONFIG_AUFS_BRANCH_MAX_127=n
+CONFIG_AUFS_SBILIST=n
+CONFIG_AUFS_BDEV_LOOP=n
diff --git a/features/aufs/aufs-fix-v6.7-kernel-build-compilation.patch b/features/aufs/aufs-fix-v6.7-kernel-build-compilation.patch
new file mode 100644
index 00000000..0ab046db
--- /dev/null
+++ b/features/aufs/aufs-fix-v6.7-kernel-build-compilation.patch
@@ -0,0 +1,144 @@
+From 35340163fed594434a42002cc041bd29941fb985 Mon Sep 17 00:00:00 2001
+From: Bruce Ashfield <bruce.ashfield@gmail.com>
+Date: Wed, 22 Nov 2023 12:06:29 -0500
+Subject: [PATCH] aufs: fix v6.7 kernel build compilation
+
+Adapting aufs to the following upstream commits:
+
+ commit 12cd44023651666bd44baa36a5c999698890debb
+ Author: Jeff Layton <jlayton@kernel.org>
+ Date: Fri Sep 29 09:05:52 2023 -0400
+
+ fs: rename inode i_atime and i_mtime fields
+
+ Rename these two fields to discourage direct access (and to help ensure
+ that we mop up any leftover direct accesses).
+
+ Signed-off-by: Jeff Layton <jlayton@kernel.org>
+ Signed-off-by: Christian Brauner <brauner@kernel.org>
+
+ commit 3e15dcf77b23b8e9b9b7f3c0d4def8fe9c12c534
+ Author: Amir Goldstein <amir73il@gmail.com>
+ Date: Fri Sep 8 16:28:59 2023 +0300
+
+ fs: rename __mnt_{want,drop}_write*() helpers
+
+ Before exporting these helpers to modules, make their names more
+ meaningful.
+
+ The names mnt_{get,put)_write_access*() were chosen, because they rhyme
+ with the inode {get,put)_write_access() helpers, which have a very close
+ meaning for the inode object.
+
+ Suggested-by: Christian Brauner <brauner@kernel.org>
+ Link: https://lore.kernel.org/r/20230817-anfechtbar-ruhelosigkeit-8c6cca8443fc@brauner/
+ Signed-off-by: Amir Goldstein <amir73il@gmail.com>
+ Message-Id: <20230908132900.2983519-2-amir73il@gmail.com>
+ Signed-off-by: Christian Brauner <brauner@kernel.org>
+
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/aufs/branch.c | 2 +-
+ fs/aufs/cpup.c | 8 ++++----
+ fs/aufs/dir.c | 2 +-
+ fs/aufs/i_op.c | 4 ++--
+ fs/aufs/vfsub.h | 2 +-
+ fs/namespace.c | 2 +-
+ 6 files changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/fs/aufs/branch.c b/fs/aufs/branch.c
+index 2a85d744d2b5..3ecc05573cc0 100644
+--- a/fs/aufs/branch.c
++++ b/fs/aufs/branch.c
+@@ -1293,7 +1293,7 @@ static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
+ if (hf->f_mode & FMODE_READ)
+ i_readcount_inc(h_inode);
+ put_write_access(h_inode);
+- __mnt_drop_write(hf->f_path.mnt);
++ mnt_put_write_access(hf->f_path.mnt);
+ }
+ }
+
+diff --git a/fs/aufs/cpup.c b/fs/aufs/cpup.c
+index 8c8bd5f7b28d..3f09876a3bd5 100644
+--- a/fs/aufs/cpup.c
++++ b/fs/aufs/cpup.c
+@@ -133,8 +133,8 @@ void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
+ dt->dt_dentry = dentry;
+ dt->dt_h_path = *h_path;
+ h_inode = d_inode(h_path->dentry);
+- dt->dt_atime = h_inode->i_atime;
+- dt->dt_mtime = h_inode->i_mtime;
++ dt->dt_atime = h_inode->__i_atime;
++ dt->dt_mtime = h_inode->__i_mtime;
+ /* smp_mb(); */
+ }
+
+@@ -200,8 +200,8 @@ int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct path *h_src,
+ } else {
+ ia.ia_uid = h_isrc->i_uid;
+ ia.ia_gid = h_isrc->i_gid;
+- ia.ia_atime = h_isrc->i_atime;
+- ia.ia_mtime = h_isrc->i_mtime;
++ ia.ia_atime = h_isrc->__i_atime;
++ ia.ia_mtime = h_isrc->__i_mtime;
+ if (h_idst->i_mode != h_isrc->i_mode
+ && !S_ISLNK(h_idst->i_mode)) {
+ ia.ia_valid |= ATTR_MODE;
+diff --git a/fs/aufs/dir.c b/fs/aufs/dir.c
+index ee900ea3264b..e986deffef5e 100644
+--- a/fs/aufs/dir.c
++++ b/fs/aufs/dir.c
+@@ -145,7 +145,7 @@ static void au_do_dir_ts(void *arg)
+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
+ h_dir = au_h_iptr(dir, btop);
+ if (h_dir->i_nlink
+- && timespec64_compare(&h_dir->i_mtime, &dt.dt_mtime) < 0) {
++ && timespec64_compare(&h_dir->__i_mtime, &dt.dt_mtime) < 0) {
+ dt.dt_h_path = h_path;
+ au_dtime_revert(&dt);
+ }
+diff --git a/fs/aufs/i_op.c b/fs/aufs/i_op.c
+index 993d57633393..8700b9e46b44 100644
+--- a/fs/aufs/i_op.c
++++ b/fs/aufs/i_op.c
+@@ -1167,8 +1167,8 @@ static void au_refresh_iattr(struct inode *inode, struct kstat *st,
+ /* don't i_[ug]id_write() here */
+ inode->i_uid = st->uid;
+ inode->i_gid = st->gid;
+- inode->i_atime = st->atime;
+- inode->i_mtime = st->mtime;
++ inode->__i_atime = st->atime;
++ inode->__i_mtime = st->mtime;
+ inode_set_ctime_to_ts( inode, st->ctime );
+
+ au_cpup_attr_nlink(inode, /*force*/0);
+diff --git a/fs/aufs/vfsub.h b/fs/aufs/vfsub.h
+index ed218d95770d..b45603c2d651 100644
+--- a/fs/aufs/vfsub.h
++++ b/fs/aufs/vfsub.h
+@@ -33,7 +33,7 @@
+
+ /* copied from linux/fs/internal.h */
+ /* todo: BAD approach!! */
+-extern void __mnt_drop_write(struct vfsmount *);
++extern void mnt_put_write_access(struct vfsmount *);
+ extern struct file *alloc_empty_file(int, const struct cred *);
+
+ /* ---------------------------------------------------------------------- */
+diff --git a/fs/namespace.c b/fs/namespace.c
+index 1b942a6b72fa..e5d02ed749c4 100644
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -489,7 +489,7 @@ void mnt_put_write_access_file(struct file *file)
+ if (!(file->f_mode & FMODE_WRITER))
+ mnt_put_write_access(file->f_path.mnt);
+ }
+-EXPORT_SYMBOL_GPL(__mnt_drop_write);
++EXPORT_SYMBOL_GPL(mnt_put_write_access_file);
+
+ void mnt_drop_write_file(struct file *file)
+ {
+--
+2.34.1
+
diff --git a/features/aufs/aufs-i_op-Add-handling-for-au_pin_hdir_set_owner-wit.patch b/features/aufs/aufs-i_op-Add-handling-for-au_pin_hdir_set_owner-wit.patch
new file mode 100644
index 00000000..3cd55ace
--- /dev/null
+++ b/features/aufs/aufs-i_op-Add-handling-for-au_pin_hdir_set_owner-wit.patch
@@ -0,0 +1,39 @@
+From 10db7ee919edbf7b6f65124e475d89864de7bb1b Mon Sep 17 00:00:00 2001
+From: He Zhe <zhe.he@windriver.com>
+Date: Fri, 5 Jan 2024 18:57:18 +0800
+Subject: [PATCH] aufs: i_op: Add handling for au_pin_hdir_set_owner with RT
+ kernel
+
+In RT kernel rw_semaphore uses rt_mutex whose owner should be set to the
+task. Add a condition to handle both cases to avoid the following build error
+for PREEMPT_RT kernel.
+
+fs/aufs/i_op.c: In function 'au_pin_hdir_set_owner':
+fs/aufs/i_op.c:639:52: error: 'struct rw_semaphore' has no member named 'owner'
+639 | atomic_long_set(&p->hdir->hi_inode->i_rwsem.owner, (long)task);
+
+Signed-off-by: He Zhe <zhe.he@windriver.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/aufs/i_op.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/fs/aufs/i_op.c b/fs/aufs/i_op.c
+index 993d57633393..a1e0d0c54d23 100644
+--- a/fs/aufs/i_op.c
++++ b/fs/aufs/i_op.c
+@@ -638,7 +638,11 @@ int au_pin_hdir_relock(struct au_pin *p)
+
+ static void au_pin_hdir_set_owner(struct au_pin *p, struct task_struct *task)
+ {
++#if IS_ENABLED(CONFIG_PREEMPT_RT)
++ p->hdir->hi_inode->i_rwsem.rwbase.rtmutex.owner = task;
++#else
+ atomic_long_set(&p->hdir->hi_inode->i_rwsem.owner, (long)task);
++#endif
+ }
+
+ void au_pin_hdir_acquire_nest(struct au_pin *p)
+--
+2.39.2
+
diff --git a/features/aufs/aufs-update-remove_page-to-remove_folio.patch b/features/aufs/aufs-update-remove_page-to-remove_folio.patch
new file mode 100644
index 00000000..d874e550
--- /dev/null
+++ b/features/aufs/aufs-update-remove_page-to-remove_folio.patch
@@ -0,0 +1,56 @@
+From e9e335352a0815018d7db98c165d3669c3d8804f Mon Sep 17 00:00:00 2001
+From: Bruce Ashfield <bruce.ashfield@gmail.com>
+Date: Tue, 23 Jan 2024 09:56:24 -0500
+Subject: [PATCH] aufs: update remove_page to remove_folio
+
+Commit af7628d6ec19 [fs: convert error_remove_page to
+error_remove_folio]
+switches remove_page to the folio equivalent. We switch
+the aufs definitions to match.
+
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/aufs/dynop.c | 2 +-
+ fs/aufs/file.c | 6 +++---
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/fs/aufs/dynop.c b/fs/aufs/dynop.c
+index 54fd16ecb6d3..f62b3b56291d 100644
+--- a/fs/aufs/dynop.c
++++ b/fs/aufs/dynop.c
+@@ -192,7 +192,7 @@ static void dy_aop(struct au_dykey *key, const void *h_op,
+ DySetAop(launder_folio);
+ DySetAop(is_partially_uptodate);
+ DySetAop(is_dirty_writeback);
+- DySetAop(error_remove_page);
++ DySetAop(error_remove_folio);
+ DySetAop(swap_activate);
+ DySetAop(swap_deactivate);
+ DySetAop(swap_rw);
+diff --git a/fs/aufs/file.c b/fs/aufs/file.c
+index 76ad444328db..2e3bdac4699a 100644
+--- a/fs/aufs/file.c
++++ b/fs/aufs/file.c
+@@ -827,8 +827,8 @@ static bool aufs_is_partially_uptodate(struct folio *folio, size_t from,
+ static void aufs_is_dirty_writeback(struct folio *folio, bool *dirty,
+ bool *writeback)
+ { AuUnsupport(); }
+-static int aufs_error_remove_page(struct address_space *mapping,
+- struct page *page)
++static int aufs_error_remove_folio(struct address_space *mapping,
++ struct folio *folio)
+ { AuUnsupport(); return 0; }
+ static int aufs_swap_activate(struct swap_info_struct *sis, struct file *file,
+ sector_t *span)
+@@ -857,7 +857,7 @@ const struct address_space_operations aufs_aop = {
+ .launder_folio = aufs_launder_folio,
+ .is_partially_uptodate = aufs_is_partially_uptodate,
+ .is_dirty_writeback = aufs_is_dirty_writeback,
+- .error_remove_page = aufs_error_remove_page,
++ .error_remove_folio = aufs_error_remove_folio,
+ .swap_activate = aufs_swap_activate,
+ .swap_deactivate = aufs_swap_deactivate,
+ .swap_rw = aufs_swap_rw
+--
+2.39.2
+
diff --git a/features/aufs/aufs.scc b/features/aufs/aufs.scc
index d474ff6f..ac6fe686 100644
--- a/features/aufs/aufs.scc
+++ b/features/aufs/aufs.scc
@@ -1,7 +1,17 @@
# SPDX-License-Identifier: MIT
#
-patch aufs5-kbuild.patch
-patch aufs5-base.patch
-patch aufs5-mmap.patch
-patch aufs5-standalone.patch
-patch aufs5-core.patch
+
+patch aufs6-kbuild.patch
+patch aufs6-base.patch
+patch aufs6-mmap.patch
+patch aufs6-standalone.patch
+patch aufs6-core.patch
+patch aufs6-adapt-to-v6.6.patch
+# the below isn't needed in 6.10+
+# patch aufs6-fix-magic.mk-include-path.patch
+patch aufs6-adapt-to-v6.6-i_op-ctime-changes.patch
+patch aufs-fix-v6.7-kernel-build-compilation.patch
+patch aufs-i_op-Add-handling-for-au_pin_hdir_set_owner-wit.patch
+patch aufs-update-remove_page-to-remove_folio.patch
+patch aufs6-correct-do_splice_from-prototype.patch
+patch aufs-adjust-for-v6.9.patch
diff --git a/features/aufs/aufs5-base.patch b/features/aufs/aufs5-base.patch
deleted file mode 100644
index f90ef0bf..00000000
--- a/features/aufs/aufs5-base.patch
+++ /dev/null
@@ -1,343 +0,0 @@
-From 7e05613a5d85ca6aeffbff55d85ecb41082e471f Mon Sep 17 00:00:00 2001
-From: Bruce Ashfield <bruce.ashfield@gmail.com>
-Date: Mon, 13 Jan 2020 12:30:59 -0500
-Subject: [PATCH 2/5] aufs5: base
-
-Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
----
- MAINTAINERS | 13 +++++++++++++
- drivers/block/loop.c | 18 ++++++++++++++++++
- fs/dcache.c | 2 +-
- fs/fcntl.c | 4 +++-
- fs/inode.c | 2 +-
- fs/namespace.c | 6 ++++++
- fs/read_write.c | 22 ++++++++++++++++++++++
- fs/splice.c | 10 +++++-----
- fs/sync.c | 2 +-
- include/linux/fs.h | 10 ++++++++++
- include/linux/lockdep.h | 3 +++
- include/linux/mnt_namespace.h | 3 +++
- include/linux/splice.h | 6 ++++++
- kernel/locking/lockdep.c | 3 ++-
- 14 files changed, 94 insertions(+), 10 deletions(-)
-
-diff --git a/MAINTAINERS b/MAINTAINERS
-index 9d3a5c54a41d..f33398b47c42 100644
---- a/MAINTAINERS
-+++ b/MAINTAINERS
-@@ -2832,6 +2832,19 @@ F: include/linux/audit.h
- F: include/uapi/linux/audit.h
- F: kernel/audit*
-
-+AUFS (advanced multi layered unification filesystem) FILESYSTEM
-+M: "J. R. Okajima" <hooanon05g@gmail.com>
-+L: aufs-users@lists.sourceforge.net (members only)
-+L: linux-unionfs@vger.kernel.org
-+W: http://aufs.sourceforge.net
-+T: git://github.com/sfjro/aufs4-linux.git
-+S: Supported
-+F: Documentation/filesystems/aufs/
-+F: Documentation/ABI/testing/debugfs-aufs
-+F: Documentation/ABI/testing/sysfs-aufs
-+F: fs/aufs/
-+F: include/uapi/linux/aufs_type.h
-+
- AUXILIARY DISPLAY DRIVERS
- M: Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com>
- S: Maintained
-diff --git a/drivers/block/loop.c b/drivers/block/loop.c
-index ef6e251857c8..a5c78e0aebe7 100644
---- a/drivers/block/loop.c
-+++ b/drivers/block/loop.c
-@@ -748,6 +748,24 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
- return error;
- }
-
-+/*
-+ * for AUFS
-+ * no get/put for file.
-+ */
-+struct file *loop_backing_file(struct super_block *sb)
-+{
-+ struct file *ret;
-+ struct loop_device *l;
-+
-+ ret = NULL;
-+ if (MAJOR(sb->s_dev) == LOOP_MAJOR) {
-+ l = sb->s_bdev->bd_disk->private_data;
-+ ret = l->lo_backing_file;
-+ }
-+ return ret;
-+}
-+EXPORT_SYMBOL_GPL(loop_backing_file);
-+
- /* loop sysfs attributes */
-
- static ssize_t loop_attr_show(struct device *dev, char *page,
-diff --git a/fs/dcache.c b/fs/dcache.c
-index e88cf0554e65..7ce4ccf5a51c 100644
---- a/fs/dcache.c
-+++ b/fs/dcache.c
-@@ -1264,7 +1264,7 @@ enum d_walk_ret {
- *
- * The @enter() callbacks are called with d_lock held.
- */
--static void d_walk(struct dentry *parent, void *data,
-+void d_walk(struct dentry *parent, void *data,
- enum d_walk_ret (*enter)(void *, struct dentry *))
- {
- struct dentry *this_parent;
-diff --git a/fs/fcntl.c b/fs/fcntl.c
-index 3d40771e8e7c..d62303c5472a 100644
---- a/fs/fcntl.c
-+++ b/fs/fcntl.c
-@@ -32,7 +32,7 @@
-
- #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
-
--static int setfl(int fd, struct file * filp, unsigned long arg)
-+int setfl(int fd, struct file * filp, unsigned long arg)
- {
- struct inode * inode = file_inode(filp);
- int error = 0;
-@@ -63,6 +63,8 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
-
- if (filp->f_op->check_flags)
- error = filp->f_op->check_flags(arg);
-+ if (!error && filp->f_op->setfl)
-+ error = filp->f_op->setfl(filp, arg);
- if (error)
- return error;
-
-diff --git a/fs/inode.c b/fs/inode.c
-index 96d62d97694e..31796c1040d6 100644
---- a/fs/inode.c
-+++ b/fs/inode.c
-@@ -1680,7 +1680,7 @@ EXPORT_SYMBOL(generic_update_time);
- * This does the actual work of updating an inodes time or version. Must have
- * had called mnt_want_write() before calling this.
- */
--static int update_time(struct inode *inode, struct timespec64 *time, int flags)
-+int update_time(struct inode *inode, struct timespec64 *time, int flags)
- {
- int (*update_time)(struct inode *, struct timespec64 *, int);
-
-diff --git a/fs/namespace.c b/fs/namespace.c
-index 2adfe7b166a3..0f7e57e5f4b7 100644
---- a/fs/namespace.c
-+++ b/fs/namespace.c
-@@ -776,6 +776,12 @@ static inline int check_mnt(struct mount *mnt)
- return mnt->mnt_ns == current->nsproxy->mnt_ns;
- }
-
-+/* for aufs, CONFIG_AUFS_BR_FUSE */
-+int is_current_mnt_ns(struct vfsmount *mnt)
-+{
-+ return check_mnt(real_mount(mnt));
-+}
-+
- /*
- * vfsmount lock must be held for write
- */
-diff --git a/fs/read_write.c b/fs/read_write.c
-index 5bbf587f5bc1..3265bb84f152 100644
---- a/fs/read_write.c
-+++ b/fs/read_write.c
-@@ -498,6 +498,28 @@ static ssize_t __vfs_write(struct file *file, const char __user *p,
- return -EINVAL;
- }
-
-+vfs_readf_t vfs_readf(struct file *file)
-+{
-+ const struct file_operations *fop = file->f_op;
-+
-+ if (fop->read)
-+ return fop->read;
-+ if (fop->read_iter)
-+ return new_sync_read;
-+ return ERR_PTR(-ENOSYS);
-+}
-+
-+vfs_writef_t vfs_writef(struct file *file)
-+{
-+ const struct file_operations *fop = file->f_op;
-+
-+ if (fop->write)
-+ return fop->write;
-+ if (fop->write_iter)
-+ return new_sync_write;
-+ return ERR_PTR(-ENOSYS);
-+}
-+
- ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
- {
- mm_segment_t old_fs;
-diff --git a/fs/splice.c b/fs/splice.c
-index e509239d7e06..8e38ef82a2ce 100644
---- a/fs/splice.c
-+++ b/fs/splice.c
-@@ -834,8 +834,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
- /*
- * Attempt to initiate a splice from pipe to file.
- */
--static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
-- loff_t *ppos, size_t len, unsigned int flags)
-+long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
-+ loff_t *ppos, size_t len, unsigned int flags)
- {
- ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
- loff_t *, size_t, unsigned int);
-@@ -851,9 +851,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
- /*
- * Attempt to initiate a splice from a file to a pipe.
- */
--static long do_splice_to(struct file *in, loff_t *ppos,
-- struct pipe_inode_info *pipe, size_t len,
-- unsigned int flags)
-+long do_splice_to(struct file *in, loff_t *ppos,
-+ struct pipe_inode_info *pipe, size_t len,
-+ unsigned int flags)
- {
- ssize_t (*splice_read)(struct file *, loff_t *,
- struct pipe_inode_info *, size_t, unsigned int);
-diff --git a/fs/sync.c b/fs/sync.c
-index 4d1ff010bc5a..457f4e4a5cc1 100644
---- a/fs/sync.c
-+++ b/fs/sync.c
-@@ -28,7 +28,7 @@
- * wait == 1 case since in that case write_inode() functions do
- * sync_dirty_buffer() and thus effectively write one block at a time.
- */
--static int __sync_filesystem(struct super_block *sb, int wait)
-+int __sync_filesystem(struct super_block *sb, int wait)
- {
- if (wait)
- sync_inodes_sb(sb);
-diff --git a/include/linux/fs.h b/include/linux/fs.h
-index 0b4d8fc79e0f..9b98b5261ed7 100644
---- a/include/linux/fs.h
-+++ b/include/linux/fs.h
-@@ -1349,6 +1349,7 @@ extern void fasync_free(struct fasync_struct *);
- /* can be called from interrupts */
- extern void kill_fasync(struct fasync_struct **, int, int);
-
-+extern int setfl(int fd, struct file * filp, unsigned long arg);
- extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int force);
- extern int f_setown(struct file *filp, unsigned long arg, int force);
- extern void f_delown(struct file *filp);
-@@ -1842,6 +1843,7 @@ struct file_operations {
- ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
- unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
- int (*check_flags)(int);
-+ int (*setfl)(struct file *, unsigned long);
- int (*flock) (struct file *, int, struct file_lock *);
- ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
- ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
-@@ -1912,6 +1914,12 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
- struct iovec *fast_pointer,
- struct iovec **ret_pointer);
-
-+typedef ssize_t (*vfs_readf_t)(struct file *, char __user *, size_t, loff_t *);
-+typedef ssize_t (*vfs_writef_t)(struct file *, const char __user *, size_t,
-+ loff_t *);
-+vfs_readf_t vfs_readf(struct file *file);
-+vfs_writef_t vfs_writef(struct file *file);
-+
- extern ssize_t __vfs_read(struct file *, char __user *, size_t, loff_t *);
- extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *);
- extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *);
-@@ -2332,6 +2340,7 @@ extern int current_umask(void);
- extern void ihold(struct inode * inode);
- extern void iput(struct inode *);
- extern int generic_update_time(struct inode *, struct timespec64 *, int);
-+extern int update_time(struct inode *, struct timespec64 *, int);
-
- /* /sys/fs */
- extern struct kobject *fs_kobj;
-@@ -2620,6 +2629,7 @@ static inline bool sb_is_blkdev_sb(struct super_block *sb)
- return false;
- }
- #endif
-+extern int __sync_filesystem(struct super_block *, int);
- extern int sync_filesystem(struct super_block *);
- extern const struct file_operations def_blk_fops;
- extern const struct file_operations def_chr_fops;
-diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
-index b8a835fd611b..f452521f2e05 100644
---- a/include/linux/lockdep.h
-+++ b/include/linux/lockdep.h
-@@ -331,6 +331,8 @@ static inline int lockdep_match_key(struct lockdep_map *lock,
- return lock->key == key;
- }
-
-+struct lock_class *lockdep_hlock_class(struct held_lock *hlock);
-+
- /*
- * Acquire a lock.
- *
-@@ -473,6 +475,7 @@ struct lockdep_map { };
-
- #define lockdep_depth(tsk) (0)
-
-+#define lockdep_is_held(lock) (1)
- #define lockdep_is_held_type(l, r) (1)
-
- #define lockdep_assert_held(l) do { (void)(l); } while (0)
-diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
-index 35942084cd40..24f5fd1a789d 100644
---- a/include/linux/mnt_namespace.h
-+++ b/include/linux/mnt_namespace.h
-@@ -6,11 +6,14 @@
- struct mnt_namespace;
- struct fs_struct;
- struct user_namespace;
-+struct vfsmount;
-
- extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
- struct user_namespace *, struct fs_struct *);
- extern void put_mnt_ns(struct mnt_namespace *ns);
-
-+extern int is_current_mnt_ns(struct vfsmount *mnt);
-+
- extern const struct file_operations proc_mounts_operations;
- extern const struct file_operations proc_mountinfo_operations;
- extern const struct file_operations proc_mountstats_operations;
-diff --git a/include/linux/splice.h b/include/linux/splice.h
-index 74b4911ac16d..19789fbea567 100644
---- a/include/linux/splice.h
-+++ b/include/linux/splice.h
-@@ -87,4 +87,10 @@ extern void splice_shrink_spd(struct splice_pipe_desc *);
-
- extern const struct pipe_buf_operations page_cache_pipe_buf_ops;
- extern const struct pipe_buf_operations default_pipe_buf_ops;
-+
-+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
-+ loff_t *ppos, size_t len, unsigned int flags);
-+extern long do_splice_to(struct file *in, loff_t *ppos,
-+ struct pipe_inode_info *pipe, size_t len,
-+ unsigned int flags);
- #endif
-diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
-index 233459c03b5a..407c08ac8ac8 100644
---- a/kernel/locking/lockdep.c
-+++ b/kernel/locking/lockdep.c
-@@ -153,7 +153,7 @@ static
- struct lock_class lock_classes[MAX_LOCKDEP_KEYS];
- static DECLARE_BITMAP(lock_classes_in_use, MAX_LOCKDEP_KEYS);
-
--static inline struct lock_class *hlock_class(struct held_lock *hlock)
-+inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock)
- {
- unsigned int class_idx = hlock->class_idx;
-
-@@ -174,6 +174,7 @@ static inline struct lock_class *hlock_class(struct held_lock *hlock)
- */
- return lock_classes + class_idx;
- }
-+#define hlock_class(hlock) lockdep_hlock_class(hlock)
-
- #ifdef CONFIG_LOCK_STAT
- static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], cpu_lock_stats);
---
-2.19.1
-
diff --git a/features/aufs/aufs5-standalone.patch b/features/aufs/aufs5-standalone.patch
deleted file mode 100644
index 669de14c..00000000
--- a/features/aufs/aufs5-standalone.patch
+++ /dev/null
@@ -1,334 +0,0 @@
-From d1e47364cab1bde711064eba0acd07859c203bfe Mon Sep 17 00:00:00 2001
-From: Bruce Ashfield <bruce.ashfield@gmail.com>
-Date: Mon, 13 Jan 2020 12:31:58 -0500
-Subject: [PATCH 4/5] aufs5: standalone
-
-Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
----
- fs/dcache.c | 2 ++
- fs/exec.c | 1 +
- fs/fcntl.c | 1 +
- fs/file_table.c | 2 ++
- fs/inode.c | 1 +
- fs/namespace.c | 3 +++
- fs/notify/group.c | 1 +
- fs/open.c | 1 +
- fs/read_write.c | 4 ++++
- fs/splice.c | 2 ++
- fs/sync.c | 1 +
- fs/xattr.c | 1 +
- kernel/locking/lockdep.c | 1 +
- kernel/task_work.c | 1 +
- security/device_cgroup.c | 1 +
- security/security.c | 8 ++++++++
- 16 files changed, 31 insertions(+)
-
-diff --git a/fs/dcache.c b/fs/dcache.c
-index 7ce4ccf5a51c..00d7e6a08026 100644
---- a/fs/dcache.c
-+++ b/fs/dcache.c
-@@ -1369,6 +1369,7 @@ void d_walk(struct dentry *parent, void *data,
- seq = 1;
- goto again;
- }
-+EXPORT_SYMBOL_GPL(d_walk);
-
- struct check_mount {
- struct vfsmount *mnt;
-@@ -2914,6 +2915,7 @@ void d_exchange(struct dentry *dentry1, struct dentry *dentry2)
-
- write_sequnlock(&rename_lock);
- }
-+EXPORT_SYMBOL_GPL(d_exchange);
-
- /**
- * d_ancestor - search for an ancestor
-diff --git a/fs/exec.c b/fs/exec.c
-index c27231234764..2b5f96e645cd 100644
---- a/fs/exec.c
-+++ b/fs/exec.c
-@@ -110,6 +110,7 @@ bool path_noexec(const struct path *path)
- return (path->mnt->mnt_flags & MNT_NOEXEC) ||
- (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC);
- }
-+EXPORT_SYMBOL_GPL(path_noexec);
-
- #ifdef CONFIG_USELIB
- /*
-diff --git a/fs/fcntl.c b/fs/fcntl.c
-index d62303c5472a..d4ad34463848 100644
---- a/fs/fcntl.c
-+++ b/fs/fcntl.c
-@@ -85,6 +85,7 @@ int setfl(int fd, struct file * filp, unsigned long arg)
- out:
- return error;
- }
-+EXPORT_SYMBOL_GPL(setfl);
-
- static void f_modown(struct file *filp, struct pid *pid, enum pid_type type,
- int force)
-diff --git a/fs/file_table.c b/fs/file_table.c
-index 30d55c9a1744..34b9bbf4c556 100644
---- a/fs/file_table.c
-+++ b/fs/file_table.c
-@@ -162,6 +162,7 @@ struct file *alloc_empty_file(int flags, const struct cred *cred)
- }
- return ERR_PTR(-ENFILE);
- }
-+EXPORT_SYMBOL_GPL(alloc_empty_file);
-
- /*
- * Variant of alloc_empty_file() that doesn't check and modify nr_files.
-@@ -375,6 +376,7 @@ void __fput_sync(struct file *file)
- }
-
- EXPORT_SYMBOL(fput);
-+EXPORT_SYMBOL_GPL(__fput_sync);
-
- void __init files_init(void)
- {
-diff --git a/fs/inode.c b/fs/inode.c
-index 31796c1040d6..217169541ac4 100644
---- a/fs/inode.c
-+++ b/fs/inode.c
-@@ -1689,6 +1689,7 @@ int update_time(struct inode *inode, struct timespec64 *time, int flags)
-
- return update_time(inode, time, flags);
- }
-+EXPORT_SYMBOL_GPL(update_time);
-
- /**
- * touch_atime - update the access time
-diff --git a/fs/namespace.c b/fs/namespace.c
-index 0f7e57e5f4b7..516c2f397d33 100644
---- a/fs/namespace.c
-+++ b/fs/namespace.c
-@@ -431,6 +431,7 @@ void __mnt_drop_write(struct vfsmount *mnt)
- mnt_dec_writers(real_mount(mnt));
- preempt_enable();
- }
-+EXPORT_SYMBOL_GPL(__mnt_drop_write);
-
- /**
- * mnt_drop_write - give up write access to a mount
-@@ -781,6 +782,7 @@ int is_current_mnt_ns(struct vfsmount *mnt)
- {
- return check_mnt(real_mount(mnt));
- }
-+EXPORT_SYMBOL_GPL(is_current_mnt_ns);
-
- /*
- * vfsmount lock must be held for write
-@@ -1903,6 +1905,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
- }
- return 0;
- }
-+EXPORT_SYMBOL_GPL(iterate_mounts);
-
- static void lock_mnt_tree(struct mount *mnt)
- {
-diff --git a/fs/notify/group.c b/fs/notify/group.c
-index 133f723aca07..0b9f7f6d8390 100644
---- a/fs/notify/group.c
-+++ b/fs/notify/group.c
-@@ -99,6 +99,7 @@ void fsnotify_get_group(struct fsnotify_group *group)
- {
- refcount_inc(&group->refcnt);
- }
-+EXPORT_SYMBOL_GPL(fsnotify_get_group);
-
- /*
- * Drop a reference to a group. Free it if it's through.
-diff --git a/fs/open.c b/fs/open.c
-index b62f5c0923a8..89af4b9c7319 100644
---- a/fs/open.c
-+++ b/fs/open.c
-@@ -65,6 +65,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
- inode_unlock(dentry->d_inode);
- return ret;
- }
-+EXPORT_SYMBOL_GPL(do_truncate);
-
- long vfs_truncate(const struct path *path, loff_t length)
- {
-diff --git a/fs/read_write.c b/fs/read_write.c
-index 3265bb84f152..5b2dbddb0efe 100644
---- a/fs/read_write.c
-+++ b/fs/read_write.c
-@@ -468,6 +468,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
-
- return ret;
- }
-+EXPORT_SYMBOL_GPL(vfs_read);
-
- static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
- {
-@@ -508,6 +509,7 @@ vfs_readf_t vfs_readf(struct file *file)
- return new_sync_read;
- return ERR_PTR(-ENOSYS);
- }
-+EXPORT_SYMBOL_GPL(vfs_readf);
-
- vfs_writef_t vfs_writef(struct file *file)
- {
-@@ -519,6 +521,7 @@ vfs_writef_t vfs_writef(struct file *file)
- return new_sync_write;
- return ERR_PTR(-ENOSYS);
- }
-+EXPORT_SYMBOL_GPL(vfs_writef);
-
- ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
- {
-@@ -588,6 +591,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
-
- return ret;
- }
-+EXPORT_SYMBOL_GPL(vfs_write);
-
- /* file_ppos returns &file->f_pos or NULL if file is stream */
- static inline loff_t *file_ppos(struct file *file)
-diff --git a/fs/splice.c b/fs/splice.c
-index 8e38ef82a2ce..d47bcda3ae68 100644
---- a/fs/splice.c
-+++ b/fs/splice.c
-@@ -847,6 +847,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
-
- return splice_write(pipe, out, ppos, len, flags);
- }
-+EXPORT_SYMBOL_GPL(do_splice_from);
-
- /*
- * Attempt to initiate a splice from a file to a pipe.
-@@ -876,6 +877,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
-
- return splice_read(in, ppos, pipe, len, flags);
- }
-+EXPORT_SYMBOL_GPL(do_splice_to);
-
- /**
- * splice_direct_to_actor - splices data directly between two non-pipes
-diff --git a/fs/sync.c b/fs/sync.c
-index 457f4e4a5cc1..67c66358f3fe 100644
---- a/fs/sync.c
-+++ b/fs/sync.c
-@@ -39,6 +39,7 @@ int __sync_filesystem(struct super_block *sb, int wait)
- sb->s_op->sync_fs(sb, wait);
- return __sync_blockdev(sb->s_bdev, wait);
- }
-+EXPORT_SYMBOL_GPL(__sync_filesystem);
-
- /*
- * Write out and wait upon all dirty data associated with this
-diff --git a/fs/xattr.c b/fs/xattr.c
-index 90dd78f0eb27..40b01dd1b14a 100644
---- a/fs/xattr.c
-+++ b/fs/xattr.c
-@@ -296,6 +296,7 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
- *xattr_value = value;
- return error;
- }
-+EXPORT_SYMBOL_GPL(vfs_getxattr_alloc);
-
- ssize_t
- __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
-diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
-index 407c08ac8ac8..d7f71842f8a2 100644
---- a/kernel/locking/lockdep.c
-+++ b/kernel/locking/lockdep.c
-@@ -174,6 +174,7 @@ inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock)
- */
- return lock_classes + class_idx;
- }
-+EXPORT_SYMBOL_GPL(lockdep_hlock_class);
- #define hlock_class(hlock) lockdep_hlock_class(hlock)
-
- #ifdef CONFIG_LOCK_STAT
-diff --git a/kernel/task_work.c b/kernel/task_work.c
-index 0fef395662a6..83fb1ecfc33d 100644
---- a/kernel/task_work.c
-+++ b/kernel/task_work.c
-@@ -116,3 +116,4 @@ void task_work_run(void)
- } while (work);
- }
- }
-+EXPORT_SYMBOL_GPL(task_work_run);
-diff --git a/security/device_cgroup.c b/security/device_cgroup.c
-index 725674f3276d..83f6494c52a2 100644
---- a/security/device_cgroup.c
-+++ b/security/device_cgroup.c
-@@ -824,3 +824,4 @@ int __devcgroup_check_permission(short type, u32 major, u32 minor,
-
- return 0;
- }
-+EXPORT_SYMBOL_GPL(__devcgroup_check_permission);
-diff --git a/security/security.c b/security/security.c
-index 1bc000f834e2..306f2c9f7ee2 100644
---- a/security/security.c
-+++ b/security/security.c
-@@ -1036,6 +1036,7 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry)
- return 0;
- return call_int_hook(path_rmdir, 0, dir, dentry);
- }
-+EXPORT_SYMBOL_GPL(security_path_rmdir);
-
- int security_path_unlink(const struct path *dir, struct dentry *dentry)
- {
-@@ -1052,6 +1053,7 @@ int security_path_symlink(const struct path *dir, struct dentry *dentry,
- return 0;
- return call_int_hook(path_symlink, 0, dir, dentry, old_name);
- }
-+EXPORT_SYMBOL_GPL(security_path_symlink);
-
- int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
- struct dentry *new_dentry)
-@@ -1060,6 +1062,7 @@ int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
- return 0;
- return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry);
- }
-+EXPORT_SYMBOL_GPL(security_path_link);
-
- int security_path_rename(const struct path *old_dir, struct dentry *old_dentry,
- const struct path *new_dir, struct dentry *new_dentry,
-@@ -1087,6 +1090,7 @@ int security_path_truncate(const struct path *path)
- return 0;
- return call_int_hook(path_truncate, 0, path);
- }
-+EXPORT_SYMBOL_GPL(security_path_truncate);
-
- int security_path_chmod(const struct path *path, umode_t mode)
- {
-@@ -1094,6 +1098,7 @@ int security_path_chmod(const struct path *path, umode_t mode)
- return 0;
- return call_int_hook(path_chmod, 0, path, mode);
- }
-+EXPORT_SYMBOL_GPL(security_path_chmod);
-
- int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
- {
-@@ -1101,6 +1106,7 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
- return 0;
- return call_int_hook(path_chown, 0, path, uid, gid);
- }
-+EXPORT_SYMBOL_GPL(security_path_chown);
-
- int security_path_chroot(const struct path *path)
- {
-@@ -1201,6 +1207,7 @@ int security_inode_permission(struct inode *inode, int mask)
- return 0;
- return call_int_hook(inode_permission, 0, inode, mask);
- }
-+EXPORT_SYMBOL_GPL(security_inode_permission);
-
- int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
- {
-@@ -1378,6 +1385,7 @@ int security_file_permission(struct file *file, int mask)
-
- return fsnotify_perm(file, mask);
- }
-+EXPORT_SYMBOL_GPL(security_file_permission);
-
- int security_file_alloc(struct file *file)
- {
---
-2.19.1
-
diff --git a/features/aufs/aufs6-adapt-to-v6.6-i_op-ctime-changes.patch b/features/aufs/aufs6-adapt-to-v6.6-i_op-ctime-changes.patch
new file mode 100644
index 00000000..cb727220
--- /dev/null
+++ b/features/aufs/aufs6-adapt-to-v6.6-i_op-ctime-changes.patch
@@ -0,0 +1,146 @@
+From 8eeb547a388fee17c1c168bbb33d95e0c19e2cb4 Mon Sep 17 00:00:00 2001
+From: Bruce Ashfield <bruce.ashfield@gmail.com>
+Date: Thu, 21 Sep 2023 22:18:30 -0400
+Subject: [PATCH 8/8] aufs6: adapt to v6.6 i_op->ctime changes
+
+The following commits in 6.6+ change the way i_nodes and ctime are
+handled. We adapt the code to match:
+
+ 541d4c798a598854fcce7326d947cbcbd35701d6 [fs: drop the timespec64 arg from generic_update_time]
+ 3e3271549670783be20e233a2b78a87a0b04c715 [vfs: get rid of old '->iterate' directory operation]
+ 0d72b92883c651a11059d93335f33d65c6eb653b [fs: pass the request_mask to generic_fillattr]
+ 913e99287b98fd051ac1976140a2764a8ef9dfbf [fs: drop the timespec64 argument from update_time]
+
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/aufs/i_op.c | 9 ++++-----
+ fs/aufs/i_op_add.c | 2 +-
+ fs/aufs/i_op_del.c | 9 ++++++---
+ fs/aufs/i_op_ren.c | 6 ++++--
+ fs/aufs/vfsub.h | 5 ++---
+ 5 files changed, 17 insertions(+), 14 deletions(-)
+
+diff --git a/fs/aufs/i_op.c b/fs/aufs/i_op.c
+index 141620c2e0bd..993d57633393 100644
+--- a/fs/aufs/i_op.c
++++ b/fs/aufs/i_op.c
+@@ -1169,7 +1169,7 @@ static void au_refresh_iattr(struct inode *inode, struct kstat *st,
+ inode->i_gid = st->gid;
+ inode->i_atime = st->atime;
+ inode->i_mtime = st->mtime;
+- inode->i_ctime = st->ctime;
++ inode_set_ctime_to_ts( inode, st->ctime );
+
+ au_cpup_attr_nlink(inode, /*force*/0);
+ if (S_ISDIR(inode->i_mode)) {
+@@ -1306,7 +1306,7 @@ static int aufs_getattr(struct mnt_idmap *idmap, const struct path *path,
+ goto out_di;
+
+ out_fill:
+- generic_fillattr(idmap, inode, st);
++ generic_fillattr(idmap, request, inode, st);
+ out_di:
+ di_read_unlock(dentry, AuLock_IR);
+ out_si:
+@@ -1388,8 +1388,7 @@ static int au_is_special(struct inode *inode)
+ return (inode->i_mode & (S_IFBLK | S_IFCHR | S_IFIFO | S_IFSOCK));
+ }
+
+-static int aufs_update_time(struct inode *inode, struct timespec64 *ts,
+- int flags)
++static int aufs_update_time(struct inode *inode, int flags)
+ {
+ int err;
+ aufs_bindex_t bindex;
+@@ -1413,7 +1412,7 @@ static int aufs_update_time(struct inode *inode, struct timespec64 *ts,
+ h_mnt = au_sbr_mnt(sb, bindex);
+ err = vfsub_mnt_want_write(h_mnt);
+ if (!err) {
+- err = vfsub_update_time(h_inode, ts, flags);
++ err = vfsub_update_time(h_inode, flags);
+ vfsub_mnt_drop_write(h_mnt);
+ }
+ } else if (au_is_special(h_inode)) {
+diff --git a/fs/aufs/i_op_add.c b/fs/aufs/i_op_add.c
+index 2adf97d4488d..1ce4d45c8f7b 100644
+--- a/fs/aufs/i_op_add.c
++++ b/fs/aufs/i_op_add.c
+@@ -824,7 +824,7 @@ int aufs_link(struct dentry *src_dentry, struct inode *dir,
+ au_dir_ts(dir, a->bdst);
+ inode_inc_iversion(dir);
+ inc_nlink(inode);
+- inode->i_ctime = dir->i_ctime;
++ inode_set_ctime_to_ts( inode, inode_get_ctime(dir));
+ d_instantiate(dentry, au_igrab(inode));
+ if (d_unhashed(a->h_path.dentry))
+ /* some filesystem calls d_drop() */
+diff --git a/fs/aufs/i_op_del.c b/fs/aufs/i_op_del.c
+index d85f47cef29f..fbbda9626f6f 100644
+--- a/fs/aufs/i_op_del.c
++++ b/fs/aufs/i_op_del.c
+@@ -277,7 +277,8 @@ static void epilog(struct inode *dir, struct dentry *dentry,
+
+ inode = d_inode(dentry);
+ d_drop(dentry);
+- inode->i_ctime = dir->i_ctime;
++ //inode->i_ctime = dir->i_ctime;
++ inode_set_ctime_to_ts(inode, inode_get_ctime(dir));
+
+ au_dir_ts(dir, bindex);
+ inode_inc_iversion(dir);
+@@ -379,10 +380,12 @@ int aufs_unlink(struct inode *dir, struct dentry *dentry)
+ if (bindex == btop) {
+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL);
+ /*ignore*/
+- inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
++ //inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
++ inode_set_ctime_to_ts(inode, inode_get_ctime(d_inode(a->h_path.dentry)) );
+ } else
+ /* todo: this timestamp may be reverted later */
+- inode->i_ctime = h_dir->i_ctime;
++ //inode->i_ctime = h_dir->i_ctime;
++ inode_set_ctime_to_ts(inode,inode_get_ctime(h_dir) );
+ goto out_unpin; /* success */
+ }
+
+diff --git a/fs/aufs/i_op_ren.c b/fs/aufs/i_op_ren.c
+index ab69a6ac9a42..f3f9d9efe6fa 100644
+--- a/fs/aufs/i_op_ren.c
++++ b/fs/aufs/i_op_ren.c
+@@ -443,12 +443,14 @@ static int do_rename(struct au_ren_args *a)
+ AuDebugOn(au_dbtop(a->dst_dentry) != a->btgt);
+ a->h_path.dentry = au_h_dptr(a->dst_dentry, a->btgt);
+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
+- a->dst_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
++ //a->dst_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
++ inode_set_ctime_to_ts( a->dst_inode, inode_get_ctime(d_inode(a->h_path.dentry)) );
+ }
+ AuDebugOn(au_dbtop(a->src_dentry) != a->btgt);
+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
+- a->src_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
++ //a->src_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
++ inode_set_ctime_to_ts( a->src_inode, inode_get_ctime(d_inode(a->h_path.dentry)) );
+
+ if (!a->exchange) {
+ /* remove whiteout for dentry */
+diff --git a/fs/aufs/vfsub.h b/fs/aufs/vfsub.h
+index 928c463620c1..ed218d95770d 100644
+--- a/fs/aufs/vfsub.h
++++ b/fs/aufs/vfsub.h
+@@ -240,10 +240,9 @@ static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
+ }
+ #endif
+
+-static inline int vfsub_update_time(struct inode *h_inode,
+- struct timespec64 *ts, int flags)
++static inline int vfsub_update_time(struct inode *h_inode, int flags)
+ {
+- return inode_update_time(h_inode, ts, flags);
++ return inode_update_time(h_inode, flags);
+ /* no vfsub_update_h_iattr() since we don't have struct path */
+ }
+
+--
+2.34.1
+
diff --git a/features/aufs/aufs6-adapt-to-v6.6.patch b/features/aufs/aufs6-adapt-to-v6.6.patch
new file mode 100644
index 00000000..e91fec7a
--- /dev/null
+++ b/features/aufs/aufs6-adapt-to-v6.6.patch
@@ -0,0 +1,40 @@
+From 5d75cb88038136d82ae6bb62da3fa8f70785e662 Mon Sep 17 00:00:00 2001
+From: Bruce Ashfield <bruce.ashfield@gmail.com>
+Date: Thu, 21 Sep 2023 18:20:40 -0400
+Subject: [PATCH 6/8] aufs6: adapt to v6.6
+
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/fcntl.c | 2 +-
+ mm/mmap.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/fs/fcntl.c b/fs/fcntl.c
+index fdd334fc02fb..ec0562996478 100644
+--- a/fs/fcntl.c
++++ b/fs/fcntl.c
+@@ -34,7 +34,7 @@
+
+ #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
+
+-int setfl(int fd, struct file *filp, unsigned int arg)
++int setfl(int fd, struct file *filp, long unsigned int arg)
+ {
+ struct inode * inode = file_inode(filp);
+ int error = 0;
+diff --git a/mm/mmap.c b/mm/mmap.c
+index 0a0f3d5f558d..0bb0c5a0ad0e 100644
+--- a/mm/mmap.c
++++ b/mm/mmap.c
+@@ -3004,7 +3004,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
+ file = vma->vm_file;
+ prfile = vma->vm_prfile;
+ ret = do_mmap(vma->vm_file, start, size,
+- prot, flags, pgoff, &populate, NULL);
++ prot, flags, 0, pgoff, &populate, NULL);
+ if (!IS_ERR_VALUE(ret) && file && prfile) {
+ struct vm_area_struct *new_vma;
+
+--
+2.34.1
+
diff --git a/features/aufs/aufs6-base.patch b/features/aufs/aufs6-base.patch
new file mode 100644
index 00000000..186a7cee
--- /dev/null
+++ b/features/aufs/aufs6-base.patch
@@ -0,0 +1,230 @@
+From 884f46eed2730a238e0bf9c9a885f777a612e3ab Mon Sep 17 00:00:00 2001
+From: Bruce Ashfield <bruce.ashfield@gmail.com>
+Date: Thu, 21 Sep 2023 17:48:58 -0400
+Subject: [PATCH] aufs6: base
+
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ MAINTAINERS | 13 +++++++++++++
+ drivers/block/loop.c | 18 ++++++++++++++++++
+ fs/dcache.c | 2 +-
+ fs/fcntl.c | 4 +++-
+ fs/namespace.c | 6 ++++++
+ fs/splice.c | 2 +-
+ include/linux/fs.h | 2 ++
+ include/linux/lockdep.h | 2 ++
+ include/linux/mnt_namespace.h | 3 +++
+ include/linux/splice.h | 6 ++++++
+ kernel/locking/lockdep.c | 3 ++-
+ 11 files changed, 57 insertions(+), 4 deletions(-)
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 8d1052fa6a69..39ec86cca0ff 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -3365,6 +3365,19 @@ F: kernel/audit*
+ F: lib/*audit.c
+ K: \baudit_[a-z_0-9]\+\b
+
++AUFS (advanced multi layered unification filesystem) FILESYSTEM
++M: "J. R. Okajima" <hooanon05g@gmail.com>
++L: aufs-users@lists.sourceforge.net (members only)
++L: linux-unionfs@vger.kernel.org
++S: Supported
++W: http://aufs.sourceforge.net
++T: git://github.com/sfjro/aufs4-linux.git
++F: Documentation/ABI/testing/debugfs-aufs
++F: Documentation/ABI/testing/sysfs-aufs
++F: Documentation/filesystems/aufs/
++F: fs/aufs/
++F: include/uapi/linux/aufs_type.h
++
+ AUXILIARY BUS DRIVER
+ M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+ R: Dave Ertman <david.m.ertman@intel.com>
+diff --git a/drivers/block/loop.c b/drivers/block/loop.c
+index f8145499da38..333b3915fe86 100644
+--- a/drivers/block/loop.c
++++ b/drivers/block/loop.c
+@@ -641,6 +641,24 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
+ goto done;
+ }
+
++/*
++ * for AUFS
++ * no get/put for file.
++ */
++struct file *loop_backing_file(struct super_block *sb)
++{
++ struct file *ret;
++ struct loop_device *l;
++
++ ret = NULL;
++ if (MAJOR(sb->s_dev) == LOOP_MAJOR) {
++ l = sb->s_bdev->bd_disk->private_data;
++ ret = l->lo_backing_file;
++ }
++ return ret;
++}
++EXPORT_SYMBOL_GPL(loop_backing_file);
++
+ /* loop sysfs attributes */
+
+ static ssize_t loop_attr_show(struct device *dev, char *page,
+diff --git a/fs/dcache.c b/fs/dcache.c
+index b813528fb147..78e322b59b8d 100644
+--- a/fs/dcache.c
++++ b/fs/dcache.c
+@@ -1219,7 +1219,7 @@ enum d_walk_ret {
+ *
+ * The @enter() callbacks are called with d_lock held.
+ */
+-static void d_walk(struct dentry *parent, void *data,
++void d_walk(struct dentry *parent, void *data,
+ enum d_walk_ret (*enter)(void *, struct dentry *))
+ {
+ struct dentry *this_parent, *dentry;
+diff --git a/fs/fcntl.c b/fs/fcntl.c
+index c80a6acad742..d64817808e40 100644
+--- a/fs/fcntl.c
++++ b/fs/fcntl.c
+@@ -34,7 +34,7 @@
+
+ #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
+
+-static int setfl(int fd, struct file * filp, unsigned int arg)
++int setfl(int fd, struct file *filp, unsigned int arg)
+ {
+ struct inode * inode = file_inode(filp);
+ int error = 0;
+@@ -64,6 +64,8 @@ static int setfl(int fd, struct file * filp, unsigned int arg)
+
+ if (filp->f_op->check_flags)
+ error = filp->f_op->check_flags(arg);
++ if (!error && filp->f_op->setfl)
++ error = filp->f_op->setfl(filp, arg);
+ if (error)
+ return error;
+
+diff --git a/fs/namespace.c b/fs/namespace.c
+index 437f60e96d40..4c5eb92d2bef 100644
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -860,6 +860,12 @@ static inline int check_mnt(struct mount *mnt)
+ return mnt->mnt_ns == current->nsproxy->mnt_ns;
+ }
+
++/* for aufs, CONFIG_AUFS_BR_FUSE */
++int is_current_mnt_ns(struct vfsmount *mnt)
++{
++ return check_mnt(real_mount(mnt));
++}
++
+ /*
+ * vfsmount lock must be held for write
+ */
+diff --git a/fs/splice.c b/fs/splice.c
+index 218e24b1ac40..7210ddc5aa81 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -933,7 +933,7 @@ static int warn_unsupported(struct file *file, const char *op)
+ /*
+ * Attempt to initiate a splice from pipe to file.
+ */
+-static ssize_t do_splice_from(struct pipe_inode_info *pipe, struct file *out,
++ssize_t do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+ loff_t *ppos, size_t len, unsigned int flags)
+ {
+ if (unlikely(!out->f_op->splice_write))
+diff --git a/include/linux/fs.h b/include/linux/fs.h
+index ed5966a70495..2f2919192af6 100644
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -1104,6 +1104,7 @@ extern void fasync_free(struct fasync_struct *);
+ /* can be called from interrupts */
+ extern void kill_fasync(struct fasync_struct **, int, int);
+
++extern int setfl(int fd, struct file *filp, unsigned long arg);
+ extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int force);
+ extern int f_setown(struct file *filp, int who, int force);
+ extern void f_delown(struct file *filp);
+@@ -2001,6 +2002,7 @@ struct file_operations {
+ int (*lock) (struct file *, int, struct file_lock *);
+ unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
+ int (*check_flags)(int);
++ int (*setfl)(struct file *, unsigned long);
+ int (*flock) (struct file *, int, struct file_lock *);
+ ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
+ ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
+diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
+index 08b0d1d9d78b..009f69c4e09d 100644
+--- a/include/linux/lockdep.h
++++ b/include/linux/lockdep.h
+@@ -192,6 +192,8 @@ static inline int lockdep_match_key(struct lockdep_map *lock,
+ return lock->key == key;
+ }
+
++struct lock_class *lockdep_hlock_class(struct held_lock *hlock);
++
+ /*
+ * Acquire a lock.
+ *
+diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
+index 8f882f5881e8..6b9808f09843 100644
+--- a/include/linux/mnt_namespace.h
++++ b/include/linux/mnt_namespace.h
+@@ -7,12 +7,15 @@ struct mnt_namespace;
+ struct fs_struct;
+ struct user_namespace;
+ struct ns_common;
++struct vfsmount;
+
+ extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
+ struct user_namespace *, struct fs_struct *);
+ extern void put_mnt_ns(struct mnt_namespace *ns);
+ extern struct ns_common *from_mnt_ns(struct mnt_namespace *);
+
++extern int is_current_mnt_ns(struct vfsmount *mnt);
++
+ extern const struct file_operations proc_mounts_operations;
+ extern const struct file_operations proc_mountinfo_operations;
+ extern const struct file_operations proc_mountstats_operations;
+diff --git a/include/linux/splice.h b/include/linux/splice.h
+index 9dec4861d09f..8024911403e9 100644
+--- a/include/linux/splice.h
++++ b/include/linux/splice.h
+@@ -108,4 +108,10 @@ extern void splice_shrink_spd(struct splice_pipe_desc *);
+
+ extern const struct pipe_buf_operations page_cache_pipe_buf_ops;
+ extern const struct pipe_buf_operations default_pipe_buf_ops;
++
++extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
++ loff_t *ppos, size_t len, unsigned int flags);
++extern long do_splice_to(struct file *in, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags);
+ #endif
+diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
+index 151bd3de5936..2223ee909c10 100644
+--- a/kernel/locking/lockdep.c
++++ b/kernel/locking/lockdep.c
+@@ -218,7 +218,7 @@ unsigned long max_lock_class_idx;
+ struct lock_class lock_classes[MAX_LOCKDEP_KEYS];
+ DECLARE_BITMAP(lock_classes_in_use, MAX_LOCKDEP_KEYS);
+
+-static inline struct lock_class *hlock_class(struct held_lock *hlock)
++inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock)
+ {
+ unsigned int class_idx = hlock->class_idx;
+
+@@ -239,6 +239,7 @@ static inline struct lock_class *hlock_class(struct held_lock *hlock)
+ */
+ return lock_classes + class_idx;
+ }
++#define hlock_class(hlock) lockdep_hlock_class(hlock)
+
+ #ifdef CONFIG_LOCK_STAT
+ static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], cpu_lock_stats);
+--
+2.39.2
+
diff --git a/features/aufs/aufs5-core.patch b/features/aufs/aufs6-core.patch
index 16075d9c..d9585572 100644
--- a/features/aufs/aufs5-core.patch
+++ b/features/aufs/aufs6-core.patch
@@ -1,103 +1,104 @@
-From 86f59bbc023cb2c9f95b71eddc394f5d86bcf4d4 Mon Sep 17 00:00:00 2001
+From 88604e3862245a999b3cdc6d96e888a3edf0b0c7 Mon Sep 17 00:00:00 2001
From: Bruce Ashfield <bruce.ashfield@gmail.com>
-Date: Mon, 13 Jan 2020 12:33:15 -0500
-Subject: [PATCH 5/5] aufs5: core
+Date: Thu, 21 Sep 2023 17:51:24 -0400
+Subject: [PATCH 5/8] aufs6: core
Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
---
Documentation/ABI/testing/debugfs-aufs | 55 +
Documentation/ABI/testing/sysfs-aufs | 31 +
- Documentation/filesystems/aufs/README | 401 ++++
+ Documentation/filesystems/aufs/README | 409 ++++
.../filesystems/aufs/design/01intro.txt | 171 ++
.../filesystems/aufs/design/02struct.txt | 258 +++
.../filesystems/aufs/design/03atomic_open.txt | 85 +
.../filesystems/aufs/design/03lookup.txt | 113 +
.../filesystems/aufs/design/04branch.txt | 74 +
.../filesystems/aufs/design/05wbr_policy.txt | 64 +
- .../filesystems/aufs/design/06dirren.dot | 31 +
+ .../filesystems/aufs/design/06dirren.dot | 44 +
.../filesystems/aufs/design/06dirren.txt | 102 +
- .../filesystems/aufs/design/06fhsm.txt | 120 +
+ .../filesystems/aufs/design/06fhsm.txt | 118 +
.../filesystems/aufs/design/06mmap.txt | 72 +
- .../filesystems/aufs/design/06xattr.txt | 96 +
+ .../filesystems/aufs/design/06xattr.txt | 94 +
.../filesystems/aufs/design/07export.txt | 58 +
.../filesystems/aufs/design/08shwh.txt | 52 +
.../filesystems/aufs/design/10dynop.txt | 47 +
fs/aufs/Kconfig | 199 ++
fs/aufs/Makefile | 46 +
fs/aufs/aufs.h | 62 +
- fs/aufs/branch.c | 1428 ++++++++++++
- fs/aufs/branch.h | 366 +++
+ fs/aufs/branch.c | 1427 ++++++++++++
+ fs/aufs/branch.h | 375 ++++
fs/aufs/conf.mk | 40 +
- fs/aufs/cpup.c | 1458 ++++++++++++
+ fs/aufs/cpup.c | 1459 +++++++++++++
fs/aufs/cpup.h | 100 +
fs/aufs/dbgaufs.c | 526 +++++
fs/aufs/dbgaufs.h | 53 +
fs/aufs/dcsub.c | 225 ++
fs/aufs/dcsub.h | 137 ++
- fs/aufs/debug.c | 441 ++++
+ fs/aufs/debug.c | 446 ++++
fs/aufs/debug.h | 226 ++
- fs/aufs/dentry.c | 1154 ++++++++++
- fs/aufs/dentry.h | 268 +++
- fs/aufs/dinfo.c | 554 +++++
- fs/aufs/dir.c | 763 +++++++
+ fs/aufs/dentry.c | 1168 ++++++++++
+ fs/aufs/dentry.h | 270 +++
+ fs/aufs/dinfo.c | 555 +++++
+ fs/aufs/dir.c | 765 +++++++
fs/aufs/dir.h | 134 ++
- fs/aufs/dirren.c | 1316 +++++++++++
+ fs/aufs/dirren.c | 1315 +++++++++++
fs/aufs/dirren.h | 140 ++
- fs/aufs/dynop.c | 367 +++
+ fs/aufs/dynop.c | 366 ++++
fs/aufs/dynop.h | 77 +
- fs/aufs/export.c | 838 +++++++
- fs/aufs/f_op.c | 819 +++++++
- fs/aufs/fhsm.c | 427 ++++
- fs/aufs/file.c | 863 ++++++++
+ fs/aufs/export.c | 830 +++++++
+ fs/aufs/f_op.c | 771 +++++++
+ fs/aufs/fhsm.c | 426 ++++
+ fs/aufs/file.c | 865 ++++++++
fs/aufs/file.h | 342 +++
fs/aufs/finfo.c | 149 ++
+ fs/aufs/fsctx.c | 1242 +++++++++++
fs/aufs/fstype.h | 401 ++++
fs/aufs/hbl.h | 65 +
- fs/aufs/hfsnotify.c | 288 +++
+ fs/aufs/hfsnotify.c | 290 +++
fs/aufs/hfsplus.c | 60 +
- fs/aufs/hnotify.c | 721 ++++++
- fs/aufs/i_op.c | 1505 +++++++++++++
- fs/aufs/i_op_add.c | 936 ++++++++
- fs/aufs/i_op_del.c | 513 +++++
- fs/aufs/i_op_ren.c | 1250 +++++++++++
+ fs/aufs/hnotify.c | 715 ++++++
+ fs/aufs/i_op.c | 1517 +++++++++++++
+ fs/aufs/i_op_add.c | 972 +++++++++
+ fs/aufs/i_op_del.c | 522 +++++
+ fs/aufs/i_op_ren.c | 1257 +++++++++++
fs/aufs/iinfo.c | 286 +++
- fs/aufs/inode.c | 529 +++++
- fs/aufs/inode.h | 698 ++++++
+ fs/aufs/inode.c | 531 +++++
+ fs/aufs/inode.h | 707 ++++++
fs/aufs/ioctl.c | 220 ++
fs/aufs/lcnt.h | 186 ++
fs/aufs/loop.c | 148 ++
fs/aufs/loop.h | 55 +
fs/aufs/magic.mk | 31 +
fs/aufs/module.c | 273 +++
- fs/aufs/module.h | 166 ++
+ fs/aufs/module.h | 180 ++
fs/aufs/mvdown.c | 706 ++++++
- fs/aufs/opts.c | 1880 ++++++++++++++++
- fs/aufs/opts.h | 225 ++
+ fs/aufs/opts.c | 1032 +++++++++
+ fs/aufs/opts.h | 263 +++
fs/aufs/plink.c | 516 +++++
fs/aufs/poll.c | 51 +
- fs/aufs/posix_acl.c | 105 +
- fs/aufs/procfs.c | 171 ++
+ fs/aufs/posix_acl.c | 108 +
+ fs/aufs/procfs.c | 170 ++
fs/aufs/rdu.c | 384 ++++
- fs/aufs/rwsem.h | 73 +
- fs/aufs/sbinfo.c | 314 +++
- fs/aufs/super.c | 1047 +++++++++
- fs/aufs/super.h | 589 +++++
- fs/aufs/sysaufs.c | 93 +
+ fs/aufs/rwsem.h | 85 +
+ fs/aufs/sbinfo.c | 316 +++
+ fs/aufs/super.c | 871 ++++++++
+ fs/aufs/super.h | 592 +++++
+ fs/aufs/sysaufs.c | 94 +
fs/aufs/sysaufs.h | 102 +
fs/aufs/sysfs.c | 374 ++++
- fs/aufs/sysrq.c | 160 ++
+ fs/aufs/sysrq.c | 149 ++
fs/aufs/vdir.c | 896 ++++++++
- fs/aufs/vfsub.c | 902 ++++++++
- fs/aufs/vfsub.h | 354 +++
+ fs/aufs/vfsub.c | 918 ++++++++
+ fs/aufs/vfsub.h | 404 ++++
fs/aufs/wbr_policy.c | 830 +++++++
- fs/aufs/whout.c | 1062 +++++++++
- fs/aufs/whout.h | 86 +
- fs/aufs/wkq.c | 392 ++++
+ fs/aufs/whout.c | 1072 +++++++++
+ fs/aufs/whout.h | 87 +
+ fs/aufs/wkq.c | 372 ++++
fs/aufs/wkq.h | 89 +
- fs/aufs/xattr.c | 356 +++
- fs/aufs/xino.c | 1965 +++++++++++++++++
+ fs/aufs/xattr.c | 360 +++
+ fs/aufs/xino.c | 1926 +++++++++++++++++
include/uapi/linux/aufs_type.h | 452 ++++
- 92 files changed, 37853 insertions(+)
+ 93 files changed, 38218 insertions(+)
create mode 100644 Documentation/ABI/testing/debugfs-aufs
create mode 100644 Documentation/ABI/testing/sysfs-aufs
create mode 100644 Documentation/filesystems/aufs/README
@@ -144,6 +145,7 @@ Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
create mode 100644 fs/aufs/file.c
create mode 100644 fs/aufs/file.h
create mode 100644 fs/aufs/finfo.c
+ create mode 100644 fs/aufs/fsctx.c
create mode 100644 fs/aufs/fstype.h
create mode 100644 fs/aufs/hbl.h
create mode 100644 fs/aufs/hfsnotify.c
@@ -193,7 +195,7 @@ Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
diff --git a/Documentation/ABI/testing/debugfs-aufs b/Documentation/ABI/testing/debugfs-aufs
new file mode 100644
-index 000000000000..4a6694194ba6
+index 000000000000..45b739879d76
--- /dev/null
+++ b/Documentation/ABI/testing/debugfs-aufs
@@ -0,0 +1,55 @@
@@ -227,7 +229,7 @@ index 000000000000..4a6694194ba6
+ When the aufs mount option 'noxino' is specified, it
+ will be empty. About XINO files, see the aufs manual.
+
-+What: /debug/aufs/si_<id>/xi0, xi1 ... xiN and xiN-N
++What: /debug/aufs/si_<id>/xi<branch-index>
+Date: March 2009
+Contact: J. R. Okajima <hooanon05g@gmail.com>
+Description:
@@ -254,7 +256,7 @@ index 000000000000..4a6694194ba6
+ will be empty. About XINO files, see the aufs manual.
diff --git a/Documentation/ABI/testing/sysfs-aufs b/Documentation/ABI/testing/sysfs-aufs
new file mode 100644
-index 000000000000..82f9518495ea
+index 000000000000..48500c0569e6
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-aufs
@@ -0,0 +1,31 @@
@@ -266,14 +268,14 @@ index 000000000000..82f9518495ea
+ per aufs mount, where <id> is a unique id generated
+ internally.
+
-+What: /sys/fs/aufs/si_<id>/br0, br1 ... brN
++What: /sys/fs/aufs/si_<id>/br<idx>
+Date: March 2009
+Contact: J. R. Okajima <hooanon05g@gmail.com>
+Description:
+ It shows the abolute path of a member directory (which
+ is called branch) in aufs, and its permission.
+
-+What: /sys/fs/aufs/si_<id>/brid0, brid1 ... bridN
++What: /sys/fs/aufs/si_<id>/brid<idx>
+Date: July 2013
+Contact: J. R. Okajima <hooanon05g@gmail.com>
+Description:
@@ -291,12 +293,12 @@ index 000000000000..82f9518495ea
+ will be empty. About XINO files, see the aufs manual.
diff --git a/Documentation/filesystems/aufs/README b/Documentation/filesystems/aufs/README
new file mode 100644
-index 000000000000..3e655d357134
+index 000000000000..04a4d069bb52
--- /dev/null
+++ b/Documentation/filesystems/aufs/README
-@@ -0,0 +1,401 @@
+@@ -0,0 +1,409 @@
+
-+Aufs5 -- advanced multi layered unification filesystem version 5.x
++Aufs6 -- advanced multi layered unification filesystem version 6.x
+http://aufs.sf.net
+Junjiro R. Okajima
+
@@ -312,13 +314,19 @@ index 000000000000..3e655d357134
+Unionfs was being developed by Professor Erez Zadok at Stony Brook
+University and his team.
+
-+Aufs5 supports linux-v5.0 and later, If you want older kernel version
-+support,
++Aufs6 supports linux-v6.0 and later, try aufs6.0 branch in
++aufs-linux.git or aufs-standalone.git.
++If you want older kernel version support,
++- for linux-v5.x series, try aufs-linux.git or aufs-standalone.git
+- for linux-v4.x series, try aufs4-linux.git or aufs4-standalone.git
+- for linux-v3.x series, try aufs3-linux.git or aufs3-standalone.git
+- for linux-v2.6.16 and later, try aufs2-2.6.git, aufs2-standalone.git
+ or aufs1 from CVS on SourceForge.
+
++Note: the name of aufs5-linux.git and aufs5-standalone.git on github
++ were changed. Now they are aufs-linux.git and
++ aufs-standalone.git and they contain aufs5 and later branches.
++
+Note: it becomes clear that "Aufs was rejected. Let's give it up."
+ According to Christoph Hellwig, linux rejects all union-type
+ filesystems but UnionMount.
@@ -377,7 +385,7 @@ index 000000000000..3e655d357134
+- userspace wrapper for pathconf(3)/fpathconf(3) with _PC_LINK_MAX.
+- and more...
+
-+Currently these features are dropped temporary from aufs5.
++Currently these features are dropped temporary from aufs6.
+See design/08plan.txt in detail.
+- nested mount, i.e. aufs as readonly no-whiteout branch of another aufs
+ (robr)
@@ -395,64 +403,63 @@ index 000000000000..3e655d357134
+
+2. Download
+----------------------------------------
-+There are three GIT trees for aufs5, aufs5-linux.git,
-+aufs5-standalone.git, and aufs-util.git. Note that there is no "5" in
-+"aufs-util.git."
-+While the aufs-util is always necessary, you need either of aufs5-linux
-+or aufs5-standalone.
++There are three GIT trees for aufs6, aufs-linux.git,
++aufs-standalone.git, and aufs-util.git.
++While the aufs-util is always necessary, you need either of aufs-linux
++or aufs-standalone.
+
-+The aufs5-linux tree includes the whole linux mainline GIT tree,
++The aufs-linux tree includes the whole linux mainline GIT tree,
+git://git.kernel.org/.../torvalds/linux.git.
+And you cannot select CONFIG_AUFS_FS=m for this version, eg. you cannot
-+build aufs5 as an external kernel module.
++build aufs6 as an external kernel module.
+Several extra patches are not included in this tree. Only
-+aufs5-standalone tree contains them. They are described in the later
++aufs-standalone tree contains them. They are described in the later
+section "Configuration and Compilation."
+
-+On the other hand, the aufs5-standalone tree has only aufs source files
++On the other hand, the aufs-standalone tree has only aufs source files
+and necessary patches, and you can select CONFIG_AUFS_FS=m.
+But you need to apply all aufs patches manually.
+
-+You will find GIT branches whose name is in form of "aufs5.x" where "x"
-+represents the linux kernel version, "linux-5.x". For instance,
-+"aufs5.0" is for linux-5.0. For latest "linux-5.x-rcN", use
-+"aufs5.x-rcN" branch.
++You will find GIT branches whose name is in form of "aufs6.x" where "x"
++represents the linux kernel version, "linux-6.x". For instance,
++"aufs6.0" is for linux-6.0. For latest "linux-6.x-rcN", use
++"aufs6.x-rcN" branch.
+
-+o aufs5-linux tree
++o aufs-linux tree
+$ git clone --reference /your/linux/git/tree \
-+ git://github.com/sfjro/aufs5-linux.git aufs5-linux.git
++ git://github.com/sfjro/aufs-linux.git aufs-linux.git
+- if you don't have linux GIT tree, then remove "--reference ..."
-+$ cd aufs5-linux.git
-+$ git checkout origin/aufs5.0
++$ cd aufs-linux.git
++$ git checkout origin/aufs6.0
+
+Or You may want to directly git-pull aufs into your linux GIT tree, and
+leave the patch-work to GIT.
+$ cd /your/linux/git/tree
-+$ git remote add aufs5 git://github.com/sfjro/aufs5-linux.git
-+$ git fetch aufs5
-+$ git checkout -b my5.0 v5.0
++$ git remote add aufs git://github.com/sfjro/aufs-linux.git
++$ git fetch aufs
++$ git checkout -b my6.0 v6.0
+$ (add your local change...)
-+$ git pull aufs5 aufs5.0
-+- now you have v5.0 + your_changes + aufs5.0 in you my5.0 branch.
++$ git pull aufs aufs6.0
++- now you have v6.0 + your_changes + aufs6.0 in you my6.0 branch.
+- you may need to solve some conflicts between your_changes and
-+ aufs5.0. in this case, git-rerere is recommended so that you can
-+ solve the similar conflicts automatically when you upgrade to 5.1 or
++ aufs6.0. in this case, git-rerere is recommended so that you can
++ solve the similar conflicts automatically when you upgrade to 6.1 or
+ later in the future.
+
-+o aufs5-standalone tree
-+$ git clone git://github.com/sfjro/aufs5-standalone.git aufs5-standalone.git
-+$ cd aufs5-standalone.git
-+$ git checkout origin/aufs5.0
++o aufs-standalone tree
++$ git clone git://github.com/sfjro/aufs-standalone.git aufs-standalone.git
++$ cd aufs-standalone.git
++$ git checkout origin/aufs6.0
+
+o aufs-util tree
+$ git clone git://git.code.sf.net/p/aufs/aufs-util aufs-util.git
+- note that the public aufs-util.git is on SourceForge instead of
+ GitHUB.
+$ cd aufs-util.git
-+$ git checkout origin/aufs5.0
++$ git checkout origin/aufs6.0
+
-+Note: The 5.x-rcN branch is to be used with `rc' kernel versions ONLY.
-+The minor version number, 'x' in '5.x', of aufs may not always
++Note: The 6.x-rcN branch is to be used with `rc' kernel versions ONLY.
++The minor version number, 'x' in '6.x', of aufs may not always
+follow the minor version number of the kernel.
+Because changes in the kernel that cause the use of a new
+minor version number do not always require changes to aufs-util.
@@ -464,8 +471,8 @@ index 000000000000..3e655d357134
+nearest lower number.
+
+For (an unreleased) example:
-+If you are using "linux-5.10" and the "aufs5.10" branch
-+does not exist in aufs-util repository, then "aufs5.9", "aufs5.8"
++If you are using "linux-6.10" and the "aufs6.10" branch
++does not exist in aufs-util repository, then "aufs6.9", "aufs6.8"
+or something numerically smaller is the branch for your kernel.
+
+Also you can view all branches by
@@ -476,19 +483,31 @@ index 000000000000..3e655d357134
+----------------------------------------
+Make sure you have git-checkout'ed the correct branch.
+
-+For aufs5-linux tree,
++For aufs-linux tree,
+- enable CONFIG_AUFS_FS.
+- set other aufs configurations if necessary.
-+
-+For aufs5-standalone tree,
++- for aufs5.13 and later
++ Because aufs is not only an ordinary filesystem (callee of VFS), but
++ also a caller of VFS functions for branch filesystems, subclassing of
++ the internal locks for LOCKDEP is necessary. LOCKDEP is a debugging
++ feature of linux kernel. If you enable CONFIG_LOCKDEP, then you will
++ need to customize some LOCKDEP numbers. Here are what I use on my
++ test environment.
++ CONFIG_LOCKDEP_BITS=21
++ CONFIG_LOCKDEP_CHAINS_BITS=21
++ CONFIG_LOCKDEP_STACK_TRACE_BITS=24
++ Also you will need to expand some constant values in LOCKDEP. Refer
++ to lockdep-debug.patch in aufs-standalone.git.
++
++For aufs-standalone tree,
+There are several ways to build.
+
+1.
-+- apply ./aufs5-kbuild.patch to your kernel source files.
-+- apply ./aufs5-base.patch too.
-+- apply ./aufs5-mmap.patch too.
-+- apply ./aufs5-standalone.patch too, if you have a plan to set
-+ CONFIG_AUFS_FS=m. otherwise you don't need ./aufs5-standalone.patch.
++- apply ./aufs6-kbuild.patch to your kernel source files.
++- apply ./aufs6-base.patch too.
++- apply ./aufs6-mmap.patch too.
++- apply ./aufs6-standalone.patch too, if you have a plan to set
++ CONFIG_AUFS_FS=m. otherwise you don't need ./aufs-standalone.patch.
+- copy ./{Documentation,fs,include/uapi/linux/aufs_type.h} files to your
+ kernel source tree. Never copy $PWD/include/uapi/linux/Kbuild.
+- enable CONFIG_AUFS_FS, you can select either
@@ -502,9 +521,9 @@ index 000000000000..3e655d357134
+
+2.
+- module only (CONFIG_AUFS_FS=m).
-+- apply ./aufs5-base.patch to your kernel source files.
-+- apply ./aufs5-mmap.patch too.
-+- apply ./aufs5-standalone.patch too.
++- apply ./aufs6-base.patch to your kernel source files.
++- apply ./aufs6-mmap.patch too.
++- apply ./aufs6-standalone.patch too.
+- build your kernel, don't forget "make headers_install", and reboot.
+- edit ./config.mk and set other aufs configurations if necessary.
+ Note: You should read $PWD/fs/aufs/Kconfig carefully which describes
@@ -520,7 +539,7 @@ index 000000000000..3e655d357134
+ available in aufs standalone version's Makefile only), or copy
+ $PWD/usr/include/linux/aufs_type.h to /usr/include/linux or wherever
+ you like manually. By default, the target directory is $PWD/usr.
-+- no need to apply aufs5-kbuild.patch, nor copying source files to your
++- no need to apply aufs6-kbuild.patch, nor copying source files to your
+ kernel source tree.
+
+Note: The header file aufs_type.h is necessary to build aufs-util
@@ -540,19 +559,12 @@ index 000000000000..3e655d357134
+ then run "make install_ulib" too. And refer to the aufs manual in
+ detail.
+
-+There several other patches in aufs5-standalone.git. They are all
++There several other patches in aufs-standalone.git. They are all
+optional. When you meet some problems, they will help you.
-+- aufs5-loopback.patch
++- aufs6-loopback.patch
+ Supports a nested loopback mount in a branch-fs. This patch is
+ unnecessary until aufs produces a message like "you may want to try
+ another patch for loopback file".
-+- proc_mounts.patch
-+ When there are many mountpoints and many mount(2)/umount(2) are
-+ running, then /proc/mounts may not show the all mountpoints. This
-+ patch makes /proc/mounts always show the full mountpoints list.
-+ If you don't want to apply this patch and meet such problem, then you
-+ need to increase the value of 'ProcMounts_Times' make-variable in
-+ aufs-util.git as a second best solution.
+- vfs-ino.patch
+ Modifies a system global kernel internal function get_next_ino() in
+ order to stop assigning 0 for an inode-number. Not directly related to
@@ -564,13 +576,9 @@ index 000000000000..3e655d357134
+ other utilities. When you find aufs XINO files for tmpfs branch
+ growing too much, try this patch.
+- lockdep-debug.patch
-+ Because aufs is not only an ordinary filesystem (callee of VFS), but
-+ also a caller of VFS functions for branch filesystems, subclassing of
-+ the internal locks for LOCKDEP is necessary. LOCKDEP is a debugging
-+ feature of linux kernel. If you enable CONFIG_LOCKDEP, then you will
-+ need to apply this debug patch to expand several constant values.
-+ If you don't know what LOCKDEP is, then you don't have apply this
-+ patch.
++ Similar to some kernel configurations for LOCKDEP (see the top of
++ this section), you will need expand some constants in LOCKDEP for
++ aufs if you enable CONFIG_LOCKDEP.
+
+
+4. Usage
@@ -671,7 +679,7 @@ index 000000000000..3e655d357134
+The Parted Magic Project made a donation (2013/9 and 11).
+Pavel Barta made a donation (2013/10).
+Nikolay Pertsev made a donation (2014/5).
-+James B made a donation (2014/7 and 2015/7).
++James B made a donation (2014/7, 2015/7, and 2021/12).
+Stefano Di Biase made a donation (2014/8).
+Daniel Epellei made a donation (2015/1).
+OmegaPhil made a donation (2016/1, 2018/4).
@@ -679,6 +687,8 @@ index 000000000000..3e655d357134
+James Burry made a donation (2016/12).
+Carsten Rose made a donation (2018/9).
+Porteus Kiosk made a donation (2018/10).
++huronOS team: Enya Quetzalli made donations (2022/5, 2023/5 and 8).
++Vasily Mikhaylichenko made a donation (2023/5).
+
+Thank you very much.
+Donations are always, including future donations, very important and
@@ -698,23 +708,23 @@ index 000000000000..3e655d357134
+# End: ;
diff --git a/Documentation/filesystems/aufs/design/01intro.txt b/Documentation/filesystems/aufs/design/01intro.txt
new file mode 100644
-index 000000000000..609bf0e9b93a
+index 000000000000..4c468b3264b5
--- /dev/null
+++ b/Documentation/filesystems/aufs/design/01intro.txt
@@ -0,0 +1,171 @@
+
-+# Copyright (C) 2005-2019 Junjiro R. Okajima
-+#
++# Copyright (C) 2005-2022 Junjiro R. Okajima
++#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
-+#
++#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
-+#
++#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
@@ -875,23 +885,23 @@ index 000000000000..609bf0e9b93a
+about it. But currently I have implemented it in kernel space.
diff --git a/Documentation/filesystems/aufs/design/02struct.txt b/Documentation/filesystems/aufs/design/02struct.txt
new file mode 100644
-index 000000000000..2467788c7f10
+index 000000000000..83be46121ae2
--- /dev/null
+++ b/Documentation/filesystems/aufs/design/02struct.txt
@@ -0,0 +1,258 @@
+
-+# Copyright (C) 2005-2019 Junjiro R. Okajima
-+#
++# Copyright (C) 2005-2022 Junjiro R. Okajima
++#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
-+#
++#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
-+#
++#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
@@ -1139,23 +1149,23 @@ index 000000000000..2467788c7f10
+For this purpose, use "aumvdown" command in aufs-util.git.
diff --git a/Documentation/filesystems/aufs/design/03atomic_open.txt b/Documentation/filesystems/aufs/design/03atomic_open.txt
new file mode 100644
-index 000000000000..9f16ac1e0173
+index 000000000000..4811f2432465
--- /dev/null
+++ b/Documentation/filesystems/aufs/design/03atomic_open.txt
@@ -0,0 +1,85 @@
+
-+# Copyright (C) 2015-2019 Junjiro R. Okajima
-+#
++# Copyright (C) 2015-2022 Junjiro R. Okajima
++#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
-+#
++#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
-+#
++#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
@@ -1230,23 +1240,23 @@ index 000000000000..9f16ac1e0173
+ be implemented in aufs, but not all I am afraid.
diff --git a/Documentation/filesystems/aufs/design/03lookup.txt b/Documentation/filesystems/aufs/design/03lookup.txt
new file mode 100644
-index 000000000000..08b443d94dfa
+index 000000000000..766a28be0263
--- /dev/null
+++ b/Documentation/filesystems/aufs/design/03lookup.txt
@@ -0,0 +1,113 @@
+
-+# Copyright (C) 2005-2019 Junjiro R. Okajima
-+#
++# Copyright (C) 2005-2022 Junjiro R. Okajima
++#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
-+#
++#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
-+#
++#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
@@ -1349,23 +1359,23 @@ index 000000000000..08b443d94dfa
+ by over-mounting something (or another method).
diff --git a/Documentation/filesystems/aufs/design/04branch.txt b/Documentation/filesystems/aufs/design/04branch.txt
new file mode 100644
-index 000000000000..3ab3682a42b4
+index 000000000000..ffeb97dcaff3
--- /dev/null
+++ b/Documentation/filesystems/aufs/design/04branch.txt
@@ -0,0 +1,74 @@
+
-+# Copyright (C) 2005-2019 Junjiro R. Okajima
-+#
++# Copyright (C) 2005-2022 Junjiro R. Okajima
++#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
-+#
++#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
-+#
++#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
@@ -1429,23 +1439,23 @@ index 000000000000..3ab3682a42b4
+ same named entry on the upper branch.
diff --git a/Documentation/filesystems/aufs/design/05wbr_policy.txt b/Documentation/filesystems/aufs/design/05wbr_policy.txt
new file mode 100644
-index 000000000000..1f9b86bc6a3e
+index 000000000000..a2143bfe6efc
--- /dev/null
+++ b/Documentation/filesystems/aufs/design/05wbr_policy.txt
@@ -0,0 +1,64 @@
+
-+# Copyright (C) 2005-2019 Junjiro R. Okajima
-+#
++# Copyright (C) 2005-2022 Junjiro R. Okajima
++#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
-+#
++#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
-+#
++#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
@@ -1499,12 +1509,25 @@ index 000000000000..1f9b86bc6a3e
+ copyup policy.
diff --git a/Documentation/filesystems/aufs/design/06dirren.dot b/Documentation/filesystems/aufs/design/06dirren.dot
new file mode 100644
-index 000000000000..2d62bb6dd55f
+index 000000000000..4e6c7e7c20ef
--- /dev/null
+++ b/Documentation/filesystems/aufs/design/06dirren.dot
-@@ -0,0 +1,31 @@
+@@ -0,0 +1,44 @@
+
+// to view this graph, run dot(1) command in GRAPHVIZ.
++//
++// This program is free software; you can redistribute it and/or modify
++// it under the terms of the GNU General Public License as published by
++// the Free Software Foundation; either version 2 of the License, or
++// (at your option) any later version.
++//
++// This program is distributed in the hope that it will be useful,
++// but WITHOUT ANY WARRANTY; without even the implied warranty of
++// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++// GNU General Public License for more details.
++//
++// You should have received a copy of the GNU General Public License
++// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+digraph G {
+node [shape=box];
@@ -1536,12 +1559,12 @@ index 000000000000..2d62bb6dd55f
+}
diff --git a/Documentation/filesystems/aufs/design/06dirren.txt b/Documentation/filesystems/aufs/design/06dirren.txt
new file mode 100644
-index 000000000000..3b80f8659b3e
+index 000000000000..58ec5e22fe3d
--- /dev/null
+++ b/Documentation/filesystems/aufs/design/06dirren.txt
@@ -0,0 +1,102 @@
+
-+# Copyright (C) 2017-2019 Junjiro R. Okajima
++# Copyright (C) 2017-2022 Junjiro R. Okajima
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
@@ -1619,7 +1642,7 @@ index 000000000000..3b80f8659b3e
+simply the inode-numbers on the branch. The file is created or updated
+in removing the branch, and loaded in adding the branch. Its lifetime is
+equal to the branch.
-+The list is refered in lookup, and when the current target inode is
++The list is referred in lookup, and when the current target inode is
+found in the list, the aufs tries loading the "detailed info per
+directory" and get the changed and valid name of the dir.
+
@@ -1644,27 +1667,25 @@ index 000000000000..3b80f8659b3e
+equivalen to udba=reval case.
diff --git a/Documentation/filesystems/aufs/design/06fhsm.txt b/Documentation/filesystems/aufs/design/06fhsm.txt
new file mode 100644
-index 000000000000..8b498d0af812
+index 000000000000..d3b56325ff87
--- /dev/null
+++ b/Documentation/filesystems/aufs/design/06fhsm.txt
-@@ -0,0 +1,120 @@
+@@ -0,0 +1,118 @@
+
-+# Copyright (C) 2011-2019 Junjiro R. Okajima
-+#
++# Copyright (C) 2011-2022 Junjiro R. Okajima
++#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
-+#
++#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
-+#
++#
+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, write to the Free Software
-+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-+
++# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+File-based Hierarchical Storage Management (FHSM)
+----------------------------------------------------------------------
@@ -1770,23 +1791,23 @@ index 000000000000..8b498d0af812
+should restore the original file state after an error happens.
diff --git a/Documentation/filesystems/aufs/design/06mmap.txt b/Documentation/filesystems/aufs/design/06mmap.txt
new file mode 100644
-index 000000000000..cdd84ea777fc
+index 000000000000..ddc65ce97fa3
--- /dev/null
+++ b/Documentation/filesystems/aufs/design/06mmap.txt
@@ -0,0 +1,72 @@
+
-+# Copyright (C) 2005-2019 Junjiro R. Okajima
-+#
++# Copyright (C) 2005-2022 Junjiro R. Okajima
++#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
-+#
++#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
-+#
++#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
@@ -1848,12 +1869,12 @@ index 000000000000..cdd84ea777fc
+I have to give up this "looks-smater" approach.
diff --git a/Documentation/filesystems/aufs/design/06xattr.txt b/Documentation/filesystems/aufs/design/06xattr.txt
new file mode 100644
-index 000000000000..edd7553f3289
+index 000000000000..4e5ead3ad741
--- /dev/null
+++ b/Documentation/filesystems/aufs/design/06xattr.txt
-@@ -0,0 +1,96 @@
+@@ -0,0 +1,94 @@
+
-+# Copyright (C) 2014-2019 Junjiro R. Okajima
++# Copyright (C) 2014-2022 Junjiro R. Okajima
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
@@ -1866,9 +1887,7 @@ index 000000000000..edd7553f3289
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
-+# along with this program; if not, write to the Free Software
-+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-+
++# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Listing XATTR/EA and getting the value
+----------------------------------------------------------------------
@@ -1950,23 +1969,23 @@ index 000000000000..edd7553f3289
+now, aufs implements the branch attributes to ignore the error.
diff --git a/Documentation/filesystems/aufs/design/07export.txt b/Documentation/filesystems/aufs/design/07export.txt
new file mode 100644
-index 000000000000..9b983f3dd78a
+index 000000000000..40b2f1f12049
--- /dev/null
+++ b/Documentation/filesystems/aufs/design/07export.txt
@@ -0,0 +1,58 @@
+
-+# Copyright (C) 2005-2019 Junjiro R. Okajima
-+#
++# Copyright (C) 2005-2022 Junjiro R. Okajima
++#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
-+#
++#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
-+#
++#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
@@ -2014,23 +2033,23 @@ index 000000000000..9b983f3dd78a
+ lookup_one_len(), vfs_getattr(), encode_fh() and others.
diff --git a/Documentation/filesystems/aufs/design/08shwh.txt b/Documentation/filesystems/aufs/design/08shwh.txt
new file mode 100644
-index 000000000000..647a86a65db7
+index 000000000000..67245e98e6b4
--- /dev/null
+++ b/Documentation/filesystems/aufs/design/08shwh.txt
@@ -0,0 +1,52 @@
+
-+# Copyright (C) 2005-2019 Junjiro R. Okajima
-+#
++# Copyright (C) 2005-2022 Junjiro R. Okajima
++#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
-+#
++#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
-+#
++#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
@@ -2072,12 +2091,12 @@ index 000000000000..647a86a65db7
+initramfs will use it to replace the old one at the next boot.
diff --git a/Documentation/filesystems/aufs/design/10dynop.txt b/Documentation/filesystems/aufs/design/10dynop.txt
new file mode 100644
-index 000000000000..13e8583f2b91
+index 000000000000..da382ec2dc05
--- /dev/null
+++ b/Documentation/filesystems/aufs/design/10dynop.txt
@@ -0,0 +1,47 @@
+
-+# Copyright (C) 2010-2019 Junjiro R. Okajima
++# Copyright (C) 2010-2022 Junjiro R. Okajima
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
@@ -2125,7 +2144,7 @@ index 000000000000..13e8583f2b91
+regular files only.
diff --git a/fs/aufs/Kconfig b/fs/aufs/Kconfig
new file mode 100644
-index 000000000000..9f436425716a
+index 000000000000..a5008b87a55f
--- /dev/null
+++ b/fs/aufs/Kconfig
@@ -0,0 +1,199 @@
@@ -2255,7 +2274,7 @@ index 000000000000..9f436425716a
+ his child on the lower branch, since it is a bad idea to issue
+ rename(2) internally for every lower branch. But user may not
+ accept this behaviour. So here is a workaround to allow such
-+ rename(2) and store some extra infromation on the writable
++ rename(2) and store some extra information on the writable
+ branch. Obviously this costs high (and I don't like it).
+ To use this feature, you need to enable this configuration AND
+ to specify the mount option `dirren.'
@@ -2330,7 +2349,7 @@ index 000000000000..9f436425716a
+endif
diff --git a/fs/aufs/Makefile b/fs/aufs/Makefile
new file mode 100644
-index 000000000000..2c819a64935e
+index 000000000000..4af8ecde3e3f
--- /dev/null
+++ b/fs/aufs/Makefile
@@ -0,0 +1,46 @@
@@ -2353,7 +2372,7 @@ index 000000000000..2c819a64935e
+endif
+
+obj-$(CONFIG_AUFS_FS) += aufs.o
-+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
++aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o fsctx.o \
+ wkq.o vfsub.o dcsub.o \
+ cpup.o whout.o wbr_policy.o \
+ dinfo.o dentry.o \
@@ -2382,15 +2401,15 @@ index 000000000000..2c819a64935e
+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
diff --git a/fs/aufs/aufs.h b/fs/aufs/aufs.h
new file mode 100644
-index 000000000000..a62a85211b88
+index 000000000000..20430cf79042
--- /dev/null
+++ b/fs/aufs/aufs.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -2450,15 +2469,15 @@ index 000000000000..a62a85211b88
+#endif /* __AUFS_H__ */
diff --git a/fs/aufs/branch.c b/fs/aufs/branch.c
new file mode 100644
-index 000000000000..608bf76f8f21
+index 000000000000..2a85d744d2b5
--- /dev/null
+++ b/fs/aufs/branch.c
-@@ -0,0 +1,1428 @@
+@@ -0,0 +1,1427 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -3735,7 +3754,7 @@ index 000000000000..608bf76f8f21
+ * file_release_write() for each file, because the branch
+ * attribute in aufs world is totally different from the native
+ * fs rw/ro mode.
-+ */
++ */
+ /* fi_read_lock(file); */
+ hfile = &au_fi(file)->fi_htop;
+ hf = hfile->hf_file;
@@ -3746,11 +3765,10 @@ index 000000000000..608bf76f8f21
+ spin_unlock(&hf->f_lock);
+ if (writer) {
+ h_inode = file_inode(hf);
++ if (hf->f_mode & FMODE_READ)
++ i_readcount_inc(h_inode);
+ put_write_access(h_inode);
+ __mnt_drop_write(hf->f_path.mnt);
-+ if ((hf->f_mode & (FMODE_READ | FMODE_WRITE))
-+ == FMODE_READ)
-+ i_readcount_inc(h_inode);
+ }
+ }
+
@@ -3884,15 +3902,15 @@ index 000000000000..608bf76f8f21
+}
diff --git a/fs/aufs/branch.h b/fs/aufs/branch.h
new file mode 100644
-index 000000000000..012459ad57f3
+index 000000000000..6818ba8df8a2
--- /dev/null
+++ b/fs/aufs/branch.h
-@@ -0,0 +1,366 @@
+@@ -0,0 +1,375 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -4036,6 +4054,11 @@ index 000000000000..012459ad57f3
+ return br->br_path.dentry;
+}
+
++static inline struct mnt_idmap *au_br_idmap(struct au_branch *br)
++{
++ return mnt_idmap(br->br_path.mnt);
++}
++
+static inline struct super_block *au_br_sb(struct au_branch *br)
+{
+ return au_br_mnt(br)->mnt_sb;
@@ -4131,10 +4154,8 @@ index 000000000000..012459ad57f3
+ ino_t *ino);
+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
+ ino_t ino);
-+ssize_t xino_fread(vfs_readf_t func, struct file *file, void *buf, size_t size,
-+ loff_t *pos);
-+ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf,
-+ size_t size, loff_t *pos);
++ssize_t xino_fread(struct file *file, void *buf, size_t size, loff_t *pos);
++ssize_t xino_fwrite(struct file *file, void *buf, size_t size, loff_t *pos);
+
+int au_xib_trunc(struct super_block *sb);
+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin);
@@ -4197,6 +4218,12 @@ index 000000000000..012459ad57f3
+}
+
+static inline
++struct mnt_idmap *au_sbr_idmap(struct super_block *sb, aufs_bindex_t bindex)
++{
++ return au_br_idmap(au_sbr(sb, bindex));
++}
++
++static inline
+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
+{
+ return au_br_sb(au_sbr(sb, bindex));
@@ -4302,15 +4329,15 @@ index 000000000000..12782f8e0f38
+-include ${srctree}/${src}/conf_priv.mk
diff --git a/fs/aufs/cpup.c b/fs/aufs/cpup.c
new file mode 100644
-index 000000000000..21134b448967
+index 000000000000..8c8bd5f7b28d
--- /dev/null
+++ b/fs/aufs/cpup.c
-@@ -0,0 +1,1458 @@
+@@ -0,0 +1,1459 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -4472,7 +4499,7 @@ index 000000000000..21134b448967
+};
+
+static noinline_for_stack
-+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src,
++int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct path *h_src,
+ struct au_cpup_reg_attr *h_src_attr)
+{
+ int err, sbits, icex;
@@ -4484,11 +4511,11 @@ index 000000000000..21134b448967
+ struct kstat *h_st;
+ struct au_branch *br;
+
-+ h_path.dentry = au_h_dptr(dst, bindex);
-+ h_idst = d_inode(h_path.dentry);
+ br = au_sbr(dst->d_sb, bindex);
+ h_path.mnt = au_br_mnt(br);
-+ h_isrc = d_inode(h_src);
++ h_path.dentry = au_h_dptr(dst, bindex);
++ h_idst = d_inode(h_path.dentry);
++ h_isrc = d_inode(h_src->dentry);
+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
+ | ATTR_ATIME | ATTR_MTIME
+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
@@ -4532,7 +4559,7 @@ index 000000000000..21134b448967
+ if (!err) {
+ mnt_flags = au_mntflags(dst->d_sb);
+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
-+ err = au_cpup_xattr(h_path.dentry, h_src, icex, verbose);
++ err = au_cpup_xattr(&h_path, h_src, icex, verbose);
+ }
+
+ return err;
@@ -4877,32 +4904,19 @@ index 000000000000..21134b448967
+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
+ struct inode *h_dir)
+{
-+ int err, symlen;
-+ mm_segment_t old_fs;
-+ union {
-+ char *k;
-+ char __user *u;
-+ } sym;
++ int err;
++ DEFINE_DELAYED_CALL(done);
++ const char *sym;
+
-+ err = -ENOMEM;
-+ sym.k = (void *)__get_free_page(GFP_NOFS);
-+ if (unlikely(!sym.k))
++ sym = vfs_get_link(h_src, &done);
++ err = PTR_ERR(sym);
++ if (IS_ERR(sym))
+ goto out;
+
-+ /* unnecessary to support mmap_sem since symlink is not mmap-able */
-+ old_fs = get_fs();
-+ set_fs(KERNEL_DS);
-+ symlen = vfs_readlink(h_src, sym.u, PATH_MAX);
-+ err = symlen;
-+ set_fs(old_fs);
-+
-+ if (symlen > 0) {
-+ sym.k[symlen] = 0;
-+ err = vfsub_symlink(h_dir, h_path, sym.k);
-+ }
-+ free_page((unsigned long)sym.k);
++ err = vfsub_symlink(h_dir, h_path, sym);
+
+out:
++ do_delayed_call(&done);
+ return err;
+}
+
@@ -4910,21 +4924,23 @@ index 000000000000..21134b448967
+ * regardless 'acl' option, reset all ACL.
+ * All ACL will be copied up later from the original entry on the lower branch.
+ */
-+static int au_reset_acl(struct inode *h_dir, struct path *h_path, umode_t mode)
++static int au_reset_acl(struct path *h_path, umode_t mode)
+{
+ int err;
+ struct dentry *h_dentry;
-+ struct inode *h_inode;
++ /* struct inode *h_inode; */
++ struct mnt_idmap *h_idmap;
+
++ h_idmap = mnt_idmap(h_path->mnt);
+ h_dentry = h_path->dentry;
-+ h_inode = d_inode(h_dentry);
++ /* h_inode = d_inode(h_dentry); */
+ /* forget_all_cached_acls(h_inode)); */
-+ err = vfsub_removexattr(h_dentry, XATTR_NAME_POSIX_ACL_ACCESS);
++ err = vfsub_remove_acl(h_idmap, h_dentry, XATTR_NAME_POSIX_ACL_ACCESS);
+ AuTraceErr(err);
+ if (err == -EOPNOTSUPP)
+ err = 0;
+ if (!err)
-+ err = vfsub_acl_chmod(h_inode, mode);
++ err = vfsub_acl_chmod(h_idmap, h_dentry, mode);
+
+ AuTraceErr(err);
+ return err;
@@ -4935,8 +4951,11 @@ index 000000000000..21134b448967
+{
+ int err;
+ struct inode *dir, *inode;
++ struct mnt_idmap *h_idmap;
+
-+ err = vfsub_removexattr(h_path->dentry, XATTR_NAME_POSIX_ACL_DEFAULT);
++ h_idmap = mnt_idmap(h_path->mnt);
++ err = vfsub_remove_acl(h_idmap, h_path->dentry,
++ XATTR_NAME_POSIX_ACL_DEFAULT);
+ AuTraceErr(err);
+ if (err == -EOPNOTSUPP)
+ err = 0;
@@ -5017,7 +5036,7 @@ index 000000000000..21134b448967
+ case S_IFCHR:
+ case S_IFBLK:
+ AuDebugOn(!capable(CAP_MKNOD));
-+ /*FALLTHROUGH*/
++ fallthrough;
+ case S_IFIFO:
+ case S_IFSOCK:
+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
@@ -5027,7 +5046,7 @@ index 000000000000..21134b448967
+ err = -EIO;
+ }
+ if (!err)
-+ err = au_reset_acl(h_dir, &h_path, mode);
++ err = au_reset_acl(&h_path, mode);
+
+ mnt_flags = au_mntflags(sb);
+ if (!au_opt_test(mnt_flags, UDBA_NONE)
@@ -5061,11 +5080,13 @@ index 000000000000..21134b448967
+{
+ int err;
+ struct dentry *dentry, *h_dentry, *h_parent, *parent;
++ struct path h_ppath;
+ struct inode *h_dir;
+ aufs_bindex_t bdst;
+
+ dentry = cpg->dentry;
+ bdst = cpg->bdst;
++ h_ppath.mnt = au_sbr_mnt(dentry->d_sb, bdst);
+ h_dentry = au_h_dptr(dentry, bdst);
+ if (!au_ftest_cpup(cpg->flags, OVERWRITE)) {
+ dget(h_dentry);
@@ -5077,9 +5098,9 @@ index 000000000000..21134b448967
+ } else {
+ err = 0;
+ parent = dget_parent(dentry);
-+ h_parent = au_h_dptr(parent, bdst);
++ h_ppath.dentry = au_h_dptr(parent, bdst);
+ dput(parent);
-+ h_path->dentry = vfsub_lkup_one(&dentry->d_name, h_parent);
++ h_path->dentry = vfsub_lkup_one(&dentry->d_name, &h_ppath);
+ if (IS_ERR(h_path->dentry))
+ err = PTR_ERR(h_path->dentry);
+ }
@@ -5117,6 +5138,7 @@ index 000000000000..21134b448967
+ struct inode *dst_inode, *h_dir, *inode, *delegated, *src_inode;
+ struct super_block *sb;
+ struct au_branch *br;
++ struct path h_src_path;
+ /* to reduce stack size */
+ struct {
+ struct au_dtime dt;
@@ -5208,7 +5230,9 @@ index 000000000000..21134b448967
+ /* todo: necessary? */
+ /* au_pin_hdir_unlock(cpg->pin); */
+
-+ err = cpup_iattr(cpg->dentry, cpg->bdst, h_src, &a->h_src_attr);
++ h_src_path.dentry = h_src;
++ h_src_path.mnt = au_sbr_mnt(sb, cpg->bsrc);
++ err = cpup_iattr(cpg->dentry, cpg->bdst, &h_src_path, &a->h_src_attr);
+ if (unlikely(err)) {
+ /* todo: necessary? */
+ /* au_pin_hdir_relock(cpg->pin); */ /* ignore an error */
@@ -5410,6 +5434,7 @@ index 000000000000..21134b448967
+ struct dentry *dentry, *parent;
+ struct file *h_file;
+ struct inode *h_dir;
++ struct mnt_idmap *h_idmap;
+
+ dentry = cpg->dentry;
+ h_file = NULL;
@@ -5423,7 +5448,8 @@ index 000000000000..21134b448967
+
+ parent = dget_parent(dentry);
+ h_dir = au_h_iptr(d_inode(parent), cpg->bdst);
-+ if (!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE)
++ h_idmap = au_sbr_idmap(dentry->d_sb, cpg->bdst);
++ if (!au_test_h_perm_sio(h_idmap, h_dir, MAY_EXEC | MAY_WRITE)
+ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode))
+ err = au_cpup_simple(cpg);
+ else {
@@ -5593,6 +5619,7 @@ index 000000000000..21134b448967
+ struct inode *dir, *h_dir, *h_tmpdir;
+ struct au_wbr *wbr;
+ struct au_pin wh_pin, *pin_orig;
++ struct mnt_idmap *h_idmap;
+
+ dentry = cpg->dentry;
+ bdst = cpg->bdst;
@@ -5621,7 +5648,8 @@ index 000000000000..21134b448967
+ cpg->pin = &wh_pin;
+ }
+
-+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE)
++ h_idmap = au_sbr_idmap(dentry->d_sb, bdst);
++ if (!au_test_h_perm_sio(h_idmap, h_tmpdir, MAY_EXEC | MAY_WRITE)
+ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode))
+ err = au_cpup_wh(cpg, file);
+ else {
@@ -5766,15 +5794,15 @@ index 000000000000..21134b448967
+}
diff --git a/fs/aufs/cpup.h b/fs/aufs/cpup.h
new file mode 100644
-index 000000000000..abcbfbc55a5c
+index 000000000000..decd8f01425a
--- /dev/null
+++ b/fs/aufs/cpup.h
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -5872,15 +5900,15 @@ index 000000000000..abcbfbc55a5c
+#endif /* __AUFS_CPUP_H__ */
diff --git a/fs/aufs/dbgaufs.c b/fs/aufs/dbgaufs.c
new file mode 100644
-index 000000000000..e32d91d1f638
+index 000000000000..d5811df890b5
--- /dev/null
+++ b/fs/aufs/dbgaufs.c
@@ -0,0 +1,526 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -6042,7 +6070,7 @@ index 000000000000..e32d91d1f638
+ } else {
+#define str "1\n0\n0\n"
+ p->n = sizeof(str) - 1;
-+ strcpy(p->a, str);
++ strscpy(p->a, str, sizeof(str));
+#undef str
+ }
+ si_read_unlock(sb);
@@ -6404,15 +6432,15 @@ index 000000000000..e32d91d1f638
+}
diff --git a/fs/aufs/dbgaufs.h b/fs/aufs/dbgaufs.h
new file mode 100644
-index 000000000000..1ea241bf0234
+index 000000000000..30f1694224e0
--- /dev/null
+++ b/fs/aufs/dbgaufs.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -6463,15 +6491,15 @@ index 000000000000..1ea241bf0234
+#endif /* __DBGAUFS_H__ */
diff --git a/fs/aufs/dcsub.c b/fs/aufs/dcsub.c
new file mode 100644
-index 000000000000..0b9122307667
+index 000000000000..fa2a9ad2b49b
--- /dev/null
+++ b/fs/aufs/dcsub.c
@@ -0,0 +1,225 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -6694,15 +6722,15 @@ index 000000000000..0b9122307667
+}
diff --git a/fs/aufs/dcsub.h b/fs/aufs/dcsub.h
new file mode 100644
-index 000000000000..5e578995c256
+index 000000000000..7e4f4eba0343
--- /dev/null
+++ b/fs/aufs/dcsub.h
@@ -0,0 +1,137 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -6837,15 +6865,15 @@ index 000000000000..5e578995c256
+#endif /* __AUFS_DCSUB_H__ */
diff --git a/fs/aufs/debug.c b/fs/aufs/debug.c
new file mode 100644
-index 000000000000..b93bb4f565bf
+index 000000000000..e14075c4bccc
--- /dev/null
+++ b/fs/aufs/debug.c
-@@ -0,0 +1,441 @@
+@@ -0,0 +1,446 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -6890,7 +6918,7 @@ index 000000000000..b93bb4f565bf
+ return sprintf(buffer, "%d", atomic_read(a));
+}
+
-+static struct kernel_param_ops param_ops_atomic_t = {
++static const struct kernel_param_ops param_ops_atomic_t = {
+ .set = param_atomic_t_set,
+ .get = param_atomic_t_get
+ /* void (*free)(void *arg) */
@@ -6970,11 +6998,13 @@ index 000000000000..b93bb4f565bf
+ }
+
+ dpri("i%d: %p, i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
++ " acl %p, def_acl %p,"
+ " hn %d, ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
+ bindex, inode,
+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
+ i_size_read(inode), (unsigned long long)inode->i_blocks,
++ inode->i_acl, inode->i_default_acl,
+ hn, (long long)timespec64_to_ns(&inode->i_ctime) & 0x0ffff,
+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
+ inode->i_state, inode->i_flags, inode_peek_iversion(inode),
@@ -7226,7 +7256,10 @@ index 000000000000..b93bb4f565bf
+ AuDbgDentry(dentry);
+ AuDbgInode(inode);
+ au_debug_off();
-+ BUG();
++ if (au_test_fuse(h_inode->i_sb))
++ WARN_ON_ONCE(1);
++ else
++ BUG();
+ }
+ }
+}
@@ -7284,15 +7317,15 @@ index 000000000000..b93bb4f565bf
+}
diff --git a/fs/aufs/debug.h b/fs/aufs/debug.h
new file mode 100644
-index 000000000000..9c52470a61fb
+index 000000000000..f757588e5000
--- /dev/null
+++ b/fs/aufs/debug.h
@@ -0,0 +1,226 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -7516,15 +7549,15 @@ index 000000000000..9c52470a61fb
+#endif /* __AUFS_DEBUG_H__ */
diff --git a/fs/aufs/dentry.c b/fs/aufs/dentry.c
new file mode 100644
-index 000000000000..faf664508e64
+index 000000000000..ed7ce8f6d1a1
--- /dev/null
+++ b/fs/aufs/dentry.c
-@@ -0,0 +1,1154 @@
+@@ -0,0 +1,1168 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -7543,7 +7576,6 @@ index 000000000000..faf664508e64
+ */
+
+#include <linux/iversion.h>
-+#include <linux/namei.h>
+#include "aufs.h"
+
+/*
@@ -7557,6 +7589,8 @@ index 000000000000..faf664508e64
+ struct dentry *h_dentry;
+ struct inode *h_inode;
+ struct au_branch *br;
++ struct mnt_idmap *h_idmap;
++ struct path h_path;
+ int wh_found, opq;
+ unsigned char wh_able;
+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
@@ -7565,9 +7599,13 @@ index 000000000000..faf664508e64
+
+ wh_found = 0;
+ br = au_sbr(dentry->d_sb, bindex);
++ h_path.dentry = h_parent;
++ h_path.mnt = au_br_mnt(br);
++ h_idmap = au_br_idmap(br);
+ wh_able = !!au_br_whable(br->br_perm);
+ if (wh_able)
-+ wh_found = au_wh_test(h_parent, &args->whname, ignore_perm);
++ wh_found = au_wh_test(h_idmap, &h_path, &args->whname,
++ ignore_perm);
+ h_dentry = ERR_PTR(wh_found);
+ if (!wh_found)
+ goto real_lookup;
@@ -7582,9 +7620,9 @@ index 000000000000..faf664508e64
+
+real_lookup:
+ if (!ignore_perm)
-+ h_dentry = vfsub_lkup_one(args->name, h_parent);
++ h_dentry = vfsub_lkup_one(args->name, &h_path);
+ else
-+ h_dentry = au_sio_lkup_one(args->name, h_parent);
++ h_dentry = au_sio_lkup_one(h_idmap, args->name, &h_path);
+ if (IS_ERR(h_dentry)) {
+ if (PTR_ERR(h_dentry) == -ENAMETOOLONG
+ && !allow_neg)
@@ -7618,8 +7656,9 @@ index 000000000000..faf664508e64
+ || (d_really_is_positive(dentry) && !d_is_dir(dentry)))
+ goto out; /* success */
+
++ h_path.dentry = h_dentry;
+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD);
-+ opq = au_diropq_test(h_dentry);
++ opq = au_diropq_test(h_idmap, &h_path);
+ inode_unlock_shared(h_inode);
+ if (opq > 0)
+ au_set_dbdiropq(dentry, bindex);
@@ -7764,18 +7803,19 @@ index 000000000000..faf664508e64
+ return err;
+}
+
-+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent)
++struct dentry *au_sio_lkup_one(struct mnt_idmap *idmap, struct qstr *name,
++ struct path *ppath)
+{
+ struct dentry *dentry;
+ int wkq_err;
+
-+ if (!au_test_h_perm_sio(d_inode(parent), MAY_EXEC))
-+ dentry = vfsub_lkup_one(name, parent);
++ if (!au_test_h_perm_sio(idmap, d_inode(ppath->dentry), MAY_EXEC))
++ dentry = vfsub_lkup_one(name, ppath);
+ else {
+ struct vfsub_lkup_one_args args = {
+ .errp = &dentry,
+ .name = name,
-+ .parent = parent
++ .ppath = ppath
+ };
+
+ wkq_err = au_wkq_wait(vfsub_call_lkup_one, &args);
@@ -7792,16 +7832,20 @@ index 000000000000..faf664508e64
+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh)
+{
+ int err;
-+ struct dentry *parent, *h_parent, *h_dentry;
++ struct dentry *parent, *h_dentry;
+ struct au_branch *br;
++ struct mnt_idmap *h_idmap;
++ struct path h_ppath;
+
+ parent = dget_parent(dentry);
-+ h_parent = au_h_dptr(parent, bindex);
+ br = au_sbr(dentry->d_sb, bindex);
++ h_ppath.dentry = au_h_dptr(parent, bindex);
++ h_ppath.mnt = au_br_mnt(br);
++ h_idmap = au_br_idmap(br);
+ if (wh)
-+ h_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
++ h_dentry = au_whtmp_lkup(h_ppath.dentry, br, &dentry->d_name);
+ else
-+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent);
++ h_dentry = au_sio_lkup_one(h_idmap, &dentry->d_name, &h_ppath);
+ err = PTR_ERR(h_dentry);
+ if (IS_ERR(h_dentry))
+ goto out;
@@ -7876,6 +7920,7 @@ index 000000000000..faf664508e64
+ struct inode *h_inode;
+ struct dentry *h_d;
+ struct super_block *h_sb;
++ struct path h_ppath;
+
+ err = 0;
+ memset(&ia, -1, sizeof(ia));
@@ -7890,7 +7935,9 @@ index 000000000000..faf664508e64
+ goto out;
+
+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
-+ h_d = vfsub_lkup_one(&h_dentry->d_name, h_parent);
++ h_ppath.dentry = h_parent;
++ h_ppath.mnt = au_br_mnt(br);
++ h_d = vfsub_lkup_one(&h_dentry->d_name, &h_ppath);
+ err = PTR_ERR(h_d);
+ if (IS_ERR(h_d))
+ goto out;
@@ -8676,15 +8723,15 @@ index 000000000000..faf664508e64
+};
diff --git a/fs/aufs/dentry.h b/fs/aufs/dentry.h
new file mode 100644
-index 000000000000..3b443fc7eef0
+index 000000000000..da4c9063d7e1
--- /dev/null
+++ b/fs/aufs/dentry.h
-@@ -0,0 +1,268 @@
+@@ -0,0 +1,270 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -8723,6 +8770,7 @@ index 000000000000..3b443fc7eef0
+ aufs_bindex_t di_btop, di_bbot, di_bwh, di_bdiropq;
+ unsigned char di_tmpfile; /* to allow the different name */
+ struct au_hdentry *di_hdentry;
++ struct file *di_htmpfile;
+ struct rcu_head rcu;
+} ____cacheline_aligned_in_smp;
+
@@ -8755,7 +8803,8 @@ index 000000000000..3b443fc7eef0
+/* dentry.c */
+extern const struct dentry_operations aufs_dop, aufs_dop_noreval;
+struct au_branch;
-+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent);
++struct dentry *au_sio_lkup_one(struct mnt_idmap *idmap, struct qstr *name,
++ struct path *ppath);
+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
+ struct dentry *h_parent, struct au_branch *br);
+
@@ -8950,15 +8999,15 @@ index 000000000000..3b443fc7eef0
+#endif /* __AUFS_DENTRY_H__ */
diff --git a/fs/aufs/dinfo.c b/fs/aufs/dinfo.c
new file mode 100644
-index 000000000000..86140548f046
+index 000000000000..bf4a94414309
--- /dev/null
+++ b/fs/aufs/dinfo.c
-@@ -0,0 +1,554 @@
+@@ -0,0 +1,555 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -9007,6 +9056,7 @@ index 000000000000..86140548f046
+ dinfo->di_tmpfile = 0;
+ for (i = 0; i < nbr; i++)
+ dinfo->di_hdentry[i].hd_id = -1;
++ dinfo->di_htmpfile = NULL;
+ goto out;
+ }
+
@@ -9510,15 +9560,15 @@ index 000000000000..86140548f046
+}
diff --git a/fs/aufs/dir.c b/fs/aufs/dir.c
new file mode 100644
-index 000000000000..68e87d6f287e
+index 000000000000..ee900ea3264b
--- /dev/null
+++ b/fs/aufs/dir.c
-@@ -0,0 +1,763 @@
+@@ -0,0 +1,765 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -10065,9 +10115,9 @@ index 000000000000..68e87d6f287e
+ aufs_bindex_t bindex;
+};
+
-+static int test_empty_cb(struct dir_context *ctx, const char *__name,
-+ int namelen, loff_t offset __maybe_unused, u64 ino,
-+ unsigned int d_type)
++static bool test_empty_cb(struct dir_context *ctx, const char *__name,
++ int namelen, loff_t offset __maybe_unused, u64 ino,
++ unsigned int d_type)
+{
+ struct test_empty_arg *arg = container_of(ctx, struct test_empty_arg,
+ ctx);
@@ -10098,7 +10148,7 @@ index 000000000000..68e87d6f287e
+out:
+ /* smp_mb(); */
+ AuTraceErr(arg->err);
-+ return arg->err;
++ return !arg->err;
+}
+
+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
@@ -10153,12 +10203,14 @@ index 000000000000..68e87d6f287e
+ int err, wkq_err;
+ struct dentry *h_dentry;
+ struct inode *h_inode;
++ struct mnt_idmap *h_idmap;
+
++ h_idmap = au_sbr_idmap(dentry->d_sb, arg->bindex);
+ h_dentry = au_h_dptr(dentry, arg->bindex);
+ h_inode = d_inode(h_dentry);
+ /* todo: i_mode changes anytime? */
+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD);
-+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
++ err = au_test_h_perm_sio(h_idmap, h_inode, MAY_EXEC | MAY_READ);
+ inode_unlock_shared(h_inode);
+ if (!err)
+ err = do_test_empty(dentry, arg);
@@ -10279,15 +10331,15 @@ index 000000000000..68e87d6f287e
+};
diff --git a/fs/aufs/dir.h b/fs/aufs/dir.h
new file mode 100644
-index 000000000000..5c8065d258bf
+index 000000000000..382342bd6ecf
--- /dev/null
+++ b/fs/aufs/dir.h
@@ -0,0 +1,134 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -10323,7 +10375,7 @@ index 000000000000..5c8065d258bf
+
+struct au_vdir_destr {
+ unsigned char len;
-+ unsigned char name[0];
++ unsigned char name[];
+} __packed;
+
+struct au_vdir_dehstr {
@@ -10419,15 +10471,15 @@ index 000000000000..5c8065d258bf
+#endif /* __AUFS_DIR_H__ */
diff --git a/fs/aufs/dirren.c b/fs/aufs/dirren.c
new file mode 100644
-index 000000000000..df8a89c970e9
+index 000000000000..2a6295ab6576
--- /dev/null
+++ b/fs/aufs/dirren.c
-@@ -0,0 +1,1316 @@
+@@ -0,0 +1,1315 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2017-2019 Junjiro R. Okajima
++ * Copyright (C) 2017-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -10506,7 +10558,7 @@ index 000000000000..df8a89c970e9
+ found = 0;
+ idx = au_dr_ihash(ino);
+ hbl = dr->dr_h_ino + idx;
-+#if 0
++#if 0 /* debug print */
+ {
+ struct hlist_bl_node *tmp;
+
@@ -10688,7 +10740,8 @@ index 000000000000..df8a89c970e9
+ dir = d_inode(path->dentry);
+ inode_lock_nested(dir, AuLsc_I_CHILD);
+ }
-+ hinopath.dentry = vfsub_lkup_one(&hinoname, path->dentry);
++ hinopath.mnt = path->mnt;
++ hinopath.dentry = vfsub_lkup_one(&hinoname, (struct path *)path);
+ err = PTR_ERR(hinopath.dentry);
+ if (IS_ERR(hinopath.dentry))
+ goto out_unlock;
@@ -10722,7 +10775,6 @@ index 000000000000..df8a89c970e9
+ }
+ flags = O_WRONLY;
+ }
-+ hinopath.mnt = path->mnt;
+ hinofile = vfsub_dentry_open(&hinopath, flags);
+ if (suspend)
+ au_hn_inode_unlock(hdir);
@@ -11009,7 +11061,7 @@ index 000000000000..df8a89c970e9
+struct au_drinfo_rev {
+ unsigned char already;
+ aufs_bindex_t nelm;
-+ struct au_drinfo_rev_elm elm[0];
++ struct au_drinfo_rev_elm elm[];
+};
+
+/* todo: isn't it too large? */
@@ -11044,7 +11096,7 @@ index 000000000000..df8a89c970e9
+ AuDebugOn(elm
+ && memcmp(elm, page_address(ZERO_PAGE(0)), sizeof(*elm)));
+
-+ infopath.dentry = vfsub_lookup_one_len(w->whname, w->h_ppath.dentry,
++ infopath.dentry = vfsub_lookup_one_len(w->whname, &w->h_ppath,
+ w->whnamelen);
+ AuTraceErrPtr(infopath.dentry);
+ if (IS_ERR(infopath.dentry)) {
@@ -11160,7 +11212,7 @@ index 000000000000..df8a89c970e9
+
+ memset(w, 0, sizeof(*w));
+ w->allocated = roundup_pow_of_two(sizeof(*w->fdata) + 40);
-+ strcpy(w->whname, AUFS_WH_DR_INFO_PFX);
++ strscpy(w->whname, AUFS_WH_DR_INFO_PFX, sizeof(AUFS_WH_DR_INFO_PFX));
+ w->infoname = w->whname + sizeof(AUFS_WH_DR_INFO_PFX) - 1;
+ w->infonamelen = sizeof(w->whname) - sizeof(AUFS_WH_DR_INFO_PFX);
+ w->btgt = btgt;
@@ -11428,8 +11480,7 @@ index 000000000000..df8a89c970e9
+ unlocked = 0;
+ h_dir = d_inode(h_ppath->dentry);
+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
-+ infopath.dentry = vfsub_lookup_one_len(whname, h_ppath->dentry,
-+ whnamelen);
++ infopath.dentry = vfsub_lookup_one_len(whname, h_ppath, whnamelen);
+ if (IS_ERR(infopath.dentry)) {
+ drinfo = (void *)infopath.dentry;
+ goto out;
@@ -11741,15 +11792,15 @@ index 000000000000..df8a89c970e9
+}
diff --git a/fs/aufs/dirren.h b/fs/aufs/dirren.h
new file mode 100644
-index 000000000000..a986736462c3
+index 000000000000..d2d57d95a77e
--- /dev/null
+++ b/fs/aufs/dirren.h
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2017-2019 Junjiro R. Okajima
++ * Copyright (C) 2017-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -11887,15 +11938,15 @@ index 000000000000..a986736462c3
+#endif /* __AUFS_DIRREN_H__ */
diff --git a/fs/aufs/dynop.c b/fs/aufs/dynop.c
new file mode 100644
-index 000000000000..ed79f8255a8f
+index 000000000000..54fd16ecb6d3
--- /dev/null
+++ b/fs/aufs/dynop.c
-@@ -0,0 +1,367 @@
+@@ -0,0 +1,366 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2010-2019 Junjiro R. Okajima
++ * Copyright (C) 2010-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -12069,27 +12120,26 @@ index 000000000000..ed79f8255a8f
+ AuDbg("%s\n", au_sbtype(h_sb));
+
+ DySetAop(writepage);
-+ DySetAopForce(readpage); /* force */
++ DySetAopForce(read_folio); /* force */
+ DySetAop(writepages);
-+ DySetAop(set_page_dirty);
-+ DySetAop(readpages);
++ DySetAop(dirty_folio);
++ DySetAop(invalidate_folio);
++ DySetAop(readahead);
+ DySetAop(write_begin);
+ DySetAop(write_end);
+ DySetAop(bmap);
-+ DySetAop(invalidatepage);
-+ DySetAop(releasepage);
-+ DySetAop(freepage);
++ DySetAop(release_folio);
++ DySetAop(free_folio);
+ /* this one will be changed according to an aufs mount option */
+ DySetAop(direct_IO);
-+ DySetAop(migratepage);
-+ DySetAop(isolate_page);
-+ DySetAop(putback_page);
-+ DySetAop(launder_page);
++ DySetAop(migrate_folio);
++ DySetAop(launder_folio);
+ DySetAop(is_partially_uptodate);
+ DySetAop(is_dirty_writeback);
+ DySetAop(error_remove_page);
+ DySetAop(swap_activate);
+ DySetAop(swap_deactivate);
++ DySetAop(swap_rw);
+
+ DyDbgSize(cnt, *h_aop);
+}
@@ -12260,15 +12310,15 @@ index 000000000000..ed79f8255a8f
+}
diff --git a/fs/aufs/dynop.h b/fs/aufs/dynop.h
new file mode 100644
-index 000000000000..5d0b36559425
+index 000000000000..60d89364b676
--- /dev/null
+++ b/fs/aufs/dynop.h
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2010-2019 Junjiro R. Okajima
++ * Copyright (C) 2010-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -12343,15 +12393,15 @@ index 000000000000..5d0b36559425
+#endif /* __AUFS_DYNOP_H__ */
diff --git a/fs/aufs/export.c b/fs/aufs/export.c
new file mode 100644
-index 000000000000..1da2ca0a969b
+index 000000000000..4c639e5d40f6
--- /dev/null
+++ b/fs/aufs/export.c
-@@ -0,0 +1,838 @@
+@@ -0,0 +1,830 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -12371,7 +12421,6 @@ index 000000000000..1da2ca0a969b
+
+#include <linux/exportfs.h>
+#include <linux/fs_struct.h>
-+#include <linux/namei.h>
+#include <linux/nsproxy.h>
+#include <linux/random.h>
+#include <linux/writeback.h>
@@ -12470,8 +12519,7 @@ index 000000000000..1da2ca0a969b
+ pos = inode->i_ino;
+ pos *= sizeof(igen);
+ igen = inode->i_generation + 1;
-+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
-+ sizeof(igen), &pos);
++ sz = xino_fwrite(sbinfo->si_xigen, &igen, sizeof(igen), &pos);
+ if (sz == sizeof(igen))
+ return; /* success */
+
@@ -12513,10 +12561,10 @@ index 000000000000..1da2ca0a969b
+ if (vfsub_f_size_read(file)
+ < pos + sizeof(inode->i_generation)) {
+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
-+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
++ sz = xino_fwrite(file, &inode->i_generation,
+ sizeof(inode->i_generation), &pos);
+ } else
-+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
++ sz = xino_fread(file, &inode->i_generation,
+ sizeof(inode->i_generation), &pos);
+ if (sz == sizeof(inode->i_generation))
+ goto out; /* success */
@@ -12697,7 +12745,7 @@ index 000000000000..1da2ca0a969b
+ int namelen;
+};
+
-+static int
++static bool
+find_name_by_ino(struct dir_context *ctx, const char *name, int namelen,
+ loff_t offset, u64 ino, unsigned int d_type)
+{
@@ -12706,12 +12754,12 @@ index 000000000000..1da2ca0a969b
+
+ a->called++;
+ if (a->ino != ino)
-+ return 0;
++ return true;
+
+ memcpy(a->name, name, namelen);
+ a->namelen = namelen;
+ a->found = 1;
-+ return 1;
++ return false;
+}
+
+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
@@ -12756,7 +12804,7 @@ index 000000000000..1da2ca0a969b
+
+ /* do not call vfsub_lkup_one() */
+ dir = d_inode(parent);
-+ dentry = vfsub_lookup_one_len_unlocked(arg.name, parent, arg.namelen);
++ dentry = vfsub_lookup_one_len_unlocked(arg.name, path, arg.namelen);
+ AuTraceErrPtr(dentry);
+ if (IS_ERR(dentry))
+ goto out_name;
@@ -13144,14 +13192,8 @@ index 000000000000..1da2ca0a969b
+ f = h_inode->i_sb->s_export_op->commit_metadata;
+ if (f)
+ err = f(h_inode);
-+ else {
-+ struct writeback_control wbc = {
-+ .sync_mode = WB_SYNC_ALL,
-+ .nr_to_write = 0 /* metadata only */
-+ };
-+
-+ err = sync_inode(h_inode, &wbc);
-+ }
++ else
++ err = sync_inode_metadata(h_inode, /*wait*/1);
+
+ au_cpup_attr_timesizes(inode);
+ ii_write_unlock(inode);
@@ -13187,15 +13229,15 @@ index 000000000000..1da2ca0a969b
+}
diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c
new file mode 100644
-index 000000000000..5254b5cd3942
+index 000000000000..320ad8a9334d
--- /dev/null
+++ b/fs/aufs/f_op.c
-@@ -0,0 +1,819 @@
+@@ -0,0 +1,771 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -13254,12 +13296,17 @@ index 000000000000..5254b5cd3942
+ /* br ref is already inc-ed */
+ }
+
-+ if ((flags & __O_TMPFILE)
-+ && !(flags & O_EXCL)) {
-+ h_inode = file_inode(h_file);
-+ spin_lock(&h_inode->i_lock);
-+ h_inode->i_state |= I_LINKABLE;
-+ spin_unlock(&h_inode->i_lock);
++ if (flags & __O_TMPFILE) {
++ AuDebugOn(!h_file);
++ AuDebugOn(h_file != au_di(dentry)->di_htmpfile);
++ au_di(dentry)->di_htmpfile = NULL;
++
++ if (!(flags & O_EXCL)) {
++ h_inode = file_inode(h_file);
++ spin_lock(&h_inode->i_lock);
++ h_inode->i_state |= I_LINKABLE;
++ spin_unlock(&h_inode->i_lock);
++ }
+ }
+ au_set_fbtop(file, bindex);
+ au_set_h_fptr(file, bindex, h_file);
@@ -13411,6 +13458,7 @@ index 000000000000..5254b5cd3942
+ if (do_ready)
+ au_unpin(&pin);
+ di_read_unlock(dentry, /*flags*/0);
++ vfsub_file_start_write(h_file);
+
+out_fi:
+ fi_write_unlock(file);
@@ -13423,6 +13471,7 @@ index 000000000000..5254b5cd3942
+{
+ struct inode *h_inode;
+
++ vfsub_file_end_write(h_file);
+ au_cpup_attr_timesizes(inode);
+ AuDebugOn(au_ibtop(inode) != wpre->btop);
+ h_inode = file_inode(h_file);
@@ -13435,34 +13484,6 @@ index 000000000000..5254b5cd3942
+ fput(h_file);
+}
+
-+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
-+ loff_t *ppos)
-+{
-+ ssize_t err;
-+ struct inode *inode;
-+ struct file *h_file;
-+ struct super_block *sb;
-+
-+ inode = file_inode(file);
-+ sb = inode->i_sb;
-+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
-+
-+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
-+ err = PTR_ERR(h_file);
-+ if (IS_ERR(h_file))
-+ goto out;
-+
-+ /* filedata may be obsoleted by concurrent copyup, but no problem */
-+ err = vfsub_read_u(h_file, buf, count, ppos);
-+ /* todo: necessary? */
-+ /* file->f_ra = h_file->f_ra; */
-+ au_read_post(inode, h_file);
-+
-+out:
-+ si_read_unlock(sb);
-+ return err;
-+}
-+
+/*
+ * todo: very ugly
+ * it locks both of i_mutex and si_rwsem for read in safe.
@@ -13485,33 +13506,6 @@ index 000000000000..5254b5cd3942
+ }
+}
+
-+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
-+ size_t count, loff_t *ppos)
-+{
-+ ssize_t err;
-+ struct au_write_pre wpre;
-+ struct inode *inode;
-+ struct file *h_file;
-+ char __user *buf = (char __user *)ubuf;
-+
-+ inode = file_inode(file);
-+ au_mtx_and_read_lock(inode);
-+
-+ wpre.lsc = 0;
-+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
-+ err = PTR_ERR(h_file);
-+ if (IS_ERR(h_file))
-+ goto out;
-+
-+ err = vfsub_write_u(h_file, buf, count, ppos);
-+ au_write_post(inode, h_file, &wpre, err);
-+
-+out:
-+ si_read_unlock(inode->i_sb);
-+ inode_unlock(inode);
-+ return err;
-+}
-+
+static ssize_t au_do_iter(struct file *h_file, int rw, struct kiocb *kio,
+ struct iov_iter *iov_iter)
+{
@@ -13523,7 +13517,7 @@ index 000000000000..5254b5cd3942
+ if (unlikely(err))
+ goto out;
+
-+ err = -ENOSYS;
++ err = -ENOSYS; /* the branch doesn't have its ->(read|write)_iter() */
+ iter = NULL;
+ if (rw == MAY_READ)
+ iter = h_file->f_op->read_iter;
@@ -13607,6 +13601,15 @@ index 000000000000..5254b5cd3942
+ return err;
+}
+
++/*
++ * We may be able to remove aufs_splice_{read,write}() since almost all FSes
++ * don't have their own .splice_{read,write} implimentations, and they use
++ * generic_file_splice_read() and iter_file_splice_write() who can act like the
++ * simple converters to f_op->iter_read() and ->iter_write().
++ * But we keep our own implementations because some non-mainlined FSes may have
++ * their own .splice_{read,write} implimentations and aufs doesn't want to take
++ * away an opportunity to co-work with aufs from them.
++ */
+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t len,
+ unsigned int flags)
@@ -13625,7 +13628,7 @@ index 000000000000..5254b5cd3942
+ if (IS_ERR(h_file))
+ goto out;
+
-+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
++ err = vfsub_splice_read(h_file, ppos, pipe, len, flags);
+ /* todo: necessary? */
+ /* file->f_ra = h_file->f_ra; */
+ au_read_post(inode, h_file);
@@ -13682,6 +13685,10 @@ index 000000000000..5254b5cd3942
+ lockdep_off();
+ err = vfs_fallocate(h_file, mode, offset, len);
+ lockdep_on();
++ /*
++ * we don't need to call file_modifed() here since au_write_post()
++ * is equivalent and copies-up all timestamps and permission bits.
++ */
+ au_write_post(inode, h_file, &wpre, /*written*/1);
+
+out:
@@ -13966,23 +13973,11 @@ index 000000000000..5254b5cd3942
+
+/* ---------------------------------------------------------------------- */
+
-+/* no one supports this operation, currently */
-+#if 0
-+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
-+ size_t len, loff_t *pos, int more)
-+{
-+}
-+#endif
-+
-+/* ---------------------------------------------------------------------- */
-+
+const struct file_operations aufs_file_fop = {
+ .owner = THIS_MODULE,
+
+ .llseek = default_llseek,
+
-+ .read = aufs_read,
-+ .write = aufs_write,
+ .read_iter = aufs_read_iter,
+ .write_iter = aufs_write_iter,
+
@@ -13999,11 +13994,10 @@ index 000000000000..5254b5cd3942
+ .release = aufs_release_nondir,
+ .fsync = aufs_fsync_nondir,
+ .fasync = aufs_fasync,
-+ /* .sendpage = aufs_sendpage, */
+ .setfl = aufs_setfl,
+ .splice_write = aufs_splice_write,
+ .splice_read = aufs_splice_read,
-+#if 0
++#if 0 /* reserved for future use */
+ .aio_splice_write = aufs_aio_splice_write,
+ .aio_splice_read = aufs_aio_splice_read,
+#endif
@@ -14012,15 +14006,15 @@ index 000000000000..5254b5cd3942
+};
diff --git a/fs/aufs/fhsm.c b/fs/aufs/fhsm.c
new file mode 100644
-index 000000000000..f86a4c24fb26
+index 000000000000..91262fbbbfae
--- /dev/null
+++ b/fs/aufs/fhsm.c
-@@ -0,0 +1,427 @@
+@@ -0,0 +1,426 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2011-2019 Junjiro R. Okajima
++ * Copyright (C) 2011-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -14031,8 +14025,7 @@ index 000000000000..f86a4c24fb26
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
@@ -14445,15 +14438,15 @@ index 000000000000..f86a4c24fb26
+}
diff --git a/fs/aufs/file.c b/fs/aufs/file.c
new file mode 100644
-index 000000000000..dbb33855d226
+index 000000000000..76ad444328db
--- /dev/null
+++ b/fs/aufs/file.c
-@@ -0,0 +1,863 @@
+@@ -0,0 +1,865 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -14537,6 +14530,11 @@ index 000000000000..dbb33855d226
+ au_lcnt_inc(&br->br_nfiles);
+ h_path.dentry = h_dentry;
+ h_path.mnt = au_br_mnt(br);
++ /*
++ * vfs::backing_file_open() looks promising since it can get rid of
++ * mm::vm_prfile approach from my mind.
++ * but I keep current approach for a while.
++ */
+ h_file = vfsub_dentry_open(&h_path, flags);
+ if (IS_ERR(h_file))
+ goto out_br;
@@ -14695,18 +14693,20 @@ index 000000000000..dbb33855d226
+ AuDebugOn(IS_ERR_OR_NULL(dentry));
+ di_write_lock_child(dentry);
+ err = au_cmoo(dentry);
-+ di_downgrade_lock(dentry, AuLock_IR);
+ if (!err) {
-+ if (!aopen)
-+ err = args->open(file, vfsub_file_flags(file), NULL);
-+ else {
++ if (!aopen) {
++ err = args->open(file, vfsub_file_flags(file),
++ au_di(dentry)->di_htmpfile);
++ di_write_unlock(dentry);
++ } else {
++ di_downgrade_lock(dentry, AuLock_IR);
+ lockdep_off();
+ err = args->open(file, vfsub_file_flags(file),
+ args->h_file);
+ lockdep_on();
++ di_read_unlock(dentry, AuLock_IR);
+ }
+ }
-+ di_read_unlock(dentry, AuLock_IR);
+
+ finfo = au_fi(file);
+ if (!err) {
@@ -15229,9 +15229,9 @@ index 000000000000..dbb33855d226
+
+/* cf. aufs_nopage() */
+/* for madvise(2) */
-+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
++static int aufs_read_folio(struct file *file __maybe_unused, struct folio *folio)
+{
-+ unlock_page(page);
++ folio_unlock(folio);
+ return 0;
+}
+
@@ -15242,7 +15242,7 @@ index 000000000000..dbb33855d226
+/* they will never be called. */
+#ifdef CONFIG_AUFS_DEBUG
+static int aufs_write_begin(struct file *file, struct address_space *mapping,
-+ loff_t pos, unsigned len, unsigned flags,
++ loff_t pos, unsigned len,
+ struct page **pagep, void **fsdata)
+{ AuUnsupport(); return 0; }
+static int aufs_write_end(struct file *file, struct address_space *mapping,
@@ -15252,29 +15252,23 @@ index 000000000000..dbb33855d226
+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
+{ AuUnsupport(); return 0; }
+
-+static int aufs_set_page_dirty(struct page *page)
-+{ AuUnsupport(); return 0; }
-+static void aufs_invalidatepage(struct page *page, unsigned int offset,
-+ unsigned int length)
++static bool aufs_dirty_folio(struct address_space *mapping, struct folio *folio)
++{ AuUnsupport(); return true; }
++static void aufs_invalidate_folio(struct folio *folio, size_t offset, size_t len)
+{ AuUnsupport(); }
-+static int aufs_releasepage(struct page *page, gfp_t gfp)
-+{ AuUnsupport(); return 0; }
++static bool aufs_release_folio(struct folio *folio, gfp_t gfp)
++{ AuUnsupport(); return true; }
+#if 0 /* called by memory compaction regardless file */
-+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
-+ struct page *page, enum migrate_mode mode)
++static int aufs_migrate_folio(struct address_space *mapping, struct folio *dst,
++ struct folio *src, enum migrate_mode mode)
+{ AuUnsupport(); return 0; }
+#endif
-+static bool aufs_isolate_page(struct page *page, isolate_mode_t mode)
-+{ AuUnsupport(); return true; }
-+static void aufs_putback_page(struct page *page)
-+{ AuUnsupport(); }
-+static int aufs_launder_page(struct page *page)
-+{ AuUnsupport(); return 0; }
-+static int aufs_is_partially_uptodate(struct page *page,
-+ unsigned long from,
-+ unsigned long count)
++static int aufs_launder_folio(struct folio *folio)
+{ AuUnsupport(); return 0; }
-+static void aufs_is_dirty_writeback(struct page *page, bool *dirty,
++static bool aufs_is_partially_uptodate(struct folio *folio, size_t from,
++ size_t count)
++{ AuUnsupport(); return true; }
++static void aufs_is_dirty_writeback(struct folio *folio, bool *dirty,
+ bool *writeback)
+{ AuUnsupport(); }
+static int aufs_error_remove_page(struct address_space *mapping,
@@ -15285,44 +15279,45 @@ index 000000000000..dbb33855d226
+{ AuUnsupport(); return 0; }
+static void aufs_swap_deactivate(struct file *file)
+{ AuUnsupport(); }
++static int aufs_swap_rw(struct kiocb *iocb, struct iov_iter *iter)
++{ AuUnsupport(); return 0; }
+#endif /* CONFIG_AUFS_DEBUG */
+
+const struct address_space_operations aufs_aop = {
-+ .readpage = aufs_readpage,
++ .read_folio = aufs_read_folio,
+ .direct_IO = aufs_direct_IO,
+#ifdef CONFIG_AUFS_DEBUG
+ .writepage = aufs_writepage,
+ /* no writepages, because of writepage */
-+ .set_page_dirty = aufs_set_page_dirty,
++ .dirty_folio = aufs_dirty_folio,
+ /* no readpages, because of readpage */
+ .write_begin = aufs_write_begin,
+ .write_end = aufs_write_end,
+ /* no bmap, no block device */
-+ .invalidatepage = aufs_invalidatepage,
-+ .releasepage = aufs_releasepage,
++ .invalidate_folio = aufs_invalidate_folio,
++ .release_folio = aufs_release_folio,
+ /* is fallback_migrate_page ok? */
-+ /* .migratepage = aufs_migratepage, */
-+ .isolate_page = aufs_isolate_page,
-+ .putback_page = aufs_putback_page,
-+ .launder_page = aufs_launder_page,
++ /* .migrate_folio = aufs_migrate_folio, */
++ .launder_folio = aufs_launder_folio,
+ .is_partially_uptodate = aufs_is_partially_uptodate,
+ .is_dirty_writeback = aufs_is_dirty_writeback,
+ .error_remove_page = aufs_error_remove_page,
+ .swap_activate = aufs_swap_activate,
-+ .swap_deactivate = aufs_swap_deactivate
++ .swap_deactivate = aufs_swap_deactivate,
++ .swap_rw = aufs_swap_rw
+#endif /* CONFIG_AUFS_DEBUG */
+};
diff --git a/fs/aufs/file.h b/fs/aufs/file.h
new file mode 100644
-index 000000000000..c679a19df528
+index 000000000000..b16f31e364a8
--- /dev/null
+++ b/fs/aufs/file.h
@@ -0,0 +1,342 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -15662,15 +15657,15 @@ index 000000000000..c679a19df528
+#endif /* __AUFS_FILE_H__ */
diff --git a/fs/aufs/finfo.c b/fs/aufs/finfo.c
new file mode 100644
-index 000000000000..448c5e9cd85d
+index 000000000000..7da7b286c006
--- /dev/null
+++ b/fs/aufs/finfo.c
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -15815,17 +15810,1265 @@ index 000000000000..448c5e9cd85d
+out:
+ return err;
+}
+diff --git a/fs/aufs/fsctx.c b/fs/aufs/fsctx.c
+new file mode 100644
+index 000000000000..e14fe4d381c5
+--- /dev/null
++++ b/fs/aufs/fsctx.c
+@@ -0,0 +1,1242 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (C) 2022 Junjiro R. Okajima
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++
++/*
++ * fs context, aka new mount api
++ */
++
++#include <linux/fs_context.h>
++#include "aufs.h"
++
++struct au_fsctx_opts {
++ aufs_bindex_t bindex;
++ unsigned char skipped;
++ struct au_opt *opt, *opt_tail;
++ struct super_block *sb;
++ struct au_sbinfo *sbinfo;
++ struct au_opts opts;
++};
++
++/* stop extra interpretation of errno in mount(8), and strange error messages */
++static int cvt_err(int err)
++{
++ AuTraceErr(err);
++
++ switch (err) {
++ case -ENOENT:
++ case -ENOTDIR:
++ case -EEXIST:
++ case -EIO:
++ err = -EINVAL;
++ }
++ return err;
++}
++
++static int au_fsctx_reconfigure(struct fs_context *fc)
++{
++ int err, do_dx;
++ unsigned int mntflags;
++ struct dentry *root;
++ struct super_block *sb;
++ struct inode *inode;
++ struct au_fsctx_opts *a = fc->fs_private;
++
++ AuDbg("fc %p\n", fc);
++
++ root = fc->root;
++ sb = root->d_sb;
++ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
++ if (!err) {
++ di_write_lock_child(root);
++ err = au_opts_verify(sb, fc->sb_flags, /*pending*/0);
++ aufs_write_unlock(root);
++ }
++
++ inode = d_inode(root);
++ inode_lock(inode);
++ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
++ if (unlikely(err))
++ goto out;
++ di_write_lock_child(root);
++
++ /* au_opts_remount() may return an error */
++ err = au_opts_remount(sb, &a->opts);
++
++ if (au_ftest_opts(a->opts.flags, REFRESH))
++ au_remount_refresh(sb, au_ftest_opts(a->opts.flags,
++ REFRESH_IDOP));
++
++ if (au_ftest_opts(a->opts.flags, REFRESH_DYAOP)) {
++ mntflags = au_mntflags(sb);
++ do_dx = !!au_opt_test(mntflags, DIO);
++ au_dy_arefresh(do_dx);
++ }
++
++ au_fhsm_wrote_all(sb, /*force*/1); /* ?? */
++ aufs_write_unlock(root);
++
++out:
++ inode_unlock(inode);
++ err = cvt_err(err);
++ AuTraceErr(err);
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static int au_fsctx_fill_super(struct super_block *sb, struct fs_context *fc)
++{
++ int err;
++ struct au_fsctx_opts *a = fc->fs_private;
++ struct au_sbinfo *sbinfo = a->sbinfo;
++ struct dentry *root;
++ struct inode *inode;
++
++ sbinfo->si_sb = sb;
++ sb->s_fs_info = sbinfo;
++ kobject_get(&sbinfo->si_kobj);
++
++ __si_write_lock(sb);
++ si_pid_set(sb);
++ au_sbilist_add(sb);
++
++ /* all timestamps always follow the ones on the branch */
++ sb->s_flags |= SB_NOATIME | SB_NODIRATIME;
++ sb->s_flags |= SB_I_VERSION; /* do we really need this? */
++ sb->s_op = &aufs_sop;
++ sb->s_d_op = &aufs_dop;
++ sb->s_magic = AUFS_SUPER_MAGIC;
++ sb->s_maxbytes = 0;
++ sb->s_stack_depth = 1;
++ au_export_init(sb);
++ au_xattr_init(sb);
++
++ err = au_alloc_root(sb);
++ if (unlikely(err)) {
++ si_write_unlock(sb);
++ goto out;
++ }
++ root = sb->s_root;
++ inode = d_inode(root);
++ ii_write_lock_parent(inode);
++ aufs_write_unlock(root);
++
++ /* lock vfs_inode first, then aufs. */
++ inode_lock(inode);
++ aufs_write_lock(root);
++ err = au_opts_mount(sb, &a->opts);
++ AuTraceErr(err);
++ if (!err && au_ftest_si(sbinfo, NO_DREVAL)) {
++ sb->s_d_op = &aufs_dop_noreval;
++ /* infofc(fc, "%ps", sb->s_d_op); */
++ pr_info("%ps\n", sb->s_d_op);
++ au_refresh_dop(root, /*force_reval*/0);
++ sbinfo->si_iop_array = aufs_iop_nogetattr;
++ au_refresh_iop(inode, /*force_getattr*/0);
++ }
++ aufs_write_unlock(root);
++ inode_unlock(inode);
++ if (!err)
++ goto out; /* success */
++
++ dput(root);
++ sb->s_root = NULL;
++
++out:
++ if (unlikely(err))
++ kobject_put(&sbinfo->si_kobj);
++ AuTraceErr(err);
++ err = cvt_err(err);
++ AuTraceErr(err);
++ return err;
++}
++
++static int au_fsctx_get_tree(struct fs_context *fc)
++{
++ int err;
++
++ AuDbg("fc %p\n", fc);
++ err = get_tree_nodev(fc, au_fsctx_fill_super);
++
++ AuTraceErr(err);
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void au_fsctx_dump(struct au_opts *opts)
++{
++#ifdef CONFIG_AUFS_DEBUG
++ /* reduce stack space */
++ union {
++ struct au_opt_add *add;
++ struct au_opt_del *del;
++ struct au_opt_mod *mod;
++ struct au_opt_xino *xino;
++ struct au_opt_xino_itrunc *xino_itrunc;
++ struct au_opt_wbr_create *create;
++ } u;
++ struct au_opt *opt;
++
++ opt = opts->opt;
++ while (opt->type != Opt_tail) {
++ switch (opt->type) {
++ case Opt_add:
++ u.add = &opt->add;
++ AuDbg("add {b%d, %s, 0x%x, %p}\n",
++ u.add->bindex, u.add->pathname, u.add->perm,
++ u.add->path.dentry);
++ break;
++ case Opt_del:
++ fallthrough;
++ case Opt_idel:
++ u.del = &opt->del;
++ AuDbg("del {%s, %p}\n",
++ u.del->pathname, u.del->h_path.dentry);
++ break;
++ case Opt_mod:
++ fallthrough;
++ case Opt_imod:
++ u.mod = &opt->mod;
++ AuDbg("mod {%s, 0x%x, %p}\n",
++ u.mod->path, u.mod->perm, u.mod->h_root);
++ break;
++ case Opt_append:
++ u.add = &opt->add;
++ AuDbg("append {b%d, %s, 0x%x, %p}\n",
++ u.add->bindex, u.add->pathname, u.add->perm,
++ u.add->path.dentry);
++ break;
++ case Opt_prepend:
++ u.add = &opt->add;
++ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
++ u.add->bindex, u.add->pathname, u.add->perm,
++ u.add->path.dentry);
++ break;
++
++ case Opt_dirwh:
++ AuDbg("dirwh %d\n", opt->dirwh);
++ break;
++ case Opt_rdcache:
++ AuDbg("rdcache %d\n", opt->rdcache);
++ break;
++ case Opt_rdblk:
++ AuDbg("rdblk %d\n", opt->rdblk);
++ break;
++ case Opt_rdhash:
++ AuDbg("rdhash %u\n", opt->rdhash);
++ break;
++
++ case Opt_xino:
++ u.xino = &opt->xino;
++ AuDbg("xino {%s %pD}\n", u.xino->path, u.xino->file);
++ break;
++
++#define au_fsctx_TF(name) \
++ case Opt_##name: \
++ if (opt->tf) \
++ AuLabel(name); \
++ else \
++ AuLabel(no##name); \
++ break;
++
++ /* simple true/false flag */
++ au_fsctx_TF(trunc_xino);
++ au_fsctx_TF(trunc_xib);
++ au_fsctx_TF(dirperm1);
++ au_fsctx_TF(plink);
++ au_fsctx_TF(shwh);
++ au_fsctx_TF(dio);
++ au_fsctx_TF(warn_perm);
++ au_fsctx_TF(verbose);
++ au_fsctx_TF(sum);
++ au_fsctx_TF(dirren);
++ au_fsctx_TF(acl);
++#undef au_fsctx_TF
++
++ case Opt_trunc_xino_path:
++ fallthrough;
++ case Opt_itrunc_xino:
++ u.xino_itrunc = &opt->xino_itrunc;
++ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
++ break;
++ case Opt_noxino:
++ AuLabel(noxino);
++ break;
++
++ case Opt_list_plink:
++ AuLabel(list_plink);
++ break;
++ case Opt_udba:
++ AuDbg("udba %d, %s\n",
++ opt->udba, au_optstr_udba(opt->udba));
++ break;
++ case Opt_diropq_a:
++ AuLabel(diropq_a);
++ break;
++ case Opt_diropq_w:
++ AuLabel(diropq_w);
++ break;
++ case Opt_wsum:
++ AuLabel(wsum);
++ break;
++ case Opt_wbr_create:
++ u.create = &opt->wbr_create;
++ AuDbg("create %d, %s\n", u.create->wbr_create,
++ au_optstr_wbr_create(u.create->wbr_create));
++ switch (u.create->wbr_create) {
++ case AuWbrCreate_MFSV:
++ fallthrough;
++ case AuWbrCreate_PMFSV:
++ AuDbg("%d sec\n", u.create->mfs_second);
++ break;
++ case AuWbrCreate_MFSRR:
++ fallthrough;
++ case AuWbrCreate_TDMFS:
++ AuDbg("%llu watermark\n",
++ u.create->mfsrr_watermark);
++ break;
++ case AuWbrCreate_MFSRRV:
++ fallthrough;
++ case AuWbrCreate_TDMFSV:
++ fallthrough;
++ case AuWbrCreate_PMFSRRV:
++ AuDbg("%llu watermark, %d sec\n",
++ u.create->mfsrr_watermark,
++ u.create->mfs_second);
++ break;
++ }
++ break;
++ case Opt_wbr_copyup:
++ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
++ au_optstr_wbr_copyup(opt->wbr_copyup));
++ break;
++ case Opt_fhsm_sec:
++ AuDbg("fhsm_sec %u\n", opt->fhsm_second);
++ break;
++
++ default:
++ AuDbg("type %d\n", opt->type);
++ BUG();
++ }
++ opt++;
++ }
++#endif
++}
++
++/* ---------------------------------------------------------------------- */
++
++/*
++ * For conditionally compiled mount options.
++ * Instead of fsparam_flag_no(), use this macro to distinguish ignore_silent.
++ */
++#define au_ignore_flag(name, action) \
++ fsparam_flag(name, action), \
++ fsparam_flag("no" name, Opt_ignore_silent)
++
++const struct fs_parameter_spec aufs_fsctx_paramspec[] = {
++ fsparam_string("br", Opt_br),
++
++ /* "add=%d:%s" or "ins=%d:%s" */
++ fsparam_string("add", Opt_add),
++ fsparam_string("ins", Opt_add),
++ fsparam_path("append", Opt_append),
++ fsparam_path("prepend", Opt_prepend),
++
++ fsparam_path("del", Opt_del),
++ /* fsparam_s32("idel", Opt_idel), */
++ fsparam_path("mod", Opt_mod),
++ /* fsparam_string("imod", Opt_imod), */
++
++ fsparam_s32("dirwh", Opt_dirwh),
++
++ fsparam_path("xino", Opt_xino),
++ fsparam_flag("noxino", Opt_noxino),
++ fsparam_flag_no("trunc_xino", Opt_trunc_xino),
++ /* "trunc_xino_v=%d:%d" */
++ /* fsparam_string("trunc_xino_v", Opt_trunc_xino_v), */
++ fsparam_path("trunc_xino", Opt_trunc_xino_path),
++ fsparam_s32("itrunc_xino", Opt_itrunc_xino),
++ /* fsparam_path("zxino", Opt_zxino), */
++ fsparam_flag_no("trunc_xib", Opt_trunc_xib),
++
++#ifdef CONFIG_PROC_FS
++ fsparam_flag_no("plink", Opt_plink),
++#else
++ au_ignore_flag("plink", Opt_ignore),
++#endif
++
++#ifdef CONFIG_AUFS_DEBUG
++ fsparam_flag("list_plink", Opt_list_plink),
++#endif
++
++ fsparam_string("udba", Opt_udba),
++
++ fsparam_flag_no("dio", Opt_dio),
++
++#ifdef CONFIG_AUFS_DIRREN
++ fsparam_flag_no("dirren", Opt_dirren),
++#else
++ au_ignore_flag("dirren", Opt_ignore),
++#endif
++
++#ifdef CONFIG_AUFS_FHSM
++ fsparam_s32("fhsm_sec", Opt_fhsm_sec),
++#else
++ fsparam_s32("fhsm_sec", Opt_ignore),
++#endif
++
++ /* always | a | whiteouted | w */
++ fsparam_string("diropq", Opt_diropq),
++
++ fsparam_flag_no("warn_perm", Opt_warn_perm),
++
++#ifdef CONFIG_AUFS_SHWH
++ fsparam_flag_no("shwh", Opt_shwh),
++#else
++ au_ignore_flag("shwh", Opt_err),
++#endif
++
++ fsparam_flag_no("dirperm1", Opt_dirperm1),
++
++ fsparam_flag_no("verbose", Opt_verbose),
++ fsparam_flag("v", Opt_verbose),
++ fsparam_flag("quiet", Opt_noverbose),
++ fsparam_flag("q", Opt_noverbose),
++ /* user-space may handle this */
++ fsparam_flag("silent", Opt_noverbose),
++
++ fsparam_flag_no("sum", Opt_sum),
++ fsparam_flag("wsum", Opt_wsum),
++
++ fsparam_s32("rdcache", Opt_rdcache),
++ /* "def" or s32 */
++ fsparam_string("rdblk", Opt_rdblk),
++ /* "def" or s32 */
++ fsparam_string("rdhash", Opt_rdhash),
++
++ fsparam_string("create", Opt_wbr_create),
++ fsparam_string("create_policy", Opt_wbr_create),
++ fsparam_string("cpup", Opt_wbr_copyup),
++ fsparam_string("copyup", Opt_wbr_copyup),
++ fsparam_string("copyup_policy", Opt_wbr_copyup),
++
++ /* generic VFS flag */
++#ifdef CONFIG_FS_POSIX_ACL
++ fsparam_flag_no("acl", Opt_acl),
++#else
++ au_ignore_flag("acl", Opt_ignore),
++#endif
++
++ /* internal use for the scripts */
++ fsparam_string("si", Opt_ignore_silent),
++
++ /* obsoleted, keep them temporary */
++ fsparam_flag("nodlgt", Opt_ignore_silent),
++ fsparam_flag("clean_plink", Opt_ignore),
++ fsparam_string("dirs", Opt_br),
++ fsparam_u32("debug", Opt_ignore),
++ /* "whiteout" or "all" */
++ fsparam_string("delete", Opt_ignore),
++ fsparam_string("imap", Opt_ignore),
++
++ /* temporary workaround, due to old mount(8)? */
++ fsparam_flag("relatime", Opt_ignore_silent),
++
++ {}
++};
++
++static int au_fsctx_parse_do_add(struct fs_context *fc, struct au_opt *opt,
++ char *brspec, size_t speclen,
++ aufs_bindex_t bindex)
++{
++ int err;
++ char *p;
++
++ AuDbg("brspec %s\n", brspec);
++
++ err = -ENOMEM;
++ if (!speclen)
++ speclen = strlen(brspec);
++ /* will be freed by au_fsctx_free() */
++ p = kmemdup_nul(brspec, speclen, GFP_NOFS);
++ if (unlikely(!p)) {
++ errorfc(fc, "failed in %s", brspec);
++ goto out;
++ }
++ err = au_opt_add(opt, p, fc->sb_flags, bindex);
++
++out:
++ AuTraceErr(err);
++ return err;
++}
++
++static int au_fsctx_parse_br(struct fs_context *fc, char *brspec)
++{
++ int err;
++ char *p;
++ struct au_fsctx_opts *a = fc->fs_private;
++ struct au_opt *opt = a->opt;
++ aufs_bindex_t bindex = a->bindex;
++
++ AuDbg("brspec %s\n", brspec);
++
++ err = -EINVAL;
++ while ((p = strsep(&brspec, ":")) && *p) {
++ err = au_fsctx_parse_do_add(fc, opt, p, /*len*/0, bindex);
++ AuTraceErr(err);
++ if (unlikely(err))
++ break;
++ bindex++;
++ opt++;
++ if (unlikely(opt > a->opt_tail)) {
++ err = -E2BIG;
++ bindex--;
++ opt--;
++ break;
++ }
++ opt->type = Opt_tail;
++ a->skipped = 1;
++ }
++ a->bindex = bindex;
++ a->opt = opt;
++
++ AuTraceErr(err);
++ return err;
++}
++
++static int au_fsctx_parse_add(struct fs_context *fc, char *addspec)
++{
++ int err, n;
++ char *p;
++ struct au_fsctx_opts *a = fc->fs_private;
++ struct au_opt *opt = a->opt;
++
++ err = -EINVAL;
++ p = strchr(addspec, ':');
++ if (unlikely(!p)) {
++ errorfc(fc, "bad arg in %s", addspec);
++ goto out;
++ }
++ *p++ = '\0';
++ err = kstrtoint(addspec, 0, &n);
++ if (unlikely(err)) {
++ errorfc(fc, "bad integer in %s", addspec);
++ goto out;
++ }
++ AuDbg("n %d\n", n);
++ err = au_fsctx_parse_do_add(fc, opt, p, /*len*/0, n);
++
++out:
++ AuTraceErr(err);
++ return err;
++}
++
++static int au_fsctx_parse_del(struct fs_context *fc, struct au_opt_del *del,
++ struct fs_parameter *param)
++{
++ int err;
++
++ err = -ENOMEM;
++ /* will be freed by au_fsctx_free() */
++ del->pathname = kmemdup_nul(param->string, param->size, GFP_NOFS);
++ if (unlikely(!del->pathname))
++ goto out;
++ AuDbg("del %s\n", del->pathname);
++ err = vfsub_kern_path(del->pathname, AuOpt_LkupDirFlags, &del->h_path);
++ if (unlikely(err))
++ errorfc(fc, "lookup failed %s (%d)", del->pathname, err);
++
++out:
++ AuTraceErr(err);
++ return err;
++}
++
++#if 0 /* reserved for future use */
++static int au_fsctx_parse_idel(struct fs_context *fc, struct au_opt_del *del,
++ aufs_bindex_t bindex)
++{
++ int err;
++ struct super_block *sb;
++ struct dentry *root;
++ struct au_fsctx_opts *a = fc->fs_private;
++
++ sb = a->sb;
++ AuDebugOn(!sb);
++
++ err = -EINVAL;
++ root = sb->s_root;
++ aufs_read_lock(root, AuLock_FLUSH);
++ if (bindex < 0 || au_sbbot(sb) < bindex) {
++ errorfc(fc, "out of bounds, %d", bindex);
++ goto out;
++ }
++
++ err = 0;
++ del->h_path.dentry = dget(au_h_dptr(root, bindex));
++ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
++
++out:
++ aufs_read_unlock(root, !AuLock_IR);
++ AuTraceErr(err);
++ return err;
++}
++#endif
++
++static int au_fsctx_parse_mod(struct fs_context *fc, struct au_opt_mod *mod,
++ struct fs_parameter *param)
++{
++ int err;
++ struct path path;
++ char *p;
++
++ err = -ENOMEM;
++ /* will be freed by au_fsctx_free() */
++ mod->path = kmemdup_nul(param->string, param->size, GFP_NOFS);
++ if (unlikely(!mod->path))
++ goto out;
++
++ err = -EINVAL;
++ p = strchr(mod->path, '=');
++ if (unlikely(!p)) {
++ errorfc(fc, "no permission %s", mod->path);
++ goto out;
++ }
++
++ *p++ = 0;
++ err = vfsub_kern_path(mod->path, AuOpt_LkupDirFlags, &path);
++ if (unlikely(err)) {
++ errorfc(fc, "lookup failed %s (%d)", mod->path, err);
++ goto out;
++ }
++
++ mod->perm = au_br_perm_val(p);
++ AuDbg("mod path %s, perm 0x%x, %s", mod->path, mod->perm, p);
++ mod->h_root = dget(path.dentry);
++ path_put(&path);
++
++out:
++ AuTraceErr(err);
++ return err;
++}
++
++#if 0 /* reserved for future use */
++static int au_fsctx_parse_imod(struct fs_context *fc, struct au_opt_mod *mod,
++ char *ibrspec)
++{
++ int err, n;
++ char *p;
++ struct super_block *sb;
++ struct dentry *root;
++ struct au_fsctx_opts *a = fc->fs_private;
++
++ sb = a->sb;
++ AuDebugOn(!sb);
++
++ err = -EINVAL;
++ p = strchr(ibrspec, ':');
++ if (unlikely(!p)) {
++ errorfc(fc, "no index, %s", ibrspec);
++ goto out;
++ }
++ *p++ = '\0';
++ err = kstrtoint(ibrspec, 0, &n);
++ if (unlikely(err)) {
++ errorfc(fc, "bad integer in %s", ibrspec);
++ goto out;
++ }
++ AuDbg("n %d\n", n);
++
++ root = sb->s_root;
++ aufs_read_lock(root, AuLock_FLUSH);
++ if (n < 0 || au_sbbot(sb) < n) {
++ errorfc(fc, "out of bounds, %d", bindex);
++ goto out_root;
++ }
++
++ err = 0;
++ mod->perm = au_br_perm_val(p);
++ AuDbg("mod path %s, perm 0x%x, %s\n",
++ mod->path, mod->perm, p);
++ mod->h_root = dget(au_h_dptr(root, bindex));
++
++out_root:
++ aufs_read_unlock(root, !AuLock_IR);
++out:
++ AuTraceErr(err);
++ return err;
++}
++#endif
++
++static int au_fsctx_parse_xino(struct fs_context *fc,
++ struct au_opt_xino *xino,
++ struct fs_parameter *param)
++{
++ int err;
++ struct au_fsctx_opts *a = fc->fs_private;
++
++ err = -ENOMEM;
++ /* will be freed by au_opts_free() */
++ xino->path = kmemdup_nul(param->string, param->size, GFP_NOFS);
++ if (unlikely(!xino->path))
++ goto out;
++ AuDbg("path %s\n", xino->path);
++
++ xino->file = au_xino_create(a->sb, xino->path, /*silent*/0,
++ /*wbrtop*/0);
++ err = PTR_ERR(xino->file);
++ if (IS_ERR(xino->file)) {
++ xino->file = NULL;
++ goto out;
++ }
++
++ err = 0;
++ if (unlikely(a->sb && xino->file->f_path.dentry->d_sb == a->sb)) {
++ err = -EINVAL;
++ errorfc(fc, "%s must be outside", xino->path);
++ }
++
++out:
++ AuTraceErr(err);
++ return err;
++}
++
++static
++int au_fsctx_parse_xino_itrunc_path(struct fs_context *fc,
++ struct au_opt_xino_itrunc *xino_itrunc,
++ char *pathname)
++{
++ int err;
++ aufs_bindex_t bbot, bindex;
++ struct path path;
++ struct dentry *root;
++ struct au_fsctx_opts *a = fc->fs_private;
++
++ AuDebugOn(!a->sb);
++
++ err = vfsub_kern_path(pathname, AuOpt_LkupDirFlags, &path);
++ if (unlikely(err)) {
++ errorfc(fc, "lookup failed %s (%d)", pathname, err);
++ goto out;
++ }
++
++ xino_itrunc->bindex = -1;
++ root = a->sb->s_root;
++ aufs_read_lock(root, AuLock_FLUSH);
++ bbot = au_sbbot(a->sb);
++ for (bindex = 0; bindex <= bbot; bindex++) {
++ if (au_h_dptr(root, bindex) == path.dentry) {
++ xino_itrunc->bindex = bindex;
++ break;
++ }
++ }
++ aufs_read_unlock(root, !AuLock_IR);
++ path_put(&path);
++
++ if (unlikely(xino_itrunc->bindex < 0)) {
++ err = -EINVAL;
++ errorfc(fc, "no such branch %s", pathname);
++ }
++
++out:
++ AuTraceErr(err);
++ return err;
++}
++
++static int au_fsctx_parse_xino_itrunc(struct fs_context *fc,
++ struct au_opt_xino_itrunc *xino_itrunc,
++ unsigned int bindex)
++{
++ int err;
++ aufs_bindex_t bbot;
++ struct super_block *sb;
++ struct au_fsctx_opts *a = fc->fs_private;
++
++ sb = a->sb;
++ AuDebugOn(!sb);
++
++ err = 0;
++ si_noflush_read_lock(sb);
++ bbot = au_sbbot(sb);
++ si_read_unlock(sb);
++ if (bindex <= bbot)
++ xino_itrunc->bindex = bindex;
++ else {
++ err = -EINVAL;
++ errorfc(fc, "out of bounds, %u", bindex);
++ }
++
++ AuTraceErr(err);
++ return err;
++}
++
++static int au_fsctx_parse_param(struct fs_context *fc, struct fs_parameter *param)
++{
++ int err, token;
++ struct fs_parse_result result;
++ struct au_fsctx_opts *a = fc->fs_private;
++ struct au_opt *opt = a->opt;
++
++ AuDbg("fc %p, param {key %s, string %s}\n",
++ fc, param->key, param->string);
++ err = fs_parse(fc, aufs_fsctx_paramspec, param, &result);
++ if (unlikely(err < 0))
++ goto out;
++ token = err;
++ AuDbg("token %d, res{negated %d, uint64 %llu}\n",
++ token, result.negated, result.uint_64);
++
++ err = -EINVAL;
++ a->skipped = 0;
++ switch (token) {
++ case Opt_br:
++ err = au_fsctx_parse_br(fc, param->string);
++ break;
++ case Opt_add:
++ err = au_fsctx_parse_add(fc, param->string);
++ break;
++ case Opt_append:
++ err = au_fsctx_parse_do_add(fc, opt, param->string, param->size,
++ /*dummy bindex*/1);
++ break;
++ case Opt_prepend:
++ err = au_fsctx_parse_do_add(fc, opt, param->string, param->size,
++ /*bindex*/0);
++ break;
++
++ case Opt_del:
++ err = au_fsctx_parse_del(fc, &opt->del, param);
++ break;
++#if 0 /* reserved for future use */
++ case Opt_idel:
++ if (!a->sb) {
++ err = 0;
++ a->skipped = 1;
++ break;
++ }
++ del->pathname = "(indexed)";
++ err = au_opts_parse_idel(fc, &opt->del, result.uint_32);
++ break;
++#endif
++
++ case Opt_mod:
++ err = au_fsctx_parse_mod(fc, &opt->mod, param);
++ break;
++#ifdef IMOD /* reserved for future use */
++ case Opt_imod:
++ if (!a->sb) {
++ err = 0;
++ a->skipped = 1;
++ break;
++ }
++ u.mod->path = "(indexed)";
++ err = au_opts_parse_imod(fc, &opt->mod, param->string);
++ break;
++#endif
++
++ case Opt_xino:
++ err = au_fsctx_parse_xino(fc, &opt->xino, param);
++ break;
++ case Opt_trunc_xino_path:
++ if (!a->sb) {
++ errorfc(fc, "no such branch %s", param->string);
++ break;
++ }
++ err = au_fsctx_parse_xino_itrunc_path(fc, &opt->xino_itrunc,
++ param->string);
++ break;
++#if 0
++ case Opt_trunc_xino_v:
++ if (!a->sb) {
++ err = 0;
++ a->skipped = 1;
++ break;
++ }
++ err = au_fsctx_parse_xino_itrunc_path(fc, &opt->xino_itrunc,
++ param->string);
++ break;
++#endif
++ case Opt_itrunc_xino:
++ if (!a->sb) {
++ errorfc(fc, "out of bounds %s", param->string);
++ break;
++ }
++ err = au_fsctx_parse_xino_itrunc(fc, &opt->xino_itrunc,
++ result.int_32);
++ break;
++
++ case Opt_dirwh:
++ err = 0;
++ opt->dirwh = result.int_32;
++ break;
++
++ case Opt_rdcache:
++ if (unlikely(result.int_32 > AUFS_RDCACHE_MAX)) {
++ errorfc(fc, "rdcache must be smaller than %d",
++ AUFS_RDCACHE_MAX);
++ break;
++ }
++ err = 0;
++ opt->rdcache = result.int_32;
++ break;
++
++ case Opt_rdblk:
++ err = 0;
++ opt->rdblk = AUFS_RDBLK_DEF;
++ if (!strcmp(param->string, "def"))
++ break;
++
++ err = kstrtoint(param->string, 0, &result.int_32);
++ if (unlikely(err)) {
++ errorfc(fc, "bad value in %s", param->key);
++ break;
++ }
++ err = -EINVAL;
++ if (unlikely(result.int_32 < 0
++ || result.int_32 > KMALLOC_MAX_SIZE)) {
++ errorfc(fc, "bad value in %s", param->key);
++ break;
++ }
++ if (unlikely(result.int_32 && result.int_32 < NAME_MAX)) {
++ errorfc(fc, "rdblk must be larger than %d", NAME_MAX);
++ break;
++ }
++ err = 0;
++ opt->rdblk = result.int_32;
++ break;
++
++ case Opt_rdhash:
++ err = 0;
++ opt->rdhash = AUFS_RDHASH_DEF;
++ if (!strcmp(param->string, "def"))
++ break;
++
++ err = kstrtoint(param->string, 0, &result.int_32);
++ if (unlikely(err)) {
++ errorfc(fc, "bad value in %s", param->key);
++ break;
++ }
++ /* how about zero? */
++ if (result.int_32 < 0
++ || result.int_32 * sizeof(struct hlist_head)
++ > KMALLOC_MAX_SIZE) {
++ err = -EINVAL;
++ errorfc(fc, "bad integer in %s", param->key);
++ break;
++ }
++ opt->rdhash = result.int_32;
++ break;
++
++ case Opt_diropq:
++ /*
++ * As other options, fs/aufs/opts.c can handle these strings by
++ * match_token(). But "diropq=" is deprecated now and will
++ * never have other value. So simple strcmp() is enough here.
++ */
++ if (!strcmp(param->string, "a") ||
++ !strcmp(param->string, "always")) {
++ err = 0;
++ opt->type = Opt_diropq_a;
++ } else if (!strcmp(param->string, "w") ||
++ !strcmp(param->string, "whiteouted")) {
++ err = 0;
++ opt->type = Opt_diropq_w;
++ } else
++ errorfc(fc, "unknown value %s", param->string);
++ break;
++
++ case Opt_udba:
++ opt->udba = au_udba_val(param->string);
++ if (opt->udba >= 0)
++ err = 0;
++ else
++ errorf(fc, "wrong value, %s", param->string);
++ break;
++
++ case Opt_wbr_create:
++ opt->wbr_create.wbr_create
++ = au_wbr_create_val(param->string, &opt->wbr_create);
++ if (opt->wbr_create.wbr_create >= 0)
++ err = 0;
++ else
++ errorf(fc, "wrong value, %s", param->key);
++ break;
++
++ case Opt_wbr_copyup:
++ opt->wbr_copyup = au_wbr_copyup_val(param->string);
++ if (opt->wbr_copyup >= 0)
++ err = 0;
++ else
++ errorfc(fc, "wrong value, %s", param->key);
++ break;
++
++ case Opt_fhsm_sec:
++ if (unlikely(result.int_32 < 0)) {
++ errorfc(fc, "bad integer in %s\n", param->key);
++ break;
++ }
++ err = 0;
++ if (sysaufs_brs)
++ opt->fhsm_second = result.int_32;
++ else
++ warnfc(fc, "ignored %s %s", param->key, param->string);
++ break;
++
++ /* simple true/false flag */
++#define au_fsctx_TF(name) \
++ case Opt_##name: \
++ err = 0; \
++ opt->tf = !result.negated; \
++ break
++ au_fsctx_TF(trunc_xino);
++ au_fsctx_TF(trunc_xib);
++ au_fsctx_TF(dirperm1);
++ au_fsctx_TF(plink);
++ au_fsctx_TF(shwh);
++ au_fsctx_TF(dio);
++ au_fsctx_TF(warn_perm);
++ au_fsctx_TF(verbose);
++ au_fsctx_TF(sum);
++ au_fsctx_TF(dirren);
++ au_fsctx_TF(acl);
++#undef au_fsctx_TF
++
++ case Opt_noverbose:
++ err = 0;
++ opt->type = Opt_verbose;
++ opt->tf = false;
++ break;
++
++ case Opt_noxino:
++ fallthrough;
++ case Opt_list_plink:
++ fallthrough;
++ case Opt_wsum:
++ err = 0;
++ break;
++
++ case Opt_ignore:
++ warnfc(fc, "ignored %s", param->key);
++ fallthrough;
++ case Opt_ignore_silent:
++ a->skipped = 1;
++ err = 0;
++ break;
++ default:
++ a->skipped = 1;
++ err = -ENOPARAM;
++ break;
++ }
++ if (unlikely(err))
++ goto out;
++ if (a->skipped)
++ goto out;
++
++ switch (token) {
++ case Opt_br:
++ fallthrough;
++ case Opt_noverbose:
++ fallthrough;
++ case Opt_diropq:
++ break;
++ default:
++ opt->type = token;
++ break;
++ }
++ opt++;
++ if (unlikely(opt > a->opt_tail)) {
++ err = -E2BIG;
++ opt--;
++ }
++ opt->type = Opt_tail;
++ a->opt = opt;
++
++out:
++ return err;
++}
++
++/*
++ * these options accept both 'name=val' and 'name:val' form.
++ * some accept optional '=' in its value.
++ * eg. br:/br1=rw:/br2=ro and br=/br1=rw:/br2=ro
++ */
++static inline unsigned int is_colonopt(char *str)
++{
++#define do_test(name) \
++ if (!strncmp(str, name ":", sizeof(name))) \
++ return sizeof(name) - 1
++ do_test("br");
++ do_test("add");
++ do_test("ins");
++ do_test("append");
++ do_test("prepend");
++ do_test("del");
++ /* do_test("idel"); */
++ do_test("mod");
++ /* do_test("imod"); */
++#undef do_test
++
++ return 0;
++}
++
++static int au_fsctx_parse_monolithic(struct fs_context *fc, void *data)
++{
++ int err;
++ unsigned int u;
++ char *str;
++ struct au_fsctx_opts *a = fc->fs_private;
++
++ str = data;
++ AuDbg("str %s\n", str);
++ while (str) {
++ u = is_colonopt(str);
++ if (u)
++ str[u] = '=';
++ str = strchr(str, ',');
++ if (!str)
++ break;
++ str++;
++ }
++ str = data;
++ AuDbg("str %s\n", str);
++
++ err = generic_parse_monolithic(fc, str);
++ AuTraceErr(err);
++ au_fsctx_dump(&a->opts);
++
++ return err;
++}
++
++/* ---------------------------------------------------------------------- */
++
++static void au_fsctx_opts_free(struct au_opts *opts)
++{
++ struct au_opt *opt;
++
++ opt = opts->opt;
++ while (opt->type != Opt_tail) {
++ switch (opt->type) {
++ case Opt_add:
++ fallthrough;
++ case Opt_append:
++ fallthrough;
++ case Opt_prepend:
++ kfree(opt->add.pathname);
++ path_put(&opt->add.path);
++ break;
++ case Opt_del:
++ kfree(opt->del.pathname);
++ fallthrough;
++ case Opt_idel:
++ path_put(&opt->del.h_path);
++ break;
++ case Opt_mod:
++ kfree(opt->mod.path);
++ fallthrough;
++ case Opt_imod:
++ dput(opt->mod.h_root);
++ break;
++ case Opt_xino:
++ kfree(opt->xino.path);
++ fput(opt->xino.file);
++ break;
++ }
++ opt++;
++ }
++}
++
++static void au_fsctx_free(struct fs_context *fc)
++{
++ struct au_fsctx_opts *a = fc->fs_private;
++
++ /* fs_type=%p, root=%pD */
++ AuDbg("fc %p{sb_flags 0x%x, sb_flags_mask 0x%x, purpose %u\n",
++ fc, fc->sb_flags, fc->sb_flags_mask, fc->purpose);
++
++ kobject_put(&a->sbinfo->si_kobj);
++ au_fsctx_opts_free(&a->opts);
++ free_page((unsigned long)a->opts.opt);
++ au_kfree_rcu(a);
++}
++
++static const struct fs_context_operations au_fsctx_ops = {
++ .free = au_fsctx_free,
++ .parse_param = au_fsctx_parse_param,
++ .parse_monolithic = au_fsctx_parse_monolithic,
++ .get_tree = au_fsctx_get_tree,
++ .reconfigure = au_fsctx_reconfigure
++ /*
++ * nfs4 requires ->dup()? No.
++ * I don't know what is this ->dup() for.
++ */
++};
++
++int aufs_fsctx_init(struct fs_context *fc)
++{
++ int err;
++ struct au_fsctx_opts *a;
++
++ /* fs_type=%p, root=%pD */
++ AuDbg("fc %p{sb_flags 0x%x, sb_flags_mask 0x%x, purpose %u\n",
++ fc, fc->sb_flags, fc->sb_flags_mask, fc->purpose);
++
++ /* they will be freed by au_fsctx_free() */
++ err = -ENOMEM;
++ a = kzalloc(sizeof(*a), GFP_NOFS);
++ if (unlikely(!a))
++ goto out;
++ a->bindex = 0;
++ a->opts.opt = (void *)__get_free_page(GFP_NOFS);
++ if (unlikely(!a->opts.opt))
++ goto out_a;
++ a->opt = a->opts.opt;
++ a->opt->type = Opt_tail;
++ a->opts.max_opt = PAGE_SIZE / sizeof(*a->opts.opt);
++ a->opt_tail = a->opt + a->opts.max_opt - 1;
++ a->opts.sb_flags = fc->sb_flags;
++
++ a->sb = NULL;
++ if (fc->root) {
++ AuDebugOn(fc->purpose != FS_CONTEXT_FOR_RECONFIGURE);
++ a->opts.flags = AuOpts_REMOUNT;
++ a->sb = fc->root->d_sb;
++ a->sbinfo = au_sbi(a->sb);
++ kobject_get(&a->sbinfo->si_kobj);
++ } else {
++ a->sbinfo = au_si_alloc(a->sb);
++ AuDebugOn(!a->sbinfo);
++ err = PTR_ERR(a->sbinfo);
++ if (IS_ERR(a->sbinfo))
++ goto out_opt;
++ au_rw_write_unlock(&a->sbinfo->si_rwsem);
++ }
++
++ err = 0;
++ fc->fs_private = a;
++ fc->ops = &au_fsctx_ops;
++ goto out; /* success */
++
++out_opt:
++ free_page((unsigned long)a->opts.opt);
++out_a:
++ au_kfree_rcu(a);
++out:
++ AuTraceErr(err);
++ return err;
++}
diff --git a/fs/aufs/fstype.h b/fs/aufs/fstype.h
new file mode 100644
-index 000000000000..510bd87e9404
+index 000000000000..24ff0d64c219
--- /dev/null
+++ b/fs/aufs/fstype.h
@@ -0,0 +1,401 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -16224,15 +17467,15 @@ index 000000000000..510bd87e9404
+#endif /* __AUFS_FSTYPE_H__ */
diff --git a/fs/aufs/hbl.h b/fs/aufs/hbl.h
new file mode 100644
-index 000000000000..6db65b16b08a
+index 000000000000..7e1e66db0264
--- /dev/null
+++ b/fs/aufs/hbl.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2017-2019 Junjiro R. Okajima
++ * Copyright (C) 2017-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -16295,15 +17538,15 @@ index 000000000000..6db65b16b08a
+#endif /* __AUFS_HBL_H__ */
diff --git a/fs/aufs/hfsnotify.c b/fs/aufs/hfsnotify.c
new file mode 100644
-index 000000000000..7945ae3ca073
+index 000000000000..caa900cea3a0
--- /dev/null
+++ b/fs/aufs/hfsnotify.c
-@@ -0,0 +1,288 @@
+@@ -0,0 +1,290 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -16461,8 +17704,8 @@ index 000000000000..7945ae3ca073
+}
+
+static int au_hfsn_handle_event(struct fsnotify_group *group,
-+ struct inode *inode,
+ u32 mask, const void *data, int data_type,
++ struct inode *dir,
+ const struct qstr *file_name, u32 cookie,
+ struct fsnotify_iter_info *iter_info)
+{
@@ -16471,7 +17714,8 @@ index 000000000000..7945ae3ca073
+ struct inode *h_dir, *h_inode;
+ struct fsnotify_mark *inode_mark;
+
-+ AuDebugOn(data_type != FSNOTIFY_EVENT_INODE);
++ AuDebugOn(!(data_type == FSNOTIFY_EVENT_INODE
++ || data_type == FSNOTIFY_EVENT_DENTRY));
+
+ err = 0;
+ /* if FS_UNMOUNT happens, there must be another bug */
@@ -16479,15 +17723,15 @@ index 000000000000..7945ae3ca073
+ if (mask & (FS_IN_IGNORED | FS_UNMOUNT))
+ goto out;
+
-+ h_dir = inode;
++ h_dir = dir;
+ h_inode = NULL;
+#ifdef AuDbgHnotify
+ au_debug_on();
-+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
-+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
++ if (1 || file_name.len != sizeof(AUFS_XINO_FNAME) - 1
++ || strncmp(file_name.name, AUFS_XINO_FNAME, file_name.len)) {
+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
+ h_dir->i_ino, mask, au_hfsn_name(mask),
-+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
++ AuLNPair(file_name), h_inode ? h_inode->i_ino : 0);
+ /* WARN_ON(1); */
+ }
+ au_debug_off();
@@ -16539,7 +17783,8 @@ index 000000000000..7945ae3ca073
+ goto out;
+
+ err = 0;
-+ group = fsnotify_alloc_group(&au_hfsn_ops);
++ group = fsnotify_alloc_group(&au_hfsn_ops,
++ /*flags - not for userspace*/0);
+ if (IS_ERR(group)) {
+ err = PTR_ERR(group);
+ pr_err("fsnotify_alloc_group() failed, %d\n", err);
@@ -16589,15 +17834,15 @@ index 000000000000..7945ae3ca073
+};
diff --git a/fs/aufs/hfsplus.c b/fs/aufs/hfsplus.c
new file mode 100644
-index 000000000000..3bd869a69c8f
+index 000000000000..c626ff2128c6
--- /dev/null
+++ b/fs/aufs/hfsplus.c
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2010-2019 Junjiro R. Okajima
++ * Copyright (C) 2010-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -16655,15 +17900,15 @@ index 000000000000..3bd869a69c8f
+}
diff --git a/fs/aufs/hnotify.c b/fs/aufs/hnotify.c
new file mode 100644
-index 000000000000..2e7c2cdb8202
+index 000000000000..8ca8c98d40a3
--- /dev/null
+++ b/fs/aufs/hnotify.c
-@@ -0,0 +1,721 @@
+@@ -0,0 +1,715 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -16843,12 +18088,6 @@ index 000000000000..2e7c2cdb8202
+
+out_dpages:
+ au_dpages_free(&dpages);
-+
-+#if 0
-+ /* discard children */
-+ dentry_unhash(dentry);
-+ dput(dentry);
-+#endif
+out:
+ return err;
+}
@@ -17251,7 +18490,7 @@ index 000000000000..2e7c2cdb8202
+ case FS_MOVED_TO:
+ au_fset_hnjob(flags[AuHn_CHILD], XINO0);
+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
-+ /*FALLTHROUGH*/
++ fallthrough;
+ case FS_CREATE:
+ AuDebugOn(!h_child_name);
+ break;
@@ -17382,15 +18621,15 @@ index 000000000000..2e7c2cdb8202
+}
diff --git a/fs/aufs/i_op.c b/fs/aufs/i_op.c
new file mode 100644
-index 000000000000..ef1e08c7ca10
+index 000000000000..141620c2e0bd
--- /dev/null
+++ b/fs/aufs/i_op.c
-@@ -0,0 +1,1505 @@
+@@ -0,0 +1,1517 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -17409,9 +18648,9 @@ index 000000000000..ef1e08c7ca10
+ */
+
+#include <linux/device_cgroup.h>
++#include <linux/filelock.h>
+#include <linux/fs_stack.h>
+#include <linux/iversion.h>
-+#include <linux/namei.h>
+#include <linux/security.h>
+#include "aufs.h"
+
@@ -17420,6 +18659,7 @@ index 000000000000..ef1e08c7ca10
+{
+ int err;
+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
++ struct mnt_idmap *h_idmap;
+
+ err = -EPERM;
+ if (write_mask && IS_IMMUTABLE(h_inode))
@@ -17439,19 +18679,22 @@ index 000000000000..ef1e08c7ca10
+ * - nfs always sets SB_POSIXACL regardless its mount option 'noacl.'
+ * in this case, generic_permission() returns -EOPNOTSUPP.
+ */
++ h_idmap = mnt_idmap(h_path->mnt);
+ if ((write_mask && !au_br_writable(brperm))
+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
+ && write_mask && !(mask & MAY_READ))
+ || !h_inode->i_op->permission) {
+ /* AuLabel(generic_permission); */
-+ /* AuDbg("get_acl %ps\n", h_inode->i_op->get_acl); */
-+ err = generic_permission(h_inode, mask);
++ /* AuDbg("get_inode_acl %ps\n",
++ h_inode->i_op->get_inode_acl); */
++ err = generic_permission(h_idmap, h_inode, mask);
+ if (err == -EOPNOTSUPP && au_test_nfs_noacl(h_inode))
-+ err = h_inode->i_op->permission(h_inode, mask);
++ err = h_inode->i_op->permission(h_idmap, h_inode,
++ mask);
+ AuTraceErr(err);
+ } else {
+ /* AuLabel(h_inode->permission); */
-+ err = h_inode->i_op->permission(h_inode, mask);
++ err = h_inode->i_op->permission(h_idmap, h_inode, mask);
+ AuTraceErr(err);
+ }
+
@@ -17460,24 +18703,12 @@ index 000000000000..ef1e08c7ca10
+ if (!err)
+ err = security_inode_permission(h_inode, mask);
+
-+#if 0
-+ if (!err) {
-+ /* todo: do we need to call ima_path_check()? */
-+ struct path h_path = {
-+ .dentry =
-+ .mnt = h_mnt
-+ };
-+ err = ima_path_check(&h_path,
-+ mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
-+ IMA_COUNT_LEAVE);
-+ }
-+#endif
-+
+out:
+ return err;
+}
+
-+static int aufs_permission(struct inode *inode, int mask)
++static int aufs_permission(struct mnt_idmap *idmap, struct inode *inode,
++ int mask)
+{
+ int err;
+ aufs_bindex_t bindex, bbot;
@@ -17494,7 +18725,13 @@ index 000000000000..ef1e08c7ca10
+ sb = inode->i_sb;
+ si_read_lock(sb, AuLock_FLUSH);
+ ii_read_lock_child(inode);
-+#if 0
++#if 0 /* reserved for future use */
++ /*
++ * This test may be rather 'too much' since the test is essentially done
++ * in the aufs_lookup(). Theoretically it is possible that the inode
++ * generation doesn't match to the superblock's here. But it isn't a
++ * big deal I suppose.
++ */
+ err = au_iigen_test(inode, au_sigen(sb));
+ if (unlikely(err))
+ goto out;
@@ -17612,7 +18849,7 @@ index 000000000000..ef1e08c7ca10
+ if (inode)
+ atomic_inc(&inode->i_count);
+ ret = d_splice_alias(inode, dentry);
-+#if 0
++#if 0 /* reserved for future use */
+ if (unlikely(d_need_lookup(dentry))) {
+ spin_lock(&dentry->d_lock);
+ dentry->d_flags &= ~DCACHE_NEED_LOOKUP;
@@ -18044,7 +19281,7 @@ index 000000000000..ef1e08c7ca10
+{
+ if (p->hdir) {
+ au_pin_hdir_set_owner(p, p->task);
-+ rwsem_release(&p->hdir->hi_inode->i_rwsem.dep_map, 1, _RET_IP_);
++ rwsem_release(&p->hdir->hi_inode->i_rwsem.dep_map, _RET_IP_);
+ }
+}
+
@@ -18319,18 +19556,20 @@ index 000000000000..ef1e08c7ca10
+ return err;
+}
+
-+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
++static int aufs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
++ struct iattr *ia)
+{
+ int err;
+ struct inode *inode, *delegated;
+ struct super_block *sb;
+ struct file *file;
+ struct au_icpup_args *a;
++ struct mnt_idmap *h_idmap;
+
+ inode = d_inode(dentry);
+ IMustLock(inode);
+
-+ err = setattr_prepare(dentry, ia);
++ err = setattr_prepare(idmap, dentry, ia);
+ if (unlikely(err))
+ goto out;
+
@@ -18423,8 +19662,10 @@ index 000000000000..ef1e08c7ca10
+ * regardless aufs 'acl' option setting.
+ * why don't all acl-aware fs call this func from their ->setattr()?
+ */
-+ if (!err && (ia->ia_valid & ATTR_MODE))
-+ err = vfsub_acl_chmod(a->h_inode, ia->ia_mode);
++ if (!err && (ia->ia_valid & ATTR_MODE)) {
++ h_idmap = mnt_idmap(a->h_path.mnt);
++ err = vfsub_acl_chmod(h_idmap, a->h_path.dentry, ia->ia_mode);
++ }
+ if (!err)
+ au_cpup_attr_changeable(inode);
+
@@ -18486,6 +19727,7 @@ index 000000000000..ef1e08c7ca10
+ struct super_block *sb;
+ struct au_icpup_args *a;
+ struct inode *h_inode;
++ struct mnt_idmap *h_idmap;
+
+ IMustLock(inode);
+
@@ -18504,23 +19746,25 @@ index 000000000000..ef1e08c7ca10
+ err = au_h_path_to_set_attr(dentry, a, &h_path);
+ if (unlikely(err))
+ goto out_di;
++ h_idmap = mnt_idmap(h_path.mnt);
+
+ inode_unlock(a->h_inode);
+ switch (arg->type) {
+ case AU_XATTR_SET:
+ AuDebugOn(d_is_negative(h_path.dentry));
-+ err = vfsub_setxattr(h_path.dentry,
++ err = vfsub_setxattr(h_idmap, h_path.dentry,
+ arg->u.set.name, arg->u.set.value,
+ arg->u.set.size, arg->u.set.flags);
+ break;
+ case AU_ACL_SET:
+ err = -EOPNOTSUPP;
+ h_inode = d_inode(h_path.dentry);
-+ if (h_inode->i_op->set_acl)
++ if (h_inode->i_op->set_acl) {
+ /* this will call posix_acl_update_mode */
-+ err = h_inode->i_op->set_acl(h_inode,
++ err = h_inode->i_op->set_acl(h_idmap, h_path.dentry,
+ arg->u.acl_set.acl,
+ arg->u.acl_set.type);
++ }
+ break;
+ }
+ if (!err)
@@ -18575,15 +19819,14 @@ index 000000000000..ef1e08c7ca10
+ * returns zero or negative (an error).
+ * @dentry will be read-locked in success.
+ */
-+int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path,
-+ int locked)
++int au_h_path_getattr(struct dentry *dentry, struct inode *inode, int force,
++ struct path *h_path, int locked)
+{
+ int err;
+ unsigned int mnt_flags, sigen;
+ unsigned char udba_none;
+ aufs_bindex_t bindex;
+ struct super_block *sb, *h_sb;
-+ struct inode *inode;
+
+ h_path->mnt = NULL;
+ h_path->dentry = NULL;
@@ -18624,7 +19867,11 @@ index 000000000000..ef1e08c7ca10
+ di_read_lock_child(dentry, AuLock_IR);
+
+body:
-+ inode = d_inode(dentry);
++ if (!inode) {
++ inode = d_inode(dentry);
++ if (unlikely(!inode))
++ goto out;
++ }
+ bindex = au_ibtop(inode);
+ h_path->mnt = au_sbr_mnt(sb, bindex);
+ h_sb = h_path->mnt->mnt_sb;
@@ -18648,8 +19895,8 @@ index 000000000000..ef1e08c7ca10
+ return err;
+}
+
-+static int aufs_getattr(const struct path *path, struct kstat *st,
-+ u32 request, unsigned int query)
++static int aufs_getattr(struct mnt_idmap *idmap, const struct path *path,
++ struct kstat *st, u32 request, unsigned int query)
+{
+ int err;
+ unsigned char positive;
@@ -18664,7 +19911,8 @@ index 000000000000..ef1e08c7ca10
+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
+ if (unlikely(err))
+ goto out;
-+ err = au_h_path_getattr(dentry, /*force*/0, &h_path, /*locked*/0);
++ err = au_h_path_getattr(dentry, /*inode*/NULL, /*force*/0, &h_path,
++ /*locked*/0);
+ if (unlikely(err))
+ goto out_si;
+ if (unlikely(!h_path.dentry))
@@ -18685,7 +19933,7 @@ index 000000000000..ef1e08c7ca10
+ goto out_di;
+
+out_fill:
-+ generic_fillattr(inode, st);
++ generic_fillattr(idmap, inode, st);
+out_di:
+ di_read_unlock(dentry, AuLock_IR);
+out_si:
@@ -18831,6 +20079,7 @@ index 000000000000..ef1e08c7ca10
+ [AuIop_SYMLINK] = {
+ .permission = aufs_permission,
+#ifdef CONFIG_FS_POSIX_ACL
++ .get_inode_acl = aufs_get_inode_acl,
+ .get_acl = aufs_get_acl,
+ .set_acl = aufs_set_acl, /* unsupport for symlink? */
+#endif
@@ -18842,7 +20091,7 @@ index 000000000000..ef1e08c7ca10
+ .listxattr = aufs_listxattr,
+#endif
+
-+ .get_link = aufs_get_link,
++ .get_link = aufs_get_link
+
+ /* .update_time = aufs_update_time */
+ },
@@ -18859,6 +20108,7 @@ index 000000000000..ef1e08c7ca10
+
+ .permission = aufs_permission,
+#ifdef CONFIG_FS_POSIX_ACL
++ .get_inode_acl = aufs_get_inode_acl,
+ .get_acl = aufs_get_acl,
+ .set_acl = aufs_set_acl,
+#endif
@@ -18877,6 +20127,7 @@ index 000000000000..ef1e08c7ca10
+ [AuIop_OTHER] = {
+ .permission = aufs_permission,
+#ifdef CONFIG_FS_POSIX_ACL
++ .get_inode_acl = aufs_get_inode_acl,
+ .get_acl = aufs_get_acl,
+ .set_acl = aufs_set_acl,
+#endif
@@ -18893,15 +20144,15 @@ index 000000000000..ef1e08c7ca10
+};
diff --git a/fs/aufs/i_op_add.c b/fs/aufs/i_op_add.c
new file mode 100644
-index 000000000000..af6893e61066
+index 000000000000..2adf97d4488d
--- /dev/null
+++ b/fs/aufs/i_op_add.c
-@@ -0,0 +1,936 @@
+@@ -0,0 +1,972 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -19265,8 +20516,8 @@ index 000000000000..af6893e61066
+ return err;
+}
+
-+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
-+ dev_t dev)
++int aufs_mknod(struct mnt_idmap *idmap, struct inode *dir,
++ struct dentry *dentry, umode_t mode, dev_t dev)
+{
+ struct simple_arg arg = {
+ .type = Mknod,
@@ -19278,7 +20529,8 @@ index 000000000000..af6893e61066
+ return add_simple(dir, dentry, &arg);
+}
+
-+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
++int aufs_symlink(struct mnt_idmap *idmap, struct inode *dir,
++ struct dentry *dentry, const char *symname)
+{
+ struct simple_arg arg = {
+ .type = Symlink,
@@ -19287,8 +20539,8 @@ index 000000000000..af6893e61066
+ return add_simple(dir, dentry, &arg);
+}
+
-+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-+ bool want_excl)
++int aufs_create(struct mnt_idmap *idmap, struct inode *dir,
++ struct dentry *dentry, umode_t mode, bool want_excl)
+{
+ struct simple_arg arg = {
+ .type = Creat,
@@ -19315,14 +20567,19 @@ index 000000000000..af6893e61066
+ return add_simple(dir, dentry, &arg);
+}
+
-+int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
++int aufs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
++ struct file *file, umode_t mode)
+{
+ int err;
+ aufs_bindex_t bindex;
++ struct path h_ppath;
+ struct super_block *sb;
-+ struct dentry *parent, *h_parent, *h_dentry;
++ struct au_branch *br;
++ struct dentry *dentry, *parent, *h_parent, *h_dentry;
+ struct inode *h_dir, *inode;
+ struct vfsmount *h_mnt;
++ struct mnt_idmap *h_idmap;
++ struct file *h_file;
+ struct au_wr_dir_args wr_dir_args = {
+ .force_btgt = -1,
+ .flags = AuWrDir_TMPFILE
@@ -19331,11 +20588,13 @@ index 000000000000..af6893e61066
+ /* copy-up may happen */
+ inode_lock(dir);
+
++ h_file = NULL;
+ sb = dir->i_sb;
+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
+ if (unlikely(err))
+ goto out;
+
++ dentry = file->f_path.dentry;
+ err = au_di_init(dentry);
+ if (unlikely(err))
+ goto out_si;
@@ -19364,18 +20623,25 @@ index 000000000000..af6893e61066
+ if (unlikely(!h_dir->i_op->tmpfile))
+ goto out_parent;
+
-+ h_mnt = au_sbr_mnt(sb, bindex);
++ br = au_sbr(sb, bindex);
++ h_mnt = au_br_mnt(br);
+ err = vfsub_mnt_want_write(h_mnt);
+ if (unlikely(err))
+ goto out_parent;
+
++ h_idmap = mnt_idmap(h_mnt);
+ h_parent = au_h_dptr(parent, bindex);
-+ h_dentry = vfs_tmpfile(h_parent, mode, /*open_flag*/0);
-+ if (IS_ERR(h_dentry)) {
-+ err = PTR_ERR(h_dentry);
++ h_ppath.mnt = h_mnt;
++ h_ppath.dentry = h_parent;
++ h_file = kernel_tmpfile_open(h_idmap, &h_ppath, mode, /*open_flag*/0,
++ current_cred());
++ if (IS_ERR(h_file)) {
++ err = PTR_ERR(h_file);
++ h_file = NULL;
+ goto out_mnt;
+ }
+
++ h_dentry = h_file->f_path.dentry;
+ au_set_dbtop(dentry, bindex);
+ au_set_dbbot(dentry, bindex);
+ au_set_h_dptr(dentry, bindex, dget(h_dentry));
@@ -19385,32 +20651,52 @@ index 000000000000..af6893e61066
+ au_set_h_dptr(dentry, bindex, NULL);
+ au_set_dbtop(dentry, -1);
+ au_set_dbbot(dentry, -1);
-+ } else {
-+ if (!inode->i_nlink)
-+ set_nlink(inode, 1);
-+ d_tmpfile(dentry, inode);
-+ au_di(dentry)->di_tmpfile = 1;
-+
-+ /* update without i_mutex */
-+ if (au_ibtop(dir) == au_dbtop(dentry))
-+ au_cpup_attr_timesizes(dir);
++ goto out_h_file;
+ }
-+ dput(h_dentry);
+
++ if (!inode->i_nlink)
++ set_nlink(inode, 1);
++ d_tmpfile(file, inode);
++ au_di(dentry)->di_tmpfile = 1;
++ get_file(h_file);
++ au_di(dentry)->di_htmpfile = h_file;
++
++ /* update without i_mutex */
++ if (au_ibtop(dir) == au_dbtop(dentry))
++ au_cpup_attr_timesizes(dir);
++
++out_h_file:
++ fput(h_file);
+out_mnt:
+ vfsub_mnt_drop_write(h_mnt);
+out_parent:
+ di_write_unlock(parent);
+ dput(parent);
+ di_write_unlock(dentry);
-+ if (unlikely(err)) {
-+ au_di_fin(dentry);
-+ dentry->d_fsdata = NULL;
-+ }
++ if (!err)
++ goto out_si;
++ if (h_file)
++ fput(h_file);
++ au_di(dentry)->di_htmpfile = NULL;
++ au_di_fin(dentry);
++ dentry->d_fsdata = NULL;
+out_si:
+ si_read_unlock(sb);
++ if (!err && h_file) {
++ /* finally... */
++ err = finish_open_simple(file, err);
++ if (!err)
++ au_lcnt_inc(&br->br_nfiles);
++ else {
++ fput(h_file);
++ au_di(dentry)->di_htmpfile = NULL;
++ au_di_fin(dentry);
++ dentry->d_fsdata = NULL;
++ }
++ }
+out:
+ inode_unlock(dir);
++ AuTraceErr(err);
+ return err;
+}
+
@@ -19726,7 +21012,8 @@ index 000000000000..af6893e61066
+ return err;
+}
+
-+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
++int aufs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
++ struct dentry *dentry, umode_t mode)
+{
+ int err, rerr;
+ aufs_bindex_t bindex;
@@ -19835,15 +21122,15 @@ index 000000000000..af6893e61066
+}
diff --git a/fs/aufs/i_op_del.c b/fs/aufs/i_op_del.c
new file mode 100644
-index 000000000000..1c459dbea5db
+index 000000000000..d85f47cef29f
--- /dev/null
+++ b/fs/aufs/i_op_del.c
-@@ -0,0 +1,513 @@
+@@ -0,0 +1,522 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -19935,6 +21222,10 @@ index 000000000000..1c459dbea5db
+ umode_t h_mode;
+ struct dentry *h_dentry, *h_latest;
+ struct inode *h_inode;
++ struct path h_ppath;
++ struct super_block *sb;
++ struct au_branch *br;
++ struct mnt_idmap *h_idmap;
+
+ h_dentry = au_h_dptr(dentry, bindex);
+ if (d_really_is_positive(dentry)) {
@@ -19972,12 +21263,17 @@ index 000000000000..1c459dbea5db
+ * let's try heavy test.
+ */
+ err = -EACCES;
-+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1)
-+ && au_test_h_perm(d_inode(h_parent),
++ sb = dentry->d_sb;
++ br = au_sbr(sb, bindex);
++ h_idmap = au_br_idmap(br);
++ if (unlikely(!au_opt_test(au_mntflags(sb), DIRPERM1)
++ && au_test_h_perm(h_idmap, d_inode(h_parent),
+ MAY_EXEC | MAY_WRITE)))
+ goto out;
+
-+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent);
++ h_ppath.dentry = h_parent;
++ h_ppath.mnt = au_br_mnt(br);
++ h_latest = au_sio_lkup_one(h_idmap, &dentry->d_name, &h_ppath);
+ err = -EIO;
+ if (IS_ERR(h_latest))
+ goto out;
@@ -20354,15 +21650,15 @@ index 000000000000..1c459dbea5db
+}
diff --git a/fs/aufs/i_op_ren.c b/fs/aufs/i_op_ren.c
new file mode 100644
-index 000000000000..91aa66594a42
+index 000000000000..ab69a6ac9a42
--- /dev/null
+++ b/fs/aufs/i_op_ren.c
-@@ -0,0 +1,1250 @@
+@@ -0,0 +1,1257 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -20510,9 +21806,12 @@ index 000000000000..91aa66594a42
+{
+ int rerr;
+ struct inode *delegated;
++ struct path h_ppath = {
++ .dentry = a->src_h_parent,
++ .mnt = a->h_path.mnt
++ };
+
-+ a->h_path.dentry = vfsub_lkup_one(&a->src_dentry->d_name,
-+ a->src_h_parent);
++ a->h_path.dentry = vfsub_lkup_one(&a->src_dentry->d_name, &h_ppath);
+ rerr = PTR_ERR(a->h_path.dentry);
+ if (IS_ERR(a->h_path.dentry)) {
+ RevertFailure("lkup one %pd", a->src_dentry);
@@ -20539,9 +21838,12 @@ index 000000000000..91aa66594a42
+{
+ int rerr;
+ struct inode *delegated;
++ struct path h_ppath = {
++ .dentry = a->dst_h_parent,
++ .mnt = a->h_path.mnt
++ };
+
-+ a->h_path.dentry = vfsub_lkup_one(&a->dst_dentry->d_name,
-+ a->dst_h_parent);
++ a->h_path.dentry = vfsub_lkup_one(&a->dst_dentry->d_name, &h_ppath);
+ rerr = PTR_ERR(a->h_path.dentry);
+ if (IS_ERR(a->h_path.dentry)) {
+ RevertFailure("lkup one %pd", a->dst_dentry);
@@ -20775,7 +22077,7 @@ index 000000000000..91aa66594a42
+ }
+
+ BUG_ON(d_is_positive(a->dst_h_dentry) && a->src_btop != a->btgt);
-+#if 0
++#if 0 /* debugging */
+ BUG_ON(!au_ftest_ren(a->auren_flags, DIRREN)
+ && d_is_positive(a->dst_h_dentry)
+ && a->src_btop != a->btgt);
@@ -21313,7 +22615,8 @@ index 000000000000..91aa66594a42
+
+/* ---------------------------------------------------------------------- */
+
-+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
++int aufs_rename(struct mnt_idmap *idmap,
++ struct inode *_src_dir, struct dentry *_src_dentry,
+ struct inode *_dst_dir, struct dentry *_dst_dentry,
+ unsigned int _flags)
+{
@@ -21610,15 +22913,15 @@ index 000000000000..91aa66594a42
+}
diff --git a/fs/aufs/iinfo.c b/fs/aufs/iinfo.c
new file mode 100644
-index 000000000000..098fd115052a
+index 000000000000..0d3a2487643b
--- /dev/null
+++ b/fs/aufs/iinfo.c
@@ -0,0 +1,286 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -21902,15 +23205,15 @@ index 000000000000..098fd115052a
+}
diff --git a/fs/aufs/inode.c b/fs/aufs/inode.c
new file mode 100644
-index 000000000000..985377d9bf66
+index 000000000000..7dbf6a6f2fee
--- /dev/null
+++ b/fs/aufs/inode.c
-@@ -0,0 +1,529 @@
+@@ -0,0 +1,531 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -22120,7 +23423,7 @@ index 000000000000..985377d9bf66
+ struct dentry *h_dentry;
+ struct inode *h_inode;
+ struct au_iinfo *iinfo;
-+ struct inode_operations *iop;
++ const struct inode_operations *iop;
+
+ IiMustWriteLock(inode);
+
@@ -22182,7 +23485,7 @@ index 000000000000..985377d9bf66
+ }
+ au_cpup_attr_all(inode, /*force*/1);
+ /*
-+ * to force calling aufs_get_acl() every time,
++ * to force calling aufs_get_inode_acl() every time,
+ * do not call cache_no_acl() for aufs inode.
+ */
+
@@ -22420,32 +23723,34 @@ index 000000000000..985377d9bf66
+ return err;
+}
+
-+int au_test_h_perm(struct inode *h_inode, int mask)
++int au_test_h_perm(struct mnt_idmap *h_idmap, struct inode *h_inode,
++ int mask)
+{
+ if (uid_eq(current_fsuid(), GLOBAL_ROOT_UID))
+ return 0;
-+ return inode_permission(h_inode, mask);
++ return inode_permission(h_idmap, h_inode, mask);
+}
+
-+int au_test_h_perm_sio(struct inode *h_inode, int mask)
++int au_test_h_perm_sio(struct mnt_idmap *h_idmap, struct inode *h_inode,
++ int mask)
+{
+ if (au_test_nfs(h_inode->i_sb)
+ && (mask & MAY_WRITE)
+ && S_ISDIR(h_inode->i_mode))
+ mask |= MAY_READ; /* force permission check */
-+ return au_test_h_perm(h_inode, mask);
++ return au_test_h_perm(h_idmap, h_inode, mask);
+}
diff --git a/fs/aufs/inode.h b/fs/aufs/inode.h
new file mode 100644
-index 000000000000..e387ef16e999
+index 000000000000..76c3bd49674a
--- /dev/null
+++ b/fs/aufs/inode.h
-@@ -0,0 +1,698 @@
+@@ -0,0 +1,707 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -22580,8 +23885,10 @@ index 000000000000..e387ef16e999
+struct inode *au_new_inode(struct dentry *dentry, int must_new);
+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
+ struct inode *inode);
-+int au_test_h_perm(struct inode *h_inode, int mask);
-+int au_test_h_perm_sio(struct inode *h_inode, int mask);
++int au_test_h_perm(struct mnt_idmap *h_idmap, struct inode *h_inode,
++ int mask);
++int au_test_h_perm_sio(struct mnt_idmap *h_idmap, struct inode *h_inode,
++ int mask);
+
+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
+ ino_t h_ino, unsigned int d_type, ino_t *ino)
@@ -22600,7 +23907,7 @@ index 000000000000..e387ef16e999
+ AuIop_OTHER,
+ AuIop_Last
+};
-+extern struct inode_operations aufs_iop[AuIop_Last],
++extern struct inode_operations aufs_iop[AuIop_Last], /* not const */
+ aufs_iop_nogetattr[AuIop_Last];
+
+/* au_wr_dir flags */
@@ -22650,24 +23957,27 @@ index 000000000000..e387ef16e999
+int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
+ struct au_icpup_args *a);
+
-+int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path,
-+ int locked);
++int au_h_path_getattr(struct dentry *dentry, struct inode *inode, int force,
++ struct path *h_path, int locked);
+
+/* i_op_add.c */
+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
+ struct dentry *h_parent, int isdir);
-+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
-+ dev_t dev);
-+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
-+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-+ bool want_excl);
++int aufs_mknod(struct mnt_idmap *idmap, struct inode *dir,
++ struct dentry *dentry, umode_t mode, dev_t dev);
++int aufs_symlink(struct mnt_idmap *idmap, struct inode *dir,
++ struct dentry *dentry, const char *symname);
++int aufs_create(struct mnt_idmap *idmap, struct inode *dir,
++ struct dentry *dentry, umode_t mode, bool want_excl);
+struct vfsub_aopen_args;
+int au_aopen_or_create(struct inode *dir, struct dentry *dentry,
+ struct vfsub_aopen_args *args);
-+int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode);
++int aufs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
++ struct file *file, umode_t mode);
+int aufs_link(struct dentry *src_dentry, struct inode *dir,
+ struct dentry *dentry);
-+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
++int aufs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
++ struct dentry *dentry, umode_t mode);
+
+/* i_op_del.c */
+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
@@ -22678,9 +23988,10 @@ index 000000000000..e387ef16e999
+
+/* i_op_ren.c */
+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
-+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
-+ struct inode *dir, struct dentry *dentry,
-+ unsigned int flags);
++int aufs_rename(struct mnt_idmap *idmap,
++ struct inode *_src_dir, struct dentry *_src_dentry,
++ struct inode *_dst_dir, struct dentry *_dst_dentry,
++ unsigned int _flags);
+
+/* iinfo.c */
+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
@@ -22750,19 +24061,22 @@ index 000000000000..e387ef16e999
+
+#ifdef CONFIG_AUFS_XATTR
+/* xattr.c */
-+int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags,
++int au_cpup_xattr(struct path *h_dst, struct path *h_src, int ignore_flags,
+ unsigned int verbose);
+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size);
+void au_xattr_init(struct super_block *sb);
+#else
-+AuStubInt0(au_cpup_xattr, struct dentry *h_dst, struct dentry *h_src,
++AuStubInt0(au_cpup_xattr, struct path *h_dst, struct path *h_src,
+ int ignore_flags, unsigned int verbose);
+AuStubVoid(au_xattr_init, struct super_block *sb);
+#endif
+
+#ifdef CONFIG_FS_POSIX_ACL
-+struct posix_acl *aufs_get_acl(struct inode *inode, int type);
-+int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
++struct posix_acl *aufs_get_inode_acl(struct inode *inode, int type, bool rcu);
++struct posix_acl *aufs_get_acl(struct mnt_idmap *idmap,
++ struct dentry *dentry, int type);
++int aufs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
++ struct posix_acl *acl, int type);
+#endif
+
+#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL)
@@ -23036,7 +24350,7 @@ index 000000000000..e387ef16e999
+ int (*alloc)(struct au_hinode *hinode);
+
+ /*
-+ * if it returns true, the the caller should free hinode->hi_notify,
++ * if it returns true, the caller should free hinode->hi_notify,
+ * otherwise ->free() frees it.
+ */
+ int (*free)(struct au_hinode *hinode,
@@ -23141,15 +24455,15 @@ index 000000000000..e387ef16e999
+#endif /* __AUFS_INODE_H__ */
diff --git a/fs/aufs/ioctl.c b/fs/aufs/ioctl.c
new file mode 100644
-index 000000000000..fb2fb758283e
+index 000000000000..2d8d91084099
--- /dev/null
+++ b/fs/aufs/ioctl.c
@@ -0,0 +1,220 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -23367,15 +24681,15 @@ index 000000000000..fb2fb758283e
+#endif
diff --git a/fs/aufs/lcnt.h b/fs/aufs/lcnt.h
new file mode 100644
-index 000000000000..d8508f875f28
+index 000000000000..6dc37108565f
--- /dev/null
+++ b/fs/aufs/lcnt.h
@@ -0,0 +1,186 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2018-2019 Junjiro R. Okajima
++ * Copyright (C) 2018-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -23559,15 +24873,15 @@ index 000000000000..d8508f875f28
+#endif /* __AUFS_LCNT_H__ */
diff --git a/fs/aufs/loop.c b/fs/aufs/loop.c
new file mode 100644
-index 000000000000..bfcb9f994c2d
+index 000000000000..383190588595
--- /dev/null
+++ b/fs/aufs/loop.c
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -23713,15 +25027,15 @@ index 000000000000..bfcb9f994c2d
+}
diff --git a/fs/aufs/loop.h b/fs/aufs/loop.h
new file mode 100644
-index 000000000000..7fc394e72d75
+index 000000000000..9726b8354e00
--- /dev/null
+++ b/fs/aufs/loop.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -23811,15 +25125,15 @@ index 000000000000..7bc9eef3ffec
+endif
diff --git a/fs/aufs/module.c b/fs/aufs/module.c
new file mode 100644
-index 000000000000..295736adfc3c
+index 000000000000..c2815fffb5c6
--- /dev/null
+++ b/fs/aufs/module.c
@@ -0,0 +1,273 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -24090,15 +25404,15 @@ index 000000000000..295736adfc3c
+module_exit(aufs_exit);
diff --git a/fs/aufs/module.h b/fs/aufs/module.h
new file mode 100644
-index 000000000000..3036754b90d0
+index 000000000000..a9d21d3e5414
--- /dev/null
+++ b/fs/aufs/module.h
-@@ -0,0 +1,166 @@
+@@ -0,0 +1,180 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -24193,7 +25507,7 @@ index 000000000000..3036754b90d0
+static inline int au_kmidx_sub(size_t sz, size_t new_sz)
+{
+#ifndef CONFIG_SLOB
-+ return kmalloc_index(sz) - kmalloc_index(new_sz);
++ return __kmalloc_index(sz, false) - __kmalloc_index(new_sz, false);
+#else
+ return -1; /* SLOB is untested */
+#endif
@@ -24231,9 +25545,11 @@ index 000000000000..3036754b90d0
+ kmem_cache_create(#type, sizeof(struct type), \
+ __alignof__(struct type), AuCacheFlags, ctor)
+
-+#define AuCacheFuncs(name, index) \
++#define AuCacheFuncAlloc(name, index) \
+ static inline struct au_##name *au_cache_alloc_##name(void) \
-+ { return kmem_cache_alloc(au_cache[AuCache_##index], GFP_NOFS); } \
++ { return kmem_cache_alloc(au_cache[AuCache_##index], GFP_NOFS); }
++
++#define AuCacheFuncs(name, index) \
+ static inline void au_cache_free_##name##_norcu(struct au_##name *p) \
+ { kmem_cache_free(au_cache[AuCache_##index], p); } \
+ \
@@ -24250,27 +25566,39 @@ index 000000000000..3036754b90d0
+ au_cache_free_##name##_rcu(p); }
+
+AuCacheFuncs(dinfo, DINFO);
++AuCacheFuncAlloc(dinfo, DINFO);
++
+AuCacheFuncs(icntnr, ICNTNR);
++static inline struct au_icntnr *au_cache_alloc_icntnr(struct super_block *sb)
++{ return alloc_inode_sb(sb, au_cache[AuCache_ICNTNR], GFP_NOFS); }
++
+AuCacheFuncs(finfo, FINFO);
++AuCacheFuncAlloc(finfo, FINFO);
++
+AuCacheFuncs(vdir, VDIR);
++AuCacheFuncAlloc(vdir, VDIR);
++
+AuCacheFuncs(vdir_dehstr, DEHSTR);
++AuCacheFuncAlloc(vdir_dehstr, DEHSTR);
++
+#ifdef CONFIG_AUFS_HNOTIFY
+AuCacheFuncs(hnotify, HNOTIFY);
++AuCacheFuncAlloc(hnotify, HNOTIFY);
+#endif
+
+#endif /* __KERNEL__ */
+#endif /* __AUFS_MODULE_H__ */
diff --git a/fs/aufs/mvdown.c b/fs/aufs/mvdown.c
new file mode 100644
-index 000000000000..cbac849ead31
+index 000000000000..daafc27e64b0
--- /dev/null
+++ b/fs/aufs/mvdown.c
@@ -0,0 +1,706 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2011-2019 Junjiro R. Okajima
++ * Copyright (C) 2011-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -24974,15 +26302,15 @@ index 000000000000..cbac849ead31
+}
diff --git a/fs/aufs/opts.c b/fs/aufs/opts.c
new file mode 100644
-index 000000000000..77e17d7b3bdf
+index 000000000000..20421440c004
--- /dev/null
+++ b/fs/aufs/opts.c
-@@ -0,0 +1,1880 @@
+@@ -0,0 +1,1032 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -25000,172 +26328,12 @@ index 000000000000..77e17d7b3bdf
+ * mount options/flags
+ */
+
-+#include <linux/namei.h>
+#include <linux/types.h> /* a distribution requires */
+#include <linux/parser.h>
+#include "aufs.h"
+
+/* ---------------------------------------------------------------------- */
+
-+enum {
-+ Opt_br,
-+ Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend,
-+ Opt_idel, Opt_imod,
-+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash,
-+ Opt_rdblk_def, Opt_rdhash_def,
-+ Opt_xino, Opt_noxino,
-+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
-+ Opt_trunc_xino_path, Opt_itrunc_xino,
-+ Opt_trunc_xib, Opt_notrunc_xib,
-+ Opt_shwh, Opt_noshwh,
-+ Opt_plink, Opt_noplink, Opt_list_plink,
-+ Opt_udba,
-+ Opt_dio, Opt_nodio,
-+ Opt_diropq_a, Opt_diropq_w,
-+ Opt_warn_perm, Opt_nowarn_perm,
-+ Opt_wbr_copyup, Opt_wbr_create,
-+ Opt_fhsm_sec,
-+ Opt_verbose, Opt_noverbose,
-+ Opt_sum, Opt_nosum, Opt_wsum,
-+ Opt_dirperm1, Opt_nodirperm1,
-+ Opt_dirren, Opt_nodirren,
-+ Opt_acl, Opt_noacl,
-+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
-+};
-+
-+static match_table_t options = {
-+ {Opt_br, "br=%s"},
-+ {Opt_br, "br:%s"},
-+
-+ {Opt_add, "add=%d:%s"},
-+ {Opt_add, "add:%d:%s"},
-+ {Opt_add, "ins=%d:%s"},
-+ {Opt_add, "ins:%d:%s"},
-+ {Opt_append, "append=%s"},
-+ {Opt_append, "append:%s"},
-+ {Opt_prepend, "prepend=%s"},
-+ {Opt_prepend, "prepend:%s"},
-+
-+ {Opt_del, "del=%s"},
-+ {Opt_del, "del:%s"},
-+ /* {Opt_idel, "idel:%d"}, */
-+ {Opt_mod, "mod=%s"},
-+ {Opt_mod, "mod:%s"},
-+ /* {Opt_imod, "imod:%d:%s"}, */
-+
-+ {Opt_dirwh, "dirwh=%d"},
-+
-+ {Opt_xino, "xino=%s"},
-+ {Opt_noxino, "noxino"},
-+ {Opt_trunc_xino, "trunc_xino"},
-+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
-+ {Opt_notrunc_xino, "notrunc_xino"},
-+ {Opt_trunc_xino_path, "trunc_xino=%s"},
-+ {Opt_itrunc_xino, "itrunc_xino=%d"},
-+ /* {Opt_zxino, "zxino=%s"}, */
-+ {Opt_trunc_xib, "trunc_xib"},
-+ {Opt_notrunc_xib, "notrunc_xib"},
-+
-+#ifdef CONFIG_PROC_FS
-+ {Opt_plink, "plink"},
-+#else
-+ {Opt_ignore_silent, "plink"},
-+#endif
-+
-+ {Opt_noplink, "noplink"},
-+
-+#ifdef CONFIG_AUFS_DEBUG
-+ {Opt_list_plink, "list_plink"},
-+#endif
-+
-+ {Opt_udba, "udba=%s"},
-+
-+ {Opt_dio, "dio"},
-+ {Opt_nodio, "nodio"},
-+
-+#ifdef CONFIG_AUFS_DIRREN
-+ {Opt_dirren, "dirren"},
-+ {Opt_nodirren, "nodirren"},
-+#else
-+ {Opt_ignore, "dirren"},
-+ {Opt_ignore_silent, "nodirren"},
-+#endif
-+
-+#ifdef CONFIG_AUFS_FHSM
-+ {Opt_fhsm_sec, "fhsm_sec=%d"},
-+#else
-+ {Opt_ignore, "fhsm_sec=%d"},
-+#endif
-+
-+ {Opt_diropq_a, "diropq=always"},
-+ {Opt_diropq_a, "diropq=a"},
-+ {Opt_diropq_w, "diropq=whiteouted"},
-+ {Opt_diropq_w, "diropq=w"},
-+
-+ {Opt_warn_perm, "warn_perm"},
-+ {Opt_nowarn_perm, "nowarn_perm"},
-+
-+ /* keep them temporary */
-+ {Opt_ignore_silent, "nodlgt"},
-+ {Opt_ignore, "clean_plink"},
-+
-+#ifdef CONFIG_AUFS_SHWH
-+ {Opt_shwh, "shwh"},
-+#endif
-+ {Opt_noshwh, "noshwh"},
-+
-+ {Opt_dirperm1, "dirperm1"},
-+ {Opt_nodirperm1, "nodirperm1"},
-+
-+ {Opt_verbose, "verbose"},
-+ {Opt_verbose, "v"},
-+ {Opt_noverbose, "noverbose"},
-+ {Opt_noverbose, "quiet"},
-+ {Opt_noverbose, "q"},
-+ {Opt_noverbose, "silent"},
-+
-+ {Opt_sum, "sum"},
-+ {Opt_nosum, "nosum"},
-+ {Opt_wsum, "wsum"},
-+
-+ {Opt_rdcache, "rdcache=%d"},
-+ {Opt_rdblk, "rdblk=%d"},
-+ {Opt_rdblk_def, "rdblk=def"},
-+ {Opt_rdhash, "rdhash=%d"},
-+ {Opt_rdhash_def, "rdhash=def"},
-+
-+ {Opt_wbr_create, "create=%s"},
-+ {Opt_wbr_create, "create_policy=%s"},
-+ {Opt_wbr_copyup, "cpup=%s"},
-+ {Opt_wbr_copyup, "copyup=%s"},
-+ {Opt_wbr_copyup, "copyup_policy=%s"},
-+
-+ /* generic VFS flag */
-+#ifdef CONFIG_FS_POSIX_ACL
-+ {Opt_acl, "acl"},
-+ {Opt_noacl, "noacl"},
-+#else
-+ {Opt_ignore, "acl"},
-+ {Opt_ignore_silent, "noacl"},
-+#endif
-+
-+ /* internal use for the scripts */
-+ {Opt_ignore_silent, "si=%s"},
-+
-+ {Opt_br, "dirs=%s"},
-+ {Opt_ignore, "debug=%d"},
-+ {Opt_ignore, "delete=whiteout"},
-+ {Opt_ignore, "delete=all"},
-+ {Opt_ignore, "imap=%s"},
-+
-+ /* temporary workaround, due to old mount(8)? */
-+ {Opt_ignore_silent, "relatime"},
-+
-+ {Opt_err, NULL}
-+};
-+
-+/* ---------------------------------------------------------------------- */
-+
+static const char *au_parser_pattern(int val, match_table_t tbl)
+{
+ struct match_token *p;
@@ -25297,7 +26465,7 @@ index 000000000000..77e17d7b3bdf
+ return q - str->a;
+}
+
-+static int noinline_for_stack br_perm_val(char *perm)
++int au_br_perm_val(char *perm)
+{
+ int val, bad, sz;
+ char *p;
@@ -25390,7 +26558,7 @@ index 000000000000..77e17d7b3bdf
+ {-1, NULL}
+};
+
-+static int noinline_for_stack udba_val(char *str)
++int au_udba_val(char *str)
+{
+ substring_t args[MAX_OPT_ARGS];
+
@@ -25461,8 +26629,7 @@ index 000000000000..77e17d7b3bdf
+ return err;
+}
+
-+static int noinline_for_stack
-+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
++int au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
+{
+ int err, e;
+ substring_t args[MAX_OPT_ARGS];
@@ -25487,7 +26654,7 @@ index 000000000000..77e17d7b3bdf
+ err = e;
+ break;
+ }
-+ /*FALLTHROUGH*/
++ fallthrough;
+ case AuWbrCreate_MFS:
+ case AuWbrCreate_PMFS:
+ create->mfs_second = AUFS_MFS_DEF_SEC;
@@ -25518,7 +26685,7 @@ index 000000000000..77e17d7b3bdf
+ {-1, NULL}
+};
+
-+static int noinline_for_stack au_wbr_copyup_val(char *str)
++int au_wbr_copyup_val(char *str)
+{
+ substring_t args[MAX_OPT_ARGS];
+
@@ -25532,235 +26699,8 @@ index 000000000000..77e17d7b3bdf
+
+/* ---------------------------------------------------------------------- */
+
-+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
-+
-+static void dump_opts(struct au_opts *opts)
-+{
-+#ifdef CONFIG_AUFS_DEBUG
-+ /* reduce stack space */
-+ union {
-+ struct au_opt_add *add;
-+ struct au_opt_del *del;
-+ struct au_opt_mod *mod;
-+ struct au_opt_xino *xino;
-+ struct au_opt_xino_itrunc *xino_itrunc;
-+ struct au_opt_wbr_create *create;
-+ } u;
-+ struct au_opt *opt;
-+
-+ opt = opts->opt;
-+ while (opt->type != Opt_tail) {
-+ switch (opt->type) {
-+ case Opt_add:
-+ u.add = &opt->add;
-+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
-+ u.add->bindex, u.add->pathname, u.add->perm,
-+ u.add->path.dentry);
-+ break;
-+ case Opt_del:
-+ case Opt_idel:
-+ u.del = &opt->del;
-+ AuDbg("del {%s, %p}\n",
-+ u.del->pathname, u.del->h_path.dentry);
-+ break;
-+ case Opt_mod:
-+ case Opt_imod:
-+ u.mod = &opt->mod;
-+ AuDbg("mod {%s, 0x%x, %p}\n",
-+ u.mod->path, u.mod->perm, u.mod->h_root);
-+ break;
-+ case Opt_append:
-+ u.add = &opt->add;
-+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
-+ u.add->bindex, u.add->pathname, u.add->perm,
-+ u.add->path.dentry);
-+ break;
-+ case Opt_prepend:
-+ u.add = &opt->add;
-+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
-+ u.add->bindex, u.add->pathname, u.add->perm,
-+ u.add->path.dentry);
-+ break;
-+ case Opt_dirwh:
-+ AuDbg("dirwh %d\n", opt->dirwh);
-+ break;
-+ case Opt_rdcache:
-+ AuDbg("rdcache %d\n", opt->rdcache);
-+ break;
-+ case Opt_rdblk:
-+ AuDbg("rdblk %u\n", opt->rdblk);
-+ break;
-+ case Opt_rdblk_def:
-+ AuDbg("rdblk_def\n");
-+ break;
-+ case Opt_rdhash:
-+ AuDbg("rdhash %u\n", opt->rdhash);
-+ break;
-+ case Opt_rdhash_def:
-+ AuDbg("rdhash_def\n");
-+ break;
-+ case Opt_xino:
-+ u.xino = &opt->xino;
-+ AuDbg("xino {%s %pD}\n", u.xino->path, u.xino->file);
-+ break;
-+ case Opt_trunc_xino:
-+ AuLabel(trunc_xino);
-+ break;
-+ case Opt_notrunc_xino:
-+ AuLabel(notrunc_xino);
-+ break;
-+ case Opt_trunc_xino_path:
-+ case Opt_itrunc_xino:
-+ u.xino_itrunc = &opt->xino_itrunc;
-+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
-+ break;
-+ case Opt_noxino:
-+ AuLabel(noxino);
-+ break;
-+ case Opt_trunc_xib:
-+ AuLabel(trunc_xib);
-+ break;
-+ case Opt_notrunc_xib:
-+ AuLabel(notrunc_xib);
-+ break;
-+ case Opt_shwh:
-+ AuLabel(shwh);
-+ break;
-+ case Opt_noshwh:
-+ AuLabel(noshwh);
-+ break;
-+ case Opt_dirperm1:
-+ AuLabel(dirperm1);
-+ break;
-+ case Opt_nodirperm1:
-+ AuLabel(nodirperm1);
-+ break;
-+ case Opt_plink:
-+ AuLabel(plink);
-+ break;
-+ case Opt_noplink:
-+ AuLabel(noplink);
-+ break;
-+ case Opt_list_plink:
-+ AuLabel(list_plink);
-+ break;
-+ case Opt_udba:
-+ AuDbg("udba %d, %s\n",
-+ opt->udba, au_optstr_udba(opt->udba));
-+ break;
-+ case Opt_dio:
-+ AuLabel(dio);
-+ break;
-+ case Opt_nodio:
-+ AuLabel(nodio);
-+ break;
-+ case Opt_diropq_a:
-+ AuLabel(diropq_a);
-+ break;
-+ case Opt_diropq_w:
-+ AuLabel(diropq_w);
-+ break;
-+ case Opt_warn_perm:
-+ AuLabel(warn_perm);
-+ break;
-+ case Opt_nowarn_perm:
-+ AuLabel(nowarn_perm);
-+ break;
-+ case Opt_verbose:
-+ AuLabel(verbose);
-+ break;
-+ case Opt_noverbose:
-+ AuLabel(noverbose);
-+ break;
-+ case Opt_sum:
-+ AuLabel(sum);
-+ break;
-+ case Opt_nosum:
-+ AuLabel(nosum);
-+ break;
-+ case Opt_wsum:
-+ AuLabel(wsum);
-+ break;
-+ case Opt_wbr_create:
-+ u.create = &opt->wbr_create;
-+ AuDbg("create %d, %s\n", u.create->wbr_create,
-+ au_optstr_wbr_create(u.create->wbr_create));
-+ switch (u.create->wbr_create) {
-+ case AuWbrCreate_MFSV:
-+ case AuWbrCreate_PMFSV:
-+ AuDbg("%d sec\n", u.create->mfs_second);
-+ break;
-+ case AuWbrCreate_MFSRR:
-+ case AuWbrCreate_TDMFS:
-+ AuDbg("%llu watermark\n",
-+ u.create->mfsrr_watermark);
-+ break;
-+ case AuWbrCreate_MFSRRV:
-+ case AuWbrCreate_TDMFSV:
-+ case AuWbrCreate_PMFSRRV:
-+ AuDbg("%llu watermark, %d sec\n",
-+ u.create->mfsrr_watermark,
-+ u.create->mfs_second);
-+ break;
-+ }
-+ break;
-+ case Opt_wbr_copyup:
-+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
-+ au_optstr_wbr_copyup(opt->wbr_copyup));
-+ break;
-+ case Opt_fhsm_sec:
-+ AuDbg("fhsm_sec %u\n", opt->fhsm_second);
-+ break;
-+ case Opt_dirren:
-+ AuLabel(dirren);
-+ break;
-+ case Opt_nodirren:
-+ AuLabel(nodirren);
-+ break;
-+ case Opt_acl:
-+ AuLabel(acl);
-+ break;
-+ case Opt_noacl:
-+ AuLabel(noacl);
-+ break;
-+ default:
-+ BUG();
-+ }
-+ opt++;
-+ }
-+#endif
-+}
-+
-+void au_opts_free(struct au_opts *opts)
-+{
-+ struct au_opt *opt;
-+
-+ opt = opts->opt;
-+ while (opt->type != Opt_tail) {
-+ switch (opt->type) {
-+ case Opt_add:
-+ case Opt_append:
-+ case Opt_prepend:
-+ path_put(&opt->add.path);
-+ break;
-+ case Opt_del:
-+ case Opt_idel:
-+ path_put(&opt->del.h_path);
-+ break;
-+ case Opt_mod:
-+ case Opt_imod:
-+ dput(opt->mod.h_root);
-+ break;
-+ case Opt_xino:
-+ fput(opt->xino.file);
-+ break;
-+ }
-+ opt++;
-+ }
-+}
-+
-+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
-+ aufs_bindex_t bindex)
++int au_opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
++ aufs_bindex_t bindex)
+{
+ int err;
+ struct au_opt_add *add = &opt->add;
@@ -25773,10 +26713,10 @@ index 000000000000..77e17d7b3bdf
+ if (p) {
+ *p++ = 0;
+ if (*p)
-+ add->perm = br_perm_val(p);
++ add->perm = au_br_perm_val(p);
+ }
+
-+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
++ err = vfsub_kern_path(add->pathname, AuOpt_LkupDirFlags, &add->path);
+ if (!err) {
+ if (!p) {
+ add->perm = AuBrPerm_RO;
@@ -25795,460 +26735,6 @@ index 000000000000..77e17d7b3bdf
+ return err;
+}
+
-+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
-+{
-+ int err;
-+
-+ del->pathname = args[0].from;
-+ AuDbg("del path %s\n", del->pathname);
-+
-+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
-+ if (unlikely(err))
-+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
-+
-+ return err;
-+}
-+
-+#if 0 /* reserved for future use */
-+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
-+ struct au_opt_del *del, substring_t args[])
-+{
-+ int err;
-+ struct dentry *root;
-+
-+ err = -EINVAL;
-+ root = sb->s_root;
-+ aufs_read_lock(root, AuLock_FLUSH);
-+ if (bindex < 0 || au_sbbot(sb) < bindex) {
-+ pr_err("out of bounds, %d\n", bindex);
-+ goto out;
-+ }
-+
-+ err = 0;
-+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
-+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
-+
-+out:
-+ aufs_read_unlock(root, !AuLock_IR);
-+ return err;
-+}
-+#endif
-+
-+static int noinline_for_stack
-+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
-+{
-+ int err;
-+ struct path path;
-+ char *p;
-+
-+ err = -EINVAL;
-+ mod->path = args[0].from;
-+ p = strchr(mod->path, '=');
-+ if (unlikely(!p)) {
-+ pr_err("no permission %s\n", args[0].from);
-+ goto out;
-+ }
-+
-+ *p++ = 0;
-+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
-+ if (unlikely(err)) {
-+ pr_err("lookup failed %s (%d)\n", mod->path, err);
-+ goto out;
-+ }
-+
-+ mod->perm = br_perm_val(p);
-+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
-+ mod->h_root = dget(path.dentry);
-+ path_put(&path);
-+
-+out:
-+ return err;
-+}
-+
-+#if 0 /* reserved for future use */
-+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
-+ struct au_opt_mod *mod, substring_t args[])
-+{
-+ int err;
-+ struct dentry *root;
-+
-+ err = -EINVAL;
-+ root = sb->s_root;
-+ aufs_read_lock(root, AuLock_FLUSH);
-+ if (bindex < 0 || au_sbbot(sb) < bindex) {
-+ pr_err("out of bounds, %d\n", bindex);
-+ goto out;
-+ }
-+
-+ err = 0;
-+ mod->perm = br_perm_val(args[1].from);
-+ AuDbg("mod path %s, perm 0x%x, %s\n",
-+ mod->path, mod->perm, args[1].from);
-+ mod->h_root = dget(au_h_dptr(root, bindex));
-+
-+out:
-+ aufs_read_unlock(root, !AuLock_IR);
-+ return err;
-+}
-+#endif
-+
-+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
-+ substring_t args[])
-+{
-+ int err;
-+ struct file *file;
-+
-+ file = au_xino_create(sb, args[0].from, /*silent*/0, /*wbrtop*/0);
-+ err = PTR_ERR(file);
-+ if (IS_ERR(file))
-+ goto out;
-+
-+ err = -EINVAL;
-+ if (unlikely(file->f_path.dentry->d_sb == sb)) {
-+ fput(file);
-+ pr_err("%s must be outside\n", args[0].from);
-+ goto out;
-+ }
-+
-+ err = 0;
-+ xino->file = file;
-+ xino->path = args[0].from;
-+
-+out:
-+ return err;
-+}
-+
-+static int noinline_for_stack
-+au_opts_parse_xino_itrunc_path(struct super_block *sb,
-+ struct au_opt_xino_itrunc *xino_itrunc,
-+ substring_t args[])
-+{
-+ int err;
-+ aufs_bindex_t bbot, bindex;
-+ struct path path;
-+ struct dentry *root;
-+
-+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
-+ if (unlikely(err)) {
-+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
-+ goto out;
-+ }
-+
-+ xino_itrunc->bindex = -1;
-+ root = sb->s_root;
-+ aufs_read_lock(root, AuLock_FLUSH);
-+ bbot = au_sbbot(sb);
-+ for (bindex = 0; bindex <= bbot; bindex++) {
-+ if (au_h_dptr(root, bindex) == path.dentry) {
-+ xino_itrunc->bindex = bindex;
-+ break;
-+ }
-+ }
-+ aufs_read_unlock(root, !AuLock_IR);
-+ path_put(&path);
-+
-+ if (unlikely(xino_itrunc->bindex < 0)) {
-+ pr_err("no such branch %s\n", args[0].from);
-+ err = -EINVAL;
-+ }
-+
-+out:
-+ return err;
-+}
-+
-+/* called without aufs lock */
-+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
-+{
-+ int err, n, token;
-+ aufs_bindex_t bindex;
-+ unsigned char skipped;
-+ struct dentry *root;
-+ struct au_opt *opt, *opt_tail;
-+ char *opt_str;
-+ /* reduce the stack space */
-+ union {
-+ struct au_opt_xino_itrunc *xino_itrunc;
-+ struct au_opt_wbr_create *create;
-+ } u;
-+ struct {
-+ substring_t args[MAX_OPT_ARGS];
-+ } *a;
-+
-+ err = -ENOMEM;
-+ a = kmalloc(sizeof(*a), GFP_NOFS);
-+ if (unlikely(!a))
-+ goto out;
-+
-+ root = sb->s_root;
-+ err = 0;
-+ bindex = 0;
-+ opt = opts->opt;
-+ opt_tail = opt + opts->max_opt - 1;
-+ opt->type = Opt_tail;
-+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
-+ err = -EINVAL;
-+ skipped = 0;
-+ token = match_token(opt_str, options, a->args);
-+ switch (token) {
-+ case Opt_br:
-+ err = 0;
-+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
-+ && *opt_str) {
-+ err = opt_add(opt, opt_str, opts->sb_flags,
-+ bindex++);
-+ if (unlikely(!err && ++opt > opt_tail)) {
-+ err = -E2BIG;
-+ break;
-+ }
-+ opt->type = Opt_tail;
-+ skipped = 1;
-+ }
-+ break;
-+ case Opt_add:
-+ if (unlikely(match_int(&a->args[0], &n))) {
-+ pr_err("bad integer in %s\n", opt_str);
-+ break;
-+ }
-+ bindex = n;
-+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
-+ bindex);
-+ if (!err)
-+ opt->type = token;
-+ break;
-+ case Opt_append:
-+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
-+ /*dummy bindex*/1);
-+ if (!err)
-+ opt->type = token;
-+ break;
-+ case Opt_prepend:
-+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
-+ /*bindex*/0);
-+ if (!err)
-+ opt->type = token;
-+ break;
-+ case Opt_del:
-+ err = au_opts_parse_del(&opt->del, a->args);
-+ if (!err)
-+ opt->type = token;
-+ break;
-+#if 0 /* reserved for future use */
-+ case Opt_idel:
-+ del->pathname = "(indexed)";
-+ if (unlikely(match_int(&args[0], &n))) {
-+ pr_err("bad integer in %s\n", opt_str);
-+ break;
-+ }
-+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
-+ if (!err)
-+ opt->type = token;
-+ break;
-+#endif
-+ case Opt_mod:
-+ err = au_opts_parse_mod(&opt->mod, a->args);
-+ if (!err)
-+ opt->type = token;
-+ break;
-+#ifdef IMOD /* reserved for future use */
-+ case Opt_imod:
-+ u.mod->path = "(indexed)";
-+ if (unlikely(match_int(&a->args[0], &n))) {
-+ pr_err("bad integer in %s\n", opt_str);
-+ break;
-+ }
-+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
-+ if (!err)
-+ opt->type = token;
-+ break;
-+#endif
-+ case Opt_xino:
-+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
-+ if (!err)
-+ opt->type = token;
-+ break;
-+
-+ case Opt_trunc_xino_path:
-+ err = au_opts_parse_xino_itrunc_path
-+ (sb, &opt->xino_itrunc, a->args);
-+ if (!err)
-+ opt->type = token;
-+ break;
-+
-+ case Opt_itrunc_xino:
-+ u.xino_itrunc = &opt->xino_itrunc;
-+ if (unlikely(match_int(&a->args[0], &n))) {
-+ pr_err("bad integer in %s\n", opt_str);
-+ break;
-+ }
-+ u.xino_itrunc->bindex = n;
-+ aufs_read_lock(root, AuLock_FLUSH);
-+ if (n < 0 || au_sbbot(sb) < n) {
-+ pr_err("out of bounds, %d\n", n);
-+ aufs_read_unlock(root, !AuLock_IR);
-+ break;
-+ }
-+ aufs_read_unlock(root, !AuLock_IR);
-+ err = 0;
-+ opt->type = token;
-+ break;
-+
-+ case Opt_dirwh:
-+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
-+ break;
-+ err = 0;
-+ opt->type = token;
-+ break;
-+
-+ case Opt_rdcache:
-+ if (unlikely(match_int(&a->args[0], &n))) {
-+ pr_err("bad integer in %s\n", opt_str);
-+ break;
-+ }
-+ if (unlikely(n > AUFS_RDCACHE_MAX)) {
-+ pr_err("rdcache must be smaller than %d\n",
-+ AUFS_RDCACHE_MAX);
-+ break;
-+ }
-+ opt->rdcache = n;
-+ err = 0;
-+ opt->type = token;
-+ break;
-+ case Opt_rdblk:
-+ if (unlikely(match_int(&a->args[0], &n)
-+ || n < 0
-+ || n > KMALLOC_MAX_SIZE)) {
-+ pr_err("bad integer in %s\n", opt_str);
-+ break;
-+ }
-+ if (unlikely(n && n < NAME_MAX)) {
-+ pr_err("rdblk must be larger than %d\n",
-+ NAME_MAX);
-+ break;
-+ }
-+ opt->rdblk = n;
-+ err = 0;
-+ opt->type = token;
-+ break;
-+ case Opt_rdhash:
-+ if (unlikely(match_int(&a->args[0], &n)
-+ || n < 0
-+ || n * sizeof(struct hlist_head)
-+ > KMALLOC_MAX_SIZE)) {
-+ pr_err("bad integer in %s\n", opt_str);
-+ break;
-+ }
-+ opt->rdhash = n;
-+ err = 0;
-+ opt->type = token;
-+ break;
-+
-+ case Opt_trunc_xino:
-+ case Opt_notrunc_xino:
-+ case Opt_noxino:
-+ case Opt_trunc_xib:
-+ case Opt_notrunc_xib:
-+ case Opt_shwh:
-+ case Opt_noshwh:
-+ case Opt_dirperm1:
-+ case Opt_nodirperm1:
-+ case Opt_plink:
-+ case Opt_noplink:
-+ case Opt_list_plink:
-+ case Opt_dio:
-+ case Opt_nodio:
-+ case Opt_diropq_a:
-+ case Opt_diropq_w:
-+ case Opt_warn_perm:
-+ case Opt_nowarn_perm:
-+ case Opt_verbose:
-+ case Opt_noverbose:
-+ case Opt_sum:
-+ case Opt_nosum:
-+ case Opt_wsum:
-+ case Opt_rdblk_def:
-+ case Opt_rdhash_def:
-+ case Opt_dirren:
-+ case Opt_nodirren:
-+ case Opt_acl:
-+ case Opt_noacl:
-+ err = 0;
-+ opt->type = token;
-+ break;
-+
-+ case Opt_udba:
-+ opt->udba = udba_val(a->args[0].from);
-+ if (opt->udba >= 0) {
-+ err = 0;
-+ opt->type = token;
-+ } else
-+ pr_err("wrong value, %s\n", opt_str);
-+ break;
-+
-+ case Opt_wbr_create:
-+ u.create = &opt->wbr_create;
-+ u.create->wbr_create
-+ = au_wbr_create_val(a->args[0].from, u.create);
-+ if (u.create->wbr_create >= 0) {
-+ err = 0;
-+ opt->type = token;
-+ } else
-+ pr_err("wrong value, %s\n", opt_str);
-+ break;
-+ case Opt_wbr_copyup:
-+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
-+ if (opt->wbr_copyup >= 0) {
-+ err = 0;
-+ opt->type = token;
-+ } else
-+ pr_err("wrong value, %s\n", opt_str);
-+ break;
-+
-+ case Opt_fhsm_sec:
-+ if (unlikely(match_int(&a->args[0], &n)
-+ || n < 0)) {
-+ pr_err("bad integer in %s\n", opt_str);
-+ break;
-+ }
-+ if (sysaufs_brs) {
-+ opt->fhsm_second = n;
-+ opt->type = token;
-+ } else
-+ pr_warn("ignored %s\n", opt_str);
-+ err = 0;
-+ break;
-+
-+ case Opt_ignore:
-+ pr_warn("ignored %s\n", opt_str);
-+ /*FALLTHROUGH*/
-+ case Opt_ignore_silent:
-+ skipped = 1;
-+ err = 0;
-+ break;
-+ case Opt_err:
-+ pr_err("unknown option %s\n", opt_str);
-+ break;
-+ }
-+
-+ if (!err && !skipped) {
-+ if (unlikely(++opt > opt_tail)) {
-+ err = -E2BIG;
-+ opt--;
-+ opt->type = Opt_tail;
-+ break;
-+ }
-+ opt->type = Opt_tail;
-+ }
-+ }
-+
-+ au_kfree_rcu(a);
-+ dump_opts(opts);
-+ if (unlikely(err))
-+ au_opts_free(opts);
-+
-+out:
-+ return err;
-+}
-+
+static int au_opt_wbr_create(struct super_block *sb,
+ struct au_opt_wbr_create *create)
+{
@@ -26275,7 +26761,7 @@ index 000000000000..77e17d7b3bdf
+ case AuWbrCreate_PMFSRR:
+ case AuWbrCreate_PMFSRRV:
+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
-+ /*FALLTHROUGH*/
++ fallthrough;
+ case AuWbrCreate_MFS:
+ case AuWbrCreate_MFSV:
+ case AuWbrCreate_PMFS:
@@ -26314,12 +26800,13 @@ index 000000000000..77e17d7b3bdf
+ break;
+
+ case Opt_plink:
-+ au_opt_set(sbinfo->si_mntflags, PLINK);
-+ break;
-+ case Opt_noplink:
-+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
-+ au_plink_put(sb, /*verbose*/1);
-+ au_opt_clr(sbinfo->si_mntflags, PLINK);
++ if (opt->tf)
++ au_opt_set(sbinfo->si_mntflags, PLINK);
++ else {
++ if (au_opt_test(sbinfo->si_mntflags, PLINK))
++ au_plink_put(sb, /*verbose*/1);
++ au_opt_clr(sbinfo->si_mntflags, PLINK);
++ }
+ break;
+ case Opt_list_plink:
+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
@@ -26327,12 +26814,13 @@ index 000000000000..77e17d7b3bdf
+ break;
+
+ case Opt_dio:
-+ au_opt_set(sbinfo->si_mntflags, DIO);
-+ au_fset_opts(opts->flags, REFRESH_DYAOP);
-+ break;
-+ case Opt_nodio:
-+ au_opt_clr(sbinfo->si_mntflags, DIO);
-+ au_fset_opts(opts->flags, REFRESH_DYAOP);
++ if (opt->tf) {
++ au_opt_set(sbinfo->si_mntflags, DIO);
++ au_fset_opts(opts->flags, REFRESH_DYAOP);
++ } else {
++ au_opt_clr(sbinfo->si_mntflags, DIO);
++ au_fset_opts(opts->flags, REFRESH_DYAOP);
++ }
+ break;
+
+ case Opt_fhsm_sec:
@@ -26347,30 +26835,31 @@ index 000000000000..77e17d7b3bdf
+ break;
+
+ case Opt_warn_perm:
-+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
-+ break;
-+ case Opt_nowarn_perm:
-+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
++ if (opt->tf)
++ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
++ else
++ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
+ break;
+
+ case Opt_verbose:
-+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
-+ break;
-+ case Opt_noverbose:
-+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
++ if (opt->tf)
++ au_opt_set(sbinfo->si_mntflags, VERBOSE);
++ else
++ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
+ break;
+
+ case Opt_sum:
-+ au_opt_set(sbinfo->si_mntflags, SUM);
++ if (opt->tf)
++ au_opt_set(sbinfo->si_mntflags, SUM);
++ else {
++ au_opt_clr(sbinfo->si_mntflags, SUM);
++ au_opt_clr(sbinfo->si_mntflags, SUM_W);
++ }
+ break;
+ case Opt_wsum:
+ au_opt_clr(sbinfo->si_mntflags, SUM);
+ au_opt_set(sbinfo->si_mntflags, SUM_W);
+ break;
-+ case Opt_nosum:
-+ au_opt_clr(sbinfo->si_mntflags, SUM);
-+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
-+ break;
+
+ case Opt_wbr_create:
+ err = au_opt_wbr_create(sb, &opt->wbr_create);
@@ -26391,35 +26880,29 @@ index 000000000000..77e17d7b3bdf
+ case Opt_rdblk:
+ sbinfo->si_rdblk = opt->rdblk;
+ break;
-+ case Opt_rdblk_def:
-+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
-+ break;
+ case Opt_rdhash:
+ sbinfo->si_rdhash = opt->rdhash;
+ break;
-+ case Opt_rdhash_def:
-+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
-+ break;
+
+ case Opt_shwh:
-+ au_opt_set(sbinfo->si_mntflags, SHWH);
-+ break;
-+ case Opt_noshwh:
-+ au_opt_clr(sbinfo->si_mntflags, SHWH);
++ if (opt->tf)
++ au_opt_set(sbinfo->si_mntflags, SHWH);
++ else
++ au_opt_clr(sbinfo->si_mntflags, SHWH);
+ break;
+
+ case Opt_dirperm1:
-+ au_opt_set(sbinfo->si_mntflags, DIRPERM1);
-+ break;
-+ case Opt_nodirperm1:
-+ au_opt_clr(sbinfo->si_mntflags, DIRPERM1);
++ if (opt->tf)
++ au_opt_set(sbinfo->si_mntflags, DIRPERM1);
++ else
++ au_opt_clr(sbinfo->si_mntflags, DIRPERM1);
+ break;
+
+ case Opt_trunc_xino:
-+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
-+ break;
-+ case Opt_notrunc_xino:
-+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
++ if (opt->tf)
++ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
++ else
++ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
+ break;
+
+ case Opt_trunc_xino_path:
@@ -26431,39 +26914,39 @@ index 000000000000..77e17d7b3bdf
+ break;
+
+ case Opt_trunc_xib:
-+ au_fset_opts(opts->flags, TRUNC_XIB);
-+ break;
-+ case Opt_notrunc_xib:
-+ au_fclr_opts(opts->flags, TRUNC_XIB);
++ if (opt->tf)
++ au_fset_opts(opts->flags, TRUNC_XIB);
++ else
++ au_fclr_opts(opts->flags, TRUNC_XIB);
+ break;
+
+ case Opt_dirren:
+ err = 1;
-+ if (!au_opt_test(sbinfo->si_mntflags, DIRREN)) {
-+ err = au_dr_opt_set(sb);
-+ if (!err)
-+ err = 1;
-+ }
-+ if (err == 1)
-+ au_opt_set(sbinfo->si_mntflags, DIRREN);
-+ break;
-+ case Opt_nodirren:
-+ err = 1;
-+ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) {
-+ err = au_dr_opt_clr(sb, au_ftest_opts(opts->flags,
-+ DR_FLUSHED));
-+ if (!err)
-+ err = 1;
++ if (opt->tf) {
++ if (!au_opt_test(sbinfo->si_mntflags, DIRREN)) {
++ err = au_dr_opt_set(sb);
++ if (!err)
++ err = 1;
++ }
++ if (err == 1)
++ au_opt_set(sbinfo->si_mntflags, DIRREN);
++ } else {
++ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) {
++ err = au_dr_opt_clr(sb, au_ftest_opts(opts->flags,
++ DR_FLUSHED));
++ if (!err)
++ err = 1;
++ }
++ if (err == 1)
++ au_opt_clr(sbinfo->si_mntflags, DIRREN);
+ }
-+ if (err == 1)
-+ au_opt_clr(sbinfo->si_mntflags, DIRREN);
+ break;
+
+ case Opt_acl:
-+ sb->s_flags |= SB_POSIXACL;
-+ break;
-+ case Opt_noacl:
-+ sb->s_flags &= ~SB_POSIXACL;
++ if (opt->tf)
++ sb->s_flags |= SB_POSIXACL;
++ else
++ sb->s_flags &= ~SB_POSIXACL;
+ break;
+
+ default:
@@ -26495,7 +26978,7 @@ index 000000000000..77e17d7b3bdf
+ /* Always goto add, not fallthrough */
+ case Opt_prepend:
+ opt->add.bindex = 0;
-+ /* fallthrough */
++ fallthrough;
+ add: /* indented label */
+ case Opt_add:
+ err = au_br_add(sb, &opt->add,
@@ -26543,12 +27026,9 @@ index 000000000000..77e17d7b3bdf
+ case Opt_xino:
+ err = au_xino_set(sb, &opt->xino,
+ !!au_ftest_opts(opts->flags, REMOUNT));
-+ if (unlikely(err))
-+ break;
-+
-+ *opt_xino = &opt->xino;
++ if (!err)
++ *opt_xino = &opt->xino;
+ break;
-+
+ case Opt_noxino:
+ au_xino_clr(sb);
+ *opt_xino = (void *)-1;
@@ -26607,7 +27087,7 @@ index 000000000000..77e17d7b3bdf
+ if ((br->br_perm & AuBrAttr_ICEX)
+ && !h_dir->i_op->listxattr)
+ br->br_perm &= ~AuBrAttr_ICEX;
-+#if 0
++#if 0 /* untested */
+ if ((br->br_perm & AuBrAttr_ICEX_SEC)
+ && (au_br_sb(br)->s_flags & SB_NOSEC))
+ br->br_perm &= ~AuBrAttr_ICEX_SEC;
@@ -26860,15 +27340,15 @@ index 000000000000..77e17d7b3bdf
+}
diff --git a/fs/aufs/opts.h b/fs/aufs/opts.h
new file mode 100644
-index 000000000000..6326b54340c7
+index 000000000000..d8bbdbf0560a
--- /dev/null
+++ b/fs/aufs/opts.h
-@@ -0,0 +1,225 @@
+@@ -0,0 +1,263 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -26891,9 +27371,34 @@ index 000000000000..6326b54340c7
+
+#ifdef __KERNEL__
+
++#include <linux/fs_parser.h>
++#include <linux/namei.h>
+#include <linux/path.h>
+
-+struct file;
++enum {
++ Opt_br,
++ Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend,
++ Opt_idel, Opt_imod,
++ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash,
++ Opt_xino, Opt_noxino,
++ Opt_trunc_xino, Opt_trunc_xino_v,
++ Opt_trunc_xino_path, Opt_itrunc_xino,
++ Opt_trunc_xib,
++ Opt_shwh,
++ Opt_plink, Opt_list_plink,
++ Opt_udba,
++ Opt_dio,
++ Opt_diropq, Opt_diropq_a, Opt_diropq_w,
++ Opt_warn_perm,
++ Opt_wbr_copyup, Opt_wbr_create,
++ Opt_fhsm_sec,
++ Opt_verbose, Opt_noverbose,
++ Opt_sum, Opt_wsum,
++ Opt_dirperm1,
++ Opt_dirren,
++ Opt_acl,
++ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
++};
+
+/* ---------------------------------------------------------------------- */
+
@@ -26938,6 +27443,8 @@ index 000000000000..6326b54340c7
+ | AuOpt_UDBA_REVAL \
+ | AuOpt_UDBA_HNOTIFY)
+
++#define AuOpt_LkupDirFlags (LOOKUP_FOLLOW | LOOKUP_DIRECTORY)
++
+#define au_opt_test(flags, name) (flags & AuOpt_##name)
+#define au_opt_set(flags, name) do { \
+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
@@ -26990,6 +27497,8 @@ index 000000000000..6326b54340c7
+
+/* ---------------------------------------------------------------------- */
+
++struct file;
++
+struct au_opt_add {
+ aufs_bindex_t bindex;
+ char *pathname;
@@ -27039,6 +27548,7 @@ index 000000000000..6326b54340c7
+ struct au_opt_wbr_create wbr_create;
+ int wbr_copyup;
+ unsigned int fhsm_second;
++ bool tf; /* generic flag, true or false */
+ };
+};
+
@@ -27072,14 +27582,18 @@ index 000000000000..6326b54340c7
+/* ---------------------------------------------------------------------- */
+
+/* opts.c */
++int au_br_perm_val(char *perm);
+void au_optstr_br_perm(au_br_perm_str_t *str, int perm);
++int au_udba_val(char *str);
+const char *au_optstr_udba(int udba);
-+const char *au_optstr_wbr_copyup(int wbr_copyup);
++int au_wbr_create_val(char *str, struct au_opt_wbr_create *create);
+const char *au_optstr_wbr_create(int wbr_create);
++int au_wbr_copyup_val(char *str);
++const char *au_optstr_wbr_copyup(int wbr_copyup);
+
-+void au_opts_free(struct au_opts *opts);
++int au_opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
++ aufs_bindex_t bindex);
+struct super_block;
-+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
+ unsigned int pending);
+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
@@ -27087,19 +27601,23 @@ index 000000000000..6326b54340c7
+
+unsigned int au_opt_udba(struct super_block *sb);
+
++/* fsctx.c */
++int aufs_fsctx_init(struct fs_context *fc);
++extern const struct fs_parameter_spec aufs_fsctx_paramspec[];
++
+#endif /* __KERNEL__ */
+#endif /* __AUFS_OPTS_H__ */
diff --git a/fs/aufs/plink.c b/fs/aufs/plink.c
new file mode 100644
-index 000000000000..718edb8827a3
+index 000000000000..5f9a5b50dcc6
--- /dev/null
+++ b/fs/aufs/plink.c
@@ -0,0 +1,516 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -27303,35 +27821,35 @@ index 000000000000..718edb8827a3
+struct au_do_plink_lkup_args {
+ struct dentry **errp;
+ struct qstr *tgtname;
-+ struct dentry *h_parent;
-+ struct au_branch *br;
++ struct path *h_ppath;
+};
+
+static struct dentry *au_do_plink_lkup(struct qstr *tgtname,
-+ struct dentry *h_parent,
-+ struct au_branch *br)
++ struct path *h_ppath)
+{
+ struct dentry *h_dentry;
+ struct inode *h_inode;
+
-+ h_inode = d_inode(h_parent);
++ h_inode = d_inode(h_ppath->dentry);
+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD2);
-+ h_dentry = vfsub_lkup_one(tgtname, h_parent);
++ h_dentry = vfsub_lkup_one(tgtname, h_ppath);
+ inode_unlock_shared(h_inode);
++
+ return h_dentry;
+}
+
+static void au_call_do_plink_lkup(void *args)
+{
+ struct au_do_plink_lkup_args *a = args;
-+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br);
++ *a->errp = au_do_plink_lkup(a->tgtname, a->h_ppath);
+}
+
+/* lookup the plink-ed @inode under the branch at @bindex */
+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
+{
-+ struct dentry *h_dentry, *h_parent;
++ struct dentry *h_dentry;
+ struct au_branch *br;
++ struct path h_ppath;
+ int wkq_err;
+ char a[PLINK_NAME_LEN];
+ struct qstr tgtname = QSTR_INIT(a, 0);
@@ -27339,40 +27857,39 @@ index 000000000000..718edb8827a3
+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
+
+ br = au_sbr(inode->i_sb, bindex);
-+ h_parent = br->br_wbr->wbr_plink;
++ h_ppath.dentry = br->br_wbr->wbr_plink;
++ h_ppath.mnt = au_br_mnt(br);
+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
+
+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) {
+ struct au_do_plink_lkup_args args = {
+ .errp = &h_dentry,
+ .tgtname = &tgtname,
-+ .h_parent = h_parent,
-+ .br = br
++ .h_ppath = &h_ppath
+ };
+
+ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args);
+ if (unlikely(wkq_err))
+ h_dentry = ERR_PTR(wkq_err);
+ } else
-+ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br);
++ h_dentry = au_do_plink_lkup(&tgtname, &h_ppath);
+
+ return h_dentry;
+}
+
+/* create a pseudo-link */
-+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
-+ struct dentry *h_dentry, struct au_branch *br)
++static int do_whplink(struct qstr *tgt, struct path *h_ppath,
++ struct dentry *h_dentry)
+{
+ int err;
-+ struct path h_path = {
-+ .mnt = au_br_mnt(br)
-+ };
++ struct path h_path;
+ struct inode *h_dir, *delegated;
+
-+ h_dir = d_inode(h_parent);
++ h_dir = d_inode(h_ppath->dentry);
+ inode_lock_nested(h_dir, AuLsc_I_CHILD2);
++ h_path.mnt = h_ppath->mnt;
+again:
-+ h_path.dentry = vfsub_lkup_one(tgt, h_parent);
++ h_path.dentry = vfsub_lkup_one(tgt, h_ppath);
+ err = PTR_ERR(h_path.dentry);
+ if (IS_ERR(h_path.dentry))
+ goto out;
@@ -27413,28 +27930,30 @@ index 000000000000..718edb8827a3
+struct do_whplink_args {
+ int *errp;
+ struct qstr *tgt;
-+ struct dentry *h_parent;
++ struct path *h_ppath;
+ struct dentry *h_dentry;
-+ struct au_branch *br;
+};
+
+static void call_do_whplink(void *args)
+{
+ struct do_whplink_args *a = args;
-+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
++ *a->errp = do_whplink(a->tgt, a->h_ppath, a->h_dentry);
+}
+
+static int whplink(struct dentry *h_dentry, struct inode *inode,
-+ aufs_bindex_t bindex, struct au_branch *br)
++ aufs_bindex_t bindex)
+{
+ int err, wkq_err;
++ struct au_branch *br;
+ struct au_wbr *wbr;
-+ struct dentry *h_parent;
++ struct path h_ppath;
+ char a[PLINK_NAME_LEN];
+ struct qstr tgtname = QSTR_INIT(a, 0);
+
-+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
-+ h_parent = wbr->wbr_plink;
++ br = au_sbr(inode->i_sb, bindex);
++ wbr = br->br_wbr;
++ h_ppath.dentry = wbr->wbr_plink;
++ h_ppath.mnt = au_br_mnt(br);
+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
+
+ /* always superio. */
@@ -27442,15 +27961,14 @@ index 000000000000..718edb8827a3
+ struct do_whplink_args args = {
+ .errp = &err,
+ .tgt = &tgtname,
-+ .h_parent = h_parent,
-+ .h_dentry = h_dentry,
-+ .br = br
++ .h_ppath = &h_ppath,
++ .h_dentry = h_dentry
+ };
+ wkq_err = au_wkq_wait(call_do_whplink, &args);
+ if (unlikely(wkq_err))
+ err = wkq_err;
+ } else
-+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
++ err = do_whplink(&tgtname, &h_ppath, h_dentry);
+
+ return err;
+}
@@ -27500,7 +28018,7 @@ index 000000000000..718edb8827a3
+ if (cnt > AUFS_PLINK_WARN)
+ AuWarn1(msg ", %d\n", cnt);
+#undef msg
-+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
++ err = whplink(h_dentry, inode, bindex);
+ if (unlikely(err)) {
+ pr_warn("err %d, damaged pseudo link.\n", err);
+ au_hbl_del(&icntnr->plink, hbl);
@@ -27613,15 +28131,15 @@ index 000000000000..718edb8827a3
+}
diff --git a/fs/aufs/poll.c b/fs/aufs/poll.c
new file mode 100644
-index 000000000000..c48c6cb6491f
+index 000000000000..83defa454c8e
--- /dev/null
+++ b/fs/aufs/poll.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -27670,15 +28188,15 @@ index 000000000000..c48c6cb6491f
+}
diff --git a/fs/aufs/posix_acl.c b/fs/aufs/posix_acl.c
new file mode 100644
-index 000000000000..3c8f9a222ed8
+index 000000000000..03742bcc6603
--- /dev/null
+++ b/fs/aufs/posix_acl.c
-@@ -0,0 +1,105 @@
+@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2014-2019 Junjiro R. Okajima
++ * Copyright (C) 2014-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -27699,7 +28217,7 @@ index 000000000000..3c8f9a222ed8
+#include <linux/fs.h>
+#include "aufs.h"
+
-+struct posix_acl *aufs_get_acl(struct inode *inode, int type)
++struct posix_acl *aufs_get_inode_acl(struct inode *inode, int type, bool rcu)
+{
+ struct posix_acl *acl;
+ int err;
@@ -27707,12 +28225,16 @@ index 000000000000..3c8f9a222ed8
+ struct inode *h_inode;
+ struct super_block *sb;
+
++ acl = ERR_PTR(-ECHILD);
++ if (rcu)
++ goto out;
++
+ acl = NULL;
+ sb = inode->i_sb;
+ si_read_lock(sb, AuLock_FLUSH);
+ ii_read_lock_child(inode);
+ if (!(sb->s_flags & SB_POSIXACL))
-+ goto out;
++ goto unlock;
+
+ bindex = au_ibtop(inode);
+ h_inode = au_h_iptr(inode, bindex);
@@ -27721,29 +28243,43 @@ index 000000000000..3c8f9a222ed8
+ != (inode->i_mode & S_IFMT)))) {
+ err = au_busy_or_stale();
+ acl = ERR_PTR(err);
-+ goto out;
++ goto unlock;
+ }
+
+ /* always topmost only */
-+ acl = get_acl(h_inode, type);
++ acl = get_inode_acl(h_inode, type);
+ if (IS_ERR(acl))
+ forget_cached_acl(inode, type);
+ else
+ set_cached_acl(inode, type, acl);
+
-+out:
++unlock:
+ ii_read_unlock(inode);
+ si_read_unlock(sb);
+
++out:
+ AuTraceErrPtr(acl);
+ return acl;
+}
+
-+int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
++struct posix_acl *aufs_get_acl(struct mnt_idmap *idmap,
++ struct dentry *dentry, int type)
++{
++ struct posix_acl *acl;
++ struct inode *inode;
++
++ inode = d_inode(dentry);
++ acl = aufs_get_inode_acl(inode, type, /*rcu*/false);
++
++ return acl;
++}
++
++int aufs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
++ struct posix_acl *acl, int type)
+{
+ int err;
+ ssize_t ssz;
-+ struct dentry *dentry;
++ struct inode *inode;
+ struct au_sxattr arg = {
+ .type = AU_ACL_SET,
+ .u.acl_set = {
@@ -27752,44 +28288,29 @@ index 000000000000..3c8f9a222ed8
+ },
+ };
+
++ inode = d_inode(dentry);
+ IMustLock(inode);
+
-+ if (inode->i_ino == AUFS_ROOT_INO)
-+ dentry = dget(inode->i_sb->s_root);
-+ else {
-+ dentry = d_find_alias(inode);
-+ if (!dentry)
-+ dentry = d_find_any_alias(inode);
-+ if (!dentry) {
-+ pr_warn("cannot handle this inode, "
-+ "please report to aufs-users ML\n");
-+ err = -ENOENT;
-+ goto out;
-+ }
-+ }
-+
+ ssz = au_sxattr(dentry, inode, &arg);
+ /* forget even it if succeeds since the branch might set differently */
+ forget_cached_acl(inode, type);
-+ dput(dentry);
+ err = ssz;
+ if (ssz >= 0)
+ err = 0;
+
-+out:
+ return err;
+}
diff --git a/fs/aufs/procfs.c b/fs/aufs/procfs.c
new file mode 100644
-index 000000000000..582dd486fcd3
+index 000000000000..0fca104ac554
--- /dev/null
+++ b/fs/aufs/procfs.c
-@@ -0,0 +1,171 @@
+@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2010-2019 Junjiro R. Okajima
++ * Copyright (C) 2010-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -27916,10 +28437,9 @@ index 000000000000..582dd486fcd3
+ return err;
+}
+
-+static const struct file_operations au_procfs_plm_fop = {
-+ .write = au_procfs_plm_write,
-+ .release = au_procfs_plm_release,
-+ .owner = THIS_MODULE
++static const struct proc_ops au_procfs_plm_op = {
++ .proc_write = au_procfs_plm_write,
++ .proc_release = au_procfs_plm_release
+};
+
+/* ---------------------------------------------------------------------- */
@@ -27943,7 +28463,7 @@ index 000000000000..582dd486fcd3
+ goto out;
+
+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | 0200,
-+ au_procfs_dir, &au_procfs_plm_fop);
++ au_procfs_dir, &au_procfs_plm_op);
+ if (unlikely(!entry))
+ goto out_dir;
+
@@ -27958,15 +28478,15 @@ index 000000000000..582dd486fcd3
+}
diff --git a/fs/aufs/rdu.c b/fs/aufs/rdu.c
new file mode 100644
-index 000000000000..3805e79627eb
+index 000000000000..144251c02c3f
--- /dev/null
+++ b/fs/aufs/rdu.c
@@ -0,0 +1,384 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -28009,8 +28529,8 @@ index 000000000000..3805e79627eb
+ int err;
+};
+
-+static int au_rdu_fill(struct dir_context *ctx, const char *name, int nlen,
-+ loff_t offset, u64 h_ino, unsigned int d_type)
++static bool au_rdu_fill(struct dir_context *ctx, const char *name, int nlen,
++ loff_t offset, u64 h_ino, unsigned int d_type)
+{
+ int err, len;
+ struct au_rdu_arg *arg = container_of(ctx, struct au_rdu_arg, ctx);
@@ -28051,7 +28571,7 @@ index 000000000000..3805e79627eb
+
+out:
+ /* AuTraceErr(err); */
-+ return err;
++ return !err;
+}
+
+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
@@ -28114,7 +28634,7 @@ index 000000000000..3805e79627eb
+ arg.end += rdu->sz;
+
+ err = -ENOTDIR;
-+ if (unlikely(!file->f_op->iterate && !file->f_op->iterate_shared))
++ if (unlikely(!file->f_op->iterate_shared))
+ goto out;
+
+ err = security_file_permission(file, MAY_READ);
@@ -28348,15 +28868,15 @@ index 000000000000..3805e79627eb
+#endif
diff --git a/fs/aufs/rwsem.h b/fs/aufs/rwsem.h
new file mode 100644
-index 000000000000..2f8988fa1bda
+index 000000000000..9d9cd50ef155
--- /dev/null
+++ b/fs/aufs/rwsem.h
-@@ -0,0 +1,73 @@
+@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -28386,19 +28906,31 @@ index 000000000000..2f8988fa1bda
+
+/* to debug easier, do not make them inlined functions */
+#define AuRwMustNoWaiters(rw) AuDebugOn(rwsem_is_contended(rw))
++
++#ifdef CONFIG_LOCKDEP
+/* rwsem_is_locked() is unusable */
-+#define AuRwMustReadLock(rw) AuDebugOn(!lockdep_recursing(current) \
-+ && debug_locks \
++#define AuRwMustReadLock(rw) AuDebugOn(IS_ENABLED(CONFIG_LOCKDEP) \
++ && !lockdep_recursing(current) \
++ && debug_locks \
+ && !lockdep_is_held_type(rw, 1))
-+#define AuRwMustWriteLock(rw) AuDebugOn(!lockdep_recursing(current) \
-+ && debug_locks \
++#define AuRwMustWriteLock(rw) AuDebugOn(IS_ENABLED(CONFIG_LOCKDEP) \
++ && !lockdep_recursing(current) \
++ && debug_locks \
+ && !lockdep_is_held_type(rw, 0))
-+#define AuRwMustAnyLock(rw) AuDebugOn(!lockdep_recursing(current) \
-+ && debug_locks \
++#define AuRwMustAnyLock(rw) AuDebugOn(IS_ENABLED(CONFIG_LOCKDEP) \
++ && !lockdep_recursing(current) \
++ && debug_locks \
+ && !lockdep_is_held(rw))
-+#define AuRwDestroy(rw) AuDebugOn(!lockdep_recursing(current) \
-+ && debug_locks \
++#define AuRwDestroy(rw) AuDebugOn(IS_ENABLED(CONFIG_LOCKDEP) \
++ && !lockdep_recursing(current) \
++ && debug_locks \
+ && lockdep_is_held(rw))
++#else
++#define AuRwMustReadLock(rw) do {} while (0)
++#define AuRwMustWriteLock(rw) do {} while (0)
++#define AuRwMustAnyLock(rw) do {} while (0)
++#define AuRwDestroy(rw) do {} while (0)
++#endif
+
+#define au_rw_init(rw) init_rwsem(rw)
+
@@ -28427,15 +28959,15 @@ index 000000000000..2f8988fa1bda
+#endif /* __AUFS_RWSEM_H__ */
diff --git a/fs/aufs/sbinfo.c b/fs/aufs/sbinfo.c
new file mode 100644
-index 000000000000..500a920b4ea1
+index 000000000000..dde9f9c17b18
--- /dev/null
+++ b/fs/aufs/sbinfo.c
-@@ -0,0 +1,314 @@
+@@ -0,0 +1,316 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -28489,10 +29021,10 @@ index 000000000000..500a920b4ea1
+ au_kfree_rcu(sbinfo);
+}
+
-+int au_si_alloc(struct super_block *sb)
++struct au_sbinfo *au_si_alloc(struct super_block *sb)
+{
-+ int err, i;
+ struct au_sbinfo *sbinfo;
++ int err, i;
+
+ err = -ENOMEM;
+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
@@ -28557,16 +29089,18 @@ index 000000000000..500a920b4ea1
+
+ /* leave other members for sysaufs and si_mnt. */
+ sbinfo->si_sb = sb;
-+ sb->s_fs_info = sbinfo;
-+ si_pid_set(sb);
-+ return 0; /* success */
++ if (sb) {
++ sb->s_fs_info = sbinfo;
++ si_pid_set(sb);
++ }
++ return sbinfo; /* success */
+
+out_br:
+ au_kfree_try_rcu(sbinfo->si_branch);
+out_sbinfo:
+ au_kfree_rcu(sbinfo);
+out:
-+ return err;
++ return ERR_PTR(err);
+}
+
+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink)
@@ -28747,15 +29281,15 @@ index 000000000000..500a920b4ea1
+}
diff --git a/fs/aufs/super.c b/fs/aufs/super.c
new file mode 100644
-index 000000000000..44ee4685b218
+index 000000000000..77c6d90808bb
--- /dev/null
+++ b/fs/aufs/super.c
-@@ -0,0 +1,1047 @@
+@@ -0,0 +1,871 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -28787,7 +29321,7 @@ index 000000000000..44ee4685b218
+{
+ struct au_icntnr *c;
+
-+ c = au_cache_alloc_icntnr();
++ c = au_cache_alloc_icntnr(sb);
+ if (c) {
+ au_icntnr_init(c);
+ inode_set_iversion(&c->vfs_inode, 1); /* sigen(sb); */
@@ -28870,7 +29404,7 @@ index 000000000000..44ee4685b218
+ return err;
+}
+
-+static void au_gen_fmt(char *fmt, int len __maybe_unused, const char *pat,
++static void au_gen_fmt(char *fmt, int len, const char *pat,
+ const char *append)
+{
+ char *p;
@@ -28879,7 +29413,7 @@ index 000000000000..44ee4685b218
+ while (*pat != ':')
+ *p++ = *pat++;
+ *p++ = *pat++;
-+ strcpy(p, append);
++ strscpy(p, append, len - (p - fmt));
+ AuDebugOn(strlen(fmt) >= len);
+}
+
@@ -28999,7 +29533,7 @@ index 000000000000..44ee4685b218
+ sb = dentry->d_sb;
+ if (sb->s_flags & SB_POSIXACL)
+ seq_puts(m, ",acl");
-+#if 0
++#if 0 /* reserved for future use */
+ if (sb->s_flags & SB_I_VERSION)
+ seq_puts(m, ",i_version");
+#endif
@@ -29206,7 +29740,7 @@ index 000000000000..44ee4685b218
+ continue;
+
+ h_sb = au_sbr_sb(sb, bindex);
-+ e = vfsub_sync_filesystem(h_sb, wait);
++ e = vfsub_sync_filesystem(h_sb);
+ if (unlikely(e && !err))
+ err = e;
+ /* go on even if an error happens */
@@ -29454,7 +29988,7 @@ index 000000000000..44ee4685b218
+ return err;
+}
+
-+static void au_remount_refresh(struct super_block *sb, unsigned int do_idop)
++void au_remount_refresh(struct super_block *sb, unsigned int do_idop)
+{
+ int err, e;
+ unsigned int udba;
@@ -29515,92 +30049,7 @@ index 000000000000..44ee4685b218
+ AuIOErr("refresh failed, ignored, %d\n", err);
+}
+
-+/* stop extra interpretation of errno in mount(8), and strange error messages */
-+static int cvt_err(int err)
-+{
-+ AuTraceErr(err);
-+
-+ switch (err) {
-+ case -ENOENT:
-+ case -ENOTDIR:
-+ case -EEXIST:
-+ case -EIO:
-+ err = -EINVAL;
-+ }
-+ return err;
-+}
-+
-+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
-+{
-+ int err, do_dx;
-+ unsigned int mntflags;
-+ struct au_opts opts = {
-+ .opt = NULL
-+ };
-+ struct dentry *root;
-+ struct inode *inode;
-+ struct au_sbinfo *sbinfo;
-+
-+ err = 0;
-+ root = sb->s_root;
-+ if (!data || !*data) {
-+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
-+ if (!err) {
-+ di_write_lock_child(root);
-+ err = au_opts_verify(sb, *flags, /*pending*/0);
-+ aufs_write_unlock(root);
-+ }
-+ goto out;
-+ }
-+
-+ err = -ENOMEM;
-+ opts.opt = (void *)__get_free_page(GFP_NOFS);
-+ if (unlikely(!opts.opt))
-+ goto out;
-+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
-+ opts.flags = AuOpts_REMOUNT;
-+ opts.sb_flags = *flags;
-+
-+ /* parse it before aufs lock */
-+ err = au_opts_parse(sb, data, &opts);
-+ if (unlikely(err))
-+ goto out_opts;
-+
-+ sbinfo = au_sbi(sb);
-+ inode = d_inode(root);
-+ inode_lock(inode);
-+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
-+ if (unlikely(err))
-+ goto out_mtx;
-+ di_write_lock_child(root);
-+
-+ /* au_opts_remount() may return an error */
-+ err = au_opts_remount(sb, &opts);
-+ au_opts_free(&opts);
-+
-+ if (au_ftest_opts(opts.flags, REFRESH))
-+ au_remount_refresh(sb, au_ftest_opts(opts.flags, REFRESH_IDOP));
-+
-+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
-+ mntflags = au_mntflags(sb);
-+ do_dx = !!au_opt_test(mntflags, DIO);
-+ au_dy_arefresh(do_dx);
-+ }
-+
-+ au_fhsm_wrote_all(sb, /*force*/1); /* ?? */
-+ aufs_write_unlock(root);
-+
-+out_mtx:
-+ inode_unlock(inode);
-+out_opts:
-+ free_page((unsigned long)opts.opt);
-+out:
-+ err = cvt_err(err);
-+ AuTraceErr(err);
-+ return err;
-+}
-+
-+static const struct super_operations aufs_sop = {
++const struct super_operations aufs_sop = {
+ .alloc_inode = aufs_alloc_inode,
+ .destroy_inode = aufs_destroy_inode,
+ .free_inode = aufs_free_inode,
@@ -29609,13 +30058,12 @@ index 000000000000..44ee4685b218
+ .show_options = aufs_show_options,
+ .statfs = aufs_statfs,
+ .put_super = aufs_put_super,
-+ .sync_fs = aufs_sync_fs,
-+ .remount_fs = aufs_remount_fs
++ .sync_fs = aufs_sync_fs
+};
+
+/* ---------------------------------------------------------------------- */
+
-+static int alloc_root(struct super_block *sb)
++int au_alloc_root(struct super_block *sb)
+{
+ int err;
+ struct inode *inode;
@@ -29651,164 +30099,74 @@ index 000000000000..44ee4685b218
+ return err;
+}
+
-+static int aufs_fill_super(struct super_block *sb, void *raw_data,
-+ int silent __maybe_unused)
++/* ---------------------------------------------------------------------- */
++
++static void aufs_kill_sb(struct super_block *sb)
+{
-+ int err;
-+ struct au_opts opts = {
-+ .opt = NULL
-+ };
+ struct au_sbinfo *sbinfo;
+ struct dentry *root;
-+ struct inode *inode;
-+ char *arg = raw_data;
-+
-+ if (unlikely(!arg || !*arg)) {
-+ err = -EINVAL;
-+ pr_err("no arg\n");
-+ goto out;
-+ }
-+
-+ err = -ENOMEM;
-+ opts.opt = (void *)__get_free_page(GFP_NOFS);
-+ if (unlikely(!opts.opt))
-+ goto out;
-+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
-+ opts.sb_flags = sb->s_flags;
+
-+ err = au_si_alloc(sb);
-+ if (unlikely(err))
-+ goto out_opts;
+ sbinfo = au_sbi(sb);
++ if (!sbinfo)
++ goto out;
+
-+ /* all timestamps always follow the ones on the branch */
-+ sb->s_flags |= SB_NOATIME | SB_NODIRATIME;
-+ sb->s_flags |= SB_I_VERSION; /* do we really need this? */
-+ sb->s_op = &aufs_sop;
-+ sb->s_d_op = &aufs_dop;
-+ sb->s_magic = AUFS_SUPER_MAGIC;
-+ sb->s_maxbytes = 0;
-+ sb->s_stack_depth = 1;
-+ au_export_init(sb);
-+ au_xattr_init(sb);
++ au_sbilist_del(sb);
+
-+ err = alloc_root(sb);
-+ if (unlikely(err)) {
-+ si_write_unlock(sb);
-+ goto out_info;
-+ }
+ root = sb->s_root;
-+ inode = d_inode(root);
-+
-+ /*
-+ * actually we can parse options regardless aufs lock here.
-+ * but at remount time, parsing must be done before aufs lock.
-+ * so we follow the same rule.
-+ */
-+ ii_write_lock_parent(inode);
-+ aufs_write_unlock(root);
-+ err = au_opts_parse(sb, arg, &opts);
-+ if (unlikely(err))
-+ goto out_root;
++ if (root)
++ aufs_write_lock(root);
++ else
++ __si_write_lock(sb);
+
-+ /* lock vfs_inode first, then aufs. */
-+ inode_lock(inode);
-+ aufs_write_lock(root);
-+ err = au_opts_mount(sb, &opts);
-+ au_opts_free(&opts);
-+ if (!err && au_ftest_si(sbinfo, NO_DREVAL)) {
-+ sb->s_d_op = &aufs_dop_noreval;
-+ pr_info("%ps\n", sb->s_d_op);
-+ au_refresh_dop(root, /*force_reval*/0);
-+ sbinfo->si_iop_array = aufs_iop_nogetattr;
-+ au_refresh_iop(inode, /*force_getattr*/0);
++ au_fhsm_fin(sb);
++ if (sbinfo->si_wbr_create_ops->fin)
++ sbinfo->si_wbr_create_ops->fin(sb);
++ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
++ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
++ au_remount_refresh(sb, /*do_idop*/0);
+ }
-+ aufs_write_unlock(root);
-+ inode_unlock(inode);
-+ if (!err)
-+ goto out_opts; /* success */
-+
-+out_root:
-+ dput(root);
-+ sb->s_root = NULL;
-+out_info:
-+ kobject_put(&sbinfo->si_kobj);
-+ sb->s_fs_info = NULL;
-+out_opts:
-+ free_page((unsigned long)opts.opt);
-+out:
-+ AuTraceErr(err);
-+ err = cvt_err(err);
-+ AuTraceErr(err);
-+ return err;
-+}
-+
-+/* ---------------------------------------------------------------------- */
-+
-+static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags,
-+ const char *dev_name __maybe_unused,
-+ void *raw_data)
-+{
-+ struct dentry *root;
++ if (au_opt_test(sbinfo->si_mntflags, PLINK))
++ au_plink_put(sb, /*verbose*/1);
++ au_xino_clr(sb);
++ if (root)
++ au_dr_opt_flush(sb);
+
-+ /* all timestamps always follow the ones on the branch */
-+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
-+ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super);
-+ if (IS_ERR(root))
-+ goto out;
++ if (root)
++ aufs_write_unlock(root);
++ else
++ __si_write_unlock(sb);
+
-+ au_sbilist_add(root->d_sb);
++ sbinfo->si_sb = NULL;
++ au_nwt_flush(&sbinfo->si_nowait);
+
+out:
-+ return root;
-+}
-+
-+static void aufs_kill_sb(struct super_block *sb)
-+{
-+ struct au_sbinfo *sbinfo;
-+
-+ sbinfo = au_sbi(sb);
-+ if (sbinfo) {
-+ au_sbilist_del(sb);
-+ aufs_write_lock(sb->s_root);
-+ au_fhsm_fin(sb);
-+ if (sbinfo->si_wbr_create_ops->fin)
-+ sbinfo->si_wbr_create_ops->fin(sb);
-+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
-+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
-+ au_remount_refresh(sb, /*do_idop*/0);
-+ }
-+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
-+ au_plink_put(sb, /*verbose*/1);
-+ au_xino_clr(sb);
-+ au_dr_opt_flush(sb);
-+ sbinfo->si_sb = NULL;
-+ aufs_write_unlock(sb->s_root);
-+ au_nwt_flush(&sbinfo->si_nowait);
-+ }
+ kill_anon_super(sb);
+}
+
+struct file_system_type aufs_fs_type = {
+ .name = AUFS_FSTYPE,
+ /* a race between rename and others */
-+ .fs_flags = FS_RENAME_DOES_D_MOVE,
-+ .mount = aufs_mount,
++ .fs_flags = FS_RENAME_DOES_D_MOVE
++ /* untested */
++ /*| FS_ALLOW_IDMAP*/
++ ,
++ .init_fs_context = aufs_fsctx_init,
++ .parameters = aufs_fsctx_paramspec,
+ .kill_sb = aufs_kill_sb,
+ /* no need to __module_get() and module_put(). */
+ .owner = THIS_MODULE,
+};
diff --git a/fs/aufs/super.h b/fs/aufs/super.h
new file mode 100644
-index 000000000000..37f02bb21324
+index 000000000000..f1d9aedcbca4
--- /dev/null
+++ b/fs/aufs/super.h
-@@ -0,0 +1,589 @@
+@@ -0,0 +1,592 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -29937,8 +30295,6 @@ index 000000000000..37f02bb21324
+ unsigned int si_mntflags;
+
+ /* external inode number (bitmap and translation table) */
-+ vfs_readf_t si_xread;
-+ vfs_writef_t si_xwrite;
+ loff_t si_ximaxent; /* max entries in a xino */
+
+ struct file *si_xib;
@@ -29985,7 +30341,7 @@ index 000000000000..37f02bb21324
+ struct hlist_bl_head si_files;
+
+ /* with/without getattr, brother of sb->s_d_op */
-+ struct inode_operations *si_iop_array;
++ const struct inode_operations *si_iop_array;
+
+ /*
+ * sysfs and lifetime management.
@@ -30069,8 +30425,8 @@ index 000000000000..37f02bb21324
+/* ---------------------------------------------------------------------- */
+
+/* super.c */
-+extern struct file_system_type aufs_fs_type;
+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
++
+typedef unsigned long long (*au_arraycb_t)(struct super_block *sb, void *array,
+ unsigned long long max, void *arg);
+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb,
@@ -30078,9 +30434,14 @@ index 000000000000..37f02bb21324
+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max);
+void au_iarray_free(struct inode **a, unsigned long long max);
+
++void au_remount_refresh(struct super_block *sb, unsigned int do_idop);
++extern const struct super_operations aufs_sop;
++int au_alloc_root(struct super_block *sb);
++extern struct file_system_type aufs_fs_type;
++
+/* sbinfo.c */
+void au_si_free(struct kobject *kobj);
-+int au_si_alloc(struct super_block *sb);
++struct au_sbinfo *au_si_alloc(struct super_block *sb);
+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink);
+
+unsigned int au_sigen_inc(struct super_block *sb);
@@ -30395,15 +30756,15 @@ index 000000000000..37f02bb21324
+#endif /* __AUFS_SUPER_H__ */
diff --git a/fs/aufs/sysaufs.c b/fs/aufs/sysaufs.c
new file mode 100644
-index 000000000000..32a0811c54de
+index 000000000000..e3f3489c7570
--- /dev/null
+++ b/fs/aufs/sysaufs.c
-@@ -0,0 +1,93 @@
+@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -30438,6 +30799,7 @@ index 000000000000..32a0811c54de
+ &sysaufs_si_attr_xi_path.attr,
+ NULL,
+};
++ATTRIBUTE_GROUPS(sysaufs_si);
+
+static const struct sysfs_ops au_sbi_ops = {
+ .show = sysaufs_si_show
@@ -30446,7 +30808,7 @@ index 000000000000..32a0811c54de
+static struct kobj_type au_sbi_ktype = {
+ .release = au_si_free,
+ .sysfs_ops = &au_sbi_ops,
-+ .default_attrs = sysaufs_si_attrs
++ .default_groups = sysaufs_si_groups
+};
+
+/* ---------------------------------------------------------------------- */
@@ -30494,15 +30856,15 @@ index 000000000000..32a0811c54de
+}
diff --git a/fs/aufs/sysaufs.h b/fs/aufs/sysaufs.h
new file mode 100644
-index 000000000000..195fe279b820
+index 000000000000..3f7efd4510be
--- /dev/null
+++ b/fs/aufs/sysaufs.h
@@ -0,0 +1,102 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -30602,15 +30964,15 @@ index 000000000000..195fe279b820
+#endif /* __SYSAUFS_H__ */
diff --git a/fs/aufs/sysfs.c b/fs/aufs/sysfs.c
new file mode 100644
-index 000000000000..eda987628dbb
+index 000000000000..4e8a4cfa9faa
--- /dev/null
+++ b/fs/aufs/sysfs.c
@@ -0,0 +1,374 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -30982,15 +31344,15 @@ index 000000000000..eda987628dbb
+}
diff --git a/fs/aufs/sysrq.c b/fs/aufs/sysrq.c
new file mode 100644
-index 000000000000..db10ec528f5d
+index 000000000000..d4bdeafe2fe3
--- /dev/null
+++ b/fs/aufs/sysrq.c
-@@ -0,0 +1,160 @@
+@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -31022,6 +31384,7 @@ index 000000000000..db10ec528f5d
+ struct hlist_bl_head *files;
+ struct hlist_bl_node *pos;
+ struct au_finfo *finfo;
++ struct inode *i;
+
+ plevel = au_plevel;
+ au_plevel = KERN_WARNING;
@@ -31034,14 +31397,7 @@ index 000000000000..db10ec528f5d
+ pr("superblock\n");
+ au_dpri_sb(sb);
+
-+#if 0
-+ pr("root dentry\n");
-+ au_dpri_dentry(sb->s_root);
-+ pr("root inode\n");
-+ au_dpri_inode(d_inode(sb->s_root));
-+#endif
-+
-+#if 0
++#if 0 /* reserved */
+ do {
+ int err, i, j, ndentry;
+ struct au_dcsub_pages dpages;
@@ -31062,21 +31418,16 @@ index 000000000000..db10ec528f5d
+ } while (0);
+#endif
+
-+#if 1
-+ {
-+ struct inode *i;
-+
-+ pr("isolated inode\n");
-+ spin_lock(&sb->s_inode_list_lock);
-+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
-+ spin_lock(&i->i_lock);
-+ if (1 || hlist_empty(&i->i_dentry))
-+ au_dpri_inode(i);
-+ spin_unlock(&i->i_lock);
-+ }
-+ spin_unlock(&sb->s_inode_list_lock);
++ pr("isolated inode\n");
++ spin_lock(&sb->s_inode_list_lock);
++ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
++ spin_lock(&i->i_lock);
++ if (hlist_empty(&i->i_dentry))
++ au_dpri_inode(i);
++ spin_unlock(&i->i_lock);
+ }
-+#endif
++ spin_unlock(&sb->s_inode_list_lock);
++
+ pr("files\n");
+ files = &au_sbi(sb)->si_files;
+ hlist_bl_lock(files);
@@ -31148,15 +31499,15 @@ index 000000000000..db10ec528f5d
+}
diff --git a/fs/aufs/vdir.c b/fs/aufs/vdir.c
new file mode 100644
-index 000000000000..dc768f5d90c6
+index 000000000000..fdf7644049c5
--- /dev/null
+++ b/fs/aufs/vdir.c
@@ -0,0 +1,896 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -31249,7 +31600,7 @@ index 000000000000..dc768f5d90c6
+
+static void nhash_count(struct hlist_head *head)
+{
-+#if 0
++#if 0 /* debugging */
+ unsigned long n;
+ struct hlist_node *pos;
+
@@ -31606,7 +31957,7 @@ index 000000000000..dc768f5d90c6
+ int err;
+};
+
-+static int fillvdir(struct dir_context *ctx, const char *__name, int nlen,
++static bool fillvdir(struct dir_context *ctx, const char *__name, int nlen,
+ loff_t offset __maybe_unused, u64 h_ino,
+ unsigned int d_type)
+{
@@ -31657,7 +32008,7 @@ index 000000000000..dc768f5d90c6
+ arg->vdir->vd_jiffy = jiffies;
+ /* smp_mb(); */
+ AuTraceErr(arg->err);
-+ return arg->err;
++ return !arg->err;
+}
+
+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
@@ -32050,15 +32401,15 @@ index 000000000000..dc768f5d90c6
+}
diff --git a/fs/aufs/vfsub.c b/fs/aufs/vfsub.c
new file mode 100644
-index 000000000000..d6945e22593e
+index 000000000000..2fb5f1ac0b31
--- /dev/null
+++ b/fs/aufs/vfsub.c
-@@ -0,0 +1,902 @@
+@@ -0,0 +1,918 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -32077,7 +32428,6 @@ index 000000000000..d6945e22593e
+ */
+
+#include <linux/mnt_namespace.h>
-+#include <linux/namei.h>
+#include <linux/nsproxy.h>
+#include <linux/security.h>
+#include <linux/splice.h>
@@ -32093,13 +32443,13 @@ index 000000000000..d6945e22593e
+}
+#endif
+
-+int vfsub_sync_filesystem(struct super_block *h_sb, int wait)
++int vfsub_sync_filesystem(struct super_block *h_sb)
+{
+ int err;
+
+ lockdep_off();
+ down_read(&h_sb->s_umount);
-+ err = __sync_filesystem(h_sb, wait);
++ err = sync_filesystem(h_sb);
+ up_read(&h_sb->s_umount);
+ lockdep_on();
+
@@ -32114,6 +32464,11 @@ index 000000000000..d6945e22593e
+ struct kstat st;
+ struct super_block *h_sb;
+
++ /*
++ * Always needs h_path->mnt for LSM or FUSE branch.
++ */
++ AuDebugOn(!h_path->mnt);
++
+ /* for remote fs, leave work for its getattr or d_revalidate */
+ /* for bad i_attr fs, handle them in aufs_getattr() */
+ /* still some fs may acquire i_mutex. we need to skip them */
@@ -32132,15 +32487,8 @@ index 000000000000..d6945e22593e
+
+struct file *vfsub_dentry_open(struct path *path, int flags)
+{
-+ struct file *file;
-+
-+ file = dentry_open(path, flags /* | __FMODE_NONOTIFY */,
++ return dentry_open(path, flags /* | __FMODE_NONOTIFY */,
+ current_cred());
-+ if (!IS_ERR_OR_NULL(file)
-+ && (file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
-+ i_readcount_inc(d_inode(path->dentry));
-+
-+ return file;
+}
+
+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
@@ -32229,38 +32577,38 @@ index 000000000000..d6945e22593e
+}
+
+struct dentry *vfsub_lookup_one_len_unlocked(const char *name,
-+ struct dentry *parent, int len)
++ struct path *ppath, int len)
+{
-+ struct path path = {
-+ .mnt = NULL
-+ };
++ struct path path;
+
-+ path.dentry = lookup_one_len_unlocked(name, parent, len);
++ path.dentry = lookup_one_len_unlocked(name, ppath->dentry, len);
+ if (IS_ERR(path.dentry))
+ goto out;
-+ if (d_is_positive(path.dentry))
++ if (d_is_positive(path.dentry)) {
++ path.mnt = ppath->mnt;
+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
++ }
+
+out:
+ AuTraceErrPtr(path.dentry);
+ return path.dentry;
+}
+
-+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
++struct dentry *vfsub_lookup_one_len(const char *name, struct path *ppath,
+ int len)
+{
-+ struct path path = {
-+ .mnt = NULL
-+ };
++ struct path path;
+
+ /* VFS checks it too, but by WARN_ON_ONCE() */
-+ IMustLock(d_inode(parent));
++ IMustLock(d_inode(ppath->dentry));
+
-+ path.dentry = lookup_one_len(name, parent, len);
++ path.dentry = lookup_one_len(name, ppath->dentry, len);
+ if (IS_ERR(path.dentry))
+ goto out;
-+ if (d_is_positive(path.dentry))
++ if (d_is_positive(path.dentry)) {
++ path.mnt = ppath->mnt;
+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
++ }
+
+out:
+ AuTraceErrPtr(path.dentry);
@@ -32270,7 +32618,7 @@ index 000000000000..d6945e22593e
+void vfsub_call_lkup_one(void *args)
+{
+ struct vfsub_lkup_one_args *a = args;
-+ *a->errp = vfsub_lkup_one(a->name, a->parent);
++ *a->errp = vfsub_lkup_one(a->name, a->ppath);
+}
+
+/* ---------------------------------------------------------------------- */
@@ -32307,6 +32655,7 @@ index 000000000000..d6945e22593e
+{
+ int err;
+ struct dentry *d;
++ struct mnt_idmap *idmap;
+
+ IMustLock(dir);
+
@@ -32316,9 +32665,10 @@ index 000000000000..d6945e22593e
+ path->dentry = d;
+ if (unlikely(err))
+ goto out;
++ idmap = mnt_idmap(path->mnt);
+
+ lockdep_off();
-+ err = vfs_create(dir, path->dentry, mode, want_excl);
++ err = vfs_create(idmap, dir, path->dentry, mode, want_excl);
+ lockdep_on();
+ if (!err) {
+ struct path tmp = *path;
@@ -32340,6 +32690,7 @@ index 000000000000..d6945e22593e
+{
+ int err;
+ struct dentry *d;
++ struct mnt_idmap *idmap;
+
+ IMustLock(dir);
+
@@ -32349,9 +32700,10 @@ index 000000000000..d6945e22593e
+ path->dentry = d;
+ if (unlikely(err))
+ goto out;
++ idmap = mnt_idmap(path->mnt);
+
+ lockdep_off();
-+ err = vfs_symlink(dir, path->dentry, symname);
++ err = vfs_symlink(idmap, dir, path->dentry, symname);
+ lockdep_on();
+ if (!err) {
+ struct path tmp = *path;
@@ -32373,6 +32725,7 @@ index 000000000000..d6945e22593e
+{
+ int err;
+ struct dentry *d;
++ struct mnt_idmap *idmap;
+
+ IMustLock(dir);
+
@@ -32382,9 +32735,10 @@ index 000000000000..d6945e22593e
+ path->dentry = d;
+ if (unlikely(err))
+ goto out;
++ idmap = mnt_idmap(path->mnt);
+
+ lockdep_off();
-+ err = vfs_mknod(dir, path->dentry, mode, dev);
++ err = vfs_mknod(idmap, dir, path->dentry, mode, dev);
+ lockdep_on();
+ if (!err) {
+ struct path tmp = *path;
@@ -32417,6 +32771,7 @@ index 000000000000..d6945e22593e
+{
+ int err;
+ struct dentry *d;
++ struct mnt_idmap *idmap;
+
+ IMustLock(dir);
+
@@ -32431,9 +32786,10 @@ index 000000000000..d6945e22593e
+ path->dentry = d;
+ if (unlikely(err))
+ goto out;
++ idmap = mnt_idmap(path->mnt);
+
+ lockdep_off();
-+ err = vfs_link(src_dentry, dir, path->dentry, delegated_inode);
++ err = vfs_link(src_dentry, idmap, dir, path->dentry, delegated_inode);
+ lockdep_on();
+ if (!err) {
+ struct path tmp = *path;
@@ -32459,6 +32815,7 @@ index 000000000000..d6945e22593e
+ struct inode **delegated_inode, unsigned int flags)
+{
+ int err;
++ struct renamedata rd;
+ struct path tmp = {
+ .mnt = path->mnt
+ };
@@ -32475,9 +32832,16 @@ index 000000000000..d6945e22593e
+ if (unlikely(err))
+ goto out;
+
++ rd.old_mnt_idmap = mnt_idmap(path->mnt);
++ rd.old_dir = src_dir;
++ rd.old_dentry = src_dentry;
++ rd.new_mnt_idmap = rd.old_mnt_idmap;
++ rd.new_dir = dir;
++ rd.new_dentry = path->dentry;
++ rd.delegated_inode = delegated_inode;
++ rd.flags = flags;
+ lockdep_off();
-+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry,
-+ delegated_inode, flags);
++ err = vfs_rename(&rd);
+ lockdep_on();
+ if (!err) {
+ int did;
@@ -32501,6 +32865,7 @@ index 000000000000..d6945e22593e
+{
+ int err;
+ struct dentry *d;
++ struct mnt_idmap *idmap;
+
+ IMustLock(dir);
+
@@ -32510,9 +32875,10 @@ index 000000000000..d6945e22593e
+ path->dentry = d;
+ if (unlikely(err))
+ goto out;
++ idmap = mnt_idmap(path->mnt);
+
+ lockdep_off();
-+ err = vfs_mkdir(dir, path->dentry, mode);
++ err = vfs_mkdir(idmap, dir, path->dentry, mode);
+ lockdep_on();
+ if (!err) {
+ struct path tmp = *path;
@@ -32534,6 +32900,7 @@ index 000000000000..d6945e22593e
+{
+ int err;
+ struct dentry *d;
++ struct mnt_idmap *idmap;
+
+ IMustLock(dir);
+
@@ -32543,9 +32910,10 @@ index 000000000000..d6945e22593e
+ path->dentry = d;
+ if (unlikely(err))
+ goto out;
++ idmap = mnt_idmap(path->mnt);
+
+ lockdep_off();
-+ err = vfs_rmdir(dir, path->dentry);
++ err = vfs_rmdir(idmap, dir, path->dentry);
+ lockdep_on();
+ if (!err) {
+ struct path tmp = {
@@ -32576,22 +32944,17 @@ index 000000000000..d6945e22593e
+ return err;
+}
+
-+/* todo: kernel_read()? */
+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
+ loff_t *ppos)
+{
+ ssize_t err;
-+ mm_segment_t oldfs;
-+ union {
-+ void *k;
-+ char __user *u;
-+ } buf;
+
-+ buf.k = kbuf;
-+ oldfs = get_fs();
-+ set_fs(KERNEL_DS);
-+ err = vfsub_read_u(file, buf.u, count, ppos);
-+ set_fs(oldfs);
++ lockdep_off();
++ err = kernel_read(file, kbuf, count, ppos);
++ lockdep_on();
++ AuTraceErr(err);
++ if (err >= 0)
++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
+ return err;
+}
+
@@ -32611,17 +32974,12 @@ index 000000000000..d6945e22593e
+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
+{
+ ssize_t err;
-+ mm_segment_t oldfs;
-+ union {
-+ void *k;
-+ const char __user *u;
-+ } buf;
+
-+ buf.k = kbuf;
-+ oldfs = get_fs();
-+ set_fs(KERNEL_DS);
-+ err = vfsub_write_u(file, buf.u, count, ppos);
-+ set_fs(oldfs);
++ lockdep_off();
++ err = kernel_write(file, kbuf, count, ppos);
++ lockdep_on();
++ if (err >= 0)
++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
+ return err;
+}
+
@@ -32660,14 +33018,14 @@ index 000000000000..d6945e22593e
+ return err;
+}
+
-+long vfsub_splice_to(struct file *in, loff_t *ppos,
-+ struct pipe_inode_info *pipe, size_t len,
-+ unsigned int flags)
++long vfsub_splice_read(struct file *in, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags)
+{
+ long err;
+
+ lockdep_off();
-+ err = do_splice_to(in, ppos, pipe, len, flags);
++ err = vfs_splice_read(in, ppos, pipe, len, flags);
+ lockdep_on();
+ file_accessed(in);
+ if (err >= 0)
@@ -32713,6 +33071,7 @@ index 000000000000..d6945e22593e
+ int err;
+ struct inode *h_inode;
+ struct super_block *h_sb;
++ struct mnt_idmap *h_idmap;
+
+ if (!h_file) {
+ err = vfsub_truncate(h_path, length);
@@ -32724,12 +33083,12 @@ index 000000000000..d6945e22593e
+ lockdep_off();
+ sb_start_write(h_sb);
+ lockdep_on();
-+ err = locks_verify_truncate(h_inode, h_file, length);
-+ if (!err)
-+ err = security_path_truncate(h_path);
++ err = security_file_truncate(h_file);
+ if (!err) {
++ h_idmap = mnt_idmap(h_path->mnt);
+ lockdep_off();
-+ err = do_truncate(h_path->dentry, length, attr, h_file);
++ err = do_truncate(h_idmap, h_path->dentry, length, attr,
++ h_file);
+ lockdep_on();
+ }
+ lockdep_off();
@@ -32758,8 +33117,10 @@ index 000000000000..d6945e22593e
+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
+{
+ int err, do_sio, wkq_err;
++ struct mnt_idmap *idmap;
+
-+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
++ idmap = mnt_idmap(path->mnt);
++ do_sio = au_test_h_perm_sio(idmap, dir, MAY_EXEC | MAY_WRITE);
+ if (!do_sio) {
+ lockdep_off();
+ err = vfsub_mkdir(dir, path, mode);
@@ -32794,8 +33155,10 @@ index 000000000000..d6945e22593e
+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
+{
+ int err, do_sio, wkq_err;
++ struct mnt_idmap *idmap;
+
-+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
++ idmap = mnt_idmap(path->mnt);
++ do_sio = au_test_h_perm_sio(idmap, dir, MAY_EXEC | MAY_WRITE);
+ if (!do_sio) {
+ lockdep_off();
+ err = vfsub_rmdir(dir, path);
@@ -32827,14 +33190,16 @@ index 000000000000..d6945e22593e
+{
+ struct notify_change_args *a = args;
+ struct inode *h_inode;
++ struct mnt_idmap *idmap;
+
+ h_inode = d_inode(a->path->dentry);
+ IMustLock(h_inode);
+
+ *a->errp = -EPERM;
+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
++ idmap = mnt_idmap(a->path->mnt);
+ lockdep_off();
-+ *a->errp = notify_change(a->path->dentry, a->ia,
++ *a->errp = notify_change(idmap, a->path->dentry, a->ia,
+ a->delegated_inode);
+ lockdep_on();
+ if (!*a->errp)
@@ -32891,6 +33256,7 @@ index 000000000000..d6945e22593e
+ struct unlink_args *a = args;
+ struct dentry *d = a->path->dentry;
+ struct inode *h_inode;
++ struct mnt_idmap *idmap;
+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
+ && au_dcount(d) == 1);
+
@@ -32910,8 +33276,9 @@ index 000000000000..d6945e22593e
+ ihold(h_inode);
+ }
+
++ idmap = mnt_idmap(a->path->mnt);
+ lockdep_off();
-+ *a->errp = vfs_unlink(a->dir, d, a->delegated_inode);
++ *a->errp = vfs_unlink(idmap, a->dir, d, a->delegated_inode);
+ lockdep_on();
+ if (!*a->errp) {
+ struct path tmp = {
@@ -32958,15 +33325,15 @@ index 000000000000..d6945e22593e
+}
diff --git a/fs/aufs/vfsub.h b/fs/aufs/vfsub.h
new file mode 100644
-index 000000000000..51e677c7f6b7
+index 000000000000..928c463620c1
--- /dev/null
+++ b/fs/aufs/vfsub.h
-@@ -0,0 +1,354 @@
+@@ -0,0 +1,404 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -33048,7 +33415,7 @@ index 000000000000..51e677c7f6b7
+AuStubInt0(vfsub_test_mntns, struct vfsmount *mnt, struct super_block *h_sb);
+#endif
+
-+int vfsub_sync_filesystem(struct super_block *h_sb, int wait);
++int vfsub_sync_filesystem(struct super_block *h_sb);
+
+/* ---------------------------------------------------------------------- */
+
@@ -33067,20 +33434,20 @@ index 000000000000..51e677c7f6b7
+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
+
+struct dentry *vfsub_lookup_one_len_unlocked(const char *name,
-+ struct dentry *parent, int len);
-+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
++ struct path *ppath, int len);
++struct dentry *vfsub_lookup_one_len(const char *name, struct path *ppath,
+ int len);
+
+struct vfsub_lkup_one_args {
+ struct dentry **errp;
+ struct qstr *name;
-+ struct dentry *parent;
++ struct path *ppath;
+};
+
+static inline struct dentry *vfsub_lkup_one(struct qstr *name,
-+ struct dentry *parent)
++ struct path *ppath)
+{
-+ return vfsub_lookup_one_len(name->name, parent, name->len);
++ return vfsub_lookup_one_len(name->name, ppath, name->len);
+}
+
+void vfsub_call_lkup_one(void *args);
@@ -33113,6 +33480,20 @@ index 000000000000..51e677c7f6b7
+}
+#endif
+
++static inline void vfsub_file_start_write(struct file *file)
++{
++ lockdep_off();
++ file_start_write(file);
++ lockdep_on();
++}
++
++static inline void vfsub_file_end_write(struct file *file)
++{
++ lockdep_off();
++ file_end_write(file);
++ lockdep_on();
++}
++
+/* ---------------------------------------------------------------------- */
+
+struct au_hinode;
@@ -33193,27 +33574,29 @@ index 000000000000..51e677c7f6b7
+static inline int vfsub_update_time(struct inode *h_inode,
+ struct timespec64 *ts, int flags)
+{
-+ return update_time(h_inode, ts, flags);
++ return inode_update_time(h_inode, ts, flags);
+ /* no vfsub_update_h_iattr() since we don't have struct path */
+}
+
+#ifdef CONFIG_FS_POSIX_ACL
-+static inline int vfsub_acl_chmod(struct inode *h_inode, umode_t h_mode)
++static inline int vfsub_acl_chmod(struct mnt_idmap *h_idmap,
++ struct dentry *h_dentry, umode_t h_mode)
+{
+ int err;
+
-+ err = posix_acl_chmod(h_inode, h_mode);
++ err = posix_acl_chmod(h_idmap, h_dentry, h_mode);
+ if (err == -EOPNOTSUPP)
+ err = 0;
+ return err;
+}
+#else
-+AuStubInt0(vfsub_acl_chmod, struct inode *h_inode, umode_t h_mode);
++AuStubInt0(vfsub_acl_chmod, struct mnt_idmap *h_idmap,
++ struct dentry *h_dentry, umode_t h_mode);
+#endif
+
-+long vfsub_splice_to(struct file *in, loff_t *ppos,
-+ struct pipe_inode_info *pipe, size_t len,
-+ unsigned int flags);
++long vfsub_splice_read(struct file *in, loff_t *ppos,
++ struct pipe_inode_info *pipe, size_t len,
++ unsigned int flags);
+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
+ loff_t *ppos, size_t len, unsigned int flags);
+
@@ -33291,42 +33674,76 @@ index 000000000000..51e677c7f6b7
+
+/* ---------------------------------------------------------------------- */
+
-+static inline int vfsub_setxattr(struct dentry *dentry, const char *name,
++static inline int vfsub_setxattr(struct mnt_idmap *idmap,
++ struct dentry *dentry, const char *name,
+ const void *value, size_t size, int flags)
+{
+ int err;
+
+ lockdep_off();
-+ err = vfs_setxattr(dentry, name, value, size, flags);
++ err = vfs_setxattr(idmap, dentry, name, value, size, flags);
++ lockdep_on();
++
++ return err;
++}
++
++static inline int vfsub_removexattr(struct mnt_idmap *idmap,
++ struct dentry *dentry, const char *name)
++{
++ int err;
++
++ lockdep_off();
++ err = vfs_removexattr(idmap, dentry, name);
+ lockdep_on();
+
+ return err;
+}
+
-+static inline int vfsub_removexattr(struct dentry *dentry, const char *name)
++#ifdef CONFIG_FS_POSIX_ACL
++static inline int vfsub_set_acl(struct mnt_idmap *idmap,
++ struct dentry *dentry, const char *name,
++ struct posix_acl *acl)
+{
+ int err;
+
+ lockdep_off();
-+ err = vfs_removexattr(dentry, name);
++ err = vfs_set_acl(idmap, dentry, name, acl);
+ lockdep_on();
+
+ return err;
+}
+
++static inline int vfsub_remove_acl(struct mnt_idmap *idmap,
++ struct dentry *dentry, const char *name)
++{
++ int err;
++
++ lockdep_off();
++ err = vfs_remove_acl(idmap, dentry, name);
++ lockdep_on();
++
++ return err;
++}
++#else
++AuStubInt0(vfsub_set_acl, struct mnt_idmap *idmap, struct dentry *dentry,
++ const char *name, struct posix_acl *acl);
++AuStubInt0(vfsub_remove_acl, struct mnt_idmap *idmap,
++ struct dentry *dentry, const char *name);
++#endif
++
+#endif /* __KERNEL__ */
+#endif /* __AUFS_VFSUB_H__ */
diff --git a/fs/aufs/wbr_policy.c b/fs/aufs/wbr_policy.c
new file mode 100644
-index 000000000000..64954145c0ec
+index 000000000000..c726f96b7bd5
--- /dev/null
+++ b/fs/aufs/wbr_policy.c
@@ -0,0 +1,830 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -34154,15 +34571,15 @@ index 000000000000..64954145c0ec
+};
diff --git a/fs/aufs/whout.c b/fs/aufs/whout.c
new file mode 100644
-index 000000000000..6c9c8501562a
+index 000000000000..7bd0392eeb87
--- /dev/null
+++ b/fs/aufs/whout.c
-@@ -0,0 +1,1062 @@
+@@ -0,0 +1,1072 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -34221,18 +34638,19 @@ index 000000000000..6c9c8501562a
+/* ---------------------------------------------------------------------- */
+
+/*
-+ * test if the @wh_name exists under @h_parent.
++ * test if the @wh_name exists under @h_ppath.
+ * @try_sio specifies the necessary of super-io.
+ */
-+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio)
++int au_wh_test(struct mnt_idmap *h_idmap, struct path *h_ppath,
++ struct qstr *wh_name, int try_sio)
+{
+ int err;
+ struct dentry *wh_dentry;
+
+ if (!try_sio)
-+ wh_dentry = vfsub_lkup_one(wh_name, h_parent);
++ wh_dentry = vfsub_lkup_one(wh_name, h_ppath);
+ else
-+ wh_dentry = au_sio_lkup_one(wh_name, h_parent);
++ wh_dentry = au_sio_lkup_one(h_idmap, wh_name, h_ppath);
+ err = PTR_ERR(wh_dentry);
+ if (IS_ERR(wh_dentry)) {
+ if (err == -ENAMETOOLONG)
@@ -34259,16 +34677,16 @@ index 000000000000..6c9c8501562a
+}
+
+/*
-+ * test if the @h_dentry sets opaque or not.
++ * test if the @h_path->dentry sets opaque or not.
+ */
-+int au_diropq_test(struct dentry *h_dentry)
++int au_diropq_test(struct mnt_idmap *h_idmap, struct path *h_path)
+{
+ int err;
+ struct inode *h_dir;
+
-+ h_dir = d_inode(h_dentry);
-+ err = au_wh_test(h_dentry, &diropq_name,
-+ au_test_h_perm_sio(h_dir, MAY_EXEC));
++ h_dir = d_inode(h_path->dentry);
++ err = au_wh_test(h_idmap, h_path, &diropq_name,
++ au_test_h_perm_sio(h_idmap, h_dir, MAY_EXEC));
+ return err;
+}
+
@@ -34285,6 +34703,8 @@ index 000000000000..6c9c8501562a
+ /* strict atomic_t is unnecessary here */
+ static unsigned short cnt;
+ struct qstr qs;
++ struct path h_ppath;
++ struct mnt_idmap *h_idmap;
+
+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
+
@@ -34308,10 +34728,13 @@ index 000000000000..6c9c8501562a
+ *p++ = '.';
+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
+
++ h_ppath.dentry = h_parent;
++ h_ppath.mnt = au_br_mnt(br);
++ h_idmap = au_br_idmap(br);
+ qs.name = name;
+ for (i = 0; i < 3; i++) {
+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
-+ dentry = au_sio_lkup_one(&qs, h_parent);
++ dentry = au_sio_lkup_one(h_idmap, &qs, &h_ppath);
+ if (IS_ERR(dentry) || d_is_negative(dentry))
+ goto out_name;
+ dput(dentry);
@@ -34405,21 +34828,20 @@ index 000000000000..6c9c8501562a
+ return err;
+}
+
-+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
-+ struct au_branch *br)
++static int unlink_wh_name(struct path *h_ppath, struct qstr *wh)
+{
+ int err;
-+ struct path h_path = {
-+ .mnt = au_br_mnt(br)
-+ };
++ struct path h_path;
+
+ err = 0;
-+ h_path.dentry = vfsub_lkup_one(wh, h_parent);
++ h_path.dentry = vfsub_lkup_one(wh, h_ppath);
+ if (IS_ERR(h_path.dentry))
+ err = PTR_ERR(h_path.dentry);
+ else {
-+ if (d_is_reg(h_path.dentry))
-+ err = do_unlink_wh(d_inode(h_parent), &h_path);
++ if (d_is_reg(h_path.dentry)) {
++ h_path.mnt = h_ppath->mnt;
++ err = do_unlink_wh(d_inode(h_ppath->dentry), &h_path);
++ }
+ dput(h_path.dentry);
+ }
+
@@ -34465,7 +34887,7 @@ index 000000000000..6c9c8501562a
+
+ pr_err("%pd (%s) doesn't support link(2), use noplink and rw+nolwh\n",
+ h_root, au_sbtype(h_root->d_sb));
-+ return -ENOSYS;
++ return -ENOSYS; /* the branch doesn't have its ->link() */
+}
+
+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
@@ -34859,15 +35281,17 @@ index 000000000000..6c9c8501562a
+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
+ unsigned int flags)
+{
-+ struct dentry *opq_dentry, *h_dentry;
++ struct dentry *opq_dentry;
+ struct super_block *sb;
+ struct au_branch *br;
++ struct path h_path;
+ int err;
+
+ sb = dentry->d_sb;
+ br = au_sbr(sb, bindex);
-+ h_dentry = au_h_dptr(dentry, bindex);
-+ opq_dentry = vfsub_lkup_one(&diropq_name, h_dentry);
++ h_path.dentry = au_h_dptr(dentry, bindex);
++ h_path.mnt = au_br_mnt(br);
++ opq_dentry = vfsub_lkup_one(&diropq_name, &h_path);
+ if (IS_ERR(opq_dentry))
+ goto out;
+
@@ -34878,11 +35302,8 @@ index 000000000000..6c9c8501562a
+ goto out; /* success */
+ }
+ } else {
-+ struct path tmp = {
-+ .dentry = opq_dentry,
-+ .mnt = au_br_mnt(br)
-+ };
-+ err = do_unlink_wh(au_h_iptr(d_inode(dentry), bindex), &tmp);
++ h_path.dentry = opq_dentry;
++ err = do_unlink_wh(au_h_iptr(d_inode(dentry), bindex), &h_path);
+ if (!err)
+ au_set_dbdiropq(dentry, -1);
+ }
@@ -34910,9 +35331,12 @@ index 000000000000..6c9c8501562a
+ unsigned int flags)
+{
+ struct dentry *diropq, *h_dentry;
++ struct mnt_idmap *h_idmap;
+
++ h_idmap = au_sbr_idmap(dentry->d_sb, bindex);
+ h_dentry = au_h_dptr(dentry, bindex);
-+ if (!au_test_h_perm_sio(d_inode(h_dentry), MAY_EXEC | MAY_WRITE))
++ if (!au_test_h_perm_sio(h_idmap, d_inode(h_dentry),
++ MAY_EXEC | MAY_WRITE))
+ diropq = do_diropq(dentry, bindex, flags);
+ else {
+ int wkq_err;
@@ -34945,11 +35369,14 @@ index 000000000000..6c9c8501562a
+ int err;
+ struct qstr wh_name;
+ struct dentry *wh_dentry;
++ struct path h_path;
+
+ err = au_wh_name_alloc(&wh_name, base_name);
+ wh_dentry = ERR_PTR(err);
+ if (!err) {
-+ wh_dentry = vfsub_lkup_one(&wh_name, h_parent);
++ h_path.dentry = h_parent;
++ h_path.mnt = au_br_mnt(br);
++ wh_dentry = vfsub_lkup_one(&wh_name, &h_path);
+ au_kfree_try_rcu(wh_name.name);
+ }
+ return wh_dentry;
@@ -34984,8 +35411,8 @@ index 000000000000..6c9c8501562a
+/* ---------------------------------------------------------------------- */
+
+/* Delete all whiteouts in this directory on branch bindex. */
-+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
-+ aufs_bindex_t bindex, struct au_branch *br)
++static int del_wh_children(struct path *h_path, struct au_nhash *whlist,
++ aufs_bindex_t bindex)
+{
+ int err;
+ unsigned long ul, n;
@@ -35015,7 +35442,7 @@ index 000000000000..6c9c8501562a
+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
+ memcpy(p, str->name, str->len);
+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
-+ err = unlink_wh_name(h_dentry, &wh_name, br);
++ err = unlink_wh_name(h_path, &wh_name);
+ if (!err)
+ continue;
+ break;
@@ -35034,16 +35461,15 @@ index 000000000000..6c9c8501562a
+
+struct del_wh_children_args {
+ int *errp;
-+ struct dentry *h_dentry;
++ struct path *h_path;
+ struct au_nhash *whlist;
+ aufs_bindex_t bindex;
-+ struct au_branch *br;
+};
+
+static void call_del_wh_children(void *args)
+{
+ struct del_wh_children_args *a = args;
-+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
++ *a->errp = del_wh_children(a->h_path, a->whlist, a->bindex);
+}
+
+/* ---------------------------------------------------------------------- */
@@ -35095,14 +35521,18 @@ index 000000000000..6c9c8501562a
+{
+ int err;
+ unsigned int h_nlink;
-+ struct path h_tmp;
++ struct path wh_path;
+ struct inode *wh_inode, *h_dir;
+ struct au_branch *br;
++ struct mnt_idmap *h_idmap;
+
+ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */
+ IMustLock(h_dir);
+
+ br = au_sbr(dir->i_sb, bindex);
++ wh_path.dentry = wh_dentry;
++ wh_path.mnt = au_br_mnt(br);
++ h_idmap = au_br_idmap(br);
+ wh_inode = d_inode(wh_dentry);
+ inode_lock_nested(wh_inode, AuLsc_I_CHILD);
+
@@ -35110,16 +35540,15 @@ index 000000000000..6c9c8501562a
+ * someone else might change some whiteouts while we were sleeping.
+ * it means this whlist may have an obsoleted entry.
+ */
-+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
-+ err = del_wh_children(wh_dentry, whlist, bindex, br);
++ if (!au_test_h_perm_sio(h_idmap, wh_inode, MAY_EXEC | MAY_WRITE))
++ err = del_wh_children(&wh_path, whlist, bindex);
+ else {
+ int wkq_err;
+ struct del_wh_children_args args = {
+ .errp = &err,
-+ .h_dentry = wh_dentry,
++ .h_path = &wh_path,
+ .whlist = whlist,
-+ .bindex = bindex,
-+ .br = br
++ .bindex = bindex
+ };
+
+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
@@ -35129,10 +35558,8 @@ index 000000000000..6c9c8501562a
+ inode_unlock(wh_inode);
+
+ if (!err) {
-+ h_tmp.dentry = wh_dentry;
-+ h_tmp.mnt = au_br_mnt(br);
+ h_nlink = h_dir->i_nlink;
-+ err = vfsub_rmdir(h_dir, &h_tmp);
++ err = vfsub_rmdir(h_dir, &wh_path);
+ /* some fs doesn't change the parent nlink in some cases */
+ h_nlink -= h_dir->i_nlink;
+ }
@@ -35222,15 +35649,15 @@ index 000000000000..6c9c8501562a
+}
diff --git a/fs/aufs/whout.h b/fs/aufs/whout.h
new file mode 100644
-index 000000000000..06f69b24e5c1
+index 000000000000..a7ae8702e7a5
--- /dev/null
+++ b/fs/aufs/whout.h
-@@ -0,0 +1,86 @@
+@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -35257,8 +35684,9 @@ index 000000000000..06f69b24e5c1
+
+/* whout.c */
+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
-+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio);
-+int au_diropq_test(struct dentry *h_dentry);
++int au_wh_test(struct mnt_idmap *h_idmap, struct path *h_ppath,
++ struct qstr *wh_name, int try_sio);
++int au_diropq_test(struct mnt_idmap *h_idmap, struct path *h_path);
+struct au_branch;
+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
+ struct qstr *prefix);
@@ -35314,15 +35742,15 @@ index 000000000000..06f69b24e5c1
+#endif /* __AUFS_WHOUT_H__ */
diff --git a/fs/aufs/wkq.c b/fs/aufs/wkq.c
new file mode 100644
-index 000000000000..b0dd8df4e414
+index 000000000000..cb71ca3bf51b
--- /dev/null
+++ b/fs/aufs/wkq.c
-@@ -0,0 +1,392 @@
+@@ -0,0 +1,372 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -35473,8 +35901,8 @@ index 000000000000..b0dd8df4e414
+ goto out;
+
+ err = 0;
-+#if 0
-+ if (0 && au_debug_test()) /* left for debugging */
++#if 0 /* left for debugging */
++ if (0 && au_debug_test())
+ lockdep_print_held_locks(curr);
+#endif
+ held_locks = curr->held_locks;
@@ -35525,7 +35953,7 @@ index 000000000000..b0dd8df4e414
+ if (!hl)
+ return;
+ while ((p = *hl++)) /* assignment */
-+ rwsem_release(p->instance, 0, /*p->acquire_ip*/_RET_IP_);
++ rwsem_release(p->instance, /*p->acquire_ip*/_RET_IP_);
+}
+#endif
+
@@ -35551,7 +35979,6 @@ index 000000000000..b0dd8df4e414
+/*
+ * Since struct completion is large, try allocating it dynamically.
+ */
-+#if 1 /* defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS) */
+#define AuWkqCompDeclare(name) struct completion *comp = NULL
+
+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
@@ -35570,25 +35997,6 @@ index 000000000000..b0dd8df4e414
+ au_kfree_rcu(comp);
+}
+
-+#else
-+
-+/* no braces */
-+#define AuWkqCompDeclare(name) \
-+ DECLARE_COMPLETION_ONSTACK(_ ## name); \
-+ struct completion *comp = &_ ## name
-+
-+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
-+{
-+ wkinfo->comp = *comp;
-+ return 0;
-+}
-+
-+static void au_wkq_comp_free(struct completion *comp __maybe_unused)
-+{
-+ /* empty */
-+}
-+#endif /* 4KSTACKS */
-+
+static void au_wkq_run(struct au_wkinfo *wkinfo)
+{
+ if (au_ftest_wkq(wkinfo->flags, NEST)) {
@@ -35712,15 +36120,15 @@ index 000000000000..b0dd8df4e414
+}
diff --git a/fs/aufs/wkq.h b/fs/aufs/wkq.h
new file mode 100644
-index 000000000000..235370d91693
+index 000000000000..f8bb8e12395e
--- /dev/null
+++ b/fs/aufs/wkq.h
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -35807,15 +36215,15 @@ index 000000000000..235370d91693
+#endif /* __AUFS_WKQ_H__ */
diff --git a/fs/aufs/xattr.c b/fs/aufs/xattr.c
new file mode 100644
-index 000000000000..8e56b15c53b5
+index 000000000000..9e08665728ae
--- /dev/null
+++ b/fs/aufs/xattr.c
-@@ -0,0 +1,356 @@
+@@ -0,0 +1,360 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2014-2019 Junjiro R. Okajima
++ * Copyright (C) 2014-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -35834,7 +36242,6 @@ index 000000000000..8e56b15c53b5
+ */
+
+#include <linux/fs.h>
-+#include <linux/posix_acl_xattr.h>
+#include <linux/xattr.h>
+#include "aufs.h"
+
@@ -35877,35 +36284,61 @@ index 000000000000..8e56b15c53b5
+
+static const int au_xattr_out_of_list = AuBrAttr_ICEX_OTH << 1;
+
-+static int au_do_cpup_xattr(struct dentry *h_dst, struct dentry *h_src,
++static int au_do_cpup_xattr(struct path *h_dst, struct path *h_src,
+ char *name, char **buf, unsigned int ignore_flags,
+ unsigned int verbose)
+{
-+ int err;
++ int err, is_acl;
+ ssize_t ssz;
+ struct inode *h_idst;
++ struct dentry *h_dst_dentry, *h_src_dentry;
++ struct mnt_idmap *h_dst_idmap, *h_src_idmap;
++ struct posix_acl *acl;
+
-+ ssz = vfs_getxattr_alloc(h_src, name, buf, 0, GFP_NOFS);
-+ err = ssz;
-+ if (unlikely(err <= 0)) {
-+ if (err == -ENODATA
-+ || (err == -EOPNOTSUPP
-+ && ((ignore_flags & au_xattr_out_of_list)
-+ || (au_test_nfs_noacl(d_inode(h_src))
-+ && (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS)
-+ || !strcmp(name,
-+ XATTR_NAME_POSIX_ACL_DEFAULT))))
-+ ))
-+ err = 0;
-+ if (err && (verbose || au_debug_test()))
-+ pr_err("%s, err %d\n", name, err);
-+ goto out;
++ is_acl = !!is_posix_acl_xattr(name);
++ h_src_idmap = mnt_idmap(h_src->mnt);
++ h_src_dentry = h_src->dentry;
++ if (is_acl) {
++ acl = vfs_get_acl(h_src_idmap, h_src_dentry, name);
++ AuDebugOn(!acl);
++ if (unlikely(IS_ERR(acl))) {
++ err = PTR_ERR(acl);
++ if (err == -ENODATA)
++ err = 0;
++ else if (err == -EOPNOTSUPP
++ && au_test_nfs_noacl(d_inode(h_src_dentry)))
++ err = 0;
++ else if (verbose || au_debug_test())
++ pr_err("%s, err %d\n", name, err);
++ goto out;
++ }
++ } else {
++ ssz = vfs_getxattr_alloc(h_src_idmap, h_src_dentry, name, buf,
++ 0, GFP_NOFS);
++ if (unlikely(ssz <= 0)) {
++ err = ssz;
++ if (err == -ENODATA)
++ err = 0;
++ else if (err == -EOPNOTSUPP
++ && (ignore_flags & au_xattr_out_of_list))
++ err = 0;
++ else if (err && (verbose || au_debug_test()))
++ pr_err("%s, err %d\n", name, err);
++ goto out;
++ }
+ }
+
+ /* unlock it temporary */
-+ h_idst = d_inode(h_dst);
++ h_dst_idmap = mnt_idmap(h_dst->mnt);
++ h_dst_dentry = h_dst->dentry;
++ h_idst = d_inode(h_dst_dentry);
+ inode_unlock(h_idst);
-+ err = vfsub_setxattr(h_dst, name, *buf, ssz, /*flags*/0);
++ if (is_acl) {
++ err = vfsub_set_acl(h_dst_idmap, h_dst_dentry, name, acl);
++ posix_acl_release(acl);
++ } else
++ err = vfsub_setxattr(h_dst_idmap, h_dst_dentry, name, *buf,
++ ssz, /*flags*/0);
+ inode_lock_nested(h_idst, AuLsc_I_CHILD2);
+ if (unlikely(err)) {
+ if (verbose || au_debug_test())
@@ -35917,25 +36350,28 @@ index 000000000000..8e56b15c53b5
+ return err;
+}
+
-+int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags,
++int au_cpup_xattr(struct path *h_dst, struct path *h_src, int ignore_flags,
+ unsigned int verbose)
+{
-+ int err, unlocked, acl_access, acl_default;
++ int err, unlocked;
+ ssize_t ssz;
++ struct dentry *h_dst_dentry, *h_src_dentry;
+ struct inode *h_isrc, *h_idst;
+ char *value, *p, *o, *e;
+
+ /* try stopping to update the source inode while we are referencing */
+ /* there should not be the parent-child relationship between them */
-+ h_isrc = d_inode(h_src);
-+ h_idst = d_inode(h_dst);
++ h_dst_dentry = h_dst->dentry;
++ h_idst = d_inode(h_dst_dentry);
++ h_src_dentry = h_src->dentry;
++ h_isrc = d_inode(h_src_dentry);
+ inode_unlock(h_idst);
+ inode_lock_shared_nested(h_isrc, AuLsc_I_CHILD);
+ inode_lock_nested(h_idst, AuLsc_I_CHILD2);
+ unlocked = 0;
+
+ /* some filesystems don't list POSIX ACL, for example tmpfs */
-+ ssz = vfs_listxattr(h_src, NULL, 0);
++ ssz = vfs_listxattr(h_src_dentry, NULL, 0);
+ err = ssz;
+ if (unlikely(err < 0)) {
+ AuTraceErr(err);
@@ -35954,7 +36390,7 @@ index 000000000000..8e56b15c53b5
+ o = p;
+ if (unlikely(!p))
+ goto out;
-+ err = vfs_listxattr(h_src, p, ssz);
++ err = vfs_listxattr(h_src_dentry, p, ssz);
+ }
+ inode_unlock_shared(h_isrc);
+ unlocked = 1;
@@ -35965,33 +36401,12 @@ index 000000000000..8e56b15c53b5
+ err = 0;
+ e = p + ssz;
+ value = NULL;
-+ acl_access = 0;
-+ acl_default = 0;
++ ignore_flags |= au_xattr_out_of_list;
+ while (!err && p < e) {
-+ acl_access |= !strncmp(p, XATTR_NAME_POSIX_ACL_ACCESS,
-+ sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1);
-+ acl_default |= !strncmp(p, XATTR_NAME_POSIX_ACL_DEFAULT,
-+ sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)
-+ - 1);
+ err = au_do_cpup_xattr(h_dst, h_src, p, &value, ignore_flags,
+ verbose);
+ p += strlen(p) + 1;
+ }
-+ AuTraceErr(err);
-+ ignore_flags |= au_xattr_out_of_list;
-+ if (!err && !acl_access) {
-+ err = au_do_cpup_xattr(h_dst, h_src,
-+ XATTR_NAME_POSIX_ACL_ACCESS, &value,
-+ ignore_flags, verbose);
-+ AuTraceErr(err);
-+ }
-+ if (!err && !acl_default) {
-+ err = au_do_cpup_xattr(h_dst, h_src,
-+ XATTR_NAME_POSIX_ACL_DEFAULT, &value,
-+ ignore_flags, verbose);
-+ AuTraceErr(err);
-+ }
-+
+ au_kfree_try_rcu(value);
+
+out_free:
@@ -36007,7 +36422,7 @@ index 000000000000..8e56b15c53b5
+
+static int au_smack_reentering(struct super_block *sb)
+{
-+#if IS_ENABLED(CONFIG_SECURITY_SMACK)
++#if IS_ENABLED(CONFIG_SECURITY_SMACK) || IS_ENABLED(CONFIG_SECURITY_SELINUX)
+ /*
+ * as a part of lookup, smack_d_instantiate() is called, and it calls
+ * i_op->getxattr(). ouch.
@@ -36038,7 +36453,8 @@ index 000000000000..8e56b15c53b5
+ } u;
+};
+
-+static ssize_t au_lgxattr(struct dentry *dentry, struct au_lgxattr *arg)
++static ssize_t au_lgxattr(struct dentry *dentry, struct inode *inode,
++ struct au_lgxattr *arg)
+{
+ ssize_t err;
+ int reenter;
@@ -36052,7 +36468,7 @@ index 000000000000..8e56b15c53b5
+ if (unlikely(err))
+ goto out;
+ }
-+ err = au_h_path_getattr(dentry, /*force*/1, &h_path, reenter);
++ err = au_h_path_getattr(dentry, inode, /*force*/1, &h_path, reenter);
+ if (unlikely(err))
+ goto out_si;
+ if (unlikely(!h_path.dentry))
@@ -36067,7 +36483,7 @@ index 000000000000..8e56b15c53b5
+ break;
+ case AU_XATTR_GET:
+ AuDebugOn(d_is_negative(h_path.dentry));
-+ err = vfs_getxattr(h_path.dentry,
++ err = vfs_getxattr(mnt_idmap(h_path.mnt), h_path.dentry,
+ arg->u.get.name, arg->u.get.value,
+ arg->u.get.size);
+ break;
@@ -36094,11 +36510,10 @@ index 000000000000..8e56b15c53b5
+ },
+ };
+
-+ return au_lgxattr(dentry, &arg);
++ return au_lgxattr(dentry, /*inode*/NULL, &arg);
+}
+
-+static ssize_t au_getxattr(struct dentry *dentry,
-+ struct inode *inode __maybe_unused,
++static ssize_t au_getxattr(struct dentry *dentry, struct inode *inode,
+ const char *name, void *value, size_t size)
+{
+ struct au_lgxattr arg = {
@@ -36110,7 +36525,7 @@ index 000000000000..8e56b15c53b5
+ },
+ };
+
-+ return au_lgxattr(dentry, &arg);
++ return au_lgxattr(dentry, inode, &arg);
+}
+
+static int au_setxattr(struct dentry *dentry, struct inode *inode,
@@ -36140,6 +36555,7 @@ index 000000000000..8e56b15c53b5
+}
+
+static int au_xattr_set(const struct xattr_handler *handler,
++ struct mnt_idmap *idmap,
+ struct dentry *dentry, struct inode *inode,
+ const char *name, const void *value, size_t size,
+ int flags)
@@ -36155,10 +36571,6 @@ index 000000000000..8e56b15c53b5
+};
+
+static const struct xattr_handler *au_xattr_handlers[] = {
-+#ifdef CONFIG_FS_POSIX_ACL
-+ &posix_acl_access_xattr_handler,
-+ &posix_acl_default_xattr_handler,
-+#endif
+ &au_xattr_handler, /* must be last */
+ NULL
+};
@@ -36169,15 +36581,15 @@ index 000000000000..8e56b15c53b5
+}
diff --git a/fs/aufs/xino.c b/fs/aufs/xino.c
new file mode 100644
-index 000000000000..35ea33469d36
+index 000000000000..e1db09b3541d
--- /dev/null
+++ b/fs/aufs/xino.c
-@@ -0,0 +1,1965 @@
+@@ -0,0 +1,1926 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -36384,7 +36796,7 @@ index 000000000000..35ea33469d36
+ }
+
+ err = -EINVAL;
-+ if (unlikely(sb == d->d_sb)) {
++ if (unlikely(sb && sb == d->d_sb)) {
+ if (!silent)
+ pr_err("%s must be outside\n", fpath);
+ goto out;
@@ -36410,22 +36822,23 @@ index 000000000000..35ea33469d36
+ struct file *copy_src)
+{
+ struct file *file;
-+ struct dentry *dentry, *parent;
++ struct dentry *dentry;
+ struct inode *dir, *delegated;
+ struct qstr *name;
-+ struct path path;
++ struct path ppath, path;
+ int err, do_unlock;
+ struct au_xino_lock_dir ldir;
+
+ do_unlock = 1;
+ au_xino_lock_dir(sb, base, &ldir);
+ dentry = base->dentry;
-+ parent = dentry->d_parent; /* dir inode is locked */
-+ dir = d_inode(parent);
++ ppath.dentry = dentry->d_parent; /* dir inode is locked */
++ ppath.mnt = base->mnt;
++ dir = d_inode(ppath.dentry);
+ IMustLock(dir);
+
+ name = &dentry->d_name;
-+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
++ path.dentry = vfsub_lookup_one_len(name->name, &ppath, name->len);
+ if (IS_ERR(path.dentry)) {
+ file = (void *)path.dentry;
+ pr_err("%pd lookup err %ld\n", dentry, PTR_ERR(path.dentry));
@@ -36433,7 +36846,7 @@ index 000000000000..35ea33469d36
+ }
+
+ /* no need to mnt_want_write() since we call dentry_open() later */
-+ err = vfs_create(dir, path.dentry, 0666, NULL);
++ err = vfs_create(mnt_idmap(base->mnt), dir, path.dentry, 0666, NULL);
+ if (unlikely(err)) {
+ file = ERR_PTR(err);
+ pr_err("%pd create err %d\n", dentry, err);
@@ -36835,8 +37248,8 @@ index 000000000000..35ea33469d36
+ ino_t h_ino, ino;
+};
+
-+static int au_xino_do_write(vfs_writef_t write, struct file *file,
-+ struct au_xi_calc *calc, ino_t ino);
++static int au_xino_do_write(struct file *file, struct au_xi_calc *calc,
++ ino_t ino);
+
+static void au_xino_call_do_new_async(void *args)
+{
@@ -36865,7 +37278,7 @@ index 000000000000..35ea33469d36
+
+ file = au_xino_file(br->br_xino, a->calc.idx);
+ AuDebugOn(!file);
-+ err = au_xino_do_write(sbi->si_xwrite, file, &a->calc, a->ino);
++ err = au_xino_do_write(file, &a->calc, a->ino);
+ if (unlikely(err)) {
+ AuIOErr("err %d\n", err);
+ goto out;
@@ -36966,7 +37379,7 @@ index 000000000000..35ea33469d36
+ return 0; /* no xino */
+
+ sbinfo = au_sbi(sb);
-+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &calc.pos);
++ sz = xino_fread(file, ino, sizeof(*ino), &calc.pos);
+ if (sz == sizeof(*ino))
+ return 0; /* success */
+
@@ -36978,12 +37391,12 @@ index 000000000000..35ea33469d36
+ return err;
+}
+
-+static int au_xino_do_write(vfs_writef_t write, struct file *file,
-+ struct au_xi_calc *calc, ino_t ino)
++static int au_xino_do_write(struct file *file, struct au_xi_calc *calc,
++ ino_t ino)
+{
+ ssize_t sz;
+
-+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &calc->pos);
++ sz = xino_fwrite(file, &ino, sizeof(ino), &calc->pos);
+ if (sz == sizeof(ino))
+ return 0; /* success */
+
@@ -37033,7 +37446,7 @@ index 000000000000..35ea33469d36
+ goto out;
+ }
+
-+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, file, &calc, ino);
++ err = au_xino_do_write(file, &calc, ino);
+ if (!err) {
+ br = au_sbr(sb, bindex);
+ if (au_opt_test(mnt_flags, TRUNC_XINO)
@@ -37047,40 +37460,27 @@ index 000000000000..35ea33469d36
+ return -EIO;
+}
+
-+static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf,
-+ size_t size, loff_t *pos);
++static ssize_t xino_fread_wkq(struct file *file, void *buf, size_t size,
++ loff_t *pos);
+
+/* todo: unnecessary to support mmap_sem since kernel-space? */
-+ssize_t xino_fread(vfs_readf_t func, struct file *file, void *kbuf, size_t size,
-+ loff_t *pos)
++ssize_t xino_fread(struct file *file, void *kbuf, size_t size, loff_t *pos)
+{
+ ssize_t err;
-+ mm_segment_t oldfs;
-+ union {
-+ void *k;
-+ char __user *u;
-+ } buf;
+ int i;
+ const int prevent_endless = 10;
+
+ i = 0;
-+ buf.k = kbuf;
-+ oldfs = get_fs();
-+ set_fs(KERNEL_DS);
+ do {
-+ err = func(file, buf.u, size, pos);
++ err = vfsub_read_k(file, kbuf, size, pos);
+ if (err == -EINTR
+ && !au_wkq_test()
+ && fatal_signal_pending(current)) {
-+ set_fs(oldfs);
-+ err = xino_fread_wkq(func, file, kbuf, size, pos);
++ err = xino_fread_wkq(file, kbuf, size, pos);
+ BUG_ON(err == -EINTR);
-+ oldfs = get_fs();
-+ set_fs(KERNEL_DS);
+ }
+ } while (i++ < prevent_endless
+ && (err == -EAGAIN || err == -EINTR));
-+ set_fs(oldfs);
+
+#if 0 /* reserved for future use */
+ if (err > 0)
@@ -37092,7 +37492,6 @@ index 000000000000..35ea33469d36
+
+struct xino_fread_args {
+ ssize_t *errp;
-+ vfs_readf_t func;
+ struct file *file;
+ void *buf;
+ size_t size;
@@ -37102,17 +37501,16 @@ index 000000000000..35ea33469d36
+static void call_xino_fread(void *args)
+{
+ struct xino_fread_args *a = args;
-+ *a->errp = xino_fread(a->func, a->file, a->buf, a->size, a->pos);
++ *a->errp = xino_fread(a->file, a->buf, a->size, a->pos);
+}
+
-+static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf,
-+ size_t size, loff_t *pos)
++static ssize_t xino_fread_wkq(struct file *file, void *buf, size_t size,
++ loff_t *pos)
+{
+ ssize_t err;
+ int wkq_err;
+ struct xino_fread_args args = {
+ .errp = &err,
-+ .func = func,
+ .file = file,
+ .buf = buf,
+ .size = size,
@@ -37126,39 +37524,27 @@ index 000000000000..35ea33469d36
+ return err;
+}
+
-+static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf,
-+ size_t size, loff_t *pos);
++static ssize_t xino_fwrite_wkq(struct file *file, void *buf, size_t size,
++ loff_t *pos);
+
-+static ssize_t do_xino_fwrite(vfs_writef_t func, struct file *file, void *kbuf,
-+ size_t size, loff_t *pos)
++static ssize_t do_xino_fwrite(struct file *file, void *kbuf, size_t size,
++ loff_t *pos)
+{
+ ssize_t err;
-+ mm_segment_t oldfs;
-+ union {
-+ void *k;
-+ const char __user *u;
-+ } buf;
+ int i;
+ const int prevent_endless = 10;
+
+ i = 0;
-+ buf.k = kbuf;
-+ oldfs = get_fs();
-+ set_fs(KERNEL_DS);
+ do {
-+ err = func(file, buf.u, size, pos);
++ err = vfsub_write_k(file, kbuf, size, pos);
+ if (err == -EINTR
+ && !au_wkq_test()
+ && fatal_signal_pending(current)) {
-+ set_fs(oldfs);
-+ err = xino_fwrite_wkq(func, file, kbuf, size, pos);
++ err = xino_fwrite_wkq(file, kbuf, size, pos);
+ BUG_ON(err == -EINTR);
-+ oldfs = get_fs();
-+ set_fs(KERNEL_DS);
+ }
+ } while (i++ < prevent_endless
+ && (err == -EAGAIN || err == -EINTR));
-+ set_fs(oldfs);
+
+#if 0 /* reserved for future use */
+ if (err > 0)
@@ -37170,7 +37556,6 @@ index 000000000000..35ea33469d36
+
+struct do_xino_fwrite_args {
+ ssize_t *errp;
-+ vfs_writef_t func;
+ struct file *file;
+ void *buf;
+ size_t size;
@@ -37180,17 +37565,16 @@ index 000000000000..35ea33469d36
+static void call_do_xino_fwrite(void *args)
+{
+ struct do_xino_fwrite_args *a = args;
-+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
++ *a->errp = do_xino_fwrite(a->file, a->buf, a->size, a->pos);
+}
+
-+static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf,
-+ size_t size, loff_t *pos)
++static ssize_t xino_fwrite_wkq(struct file *file, void *buf, size_t size,
++ loff_t *pos)
+{
+ ssize_t err;
+ int wkq_err;
+ struct do_xino_fwrite_args args = {
+ .errp = &err,
-+ .func = func,
+ .file = file,
+ .buf = buf,
+ .size = size,
@@ -37208,18 +37592,17 @@ index 000000000000..35ea33469d36
+ return err;
+}
+
-+ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf,
-+ size_t size, loff_t *pos)
++ssize_t xino_fwrite(struct file *file, void *buf, size_t size, loff_t *pos)
+{
+ ssize_t err;
+
+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
+ lockdep_off();
-+ err = do_xino_fwrite(func, file, buf, size, pos);
++ err = do_xino_fwrite(file, buf, size, pos);
+ lockdep_on();
+ } else {
+ lockdep_off();
-+ err = xino_fwrite_wkq(func, file, buf, size, pos);
++ err = xino_fwrite_wkq(file, buf, size, pos);
+ lockdep_on();
+ }
+
@@ -37270,17 +37653,17 @@ index 000000000000..35ea33469d36
+ p = sbinfo->si_xib_buf;
+ pos = sbinfo->si_xib_last_pindex;
+ pos *= PAGE_SIZE;
-+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
++ sz = xino_fwrite(xib, p, PAGE_SIZE, &pos);
+ if (unlikely(sz != PAGE_SIZE))
+ goto out;
+
+ pos = pindex;
+ pos *= PAGE_SIZE;
+ if (vfsub_f_size_read(xib) >= pos + PAGE_SIZE)
-+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
++ sz = xino_fread(xib, p, PAGE_SIZE, &pos);
+ else {
+ memset(p, 0, PAGE_SIZE);
-+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
++ sz = xino_fwrite(xib, p, PAGE_SIZE, &pos);
+ }
+ if (sz == PAGE_SIZE) {
+ sbinfo->si_xib_last_pindex = pindex;
@@ -37331,7 +37714,6 @@ index 000000000000..35ea33469d36
+ unsigned long pindex;
+ loff_t pos, pend;
+ struct au_sbinfo *sbinfo;
-+ vfs_readf_t func;
+ ino_t *ino;
+ unsigned long *p;
+
@@ -37339,11 +37721,10 @@ index 000000000000..35ea33469d36
+ sbinfo = au_sbi(sb);
+ MtxMustLock(&sbinfo->si_xib_mtx);
+ p = sbinfo->si_xib_buf;
-+ func = sbinfo->si_xread;
+ pend = vfsub_f_size_read(file);
+ pos = 0;
+ while (pos < pend) {
-+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
++ sz = xino_fread(file, page, PAGE_SIZE, &pos);
+ err = sz;
+ if (unlikely(sz <= 0))
+ goto out;
@@ -37432,7 +37813,7 @@ index 000000000000..35ea33469d36
+ p = sbinfo->si_xib_buf;
+ memset(p, 0, PAGE_SIZE);
+ pos = 0;
-+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
++ sz = xino_fwrite(sbinfo->si_xib, p, PAGE_SIZE, &pos);
+ if (unlikely(sz != PAGE_SIZE)) {
+ err = sz;
+ AuIOErr("err %d\n", err);
@@ -37530,9 +37911,10 @@ index 000000000000..35ea33469d36
+ if (unlikely(ul)) {
+ pr_warn("xi_writing %lu\n", ul);
+ hlist_bl_lock(hbl);
-+ hlist_bl_for_each_entry_safe (p, pos, n, hbl, node) {
++ hlist_bl_for_each_entry_safe(p, pos, n, hbl, node) {
+ hlist_bl_del(&p->node);
-+ au_kfree_rcu(p);
++ /* kmemleak reported au_kfree_rcu() doesn't free it */
++ kfree(p);
+ }
+ hlist_bl_unlock(hbl);
+ }
@@ -37570,7 +37952,6 @@ index 000000000000..35ea33469d36
+ SiMustWriteLock(sb);
+
+ sbinfo = au_sbi(sb);
-+ /* unnecessary to clear sbinfo->si_xread and ->si_xwrite */
+ if (sbinfo->si_xib)
+ fput(sbinfo->si_xib);
+ sbinfo->si_xib = NULL;
@@ -37597,8 +37978,6 @@ index 000000000000..35ea33469d36
+ if (sbinfo->si_xib)
+ fput(sbinfo->si_xib);
+ sbinfo->si_xib = file;
-+ sbinfo->si_xread = vfs_readf(file);
-+ sbinfo->si_xwrite = vfs_writef(file);
+ xi_sb = file_inode(file)->i_sb;
+ sbinfo->si_ximaxent = xi_sb->s_maxbytes;
+ if (unlikely(sbinfo->si_ximaxent < PAGE_SIZE)) {
@@ -37619,8 +37998,7 @@ index 000000000000..35ea33469d36
+ sbinfo->si_xib_next_bit = 0;
+ if (vfsub_f_size_read(file) < PAGE_SIZE) {
+ pos = 0;
-+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
-+ PAGE_SIZE, &pos);
++ err = xino_fwrite(file, sbinfo->si_xib_buf, PAGE_SIZE, &pos);
+ if (unlikely(err != PAGE_SIZE))
+ goto out_free;
+ }
@@ -37671,7 +38049,6 @@ index 000000000000..35ea33469d36
+}
+
+struct au_xino_do_set_br {
-+ vfs_writef_t writef;
+ struct au_branch *br;
+ ino_t h_ino;
+ aufs_bindex_t bshared;
@@ -37713,7 +38090,7 @@ index 000000000000..35ea33469d36
+ goto out;
+ AuDebugOn(!file);
+
-+ err = au_xino_do_write(args->writef, file, &calc, AUFS_ROOT_INO);
++ err = au_xino_do_write(file, &calc, AUFS_ROOT_INO);
+ if (unlikely(err))
+ au_xino_put(br);
+
@@ -37733,7 +38110,6 @@ index 000000000000..35ea33469d36
+
+ bbot = au_sbbot(sb);
+ inode = d_inode(sb->s_root);
-+ args.writef = au_sbi(sb)->si_xwrite;
+ for (bindex = 0; bindex <= bbot; bindex++) {
+ args.h_ino = au_h_iptr(inode, bindex)->i_ino;
+ args.br = au_sbr(sb, bindex);
@@ -37888,7 +38264,6 @@ index 000000000000..35ea33469d36
+ .br = br
+ };
+
-+ args.writef = au_sbi(sb)->si_xwrite;
+ args.bshared = sbr_find_shared(sb, /*btop*/0, au_sbbot(sb),
+ au_br_sb(br));
+ err = au_xino_do_set_br(sb, base, &args);
@@ -37972,7 +38347,6 @@ index 000000000000..35ea33469d36
+ struct au_hinode *hi;
+ struct inode *h_inode;
+ struct au_branch *br;
-+ vfs_writef_t xwrite;
+ struct au_xi_calc calc;
+ struct file *file;
+
@@ -37994,7 +38368,6 @@ index 000000000000..35ea33469d36
+ if (bindex < 0)
+ return;
+
-+ xwrite = au_sbi(sb)->si_xwrite;
+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
+ hi = au_hinode(iinfo, bindex);
+ bbot = iinfo->ii_bbot;
@@ -38015,7 +38388,7 @@ index 000000000000..35ea33469d36
+ if (IS_ERR_OR_NULL(file))
+ continue;
+
-+ err = au_xino_do_write(xwrite, file, &calc, /*ino*/0);
++ err = au_xino_do_write(file, &calc, /*ino*/0);
+ if (!err && try_trunc
+ && au_test_fs_trunc_xino(au_br_sb(br)))
+ xino_try_trunc(sb, br);
@@ -38140,15 +38513,15 @@ index 000000000000..35ea33469d36
+}
diff --git a/include/uapi/linux/aufs_type.h b/include/uapi/linux/aufs_type.h
new file mode 100644
-index 000000000000..14841899ea18
+index 000000000000..83d3a5132b5a
--- /dev/null
+++ b/include/uapi/linux/aufs_type.h
@@ -0,0 +1,452 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
-+ * Copyright (C) 2005-2019 Junjiro R. Okajima
++ * Copyright (C) 2005-2022 Junjiro R. Okajima
+ *
-+ * This program, aufs is free software; you can redistribute it and/or modify
++ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
@@ -38179,14 +38552,14 @@ index 000000000000..14841899ea18
+#define pr_fmt(fmt) \
+ AUFS_NAME " %s:%d:%.*s[%d]: " fmt, __func__, __LINE__, \
+ (int)sizeof(current->comm), current->comm, current->pid
++#include <linux/limits.h>
+#else
+#include <stdint.h>
+#include <sys/types.h>
++#include <limits.h>
+#endif /* __KERNEL__ */
+
-+#include <linux/limits.h>
-+
-+#define AUFS_VERSION "5.4.3-20200113"
++#define AUFS_VERSION "6.5-20230918"
+
+/* todo? move this to linux-2.6.19/include/magic.h */
+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
@@ -38433,7 +38806,7 @@ index 000000000000..14841899ea18
+ uint8_t type;
+ uint8_t nlen;
+ uint8_t wh;
-+ char name[0];
++ char name[];
+} __aligned(8);
+
+static inline int au_rdu_len(int nlen)
@@ -38484,7 +38857,7 @@ index 000000000000..14841899ea18
+ uint8_t oldnamelen;
+ uint64_t _padding;
+ };
-+ uint8_t oldname[0];
++ uint8_t oldname[];
+} __aligned(8);
+
+struct au_drinfo_fdata {
@@ -38578,7 +38951,7 @@ index 000000000000..14841899ea18
+ struct {
+ int16_t id;
+ int perm;
-+ char path[0];
++ char path[];
+ };
+} __aligned(8);
+
@@ -38597,5 +38970,5 @@ index 000000000000..14841899ea18
+
+#endif /* __AUFS_TYPE_H__ */
--
-2.19.1
+2.34.1
diff --git a/features/aufs/aufs6-correct-do_splice_from-prototype.patch b/features/aufs/aufs6-correct-do_splice_from-prototype.patch
new file mode 100644
index 00000000..dd83db1e
--- /dev/null
+++ b/features/aufs/aufs6-correct-do_splice_from-prototype.patch
@@ -0,0 +1,26 @@
+From c76e5c498001148b22148fadc86611fd1874caa9 Mon Sep 17 00:00:00 2001
+From: Bruce Ashfield <bruce.ashfield@gmail.com>
+Date: Thu, 25 Jan 2024 11:17:19 -0500
+Subject: [PATCH] aufs6: correct do_splice_from prototype
+
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ include/linux/splice.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/linux/splice.h b/include/linux/splice.h
+index 8024911403e9..727e61a98c49 100644
+--- a/include/linux/splice.h
++++ b/include/linux/splice.h
+@@ -109,7 +109,7 @@ extern void splice_shrink_spd(struct splice_pipe_desc *);
+ extern const struct pipe_buf_operations page_cache_pipe_buf_ops;
+ extern const struct pipe_buf_operations default_pipe_buf_ops;
+
+-extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
++extern ssize_t do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+ loff_t *ppos, size_t len, unsigned int flags);
+ extern long do_splice_to(struct file *in, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t len,
+--
+2.39.2
+
diff --git a/features/aufs/aufs6-fix-magic.mk-include-path.patch b/features/aufs/aufs6-fix-magic.mk-include-path.patch
new file mode 100644
index 00000000..9bb1cf43
--- /dev/null
+++ b/features/aufs/aufs6-fix-magic.mk-include-path.patch
@@ -0,0 +1,37 @@
+From 001144b1c29e0214cad19720e6e1c35a576b124c Mon Sep 17 00:00:00 2001
+From: Bruce Ashfield <bruce.ashfield@gmail.com>
+Date: Thu, 6 Jul 2023 11:34:59 -0400
+Subject: [PATCH 7/8] aufs6: fix magic.mk include path
+
+commit 482d7131560c51da3ca [aufs stdalone: make it standalone] in the
+aufs upstream changes the way that the .mk file is included.
+
+This doesn't work properly with all kernel build processes, so we
+restore the use of srctree/src to locate the file.
+
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/aufs/Makefile | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/fs/aufs/Makefile b/fs/aufs/Makefile
+index 4af8ecde3e3f..72db3cae2b92 100644
+--- a/fs/aufs/Makefile
++++ b/fs/aufs/Makefile
+@@ -1,10 +1,10 @@
+ # SPDX-License-Identifier: GPL-2.0
+
+-include ${src}/magic.mk
++include ${srctree}/${src}/magic.mk
+ ifeq (${CONFIG_AUFS_FS},m)
+-include ${src}/conf.mk
++include ${srctree}/${src}/conf.mk
+ endif
+--include ${src}/priv_def.mk
++-include ${srctree}/${src}/priv_def.mk
+
+ # cf. include/linux/kernel.h
+ # enable pr_debug
+--
+2.34.1
+
diff --git a/features/aufs/aufs5-kbuild.patch b/features/aufs/aufs6-kbuild.patch
index f5cef0d3..57532dd5 100644
--- a/features/aufs/aufs5-kbuild.patch
+++ b/features/aufs/aufs6-kbuild.patch
@@ -1,7 +1,7 @@
-From aa75a790b5420a7ed5ab405c3232969b921d5746 Mon Sep 17 00:00:00 2001
+From 9962a8dfbc2b485c58d9ca511ae7bdfd808f78cc Mon Sep 17 00:00:00 2001
From: Bruce Ashfield <bruce.ashfield@gmail.com>
-Date: Mon, 13 Jan 2020 12:30:06 -0500
-Subject: [PATCH 1/5] aufs5: kbuild
+Date: Thu, 21 Sep 2023 17:47:14 -0400
+Subject: [PATCH 1/8] aufs6: kbuild
Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
---
@@ -10,26 +10,26 @@ Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
2 files changed, 2 insertions(+)
diff --git a/fs/Kconfig b/fs/Kconfig
-index 9bdef69b0358..73ea301c9119 100644
+index 3800e18ad2ea..a0b5168e1ef6 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
-@@ -265,6 +265,7 @@ source "fs/pstore/Kconfig"
- source "fs/sysv/Kconfig"
+@@ -332,6 +332,7 @@ source "fs/sysv/Kconfig"
source "fs/ufs/Kconfig"
source "fs/erofs/Kconfig"
+ source "fs/vboxsf/Kconfig"
+source "fs/aufs/Kconfig"
endif # MISC_FILESYSTEMS
diff --git a/fs/Makefile b/fs/Makefile
-index 6c03b014a129..7876ba238244 100644
+index 23cc0a3852aa..d58a3f162e31 100644
--- a/fs/Makefile
+++ b/fs/Makefile
-@@ -133,3 +133,4 @@ obj-$(CONFIG_PSTORE) += pstore/
- obj-$(CONFIG_EFIVAR_FS) += efivarfs/
- obj-$(CONFIG_EROFS_FS) += erofs/
+@@ -130,3 +130,4 @@ obj-$(CONFIG_EROFS_FS) += erofs/
+ obj-$(CONFIG_VBOXSF_FS) += vboxsf/
+ obj-$(CONFIG_ZONEFS_FS) += zonefs/
obj-$(CONFIG_YAFFS_FS) += yaffs2/
+obj-$(CONFIG_AUFS_FS) += aufs/
--
-2.19.1
+2.34.1
diff --git a/features/aufs/aufs5-mmap.patch b/features/aufs/aufs6-mmap.patch
index e95f7328..d1e5168f 100644
--- a/features/aufs/aufs5-mmap.patch
+++ b/features/aufs/aufs6-mmap.patch
@@ -1,43 +1,43 @@
-From 74a8e4bf3f2bc46bf02280185310367df8b274ad Mon Sep 17 00:00:00 2001
+From 550fbd6a226ed0b04b497dd4dcf5e14c7cd113f1 Mon Sep 17 00:00:00 2001
From: Bruce Ashfield <bruce.ashfield@gmail.com>
-Date: Mon, 13 Jan 2020 12:31:31 -0500
-Subject: [PATCH 3/5] aufs5: mmap
+Date: Thu, 21 Sep 2023 17:49:39 -0400
+Subject: [PATCH] aufs6: mmap
Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
---
fs/proc/base.c | 2 +-
fs/proc/nommu.c | 5 ++-
- fs/proc/task_mmu.c | 7 +++-
+ fs/proc/task_mmu.c | 6 ++-
fs/proc/task_nommu.c | 5 ++-
- include/linux/mm.h | 22 ++++++++++
- include/linux/mm_types.h | 2 +
+ include/linux/mm.h | 37 +++++++++++++++++
+ include/linux/mm_types.h | 6 +++
kernel/fork.c | 2 +-
- mm/Makefile | 2 +-
+ mm/Makefile | 1 +
mm/filemap.c | 2 +-
- mm/mmap.c | 33 +++++++++++----
+ mm/mmap.c | 41 +++++++++++++++----
mm/nommu.c | 10 ++---
mm/prfile.c | 86 ++++++++++++++++++++++++++++++++++++++++
- 12 files changed, 157 insertions(+), 21 deletions(-)
+ 12 files changed, 184 insertions(+), 19 deletions(-)
create mode 100644 mm/prfile.c
diff --git a/fs/proc/base.c b/fs/proc/base.c
-index ebea9501afb8..dc7edc5f7267 100644
+index 98a031ac2648..9cd1d25f9fc0 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
-@@ -2037,7 +2037,7 @@ static int map_files_get_link(struct dentry *dentry, struct path *path)
+@@ -2215,7 +2215,7 @@ static int map_files_get_link(struct dentry *dentry, struct path *path)
rc = -ENOENT;
vma = find_exact_vma(mm, vm_start, vm_end);
if (vma && vma->vm_file) {
-- *path = vma->vm_file->f_path;
-+ *path = vma_pr_or_file(vma)->f_path;
+- *path = *file_user_path(vma->vm_file);
++ *path = *file_user_path(vma_pr_or_file(vma));
path_get(path);
rc = 0;
}
diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c
-index 14c2badb8fd9..65afe5287e43 100644
+index c6e7ebc63756..d7ccfd909764 100644
--- a/fs/proc/nommu.c
+++ b/fs/proc/nommu.c
-@@ -41,7 +41,10 @@ static int nommu_region_show(struct seq_file *m, struct vm_region *region)
+@@ -39,7 +39,10 @@ static int nommu_region_show(struct seq_file *m, struct vm_region *region)
file = region->vm_file;
if (file) {
@@ -50,35 +50,35 @@ index 14c2badb8fd9..65afe5287e43 100644
ino = inode->i_ino;
}
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
-index 9442631fd4af..1fa8a5fcdeee 100644
+index 3f78ebbb795f..32f9aaf5345e 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
-@@ -309,7 +309,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
+@@ -273,8 +273,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
const char *name = NULL;
if (file) {
-- struct inode *inode = file_inode(vma->vm_file);
+- const struct inode *inode = file_user_inode(vma->vm_file);
+ struct inode *inode;
-+
+
+ file = vma_pr_or_file(vma);
-+ inode = file_inode(file);
++ inode = file_user_inode(vma->vm_file);
dev = inode->i_sb->s_dev;
ino = inode->i_ino;
pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
-@@ -1819,7 +1822,7 @@ static int show_numa_map(struct seq_file *m, void *v)
+@@ -2701,7 +2703,7 @@ static int show_numa_map(struct seq_file *m, void *v)
struct proc_maps_private *proc_priv = &numa_priv->proc_maps;
struct vm_area_struct *vma = v;
struct numa_maps *md = &numa_priv->md;
- struct file *file = vma->vm_file;
+ struct file *file = vma_pr_or_file(vma);
struct mm_struct *mm = vma->vm_mm;
- struct mempolicy *pol;
char buffer[64];
+ struct mempolicy *pol;
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
-index 7907e6419e57..d17209cf52bc 100644
+index bce674533000..b12b5a75c799 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
-@@ -155,7 +155,10 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
+@@ -137,7 +137,10 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
file = vma->vm_file;
if (file) {
@@ -91,13 +91,14 @@ index 7907e6419e57..d17209cf52bc 100644
ino = inode->i_ino;
pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
diff --git a/include/linux/mm.h b/include/linux/mm.h
-index a2adf95b3f9c..70e1dccc1283 100644
+index f5a97dec5169..dc908f541ce9 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
-@@ -1510,6 +1510,28 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping,
- unmap_mapping_range(mapping, holebegin, holelen, 0);
- }
+@@ -2432,6 +2432,43 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping,
+ static inline struct vm_area_struct *vma_lookup(struct mm_struct *mm,
+ unsigned long addr);
++#if 1 /* IS_ENABLED(CONFIG_AUFS_FS) */
+extern void vma_do_file_update_time(struct vm_area_struct *, const char[], int);
+extern struct file *vma_do_pr_or_file(struct vm_area_struct *, const char[],
+ int);
@@ -120,101 +121,105 @@ index a2adf95b3f9c..70e1dccc1283 100644
+#define vmr_fput(region) vmr_do_fput(region, __func__, __LINE__)
+#endif /* !CONFIG_MMU */
+
++#else
++
++#define vma_file_update_time(vma) file_update_time((vma)->vm_file)
++#define vma_pr_or_file(vma) (vma)->vm_file
++#define vma_get_file(vma) get_file((vma)->vm_file)
++#define vma_fput(vma) fput((vma)->vm_file)
++
++#ifndef CONFIG_MMU
++#define vmr_pr_or_file(region) (region)->vm_file
++#define vmr_fput(region) fput((region)->vm_file)
++#endif /* !CONFIG_MMU */
++
++#endif /* CONFIG_AUFS_FS */
++
extern int access_process_vm(struct task_struct *tsk, unsigned long addr,
void *buf, int len, unsigned int gup_flags);
extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
-index 270aa8fd2800..33848c2165e2 100644
+index 8b611e13153e..f5f10bfa5b63 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
-@@ -267,6 +267,7 @@ struct vm_region {
+@@ -527,6 +527,9 @@ struct vm_region {
unsigned long vm_top; /* region allocated to here */
unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */
struct file *vm_file; /* the backing file or NULL */
++#if 1 /* IS_ENABLED(CONFIG_AUFS_FS) */
+ struct file *vm_prfile; /* the virtual backing file or NULL */
++#endif
int vm_usage; /* region usage count (access under nommu_region_sem) */
bool vm_icache_flushed : 1; /* true if the icache has been flushed for
-@@ -341,6 +342,7 @@ struct vm_area_struct {
+@@ -691,6 +694,9 @@ struct vm_area_struct {
unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE
units */
struct file * vm_file; /* File we map to (can be NULL). */
++#if 1 /* IS_ENABLED(CONFIG_AUFS_FS) */
+ struct file *vm_prfile; /* shadow of vm_file */
++#endif
void * vm_private_data; /* was vm_pte (shared mem) */
- #ifdef CONFIG_SWAP
+ #ifdef CONFIG_ANON_VMA_NAME
diff --git a/kernel/fork.c b/kernel/fork.c
-index 6cabc124378c..53a5a521aba8 100644
+index 47ff3b35352e..41a80f248514 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
-@@ -562,7 +562,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
- struct inode *inode = file_inode(file);
+@@ -716,7 +716,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
+ if (file) {
struct address_space *mapping = file->f_mapping;
- get_file(file);
+ vma_get_file(tmp);
- if (tmp->vm_flags & VM_DENYWRITE)
- atomic_dec(&inode->i_writecount);
i_mmap_lock_write(mapping);
+ if (vma_is_shared_maywrite(tmp))
+ mapping_allow_writable(mapping);
diff --git a/mm/Makefile b/mm/Makefile
-index d996846697ef..fbadb91df4e4 100644
+index e4b5b75aaec9..d69ba9efb769 100644
--- a/mm/Makefile
+++ b/mm/Makefile
-@@ -42,7 +42,7 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \
- mm_init.o mmu_context.o percpu.o slab_common.o \
- compaction.o vmacache.o \
- interval_tree.o list_lru.o workingset.o \
-- debug.o gup.o $(mmu-y)
-+ prfile.o debug.o gup.o $(mmu-y)
-
- # Give 'page_alloc' its own module-parameter namespace
- page-alloc-y := page_alloc.o
+@@ -134,3 +134,4 @@ obj-$(CONFIG_IO_MAPPING) += io-mapping.o
+ obj-$(CONFIG_HAVE_BOOTMEM_INFO_NODE) += bootmem_info.o
+ obj-$(CONFIG_GENERIC_IOREMAP) += ioremap.o
+ obj-$(CONFIG_SHRINKER_DEBUG) += shrinker_debug.o
++obj-y += prfile.o
diff --git a/mm/filemap.c b/mm/filemap.c
-index 1f5731768222..a3def534d7c1 100644
+index 750e779c23db..b84a752ff676 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
-@@ -2675,7 +2675,7 @@ vm_fault_t filemap_page_mkwrite(struct vm_fault *vmf)
+@@ -3587,7 +3587,7 @@ vm_fault_t filemap_page_mkwrite(struct vm_fault *vmf)
vm_fault_t ret = VM_FAULT_LOCKED;
- sb_start_pagefault(inode->i_sb);
+ sb_start_pagefault(mapping->host->i_sb);
- file_update_time(vmf->vma->vm_file);
+ vma_file_update_time(vmf->vma);
- lock_page(page);
- if (page->mapping != inode->i_mapping) {
- unlock_page(page);
+ folio_lock(folio);
+ if (folio->mapping != mapping) {
+ folio_unlock(folio);
diff --git a/mm/mmap.c b/mm/mmap.c
-index 4390dbea4aa5..e697082d36e4 100644
+index b78e83d351d2..e2ae3999a51c 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
-@@ -176,7 +176,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma)
+@@ -140,7 +140,7 @@ static void remove_vma(struct vm_area_struct *vma, bool unreachable)
if (vma->vm_ops && vma->vm_ops->close)
vma->vm_ops->close(vma);
if (vma->vm_file)
- fput(vma->vm_file);
+ vma_fput(vma);
mpol_put(vma_policy(vma));
- vm_area_free(vma);
- return next;
-@@ -934,7 +934,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
- if (remove_next) {
- if (file) {
- uprobe_munmap(next, next->vm_start, next->vm_end);
-- fput(file);
-+ vma_fput(vma);
+ if (unreachable)
+ __vm_area_free(vma);
+@@ -554,7 +554,7 @@ static inline void vma_complete(struct vma_prepare *vp,
+ if (vp->file) {
+ uprobe_munmap(vp->remove, vp->remove->vm_start,
+ vp->remove->vm_end);
+- fput(vp->file);
++ vma_fput(vp->vma);
}
- if (next->anon_vma)
- anon_vma_merge(vma, next);
-@@ -1859,8 +1859,8 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
- return addr;
-
- unmap_and_free_vma:
-+ vma_fput(vma);
- vma->vm_file = NULL;
-- fput(file);
-
- /* Undo any partial mapping done by a device driver. */
- unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end);
-@@ -2689,7 +2689,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
+ if (vp->remove->anon_vma)
+ anon_vma_merge(vp->vma, vp->remove);
+@@ -2355,7 +2355,7 @@ static int __split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma,
goto out_free_mpol;
if (new->vm_file)
@@ -223,54 +228,70 @@ index 4390dbea4aa5..e697082d36e4 100644
if (new->vm_ops && new->vm_ops->open)
new->vm_ops->open(new);
-@@ -2708,7 +2708,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
- if (new->vm_ops && new->vm_ops->close)
- new->vm_ops->close(new);
- if (new->vm_file)
-- fput(new->vm_file);
-+ vma_fput(new);
- unlink_anon_vmas(new);
- out_free_mpol:
- mpol_put(vma_policy(new));
-@@ -2900,7 +2900,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
- struct vm_area_struct *vma;
+@@ -2853,7 +2853,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
+ * and cause general protection fault
+ * ultimately.
+ */
+- fput(vma->vm_file);
++ vma_fput(vma);
+ vm_area_free(vma);
+ vma = merge;
+ /* Update vm_flags to pick up the change. */
+@@ -2948,7 +2948,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
+
+ if (file || vma->vm_file) {
+ unmap_and_free_vma:
+- fput(vma->vm_file);
++ vma_fput(vma);
+ vma->vm_file = NULL;
+
+ vma_iter_set(&vmi, vma->vm_end);
+@@ -3010,6 +3010,9 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
unsigned long populate = 0;
unsigned long ret = -EINVAL;
-- struct file *file;
-+ struct file *file, *prfile;
+ struct file *file;
++#if 1 /* IS_ENABLED(CONFIG_AUFS_FS) */
++ struct file *prfile;
++#endif
- pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/vm/remap_file_pages.rst.\n",
+ pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/mm/remap_file_pages.rst.\n",
current->comm, current->pid);
-@@ -2975,10 +2975,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
- }
- }
+@@ -3068,10 +3071,34 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
+ if (vma->vm_flags & VM_LOCKED)
+ flags |= MAP_LOCKED;
-- file = get_file(vma->vm_file);
++#if 1 /* IS_ENABLED(CONFIG_AUFS_FS) */
+ vma_get_file(vma);
+ file = vma->vm_file;
+ prfile = vma->vm_prfile;
- ret = do_mmap_pgoff(vma->vm_file, start, size,
- prot, flags, pgoff, &populate, NULL);
++ ret = do_mmap(vma->vm_file, start, size,
++ prot, flags, pgoff, &populate, NULL);
+ if (!IS_ERR_VALUE(ret) && file && prfile) {
+ struct vm_area_struct *new_vma;
+
+ new_vma = find_vma(mm, ret);
+ if (!new_vma->vm_prfile)
+ new_vma->vm_prfile = prfile;
-+ if (new_vma != vma)
++ if (prfile)
+ get_file(prfile);
+ }
+ /*
+ * two fput()s instead of vma_fput(vma),
+ * coz vma may not be available anymore.
+ */
- fput(file);
++ fput(file);
+ if (prfile)
+ fput(prfile);
++#else
+ file = get_file(vma->vm_file);
+ ret = do_mmap(vma->vm_file, start, size,
+ prot, flags, 0, pgoff, &populate, NULL);
+ fput(file);
++#endif /* CONFIG_AUFS_FS */
out:
- up_write(&mm->mmap_sem);
+ mmap_write_unlock(mm);
if (populate)
-@@ -3268,7 +3285,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
+@@ -3418,7 +3445,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
if (anon_vma_clone(new_vma, vma))
goto out_free_mempol;
if (new_vma->vm_file)
@@ -278,12 +299,21 @@ index 4390dbea4aa5..e697082d36e4 100644
+ vma_get_file(new_vma);
if (new_vma->vm_ops && new_vma->vm_ops->open)
new_vma->vm_ops->open(new_vma);
- vma_link(mm, new_vma, prev, rb_link, rb_parent);
+ if (vma_link(mm, new_vma))
+@@ -3432,7 +3459,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
+ new_vma->vm_ops->close(new_vma);
+
+ if (new_vma->vm_file)
+- fput(new_vma->vm_file);
++ vma_fput(new_vma);
+
+ unlink_anon_vmas(new_vma);
+ out_free_mempol:
diff --git a/mm/nommu.c b/mm/nommu.c
-index 99b7ec318824..de5b6cd162fe 100644
+index b6dc558d3144..d96655486468 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
-@@ -552,7 +552,7 @@ static void __put_nommu_region(struct vm_region *region)
+@@ -523,7 +523,7 @@ static void __put_nommu_region(struct vm_region *region)
up_write(&nommu_region_sem);
if (region->vm_file)
@@ -292,7 +322,7 @@ index 99b7ec318824..de5b6cd162fe 100644
/* IO memory and memory shared directly out of the pagecache
* from ramfs/tmpfs mustn't be released here */
-@@ -690,7 +690,7 @@ static void delete_vma(struct mm_struct *mm, struct vm_area_struct *vma)
+@@ -603,7 +603,7 @@ static void delete_vma(struct mm_struct *mm, struct vm_area_struct *vma)
if (vma->vm_ops && vma->vm_ops->close)
vma->vm_ops->close(vma);
if (vma->vm_file)
@@ -301,7 +331,7 @@ index 99b7ec318824..de5b6cd162fe 100644
put_nommu_region(vma->vm_region);
vm_area_free(vma);
}
-@@ -1213,7 +1213,7 @@ unsigned long do_mmap(struct file *file,
+@@ -1135,7 +1135,7 @@ unsigned long do_mmap(struct file *file,
goto error_just_free;
}
}
@@ -310,9 +340,9 @@ index 99b7ec318824..de5b6cd162fe 100644
kmem_cache_free(vm_region_jar, region);
region = pregion;
result = start;
-@@ -1290,10 +1290,10 @@ unsigned long do_mmap(struct file *file,
- up_write(&nommu_region_sem);
+@@ -1221,10 +1221,10 @@ unsigned long do_mmap(struct file *file,
error:
+ vma_iter_free(&vmi);
if (region->vm_file)
- fput(region->vm_file);
+ vmr_fput(region);
@@ -325,7 +355,7 @@ index 99b7ec318824..de5b6cd162fe 100644
diff --git a/mm/prfile.c b/mm/prfile.c
new file mode 100644
-index 000000000000..024cdcfae1b1
+index 000000000000..8f820a235364
--- /dev/null
+++ b/mm/prfile.c
@@ -0,0 +1,86 @@
@@ -337,7 +367,7 @@ index 000000000000..024cdcfae1b1
+ *
+ * See Documentation/filesystems/aufs/design/06mmap.txt
+ *
-+ * Copyright (c) 2014-2019 Junjro R. Okajima
++ * Copyright (c) 2014-2022 Junjro R. Okajima
+ * Copyright (c) 2014 Ian Campbell
+ */
+
@@ -416,5 +446,5 @@ index 000000000000..024cdcfae1b1
+}
+#endif /* !CONFIG_MMU */
--
-2.19.1
+2.39.2
diff --git a/features/aufs/aufs6-standalone.patch b/features/aufs/aufs6-standalone.patch
new file mode 100644
index 00000000..d7ceb50a
--- /dev/null
+++ b/features/aufs/aufs6-standalone.patch
@@ -0,0 +1,266 @@
+From da930b7640bef946a6d703e28ec8c8d785245ab1 Mon Sep 17 00:00:00 2001
+From: Bruce Ashfield <bruce.ashfield@gmail.com>
+Date: Thu, 21 Sep 2023 17:50:11 -0400
+Subject: [PATCH 4/8] aufs6: standalone
+
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/dcache.c | 2 ++
+ fs/exec.c | 1 +
+ fs/fcntl.c | 1 +
+ fs/file_table.c | 1 +
+ fs/namespace.c | 3 +++
+ fs/notify/group.c | 1 +
+ fs/open.c | 1 +
+ fs/read_write.c | 2 ++
+ fs/splice.c | 1 +
+ fs/xattr.c | 1 +
+ kernel/locking/lockdep.c | 1 +
+ kernel/task_work.c | 1 +
+ security/security.c | 8 ++++++++
+ 13 files changed, 24 insertions(+)
+
+diff --git a/fs/dcache.c b/fs/dcache.c
+index 6c930ceed526..576ad162cdec 100644
+--- a/fs/dcache.c
++++ b/fs/dcache.c
+@@ -1450,6 +1450,7 @@ void d_walk(struct dentry *parent, void *data,
+ seq = 1;
+ goto again;
+ }
++EXPORT_SYMBOL_GPL(d_walk);
+
+ struct check_mount {
+ struct vfsmount *mnt;
+@@ -3051,6 +3052,7 @@ void d_exchange(struct dentry *dentry1, struct dentry *dentry2)
+
+ write_sequnlock(&rename_lock);
+ }
++EXPORT_SYMBOL_GPL(d_exchange);
+
+ /**
+ * d_ancestor - search for an ancestor
+diff --git a/fs/exec.c b/fs/exec.c
+index 6518e33ea813..b67efac6a1ad 100644
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -112,6 +112,7 @@ bool path_noexec(const struct path *path)
+ return (path->mnt->mnt_flags & MNT_NOEXEC) ||
+ (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC);
+ }
++EXPORT_SYMBOL_GPL(path_noexec);
+
+ #ifdef CONFIG_USELIB
+ /*
+diff --git a/fs/fcntl.c b/fs/fcntl.c
+index 84a52a8eec92..fdd334fc02fb 100644
+--- a/fs/fcntl.c
++++ b/fs/fcntl.c
+@@ -87,6 +87,7 @@ int setfl(int fd, struct file *filp, unsigned int arg)
+ out:
+ return error;
+ }
++EXPORT_SYMBOL_GPL(setfl);
+
+ static void f_modown(struct file *filp, struct pid *pid, enum pid_type type,
+ int force)
+diff --git a/fs/file_table.c b/fs/file_table.c
+index ee21b3da9d08..c45ac36795dd 100644
+--- a/fs/file_table.c
++++ b/fs/file_table.c
+@@ -225,6 +225,7 @@ struct file *alloc_empty_file(int flags, const struct cred *cred)
+ }
+ return ERR_PTR(-ENFILE);
+ }
++EXPORT_SYMBOL_GPL(alloc_empty_file);
+
+ /*
+ * Variant of alloc_empty_file() that doesn't check and modify nr_files.
+diff --git a/fs/namespace.c b/fs/namespace.c
+index 6c57487f126b..16be9ac1c734 100644
+--- a/fs/namespace.c
++++ b/fs/namespace.c
+@@ -466,6 +466,7 @@ void __mnt_drop_write(struct vfsmount *mnt)
+ mnt_dec_writers(real_mount(mnt));
+ preempt_enable();
+ }
++EXPORT_SYMBOL_GPL(__mnt_drop_write);
+
+ /**
+ * mnt_drop_write - give up write access to a mount
+@@ -877,6 +878,7 @@ int is_current_mnt_ns(struct vfsmount *mnt)
+ {
+ return check_mnt(real_mount(mnt));
+ }
++EXPORT_SYMBOL_GPL(is_current_mnt_ns);
+
+ /*
+ * vfsmount lock must be held for write
+@@ -2152,6 +2154,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
+ }
+ return 0;
+ }
++EXPORT_SYMBOL_GPL(iterate_mounts);
+
+ static void lock_mnt_tree(struct mount *mnt)
+ {
+diff --git a/fs/notify/group.c b/fs/notify/group.c
+index 1de6631a3925..3008eb37a18d 100644
+--- a/fs/notify/group.c
++++ b/fs/notify/group.c
+@@ -100,6 +100,7 @@ void fsnotify_get_group(struct fsnotify_group *group)
+ {
+ refcount_inc(&group->refcnt);
+ }
++EXPORT_SYMBOL_GPL(fsnotify_get_group);
+
+ /*
+ * Drop a reference to a group. Free it if it's through.
+diff --git a/fs/open.c b/fs/open.c
+index 98f6601fbac6..8624e4ffa15b 100644
+--- a/fs/open.c
++++ b/fs/open.c
+@@ -67,6 +67,7 @@ int do_truncate(struct mnt_idmap *idmap, struct dentry *dentry,
+ inode_unlock(dentry->d_inode);
+ return ret;
+ }
++EXPORT_SYMBOL_GPL(do_truncate);
+
+ long vfs_truncate(const struct path *path, loff_t length)
+ {
+diff --git a/fs/read_write.c b/fs/read_write.c
+index 4771701c896b..c79270aba792 100644
+--- a/fs/read_write.c
++++ b/fs/read_write.c
+@@ -477,6 +477,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
+ inc_syscr(current);
+ return ret;
+ }
++EXPORT_SYMBOL_GPL(vfs_read);
+
+ static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
+ {
+@@ -592,6 +593,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
+ file_end_write(file);
+ return ret;
+ }
++EXPORT_SYMBOL_GPL(vfs_write);
+
+ /* file_ppos returns &file->f_pos or NULL if file is stream */
+ static inline loff_t *file_ppos(struct file *file)
+diff --git a/fs/splice.c b/fs/splice.c
+index 7216ef993b5f..7ce1f1bc4268 100644
+--- a/fs/splice.c
++++ b/fs/splice.c
+@@ -932,6 +932,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
+ return warn_unsupported(out, "write");
+ return out->f_op->splice_write(pipe, out, ppos, len, flags);
+ }
++EXPORT_SYMBOL_GPL(do_splice_from);
+
+ /*
+ * Indicate to the caller that there was a premature EOF when reading from the
+diff --git a/fs/xattr.c b/fs/xattr.c
+index efd4736bc94b..ce1a2c39ab23 100644
+--- a/fs/xattr.c
++++ b/fs/xattr.c
+@@ -406,6 +406,7 @@ vfs_getxattr_alloc(struct mnt_idmap *idmap, struct dentry *dentry,
+ *xattr_value = value;
+ return error;
+ }
++EXPORT_SYMBOL_GPL(vfs_getxattr_alloc);
+
+ ssize_t
+ __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
+diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
+index db4297f60bd3..9aca18312afb 100644
+--- a/kernel/locking/lockdep.c
++++ b/kernel/locking/lockdep.c
+@@ -239,6 +239,7 @@ inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock)
+ */
+ return lock_classes + class_idx;
+ }
++EXPORT_SYMBOL_GPL(lockdep_hlock_class);
+ #define hlock_class(hlock) lockdep_hlock_class(hlock)
+
+ #ifdef CONFIG_LOCK_STAT
+diff --git a/kernel/task_work.c b/kernel/task_work.c
+index 065e1ef8fc8d..c623c6f0c645 100644
+--- a/kernel/task_work.c
++++ b/kernel/task_work.c
+@@ -182,3 +182,4 @@ void task_work_run(void)
+ } while (work);
+ }
+ }
++EXPORT_SYMBOL_GPL(task_work_run);
+diff --git a/security/security.c b/security/security.c
+index 23b129d482a7..fca4c5707a1c 100644
+--- a/security/security.c
++++ b/security/security.c
+@@ -1750,6 +1750,7 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry)
+ return 0;
+ return call_int_hook(path_rmdir, 0, dir, dentry);
+ }
++EXPORT_SYMBOL_GPL(security_path_rmdir);
+
+ /**
+ * security_path_unlink() - Check if removing a hard link is allowed
+@@ -1785,6 +1786,7 @@ int security_path_symlink(const struct path *dir, struct dentry *dentry,
+ return 0;
+ return call_int_hook(path_symlink, 0, dir, dentry, old_name);
+ }
++EXPORT_SYMBOL_GPL(security_path_symlink);
+
+ /**
+ * security_path_link - Check if creating a hard link is allowed
+@@ -1803,6 +1805,7 @@ int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
+ return 0;
+ return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry);
+ }
++EXPORT_SYMBOL_GPL(security_path_link);
+
+ /**
+ * security_path_rename() - Check if renaming a file is allowed
+@@ -1864,6 +1867,7 @@ int security_path_chmod(const struct path *path, umode_t mode)
+ return 0;
+ return call_int_hook(path_chmod, 0, path, mode);
+ }
++EXPORT_SYMBOL_GPL(security_path_chmod);
+
+ /**
+ * security_path_chown() - Check if changing the file's owner/group is allowed
+@@ -1881,6 +1885,7 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
+ return 0;
+ return call_int_hook(path_chown, 0, path, uid, gid);
+ }
++EXPORT_SYMBOL_GPL(security_path_chown);
+
+ /**
+ * security_path_chroot() - Check if changing the root directory is allowed
+@@ -2110,6 +2115,7 @@ int security_inode_permission(struct inode *inode, int mask)
+ return 0;
+ return call_int_hook(inode_permission, 0, inode, mask);
+ }
++EXPORT_SYMBOL_GPL(security_inode_permission);
+
+ /**
+ * security_inode_setattr() - Check if setting file attributes is allowed
+@@ -2588,6 +2594,7 @@ int security_file_permission(struct file *file, int mask)
+
+ return fsnotify_perm(file, mask);
+ }
++EXPORT_SYMBOL_GPL(security_file_permission);
+
+ /**
+ * security_file_alloc() - Allocate and init a file's LSM blob
+@@ -2854,6 +2861,7 @@ int security_file_truncate(struct file *file)
+ {
+ return call_int_hook(file_truncate, 0, file);
+ }
++EXPORT_SYMBOL_GPL(security_file_truncate);
+
+ /**
+ * security_task_alloc() - Allocate a task's LSM blob
+--
+2.34.1
+
diff --git a/features/random/random.cfg b/features/bluetooth/bluetooth-vhci.cfg
index bacab3cb..3f7c7850 100644
--- a/features/random/random.cfg
+++ b/features/bluetooth/bluetooth-vhci.cfg
@@ -1,2 +1,2 @@
# SPDX-License-Identifier: MIT
-CONFIG_RANDOM_TRUST_CPU=y
+CONFIG_BT_HCIVHCI=y
diff --git a/features/bluetooth/bluetooth-vhci.scc b/features/bluetooth/bluetooth-vhci.scc
new file mode 100644
index 00000000..e99f33d5
--- /dev/null
+++ b/features/bluetooth/bluetooth-vhci.scc
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable Bluetooth Virtual HCI device driver"
+define KFEATURE_COMPATIBILITY all
+
+include bluetooth.scc
+
+kconf non-hardware bluetooth-vhci.cfg
diff --git a/features/bluetooth/bluetooth.cfg b/features/bluetooth/bluetooth.cfg
index 3523b601..171cbe2b 100644
--- a/features/bluetooth/bluetooth.cfg
+++ b/features/bluetooth/bluetooth.cfg
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: MIT
# Dependencies
CONFIG_ISDN=y
-CONFIG_ISDN_CAPI=m
+CONFIG_ISDN_CAPI=y
# Features
CONFIG_BT=y
diff --git a/features/bpf/bpf.cfg b/features/bpf/bpf.cfg
index b90e87a5..50c27ceb 100644
--- a/features/bpf/bpf.cfg
+++ b/features/bpf/bpf.cfg
@@ -3,4 +3,5 @@ CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_BPF_EVENTS=y
+CONFIG_BPF_UNPRIV_DEFAULT_OFF=y
CONFIG_CGROUP_BPF=y
diff --git a/features/can/can.cfg b/features/can/can.cfg
index a15e6061..d50e8109 100644
--- a/features/can/can.cfg
+++ b/features/can/can.cfg
@@ -19,8 +19,6 @@ CONFIG_CAN_GS_USB=m
CONFIG_CAN_KVASER_USB=m
CONFIG_CAN_PEAK_USB=m
CONFIG_CAN_8DEV_USB=m
-# x86 PCH
-#CONFIG_PCH_CAN=m
# drivers for ISA/PCI cards
CONFIG_CAN_C_CAN_PCI=m
# Philips/NXP SJA1000 based PCI(e)
diff --git a/features/can/m_can.cfg b/features/can/m_can.cfg
new file mode 100644
index 00000000..d89b23aa
--- /dev/null
+++ b/features/can/m_can.cfg
@@ -0,0 +1,5 @@
+CONFIG_CAN=m
+CONFIG_CAN_M_CAN=m
+CONFIG_CAN_M_CAN_PCI=m
+CONFIG_CAN_M_CAN_PLATFORM=m
+CONFIG_CAN_M_CAN_TCAN4X5X=m
diff --git a/features/can/m_can.scc b/features/can/m_can.scc
new file mode 100644
index 00000000..9a169170
--- /dev/null
+++ b/features/can/m_can.scc
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable Bosch M_CAN controller support"
+define KFEATURE_COMPATIBILITY board
+
+kconf hardware m_can.cfg
diff --git a/features/cgroups/cgroups.cfg b/features/cgroups/cgroups.cfg
index 5c6cb1b0..d2d0c3ea 100644
--- a/features/cgroups/cgroups.cfg
+++ b/features/cgroups/cgroups.cfg
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: MIT
# General controller group
CONFIG_CGROUPS=y
-CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_DEBUG=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_DEVICE=y
@@ -13,13 +13,11 @@ CONFIG_CGROUP_NET_PRIO=y
CONFIG_CGROUP_PERF=y
CONFIG_MEMCG=y
-CONFIG_MEMCG_SWAP=y
CONFIG_CGROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
-CONFIG_RT_GROUP_SCHED=y
CONFIG_BLK_CGROUP=y
-# CONFIG_BFQ_CGROUP_DEBUG is not set
+CONFIG_BFQ_CGROUP_DEBUG=n
# Namespace controller
diff --git a/features/clear_warn_once/clear_warn_once-add-a-clear_warn_once-boot-parameter.patch b/features/clear_warn_once/clear_warn_once-add-a-clear_warn_once-boot-parameter.patch
new file mode 100644
index 00000000..8016e2a6
--- /dev/null
+++ b/features/clear_warn_once/clear_warn_once-add-a-clear_warn_once-boot-parameter.patch
@@ -0,0 +1,75 @@
+From 9ad5defd90591efb015c9a6c59b47108fe68e961 Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Wed, 16 Dec 2020 12:22:58 -0500
+Subject: [PATCH 3/3] clear_warn_once: add a clear_warn_once= boot parameter
+
+In the event debugfs is not mounted, or if built with the .config
+setting DEBUG_FS_ALLOW_NONE chosen, this gives the sysadmin access
+to reset the WARN_ONCE() state on a periodic basis.
+
+Link: https://lore.kernel.org/r/20201126063029.2030-1-paul.gortmaker@windriver.com
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ .../admin-guide/kernel-parameters.txt | 8 +++++++
+ kernel/panic.c | 21 +++++++++++++++++++
+ 2 files changed, 29 insertions(+)
+
+diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
+index 74ba077e99e5..b0c5a7458c03 100644
+--- a/Documentation/admin-guide/kernel-parameters.txt
++++ b/Documentation/admin-guide/kernel-parameters.txt
+@@ -5352,6 +5352,14 @@
+ vt.underline= [VT] Default color for underlined text; 0-15.
+ Default: 3 = cyan.
+
++ clear_warn_once=
++ [KNL]
++ Set the WARN_ONCE reset period in minutes. Normally
++ a WARN_ONCE() will only ever emit a message once per
++ boot, but for example, setting this to 60 would
++ effectively rate-limit WARN_ONCE to once per hour.
++ Default: 0 = never.
++
+ watchdog timers [HW,WDT] For information on watchdog timers,
+ see Documentation/watchdog/watchdog-parameters.rst
+ or other driver-specific files in the
+diff --git a/kernel/panic.c b/kernel/panic.c
+index e3a462e39062..f4f3633f4f69 100644
+--- a/kernel/panic.c
++++ b/kernel/panic.c
+@@ -697,10 +697,31 @@ static __init int register_warn_debugfs(void)
+ /* Don't care about failure */
+ debugfs_create_file_unsafe("clear_warn_once", 0600, NULL,
+ &clear_warn_once, &clear_warn_once_fops);
++
++ /* if a bootarg was used, set the initial timer */
++ if (clear_warn_once)
++ warn_once_set(NULL, clear_warn_once);
++
+ return 0;
+ }
+
+ device_initcall(register_warn_debugfs);
++
++static int __init warn_once_setup(char *s)
++{
++ int r;
++
++ if (!s)
++ return -EINVAL;
++
++ r = kstrtoull(s, 0, &clear_warn_once);
++ if (r)
++ return r;
++
++ return 1;
++}
++__setup("clear_warn_once=", warn_once_setup);
++
+ #endif
+
+ #ifdef CONFIG_STACKPROTECTOR
+--
+2.19.1
+
diff --git a/features/clear_warn_once/clear_warn_once-bind-a-timer-to-written-reset-value.patch b/features/clear_warn_once/clear_warn_once-bind-a-timer-to-written-reset-value.patch
new file mode 100644
index 00000000..63053deb
--- /dev/null
+++ b/features/clear_warn_once/clear_warn_once-bind-a-timer-to-written-reset-value.patch
@@ -0,0 +1,104 @@
+From fbda05a6df0125f733e0e28a3e0ae60bb6765d51 Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Wed, 16 Dec 2020 12:22:57 -0500
+Subject: [PATCH 2/3] clear_warn_once: bind a timer to written reset value
+
+Existing documentation has a write of "1" to clear/reset all the
+WARN_ONCE and similar to the as-booted state, so they can possibly
+be re-triggered again during debugging/testing.
+
+But having them auto-reset once a day, or once a week, might shed
+valuable information to a sysadmin on what the system is doing while
+trying to debug an issue.
+
+Here we extend the existing debugfs variable to bind a timer to the
+written value N, so that it will reset every N minutes, for N>1.
+Writing a zero will clear any previously set timer value.
+
+The pre-existing behaviour of writing N=1 will do a one-shot clear.
+
+Link: https://lore.kernel.org/r/20201126063029.2030-1-paul.gortmaker@windriver.com
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ .../admin-guide/clearing-warn-once.rst | 9 ++++++
+ kernel/panic.c | 32 +++++++++++++++++++
+ 2 files changed, 41 insertions(+)
+
+diff --git a/Documentation/admin-guide/clearing-warn-once.rst b/Documentation/admin-guide/clearing-warn-once.rst
+index 211fd926cf00..8d058bbc0859 100644
+--- a/Documentation/admin-guide/clearing-warn-once.rst
++++ b/Documentation/admin-guide/clearing-warn-once.rst
+@@ -7,3 +7,12 @@ echo 1 > /sys/kernel/debug/clear_warn_once
+
+ clears the state and allows the warnings to print once again.
+ This can be useful after test suite runs to reproduce problems.
++
++Values greater than one set a timer for a periodic state reset; e.g.
++
++echo 60 > /sys/kernel/debug/clear_warn_once
++
++will establish an hourly state reset, effectively turning WARN_ONCE
++into a long period rate-limited warning.
++
++Writing a value of zero (or one) will remove any previously set timer.
+diff --git a/kernel/panic.c b/kernel/panic.c
+index 53088219d7df..e3a462e39062 100644
+--- a/kernel/panic.c
++++ b/kernel/panic.c
+@@ -636,6 +636,7 @@ EXPORT_SYMBOL(__warn_printk);
+ /* Support resetting WARN*_ONCE state */
+
+ static u64 clear_warn_once;
++static bool warn_timer_active;
+
+ static void do_clear_warn_once(void)
+ {
+@@ -643,6 +644,14 @@ static void do_clear_warn_once(void)
+ memset(__start_once, 0, __end_once - __start_once);
+ }
+
++static void timer_warn_once(struct timer_list *timer)
++{
++ do_clear_warn_once();
++ timer->expires = jiffies + clear_warn_once * HZ * 60;
++ add_timer(timer);
++}
++static DEFINE_TIMER(warn_reset_timer, timer_warn_once);
++
+ static int warn_once_get(void *data, u64 *val)
+ {
+ *val = clear_warn_once;
+@@ -653,6 +662,29 @@ static int warn_once_set(void *data, u64 val)
+ {
+ clear_warn_once = val;
+
++ if (val > 1) { /* set/reset new timer */
++ unsigned long expires = jiffies + val * HZ * 60;
++
++ if (warn_timer_active) {
++ mod_timer(&warn_reset_timer, expires);
++ } else {
++ warn_timer_active = 1;
++ warn_reset_timer.expires = expires;
++ add_timer(&warn_reset_timer);
++ }
++ return 0;
++ }
++
++ if (warn_timer_active) {
++ del_timer_sync(&warn_reset_timer);
++ warn_timer_active = 0;
++ }
++ clear_warn_once = 0;
++
++ if (val == 0) /* cleared timer, we are done */
++ return 0;
++
++ /* Getting here means val == 1 ---> so clear existing data */
+ do_clear_warn_once();
+ return 0;
+ }
+--
+2.19.1
+
diff --git a/features/clear_warn_once/clear_warn_once-expand-debugfs-to-include-read-suppo.patch b/features/clear_warn_once/clear_warn_once-expand-debugfs-to-include-read-suppo.patch
new file mode 100644
index 00000000..c1a46aa5
--- /dev/null
+++ b/features/clear_warn_once/clear_warn_once-expand-debugfs-to-include-read-suppo.patch
@@ -0,0 +1,77 @@
+From 2365198f516a84982bca08e7b3f862d264b7a17e Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Wed, 16 Dec 2020 12:22:56 -0500
+Subject: [PATCH 1/3] clear_warn_once: expand debugfs to include read support
+
+The existing clear_warn_once variable is write-only; used as per the
+documentation to reset the warn_once to as-booted state with:
+
+ echo 1 > /sys/kernel/debug/clear_warn_once
+
+The objective is to expand on that functionality, which requires the
+debugfs variable to be read/write and not just write-only.
+
+Here, we deal with the debugfs boilerplate associated with converting
+it from write-only to read-write, in order to factor that out for easier
+review, and for what may be a possible future useful bisect point.
+
+Existing functionality is unchanged - the only difference is that we
+have tied in a variable that lets you now read the variable and see
+the last value written.
+
+Link: https://lore.kernel.org/r/20201126063029.2030-1-paul.gortmaker@windriver.com
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ kernel/panic.c | 25 ++++++++++++++++++++-----
+ 1 file changed, 20 insertions(+), 5 deletions(-)
+
+diff --git a/kernel/panic.c b/kernel/panic.c
+index f470a038b05b..53088219d7df 100644
+--- a/kernel/panic.c
++++ b/kernel/panic.c
+@@ -635,21 +635,36 @@ EXPORT_SYMBOL(__warn_printk);
+
+ /* Support resetting WARN*_ONCE state */
+
+-static int clear_warn_once_set(void *data, u64 val)
++static u64 clear_warn_once;
++
++static void do_clear_warn_once(void)
+ {
+ generic_bug_clear_once();
+ memset(__start_once, 0, __end_once - __start_once);
++}
++
++static int warn_once_get(void *data, u64 *val)
++{
++ *val = clear_warn_once;
++ return 0;
++}
++
++static int warn_once_set(void *data, u64 val)
++{
++ clear_warn_once = val;
++
++ do_clear_warn_once();
+ return 0;
+ }
+
+-DEFINE_DEBUGFS_ATTRIBUTE(clear_warn_once_fops, NULL, clear_warn_once_set,
+- "%lld\n");
++DEFINE_DEBUGFS_ATTRIBUTE(clear_warn_once_fops, warn_once_get, warn_once_set,
++ "%llu\n");
+
+ static __init int register_warn_debugfs(void)
+ {
+ /* Don't care about failure */
+- debugfs_create_file_unsafe("clear_warn_once", 0200, NULL, NULL,
+- &clear_warn_once_fops);
++ debugfs_create_file_unsafe("clear_warn_once", 0600, NULL,
++ &clear_warn_once, &clear_warn_once_fops);
+ return 0;
+ }
+
+--
+2.19.1
+
diff --git a/features/clear_warn_once/clear_warn_once.scc b/features/clear_warn_once/clear_warn_once.scc
new file mode 100644
index 00000000..d5e0e017
--- /dev/null
+++ b/features/clear_warn_once/clear_warn_once.scc
@@ -0,0 +1,4 @@
+patch clear_warn_once-expand-debugfs-to-include-read-suppo.patch
+patch clear_warn_once-bind-a-timer-to-written-reset-value.patch
+patch clear_warn_once-add-a-clear_warn_once-boot-parameter.patch
+patch sched-isolation-really-align-nohz_full-with-rcu_nocb.patch
diff --git a/features/clear_warn_once/sched-isolation-really-align-nohz_full-with-rcu_nocb.patch b/features/clear_warn_once/sched-isolation-really-align-nohz_full-with-rcu_nocb.patch
new file mode 100644
index 00000000..35145584
--- /dev/null
+++ b/features/clear_warn_once/sched-isolation-really-align-nohz_full-with-rcu_nocb.patch
@@ -0,0 +1,88 @@
+Date: Mon, 21 Feb 2022 13:20:08 -0500
+Subject: [PATCH 1/2] sched/isolation: really align nohz_full with rcu_nocbs
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+To: linux-kernel@vger.kernel.org, Frederic Weisbecker <fweisbec@gmail.com>,
+ Peter Zijlstra <peterz@infradead.org>
+CC: Paul Gortmaker <paul.gortmaker@windriver.com>, Thomas Gleixner
+ <tglx@linutronix.de>, "Paul E . McKenney" <paulmck@kernel.org>, Ingo Molnar
+ <mingo@kernel.org>
+X-Mailer: git-send-email 2.17.1
+MIME-Version: 1.0
+Content-Transfer-Encoding: 8bit
+Content-Type: text/plain; charset=utf-8
+
+At the moment it is currently possible to sneak a core into nohz_full
+that lies between nr_possible and NR_CPUS - but you won't "see" it
+because cpumask_pr_args() implicitly hides anything above nr_cpu_ids.
+
+This becomes a problem when the nohz_full CPU set doesn't contain at
+least one other valid nohz CPU - in which case we end up with the
+tick_nohz_full_running set and no tick core specified, which trips an
+endless sequence of WARN() and renders the machine unusable.
+
+I inadvertently opened the door for this when fixing an overly
+restrictive nohz_full conditional in the below Fixes: commit - and then
+courtesy of my optimistic ACPI reporting nr_possible of 64 (the default
+Kconfig for NR_CPUS) and the not-so helpful implict filtering done by
+cpumask_pr_args, I unfortunately did not spot it during my testing.
+
+So here, I don't rely on what was printed anymore, but code exactly what
+our restrictions should be in order to be aligned with rcu_nocbs - which
+was the original goal. Since the checks lie in "__init" code it is largely
+free for us to do this anyway.
+
+Building with NOHZ_FULL and NR_CPUS=128 on an otherwise defconfig, and
+booting with "rcu_nocbs=8-127 nohz_full=96-127" on the same 16 core T5500
+Dell machine now results in the following (only relevant lines shown):
+
+ smpboot: Allowing 64 CPUs, 48 hotplug CPUs
+ setup_percpu: NR_CPUS:128 nr_cpumask_bits:128 nr_cpu_ids:64 nr_node_ids:2
+ housekeeping: kernel parameter 'nohz_full=' or 'isolcpus=' contains nonexistent CPUs.
+ housekeeping: kernel parameter 'nohz_full=' or 'isolcpus=' has no valid CPUs.
+ rcu: RCU restricting CPUs from NR_CPUS=128 to nr_cpu_ids=64.
+ rcu: Note: kernel parameter 'rcu_nocbs=', 'nohz_full', or 'isolcpus=' contains nonexistent CPUs.
+ rcu: Offload RCU callbacks from CPUs: 8-63.
+
+One can see both new housekeeping checks are triggered in the above.
+The same invalid boot arg combination would have previously resulted in
+an infinitely scrolling mix of WARN from all cores per tick on this box.
+
+We may need to revisit these sanity checks when nohz_full is accepted as
+a stand alone keyword "enable" w/o a cpuset (see rcu/nohz d2cf0854d728).
+
+Fixes: 915a2bc3c6b7 ("sched/isolation: Reconcile rcu_nocbs= and nohz_full=")
+Cc: Frederic Weisbecker <fweisbec@gmail.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Paul E. McKenney <paulmck@kernel.org>
+Cc: Ingo Molnar <mingo@kernel.org>
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+---
+ kernel/sched/isolation.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/kernel/sched/isolation.c b/kernel/sched/isolation.c
+index b4d10815c45a..f7d2406c1f1d 100644
+--- a/kernel/sched/isolation.c
++++ b/kernel/sched/isolation.c
+@@ -126,6 +126,17 @@ static int __init housekeeping_setup(char *str, unsigned long flags)
+ goto free_non_housekeeping_mask;
+ }
+
++ if (!cpumask_subset(non_housekeeping_mask, cpu_possible_mask)) {
++ pr_info("housekeeping: kernel parameter 'nohz_full=' or 'isolcpus=' contains nonexistent CPUs.\n");
++ cpumask_and(non_housekeeping_mask, cpu_possible_mask,
++ non_housekeeping_mask);
++ }
++
++ if (cpumask_empty(non_housekeeping_mask)) {
++ pr_info("housekeeping: kernel parameter 'nohz_full=' or 'isolcpus=' has no valid CPUs.\n");
++ goto free_non_housekeeping_mask;
++ }
++
+ alloc_bootmem_cpumask_var(&housekeeping_staging);
+ cpumask_andnot(housekeeping_staging,
+ cpu_possible_mask, non_housekeeping_mask);
+--
+2.17.1
+
diff --git a/features/debug/debug-btf.cfg b/features/debug/debug-btf.cfg
new file mode 100644
index 00000000..59df424f
--- /dev/null
+++ b/features/debug/debug-btf.cfg
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: MIT
+CONFIG_DEBUG_INFO_BTF=y
+CONFIG_MODULE_ALLOW_BTF_MISMATCH=y
diff --git a/features/debug/debug-btf.scc b/features/debug/debug-btf.scc
new file mode 100644
index 00000000..57dfb930
--- /dev/null
+++ b/features/debug/debug-btf.scc
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable BTF debug"
+define KFEATURE_COMPATIBILITY all
+
+include debug-kernel.scc
+kconf non-hardware debug-btf.cfg
diff --git a/features/debug/debug-kernel.cfg b/features/debug/debug-kernel.cfg
index 53fcbf0a..048ed3d9 100644
--- a/features/debug/debug-kernel.cfg
+++ b/features/debug/debug-kernel.cfg
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: MIT
CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_PREEMPT=y
diff --git a/features/debug/debug-runtime.cfg b/features/debug/debug-runtime.cfg
new file mode 100644
index 00000000..344bad2f
--- /dev/null
+++ b/features/debug/debug-runtime.cfg
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: MIT
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOCK_DEBUGGING_SUPPORT=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_DEBUG_TIMEKEEPING=y \ No newline at end of file
diff --git a/features/debug/debug-runtime.scc b/features/debug/debug-runtime.scc
new file mode 100644
index 00000000..2db9a271
--- /dev/null
+++ b/features/debug/debug-runtime.scc
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: MIT
+
+define KFEATURE_DESCRIPTION "Enable kernel reuntime debugging"
+define KFEATURE_COMPATIBILITY all
+
+kconf non-hardware debug-runtime.cfg
diff --git a/features/debug/printk.cfg b/features/debug/printk.cfg
index 0df20f91..5beb425f 100644
--- a/features/debug/printk.cfg
+++ b/features/debug/printk.cfg
@@ -5,8 +5,5 @@
CONFIG_PRINTK=y
CONFIG_PRINTK_TIME=y
-CONFIG_EARLY_PRINTK=y
-
-CONFIG_EARLY_PRINTK_DBGP=y
CONFIG_EFI_EARLYCON=y
CONFIG_TTY_PRINTK=y
diff --git a/features/device-mapper/dm-verity.cfg b/features/device-mapper/dm-verity.cfg
index ca052267..236a9916 100644
--- a/features/device-mapper/dm-verity.cfg
+++ b/features/device-mapper/dm-verity.cfg
@@ -1,2 +1,4 @@
# SPDX-License-Identifier: MIT
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
CONFIG_DM_VERITY=y
diff --git a/features/docker/docker.scc b/features/docker/docker.scc
new file mode 100644
index 00000000..2bc55019
--- /dev/null
+++ b/features/docker/docker.scc
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: MIT
+
+define KFEATURE_DESCRIPTION "Enable Features needed by docker in addition to LXC features"
+define KFEATURE_COMPATIBILITY board
+
+include cfg/docker.scc
diff --git a/features/drm-bochs/drm-bochs.cfg b/features/drm-bochs/drm-bochs.cfg
index 1c37b67d..2d061433 100644
--- a/features/drm-bochs/drm-bochs.cfg
+++ b/features/drm-bochs/drm-bochs.cfg
@@ -8,11 +8,9 @@ CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_COMPAT=y
CONFIG_I2C_HELPER_AUTO=y
-CONFIG_I2C_ALGOBIT=y
CONFIG_DRM=y
CONFIG_DRM_KMS_HELPER=y
-CONFIG_DRM_KMS_FB_HELPER=y
CONFIG_DRM_FBDEV_EMULATION=y
CONFIG_DRM_FBDEV_OVERALLOC=100
CONFIG_DRM_TTM=y
@@ -22,7 +20,7 @@ CONFIG_DRM_PANEL=y
CONFIG_DRM_BRIDGE=y
CONFIG_DRM_PANEL_BRIDGE=y
CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y
-CONFIG_FB_CMDLINE=y
+CONFIG_VIDEO_CMDLINE=y
CONFIG_FB_NOTIFY=y
CONFIG_FB=y
CONFIG_FB_CFB_FILLRECT=y
diff --git a/features/drm-emgd/drm-emgd.cfg b/features/drm-emgd/drm-emgd.cfg
index 13678d58..298549ad 100644
--- a/features/drm-emgd/drm-emgd.cfg
+++ b/features/drm-emgd/drm-emgd.cfg
@@ -5,11 +5,10 @@ CONFIG_DRM_EGD=m
CONFIG_DRM_KMS_HELPER=m
CONFIG_I2C=y
-CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEO_DEV=m
CONFIG_VIDEO_IVTV=y
CONFIG_MEDIA_SUPPORT=m
CONFIG_VIDEO_DEV=m
-CONFIG_I2C_ALGOBIT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
CONFIG_FB_CFB_FILLRECT=y
diff --git a/features/drm-gma500/drm-gma500.cfg b/features/drm-gma500/drm-gma500.cfg
index 3e320e9f..dc26f5d1 100644
--- a/features/drm-gma500/drm-gma500.cfg
+++ b/features/drm-gma500/drm-gma500.cfg
@@ -1,6 +1,4 @@
# SPDX-License-Identifier: MIT
CONFIG_DRM=y
-CONFIG_DRM_KMS_HELPER=y
+CONFIG_DRM_KMS_HELPER=m
CONFIG_DRM_GMA500=m
-CONFIG_DRM_GMA600=y
-CONFIG_DRM_GMA3600=y
diff --git a/features/drm-psb/drm-psb.cfg b/features/drm-psb/drm-psb.cfg
index 86e508bd..2af3ab9c 100644
--- a/features/drm-psb/drm-psb.cfg
+++ b/features/drm-psb/drm-psb.cfg
@@ -3,11 +3,10 @@ CONFIG_DRM=y
CONFIG_DRM_PSB=m
CONFIG_I2C=y
-CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_DEV=y
CONFIG_VIDEO_IVTV=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_VIDEO_DEV=y
-CONFIG_I2C_ALGOBIT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
CONFIG_FB_CFB_FILLRECT=y
diff --git a/features/edac/edac.cfg b/features/edac/edac.cfg
index 9b3d3fc5..4f75d2f8 100644
--- a/features/edac/edac.cfg
+++ b/features/edac/edac.cfg
@@ -15,3 +15,11 @@
CONFIG_RAS=y
CONFIG_EDAC=y
CONFIG_EDAC_DEBUG=y
+CONFIG_EDAC_SBRIDGE=m
+CONFIG_ACPI_APEI=y
+CONFIG_ACPI_APEI_EINJ=m
+CONFIG_ACPI_APEI_GHES=y
+CONFIG_EDAC_PND2=m
+CONFIG_EDAC_SKX=m
+CONFIG_EDAC_I10NM=m
+CONFIG_EDAC_IGEN6=m
diff --git a/features/edf/edf.cfg b/features/edf/edf.cfg
index 97e4b7cd..531548fb 100644
--- a/features/edf/edf.cfg
+++ b/features/edf/edf.cfg
@@ -2,4 +2,4 @@
CONFIG_HIGH_RES_TIMERS=y
CONFIG_PREEMPT=y
CONFIG_HZ_1000=y
-# CONFIG_NO_HZ is not set
+CONFIG_NO_HZ=n
diff --git a/features/eg20t/eg20t.cfg b/features/eg20t/eg20t.cfg
index 8bfff936..9c411acf 100644
--- a/features/eg20t/eg20t.cfg
+++ b/features/eg20t/eg20t.cfg
@@ -30,4 +30,3 @@ CONFIG_GPIO_PCH=y
CONFIG_CAN=y
CONFIG_CAN_DEV=y
-CONFIG_PCH_CAN=y
diff --git a/features/f2fs/f2fs.cfg b/features/f2fs/f2fs.cfg
new file mode 100644
index 00000000..6b1e6e80
--- /dev/null
+++ b/features/f2fs/f2fs.cfg
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: MIT
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_STAT_FS=y
+CONFIG_F2FS_FS_XATTR=y
+CONFIG_F2FS_FS_POSIX_ACL=y
+CONFIG_F2FS_FS_SECURITY=y
+CONFIG_F2FS_CHECK_FS=y
+CONFIG_F2FS_FAULT_INJECTION=y
diff --git a/features/f2fs/f2fs.scc b/features/f2fs/f2fs.scc
new file mode 100644
index 00000000..a070c6bf
--- /dev/null
+++ b/features/f2fs/f2fs.scc
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: MIT
+kconf non-hardware f2fs.cfg
diff --git a/features/firewire/firewire.cfg b/features/firewire/firewire.cfg
index 5006e4f3..9dbe643c 100644
--- a/features/firewire/firewire.cfg
+++ b/features/firewire/firewire.cfg
@@ -3,14 +3,14 @@ CONFIG_FIREWIRE=m
CONFIG_FIREWIRE_OHCI=m
CONFIG_FIREWIRE_SBP2=m
CONFIG_FIREWIRE_NET=m
-# CONFIG_DVB_FIREDTV is not set
+CONFIG_DVB_FIREDTV=n
CONFIG_SND_FIREWIRE=y
CONFIG_SND_FIREWIRE_LIB=m
CONFIG_SND_DICE=m
-# CONFIG_SND_OXFW is not set
-# CONFIG_SND_ISIGHT is not set
-# CONFIG_SND_FIREWORKS is not set
-# CONFIG_SND_BEBOB is not set
-# CONFIG_SND_FIREWIRE_DIGI00X is not set
+CONFIG_SND_OXFW=n
+CONFIG_SND_ISIGHT=n
+CONFIG_SND_FIREWORKS=n
+CONFIG_SND_BEBOB=n
+CONFIG_SND_FIREWIRE_DIGI00X=n
CONFIG_SND_FIREWIRE_TASCAM=m
-# CONFIG_FIREWIRE_SERIAL is not set
+CONFIG_FIREWIRE_SERIAL=n
diff --git a/features/firmware/firmware.cfg b/features/firmware/firmware.cfg
index 37c41e91..87bf6153 100644
--- a/features/firmware/firmware.cfg
+++ b/features/firmware/firmware.cfg
@@ -2,5 +2,8 @@
#
# Generic Driver Options
#
-CONFIG_FW_LOADER=m
+
+# the dependencies of this are =y, so we can't force this
+# to =m.
+CONFIG_FW_LOADER=y
CONFIG_EXTRA_FIRMWARE=""
diff --git a/features/ftrace/ftrace-function-tracer-disable.cfg b/features/ftrace/ftrace-function-tracer-disable.cfg
index e60ac8a9..e27cba4b 100644
--- a/features/ftrace/ftrace-function-tracer-disable.cfg
+++ b/features/ftrace/ftrace-function-tracer-disable.cfg
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: MIT
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_FUNCTION_GRAPH_TRACER is not set
-# CONFIG_DYNAMIC_FTRACE is not set
+CONFIG_FUNCTION_TRACER=n
+CONFIG_FUNCTION_GRAPH_TRACER=n
+CONFIG_DYNAMIC_FTRACE=n
diff --git a/features/full_nohz/full_nohz.cfg b/features/full_nohz/full_nohz.cfg
index fbccdad7..16db2004 100644
--- a/features/full_nohz/full_nohz.cfg
+++ b/features/full_nohz/full_nohz.cfg
@@ -1,3 +1,3 @@
# SPDX-License-Identifier: MIT
CONFIG_NO_HZ_FULL=y
-CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_RCU_EXPERT=y
diff --git a/features/gpio/mockup.cfg b/features/gpio/mockup.cfg
new file mode 100644
index 00000000..7242fdb4
--- /dev/null
+++ b/features/gpio/mockup.cfg
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: MIT
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_MOCKUP=m
diff --git a/features/gpio/mockup.scc b/features/gpio/mockup.scc
new file mode 100644
index 00000000..3ba86d58
--- /dev/null
+++ b/features/gpio/mockup.scc
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable support for GPIO testing module"
+define KFEATURE_COMPATIBILITY all
+
+kconf non-hardware mockup.cfg
diff --git a/features/gpio/sim.cfg b/features/gpio/sim.cfg
new file mode 100644
index 00000000..ce76a1fe
--- /dev/null
+++ b/features/gpio/sim.cfg
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: MIT
+
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SIM=m
diff --git a/features/gpio/sim.scc b/features/gpio/sim.scc
new file mode 100644
index 00000000..d98952dd
--- /dev/null
+++ b/features/gpio/sim.scc
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: MIT
+
+define KFEATURE_DESCRIPTION "Enable support for the GPIO simulator module"
+define KFEATURE_COMPATIBILITY all
+
+kconf non-hardware sim.cfg
diff --git a/features/gre/gre.cfg b/features/gre/gre.cfg
index cd436df7..c713f965 100644
--- a/features/gre/gre.cfg
+++ b/features/gre/gre.cfg
@@ -4,4 +4,4 @@ CONFIG_NET_IPGRE=m
CONFIG_NET_IPGRE_BROADCAST=y
CONFIG_IPV6_GRE=m
CONFIG_OPENVSWITCH_GRE=y
-# CONFIG_PPTP is not set
+CONFIG_PPTP=n
diff --git a/features/grsec/grsec.cfg b/features/grsec/grsec.cfg
index f984225d..b90fb86a 100644
--- a/features/grsec/grsec.cfg
+++ b/features/grsec/grsec.cfg
@@ -3,16 +3,16 @@
# Grsecurity
#
CONFIG_GRKERNSEC=y
-# CONFIG_GRKERNSEC_LOW is not set
-# CONFIG_GRKERNSEC_MEDIUM is not set
-# CONFIG_GRKERNSEC_HIGH is not set
+CONFIG_GRKERNSEC_LOW=n
+CONFIG_GRKERNSEC_MEDIUM=n
+CONFIG_GRKERNSEC_HIGH=n
CONFIG_GRKERNSEC_CUSTOM=y
CONFIG_GRKERNSEC_KMEM=y
CONFIG_GRKERNSEC_PROC_MEMMAP=y
CONFIG_GRKERNSEC_BRUTE=y
CONFIG_GRKERNSEC_MODSTOP=y
-# CONFIG_GRKERNSEC_HIDESYM is not set
+CONFIG_GRKERNSEC_HIDESYM=n
#
# Role Based Access Control Options
@@ -99,16 +99,16 @@ CONFIG_PAX_RANDKSTACK=y
CONFIG_PAX_MEMORY_UDEREF=y
CONFIG_GRKERNSEC_IO=y
-# CONFIG_GRKERNSEC_MODHARDEN is not set
-# CONFIG_GRKERNSEC_NO_RBAC is not set
-# CONFIG_GRKERNSEC_ROFS is not set
-# CONFIG_GRKERNSEC_AUDIT_PTRACE is not set
-# CONFIG_GRKERNSEC_AUDIT_TEXTREL is not set
-# CONFIG_GRKERNSEC_HARDEN_PTRACE is not set
-# CONFIG_GRKERNSEC_BLACKHOLE is not set
-# CONFIG_GRKERNSEC_VM86 is not set
-# CONFIG_PAX_MPROTECT_ALLOW_PTRACE is not set
-# CONFIG_PAX_SEGMEXEC is not set
-# CONFIG_PAX_KERNEXEC is not set
-# CONFIG_PAX_NOELFRELOCS is not set
-# CONFIG_PAX_USERCOPY is not set
+CONFIG_GRKERNSEC_MODHARDEN=n
+CONFIG_GRKERNSEC_NO_RBAC=n
+CONFIG_GRKERNSEC_ROFS=n
+CONFIG_GRKERNSEC_AUDIT_PTRACE=n
+CONFIG_GRKERNSEC_AUDIT_TEXTREL=n
+CONFIG_GRKERNSEC_HARDEN_PTRACE=n
+CONFIG_GRKERNSEC_BLACKHOLE=n
+CONFIG_GRKERNSEC_VM86=n
+CONFIG_PAX_MPROTECT_ALLOW_PTRACE=n
+CONFIG_PAX_SEGMEXEC=n
+CONFIG_PAX_KERNEXEC=n
+CONFIG_PAX_NOELFRELOCS=n
+CONFIG_PAX_USERCOPY=n
diff --git a/features/grsec/pax.cfg b/features/grsec/pax.cfg
index 6042947a..4ea6b0c3 100644
--- a/features/grsec/pax.cfg
+++ b/features/grsec/pax.cfg
@@ -7,8 +7,8 @@ CONFIG_PAX=y
CONFIG_PAX_SOFTMODE=y
CONFIG_PAX_EI_PAX=y
CONFIG_PAX_PT_PAX_FLAGS=y
-# CONFIG_PAX_NO_ACL_FLAGS is not set
-# CONFIG_PAX_HAVE_ACL_FLAGS is not set
+CONFIG_PAX_NO_ACL_FLAGS=n
+CONFIG_PAX_HAVE_ACL_FLAGS=n
CONFIG_PAX_HOOK_ACL_FLAGS=y
#
@@ -27,7 +27,7 @@ CONFIG_PAX_EMUPLT=y
#
CONFIG_PAX_ASLR=y
CONFIG_PAX_RANDUSTACK=y
-# CONFIG_PAX_RANDMMAP is not set
+CONFIG_PAX_RANDMMAP=n
#
# Miscellaneous hardening features
diff --git a/features/hid/hid.cfg b/features/hid/hid.cfg
new file mode 100644
index 00000000..cfd84dbd
--- /dev/null
+++ b/features/hid/hid.cfg
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: MIT
+
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
diff --git a/features/hid/hid.scc b/features/hid/hid.scc
new file mode 100644
index 00000000..28d242df
--- /dev/null
+++ b/features/hid/hid.scc
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable base HID config"
+define KFEATURE_COMPATIBILITY board
+
+kconf hardware hid.cfg
diff --git a/features/hostapd/hostapd.scc b/features/hostapd/hostapd.scc
index d03b3ce2..aedf9549 100644
--- a/features/hostapd/hostapd.scc
+++ b/features/hostapd/hostapd.scc
@@ -1,2 +1,2 @@
# SPDX-License-Identifier: MIT
-kconf hardware hostapd.cfg
+kconf non-hardware hostapd.cfg
diff --git a/features/i3c/i3c.cfg b/features/i3c/i3c.cfg
new file mode 100644
index 00000000..17f0ce91
--- /dev/null
+++ b/features/i3c/i3c.cfg
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: MIT
+CONFIG_I3C=m
+CONFIG_CDNS_I3C_MASTER=m
+CONFIG_DW_I3C_MASTER=m
+CONFIG_SVC_I3C_MASTER=m
+CONFIG_MIPI_I3C_HCI=m
diff --git a/features/i3c/i3c.scc b/features/i3c/i3c.scc
new file mode 100644
index 00000000..f5615e88
--- /dev/null
+++ b/features/i3c/i3c.scc
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable I3C Support"
+define KFEATURE_COMPATIBILITY board
+
+kconf hardware i3c.cfg
diff --git a/features/i915/i915.cfg b/features/i915/i915.cfg
index 8489fabb..f5e9351a 100644
--- a/features/i915/i915.cfg
+++ b/features/i915/i915.cfg
@@ -3,12 +3,9 @@ CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_COMPAT=y
CONFIG_I2C_HELPER_AUTO=y
-CONFIG_I2C_ALGOBIT=y
CONFIG_AGP=y
CONFIG_AGP_INTEL=y
CONFIG_DRM=y
-CONFIG_DRM_KMS_HELPER=y
+CONFIG_DRM_KMS_HELPER=m
CONFIG_DRM_I915=m
-CONFIG_DRM_KMS_FB_HELPER=y
-CONFIG_DRM_I915_ALPHA_SUPPORT=y
diff --git a/features/ice/ice.cfg b/features/ice/ice.cfg
new file mode 100644
index 00000000..855d37ea
--- /dev/null
+++ b/features/ice/ice.cfg
@@ -0,0 +1 @@
+CONFIG_ICE=m
diff --git a/features/ice/ice.scc b/features/ice/ice.scc
new file mode 100644
index 00000000..e02d0906
--- /dev/null
+++ b/features/ice/ice.scc
@@ -0,0 +1,4 @@
+define KFEATURE_DESCRIPTION "Intel(R) Ethernet Connection E800 Series Support"
+define KFEATURE_COMPATIBILITY board
+
+kconf hardware ice.cfg
diff --git a/features/ieee802154/ieee802154-hwsim.cfg b/features/ieee802154/ieee802154-hwsim.cfg
new file mode 100644
index 00000000..5fe6f5c6
--- /dev/null
+++ b/features/ieee802154/ieee802154-hwsim.cfg
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: MIT
+# dependencies
+CONFIG_MAC802154=y
+CONFIG_NETDEVICES=y
+CONFIG_IEEE802154=y
+CONFIG_IEEE802154_DRIVERS=y
+
+CONFIG_IEEE802154_HWSIM=y
diff --git a/features/ieee802154/ieee802154-hwsim.scc b/features/ieee802154/ieee802154-hwsim.scc
new file mode 100644
index 00000000..c29d43f5
--- /dev/null
+++ b/features/ieee802154/ieee802154-hwsim.scc
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable simulated radio testing tool for mac802154"
+define KFEATURE_COMPATIBILITY all
+
+kconf non-hardware ieee802154-hwsim.cfg
diff --git a/features/inline/inline.cfg b/features/igc/igc.cfg
index efb301db..946ace52 100644
--- a/features/inline/inline.cfg
+++ b/features/igc/igc.cfg
@@ -1,2 +1,2 @@
# SPDX-License-Identifier: MIT
-CONFIG_OPTIMIZE_INLINING=y
+CONFIG_IGC=m
diff --git a/features/igc/igc.scc b/features/igc/igc.scc
new file mode 100644
index 00000000..7b26e476
--- /dev/null
+++ b/features/igc/igc.scc
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Intel Ethernet Controller I225-LM/I225-V family"
+define KFEATURE_COMPATIBILITY board
+
+kconf hardware igc.cfg
diff --git a/features/ima/ima.cfg b/features/ima/ima.cfg
index 1c613636..5fd3288e 100644
--- a/features/ima/ima.cfg
+++ b/features/ima/ima.cfg
@@ -1,19 +1,34 @@
# SPDX-License-Identifier: MIT
CONFIG_IMA=y
+CONFIG_IMA_LSM_RULES=y
CONFIG_IMA_MEASURE_PCR_IDX=10
-CONFIG_IMA_NG_TEMPLATE=y
-CONFIG_IMA_DEFAULT_TEMPLATE="ima-ng"
-CONFIG_IMA_DEFAULT_HASH_SHA1=y
-CONFIG_IMA_DEFAULT_HASH="sha1"
-CONFIG_IMA_APPRAISE=y
-CONFIG_IMA_APPRAISE_BOOTPARAM=y
-CONFIG_IMA_TRUSTED_KEYRING=y
+CONFIG_IMA_SIG_TEMPLATE=y
+CONFIG_IMA_DEFAULT_TEMPLATE="ima-sig"
+CONFIG_IMA_DEFAULT_HASH_SHA256=y
+CONFIG_IMA_DEFAULT_HASH="sha256"
+CONFIG_IMA_ARCH_POLICY=y
+CONFIG_IMA_APPRAISE_BUILD_POLICY=y
+CONFIG_IMA_APPRAISE_REQUIRE_POLICY_SIGS=y
+CONFIG_IMA_APPRAISE_SIGNED_INIT=y
+CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS=y
+CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS=y
+CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT=y
+CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY=y
CONFIG_SIGNATURE=y
CONFIG_IMA_WRITE_POLICY=y
CONFIG_IMA_READ_POLICY=y
-CONFIG_IMA_LOAD_X509=y
-CONFIG_IMA_X509_PATH="/etc/keys/x509_ima.der"
-
-#CONFIG_INTEGRITY_SIGNATURE=y
-#CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
-#CONFIG_INTEGRITY_TRUSTED_KEYRING=y
+CONFIG_INTEGRITY=y
+CONFIG_INTEGRITY_SIGNATURE=y
+CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
+CONFIG_INTEGRITY_TRUSTED_KEYRING=y
+CONFIG_EVM=y
+CONFIG_KEYS=y
+CONFIG_ASYMMETRIC_KEY_TYPE=y
+CONFIG_SYSTEM_TRUSTED_KEYRING=y
+CONFIG_SECONDARY_TRUSTED_KEYRING=y
+CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
+CONFIG_X509_CERTIFICATE_PARSER=y
+CONFIG_PKCS8_PRIVATE_KEY_PARSER=y
+CONFIG_CRYPTO_ECDSA=y
+CONFIG_SECURITY=y
+CONFIG_SECURITYFS=y
diff --git a/features/ima/ima_evm_root_ca.cfg b/features/ima/ima_evm_root_ca.cfg
index b4392afb..0761fb28 100644
--- a/features/ima/ima_evm_root_ca.cfg
+++ b/features/ima/ima_evm_root_ca.cfg
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: MIT
-# CONFIG_IMA_APPRAISE_SIGNED_INIT is not set
+CONFIG_IMA_APPRAISE_SIGNED_INIT=n
CONFIG_EVM_LOAD_X509=y
CONFIG_EVM_X509_PATH="/etc/keys/x509_evm.der"
diff --git a/features/initramfs/initramfs-add-wrapper.patch b/features/initramfs/initramfs-add-wrapper.patch
index 26468afc..29fb9220 100644
--- a/features/initramfs/initramfs-add-wrapper.patch
+++ b/features/initramfs/initramfs-add-wrapper.patch
@@ -1,4 +1,4 @@
-From 1975393f0ee791bb184a9acfa1108c7578648c84 Mon Sep 17 00:00:00 2001
+From e541445b92cc3750f5376a5998b57ab778f5d410 Mon Sep 17 00:00:00 2001
From: Bruce Ashfield <bruce.ashfield@windriver.com>
Date: Mon, 8 Oct 2018 13:33:11 -0400
Subject: [PATCH] initramfs: allow an optional wrapper script around initramfs
@@ -15,18 +15,18 @@ Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/usr/Makefile b/usr/Makefile
-index 748f6a60bb1e..7dfd8d858244 100644
+index c12e6b15ce72..ed29c43088aa 100644
--- a/usr/Makefile
+++ b/usr/Makefile
-@@ -24,7 +24,7 @@ $(obj)/initramfs_data.o: $(obj)/$(datafile_y) FORCE
- # Generate the initramfs cpio archive
+@@ -55,7 +55,7 @@ cpio-data := $(obj)/initramfs_data.cpio
+ hostprogs := gen_init_cpio
- hostprogs-y := gen_init_cpio
--initramfs := $(CONFIG_SHELL) $(srctree)/$(src)/gen_initramfs_list.sh
-+initramfs := $(INITRAMFS_WRAPPER) $(CONFIG_SHELL) $(srctree)/$(src)/gen_initramfs_list.sh
- ramfs-input := $(if $(filter-out "",$(CONFIG_INITRAMFS_SOURCE)), \
- $(shell echo $(CONFIG_INITRAMFS_SOURCE)),-d)
- ramfs-args := \
+ # .initramfs_data.cpio.d is used to identify all files included
+-# in initramfs and to detect if any files are added/removed.
++# in initramfs $(INITRAMFS_WRAPPER) and to detect if any files are added/removed.
+ # Removed files are identified by directory timestamp being updated
+ # The dependency list is generated by gen_initramfs.sh -l
+ -include $(obj)/.initramfs_data.cpio.d
--
-2.5.0
+2.19.1
diff --git a/features/inline/inline.scc b/features/inline/inline.scc
deleted file mode 100644
index ef6dde14..00000000
--- a/features/inline/inline.scc
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: MIT
-define KFEATURE_DESCRIPTION "Allow gcc to uninline functions marked 'inline'"
-define KFEATURE_COMPATIBILITY all
-
-kconf non-hardware inline.cfg
diff --git a/features/intel-dptf/intel-dptf.cfg b/features/intel-dptf/intel-dptf.cfg
new file mode 100644
index 00000000..38aa260f
--- /dev/null
+++ b/features/intel-dptf/intel-dptf.cfg
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: MIT
+CONFIG_DPTF_PCH_FIVR=m
diff --git a/features/intel-dptf/intel-dptf.scc b/features/intel-dptf/intel-dptf.scc
new file mode 100644
index 00000000..b488a2c5
--- /dev/null
+++ b/features/intel-dptf/intel-dptf.scc
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable Dynamic Platform and Thermal Framework PCH FIVR Participant device support"
+
+kconf non-hardware intel-dptf.cfg
diff --git a/features/intel-idxd/intel-idxd.cfg b/features/intel-idxd/intel-idxd.cfg
new file mode 100644
index 00000000..abd30923
--- /dev/null
+++ b/features/intel-idxd/intel-idxd.cfg
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: MIT
+CONFIG_INTEL_IDXD=m
diff --git a/features/intel-idxd/intel-idxd.scc b/features/intel-idxd/intel-idxd.scc
new file mode 100644
index 00000000..c20a3d76
--- /dev/null
+++ b/features/intel-idxd/intel-idxd.scc
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable Intel Data Accelerators support"
+
+kconf hardware intel-idxd.cfg
diff --git a/features/intel-npu/intel-npu.cfg b/features/intel-npu/intel-npu.cfg
new file mode 100644
index 00000000..6b7ced30
--- /dev/null
+++ b/features/intel-npu/intel-npu.cfg
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: MIT
+CONFIG_DRM_ACCEL=y
+CONFIG_DRM_ACCEL_IVPU=m
diff --git a/features/intel-npu/intel-npu.scc b/features/intel-npu/intel-npu.scc
new file mode 100644
index 00000000..782c8499
--- /dev/null
+++ b/features/intel-npu/intel-npu.scc
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable Intel NPU for Computer Vision and Deep Learning applications"
+
+kconf hardware intel-npu.cfg
diff --git a/features/intel-persistent-memory/intel-x86-64-dax.cfg b/features/intel-persistent-memory/intel-x86-64-dax.cfg
index 9e887919..ca53f2de 100644
--- a/features/intel-persistent-memory/intel-x86-64-dax.cfg
+++ b/features/intel-persistent-memory/intel-x86-64-dax.cfg
@@ -5,4 +5,3 @@
CONFIG_DEV_DAX=m
CONFIG_DEV_DAX_PMEM=m
CONFIG_DEV_DAX_KMEM=m
-CONFIG_DEV_DAX_PMEM_COMPAT=m
diff --git a/features/intel-persistent-memory/intel-x86-64-pmem.cfg b/features/intel-persistent-memory/intel-x86-64-pmem.cfg
index a0ab17e9..e7f039e9 100644
--- a/features/intel-persistent-memory/intel-x86-64-pmem.cfg
+++ b/features/intel-persistent-memory/intel-x86-64-pmem.cfg
@@ -16,7 +16,6 @@ CONFIG_ZONE_DEVICE=y
#
CONFIG_LIBNVDIMM=m
CONFIG_BLK_DEV_PMEM=m
-CONFIG_ND_BLK=m
CONFIG_BTT=y
CONFIG_NVDIMM_PFN=y
CONFIG_NVDIMM_DAX=y
diff --git a/features/intel-pinctrl/intel-pinctrl.cfg b/features/intel-pinctrl/intel-pinctrl.cfg
index 406cf3ce..28abf222 100644
--- a/features/intel-pinctrl/intel-pinctrl.cfg
+++ b/features/intel-pinctrl/intel-pinctrl.cfg
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: MIT
CONFIG_PINCTRL_INTEL=y
+CONFIG_PINCTRL_ALDERLAKE=y
CONFIG_PINCTRL_BAYTRAIL=y
CONFIG_PINCTRL_CHERRYVIEW=y
CONFIG_PINCTRL_BROXTON=y
@@ -12,3 +13,6 @@ CONFIG_PINCTRL_GEMINILAKE=y
CONFIG_PINCTRL_ICELAKE=y
CONFIG_PINCTRL_LEWISBURG=y
CONFIG_PINCTRL_LYNXPOINT=m
+CONFIG_PINCTRL_TIGERLAKE=y
+CONFIG_PINCTRL_ELKHARTLAKE=y
+CONFIG_PINCTRL_METEORLAKE=y
diff --git a/features/intel-sgx/intel-sgx.cfg b/features/intel-sgx/intel-sgx.cfg
new file mode 100644
index 00000000..35010062
--- /dev/null
+++ b/features/intel-sgx/intel-sgx.cfg
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: MIT
+CONFIG_X86_SGX=y
diff --git a/features/intel-sgx/intel-sgx.scc b/features/intel-sgx/intel-sgx.scc
new file mode 100644
index 00000000..2ec2ec60
--- /dev/null
+++ b/features/intel-sgx/intel-sgx.scc
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable Intel Software Guard eXtensions (SGX)"
+
+kconf hardware intel-sgx.cfg
diff --git a/features/intel-sst/intel-sst.cfg b/features/intel-sst/intel-sst.cfg
new file mode 100644
index 00000000..05172701
--- /dev/null
+++ b/features/intel-sst/intel-sst.cfg
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: MIT
+CONFIG_INTEL_SPEED_SELECT_INTERFACE=m
diff --git a/features/intel-sst/intel-sst.scc b/features/intel-sst/intel-sst.scc
new file mode 100644
index 00000000..1ab6626b
--- /dev/null
+++ b/features/intel-sst/intel-sst.scc
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable Intel Speed Select Technology interface"
+
+kconf hardware intel-sst.cfg
diff --git a/features/intel-tco/intel-tco.cfg b/features/intel-tco/intel-tco.cfg
index 3310d62e..7512eb97 100644
--- a/features/intel-tco/intel-tco.cfg
+++ b/features/intel-tco/intel-tco.cfg
@@ -1,2 +1,2 @@
# SPDX-License-Identifier: MIT
-CONFIG_ITCO_WDT=y
+CONFIG_ITCO_WDT=m
diff --git a/features/intel-th/intel-th.cfg b/features/intel-th/intel-th.cfg
new file mode 100644
index 00000000..a74438fa
--- /dev/null
+++ b/features/intel-th/intel-th.cfg
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: MIT
+CONFIG_INTEL_TH=m
+CONFIG_INTEL_TH_PCI=m
+CONFIG_INTEL_TH_ACPI=m
+CONFIG_INTEL_TH_GTH=m
+CONFIG_INTEL_TH_STH=m
+CONFIG_INTEL_TH_MSU=m
+CONFIG_INTEL_TH_PTI=m
diff --git a/features/intel-th/intel-th.scc b/features/intel-th/intel-th.scc
new file mode 100644
index 00000000..8b971982
--- /dev/null
+++ b/features/intel-th/intel-th.scc
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Intel Trace Hub support"
+
+kconf hardware intel-th.cfg
diff --git a/features/intel-uncore-frequency/intel-uncore-frequency.cfg b/features/intel-uncore-frequency/intel-uncore-frequency.cfg
new file mode 100644
index 00000000..52d5ae13
--- /dev/null
+++ b/features/intel-uncore-frequency/intel-uncore-frequency.cfg
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: MIT
+CONFIG_INTEL_UNCORE_FREQ_CONTROL=m
diff --git a/features/intel-uncore-frequency/intel-uncore-frequency.scc b/features/intel-uncore-frequency/intel-uncore-frequency.scc
new file mode 100644
index 00000000..75da5a35
--- /dev/null
+++ b/features/intel-uncore-frequency/intel-uncore-frequency.scc
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable Intel Uncore frequency control driver"
+
+kconf hardware intel-uncore-frequency.cfg
diff --git a/features/iommu/iommu.cfg b/features/iommu/iommu.cfg
index 4becf3eb..56221474 100644
--- a/features/iommu/iommu.cfg
+++ b/features/iommu/iommu.cfg
@@ -5,4 +5,4 @@ CONFIG_IOMMU_API=y
CONFIG_IOMMU_IOVA=y
CONFIG_INTEL_IOMMU=y
CONFIG_INTEL_IOMMU_FLOPPY_WA=y
-# CONFIG_INTEL_IOMMU_DEFAULT_ON is not set
+CONFIG_INTEL_IOMMU_DEFAULT_ON=n
diff --git a/features/iscsi/iscsi.cfg b/features/iscsi/iscsi.cfg
new file mode 100644
index 00000000..7c47204b
--- /dev/null
+++ b/features/iscsi/iscsi.cfg
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: MIT
+CONFIG_ISCSI_TCP=m
+CONFIG_ISCSI_BOOT_SYSFS=m
diff --git a/features/iscsi/iscsi.scc b/features/iscsi/iscsi.scc
new file mode 100644
index 00000000..4fc0cec3
--- /dev/null
+++ b/features/iscsi/iscsi.scc
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "iSCSI Initiator over TCP/IP"
+
+kconf non-hardware iscsi.cfg
diff --git a/features/kfence/kfence.cfg b/features/kfence/kfence.cfg
new file mode 100644
index 00000000..6f4875c3
--- /dev/null
+++ b/features/kfence/kfence.cfg
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: MIT
+CONFIG_KFENCE=y
diff --git a/features/kfence/kfence.scc b/features/kfence/kfence.scc
new file mode 100644
index 00000000..741bca26
--- /dev/null
+++ b/features/kfence/kfence.scc
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "a low-overhead sampling-based memory safety error detector"
+define KFEATURE_COMPATIBILITY arch
+
+kconf non-hardware kfence.cfg
diff --git a/features/kmemcheck/kmemcheck.cfg b/features/kmemcheck/kmemcheck.cfg
index 210e7e26..0e6fbef9 100644
--- a/features/kmemcheck/kmemcheck.cfg
+++ b/features/kmemcheck/kmemcheck.cfg
@@ -1,8 +1,8 @@
# SPDX-License-Identifier: MIT
# To get more information
CONFIG_DEBUG_INFO=y
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_FUNCTION_TRACER=n
+CONFIG_DEBUG_PAGEALLOC=n
# kmemcheck related
CONFIG_KMEMCHECK=y
diff --git a/features/landlock/landlock.cfg b/features/landlock/landlock.cfg
new file mode 100644
index 00000000..dfe9f066
--- /dev/null
+++ b/features/landlock/landlock.cfg
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: MIT
+CONFIG_SECURITY_LANDLOCK=y
+
diff --git a/features/landlock/landlock.scc b/features/landlock/landlock.scc
new file mode 100644
index 00000000..d2917123
--- /dev/null
+++ b/features/landlock/landlock.scc
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable the landlock security module"
+define KFEATURE_COMPATIBILITY all
+
+kconf non-hardware landlock.cfg
+
diff --git a/features/leds/leds.cfg b/features/leds/leds.cfg
index eb40627c..33f3da76 100644
--- a/features/leds/leds.cfg
+++ b/features/leds/leds.cfg
@@ -13,4 +13,3 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
# Include them here, but they won't be enabled unless GPIO is explicitly
# enabled as well.
CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGER_GPIO=y
diff --git a/features/lto/lto-disable.cfg b/features/lto/lto-disable.cfg
index 81939aff..75bedad3 100644
--- a/features/lto/lto-disable.cfg
+++ b/features/lto/lto-disable.cfg
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: MIT
-# CONFIG_LTO_MENU is not set
-# CONFIG_LTO is not set
-# CONFIG_LTO_DEBUG is not set
-# CONFIG_LTO_CP_CLONE is not set
-# CONFIG_LTO_SLIM is not set
+CONFIG_LTO_MENU=n
+CONFIG_LTO=n
+CONFIG_LTO_DEBUG=n
+CONFIG_LTO_CP_CLONE=n
+CONFIG_LTO_SLIM=n
diff --git a/features/lxc/lxc-enable.scc b/features/lxc/lxc-enable.scc
index 1482f6ad..1fabf96d 100644
--- a/features/lxc/lxc-enable.scc
+++ b/features/lxc/lxc-enable.scc
@@ -2,4 +2,4 @@
define KFEATURE_DESCRIPTION "Enable LXC support"
define KFEATURE_COMPATIBILITY all
-kconf non-hardware lxc.cfg
+include cfg/lxc.scc
diff --git a/features/lxc/lxc.cfg b/features/lxc/lxc.cfg
deleted file mode 100644
index c289ddd0..00000000
--- a/features/lxc/lxc.cfg
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: MIT
-# Misc configs
-CONFIG_VETH=y
-CONFIG_MACVLAN=y
diff --git a/features/mac80211/mac80211-hwsim.cfg b/features/mac80211/mac80211-hwsim.cfg
new file mode 100644
index 00000000..863a041f
--- /dev/null
+++ b/features/mac80211/mac80211-hwsim.cfg
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: MIT
+# dependencies
+CONFIG_CFG80211=y
+CONFIG_MAC80211=y
+
+CONFIG_MAC80211_HWSIM=y
diff --git a/features/mac80211/mac80211-hwsim.scc b/features/mac80211/mac80211-hwsim.scc
new file mode 100644
index 00000000..71df2daf
--- /dev/null
+++ b/features/mac80211/mac80211-hwsim.scc
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable simulated radio testing tool for mac80211"
+define KFEATURE_COMPATIBILITY all
+
+kconf non-hardware mac80211-hwsim.cfg
diff --git a/features/mac80211/mac80211.scc b/features/mac80211/mac80211.scc
index 5939f434..01806b6e 100644
--- a/features/mac80211/mac80211.scc
+++ b/features/mac80211/mac80211.scc
@@ -2,4 +2,4 @@
define KFEATURE_DESCRIPTION "Enable mac 80211 + WLAN support"
define KFEATURE_COMPATIBILITY board
-kconf hardware mac80211.cfg
+kconf non-hardware mac80211.cfg
diff --git a/features/media/media-dvb-frontends.cfg b/features/media/media-dvb-frontends.cfg
index acada3df..10f02cc5 100644
--- a/features/media/media-dvb-frontends.cfg
+++ b/features/media/media-dvb-frontends.cfg
@@ -29,12 +29,9 @@ CONFIG_DVB_STV6110=m
CONFIG_DVB_STV0900=m
CONFIG_DVB_TDA8083=m
CONFIG_DVB_TDA10086=m
-CONFIG_DVB_TDA8261=m
-CONFIG_DVB_VES1X93=m
CONFIG_DVB_TUNER_ITD1000=m
CONFIG_DVB_TUNER_CX24113=m
CONFIG_DVB_TDA826X=m
-CONFIG_DVB_TUA6100=m
CONFIG_DVB_CX24116=m
CONFIG_DVB_SI21XX=m
CONFIG_DVB_DS3000=m
@@ -44,12 +41,10 @@ CONFIG_DVB_TDA10071=m
#
# DVB-T (terrestrial) frontends
#
-CONFIG_DVB_SP8870=m
CONFIG_DVB_SP887X=m
CONFIG_DVB_CX22700=m
CONFIG_DVB_CX22702=m
CONFIG_DVB_DRXD=m
-CONFIG_DVB_L64781=m
CONFIG_DVB_TDA1004X=m
CONFIG_DVB_NXT6000=m
CONFIG_DVB_MT352=m
diff --git a/features/media/media-i2c.cfg b/features/media/media-i2c.cfg
index f87806a9..2069c5b2 100644
--- a/features/media/media-i2c.cfg
+++ b/features/media/media-i2c.cfg
@@ -9,9 +9,6 @@
CONFIG_VIDEO_IR_I2C=m
CONFIG_VIDEO_TVAUDIO=m
CONFIG_VIDEO_TDA7432=m
-CONFIG_VIDEO_TDA9840=m
-CONFIG_VIDEO_TEA6415C=m
-CONFIG_VIDEO_TEA6420=m
CONFIG_VIDEO_MSP3400=m
CONFIG_VIDEO_CS5345=m
CONFIG_VIDEO_CS53L32A=m
diff --git a/features/media/media-pci-capture.cfg b/features/media/media-pci-capture.cfg
index 33f1079e..fdf12149 100644
--- a/features/media/media-pci-capture.cfg
+++ b/features/media/media-pci-capture.cfg
@@ -11,10 +11,6 @@ CONFIG_VIDEO_IVTV=m
CONFIG_VIDEO_IVTV_ALSA=m
CONFIG_VIDEO_FB_IVTV=m
-CONFIG_VIDEO_HEXIUM_GEMINI=m
-CONFIG_VIDEO_HEXIUM_ORION=m
-CONFIG_VIDEO_MXB=m
-
#
# Media capture/analog/hybrid TV support
#
@@ -43,17 +39,6 @@ CONFIG_VIDEO_SAA7134_RC=y
CONFIG_VIDEO_SAA7134_DVB=m
CONFIG_VIDEO_SAA7164=m
-#
-# Media digital TV PCI Adapters
-#
-CONFIG_DVB_AV7110=m
-CONFIG_DVB_AV7110_OSD=y
-CONFIG_DVB_BUDGET_CORE=m
-CONFIG_DVB_BUDGET=m
-CONFIG_DVB_BUDGET_CI=m
-CONFIG_DVB_BUDGET_AV=m
-CONFIG_DVB_BUDGET_PATCH=m
-
CONFIG_DVB_B2C2_FLEXCOP_PCI=m
CONFIG_DVB_PLUTO2=m
diff --git a/features/media/media-platform.cfg b/features/media/media-platform.cfg
index 58ad7330..135e3eeb 100644
--- a/features/media/media-platform.cfg
+++ b/features/media/media-platform.cfg
@@ -2,5 +2,6 @@
#
# Media Platform Configuration
#
+CONFIG_MEDIA_PLATFORM_SUPPORT=y
CONFIG_V4L_MEM2MEM_DRIVERS=y
CONFIG_VIDEO_MEM2MEM_DEINTERLACE=m
diff --git a/features/media/media-radio.cfg b/features/media/media-radio.cfg
index 19453262..ca695abf 100644
--- a/features/media/media-radio.cfg
+++ b/features/media/media-radio.cfg
@@ -3,7 +3,7 @@
# Media AM/FM Radio Adapters
#
CONFIG_MEDIA_RADIO_SUPPORT=y
-CONFIG_RADIO_ADAPTERS=y
+CONFIG_RADIO_ADAPTERS=m
CONFIG_RADIO_SI470X=m
CONFIG_USB_SI470X=m
CONFIG_I2C_SI470X=m
diff --git a/features/media/media-usb-tv.cfg b/features/media/media-usb-tv.cfg
index 393cf377..33e2279a 100644
--- a/features/media/media-usb-tv.cfg
+++ b/features/media/media-usb-tv.cfg
@@ -7,9 +7,7 @@ CONFIG_VIDEO_PVRUSB2=m
CONFIG_VIDEO_PVRUSB2_SYSFS=y
CONFIG_VIDEO_PVRUSB2_DVB=y
CONFIG_VIDEO_HDPVR=m
-CONFIG_VIDEO_USBVISION=m
CONFIG_VIDEO_STK1160=m
-CONFIG_VIDEO_STK1160_COMMON=m
#
# Analog/digital TV USB devices
@@ -18,9 +16,6 @@ CONFIG_VIDEO_CX231XX=m
CONFIG_VIDEO_CX231XX_RC=y
CONFIG_VIDEO_CX231XX_ALSA=m
CONFIG_VIDEO_CX231XX_DVB=m
-CONFIG_VIDEO_TM6000=m
-CONFIG_VIDEO_TM6000_ALSA=m
-CONFIG_VIDEO_TM6000_DVB=m
#
# Digital TV USB devices
diff --git a/features/media/media-usb-webcams.cfg b/features/media/media-usb-webcams.cfg
index 93361188..8549b0a8 100644
--- a/features/media/media-usb-webcams.cfg
+++ b/features/media/media-usb-webcams.cfg
@@ -56,12 +56,5 @@ CONFIG_USB_GSPCA_ZC3XX=m
CONFIG_USB_PWC=m
CONFIG_USB_PWC_INPUT_EVDEV=y
-# Vision's CPiA2 (Colour Processor Interface ASIC) Camera Drivers
-CONFIG_VIDEO_CPIA2=m
-
-
-# USB Syntek DC1125 Camera Support
-CONFIG_USB_STKWEBCAM=m
-
# USB Sensoray 2255 video capture Device
CONFIG_USB_S2255=m
diff --git a/features/media/media.cfg b/features/media/media.cfg
index 401acae6..148fa991 100644
--- a/features/media/media.cfg
+++ b/features/media/media.cfg
@@ -10,7 +10,6 @@ CONFIG_MEDIA_CONTROLLER=y
# Enable the V4L2 core and API
#
CONFIG_VIDEO_DEV=m
-CONFIG_VIDEO_V4L2=m
CONFIG_VIDEO_V4L2_SUBDEV_API=y
#
@@ -19,14 +18,6 @@ CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_V4L2_MEM2MEM_DEV=m
#
-# Used by drivers that need Videobuf modules
-#
-CONFIG_VIDEOBUF_GEN=m
-CONFIG_VIDEOBUF_DMA_SG=m
-CONFIG_VIDEOBUF_DMA_CONTIG=m
-CONFIG_VIDEOBUF_VMALLOC=m
-
-#
# Used by drivers that need Videobuf2 modules
#
CONFIG_VIDEOBUF2_CORE=m
@@ -38,7 +29,7 @@ CONFIG_VIDEOBUF2_VMALLOC=m
#
# Digital Video Broadcast support
#
-CONFIG_DVB_CORE=y
+CONFIG_DVB_CORE=m
CONFIG_DVB_NET=y
CONFIG_DVB_MAX_ADAPTERS=8
CONFIG_DVB_DYNAMIC_MINORS=y
diff --git a/features/mei/amt.cfg b/features/mei/amt.cfg
index f1c7aa59..df0bf237 100644
--- a/features/mei/amt.cfg
+++ b/features/mei/amt.cfg
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: MIT
CONFIG_WATCHDOG_CORE=y
+CONFIG_WATCHDOG_SYSFS=y
CONFIG_INTEL_MEI_WDT=m
diff --git a/features/minnow-io/minnow-io.cfg b/features/minnow-io/minnow-io.cfg
index 5ca458d1..c8fe2ce3 100644
--- a/features/minnow-io/minnow-io.cfg
+++ b/features/minnow-io/minnow-io.cfg
@@ -4,7 +4,6 @@ CONFIG_MINNOWBOARD_GPIO=m
CONFIG_MINNOWBOARD_KEYS=m
# GPIO Support
-CONFIG_GPIO_SYSFS=y
CONFIG_GPIOLIB=y
CONFIG_GPIO_GENERIC=y
diff --git a/features/misc/bosch-pressure-sensor-i2c.cfg b/features/misc/bosch-pressure-sensor-i2c.cfg
index 420a95f7..8594140b 100644
--- a/features/misc/bosch-pressure-sensor-i2c.cfg
+++ b/features/misc/bosch-pressure-sensor-i2c.cfg
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: MIT
-# CONFIG_BMP280 is not set
+CONFIG_BMP280=n
CONFIG_BMP085=m
CONFIG_BMP085_I2C=m
diff --git a/features/net/net.scc b/features/net/net.scc
index a907e016..606aaa91 100644
--- a/features/net/net.scc
+++ b/features/net/net.scc
@@ -1,4 +1,3 @@
# SPDX-License-Identifier: MIT
kconf hardware net.cfg
-patch netfilter-Fix-remainder-of-pseudo-header-protocol-0.patch
diff --git a/features/net/netfilter-Fix-remainder-of-pseudo-header-protocol-0.patch b/features/net/netfilter-Fix-remainder-of-pseudo-header-protocol-0.patch
deleted file mode 100644
index d1fdbf98..00000000
--- a/features/net/netfilter-Fix-remainder-of-pseudo-header-protocol-0.patch
+++ /dev/null
@@ -1,92 +0,0 @@
-From b383959122e464ccdc21f6b37af88152d29cdf95 Mon Sep 17 00:00:00 2001
-From: He Zhe <zhe.he@windriver.com>
-Date: Tue, 25 Jun 2019 18:15:50 +0800
-Subject: [PATCH] netfilter: Fix remainder of pseudo-header protocol 0
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Since v5.1-rc1, some types of packets do not get unreachable reply with the
-following iptables setting. Fox example,
-
-$ iptables -A INPUT -p icmp --icmp-type 8 -j REJECT
-$ ping 127.0.0.1 -c 1
-PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
-— 127.0.0.1 ping statistics —
-1 packets transmitted, 0 received, 100% packet loss, time 0ms
-
-We should have got the following reply from command line, but we did not.
-From 127.0.0.1 icmp_seq=1 Destination Port Unreachable
-
-Yi Zhao reported it and narrowed it down to:
-7fc38225363d ("netfilter: reject: skip csum verification for protocols that don't support it"),
-
-This is because nf_ip_checksum still expects pseudo-header protocol type 0 for
-packets that are of neither TCP or UDP, and thus ICMP packets are mistakenly
-treated as TCP/UDP.
-
-This patch corrects the conditions in nf_ip_checksum and all other places that
-still call it with protocol 0.
-
-Fixes: 7fc38225363d ("netfilter: reject: skip csum verification for protocols that don't support it")
-Reported-by: Yi Zhao <yi.zhao@windriver.com>
-Signed-off-by: He Zhe <zhe.he@windriver.com>
-Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
----
- net/netfilter/nf_conntrack_proto_icmp.c | 2 +-
- net/netfilter/nf_nat_proto.c | 2 +-
- net/netfilter/utils.c | 5 +++--
- 3 files changed, 5 insertions(+), 4 deletions(-)
-
-diff --git a/net/netfilter/nf_conntrack_proto_icmp.c b/net/netfilter/nf_conntrack_proto_icmp.c
-index a824367ed518..dd53e2b20f6b 100644
---- a/net/netfilter/nf_conntrack_proto_icmp.c
-+++ b/net/netfilter/nf_conntrack_proto_icmp.c
-@@ -218,7 +218,7 @@ int nf_conntrack_icmpv4_error(struct nf_conn *tmpl,
- /* See ip_conntrack_proto_tcp.c */
- if (state->net->ct.sysctl_checksum &&
- state->hook == NF_INET_PRE_ROUTING &&
-- nf_ip_checksum(skb, state->hook, dataoff, 0)) {
-+ nf_ip_checksum(skb, state->hook, dataoff, IPPROTO_ICMP)) {
- icmp_error_log(skb, state, "bad hw icmp checksum");
- return -NF_ACCEPT;
- }
-diff --git a/net/netfilter/nf_nat_proto.c b/net/netfilter/nf_nat_proto.c
-index 07da07788f6b..83a24cc5753b 100644
---- a/net/netfilter/nf_nat_proto.c
-+++ b/net/netfilter/nf_nat_proto.c
-@@ -564,7 +564,7 @@ int nf_nat_icmp_reply_translation(struct sk_buff *skb,
-
- if (!skb_make_writable(skb, hdrlen + sizeof(*inside)))
- return 0;
-- if (nf_ip_checksum(skb, hooknum, hdrlen, 0))
-+ if (nf_ip_checksum(skb, hooknum, hdrlen, IPPROTO_ICMP))
- return 0;
-
- inside = (void *)skb->data + hdrlen;
-diff --git a/net/netfilter/utils.c b/net/netfilter/utils.c
-index 06dc55590441..51b454d8fa9c 100644
---- a/net/netfilter/utils.c
-+++ b/net/netfilter/utils.c
-@@ -17,7 +17,8 @@ __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
- case CHECKSUM_COMPLETE:
- if (hook != NF_INET_PRE_ROUTING && hook != NF_INET_LOCAL_IN)
- break;
-- if ((protocol == 0 && !csum_fold(skb->csum)) ||
-+ if ((protocol != IPPROTO_TCP && protocol != IPPROTO_UDP &&
-+ !csum_fold(skb->csum)) ||
- !csum_tcpudp_magic(iph->saddr, iph->daddr,
- skb->len - dataoff, protocol,
- skb->csum)) {
-@@ -26,7 +27,7 @@ __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
- }
- /* fall through */
- case CHECKSUM_NONE:
-- if (protocol == 0)
-+ if (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP)
- skb->csum = 0;
- else
- skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
---
-2.19.1
-
diff --git a/features/net/xdp/xdp.cfg b/features/net/xdp/xdp.cfg
new file mode 100644
index 00000000..061b65a4
--- /dev/null
+++ b/features/net/xdp/xdp.cfg
@@ -0,0 +1 @@
+CONFIG_XDP_SOCKETS=y
diff --git a/features/net/xdp/xdp.scc b/features/net/xdp/xdp.scc
new file mode 100644
index 00000000..e4df6d09
--- /dev/null
+++ b/features/net/xdp/xdp.scc
@@ -0,0 +1 @@
+kconf hardware xdp.cfg
diff --git a/features/net_sched/net_sched.cfg b/features/net_sched/net_sched.cfg
index c9714dab..137ca752 100644
--- a/features/net_sched/net_sched.cfg
+++ b/features/net_sched/net_sched.cfg
@@ -7,7 +7,6 @@ CONFIG_NET_SCHED=y
#
# Queueing/Scheduling
#
-CONFIG_NET_SCH_CBQ=m
CONFIG_NET_SCH_HTB=m
CONFIG_NET_SCH_HFSC=m
CONFIG_NET_SCH_PRIO=m
@@ -16,12 +15,13 @@ CONFIG_NET_SCH_SFQ=m
CONFIG_NET_SCH_TEQL=m
CONFIG_NET_SCH_TBF=m
CONFIG_NET_SCH_GRED=m
-CONFIG_NET_SCH_DSMARK=m
CONFIG_NET_SCH_NETEM=m
CONFIG_NET_SCH_INGRESS=m
CONFIG_NET_SCH_CODEL=m
CONFIG_NET_SCH_FQ_CODEL=m
+CONFIG_NET_SCH_MULTIQ=m
+
#
# Classification
#
@@ -31,3 +31,8 @@ CONFIG_NET_CLS_BASIC=y
CONFIG_NET_CLS_CGROUP=y
CONFIG_NET_CLS_U32=y
CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_SKBEDIT=m
+CONFIG_NET_EMATCH=y
+
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
diff --git a/features/netfilter/netfilter.cfg b/features/netfilter/netfilter.cfg
index 4e8d1bb6..ba275be4 100644
--- a/features/netfilter/netfilter.cfg
+++ b/features/netfilter/netfilter.cfg
@@ -13,9 +13,9 @@ CONFIG_NETFILTER_NETLINK_QUEUE=m
CONFIG_NETFILTER_NETLINK_LOG=m
CONFIG_NF_CONNTRACK=m
CONFIG_NF_CONNTRACK_MARK=y
-CONFIG_NF_CT_PROTO_GRE=m
-CONFIG_NF_CT_PROTO_SCTP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CT_PROTO_GRE=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
CONFIG_NF_CONNTRACK_AMANDA=m
CONFIG_NF_CONNTRACK_FTP=m
CONFIG_NF_CONNTRACK_H323=m
@@ -29,13 +29,14 @@ CONFIG_NF_CT_NETLINK=m
CONFIG_NETFILTER_XTABLES=m
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_CT=m
CONFIG_NETFILTER_XT_TARGET_DSCP=m
CONFIG_NETFILTER_XT_TARGET_HL=m
CONFIG_NETFILTER_XT_TARGET_LOG=m
CONFIG_NETFILTER_XT_TARGET_MARK=m
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
-CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set
CONFIG_NETFILTER_XT_TARGET_TRACE=m
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
@@ -91,7 +92,6 @@ CONFIG_NF_NAT_PPTP=m
CONFIG_NF_NAT_H323=m
CONFIG_NF_NAT_SIP=m
CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_CLUSTERIP=m
CONFIG_IP_NF_TARGET_ECN=m
CONFIG_IP_NF_TARGET_TTL=m
CONFIG_IP_NF_RAW=m
diff --git a/features/nf_tables/nf_tables.cfg b/features/nf_tables/nf_tables.cfg
index afb13964..5b0f28df 100644
--- a/features/nf_tables/nf_tables.cfg
+++ b/features/nf_tables/nf_tables.cfg
@@ -1,32 +1,24 @@
# SPDX-License-Identifier: MIT
-CONFIG_NF_TABLES=m
-CONFIG_NF_TABLES_INET=m
-CONFIG_NFT_EXTHDR=m
-CONFIG_NFT_META=m
+CONFIG_NF_TABLES=y
+CONFIG_NF_TABLES_INET=y
+CONFIG_NF_TABLES_NETDEV=y
CONFIG_NFT_CT=m
-CONFIG_NFT_SET_RBTREE=m
-CONFIG_NFT_SET_HASH=m
-CONFIG_NFT_RBTREE=m
CONFIG_NFT_HASH=m
-CONFIG_NFT_COUNTER=m
CONFIG_NFT_MASQ=m
-CONFIG_NFT_MASQ_IPV4=m
CONFIG_NFT_REDIR=m
-CONFIG_NFT_REDIR_IPV4=m
CONFIG_NFT_LOG=m
CONFIG_NFT_LIMIT=m
+CONFIG_NFT_CONNLIMIT=m
+CONFIG_NFT_TUNNEL=m
CONFIG_NFT_NAT=m
CONFIG_NFT_QUEUE=m
CONFIG_NFT_REJECT=m
CONFIG_NFT_REJECT_INET=m
CONFIG_NFT_COMPAT=m
-CONFIG_NF_TABLES_IPV4=m
-CONFIG_NFT_CHAIN_ROUTE_IPV4=m
-CONFIG_NFT_CHAIN_NAT_IPV4=m
+CONFIG_NF_TABLES_IPV4=y
CONFIG_NFT_REJECT_IPV4=m
CONFIG_NFT_REJECT_IPV6=m
-CONFIG_NF_TABLES_ARP=m
-CONFIG_NF_TABLES_IPV6=m
-CONFIG_NFT_CHAIN_ROUTE_IPV6=m
-CONFIG_NFT_REJECT_IPV6=m
+CONFIG_NF_TABLES_ARP=y
+CONFIG_NF_TABLES_IPV6=y
CONFIG_NF_TABLES_BRIDGE=m
+CONFIG_NFT_SOCKET=m
diff --git a/features/nf_tables/nft_test.cfg b/features/nf_tables/nft_test.cfg
new file mode 100644
index 00000000..0a959d0e
--- /dev/null
+++ b/features/nf_tables/nft_test.cfg
@@ -0,0 +1,13 @@
+CONFIG_NF_CONNTRACK_TIMEOUT=y
+CONFIG_NF_FLOW_TABLE_INET=m
+CONFIG_NF_FLOW_TABLE=m
+CONFIG_NFT_FIB_INET=y
+CONFIG_NFT_FIB_IPV4=y
+CONFIG_NFT_FIB_IPV6=y
+CONFIG_NFT_FLOW_OFFLOAD=m
+CONFIG_NFT_NUMGEN=m
+CONFIG_NFT_OSF=m
+CONFIG_NFT_QUOTA=m
+CONFIG_NFT_SYNPROXY=m
+CONFIG_NFT_XFRM=m
+CONFIG_VETH=y
diff --git a/features/nf_tables/nft_test.scc b/features/nf_tables/nft_test.scc
new file mode 100644
index 00000000..8181c215
--- /dev/null
+++ b/features/nf_tables/nft_test.scc
@@ -0,0 +1,5 @@
+define KFEATURE_DESCRIPTION "Add extra nftables modules"
+define KFEATURE_COMPATIBILITY all
+
+include nf_tables.cfg
+include nft_test.cfg
diff --git a/features/nfsd/nfsd.cfg b/features/nfsd/nfsd.cfg
index ff94b98c..8cd76e3c 100644
--- a/features/nfsd/nfsd.cfg
+++ b/features/nfsd/nfsd.cfg
@@ -1,6 +1,4 @@
# SPDX-License-Identifier: MIT
CONFIG_NFSD=m
-CONFIG_NFSD_V3=y
-# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V3_ACL=n
CONFIG_NFSD_V4=y
-# CONFIG_NFSD_FAULT_INJECTION is not set
diff --git a/features/numa/numa.cfg b/features/numa/numa.cfg
index 351c5d97..2cf4bae2 100644
--- a/features/numa/numa.cfg
+++ b/features/numa/numa.cfg
@@ -1,9 +1,9 @@
# SPDX-License-Identifier: MIT
CONFIG_NUMA=y
+CONFIG_NUMA_BALANCING=y
+CONFIG_NUMA_BALANCING_DEFAULT_ENABLED=y
CONFIG_X86_64_ACPI_NUMA=y
-CONFIG_NODES_SPAN_OTHER_NODES=y
CONFIG_NUMA_EMU=y
CONFIG_NODES_SHIFT=6
-CONFIG_NEED_MULTIPLE_NODES=y
CONFIG_USE_PERCPU_NUMA_NODE_ID=y
CONFIG_ACPI_NUMA=y
diff --git a/features/ocicontainer/cgroup.scc b/features/ocicontainer/cgroup.scc
new file mode 100644
index 00000000..4bfbccef
--- /dev/null
+++ b/features/ocicontainer/cgroup.scc
@@ -0,0 +1,4 @@
+define KFEATURE_DESCRIPTION "Enable cgroups needed to run containerd"
+define KFEATURE_COMPATIBILITY board
+
+kconf non-hardware features/cgroups/cgroups.cfg
diff --git a/features/ocicontainer/ebtables.cfg b/features/ocicontainer/ebtables.cfg
new file mode 100644
index 00000000..a3c514e1
--- /dev/null
+++ b/features/ocicontainer/ebtables.cfg
@@ -0,0 +1,2 @@
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_T_NAT=m
diff --git a/features/ocicontainer/ebtables.scc b/features/ocicontainer/ebtables.scc
new file mode 100644
index 00000000..b3895e58
--- /dev/null
+++ b/features/ocicontainer/ebtables.scc
@@ -0,0 +1,4 @@
+define KFEATURE_DESCRIPTION "Enable ebtables support"
+define KFEATURE_COMPATIBILITY board
+
+kconf non-hardware ebtables.cfg
diff --git a/features/ocicontainer/ocicontainer.scc b/features/ocicontainer/ocicontainer.scc
new file mode 100644
index 00000000..d18e9dfc
--- /dev/null
+++ b/features/ocicontainer/ocicontainer.scc
@@ -0,0 +1,7 @@
+include xt-checksum.scc
+include ebtables.scc
+include features/vswitch/vswitch.scc
+include features/lxc/lxc-enable.scc
+include features/docker/docker.scc
+include cgroup.scc
+
diff --git a/features/ocicontainer/xt-checksum.cfg b/features/ocicontainer/xt-checksum.cfg
new file mode 100644
index 00000000..58afbff6
--- /dev/null
+++ b/features/ocicontainer/xt-checksum.cfg
@@ -0,0 +1 @@
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
diff --git a/features/ocicontainer/xt-checksum.scc b/features/ocicontainer/xt-checksum.scc
new file mode 100644
index 00000000..d3804f0c
--- /dev/null
+++ b/features/ocicontainer/xt-checksum.scc
@@ -0,0 +1,4 @@
+define KFEATURE_DESCRIPTION "Add extra iptables modules"
+define KFEATURE_COMPATIBILITY board
+
+kconf non-hardware xt-checksum.cfg
diff --git a/features/optee/optee.cfg b/features/optee/optee.cfg
new file mode 100644
index 00000000..3aa27f0a
--- /dev/null
+++ b/features/optee/optee.cfg
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: MIT
+CONFIG_TEE=y
+CONFIG_OPTEE=y
diff --git a/features/optee/optee.scc b/features/optee/optee.scc
new file mode 100644
index 00000000..db4c19e5
--- /dev/null
+++ b/features/optee/optee.scc
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable optee support"
+
+kconf hardware optee.cfg
diff --git a/features/pci/pci-of-generic.cfg b/features/pci/pci-of-generic.cfg
new file mode 100644
index 00000000..67a3ccff
--- /dev/null
+++ b/features/pci/pci-of-generic.cfg
@@ -0,0 +1,3 @@
+# Support a simple generic PCI host controller, such as the one emulated by kvmtool
+CONFIG_PCI_HOST_GENERIC=y
+
diff --git a/features/pci/pci-of-generic.scc b/features/pci/pci-of-generic.scc
new file mode 100644
index 00000000..cc76fb88
--- /dev/null
+++ b/features/pci/pci-of-generic.scc
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable Generic PCI OF device"
+define KFEATURE_COMPATIBILITY board
+
+kconf hardware pci-of-generic.cfg
diff --git a/features/pci/pci.cfg b/features/pci/pci.cfg
index f3c57c54..3ed13b59 100644
--- a/features/pci/pci.cfg
+++ b/features/pci/pci.cfg
@@ -1,12 +1,8 @@
# SPDX-License-Identifier: MIT
CONFIG_PCI=y
-CONFIG_PCI_MMCONFIG=y
CONFIG_PCI_MSI=y
CONFIG_PCIEPORTBUS=y
CONFIG_HOTPLUG_PCI=y
-# CONFIG_HOTPLUG_PCI_PCIE is not set
-
-
-
+CONFIG_HOTPLUG_PCI_PCIE=n
diff --git a/features/perf/libbpf-Fix-build-warning-on-ref_ctr_off.patch b/features/perf/libbpf-Fix-build-warning-on-ref_ctr_off.patch
new file mode 100644
index 00000000..10ed1460
--- /dev/null
+++ b/features/perf/libbpf-Fix-build-warning-on-ref_ctr_off.patch
@@ -0,0 +1,46 @@
+From a41f5bda3e72b4f2bcdbe84cd65190121e3cc3ff Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Sun, 4 Dec 2022 18:23:47 -0800
+Subject: [PATCH] libbpf: Fix build warning on ref_ctr_off
+
+Clang warns on 32-bit ARM on this comparision
+
+libbpf.c:10497:18: error: result of comparison of constant 4294967296 with expression of type 'size_t' (aka 'unsigned int') is always false [-Werror,-Wtautological-constant-out-of-range-compare]
+ if (ref_ctr_off >= (1ULL << PERF_UPROBE_REF_CTR_OFFSET_BITS))
+ ~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Check for platform long int to be larger than 32-bits before enabling
+this check, it false on 32bit anyways.
+
+Cc: Alexei Starovoitov <ast@kernel.org>
+Cc: Daniel Borkmann <daniel@iogearbox.net>
+Cc: Song Liu <song@kernel.org>
+Cc: Yonghong Song <yhs@fb.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Paul Walmsley <paul.walmsley@sifive.com>
+Cc: Palmer Dabbelt <palmer@dabbelt.com>
+Cc: Nathan Chancellor <nathan@kernel.org>
+Cc: Nick Desaulniers <ndesaulniers@google.com>
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ tools/lib/bpf/libbpf.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
+index 05c4db355f28..23991e0d21a9 100644
+--- a/tools/lib/bpf/libbpf.c
++++ b/tools/lib/bpf/libbpf.c
+@@ -9867,7 +9867,7 @@ static int perf_event_open_probe(bool uprobe, bool retprobe, const char *name,
+ char errmsg[STRERR_BUFSIZE];
+ int type, pfd;
+
+- if ((__u64)ref_ctr_off >= (1ULL << PERF_UPROBE_REF_CTR_OFFSET_BITS))
++ if (BITS_PER_LONG > 32 && (__u64)ref_ctr_off >= (1ULL << PERF_UPROBE_REF_CTR_OFFSET_BITS))
+ return -EINVAL;
+
+ memset(&attr, 0, attr_sz);
+--
+2.34.1
+
diff --git a/features/perf/perf-perf-can-not-parser-the-backtrace-of-app-in-the.patch b/features/perf/perf-perf-can-not-parser-the-backtrace-of-app-in-the.patch
new file mode 100644
index 00000000..91ab18c5
--- /dev/null
+++ b/features/perf/perf-perf-can-not-parser-the-backtrace-of-app-in-the.patch
@@ -0,0 +1,33 @@
+From 4b69a5a32098d3abcd0800f6d24fa29451a82c3a Mon Sep 17 00:00:00 2001
+From: Jiping Ma <jiping.ma2@windriver.com>
+Date: Thu, 30 Apr 2020 09:35:06 +0800
+Subject: [PATCH] perf: perf can not parser the backtrace of app in the 32bit
+ system and 64bit kernel.
+
+Record PC value from regs[15], it should be regs[32], which cause perf
+parser the backtrace failed.
+
+Signed-off-by: Jiping Ma <jiping.ma2@windriver.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ arch/arm64/kernel/perf_regs.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/arch/arm64/kernel/perf_regs.c b/arch/arm64/kernel/perf_regs.c
+index 0bbac612146e..04088e6b6092 100644
+--- a/arch/arm64/kernel/perf_regs.c
++++ b/arch/arm64/kernel/perf_regs.c
+@@ -32,6 +32,10 @@ u64 perf_reg_value(struct pt_regs *regs, int idx)
+ if ((u32)idx == PERF_REG_ARM64_PC)
+ return regs->pc;
+
++ if (perf_reg_abi(current) == PERF_SAMPLE_REGS_ABI_32
++ && idx == 15)
++ return regs->regs[PERF_REG_ARM64_PC];
++
+ return regs->regs[idx];
+ }
+
+--
+2.19.1
+
diff --git a/features/perf/perf.scc b/features/perf/perf.scc
index b4478355..dc9de471 100644
--- a/features/perf/perf.scc
+++ b/features/perf/perf.scc
@@ -9,3 +9,6 @@ patch perf-add-SLANG_INC-for-slang.h.patch
patch perf-fix-bench-numa-compilation.patch
patch perf-mips64-Convert-__u64-to-unsigned-long-long.patch
patch perf-x86-32-explicitly-include-errno.h.patch
+patch perf-perf-can-not-parser-the-backtrace-of-app-in-the.patch
+patch libbpf-Fix-build-warning-on-ref_ctr_off.patch
+patch tools-Remove-some-options-from-CLANG_CROSS_FLAGS.patch
diff --git a/features/perf/tools-Remove-some-options-from-CLANG_CROSS_FLAGS.patch b/features/perf/tools-Remove-some-options-from-CLANG_CROSS_FLAGS.patch
new file mode 100644
index 00000000..31008bfa
--- /dev/null
+++ b/features/perf/tools-Remove-some-options-from-CLANG_CROSS_FLAGS.patch
@@ -0,0 +1,37 @@
+From 2c720c18adae3422b022c2c88fb91379b1f3e2c6 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Sun, 4 Dec 2022 18:33:48 -0800
+Subject: [PATCH 3/3] tools: Remove some options from CLANG_CROSS_FLAGS
+
+These options are not needed with OE/Yocto since compiler is already
+passing these options via TOOLCHAIN_OPTIONS, having these options infact
+regressed OE builds because build time --sysroot on OE cross compiler is
+/not/exist and that creates problems where clang can no more find system
+headers anymore during compilation
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ tools/scripts/Makefile.include | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
+index 0efb8f2b33ce..3d206d772cc2 100644
+--- a/tools/scripts/Makefile.include
++++ b/tools/scripts/Makefile.include
+@@ -101,9 +101,9 @@ ifeq ($(CLANG_CROSS_FLAGS),)
+ CLANG_CROSS_FLAGS := --target=$(notdir $(CROSS_COMPILE:%-=%))
+ GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE)gcc 2>/dev/null))
+ ifneq ($(GCC_TOOLCHAIN_DIR),)
+-CLANG_CROSS_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
+-CLANG_CROSS_FLAGS += --sysroot=$(shell $(CROSS_COMPILE)gcc -print-sysroot)
+-CLANG_CROSS_FLAGS += --gcc-toolchain=$(realpath $(GCC_TOOLCHAIN_DIR)/..)
++#CLANG_CROSS_FLAGS += --prefix=$(GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE))
++#CLANG_CROSS_FLAGS += --sysroot=$(shell $(CROSS_COMPILE)gcc -print-sysroot)
++#CLANG_CROSS_FLAGS += --gcc-toolchain=$(realpath $(GCC_TOOLCHAIN_DIR)/..)
+ endif # GCC_TOOLCHAIN_DIR
+ endif # CLANG_CROSS_FLAGS
+ CFLAGS += $(CLANG_CROSS_FLAGS)
+--
+2.19.1
+
diff --git a/features/profiling/profiling.cfg b/features/profiling/profiling.cfg
index 3c28606c..9728b889 100644
--- a/features/profiling/profiling.cfg
+++ b/features/profiling/profiling.cfg
@@ -1,6 +1,5 @@
# SPDX-License-Identifier: MIT
# for oprofile and powertop
CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
CONFIG_FRAME_POINTER=y
CONFIG_X86_LOCAL_APIC=y
diff --git a/features/qat/qat.cfg b/features/qat/qat.cfg
index 2dc36225..5f138f1f 100644
--- a/features/qat/qat.cfg
+++ b/features/qat/qat.cfg
@@ -10,3 +10,5 @@ CONFIG_CRYPTO_VMAC=m
CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_RSA=y
CONFIG_CRYPTO_DH=y
+CONFIG_PCIEAER=y
+CONFIG_RAS=y
diff --git a/features/qat/y_or_m_enabled.cfg b/features/qat/y_or_m_enabled.cfg
new file mode 100644
index 00000000..357efc5a
--- /dev/null
+++ b/features/qat/y_or_m_enabled.cfg
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: MIT
+CONFIG_CRYPTO_CCM
+CONFIG_CRYPTO_GCM
diff --git a/features/random/random.scc b/features/random/random.scc
deleted file mode 100644
index 0fd6584c..00000000
--- a/features/random/random.scc
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: MIT
-define KFEATURE_DESCRIPTION "Trust CPU's random number generator for initializing kernel's CRNG"
-define KFEATURE_COMPATIBILITY arch
-
-kconf hardware random.cfg
diff --git a/features/reproducibility/reproducibility.cfg b/features/reproducibility/reproducibility.cfg
new file mode 100644
index 00000000..97e7462c
--- /dev/null
+++ b/features/reproducibility/reproducibility.cfg
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: MIT
+CONFIG_IKHEADERS=m
diff --git a/features/reproducibility/reproducibility.scc b/features/reproducibility/reproducibility.scc
new file mode 100644
index 00000000..e8b069cd
--- /dev/null
+++ b/features/reproducibility/reproducibility.scc
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable kernel build reproducibility options"
+define KFEATURE_COMPATIBILITY arch
+
+kconf non-hardware reproducibility.cfg
diff --git a/features/rt/rt.scc b/features/rt/rt.scc
index 548d2d44..4cc0cb9a 100644
--- a/features/rt/rt.scc
+++ b/features/rt/rt.scc
@@ -1 +1,3 @@
# SPDX-License-Identifier: MIT
+#
+
diff --git a/features/scsi/scsi-debug.cfg b/features/scsi/scsi-debug.cfg
index 11dc381f..90e6aa4b 100644
--- a/features/scsi/scsi-debug.cfg
+++ b/features/scsi/scsi-debug.cfg
@@ -1,2 +1,3 @@
# SPDX-License-Identifier: MIT
+CONFIG_SCSI_LOWLEVEL=y
CONFIG_SCSI_DEBUG=m
diff --git a/features/scsi/scsi-debug.scc b/features/scsi/scsi-debug.scc
index 2032872a..f591db62 100644
--- a/features/scsi/scsi-debug.scc
+++ b/features/scsi/scsi-debug.scc
@@ -5,5 +5,6 @@ define KFEATURE_COMPATIBILITY board
# if we are turning on debug support, we need to be sure that core scsi
# support is enabled.
include scsi.scc
+include disk.scc
kconf hardware scsi-debug.cfg
diff --git a/features/security/security-arm64.cfg b/features/security/security-arm64.cfg
new file mode 100644
index 00000000..5222afb3
--- /dev/null
+++ b/features/security/security-arm64.cfg
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: MIT
+
+# Make sure PAN emulation is enabled.
+CONFIG_ARM64_SW_TTBR0_PAN=y
+
+# Enable Kernel Page Table Isolation to remove an entire class of cache timing side-channels.
+CONFIG_UNMAP_KERNEL_AT_EL0=y
+
+# Software Shadow Stack or PAC
+CONFIG_SHADOW_CALL_STACK=y
+
+# Pointer authentication (ARMv8.3 and later). If hardware actually supports it, one can
+# turn off CONFIG_STACKPROTECTOR_STRONG with this enabled.
+CONFIG_ARM64_PTR_AUTH=y
+CONFIG_ARM64_PTR_AUTH_KERNEL=y
+
+# Available in ARMv8.5 and later.
+CONFIG_ARM64_BTI=y
+CONFIG_ARM64_BTI_KERNEL=y
+CONFIG_ARM64_MTE=y
+CONFIG_KASAN_HW_TAGS=y
+CONFIG_ARM64_E0PD=y
+
+# Available in ARMv8.7 and later.
+CONFIG_ARM64_EPAN=y
+
+# Enable Control Flow Integrity
+CONFIG_CFI_CLANG=y
+# CONFIG_CFI_PERMISSIVE is not set
diff --git a/features/security/security-x86_64.cfg b/features/security/security-x86_64.cfg
new file mode 100644
index 00000000..1c12034a
--- /dev/null
+++ b/features/security/security-x86_64.cfg
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: MIT
+# Modern libc no longer needs a fixed-position mapping in userspace, remove it as a possible target.
+CONFIG_LEGACY_VSYSCALL_NONE=y
diff --git a/features/security/security.cfg b/features/security/security.cfg
index 0486eb1a..336adcc4 100644
--- a/features/security/security.cfg
+++ b/features/security/security.cfg
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: MIT
# Protect against ioctl buffer overflows
CONFIG_HARDENED_USERCOPY=y
-# CONFIG_HARDENED_USERCOPY_FALLBACK is not set
# Check for memory copies that might overflow a structure in str*() and mem*()
# functions both at build-time and run-time
@@ -15,31 +14,24 @@ CONFIG_SLAB_FREELIST_HARDENED=y
CONFIG_STACKPROTECTOR=y
CONFIG_STACKPROTECTOR_STRONG=y
-# Perform extensive checks on reference counting
-CONFIG_REFCOUNT_FULL=y
-
# Disable to ensure random heap placement to make exploits harder
-# CONFIG_COMPAT_BRK is not set
+CONFIG_COMPAT_BRK=n
# Disable; exposes kernel text image layout
-# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_KCORE=n
# Increases the low-level kernel attack surface. Disable it instead.
# Removes the modify_ldt system call.
CONFIG_EXPERT=y
CONFIG_MODIFY_LDT_SYSCALL=n
-# Modern libc no longer needs a fixed-position mapping in userspace, remove it as a possible target.
-# CONFIG_LEGACY_VSYSCALL_EMULATE is not set
-CONFIG_LEGACY_VSYSCALL_NONE=y
-
# Prior to v4.1, assists heap memory attacks; best to keep interface disabled.
-# CONFIG_INET_DIAG is not set
+CONFIG_INET_DIAG=n
# Do not allow direct physical memory access (enable only STRICT mode...)
# Note that drivers like uvesafb/v86d depending on direct physical memory
# access would be affected.
-# CONFIG_DEVMEM is not set
+CONFIG_DEVMEM=y
CONFIG_STRICT_DEVMEM=y
CONFIG_IO_STRICT_DEVMEM=y
@@ -48,7 +40,6 @@ CONFIG_SCHED_STACK_END_CHECK=y
CONFIG_DEBUG_LIST=y
CONFIG_DEBUG_SG=y
CONFIG_DEBUG_NOTIFIERS=y
-CONFIG_DEBUG_CREDENTIALS=y
# Information exposure
CONFIG_PAGE_POISONING=y
@@ -64,3 +55,15 @@ CONFIG_STRICT_MODULE_RWX=y
# Meltdown and Spectre
CONFIG_PAGE_TABLE_ISOLATION=y
CONFIG_RETPOLINE=y
+
+# Exposing the TPM's Random Number Generator as a hwrng device.
+CONFIG_HW_RANDOM_TPM=y
+
+# Warn on W+X mappings at boot
+CONFIG_DEBUG_WX=y
+
+# Restrict unprivileged access to the kernel syslog
+CONFIG_SECURITY_DMESG_RESTRICT=y
+
+# The kernel will automatically load the module of any line dicipline that is asked for.
+CONFIG_LDISC_AUTOLOAD=n
diff --git a/features/security/security.scc b/features/security/security.scc
index 4abdf457..f3a651c0 100644
--- a/features/security/security.scc
+++ b/features/security/security.scc
@@ -3,3 +3,11 @@ define KFEATURE_DESCRIPTION "Enable/disable configurations that impact kernel se
define KFEATURE_COMPATIBILITY all
kconf non-hardware security.cfg
+
+if [ "$KARCH" = "x86_64" ]; then
+ kconf non-hardware security-x86_64.cfg
+fi
+
+if [ "$KARCH" = "arm64" ]; then
+ kconf non-hardware security-arm64.cfg
+fi
diff --git a/features/soc/baytrail/baytrail.cfg b/features/soc/baytrail/baytrail.cfg
index 390ef51b..c1b1120a 100644
--- a/features/soc/baytrail/baytrail.cfg
+++ b/features/soc/baytrail/baytrail.cfg
@@ -14,7 +14,6 @@ CONFIG_X86_INTEL_LPSS=y
# GPIO Support
CONFIG_GPIOLIB=y
-CONFIG_GPIO_SYSFS=y
CONFIG_SERIAL_8250_DW=y
diff --git a/features/soc/broxton/broxton.cfg b/features/soc/broxton/broxton.cfg
index b62b895c..4a760f6b 100644
--- a/features/soc/broxton/broxton.cfg
+++ b/features/soc/broxton/broxton.cfg
@@ -15,10 +15,9 @@ CONFIG_DMA_VIRTUAL_CHANNELS=y
CONFIG_INTEL_IDMA64=y
# GPIO support
-CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_GENERIC=y
CONFIG_GPIO_GENERIC_PLATFORM=y
# ACPI operation region support for BXT WhiskeyCove PMIC
-CONFIG_INTEL_SOC_PMIC_BXTWC=y
+CONFIG_INTEL_SOC_PMIC_BXTWC=m
CONFIG_BXT_WC_PMIC_OPREGION=y
diff --git a/features/soc/skylake/skylake.cfg b/features/soc/skylake/skylake.cfg
index 34066635..a1641a09 100644
--- a/features/soc/skylake/skylake.cfg
+++ b/features/soc/skylake/skylake.cfg
@@ -16,7 +16,6 @@ CONFIG_SENSORS_I5500=m
CONFIG_SND_HDA_I915=y
CONFIG_SND_SOC_INTEL_SKL_RT286_MACH=m
CONFIG_SND_SOC_INTEL_SST=m
-CONFIG_SND_SOC_INTEL_SST_ACPI=m
CONFIG_SND_DYNAMIC_MINORS=y
CONFIG_CRC8=m
diff --git a/features/sound/intel-snd-sof.cfg b/features/sound/intel-snd-sof.cfg
new file mode 100644
index 00000000..5efcd0c8
--- /dev/null
+++ b/features/sound/intel-snd-sof.cfg
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: MIT
+CONFIG_SOUNDWIRE=m
+CONFIG_SND_SOC=m
+CONFIG_SND_SOC_SOF_TOPLEVEL=y
+CONFIG_SND_SOC_SOF_INTEL_TOPLEVEL=y
+CONFIG_SND_SOC_SOF_PCI=m
+CONFIG_SND_SOC_SOF_ALDERLAKE=m
+CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE=m
+CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES=y
+CONFIG_SND_SOC_INTEL_SOUNDWIRE_SOF_MACH=m
+CONFIG_SND_SOC_SOF_HDA_LINK=y
+CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC=y
diff --git a/features/sound/intel-snd-sof.scc b/features/sound/intel-snd-sof.scc
new file mode 100644
index 00000000..85632930
--- /dev/null
+++ b/features/sound/intel-snd-sof.scc
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable Intel Sound Open Firmware(SOF) support for Intel audio DSPs"
+
+kconf hardware intel-snd-sof.cfg
diff --git a/features/stm/stm.cfg b/features/stm/stm.cfg
new file mode 100644
index 00000000..83fe45a9
--- /dev/null
+++ b/features/stm/stm.cfg
@@ -0,0 +1,7 @@
+CONFIG_STM=m
+CONFIG_STM_PROTO_BASIC=m
+CONFIG_STM_PROTO_SYS_T=m
+CONFIG_STM_DUMMY=m
+CONFIG_STM_SOURCE_CONSOLE=m
+CONFIG_STM_SOURCE_HEARTBEAT=m
+CONFIG_STM_SOURCE_FTRACE=m
diff --git a/features/stm/stm.scc b/features/stm/stm.scc
new file mode 100644
index 00000000..1e340623
--- /dev/null
+++ b/features/stm/stm.scc
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "A System Trace Module support"
+
+kconf hardware stm.cfg
diff --git a/features/telemetry/intel-telemetry.cfg b/features/telemetry/intel-telemetry.cfg
index dd07fe91..9372aa17 100644
--- a/features/telemetry/intel-telemetry.cfg
+++ b/features/telemetry/intel-telemetry.cfg
@@ -3,8 +3,8 @@
CONFIG_X86_64=y
# Other dependencies
-CONFIG_INTEL_PMC_IPC=y
+CONFIG_MFD_INTEL_PMC_BXT=m
CONFIG_INTEL_PUNIT_IPC=y
# The feature
-CONFIG_INTEL_TELEMETRY=y
+CONFIG_INTEL_TELEMETRY=m
diff --git a/features/thermal/coretemp-x86_64.cfg b/features/thermal/coretemp-x86_64.cfg
new file mode 100644
index 00000000..4a34163a
--- /dev/null
+++ b/features/thermal/coretemp-x86_64.cfg
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: MIT
+# ACPI INT340X thermal drivers
+CONFIG_INT340X_THERMAL=m
+
diff --git a/features/thermal/coretemp.cfg b/features/thermal/coretemp.cfg
index 85e2d58b..1b89b549 100644
--- a/features/thermal/coretemp.cfg
+++ b/features/thermal/coretemp.cfg
@@ -8,12 +8,10 @@ CONFIG_SENSORS_CORETEMP=m
# Intel SoCs DTS thermal driver
CONFIG_INTEL_SOC_DTS_THERMAL=m
-# ACPI INT340X thermal drivers
-CONFIG_INT340X_THERMAL=m
-
# Intel PowerClamp idle injection driver
CONFIG_INTEL_POWERCLAMP=m
# Intel PMIC thermal driver
+CONFIG_MFD_INTEL_PMC_BXT=m
CONFIG_INTEL_SOC_PMIC_BXTWC=m
CONFIG_INTEL_BXT_PMIC_THERMAL=m
diff --git a/features/thermal/coretemp.scc b/features/thermal/coretemp.scc
index 272d5578..ded07295 100644
--- a/features/thermal/coretemp.scc
+++ b/features/thermal/coretemp.scc
@@ -3,3 +3,7 @@ define KFEATURE_DESCRIPTION "Coretemp support for Intel platforms"
define KFEATURE_COMPATIBILITY board
kconf hardware coretemp.cfg
+if [ "$KARCH" = "x86_64" ] ; then
+ kconf hardware coretemp-x86_64.cfg
+fi
+
diff --git a/features/thunderbolt/thunderbolt.cfg b/features/thunderbolt/thunderbolt.cfg
index 2408da5b..b110f956 100644
--- a/features/thunderbolt/thunderbolt.cfg
+++ b/features/thunderbolt/thunderbolt.cfg
@@ -1,2 +1,4 @@
# SPDX-License-Identifier: MIT
-CONFIG_THUNDERBOLT=m
+CONFIG_USB4=m
+CONFIG_INTEL_WMI_THUNDERBOLT=m
+CONFIG_USB4_NET=m
diff --git a/features/tpm/tpm-1.2.cfg b/features/tpm/tpm-1.2.cfg
new file mode 100644
index 00000000..d1fcf98c
--- /dev/null
+++ b/features/tpm/tpm-1.2.cfg
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: MIT
+# Enable TPM 1.2 device drivers.
+CONFIG_TCG_TIS_I2C_ATMEL=y
+CONFIG_TCG_TIS_I2C_INFINEON=y
+CONFIG_TCG_TIS_I2C_NUVOTON=y
+CONFIG_TCG_NSC=y
+CONFIG_TCG_ATMEL=y
+CONFIG_TCG_INFINEON=y
+CONFIG_TCG_TIS_ST33ZP24=y
+CONFIG_TCG_TIS_ST33ZP24_I2C=y
+CONFIG_TCG_TIS_ST33ZP24_SPI=y \ No newline at end of file
diff --git a/features/tpm/tpm-1.2.scc b/features/tpm/tpm-1.2.scc
new file mode 100644
index 00000000..74900486
--- /dev/null
+++ b/features/tpm/tpm-1.2.scc
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable TCG TPM (Trusted Computing Group Trusted Platform Module) 1.2 drivers"
+define KFEATURE_COMPATIBILITY board
+
+include tpm-common.scc
+
+kconf hardware tpm-1.2.cfg
diff --git a/features/tpm/tpm-2.0-crb.cfg b/features/tpm/tpm-2.0-crb.cfg
new file mode 100644
index 00000000..27a1ba25
--- /dev/null
+++ b/features/tpm/tpm-2.0-crb.cfg
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: MIT
+# Enable TPM device drivers.
+CONFIG_TCG_CRB=y
diff --git a/features/tpm/tpm-2.0-crb.scc b/features/tpm/tpm-2.0-crb.scc
new file mode 100644
index 00000000..1274b3c7
--- /dev/null
+++ b/features/tpm/tpm-2.0-crb.scc
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable TCG CRB TPM (Trusted Computing Group Command Response Buffer Trusted Platform Module) 2.0 driver"
+define KFEATURE_COMPATIBILITY board
+
+include tpm-common.scc
+
+kconf hardware tpm-2.0-crb.cfg
diff --git a/features/tpm/tpm-2.0.cfg b/features/tpm/tpm-2.0.cfg
new file mode 100644
index 00000000..9f427afa
--- /dev/null
+++ b/features/tpm/tpm-2.0.cfg
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: MIT
+# Enable TPM device drivers.
+CONFIG_SPI=y
+CONFIG_TCG_TIS_SPI=y
diff --git a/features/tpm/tpm-2.0.scc b/features/tpm/tpm-2.0.scc
new file mode 100644
index 00000000..83440f8b
--- /dev/null
+++ b/features/tpm/tpm-2.0.scc
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable TCG TPM (Trusted Computing Group Trusted Platform Module) 2.0 drivers"
+define KFEATURE_COMPATIBILITY board
+
+include tpm-common.scc
+
+kconf hardware tpm-2.0.cfg
diff --git a/features/tpm/tpm-common.cfg b/features/tpm/tpm-common.cfg
new file mode 100644
index 00000000..7e2ea6c1
--- /dev/null
+++ b/features/tpm/tpm-common.cfg
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: MIT
+# Enable TPM hardware support.
+CONFIG_TCG_TPM=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_TPM=y
+CONFIG_TCG_TIS_CORE=y
+CONFIG_TCG_TIS=y
diff --git a/features/tpm/tpm-common.scc b/features/tpm/tpm-common.scc
new file mode 100644
index 00000000..31a070c0
--- /dev/null
+++ b/features/tpm/tpm-common.scc
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable common TCG TPM (Trusted Computing Group Trusted Platform Module) features"
+define KFEATURE_COMPATIBILITY board
+
+kconf hardware tpm-common.cfg
diff --git a/features/tpm/tpm.cfg b/features/tpm/tpm.cfg
deleted file mode 100644
index ea10c1fb..00000000
--- a/features/tpm/tpm.cfg
+++ /dev/null
@@ -1,20 +0,0 @@
-# SPDX-License-Identifier: MIT
-# Enable TPM device drivers.
-CONFIG_TCG_TPM=y
-CONFIG_HW_RANDOM=y
-CONFIG_HW_RANDOM_TPM=y
-CONFIG_TCG_TIS_CORE=y
-CONFIG_TCG_TIS=y
-CONFIG_SPI=y
-CONFIG_TCG_TIS_SPI=y
-CONFIG_TCG_TIS_I2C_ATMEL=y
-CONFIG_TCG_TIS_I2C_INFINEON=y
-CONFIG_TCG_TIS_I2C_NUVOTON=y
-CONFIG_TCG_NSC=y
-CONFIG_TCG_ATMEL=y
-CONFIG_TCG_INFINEON=y
-CONFIG_TCG_CRB=y
-CONFIG_TCG_VTPM_PROXY=y
-CONFIG_TCG_TIS_ST33ZP24=y
-CONFIG_TCG_TIS_ST33ZP24_I2C=y
-CONFIG_TCG_TIS_ST33ZP24_SPI=y
diff --git a/features/tpm/tpm.scc b/features/tpm/tpm.scc
index a1435480..1f3ba9cf 100644
--- a/features/tpm/tpm.scc
+++ b/features/tpm/tpm.scc
@@ -1,5 +1,9 @@
# SPDX-License-Identifier: MIT
-define KFEATURE_DESCRIPTION "Enable TCG TPM driver (Trusted Computing Group Trusted Platform Module)"
+define KFEATURE_DESCRIPTION "Enable TCG TPM (Trusted Computing Group Trusted Platform Module) drivers"
define KFEATURE_COMPATIBILITY board
-kconf hardware tpm.cfg
+include tpm-common.scc
+include tpm-1.2.scc
+include tpm-2.0.scc
+include tpm-2.0-crb.scc
+include vtpm.scc
diff --git a/features/tpm/vtpm.cfg b/features/tpm/vtpm.cfg
new file mode 100644
index 00000000..eeb58e96
--- /dev/null
+++ b/features/tpm/vtpm.cfg
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: MIT
+# Enable vTPM device drivers.
+CONFIG_TCG_VTPM_PROXY=y
diff --git a/features/tpm/vtpm.scc b/features/tpm/vtpm.scc
new file mode 100644
index 00000000..e927ffb6
--- /dev/null
+++ b/features/tpm/vtpm.scc
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable virtual TCG TPM (Trusted Computing Group Trusted Platform Module) proxy driver"
+define KFEATURE_COMPATIBILITY board
+
+include tpm-common.scc
+
+kconf hardware vtpm.cfg
diff --git a/features/transparent-hugepage/transparent-hugepage.cfg b/features/transparent-hugepage/transparent-hugepage.cfg
new file mode 100644
index 00000000..5079bf3f
--- /dev/null
+++ b/features/transparent-hugepage/transparent-hugepage.cfg
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: MIT
+#
+# Memory Management options
+#
+CONFIG_TRANSPARENT_HUGEPAGE=y
+CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS=y
diff --git a/features/transparent-hugepage/transparent-hugepage.scc b/features/transparent-hugepage/transparent-hugepage.scc
new file mode 100644
index 00000000..3cad4b3a
--- /dev/null
+++ b/features/transparent-hugepage/transparent-hugepage.scc
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Transparent Hugepage Support"
+
+kconf hardware transparent-hugepage.cfg
diff --git a/features/tsn/tsn.cfg b/features/tsn/tsn.cfg
new file mode 100644
index 00000000..c0cac7db
--- /dev/null
+++ b/features/tsn/tsn.cfg
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+CONFIG_NET_SCH_ETF=m
+CONFIG_NET_SCH_CBS=m
+CONFIG_NET_SCH_MQPRIO=m
+CONFIG_NET_SCH_TAPRIO=m
diff --git a/features/tsn/tsn.scc b/features/tsn/tsn.scc
new file mode 100644
index 00000000..0f33451e
--- /dev/null
+++ b/features/tsn/tsn.scc
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable Time-Sensitive Networking support"
+kconf non-hardware tsn.cfg
diff --git a/features/tun/tun.cfg b/features/tun/tun.cfg
new file mode 100644
index 00000000..b45d3e9b
--- /dev/null
+++ b/features/tun/tun.cfg
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+# dependency
+CONFIG_INET=y
+
+CONFIG_TUN=y
diff --git a/features/tun/tun.scc b/features/tun/tun.scc
new file mode 100644
index 00000000..5a4cc3bc
--- /dev/null
+++ b/features/tun/tun.scc
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable universal TUN/TAP device driver support"
+define KFEATURE_COMPATIBILITY all
+
+kconf non-hardware tun.cfg
diff --git a/features/uptime/uptime-allow-the-optional-limiting-of-kernel-runtime.patch b/features/uptime/uptime-allow-the-optional-limiting-of-kernel-runtime.patch
deleted file mode 100644
index aa143059..00000000
--- a/features/uptime/uptime-allow-the-optional-limiting-of-kernel-runtime.patch
+++ /dev/null
@@ -1,251 +0,0 @@
-From a21e483b57c8c31beaa5063268ec35da375daf04 Mon Sep 17 00:00:00 2001
-From: Bruce Ashfield <bruce.ashfield@windriver.com>
-Date: Tue, 12 Jul 2011 10:26:50 -0400
-Subject: [PATCH] uptime: allow the optional limiting of kernel runtime
-
-Introduce the ability to limit the limit the uptime of a kernel.
-When enabled, these options set a maximum uptime on the kernel, and
-(optionally) trigger a clean reboot at expiration.
-
-This functionality may appear to be very close to the softdog watchdog
-implementation. It is. But can't be the softdog for several reasons:
-
- - The soft watchdog should be available while this functionality is active
- - The duration range is different between this and the softdog. The
- timeout available here is potentially quite a bit longer.
- - At expiration, there are different expiration requirements and actions.
- - This functionality is specific to a particular use case and should
- not impact mainline functionality
-
-To cleanly restart the kernel after one minute of uptime, the following
-config items would be required:
-
- CONFIG_UPTIME_LIMITED_KERNEL=y
- CONFIG_UPTIME_LIMIT_DURATION=1
- CONFIG_UPTIME_LIMIT_KERNEL_REBOOT=y
-
-Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
-
-diff --git a/init/Kconfig b/init/Kconfig
-index cac3f096050d..77d6d5fa1b1d 100644
---- a/init/Kconfig
-+++ b/init/Kconfig
-@@ -1376,6 +1376,31 @@ menuconfig EXPERT
- environments which can tolerate a "non-standard" kernel.
- Only use this if you really know what you are doing.
-
-+config UPTIME_LIMITED_KERNEL
-+ bool "Create a kernel with uptime limitations"
-+ default n
-+ help
-+ Limit the amount of time a kernel can run. The associated UPTIME_LIMIT*
-+ kernel config options should be used to tune the behaviour.
-+
-+config UPTIME_LIMIT_DURATION
-+ int "Kernel uptime limit in minutes"
-+ depends on UPTIME_LIMITED_KERNEL
-+ range 0 14400
-+ default 0
-+ help
-+ Define the uptime limitation on a kernel in minutes. Once
-+ the defined time expires the kernel will emit a warning, cease
-+ to be usable and eventually restart. The valid range is 0 (disable)
-+ to 14400 (10 days)
-+
-+config UPTIME_LIMIT_KERNEL_REBOOT
-+ bool "Reboot a time limited kernel at expiration"
-+ depends on UPTIME_LIMITED_KERNEL
-+ default y
-+ help
-+ Reboot an uptime limited kernel at expiration.
-+
- config UID16
- bool "Enable 16-bit UID system calls" if EXPERT
- depends on HAVE_UID16 && MULTIUSER
-diff --git a/kernel/Makefile b/kernel/Makefile
-index e2ec54e2b952..6b7bdddd624b 100644
---- a/kernel/Makefile
-+++ b/kernel/Makefile
-@@ -45,6 +45,7 @@ obj-$(CONFIG_FREEZER) += freezer.o
- obj-$(CONFIG_PROFILING) += profile.o
- obj-$(CONFIG_STACKTRACE) += stacktrace.o
- obj-y += time/
-+obj-$(CONFIG_UPTIME_LIMITED_KERNEL) += uptime_limit.o
- obj-$(CONFIG_FUTEX) += futex.o
- ifeq ($(CONFIG_COMPAT),y)
- obj-$(CONFIG_FUTEX) += futex_compat.o
-diff --git a/kernel/uptime_limit.c b/kernel/uptime_limit.c
-new file mode 100644
-index 000000000000..b6a1a5e4f9d9
---- /dev/null
-+++ b/kernel/uptime_limit.c
-@@ -0,0 +1,166 @@
-+/*
-+ * uptime_limit.c
-+ *
-+ * This file contains the functions which can limit kernel uptime
-+ *
-+ * Copyright (C) 2011 Bruce Ashfield (bruce.ashfield@windriver.com)
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ *
-+ * This functionality is somewhat close to the softdog watchdog
-+ * implementation, but it cannot be used directly for several reasons:
-+ *
-+ * - The soft watchdog should be available while this functionality is active
-+ * - The duration range is different between this and the softdog. The
-+ * timeout available here is potentially quite a bit longer.
-+ * - At expiration, there are different expiration requirements and actions.
-+ * - This functionality is specific to a particular use case and should
-+ * not impact mainline functionality
-+ *
-+ */
-+#include <linux/kernel.h>
-+#include <linux/reboot.h>
-+#include <linux/timer.h>
-+#include <linux/delay.h>
-+#include <linux/kthread.h>
-+
-+#define UPTIME_LIMIT_IN_SECONDS (CONFIG_UPTIME_LIMIT_DURATION * 60)
-+#define MIN(X, Y) ((X) <= (Y) ? (X) : (Y))
-+#define TEN_MINUTES_IN_SECONDS 600
-+
-+enum uptime_expiration_type {
-+ uptime_no_action,
-+ uptime_reboot
-+};
-+
-+static enum uptime_expiration_type uptime_expiration_action = uptime_no_action;
-+static struct timer_list timelimit_timer;
-+static struct task_struct *uptime_worker_task;
-+
-+static void timelimit_expire(unsigned long timeout_seconds)
-+{
-+ char msg[128];
-+ int msglen = 127;
-+
-+ if (timeout_seconds) {
-+ if (timeout_seconds >= 60)
-+ snprintf(msg, msglen,
-+ "Uptime: kernel validity duration has %d %s remaining\n",
-+ (int) timeout_seconds / 60, "minute(s)");
-+ else
-+ snprintf(msg, msglen,
-+ "Uptime: kernel validity duration has %d %s remaining\n",
-+ (int) timeout_seconds, "seconds");
-+
-+ printk(KERN_CRIT "%s", msg);
-+
-+ timelimit_timer.expires = jiffies + timeout_seconds * HZ;
-+ timelimit_timer.data = 0;
-+ add_timer_on(&timelimit_timer, cpumask_first(cpu_online_mask));
-+ } else {
-+ printk(KERN_CRIT "Uptime: Kernel validity timeout has expired\n");
-+#ifdef CONFIG_UPTIME_LIMIT_KERNEL_REBOOT
-+ uptime_expiration_action = uptime_reboot;
-+ wake_up_process(uptime_worker_task);
-+ }
-+#endif
-+}
-+
-+/*
-+ * This thread starts and then immediately goes to sleep. When it is woken
-+ * up, it carries out the instructions left in uptime_expiration_action. If
-+ * no action was specified it simply goes back to sleep.
-+ */
-+static int uptime_worker(void *unused)
-+{
-+ set_current_state(TASK_INTERRUPTIBLE);
-+
-+ while (!kthread_should_stop()) {
-+ schedule();
-+
-+ if (kthread_should_stop())
-+ break;
-+
-+ if (uptime_expiration_action == uptime_reboot) {
-+ printk(KERN_CRIT "Uptime: restarting machine\n");
-+ kernel_restart(NULL);
-+ }
-+
-+ set_current_state(TASK_INTERRUPTIBLE);
-+ }
-+ __set_current_state(TASK_RUNNING);
-+
-+ return 0;
-+}
-+
-+static int timeout_enable(int cpu)
-+{
-+ int err = 0;
-+ int warning_limit;
-+
-+ /*
-+ * Create an uptime worker thread. This thread is required since the
-+ * safe version of kernel restart cannot be called from a
-+ * non-interruptible context. Which means we cannot call it directly
-+ * from a timer callback. So we arrange for the timer expiration to
-+ * wakeup a thread, which performs the action.
-+ */
-+ uptime_worker_task = kthread_create(uptime_worker,
-+ (void *)(unsigned long)cpu,
-+ "uptime_worker/%d", cpu);
-+ if (IS_ERR(uptime_worker_task)) {
-+ printk(KERN_ERR "Uptime: task for cpu %i failed\n", cpu);
-+ err = PTR_ERR(uptime_worker_task);
-+ goto out;
-+ }
-+ /* bind to cpu0 to avoid migration and hot plug nastiness */
-+ kthread_bind(uptime_worker_task, cpu);
-+ wake_up_process(uptime_worker_task);
-+
-+ /* Create the timer that will wake the uptime thread at expiration */
-+ init_timer(&timelimit_timer);
-+ timelimit_timer.function = timelimit_expire;
-+ /*
-+ * Fire two timers. One warning timeout and the final timer
-+ * which will carry out the expiration action. The warning timer will
-+ * expire at the minimum of half the original time or ten minutes.
-+ */
-+ warning_limit = MIN(UPTIME_LIMIT_IN_SECONDS/2, TEN_MINUTES_IN_SECONDS);
-+ timelimit_timer.expires = jiffies + warning_limit * HZ;
-+ timelimit_timer.data = UPTIME_LIMIT_IN_SECONDS - warning_limit;
-+
-+ add_timer_on(&timelimit_timer, cpumask_first(cpu_online_mask));
-+out:
-+ return err;
-+}
-+
-+static int __init timelimit_init(void)
-+{
-+ int err = 0;
-+
-+ printk(KERN_INFO "Uptime: system uptime restrictions enabled\n");
-+
-+ /*
-+ * Enable the timeout thread for cpu 0 only, assuming that the
-+ * uptime limit is non-zero, to protect against any cpu
-+ * migration issues.
-+ */
-+ if (UPTIME_LIMIT_IN_SECONDS)
-+ err = timeout_enable(0);
-+
-+ return err;
-+}
-+device_initcall(timelimit_init);
---
-2.10.1
-
diff --git a/features/uptime/uptime.scc b/features/uptime/uptime.scc
deleted file mode 100644
index 4f8a58ba..00000000
--- a/features/uptime/uptime.scc
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: MIT
-patch uptime-allow-the-optional-limiting-of-kernel-runtime.patch
diff --git a/features/usb/usb-dummy-hcd.cfg b/features/usb/usb-dummy-hcd.cfg
new file mode 100644
index 00000000..ab7c2143
--- /dev/null
+++ b/features/usb/usb-dummy-hcd.cfg
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: MIT
+CONFIG_USB_DUMMY_HCD=y
diff --git a/features/usb/usb-dummy-hcd.scc b/features/usb/usb-dummy-hcd.scc
new file mode 100644
index 00000000..6684ed9c
--- /dev/null
+++ b/features/usb/usb-dummy-hcd.scc
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable emulated USB host and device support (dummy HCD)"
+define KFEATURE_COMPATIBILITY all
+
+include usb-base.scc
+
+kconf non-hardware usb-dummy-hcd.cfg
diff --git a/features/usb/usb-raw-gadget.cfg b/features/usb/usb-raw-gadget.cfg
new file mode 100644
index 00000000..6e169ab5
--- /dev/null
+++ b/features/usb/usb-raw-gadget.cfg
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+# dependency
+CONFIG_USB_GADGET=y
+
+CONFIG_USB_RAW_GADGET=y
diff --git a/features/usb/usb-raw-gadget.scc b/features/usb/usb-raw-gadget.scc
new file mode 100644
index 00000000..9f0c2eb8
--- /dev/null
+++ b/features/usb/usb-raw-gadget.scc
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable USB raw gadget"
+define KFEATURE_COMPATIBILITY all
+
+include usb-base.scc
+
+kconf non-hardware usb-raw-gadget.cfg
diff --git a/features/usb/usb-typec.cfg b/features/usb/usb-typec.cfg
index f8cef1d3..3c5a2312 100644
--- a/features/usb/usb-typec.cfg
+++ b/features/usb/usb-typec.cfg
@@ -3,7 +3,9 @@ CONFIG_TYPEC=m
CONFIG_TYPEC_TCPM=m
# Dependencies
-CONFIG_INTEL_PMC_IPC=y
+CONFIG_MFD_INTEL_PMC_BXT=m
# Intel WhiskeyCove PMIC USB Type-C PHY driver
CONFIG_TYPEC_WCOVE=m
+
+CONFIG_TYPEC_TCPCI=m
diff --git a/features/vdso/vdso.cfg b/features/vdso/vdso.cfg
index 9b1cdd3d..ba84655b 100644
--- a/features/vdso/vdso.cfg
+++ b/features/vdso/vdso.cfg
@@ -1,2 +1,2 @@
# SPDX-License-Identifier: MIT
-# CONFIG_COMPAT_VDSO is not set
+CONFIG_COMPAT_VDSO=n
diff --git a/features/vfat/fat-Replace-prandom_u32-with-get_random_u32.patch b/features/vfat/fat-Replace-prandom_u32-with-get_random_u32.patch
new file mode 100644
index 00000000..3d4b8092
--- /dev/null
+++ b/features/vfat/fat-Replace-prandom_u32-with-get_random_u32.patch
@@ -0,0 +1,40 @@
+From 0b07d2478b6baf627d000f7f1901b148f2a6dfc2 Mon Sep 17 00:00:00 2001
+From: Kevin Hao <kexin.hao@windriver.com>
+Date: Fri, 7 Apr 2023 21:03:41 +0800
+Subject: [PATCH] fat: Replace prandom_u32() with get_random_u32()
+
+The prandom_u32() is just wrapper of get_random_u32() and has been
+removed by commit de492c83cae0 ("prandom: remove unused functions").
+So use get_random_u32() directly.
+
+Signed-off-by: Kevin Hao <kexin.hao@windriver.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/fat/namei_vfat.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
+index ef5cf74789ca..ef79a242751d 100644
+--- a/fs/fat/namei_vfat.c
++++ b/fs/fat/namei_vfat.c
+@@ -616,7 +616,7 @@ static void vfat_build_dummy_83_buffer(struct inode *dir, char *msdos_name,
+ 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x22, 0x2a,
+ 0x3a, 0x3c, 0x3e, 0x3f, 0x5b, 0x5d, 0x7c };
+ int i, tilde_pos, slash_pos;
+- u32 rand_num = prandom_u32();
++ u32 rand_num = get_random_u32();
+
+ /* We need a '~' in the prefix to make Win98 happy. */
+ tilde_pos = rand_num % 8;
+@@ -651,7 +651,7 @@ static void vfat_build_dummy_83_buffer(struct inode *dir, char *msdos_name,
+ invalidchar[rand_num % sizeof(invalidchar)];
+ rand_num /= sizeof(invalidchar);
+ if (rand_num < sizeof(invalidchar))
+- rand_num = prandom_u32();
++ rand_num = get_random_u32();
+ }
+ }
+ }
+--
+2.34.1
+
diff --git a/features/vfat/vfat.scc b/features/vfat/vfat.scc
index cfe1c7d9..24ec7dfd 100644
--- a/features/vfat/vfat.scc
+++ b/features/vfat/vfat.scc
@@ -3,3 +3,4 @@ patch FAT-Add-CONFIG_VFAT_FS_NO_DUALNAMES-option.patch
patch FAT-Add-CONFIG_VFAT_NO_CREATE_WITH_LONGNAMES-option.patch
patch FAT-Added-FAT_NO_83NAME.patch
patch fat-don-t-use-obsolete-random32-call-in-namei_vfat.patch
+patch fat-Replace-prandom_u32-with-get_random_u32.patch
diff --git a/features/vfio/vfio.cfg b/features/vfio/vfio.cfg
index 267fbaf8..94991365 100644
--- a/features/vfio/vfio.cfg
+++ b/features/vfio/vfio.cfg
@@ -1,6 +1,5 @@
# SPDX-License-Identifier: MIT
CONFIG_VFIO_IOMMU_TYPE1=m
-CONFIG_VFIO_VIRQFD=m
CONFIG_VFIO=m
CONFIG_VFIO_PCI=m
CONFIG_VFIO_PCI_VGA=y
diff --git a/features/vswitch/vswitch.cfg b/features/vswitch/vswitch.cfg
new file mode 100644
index 00000000..7e39b558
--- /dev/null
+++ b/features/vswitch/vswitch.cfg
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+# Misc configs
+CONFIG_OPENVSWITCH=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_ACT_POLICE=m
diff --git a/features/vswitch/vswitch.scc b/features/vswitch/vswitch.scc
new file mode 100644
index 00000000..12c6affb
--- /dev/null
+++ b/features/vswitch/vswitch.scc
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable in kernel OpenvSwitch module"
+define KFEATURE_COMPATIBILITY board
+
+kconf non-hardware vswitch.cfg
diff --git a/features/wifi/ralink-pci.cfg b/features/wifi/ralink-pci.cfg
index b4639ea0..c7e95040 100644
--- a/features/wifi/ralink-pci.cfg
+++ b/features/wifi/ralink-pci.cfg
@@ -10,7 +10,7 @@ CONFIG_RT2500PCI=m
CONFIG_RT61PCI=m
CONFIG_RT2800PCI=m
CONFIG_RT2800PCI_RT33XX=y
-config RT2800PCI_RT35XX=y
-config RT2800PCI_RT53XX=y
-config RT2800PCI_RT3290=y
+CONFIG_RT2800PCI_RT35XX=y
+CONFIG_RT2800PCI_RT53XX=y
+CONFIG_RT2800PCI_RT3290=y
diff --git a/features/x2apic/x2apic.cfg b/features/x2apic/x2apic.cfg
index ca91dc0d..8efa10f8 100644
--- a/features/x2apic/x2apic.cfg
+++ b/features/x2apic/x2apic.cfg
@@ -1,3 +1,5 @@
# SPDX-License-Identifier: MIT
+
+CONFIG_IOMMU_SUPPORT=y
CONFIG_IRQ_REMAP=y
CONFIG_X86_X2APIC=y
diff --git a/features/xen/xen-x86.cfg b/features/xen/xen-x86.cfg
new file mode 100644
index 00000000..69fcd731
--- /dev/null
+++ b/features/xen/xen-x86.cfg
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: MIT
+
+CONFIG_HYPERVISOR_GUEST=y
+CONFIG_PCI_XEN=y
+CONFIG_XEN_ACPI_PROCESSOR=m
+CONFIG_XEN_DEBUG_FS=n
+CONFIG_XEN_MCE_LOG=y
+CONFIG_XEN_PCIDEV_BACKEND=m
+CONFIG_XEN_PCIDEV_FRONTEND=y
+CONFIG_XEN_PVHVM=y
+CONFIG_XEN_SAVE_RESTORE=y
diff --git a/features/xen/xen.cfg b/features/xen/xen.cfg
new file mode 100644
index 00000000..7da87825
--- /dev/null
+++ b/features/xen/xen.cfg
@@ -0,0 +1,38 @@
+CONFIG_PARAVIRT=y
+CONFIG_XEN=y
+CONFIG_XEN_DOM0=y
+CONFIG_MMU_NOTIFIER=y
+CONFIG_HIBERNATE_CALLBACKS=y
+CONFIG_SYS_HYPERVISOR=y
+CONFIG_XEN_BLKDEV_FRONTEND=y
+CONFIG_XEN_BLKDEV_BACKEND=m
+CONFIG_XEN_SCSI_FRONTEND=m
+CONFIG_XEN_NETDEV_FRONTEND=y
+CONFIG_XEN_NETDEV_BACKEND=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_XEN_KBDDEV_FRONTEND=y
+CONFIG_HVC_IRQ=y
+CONFIG_HVC_XEN=y
+CONFIG_HVC_XEN_FRONTEND=y
+CONFIG_XEN_WDT=m
+CONFIG_FB_SYS_FILLRECT=y
+CONFIG_FB_SYS_COPYAREA=y
+CONFIG_FB_SYS_IMAGEBLIT=y
+CONFIG_FB_SYS_FOPS=y
+CONFIG_FB_DEFERRED_IO=y
+CONFIG_XEN_FBDEV_FRONTEND=y
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_SCRUB_PAGES_DEFAULT=y
+CONFIG_XEN_DEV_EVTCHN=y
+CONFIG_XEN_BACKEND=y
+CONFIG_XENFS=y
+CONFIG_XEN_COMPAT_XENFS=y
+CONFIG_XEN_SYS_HYPERVISOR=y
+CONFIG_XEN_XENBUS_FRONTEND=y
+CONFIG_XEN_GNTDEV=m
+CONFIG_XEN_GRANT_DEV_ALLOC=m
+CONFIG_SWIOTLB_XEN=y
+CONFIG_XEN_PRIVCMD=y
+CONFIG_XEN_HAVE_PVMMU=y
+CONFIG_XEN_PVCALLS_FRONTEND=y
+CONFIG_XEN_PVCALLS_BACKEND=y
diff --git a/features/xen/xen.scc b/features/xen/xen.scc
new file mode 100644
index 00000000..e7c85a1b
--- /dev/null
+++ b/features/xen/xen.scc
@@ -0,0 +1,8 @@
+define KFEATURE_DESCRIPTION "Xen Kernel Support"
+define KFEATURE_COMPATIBILITY arch
+
+kconf non-hardware xen.cfg
+
+if [ "$KARCH" = "x86_64" ] || [ "$KARCH" = "i386" ]; then
+ kconf non-hardware xen-x86.cfg
+fi
diff --git a/features/xilinx/hdmi-module/hdmi-module.cfg b/features/xilinx/hdmi-module/hdmi-module.cfg
new file mode 100644
index 00000000..b0117515
--- /dev/null
+++ b/features/xilinx/hdmi-module/hdmi-module.cfg
@@ -0,0 +1,224 @@
+# SPDX-License-Identifier: MIT
+CONFIG_VIDEO_TDA1997X=n
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_JACK=y
+CONFIG_SND_JACK_INPUT_DEV=y
+CONFIG_SND_OSSEMUL=n
+CONFIG_SND_PCM_TIMER=y
+CONFIG_SND_HRTIMER=n
+CONFIG_SND_DYNAMIC_MINORS=n
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_PROC_FS=y
+CONFIG_SND_VERBOSE_PROCFS=y
+CONFIG_SND_VERBOSE_PRINTK=n
+CONFIG_SND_DEBUG=n
+CONFIG_SND_SEQUENCER=n
+CONFIG_SND_DRIVERS=y
+CONFIG_SND_DUMMY=n
+CONFIG_SND_ALOOP=n
+CONFIG_SND_MTPAV=n
+CONFIG_SND_SERIAL_U16550=n
+CONFIG_SND_MPU401=n
+
+#
+# HD-Audio
+#
+# end of HD-Audio
+
+CONFIG_SND_HDA_PREALLOC_SIZE=64
+CONFIG_SND_SPI=y
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=n
+CONFIG_SND_USB_UA101=n
+CONFIG_SND_USB_CAIAQ=n
+CONFIG_SND_USB_6FIRE=n
+CONFIG_SND_USB_HIFACE=n
+CONFIG_SND_BCD2000=n
+CONFIG_SND_USB_POD=n
+CONFIG_SND_USB_PODHD=n
+CONFIG_SND_USB_TONEPORT=n
+CONFIG_SND_USB_VARIAX=n
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_AMD_ACP=n
+CONFIG_SND_ATMEL_SOC=n
+CONFIG_SND_DESIGNWARE_I2S=n
+
+#
+# SoC Audio for Freescale CPUs
+#
+
+#
+# Common SoC Audio options for Freescale CPUs:
+#
+CONFIG_SND_SOC_FSL_ASRC=n
+CONFIG_SND_SOC_FSL_SAI=n
+CONFIG_SND_SOC_FSL_AUDMIX=n
+CONFIG_SND_SOC_FSL_SSI=n
+CONFIG_SND_SOC_FSL_SPDIF=n
+CONFIG_SND_SOC_FSL_ESAI=n
+CONFIG_SND_SOC_FSL_MICFIL=n
+CONFIG_SND_SOC_IMX_AUDMUX=n
+# end of SoC Audio for Freescale CPUs
+
+CONFIG_SND_I2S_HI6210_I2S=n
+CONFIG_SND_SOC_IMG=n
+CONFIG_SND_SOC_MTK_BTCVSD=n
+CONFIG_SND_SOC_SOF_TOPLEVEL=n
+
+#
+# STMicroelectronics STM32 SOC audio support
+#
+# end of STMicroelectronics STM32 SOC audio support
+
+CONFIG_SND_SOC_XILINX_DP=n
+CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER=n
+CONFIG_SND_SOC_XILINX_SDI=n
+CONFIG_SND_SOC_XILINX_I2S=n
+CONFIG_SND_SOC_XILINX_SPDIF=n
+CONFIG_SND_SOC_XTFPGA_I2S=n
+CONFIG_ZX_TDM=n
+CONFIG_SND_SOC_I2C_AND_SPI=y
+
+#
+# CODEC drivers
+#
+CONFIG_SND_SOC_AC97_CODEC=n
+CONFIG_SND_SOC_ADAU1701=n
+CONFIG_SND_SOC_ADAU1761_I2C=n
+CONFIG_SND_SOC_ADAU1761_SPI=n
+CONFIG_SND_SOC_ADAU7002=n
+CONFIG_SND_SOC_AK4104=n
+CONFIG_SND_SOC_AK4118=n
+CONFIG_SND_SOC_AK4458=n
+CONFIG_SND_SOC_AK4554=n
+CONFIG_SND_SOC_AK4613=n
+CONFIG_SND_SOC_AK4642=n
+CONFIG_SND_SOC_AK5386=n
+CONFIG_SND_SOC_AK5558=n
+CONFIG_SND_SOC_ALC5623=n
+CONFIG_SND_SOC_BD28623=n
+CONFIG_SND_SOC_BT_SCO=n
+CONFIG_SND_SOC_CS35L32=n
+CONFIG_SND_SOC_CS35L33=n
+CONFIG_SND_SOC_CS35L34=n
+CONFIG_SND_SOC_CS35L35=n
+CONFIG_SND_SOC_CS35L36=n
+CONFIG_SND_SOC_CS42L42=n
+CONFIG_SND_SOC_CS42L51_I2C=n
+CONFIG_SND_SOC_CS42L52=n
+CONFIG_SND_SOC_CS42L56=n
+CONFIG_SND_SOC_CS42L73=n
+CONFIG_SND_SOC_CS4265=n
+CONFIG_SND_SOC_CS4270=n
+CONFIG_SND_SOC_CS4271_I2C=n
+CONFIG_SND_SOC_CS4271_SPI=n
+CONFIG_SND_SOC_CS42XX8_I2C=n
+CONFIG_SND_SOC_CS43130=n
+CONFIG_SND_SOC_CS4341=n
+CONFIG_SND_SOC_CS4349=n
+CONFIG_SND_SOC_CS53L30=n
+CONFIG_SND_SOC_CX2072X=n
+CONFIG_SND_SOC_DMIC=n
+CONFIG_SND_SOC_ES7134=n
+CONFIG_SND_SOC_ES7241=n
+CONFIG_SND_SOC_ES8316=n
+CONFIG_SND_SOC_ES8328_I2C=n
+CONFIG_SND_SOC_ES8328_SPI=n
+CONFIG_SND_SOC_GTM601=n
+CONFIG_SND_SOC_INNO_RK3036=n
+CONFIG_SND_SOC_MAX98088=n
+CONFIG_SND_SOC_MAX98357A=n
+CONFIG_SND_SOC_MAX98504=n
+CONFIG_SND_SOC_MAX9867=n
+CONFIG_SND_SOC_MAX98927=n
+CONFIG_SND_SOC_MAX98373=n
+CONFIG_SND_SOC_MAX9860=n
+CONFIG_SND_SOC_MSM8916_WCD_DIGITAL=n
+CONFIG_SND_SOC_PCM1681=n
+CONFIG_SND_SOC_PCM1789_I2C=n
+CONFIG_SND_SOC_PCM179X_I2C=n
+CONFIG_SND_SOC_PCM179X_SPI=n
+CONFIG_SND_SOC_PCM186X_I2C=n
+CONFIG_SND_SOC_PCM186X_SPI=n
+CONFIG_SND_SOC_PCM3060_I2C=n
+CONFIG_SND_SOC_PCM3060_SPI=n
+CONFIG_SND_SOC_PCM3168A_I2C=n
+CONFIG_SND_SOC_PCM3168A_SPI=n
+CONFIG_SND_SOC_PCM512x_I2C=n
+CONFIG_SND_SOC_PCM512x_SPI=n
+CONFIG_SND_SOC_RK3328=n
+CONFIG_SND_SOC_RT5616=n
+CONFIG_SND_SOC_RT5631=n
+CONFIG_SND_SOC_SGTL5000=n
+CONFIG_SND_SOC_SIMPLE_AMPLIFIER=n
+CONFIG_SND_SOC_SIRF_AUDIO_CODEC=n
+CONFIG_SND_SOC_SPDIF=n
+CONFIG_SND_SOC_SSM2305=n
+CONFIG_SND_SOC_SSM2602_SPI=n
+CONFIG_SND_SOC_SSM2602_I2C=n
+CONFIG_SND_SOC_SSM4567=n
+CONFIG_SND_SOC_STA32X=n
+CONFIG_SND_SOC_STA350=n
+CONFIG_SND_SOC_STI_SAS=n
+CONFIG_SND_SOC_TAS2552=n
+CONFIG_SND_SOC_TAS5086=n
+CONFIG_SND_SOC_TAS571X=n
+CONFIG_SND_SOC_TAS5720=n
+CONFIG_SND_SOC_TAS6424=n
+CONFIG_SND_SOC_TDA7419=n
+CONFIG_SND_SOC_TFA9879=n
+CONFIG_SND_SOC_TLV320AIC23_I2C=n
+CONFIG_SND_SOC_TLV320AIC23_SPI=n
+CONFIG_SND_SOC_TLV320AIC31XX=n
+CONFIG_SND_SOC_TLV320AIC32X4_I2C=n
+CONFIG_SND_SOC_TLV320AIC32X4_SPI=n
+CONFIG_SND_SOC_TLV320AIC3X=n
+CONFIG_SND_SOC_TS3A227E=n
+CONFIG_SND_SOC_TSCS42XX=n
+CONFIG_SND_SOC_TSCS454=n
+CONFIG_SND_SOC_UDA1334=n
+CONFIG_SND_SOC_WM8510=n
+CONFIG_SND_SOC_WM8523=n
+CONFIG_SND_SOC_WM8524=n
+CONFIG_SND_SOC_WM8580=n
+CONFIG_SND_SOC_WM8711=n
+CONFIG_SND_SOC_WM8728=n
+CONFIG_SND_SOC_WM8731=n
+CONFIG_SND_SOC_WM8737=n
+CONFIG_SND_SOC_WM8741=n
+CONFIG_SND_SOC_WM8750=n
+CONFIG_SND_SOC_WM8753=n
+CONFIG_SND_SOC_WM8770=n
+CONFIG_SND_SOC_WM8776=n
+CONFIG_SND_SOC_WM8782=n
+CONFIG_SND_SOC_WM8804_I2C=n
+CONFIG_SND_SOC_WM8804_SPI=n
+CONFIG_SND_SOC_WM8903=n
+CONFIG_SND_SOC_WM8904=n
+CONFIG_SND_SOC_WM8960=n
+CONFIG_SND_SOC_WM8962=n
+CONFIG_SND_SOC_WM8974=n
+CONFIG_SND_SOC_WM8978=n
+CONFIG_SND_SOC_WM8985=n
+CONFIG_SND_SOC_ZX_AUD96P22=n
+CONFIG_SND_SOC_MAX9759=n
+CONFIG_SND_SOC_MT6351=n
+CONFIG_SND_SOC_MT6358=n
+CONFIG_SND_SOC_NAU8540=n
+CONFIG_SND_SOC_NAU8810=n
+CONFIG_SND_SOC_NAU8822=n
+CONFIG_SND_SOC_NAU8824=n
+CONFIG_SND_SOC_TPA6130A2=n
+# end of CODEC drivers
+
+CONFIG_SND_SIMPLE_CARD=n
+CONFIG_SND_AUDIO_GRAPH_CARD=n
+CONFIG_SND_XEN_FRONTEND=n
+CONFIG_HID_PRODIKEYS=n
+CONFIG_USB_CONFIGFS_F_UAC1=n
+CONFIG_USB_CONFIGFS_F_UAC1_LEGACY=n
+CONFIG_USB_CONFIGFS_F_UAC2=n
+CONFIG_USB_CONFIGFS_F_MIDI=n
diff --git a/features/xilinx/hdmi-module/hdmi-module.scc b/features/xilinx/hdmi-module/hdmi-module.scc
new file mode 100644
index 00000000..d248e936
--- /dev/null
+++ b/features/xilinx/hdmi-module/hdmi-module.scc
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Kernel Config for hdmi module "
+define KFEATURE_COMPATIBILITY board
+
+kconf hardware hdmi-module.cfg
+
diff --git a/features/xilinx/overlay_of/overlay_of.cfg b/features/xilinx/overlay_of/overlay_of.cfg
new file mode 100644
index 00000000..901d4786
--- /dev/null
+++ b/features/xilinx/overlay_of/overlay_of.cfg
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: MIT
+# Device Tree support
+CONFIG_OF_CONFIGFS=y
+CONFIG_OF_OVERLAY=y
diff --git a/features/xilinx/overlay_of/overlay_of.scc b/features/xilinx/overlay_of/overlay_of.scc
new file mode 100644
index 00000000..1e61bb37
--- /dev/null
+++ b/features/xilinx/overlay_of/overlay_of.scc
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable overlay"
+define KFEATURE_COMPATIBILITY board
+
+kconfig hardware overlay_of.cfg
diff --git a/features/xilinx/v4l2/v4l2.cfg b/features/xilinx/v4l2/v4l2.cfg
new file mode 100644
index 00000000..32a948a3
--- /dev/null
+++ b/features/xilinx/v4l2/v4l2.cfg
@@ -0,0 +1,23 @@
+# SPDX-License-Identifier: MIT
+# Media support
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+
+# V4L
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+
+# Xilinx Video drivers
+CONFIG_VIDEO_XILINX=y
+CONFIG_VIDEO_XILINX_CFA=y
+CONFIG_VIDEO_XILINX_CRESAMPLE=y
+CONFIG_VIDEO_XILINX_HLS=y
+CONFIG_VIDEO_XILINX_REMAPPER=y
+CONFIG_VIDEO_XILINX_RGB2YUV=y
+CONFIG_VIDEO_XILINX_SCALER=y
+CONFIG_VIDEO_XILINX_SWITCH=y
+CONFIG_VIDEO_XILINX_TPG=y
+CONFIG_VIDEO_XILINX_VTC=y
+
diff --git a/features/xilinx/v4l2/v4l2.scc b/features/xilinx/v4l2/v4l2.scc
new file mode 100644
index 00000000..bd1201e8
--- /dev/null
+++ b/features/xilinx/v4l2/v4l2.scc
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Enable Xilinx V4L2 support"
+define KFEATURE_COMPATIBILITY board
+
+kconfig hardware v4l2.cfg
diff --git a/features/yaffs2/0001-yaffs2-convert-read_page-readfolio.patch b/features/yaffs2/0001-yaffs2-convert-read_page-readfolio.patch
new file mode 100644
index 00000000..78a5c311
--- /dev/null
+++ b/features/yaffs2/0001-yaffs2-convert-read_page-readfolio.patch
@@ -0,0 +1,76 @@
+From a10fa57649a96e7cd87ec4b93badc2b441b06ec5 Mon Sep 17 00:00:00 2001
+From: Bruce Ashfield <bruce.ashfield@gmail.com>
+Date: Wed, 29 Jun 2022 10:51:56 -0400
+Subject: [PATCH] yaffs2: convert read_page -> readfolio
+
+This is a first pass of changing yaffs2 to use the new read_folio,
+versus readpage routines. We also adjust writepage to no longer use
+flags, which have been dropped in 5.19+
+
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/yaffs2/yaffs_vfs.c | 21 +++++++++++++++------
+ 1 file changed, 15 insertions(+), 6 deletions(-)
+
+diff --git a/fs/yaffs2/yaffs_vfs.c b/fs/yaffs2/yaffs_vfs.c
+index 8ceb66c0d070..52f2d13c7126 100644
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -367,13 +367,13 @@ static int yaffs_readpage_unlock(struct file *f, struct page *pg)
+ return ret;
+ }
+
+-static int yaffs_readpage(struct file *f, struct page *pg)
++static int yaffs_read_folio(struct file *f, struct folio *folio)
+ {
+ int ret;
+
+- yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage");
+- ret = yaffs_readpage_unlock(f, pg);
+- yaffs_trace(YAFFS_TRACE_OS, "yaffs_readpage done");
++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_read_folio");
++ ret = yaffs_readpage_unlock(f, &folio->page);
++ yaffs_trace(YAFFS_TRACE_OS, "yaffs_read_folio done");
+ return ret;
+ }
+
+@@ -548,9 +548,16 @@ static void yaffs_release_space(struct file *f)
+ }
+
+ #if (YAFFS_USE_WRITE_BEGIN_END > 0)
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0)
++static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
++ loff_t pos, unsigned len,
++ struct page **pagep, void **fsdata)
++#else
+ static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
++#endif
+ {
+ struct page *pg = NULL;
+ pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+@@ -559,7 +566,9 @@ static int yaffs_write_begin(struct file *filp, struct address_space *mapping,
+ int space_held = 0;
+
+ /* Get a page */
+-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 19, 0)
++ pg = grab_cache_page_write_begin(mapping, index);
++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
+ pg = grab_cache_page_write_begin(mapping, index, flags);
+ #else
+ pg = __grab_cache_page(mapping, index);
+@@ -748,7 +757,7 @@ static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,
+ #endif
+
+ static struct address_space_operations yaffs_file_address_operations = {
+- .readpage = yaffs_readpage,
++ .read_folio = yaffs_read_folio,
+ .writepage = yaffs_writepage,
+ #if (YAFFS_USE_WRITE_BEGIN_END > 0)
+ .write_begin = yaffs_write_begin,
+--
+2.19.1
+
diff --git a/features/yaffs2/0001-yaffs2-replace-bdevname-call-with-sprintf.patch b/features/yaffs2/0001-yaffs2-replace-bdevname-call-with-sprintf.patch
new file mode 100644
index 00000000..b3c829ab
--- /dev/null
+++ b/features/yaffs2/0001-yaffs2-replace-bdevname-call-with-sprintf.patch
@@ -0,0 +1,34 @@
+From ae1445c1cc1cec47fa51f7831cd9110ecd5b2a55 Mon Sep 17 00:00:00 2001
+From: Bruce Ashfield <bruce.ashfield@gmail.com>
+Date: Mon, 3 Oct 2022 15:16:27 -0400
+Subject: [PATCH] yaffs2: replace bdevname call with sprintf
+
+commit 900d156bac2bc474cf7c7bee4efbc6c83ec5ae58 [block: remove bdevname]
+removed this function, we follow the pattern and use sprintf as a
+replacement.
+
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/yaffs2/yaffs_vfs.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/fs/yaffs2/yaffs_vfs.c b/fs/yaffs2/yaffs_vfs.c
+index 52f2d13c7126..140f7aa7a1a1 100644
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -117,7 +117,11 @@
+ #define Page_Uptodate(page) test_bit(PG_uptodate, &(page)->flags)
+
+ /* FIXME: use sb->s_id instead ? */
+-#define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf)
++//#define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf)
++static inline char* yaffs_devname(struct super_block *sb, char *buf) {
++ snprintf(buf, sizeof(buf), "%pg", sb->s_bdev);
++ return buf;
++}
+
+ #else
+
+--
+2.19.1
+
diff --git a/features/yaffs2/0001-yaffs2-update-VFS-ctime-operations-to-6.6.patch b/features/yaffs2/0001-yaffs2-update-VFS-ctime-operations-to-6.6.patch
new file mode 100644
index 00000000..9ea1aa07
--- /dev/null
+++ b/features/yaffs2/0001-yaffs2-update-VFS-ctime-operations-to-6.6.patch
@@ -0,0 +1,64 @@
+From 70f40841c195a81a8ef8290862adeb86fe264b24 Mon Sep 17 00:00:00 2001
+From: Bruce Ashfield <bruce.ashfield@gmail.com>
+Date: Thu, 21 Sep 2023 17:04:31 -0400
+Subject: [PATCH] yaffs2: update VFS ctime operations to 6.6+
+
+In 6.6+ kernels the inode ctime is hidden, and should only
+be accessed through accesor routines. We convert one of our
+calls to the accesor, but the other, we use the new "hidden"
+__ctime.
+
+We also convert the interator to use the shared iterator and
+iterator wrap routines.
+
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/yaffs2/yaffs_vfs.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/fs/yaffs2/yaffs_vfs.c b/fs/yaffs2/yaffs_vfs.c
+index 04abeee99ff5..8a9738de8906 100644
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -282,7 +282,7 @@ MODULE_PARM(yaffs_gc_control, "i");
+ } while (0)
+ #else
+ #define update_dir_time(dir) do {\
+- (dir)->i_ctime = (dir)->i_mtime = current_time(dir); \
++ (dir)->i_mtime = inode_set_ctime_to_ts( dir, current_time(dir) ); \
+ } while (0)
+ #endif
+
+@@ -1901,7 +1901,7 @@ static int yaffs_iterate(struct file *f, struct dir_context *dc)
+
+ return ret_val;
+ }
+-
++WRAP_DIR_ITER(yaffs_iterate)
+ #else
+
+ static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
+@@ -2018,7 +2018,7 @@ static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
+ static const struct file_operations yaffs_dir_operations = {
+ .read = generic_read_dir,
+ #ifdef YAFFS_USE_DIR_ITERATE
+- .iterate = yaffs_iterate,
++ .iterate_shared = shared_yaffs_iterate,
+ #else
+ .readdir = yaffs_readdir,
+ #endif
+@@ -2079,8 +2079,9 @@ static void yaffs_fill_inode_from_obj(struct inode *inode,
+ inode->i_atime.tv_nsec = 0;
+ inode->i_mtime.tv_sec = (time64_t) obj->yst_mtime;
+ inode->i_mtime.tv_nsec = 0;
+- inode->i_ctime.tv_sec = (time64_t) obj->yst_ctime;
+- inode->i_ctime.tv_nsec = 0;
++ //inode->i_ctime.tv_sec = (time64_t) obj->yst_ctime;
++ inode->__i_ctime.tv_sec = (time64_t) obj->yst_ctime;
++ inode->__i_ctime.tv_nsec = 0;
+ #else
+ inode->i_rdev = obj->yst_rdev;
+ inode->i_atime = obj->yst_atime;
+--
+2.34.1
+
diff --git a/features/yaffs2/0001-yaffs2-v5.12-build-fixups-not-runtime-tested.patch b/features/yaffs2/0001-yaffs2-v5.12-build-fixups-not-runtime-tested.patch
new file mode 100644
index 00000000..13bbba8a
--- /dev/null
+++ b/features/yaffs2/0001-yaffs2-v5.12-build-fixups-not-runtime-tested.patch
@@ -0,0 +1,105 @@
+From d16f6eab238d58479a7140507a2eb32573c1a106 Mon Sep 17 00:00:00 2001
+From: Bruce Ashfield <bruce.ashfield@gmail.com>
+Date: Fri, 19 Mar 2021 12:13:36 -0400
+Subject: [PATCH] yaffs2: v5.12+ build fixups (not runtime tested)
+
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/yaffs2/yaffs_vfs.c | 21 +++++++++++----------
+ 1 file changed, 11 insertions(+), 10 deletions(-)
+
+diff --git a/fs/yaffs2/yaffs_vfs.c b/fs/yaffs2/yaffs_vfs.c
+index a9cf8edc2245..ee9d6955ed79 100644
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -897,7 +897,7 @@ static int yaffs_vfs_setsize(struct inode *inode, loff_t newsize)
+ static int yaffs_vfs_setattr(struct inode *inode, struct iattr *attr)
+ {
+ #ifdef YAFFS_USE_SETATTR_COPY
+- setattr_copy(inode, attr);
++ setattr_copy(&init_user_ns,inode, attr);
+ return 0;
+ #else
+ return inode_setattr(inode, attr);
+@@ -905,7 +905,7 @@ static int yaffs_vfs_setattr(struct inode *inode, struct iattr *attr)
+
+ }
+
+-static int yaffs_setattr(struct dentry *dentry, struct iattr *attr)
++static int yaffs_setattr(struct user_namespace *ns, struct dentry *dentry, struct iattr *attr)
+ {
+ struct inode *inode = dentry->d_inode;
+ int error = 0;
+@@ -921,7 +921,7 @@ static int yaffs_setattr(struct dentry *dentry, struct iattr *attr)
+ #endif
+
+ if (error == 0)
+- error = setattr_prepare(dentry, attr);
++ error = setattr_prepare(&init_user_ns,dentry, attr);
+ if (error == 0) {
+ int result;
+ if (!error) {
+@@ -1339,7 +1339,7 @@ struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
+
+
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+-static int yaffs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
++static int yaffs_mknod(struct user_namespace *ns, struct inode *dir, struct dentry *dentry, umode_t mode,
+ dev_t rdev)
+ #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
+@@ -1433,20 +1433,20 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
+ }
+
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+-static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
++static int yaffs_mkdir(struct user_namespace *ns, struct inode *dir, struct dentry *dentry, umode_t mode)
+ #else
+ static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+ #endif
+ {
+ int ret_val;
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_mkdir");
+- ret_val = yaffs_mknod(dir, dentry, mode | S_IFDIR, 0);
++ ret_val = yaffs_mknod(ns, dir, dentry, mode | S_IFDIR, 0);
+ return ret_val;
+ }
+
+
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+-static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
++static int yaffs_create(struct user_namespace *ns, struct inode *dir, struct dentry *dentry, umode_t mode,
+ bool dummy)
+ #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+ static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+@@ -1459,7 +1459,7 @@ static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode)
+ #endif
+ {
+ yaffs_trace(YAFFS_TRACE_OS, "yaffs_create");
+- return yaffs_mknod(dir, dentry, mode | S_IFREG, 0);
++ return yaffs_mknod(ns, dir, dentry, mode | S_IFREG, 0);
+ }
+
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+@@ -1551,7 +1551,8 @@ static int yaffs_link(struct dentry *old_dentry, struct inode *dir,
+ return -EPERM;
+ }
+
+-static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
++static int yaffs_symlink(struct user_namespace *ns,
++ struct inode *dir, struct dentry *dentry,
+ const char *symname)
+ {
+ struct yaffs_obj *obj;
+@@ -1597,7 +1598,7 @@ static int yaffs_symlink(struct inode *dir, struct dentry *dentry,
+ * NB: POSIX says you can rename an object over an old object of the same name
+ */
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
+-static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,
++static int yaffs_rename(struct user_namespace *ns, struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry, unsigned int unused)
+ #else
+ static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,
+--
+2.19.1
+
diff --git a/features/yaffs2/yaffs-fix-Wstringop-overread-compile-warning-in-yaff.patch b/features/yaffs2/yaffs-fix-Wstringop-overread-compile-warning-in-yaff.patch
new file mode 100644
index 00000000..7a47c4a5
--- /dev/null
+++ b/features/yaffs2/yaffs-fix-Wstringop-overread-compile-warning-in-yaff.patch
@@ -0,0 +1,44 @@
+From ea777841e8ea883bfa160693e650882f86e75167 Mon Sep 17 00:00:00 2001
+From: Quanyang Wang <quanyang.wang@windriver.com>
+Date: Sun, 13 Jun 2021 12:08:21 +0800
+Subject: [PATCH] yaffs: fix -Wstringop-overread compile warning in
+ yaffs_fix_null_name
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+In yaffs_fix_null_name, "if (strnlen(name, YAFFS_MAX_NAME_LENGTH) == 0)"
+is used to judge if the "name" string is zero length. But this is wrong
+when the "name" char array size is less than YAFFS_MAX_NAME_LENGTH and
+this will trigger compile warnig as below:
+
+fs/yaffs2/yaffs_guts.c:4501:13: warning: ‘strnlen’ specified bound 255 exceeds source size 16 [-Wstringop-overread]
+ 4501 | if (strnlen(name, YAFFS_MAX_NAME_LENGTH) == 0) {
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Let's use buffer_size to do this instead of YAFFS_MAX_NAME_LENGTH
+because buffer_size is passed to yaffs_fix_null_name by caller with
+appropriate value which is fixed to the size of "name" char array.
+
+Signed-off-by: Quanyang Wang <quanyang.wang@windriver.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/yaffs2/yaffs_guts.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/yaffs2/yaffs_guts.c b/fs/yaffs2/yaffs_guts.c
+index 40a5b46cf6ca..0cc794ebc347 100644
+--- a/fs/yaffs2/yaffs_guts.c
++++ b/fs/yaffs2/yaffs_guts.c
+@@ -4498,7 +4498,7 @@ static void yaffs_fix_null_name(struct yaffs_obj *obj, YCHAR *name,
+ int buffer_size)
+ {
+ /* Create an object name if we could not find one. */
+- if (strnlen(name, YAFFS_MAX_NAME_LENGTH) == 0) {
++ if (strnlen(name, buffer_size) == 0) {
+ YCHAR local_name[20];
+ YCHAR num_string[20];
+ YCHAR *x = &num_string[19];
+--
+2.19.1
+
diff --git a/features/yaffs2/yaffs-fix-misplaced-variable-declaration.patch b/features/yaffs2/yaffs-fix-misplaced-variable-declaration.patch
new file mode 100644
index 00000000..b7da6b82
--- /dev/null
+++ b/features/yaffs2/yaffs-fix-misplaced-variable-declaration.patch
@@ -0,0 +1,40 @@
+From f28b801ca5c4853b60f16eaf5525b05b5174ab43 Mon Sep 17 00:00:00 2001
+From: Paul Gortmaker <paul.gortmaker@windriver.com>
+Date: Thu, 30 Apr 2020 12:59:46 -0400
+Subject: [PATCH] yaffs: fix misplaced variable declaration
+
+A variable declaration landed one function higher than intended,
+leading to an unused variable warning for configurations with
+YAFFS_USE_DIR_ITERATE=y and a build failure for configurations
+with the same being unset.
+
+Fixes: "yaffs: Fix build failure by handling inode i_version with proper atomic API"
+Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/yaffs2/yaffs_vfs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/yaffs2/yaffs_vfs.c b/fs/yaffs2/yaffs_vfs.c
+index 598ecd57a0ed..3ffdc0129637 100644
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -1826,7 +1826,6 @@ static int yaffs_iterate(struct file *f, struct dir_context *dc)
+ int ret_val = 0;
+
+ char name[YAFFS_MAX_NAME_LENGTH + 1];
+- u64 i_version;
+
+ obj = yaffs_dentry_to_obj(Y_GET_DENTRY(f));
+ dev = obj->my_dev;
+@@ -1898,6 +1897,7 @@ static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir)
+ unsigned long offset, curoffs;
+ struct yaffs_obj *l;
+ int ret_val = 0;
++ u64 i_version;
+
+ char name[YAFFS_MAX_NAME_LENGTH + 1];
+
+--
+2.19.1
+
diff --git a/features/yaffs2/yaffs-fix-mtime-itime-field-access.patch b/features/yaffs2/yaffs-fix-mtime-itime-field-access.patch
new file mode 100644
index 00000000..482312a0
--- /dev/null
+++ b/features/yaffs2/yaffs-fix-mtime-itime-field-access.patch
@@ -0,0 +1,65 @@
+From 7614fa80bc6abefd1450b5c4c3839386ac2b92cc Mon Sep 17 00:00:00 2001
+From: Bruce Ashfield <bruce.ashfield@gmail.com>
+Date: Wed, 22 Nov 2023 12:04:28 -0500
+Subject: [PATCH] yaffs: fix mtime/itime field access
+
+Adapting our inode field access to the following upstream
+commit:
+
+ commit 12cd44023651666bd44baa36a5c999698890debb
+ Author: Jeff Layton <jlayton@kernel.org>
+ Date: Fri Sep 29 09:05:52 2023 -0400
+
+ fs: rename inode i_atime and i_mtime fields
+
+ Rename these two fields to discourage direct access (and to help ensure
+ that we mop up any leftover direct accesses).
+
+ Signed-off-by: Jeff Layton <jlayton@kernel.org>
+ Signed-off-by: Christian Brauner <brauner@kernel.org>
+
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/yaffs2/yaffs_vfs.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/fs/yaffs2/yaffs_vfs.c b/fs/yaffs2/yaffs_vfs.c
+index 8a9738de8906..ec4016cfeedf 100644
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -282,7 +282,7 @@ MODULE_PARM(yaffs_gc_control, "i");
+ } while (0)
+ #else
+ #define update_dir_time(dir) do {\
+- (dir)->i_mtime = inode_set_ctime_to_ts( dir, current_time(dir) ); \
++ (dir)->__i_mtime = inode_set_ctime_to_ts( dir, current_time(dir) ); \
+ } while (0)
+ #endif
+
+@@ -2075,17 +2075,17 @@ static void yaffs_fill_inode_from_obj(struct inode *inode,
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+
+ inode->i_rdev = old_decode_dev(obj->yst_rdev);
+- inode->i_atime.tv_sec = (time64_t) (obj->yst_atime);
+- inode->i_atime.tv_nsec = 0;
+- inode->i_mtime.tv_sec = (time64_t) obj->yst_mtime;
+- inode->i_mtime.tv_nsec = 0;
++ inode->__i_atime.tv_sec = (time64_t) (obj->yst_atime);
++ inode->__i_atime.tv_nsec = 0;
++ inode->__i_mtime.tv_sec = (time64_t) obj->yst_mtime;
++ inode->__i_mtime.tv_nsec = 0;
+ //inode->i_ctime.tv_sec = (time64_t) obj->yst_ctime;
+ inode->__i_ctime.tv_sec = (time64_t) obj->yst_ctime;
+ inode->__i_ctime.tv_nsec = 0;
+ #else
+ inode->i_rdev = obj->yst_rdev;
+- inode->i_atime = obj->yst_atime;
+- inode->i_mtime = obj->yst_mtime;
++ inode->__i_atime = obj->yst_atime;
++ inode->__i_mtime = obj->yst_mtime;
+ inode->i_ctime = obj->yst_ctime;
+ #endif
+ inode->i_size = yaffs_get_obj_length(obj);
+--
+2.34.1
+
diff --git a/features/yaffs2/yaffs-include-blkdev.h.patch b/features/yaffs2/yaffs-include-blkdev.h.patch
new file mode 100644
index 00000000..e75911de
--- /dev/null
+++ b/features/yaffs2/yaffs-include-blkdev.h.patch
@@ -0,0 +1,28 @@
+From a07a378f2bbfc640c6b76abfa3ef2a32a86cbfa2 Mon Sep 17 00:00:00 2001
+From: Bruce Ashfield <bruce.ashfield@gmail.com>
+Date: Sat, 29 Aug 2020 10:25:04 -0400
+Subject: [PATCH] yaffs: include blkdev.h
+
+The definition of BDEVNAME_SIZE has moved, so we add the new .h
+
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/yaffs2/yaffs_vfs.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/fs/yaffs2/yaffs_vfs.c b/fs/yaffs2/yaffs_vfs.c
+index 3ffdc0129637..a9cf8edc2245 100644
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -74,6 +74,8 @@
+ #include <linux/config.h>
+ #endif
+
++#include <linux/blkdev.h>
++
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
+--
+2.19.1
+
diff --git a/features/yaffs2/yaffs-replace-IS_ERR-with-IS_ERR_OR_NULL-to-check-bo.patch b/features/yaffs2/yaffs-replace-IS_ERR-with-IS_ERR_OR_NULL-to-check-bo.patch
new file mode 100644
index 00000000..4956ff5e
--- /dev/null
+++ b/features/yaffs2/yaffs-replace-IS_ERR-with-IS_ERR_OR_NULL-to-check-bo.patch
@@ -0,0 +1,49 @@
+From f3ffb6a61225aa0a89d0edfeb7cdd99b9963faa0 Mon Sep 17 00:00:00 2001
+From: Meng Li <Meng.Li@windriver.com>
+Date: Thu, 21 Oct 2021 09:27:20 +0800
+Subject: [PATCH] yaffs: replace IS_ERR with IS_ERR_OR_NULL to check both ERR
+ and NULL
+
+When run below command to mount a yaffs2 FS to nor flash, there
+is kernel panic as below:
+Unable to handle kernel NULL pointer dereference at virtual address 0000000000000020
+......
+Internal error: Oops: 96000004 [#1] PREEMPT SMP
+Modules linked in:
+CPU: 1 PID: 335 Comm: mount Not tainted 5.10.73-yocto-standard #1
+......
+Call trace:
+ yaffs_internal_read_super.constprop.0+0x24c/0x6fc
+ yaffs2_internal_read_super_mtd+0x28/0x40
+ mount_bdev+0x1cc/0x200
+ ......
+ el0_sync_handler+0x1a4/0x1b0
+ el0_sync+0x180/0x1c0
+Because in function yaffs_get_mtd_device(), it check the type of
+mtd device. If it is not NAND flash, NULL will be returned. This
+causes kernel panic if the ret value is not checked whether it
+is NULL or not. So, replace IS_ERR with IS_ERR_OR_NULL to check
+both ERR and NULL.
+
+Signed-off-by: Meng Li <Meng.Li@windriver.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/yaffs2/yaffs_vfs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/yaffs2/yaffs_vfs.c b/fs/yaffs2/yaffs_vfs.c
+index ee9d6955ed79..8ceb66c0d070 100644
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -2965,7 +2965,7 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
+
+
+ mtd = yaffs_get_mtd_device(sb->s_dev);
+- if (IS_ERR(mtd)) {
++ if (IS_ERR_OR_NULL(mtd)) {
+ return NULL;
+ }
+
+--
+2.19.1
+
diff --git a/features/yaffs2/yaffs2-Fix-miscalculation-of-devname-buffer-length.patch b/features/yaffs2/yaffs2-Fix-miscalculation-of-devname-buffer-length.patch
new file mode 100644
index 00000000..79deb483
--- /dev/null
+++ b/features/yaffs2/yaffs2-Fix-miscalculation-of-devname-buffer-length.patch
@@ -0,0 +1,65 @@
+From dded404c66bb87f08216afd1e3c9d84359e80012 Mon Sep 17 00:00:00 2001
+From: He Zhe <zhe.he@windriver.com>
+Date: Wed, 31 May 2023 14:01:07 +0800
+Subject: [PATCH] yaffs2: Fix miscalculation of devname buffer length
+
+The following build warning helps us find a real mishandling of array length.
+
+fs/yaffs2/yaffs_vfs.c:122:29: warning: argument to 'sizeof' in 'snprintf' call
+is the same expression as the destination; did you mean to provide an explicit
+length? [-Wsizeof-pointer-memaccess]
+
+If an array is passed as a function parameter it'll be treated as a simple
+pointer and thus sizeof will return the length of a pointer rather than the
+length of the array.
+
+Add and pass the buffer length to make it work correctly.
+
+Signed-off-by: He Zhe <zhe.he@windriver.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/yaffs2/yaffs_vfs.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/fs/yaffs2/yaffs_vfs.c b/fs/yaffs2/yaffs_vfs.c
+index 140f7aa7a1a1..e9e29a41a680 100644
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -118,8 +118,8 @@
+
+ /* FIXME: use sb->s_id instead ? */
+ //#define yaffs_devname(sb, buf) bdevname(sb->s_bdev, buf)
+-static inline char* yaffs_devname(struct super_block *sb, char *buf) {
+- snprintf(buf, sizeof(buf), "%pg", sb->s_bdev);
++static inline char* yaffs_devname(struct super_block *sb, char *buf, unsigned long len) {
++ snprintf(buf, len, "%pg", sb->s_bdev);
+ return buf;
+ }
+
+@@ -2944,12 +2944,12 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
+
+ if (!sb->s_dev)
+ printk(KERN_INFO "yaffs: sb->s_dev is NULL\n");
+- else if (!yaffs_devname(sb, devname_buf))
++ else if (!yaffs_devname(sb, devname_buf, sizeof(devname_buf)))
+ printk(KERN_INFO "yaffs: devname is NULL\n");
+ else
+ printk(KERN_INFO "yaffs: dev is %d name is \"%s\" %s\n",
+ sb->s_dev,
+- yaffs_devname(sb, devname_buf), read_only ? "ro" : "rw");
++ yaffs_devname(sb, devname_buf, sizeof(devname_buf)), read_only ? "ro" : "rw");
+
+ if (!data_str)
+ data_str = "";
+@@ -2974,7 +2974,7 @@ static struct super_block *yaffs_internal_read_super(int yaffs_version,
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "yaffs: Attempting MTD mount of %u.%u,\"%s\"",
+ MAJOR(sb->s_dev), MINOR(sb->s_dev),
+- yaffs_devname(sb, devname_buf));
++ yaffs_devname(sb, devname_buf, sizeof(devname_buf)));
+
+
+ mtd = yaffs_get_mtd_device(sb->s_dev);
+--
+2.34.1
+
diff --git a/features/yaffs2/yaffs2-convert-user_namespace-to-mnt_idmap.patch b/features/yaffs2/yaffs2-convert-user_namespace-to-mnt_idmap.patch
new file mode 100644
index 00000000..1a67540b
--- /dev/null
+++ b/features/yaffs2/yaffs2-convert-user_namespace-to-mnt_idmap.patch
@@ -0,0 +1,96 @@
+From 5440769b1bbff51e64557c2a981a6cdfece8adec Mon Sep 17 00:00:00 2001
+From: Bruce Ashfield <bruce.ashfield@gmail.com>
+Date: Fri, 17 Mar 2023 22:31:42 -0400
+Subject: [PATCH] yaffs2: convert user_namespace to mnt_idmap
+
+commit c1632a0f11209338fc300c66252bcc4686e609e8 [fs: port ->setattr() to
+pass mnt_idmap] changes the parameters to attr operations to a
+mnt_idmap.
+
+yaffs2 isn't using the user namespace directly, so we switch to the
+default map.
+
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/yaffs2/yaffs_vfs.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/fs/yaffs2/yaffs_vfs.c b/fs/yaffs2/yaffs_vfs.c
+index 140f7aa7a1a1..3844d542608e 100644
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -910,7 +910,7 @@ static int yaffs_vfs_setsize(struct inode *inode, loff_t newsize)
+ static int yaffs_vfs_setattr(struct inode *inode, struct iattr *attr)
+ {
+ #ifdef YAFFS_USE_SETATTR_COPY
+- setattr_copy(&init_user_ns,inode, attr);
++ setattr_copy(&nop_mnt_idmap,inode, attr);
+ return 0;
+ #else
+ return inode_setattr(inode, attr);
+@@ -918,7 +918,7 @@ static int yaffs_vfs_setattr(struct inode *inode, struct iattr *attr)
+
+ }
+
+-static int yaffs_setattr(struct user_namespace *ns, struct dentry *dentry, struct iattr *attr)
++static int yaffs_setattr(struct mnt_idmap *ns, struct dentry *dentry, struct iattr *attr)
+ {
+ struct inode *inode = dentry->d_inode;
+ int error = 0;
+@@ -934,7 +934,7 @@ static int yaffs_setattr(struct user_namespace *ns, struct dentry *dentry, struc
+ #endif
+
+ if (error == 0)
+- error = setattr_prepare(&init_user_ns,dentry, attr);
++ error = setattr_prepare(&nop_mnt_idmap,dentry, attr);
+ if (error == 0) {
+ int result;
+ if (!error) {
+@@ -1352,7 +1352,7 @@ struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,
+
+
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+-static int yaffs_mknod(struct user_namespace *ns, struct inode *dir, struct dentry *dentry, umode_t mode,
++static int yaffs_mknod(struct mnt_idmap *ns, struct inode *dir, struct dentry *dentry, umode_t mode,
+ dev_t rdev)
+ #elif (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
+@@ -1446,7 +1446,7 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,
+ }
+
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+-static int yaffs_mkdir(struct user_namespace *ns, struct inode *dir, struct dentry *dentry, umode_t mode)
++static int yaffs_mkdir(struct mnt_idmap *ns, struct inode *dir, struct dentry *dentry, umode_t mode)
+ #else
+ static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+ #endif
+@@ -1459,7 +1459,7 @@ static int yaffs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+
+
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+-static int yaffs_create(struct user_namespace *ns, struct inode *dir, struct dentry *dentry, umode_t mode,
++static int yaffs_create(struct mnt_idmap *ns, struct inode *dir, struct dentry *dentry, umode_t mode,
+ bool dummy)
+ #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+ static int yaffs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+@@ -1564,7 +1564,7 @@ static int yaffs_link(struct dentry *old_dentry, struct inode *dir,
+ return -EPERM;
+ }
+
+-static int yaffs_symlink(struct user_namespace *ns,
++static int yaffs_symlink(struct mnt_idmap *ns,
+ struct inode *dir, struct dentry *dentry,
+ const char *symname)
+ {
+@@ -1611,7 +1611,7 @@ static int yaffs_symlink(struct user_namespace *ns,
+ * NB: POSIX says you can rename an object over an old object of the same name
+ */
+ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
+-static int yaffs_rename(struct user_namespace *ns, struct inode *old_dir, struct dentry *old_dentry,
++static int yaffs_rename(struct mnt_idmap *ns, struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry, unsigned int unused)
+ #else
+ static int yaffs_rename(struct inode *old_dir, struct dentry *old_dentry,
+--
+2.34.1
+
diff --git a/features/yaffs2/yaffs2-fix-memory-leak-when-proc-yaffs-is-read.patch b/features/yaffs2/yaffs2-fix-memory-leak-when-proc-yaffs-is-read.patch
new file mode 100644
index 00000000..23c0ee48
--- /dev/null
+++ b/features/yaffs2/yaffs2-fix-memory-leak-when-proc-yaffs-is-read.patch
@@ -0,0 +1,38 @@
+From e64f1a1d9447f4def5e36c9278b433b19eec1798 Mon Sep 17 00:00:00 2001
+From: Charles Manning <cdhmanning@gmail.com>
+Date: Mon, 16 Mar 2020 16:52:51 +0800
+Subject: [PATCH] yaffs2: fix memory leak when /proc/yaffs is read
+
+commit 27f18203551940abf35826a66978daf1b8124c6b from
+git://www.aleph1.co.uk/yaffs2
+
+Thanks to Jisheng Zhang <Jisheng.Zhang@synaptics.com> for supplying this patch
+
+There is a kernel memory leak observed when the proc file /proc/yaffs
+is read. This reason is that in yaffs_proc_open, single_open is called
+and the respective release function is not called during release.
+
+Fix with correct release function - single_release().
+
+Signed-off-by: Jisheng Zhang <Jisheng.Zhang@synaptics.com>
+Signed-off-by: Quanyang Wang <quanyang.wang@windriver.com>
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/yaffs2/yaffs_vfs.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/yaffs2/yaffs_vfs.c b/fs/yaffs2/yaffs_vfs.c
+index d3f89e07401b..4fbd0a42ff3d 100644
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -3697,6 +3697,7 @@ static struct file_operations procfs_ops = {
+ .open = yaffs_proc_open,
+ .read = seq_read,
+ .write = yaffs_proc_write,
++ .release = single_release,
+ };
+
+ static int yaffs_procfs_init(void)
+--
+2.19.1
+
diff --git a/features/yaffs2/yaffs2-import-git-revision-b4ce1bb-jan-2020.patch b/features/yaffs2/yaffs2-import-git-revision-b4ce1bb-jan-2020.patch
index 53673b8a..ef8109c8 100644
--- a/features/yaffs2/yaffs2-import-git-revision-b4ce1bb-jan-2020.patch
+++ b/features/yaffs2/yaffs2-import-git-revision-b4ce1bb-jan-2020.patch
@@ -1,4 +1,4 @@
-From 8c6f9b2baa402d8c9269fc08ccb26c1126e28f62 Mon Sep 17 00:00:00 2001
+From 5fd0c1a67df759fe4d214f645c6bbdfb72e95518 Mon Sep 17 00:00:00 2001
From: Bruce Ashfield <bruce.ashfield@gmail.com>
Date: Mon, 13 Jan 2020 12:19:30 -0500
Subject: [PATCH] yaffs2: import git revision b4ce1bb (jan, 2020)
@@ -6,9 +6,7 @@ Subject: [PATCH] yaffs2: import git revision b4ce1bb (jan, 2020)
Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
---
fs/Kconfig | 1 +
- fs/Kconfig.pre.yaffs | 325 ++
fs/Makefile | 1 +
- fs/Makefile.pre.yaffs | 134 +
fs/yaffs2/Kconfig | 171 ++
fs/yaffs2/Makefile | 19 +
fs/yaffs2/yaffs_allocator.c | 356 +++
@@ -52,9 +50,7 @@ Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
fs/yaffs2/yaffs_yaffs2.c | 1711 +++++++++++
fs/yaffs2/yaffs_yaffs2.h | 38 +
fs/yaffs2/yportenv.h | 92 +
- 47 files changed, 17522 insertions(+)
- create mode 100644 fs/Kconfig.pre.yaffs
- create mode 100644 fs/Makefile.pre.yaffs
+ 45 files changed, 17063 insertions(+)
create mode 100644 fs/yaffs2/Kconfig
create mode 100644 fs/yaffs2/Makefile
create mode 100644 fs/yaffs2/yaffs_allocator.c
@@ -100,10 +96,10 @@ Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
create mode 100644 fs/yaffs2/yportenv.h
diff --git a/fs/Kconfig b/fs/Kconfig
-index 2501e6f1f965..9bdef69b0358 100644
+index 708ba336e689..fe77c48345ac 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
-@@ -248,6 +248,7 @@ source "fs/hfsplus/Kconfig"
+@@ -249,6 +249,7 @@ source "fs/hfsplus/Kconfig"
source "fs/befs/Kconfig"
source "fs/bfs/Kconfig"
source "fs/efs/Kconfig"
@@ -111,486 +107,15 @@ index 2501e6f1f965..9bdef69b0358 100644
source "fs/jffs2/Kconfig"
# UBIFS File system configuration
source "fs/ubifs/Kconfig"
-diff --git a/fs/Kconfig.pre.yaffs b/fs/Kconfig.pre.yaffs
-new file mode 100644
-index 000000000000..2501e6f1f965
---- /dev/null
-+++ b/fs/Kconfig.pre.yaffs
-@@ -0,0 +1,325 @@
-+# SPDX-License-Identifier: GPL-2.0-only
-+#
-+# File system configuration
-+#
-+
-+menu "File systems"
-+
-+# Use unaligned word dcache accesses
-+config DCACHE_WORD_ACCESS
-+ bool
-+
-+config VALIDATE_FS_PARSER
-+ bool "Validate filesystem parameter description"
-+ help
-+ Enable this to perform validation of the parameter description for a
-+ filesystem when it is registered.
-+
-+if BLOCK
-+
-+config FS_IOMAP
-+ bool
-+
-+source "fs/ext2/Kconfig"
-+source "fs/ext4/Kconfig"
-+source "fs/jbd2/Kconfig"
-+
-+config FS_MBCACHE
-+# Meta block cache for Extended Attributes (ext2/ext3/ext4)
-+ tristate
-+ default y if EXT2_FS=y && EXT2_FS_XATTR
-+ default y if EXT4_FS=y
-+ default m if EXT2_FS_XATTR || EXT4_FS
-+
-+source "fs/reiserfs/Kconfig"
-+source "fs/jfs/Kconfig"
-+
-+source "fs/xfs/Kconfig"
-+source "fs/gfs2/Kconfig"
-+source "fs/ocfs2/Kconfig"
-+source "fs/btrfs/Kconfig"
-+source "fs/nilfs2/Kconfig"
-+source "fs/f2fs/Kconfig"
-+
-+config FS_DAX
-+ bool "Direct Access (DAX) support"
-+ depends on MMU
-+ depends on !(ARM || MIPS || SPARC)
-+ select DEV_PAGEMAP_OPS if (ZONE_DEVICE && !FS_DAX_LIMITED)
-+ select FS_IOMAP
-+ select DAX
-+ help
-+ Direct Access (DAX) can be used on memory-backed block devices.
-+ If the block device supports DAX and the filesystem supports DAX,
-+ then you can avoid using the pagecache to buffer I/Os. Turning
-+ on this option will compile in support for DAX; you will need to
-+ mount the filesystem using the -o dax option.
-+
-+ If you do not have a block device that is capable of using this,
-+ or if unsure, say N. Saying Y will increase the size of the kernel
-+ by about 5kB.
-+
-+config FS_DAX_PMD
-+ bool
-+ default FS_DAX
-+ depends on FS_DAX
-+ depends on ZONE_DEVICE
-+ depends on TRANSPARENT_HUGEPAGE
-+
-+# Selected by DAX drivers that do not expect filesystem DAX to support
-+# get_user_pages() of DAX mappings. I.e. "limited" indicates no support
-+# for fork() of processes with MAP_SHARED mappings or support for
-+# direct-I/O to a DAX mapping.
-+config FS_DAX_LIMITED
-+ bool
-+
-+endif # BLOCK
-+
-+# Posix ACL utility routines
-+#
-+# Note: Posix ACLs can be implemented without these helpers. Never use
-+# this symbol for ifdefs in core code.
-+#
-+config FS_POSIX_ACL
-+ def_bool n
-+
-+config EXPORTFS
-+ tristate
-+
-+config EXPORTFS_BLOCK_OPS
-+ bool "Enable filesystem export operations for block IO"
-+ help
-+ This option enables the export operations for a filesystem to support
-+ external block IO.
-+
-+config FILE_LOCKING
-+ bool "Enable POSIX file locking API" if EXPERT
-+ default y
-+ help
-+ This option enables standard file locking support, required
-+ for filesystems like NFS and for the flock() system
-+ call. Disabling this option saves about 11k.
-+
-+config MANDATORY_FILE_LOCKING
-+ bool "Enable Mandatory file locking"
-+ depends on FILE_LOCKING
-+ default y
-+ help
-+ This option enables files appropriately marked files on appropriely
-+ mounted filesystems to support mandatory locking.
-+
-+ To the best of my knowledge this is dead code that no one cares about.
-+
-+source "fs/crypto/Kconfig"
-+
-+source "fs/verity/Kconfig"
-+
-+source "fs/notify/Kconfig"
-+
-+source "fs/quota/Kconfig"
-+
-+source "fs/autofs/Kconfig"
-+source "fs/fuse/Kconfig"
-+source "fs/overlayfs/Kconfig"
-+
-+menu "Caches"
-+
-+source "fs/fscache/Kconfig"
-+source "fs/cachefiles/Kconfig"
-+
-+endmenu
-+
-+if BLOCK
-+menu "CD-ROM/DVD Filesystems"
-+
-+source "fs/isofs/Kconfig"
-+source "fs/udf/Kconfig"
-+
-+endmenu
-+endif # BLOCK
-+
-+if BLOCK
-+menu "DOS/FAT/NT Filesystems"
-+
-+source "fs/fat/Kconfig"
-+source "fs/ntfs/Kconfig"
-+
-+endmenu
-+endif # BLOCK
-+
-+menu "Pseudo filesystems"
-+
-+source "fs/proc/Kconfig"
-+source "fs/kernfs/Kconfig"
-+source "fs/sysfs/Kconfig"
-+
-+config TMPFS
-+ bool "Tmpfs virtual memory file system support (former shm fs)"
-+ depends on SHMEM
-+ help
-+ Tmpfs is a file system which keeps all files in virtual memory.
-+
-+ Everything in tmpfs is temporary in the sense that no files will be
-+ created on your hard drive. The files live in memory and swap
-+ space. If you unmount a tmpfs instance, everything stored therein is
-+ lost.
-+
-+ See <file:Documentation/filesystems/tmpfs.txt> for details.
-+
-+config TMPFS_POSIX_ACL
-+ bool "Tmpfs POSIX Access Control Lists"
-+ depends on TMPFS
-+ select TMPFS_XATTR
-+ select FS_POSIX_ACL
-+ help
-+ POSIX Access Control Lists (ACLs) support additional access rights
-+ for users and groups beyond the standard owner/group/world scheme,
-+ and this option selects support for ACLs specifically for tmpfs
-+ filesystems.
-+
-+ If you've selected TMPFS, it's possible that you'll also need
-+ this option as there are a number of Linux distros that require
-+ POSIX ACL support under /dev for certain features to work properly.
-+ For example, some distros need this feature for ALSA-related /dev
-+ files for sound to work properly. In short, if you're not sure,
-+ say Y.
-+
-+config TMPFS_XATTR
-+ bool "Tmpfs extended attributes"
-+ depends on TMPFS
-+ default n
-+ help
-+ Extended attributes are name:value pairs associated with inodes by
-+ the kernel or by users (see the attr(5) manual page for details).
-+
-+ Currently this enables support for the trusted.* and
-+ security.* namespaces.
-+
-+ You need this for POSIX ACL support on tmpfs.
-+
-+ If unsure, say N.
-+
-+config HUGETLBFS
-+ bool "HugeTLB file system support"
-+ depends on X86 || IA64 || SPARC64 || (S390 && 64BIT) || \
-+ SYS_SUPPORTS_HUGETLBFS || BROKEN
-+ help
-+ hugetlbfs is a filesystem backing for HugeTLB pages, based on
-+ ramfs. For architectures that support it, say Y here and read
-+ <file:Documentation/admin-guide/mm/hugetlbpage.rst> for details.
-+
-+ If unsure, say N.
-+
-+config HUGETLB_PAGE
-+ def_bool HUGETLBFS
-+
-+config MEMFD_CREATE
-+ def_bool TMPFS || HUGETLBFS
-+
-+config ARCH_HAS_GIGANTIC_PAGE
-+ bool
-+
-+source "fs/configfs/Kconfig"
-+source "fs/efivarfs/Kconfig"
-+
-+endmenu
-+
-+menuconfig MISC_FILESYSTEMS
-+ bool "Miscellaneous filesystems"
-+ default y
-+ ---help---
-+ Say Y here to get to see options for various miscellaneous
-+ filesystems, such as filesystems that came from other
-+ operating systems.
-+
-+ This option alone does not add any kernel code.
-+
-+ If you say N, all options in this submenu will be skipped and
-+ disabled; if unsure, say Y here.
-+
-+if MISC_FILESYSTEMS
-+
-+source "fs/orangefs/Kconfig"
-+source "fs/adfs/Kconfig"
-+source "fs/affs/Kconfig"
-+source "fs/ecryptfs/Kconfig"
-+source "fs/hfs/Kconfig"
-+source "fs/hfsplus/Kconfig"
-+source "fs/befs/Kconfig"
-+source "fs/bfs/Kconfig"
-+source "fs/efs/Kconfig"
-+source "fs/jffs2/Kconfig"
-+# UBIFS File system configuration
-+source "fs/ubifs/Kconfig"
-+source "fs/cramfs/Kconfig"
-+source "fs/squashfs/Kconfig"
-+source "fs/freevxfs/Kconfig"
-+source "fs/minix/Kconfig"
-+source "fs/omfs/Kconfig"
-+source "fs/hpfs/Kconfig"
-+source "fs/qnx4/Kconfig"
-+source "fs/qnx6/Kconfig"
-+source "fs/romfs/Kconfig"
-+source "fs/pstore/Kconfig"
-+source "fs/sysv/Kconfig"
-+source "fs/ufs/Kconfig"
-+source "fs/erofs/Kconfig"
-+
-+endif # MISC_FILESYSTEMS
-+
-+menuconfig NETWORK_FILESYSTEMS
-+ bool "Network File Systems"
-+ default y
-+ depends on NET
-+ ---help---
-+ Say Y here to get to see options for network filesystems and
-+ filesystem-related networking code, such as NFS daemon and
-+ RPCSEC security modules.
-+
-+ This option alone does not add any kernel code.
-+
-+ If you say N, all options in this submenu will be skipped and
-+ disabled; if unsure, say Y here.
-+
-+if NETWORK_FILESYSTEMS
-+
-+source "fs/nfs/Kconfig"
-+source "fs/nfsd/Kconfig"
-+
-+config GRACE_PERIOD
-+ tristate
-+
-+config LOCKD
-+ tristate
-+ depends on FILE_LOCKING
-+ select GRACE_PERIOD
-+
-+config LOCKD_V4
-+ bool
-+ depends on NFSD_V3 || NFS_V3
-+ depends on FILE_LOCKING
-+ default y
-+
-+config NFS_ACL_SUPPORT
-+ tristate
-+ select FS_POSIX_ACL
-+
-+config NFS_COMMON
-+ bool
-+ depends on NFSD || NFS_FS || LOCKD
-+ default y
-+
-+source "net/sunrpc/Kconfig"
-+source "fs/ceph/Kconfig"
-+source "fs/cifs/Kconfig"
-+source "fs/coda/Kconfig"
-+source "fs/afs/Kconfig"
-+source "fs/9p/Kconfig"
-+
-+endif # NETWORK_FILESYSTEMS
-+
-+source "fs/nls/Kconfig"
-+source "fs/dlm/Kconfig"
-+source "fs/unicode/Kconfig"
-+
-+endmenu
diff --git a/fs/Makefile b/fs/Makefile
-index 14231b4cf383..6c03b014a129 100644
+index 505e51166973..4b7b6634e2ae 100644
--- a/fs/Makefile
+++ b/fs/Makefile
-@@ -132,3 +132,4 @@ obj-$(CONFIG_CEPH_FS) += ceph/
- obj-$(CONFIG_PSTORE) += pstore/
- obj-$(CONFIG_EFIVAR_FS) += efivarfs/
+@@ -135,3 +135,4 @@ obj-$(CONFIG_EFIVAR_FS) += efivarfs/
obj-$(CONFIG_EROFS_FS) += erofs/
+ obj-$(CONFIG_VBOXSF_FS) += vboxsf/
+ obj-$(CONFIG_ZONEFS_FS) += zonefs/
+obj-$(CONFIG_YAFFS_FS) += yaffs2/
-diff --git a/fs/Makefile.pre.yaffs b/fs/Makefile.pre.yaffs
-new file mode 100644
-index 000000000000..14231b4cf383
---- /dev/null
-+++ b/fs/Makefile.pre.yaffs
-@@ -0,0 +1,134 @@
-+# SPDX-License-Identifier: GPL-2.0
-+#
-+# Makefile for the Linux filesystems.
-+#
-+# 14 Sep 2000, Christoph Hellwig <hch@infradead.org>
-+# Rewritten to use lists instead of if-statements.
-+#
-+
-+obj-y := open.o read_write.o file_table.o super.o \
-+ char_dev.o stat.o exec.o pipe.o namei.o fcntl.o \
-+ ioctl.o readdir.o select.o dcache.o inode.o \
-+ attr.o bad_inode.o file.o filesystems.o namespace.o \
-+ seq_file.o xattr.o libfs.o fs-writeback.o \
-+ pnode.o splice.o sync.o utimes.o d_path.o \
-+ stack.o fs_struct.o statfs.o fs_pin.o nsfs.o \
-+ fs_types.o fs_context.o fs_parser.o fsopen.o
-+
-+ifeq ($(CONFIG_BLOCK),y)
-+obj-y += buffer.o block_dev.o direct-io.o mpage.o
-+else
-+obj-y += no-block.o
-+endif
-+
-+obj-$(CONFIG_PROC_FS) += proc_namespace.o
-+
-+obj-y += notify/
-+obj-$(CONFIG_EPOLL) += eventpoll.o
-+obj-y += anon_inodes.o
-+obj-$(CONFIG_SIGNALFD) += signalfd.o
-+obj-$(CONFIG_TIMERFD) += timerfd.o
-+obj-$(CONFIG_EVENTFD) += eventfd.o
-+obj-$(CONFIG_USERFAULTFD) += userfaultfd.o
-+obj-$(CONFIG_AIO) += aio.o
-+obj-$(CONFIG_IO_URING) += io_uring.o
-+obj-$(CONFIG_FS_DAX) += dax.o
-+obj-$(CONFIG_FS_ENCRYPTION) += crypto/
-+obj-$(CONFIG_FS_VERITY) += verity/
-+obj-$(CONFIG_FILE_LOCKING) += locks.o
-+obj-$(CONFIG_COMPAT) += compat.o compat_ioctl.o
-+obj-$(CONFIG_BINFMT_AOUT) += binfmt_aout.o
-+obj-$(CONFIG_BINFMT_EM86) += binfmt_em86.o
-+obj-$(CONFIG_BINFMT_MISC) += binfmt_misc.o
-+obj-$(CONFIG_BINFMT_SCRIPT) += binfmt_script.o
-+obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o
-+obj-$(CONFIG_COMPAT_BINFMT_ELF) += compat_binfmt_elf.o
-+obj-$(CONFIG_BINFMT_ELF_FDPIC) += binfmt_elf_fdpic.o
-+obj-$(CONFIG_BINFMT_FLAT) += binfmt_flat.o
-+
-+obj-$(CONFIG_FS_MBCACHE) += mbcache.o
-+obj-$(CONFIG_FS_POSIX_ACL) += posix_acl.o
-+obj-$(CONFIG_NFS_COMMON) += nfs_common/
-+obj-$(CONFIG_COREDUMP) += coredump.o
-+obj-$(CONFIG_SYSCTL) += drop_caches.o
-+
-+obj-$(CONFIG_FHANDLE) += fhandle.o
-+obj-y += iomap/
-+
-+obj-y += quota/
-+
-+obj-$(CONFIG_PROC_FS) += proc/
-+obj-$(CONFIG_KERNFS) += kernfs/
-+obj-$(CONFIG_SYSFS) += sysfs/
-+obj-$(CONFIG_CONFIGFS_FS) += configfs/
-+obj-y += devpts/
-+
-+obj-$(CONFIG_PROFILING) += dcookies.o
-+obj-$(CONFIG_DLM) += dlm/
-+
-+# Do not add any filesystems before this line
-+obj-$(CONFIG_FSCACHE) += fscache/
-+obj-$(CONFIG_REISERFS_FS) += reiserfs/
-+obj-$(CONFIG_EXT4_FS) += ext4/
-+# We place ext4 before ext2 so that clean ext3 root fs's do NOT mount using the
-+# ext2 driver, which doesn't know about journalling! Explicitly request ext2
-+# by giving the rootfstype= parameter.
-+obj-$(CONFIG_EXT2_FS) += ext2/
-+obj-$(CONFIG_JBD2) += jbd2/
-+obj-$(CONFIG_CRAMFS) += cramfs/
-+obj-$(CONFIG_SQUASHFS) += squashfs/
-+obj-y += ramfs/
-+obj-$(CONFIG_HUGETLBFS) += hugetlbfs/
-+obj-$(CONFIG_CODA_FS) += coda/
-+obj-$(CONFIG_MINIX_FS) += minix/
-+obj-$(CONFIG_FAT_FS) += fat/
-+obj-$(CONFIG_BFS_FS) += bfs/
-+obj-$(CONFIG_ISO9660_FS) += isofs/
-+obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+
-+obj-$(CONFIG_HFS_FS) += hfs/
-+obj-$(CONFIG_ECRYPT_FS) += ecryptfs/
-+obj-$(CONFIG_VXFS_FS) += freevxfs/
-+obj-$(CONFIG_NFS_FS) += nfs/
-+obj-$(CONFIG_EXPORTFS) += exportfs/
-+obj-$(CONFIG_NFSD) += nfsd/
-+obj-$(CONFIG_LOCKD) += lockd/
-+obj-$(CONFIG_NLS) += nls/
-+obj-$(CONFIG_UNICODE) += unicode/
-+obj-$(CONFIG_SYSV_FS) += sysv/
-+obj-$(CONFIG_CIFS) += cifs/
-+obj-$(CONFIG_HPFS_FS) += hpfs/
-+obj-$(CONFIG_NTFS_FS) += ntfs/
-+obj-$(CONFIG_UFS_FS) += ufs/
-+obj-$(CONFIG_EFS_FS) += efs/
-+obj-$(CONFIG_JFFS2_FS) += jffs2/
-+obj-$(CONFIG_UBIFS_FS) += ubifs/
-+obj-$(CONFIG_AFFS_FS) += affs/
-+obj-$(CONFIG_ROMFS_FS) += romfs/
-+obj-$(CONFIG_QNX4FS_FS) += qnx4/
-+obj-$(CONFIG_QNX6FS_FS) += qnx6/
-+obj-$(CONFIG_AUTOFS_FS) += autofs/
-+obj-$(CONFIG_ADFS_FS) += adfs/
-+obj-$(CONFIG_FUSE_FS) += fuse/
-+obj-$(CONFIG_OVERLAY_FS) += overlayfs/
-+obj-$(CONFIG_ORANGEFS_FS) += orangefs/
-+obj-$(CONFIG_UDF_FS) += udf/
-+obj-$(CONFIG_SUN_OPENPROMFS) += openpromfs/
-+obj-$(CONFIG_OMFS_FS) += omfs/
-+obj-$(CONFIG_JFS_FS) += jfs/
-+obj-$(CONFIG_XFS_FS) += xfs/
-+obj-$(CONFIG_9P_FS) += 9p/
-+obj-$(CONFIG_AFS_FS) += afs/
-+obj-$(CONFIG_NILFS2_FS) += nilfs2/
-+obj-$(CONFIG_BEFS_FS) += befs/
-+obj-$(CONFIG_HOSTFS) += hostfs/
-+obj-$(CONFIG_CACHEFILES) += cachefiles/
-+obj-$(CONFIG_DEBUG_FS) += debugfs/
-+obj-$(CONFIG_TRACING) += tracefs/
-+obj-$(CONFIG_OCFS2_FS) += ocfs2/
-+obj-$(CONFIG_BTRFS_FS) += btrfs/
-+obj-$(CONFIG_GFS2_FS) += gfs2/
-+obj-$(CONFIG_F2FS_FS) += f2fs/
-+obj-$(CONFIG_CEPH_FS) += ceph/
-+obj-$(CONFIG_PSTORE) += pstore/
-+obj-$(CONFIG_EFIVAR_FS) += efivarfs/
-+obj-$(CONFIG_EROFS_FS) += erofs/
diff --git a/fs/yaffs2/Kconfig b/fs/yaffs2/Kconfig
new file mode 100644
index 000000000000..408570fc7a5e
diff --git a/features/yaffs2/yaffs2-v5.6-build-fixups.patch b/features/yaffs2/yaffs2-v5.6-build-fixups.patch
new file mode 100644
index 00000000..375625b4
--- /dev/null
+++ b/features/yaffs2/yaffs2-v5.6-build-fixups.patch
@@ -0,0 +1,50 @@
+From 046fe0a1215486fa81327553215eca8acab9d546 Mon Sep 17 00:00:00 2001
+From: Bruce Ashfield <bruce.ashfield@gmail.com>
+Date: Mon, 16 Mar 2020 23:20:57 -0400
+Subject: [PATCH] yaffs2: v5.6 build fixups
+
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/yaffs2/yaffs_vfs.c | 17 ++++++++---------
+ 1 file changed, 8 insertions(+), 9 deletions(-)
+
+diff --git a/fs/yaffs2/yaffs_vfs.c b/fs/yaffs2/yaffs_vfs.c
+index 4fbd0a42ff3d..598ecd57a0ed 100644
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -2059,11 +2059,11 @@ static void yaffs_fill_inode_from_obj(struct inode *inode,
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))
+
+ inode->i_rdev = old_decode_dev(obj->yst_rdev);
+- inode->i_atime.tv_sec = (time_t) (obj->yst_atime);
++ inode->i_atime.tv_sec = (time64_t) (obj->yst_atime);
+ inode->i_atime.tv_nsec = 0;
+- inode->i_mtime.tv_sec = (time_t) obj->yst_mtime;
++ inode->i_mtime.tv_sec = (time64_t) obj->yst_mtime;
+ inode->i_mtime.tv_nsec = 0;
+- inode->i_ctime.tv_sec = (time_t) obj->yst_ctime;
++ inode->i_ctime.tv_sec = (time64_t) obj->yst_ctime;
+ inode->i_ctime.tv_nsec = 0;
+ #else
+ inode->i_rdev = obj->yst_rdev;
+@@ -3692,12 +3692,11 @@ static int yaffs_proc_open(struct inode *inode, struct file *file)
+ return single_open(file, yaffs_proc_show, NULL);
+ }
+
+-static struct file_operations procfs_ops = {
+- .owner = THIS_MODULE,
+- .open = yaffs_proc_open,
+- .read = seq_read,
+- .write = yaffs_proc_write,
+- .release = single_release,
++static struct proc_ops procfs_ops = {
++ .proc_open = yaffs_proc_open,
++ .proc_read = seq_read,
++ .proc_write = yaffs_proc_write,
++ .proc_release = single_release,
+ };
+
+ static int yaffs_procfs_init(void)
+--
+2.19.1
+
diff --git a/features/yaffs2/yaffs2-v6.5-fixups.patch b/features/yaffs2/yaffs2-v6.5-fixups.patch
new file mode 100644
index 00000000..0159a00b
--- /dev/null
+++ b/features/yaffs2/yaffs2-v6.5-fixups.patch
@@ -0,0 +1,26 @@
+From e9ca040537fb905d7a55ee9d20ce0414eed5f10e Mon Sep 17 00:00:00 2001
+From: Bruce Ashfield <bruce.ashfield@gmail.com>
+Date: Thu, 27 Jul 2023 18:17:32 -0400
+Subject: [PATCH] yaffs2: v6.5 fixups
+
+Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
+---
+ fs/yaffs2/yaffs_vfs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/yaffs2/yaffs_vfs.c b/fs/yaffs2/yaffs_vfs.c
+index 32864c715545..04abeee99ff5 100644
+--- a/fs/yaffs2/yaffs_vfs.c
++++ b/fs/yaffs2/yaffs_vfs.c
+@@ -844,7 +844,7 @@ static const struct file_operations yaffs_file_operations = {
+ .mmap = generic_file_mmap,
+ .flush = yaffs_file_flush,
+ .fsync = yaffs_sync_object,
+- .splice_read = generic_file_splice_read,
++ .splice_read = copy_splice_read,
+ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
+ .splice_write = iter_file_splice_write,
+ #else
+--
+2.34.1
+
diff --git a/features/yaffs2/yaffs2.scc b/features/yaffs2/yaffs2.scc
index 37628e70..5b131bd7 100644
--- a/features/yaffs2/yaffs2.scc
+++ b/features/yaffs2/yaffs2.scc
@@ -8,3 +8,17 @@ patch yaffs2-fix-memory-leak-in-mount-umount.patch
patch yaffs-Fix-build-failure-by-handling-inode-i_version-.patch
patch yaffs-repair-yaffs_get_mtd_device.patch
patch yaffs-add-strict-check-when-call-yaffs_internal_read.patch
+patch yaffs2-fix-memory-leak-when-proc-yaffs-is-read.patch
+patch yaffs2-v5.6-build-fixups.patch
+patch yaffs-fix-misplaced-variable-declaration.patch
+patch yaffs-include-blkdev.h.patch
+patch 0001-yaffs2-v5.12-build-fixups-not-runtime-tested.patch
+patch yaffs-fix-Wstringop-overread-compile-warning-in-yaff.patch
+patch yaffs-replace-IS_ERR-with-IS_ERR_OR_NULL-to-check-bo.patch
+patch 0001-yaffs2-convert-read_page-readfolio.patch
+patch 0001-yaffs2-replace-bdevname-call-with-sprintf.patch
+patch yaffs2-convert-user_namespace-to-mnt_idmap.patch
+patch yaffs2-Fix-miscalculation-of-devname-buffer-length.patch
+patch yaffs2-v6.5-fixups.patch
+patch 0001-yaffs2-update-VFS-ctime-operations-to-6.6.patch
+patch yaffs-fix-mtime-itime-field-access.patch
diff --git a/features/zram/zram.cfg b/features/zram/zram.cfg
new file mode 100644
index 00000000..9e58fb71
--- /dev/null
+++ b/features/zram/zram.cfg
@@ -0,0 +1,23 @@
+# SPDX-License-Identifier: MIT
+CONFIG_ZSMALLOC=y
+CONFIG_ZSMALLOC_STAT=n
+CONFIG_ZRAM=y
+CONFIG_ZRAM_DEF_COMP_LZORLE=y
+CONFIG_ZRAM_DEF_COMP_ZSTD=n
+CONFIG_ZRAM_DEF_COMP_LZ4=n
+CONFIG_ZRAM_DEF_COMP_LZO=n
+CONFIG_ZRAM_DEF_COMP_LZ4HC=n
+CONFIG_ZRAM_DEF_COMP_842=n
+CONFIG_ZRAM_DEF_COMP="lzo-rle"
+CONFIG_ZRAM_WRITEBACK=n
+CONFIG_ZRAM_MEMORY_TRACKING=n
+CONFIG_CRYPTO_LZO=y
+CONFIG_CRYPTO_842=y
+CONFIG_CRYPTO_LZ4=y
+CONFIG_CRYPTO_LZ4HC=y
+CONFIG_CRYPTO_ZSTD=y
+CONFIG_842_COMPRESS=y
+CONFIG_842_DECOMPRESS=y
+CONFIG_LZ4_COMPRESS=y
+CONFIG_LZ4HC_COMPRESS=y
+CONFIG_ZSTD_COMPRESS=y
diff --git a/features/zram/zram.scc b/features/zram/zram.scc
new file mode 100644
index 00000000..30388842
--- /dev/null
+++ b/features/zram/zram.scc
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: MIT
+define KFEATURE_DESCRIPTION "Compressed RAM block device support"
+define KFEATURE_COMPATIBILITY all
+
+kconf non-hardware zram.cfg