From fa57952dbe2cf4f8ffd852545b9005b17305a444 Mon Sep 17 00:00:00 2001 From: "J. R. Okajima" Date: Tue, 17 Sep 2024 19:21:50 +0900 Subject: [PATCH] 6.11 20240923 Signed-off-by: J. R. Okajima --- aufs6-base.patch | 219 +++++++++++++++++ aufs6-kbuild.patch | 24 ++ aufs6-loopback.patch | 239 ++++++++++++++++++ aufs6-mmap.patch | 436 +++++++++++++++++++++++++++++++++ aufs6-standalone.patch | 252 +++++++++++++++++++ include/uapi/linux/aufs_type.h | 2 +- lockdep-debug.patch | 16 ++ tmpfs-idr.patch | 217 ++++++++++++++++ vfs-ino.patch | 24 ++ 9 files changed, 1428 insertions(+), 1 deletion(-) create mode 100644 aufs6-base.patch create mode 100644 aufs6-kbuild.patch create mode 100644 aufs6-loopback.patch create mode 100644 aufs6-mmap.patch create mode 100644 aufs6-standalone.patch create mode 100644 lockdep-debug.patch create mode 100644 tmpfs-idr.patch create mode 100644 vfs-ino.patch diff --git a/aufs6-base.patch b/aufs6-base.patch new file mode 100644 index 00000000..62090ee3 --- /dev/null +++ b/aufs6-base.patch @@ -0,0 +1,219 @@ +SPDX-License-Identifier: GPL-2.0 +aufs6.11 base patch + +diff --git a/MAINTAINERS b/MAINTAINERS +index cc40a9d9b8cd..ba788b0b667c 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -3570,6 +3570,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" ++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 + R: Dave Ertman +diff --git a/drivers/block/loop.c b/drivers/block/loop.c +index 78a7bb28defe..479480f25a6c 100644 +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -661,6 +661,26 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, + goto done; + } + ++/* ++ * for AUFS ++ * no get/put for file. ++ */ ++/* Just to make the compiler silence, declare it */ ++struct file *loop_backing_file(struct super_block *sb); ++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 6386b9b625dd..e5f57c3cfbfc 100644 +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -1223,6 +1223,9 @@ enum d_walk_ret { + D_WALK_SKIP, + }; + ++/* AUFS calls d_walk(). Just to make the compiler silence, declare it */ ++void d_walk(struct dentry *parent, void *data, ++ enum d_walk_ret (*enter)(void *, struct dentry *)); + /** + * d_walk - walk the dentry tree + * @parent: start of walk +@@ -1231,7 +1234,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 300e5d9ad913..3f927cbf63b3 100644 +--- a/fs/fcntl.c ++++ b/fs/fcntl.c +@@ -35,7 +35,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; +@@ -65,6 +65,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 328087a4df8a..e033b3d72b00 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -966,6 +966,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 60aed8de21f8..04af758d332c 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 6ca11e241a24..5092a7e8f9e9 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -1121,6 +1121,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 int 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); +@@ -2042,6 +2043,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 217f7abf2cbf..0e17b8c23f10 100644 +--- a/include/linux/lockdep.h ++++ b/include/linux/lockdep.h +@@ -210,6 +210,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..14583d846864 100644 +--- a/include/linux/splice.h ++++ b/include/linux/splice.h +@@ -108,4 +108,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 ssize_t do_splice_from(struct pipe_inode_info *pipe, struct file *out, ++ loff_t *ppos, size_t len, unsigned int flags); + #endif +diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c +index 0349f957e672..32be18a5ad55 100644 +--- a/kernel/locking/lockdep.c ++++ b/kernel/locking/lockdep.c +@@ -217,7 +217,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; + +@@ -238,6 +238,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); diff --git a/aufs6-kbuild.patch b/aufs6-kbuild.patch new file mode 100644 index 00000000..b2f2985d --- /dev/null +++ b/aufs6-kbuild.patch @@ -0,0 +1,24 @@ +SPDX-License-Identifier: GPL-2.0 +aufs6.11 kbuild patch + +diff --git a/fs/Kconfig b/fs/Kconfig +index a46b0cbc4d8f..d90a3b0dbc53 100644 +--- a/fs/Kconfig ++++ b/fs/Kconfig +@@ -337,6 +337,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 6ecc9b0a53f2..255420c2676e 100644 +--- a/fs/Makefile ++++ b/fs/Makefile +@@ -129,3 +129,4 @@ obj-$(CONFIG_EFIVAR_FS) += efivarfs/ + obj-$(CONFIG_EROFS_FS) += erofs/ + obj-$(CONFIG_VBOXSF_FS) += vboxsf/ + obj-$(CONFIG_ZONEFS_FS) += zonefs/ ++obj-$(CONFIG_AUFS_FS) += aufs/ diff --git a/aufs6-loopback.patch b/aufs6-loopback.patch new file mode 100644 index 00000000..1ddf7ad7 --- /dev/null +++ b/aufs6-loopback.patch @@ -0,0 +1,239 @@ +SPDX-License-Identifier: GPL-2.0 +aufs6.11 loopback patch + +diff --git a/drivers/block/loop.c b/drivers/block/loop.c +index 479480f25a6c..ba3477c30e29 100644 +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -54,7 +54,7 @@ struct loop_device { + int lo_flags; + char lo_file_name[LO_NAME_SIZE]; + +- struct file * lo_backing_file; ++ struct file *lo_backing_file, *lo_backing_virt_file; + struct block_device *lo_device; + + gfp_t old_gfp_mask; +@@ -526,6 +526,15 @@ static inline void loop_update_dio(struct loop_device *lo) + lo->use_dio); + } + ++static struct file *loop_real_file(struct file *file) ++{ ++ struct file *f = NULL; ++ ++ if (file->f_path.dentry->d_sb->s_op->real_loop) ++ f = file->f_path.dentry->d_sb->s_op->real_loop(file); ++ return f; ++} ++ + static void loop_reread_partitions(struct loop_device *lo) + { + int rc; +@@ -583,6 +592,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, + { + struct file *file = fget(arg); + struct file *old_file; ++ struct file *f, *virt_file = NULL, *old_virt_file; + int error; + bool partscan; + bool is_loop; +@@ -606,11 +616,19 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, + if (!(lo->lo_flags & LO_FLAGS_READ_ONLY)) + goto out_err; + ++ f = loop_real_file(file); ++ if (f) { ++ virt_file = file; ++ file = f; ++ get_file(file); ++ } ++ + error = loop_validate_file(file, bdev); + if (error) + goto out_err; + + old_file = lo->lo_backing_file; ++ old_virt_file = lo->lo_backing_virt_file; + + error = -EINVAL; + +@@ -623,6 +641,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, + blk_mq_freeze_queue(lo->lo_queue); + mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask); + lo->lo_backing_file = file; ++ lo->lo_backing_virt_file = virt_file; + lo->old_gfp_mask = mapping_gfp_mask(file->f_mapping); + mapping_set_gfp_mask(file->f_mapping, + lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS)); +@@ -645,6 +664,8 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, + * dependency. + */ + fput(old_file); ++ if (old_virt_file) ++ fput(old_virt_file); + if (partscan) + loop_reread_partitions(lo); + +@@ -658,6 +679,8 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, + loop_global_unlock(lo, is_loop); + out_putf: + fput(file); ++ if (virt_file) ++ fput(virt_file); + goto done; + } + +@@ -1039,6 +1062,7 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode, + const struct loop_config *config) + { + struct file *file = fget(config->fd); ++ struct file *f, *virt_file = NULL; + struct address_space *mapping; + int error; + loff_t size; +@@ -1052,6 +1076,13 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode, + /* This is safe, since we have a reference from open(). */ + __module_get(THIS_MODULE); + ++ f = loop_real_file(file); ++ if (f) { ++ virt_file = file; ++ file = f; ++ get_file(file); ++ } ++ + /* + * If we don't hold exclusive handle for the device, upgrade to it + * here to avoid changing device under exclusive owner. +@@ -1108,6 +1139,7 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode, + lo->use_dio = lo->lo_flags & LO_FLAGS_DIRECT_IO; + lo->lo_device = bdev; + lo->lo_backing_file = file; ++ lo->lo_backing_virt_file = virt_file; + lo->old_gfp_mask = mapping_gfp_mask(mapping); + mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS)); + +@@ -1150,6 +1182,8 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode, + bd_abort_claiming(bdev, loop_configure); + out_putf: + fput(file); ++ if (virt_file) ++ fput(virt_file); + /* This is safe: open() is still holding a reference. */ + module_put(THIS_MODULE); + return error; +@@ -1159,11 +1193,13 @@ static void __loop_clr_fd(struct loop_device *lo) + { + struct queue_limits lim; + struct file *filp; ++ struct file *virt_filp = lo->lo_backing_virt_file; + gfp_t gfp = lo->old_gfp_mask; + + spin_lock_irq(&lo->lo_lock); + filp = lo->lo_backing_file; + lo->lo_backing_file = NULL; ++ lo->lo_backing_virt_file = NULL; + spin_unlock_irq(&lo->lo_lock); + + lo->lo_device = NULL; +@@ -1225,6 +1261,8 @@ static void __loop_clr_fd(struct loop_device *lo) + * fput can take open_mutex which is usually taken before lo_mutex. + */ + fput(filp); ++ if (virt_filp) ++ fput(virt_filp); + } + + static int loop_clr_fd(struct loop_device *lo) +diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c +index d109c1392d60..dfe82d9c6292 100644 +--- a/fs/aufs/f_op.c ++++ b/fs/aufs/f_op.c +@@ -317,7 +317,7 @@ static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter) + if (IS_ERR(h_file)) + goto out; + +- if (au_test_loopback_kthread()) { ++ if (0 && au_test_loopback_kthread()) { + au_warn_loopback(h_file->f_path.dentry->d_sb); + if (file->f_mapping != h_file->f_mapping) { + file->f_mapping = h_file->f_mapping; +diff --git a/fs/aufs/loop.c b/fs/aufs/loop.c +index 58043e31e5f3..e2bfae6f9d59 100644 +--- a/fs/aufs/loop.c ++++ b/fs/aufs/loop.c +@@ -133,3 +133,19 @@ void au_loopback_fin(void) + symbol_put(loop_backing_file); + au_kfree_try_rcu(au_warn_loopback_array); + } ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* support the loopback block device insude aufs */ ++ ++struct file *aufs_real_loop(struct file *file) ++{ ++ struct file *f; ++ ++ BUG_ON(!au_test_aufs(file->f_path.dentry->d_sb)); ++ fi_read_lock(file); ++ f = au_hf_top(file); ++ fi_read_unlock(file); ++ AuDebugOn(!f); ++ return f; ++} +diff --git a/fs/aufs/loop.h b/fs/aufs/loop.h +index 03d4908a6c03..34d356e181d5 100644 +--- a/fs/aufs/loop.h ++++ b/fs/aufs/loop.h +@@ -26,6 +26,8 @@ void au_warn_loopback(struct super_block *h_sb); + + int au_loopback_init(void); + void au_loopback_fin(void); ++ ++struct file *aufs_real_loop(struct file *file); + #else + AuStub(struct file *, loop_backing_file, return NULL, struct super_block *sb) + +@@ -36,6 +38,8 @@ AuStubVoid(au_warn_loopback, struct super_block *h_sb) + + AuStubInt0(au_loopback_init, void) + AuStubVoid(au_loopback_fin, void) ++ ++AuStub(struct file *, aufs_real_loop, return NULL, struct file *file) + #endif /* BLK_DEV_LOOP */ + + #endif /* __KERNEL__ */ +diff --git a/fs/aufs/super.c b/fs/aufs/super.c +index 07d3412e950f..c4a00f620e57 100644 +--- a/fs/aufs/super.c ++++ b/fs/aufs/super.c +@@ -758,7 +758,10 @@ const struct super_operations aufs_sop = { + .show_options = aufs_show_options, + .statfs = aufs_statfs, + .put_super = aufs_put_super, +- .sync_fs = aufs_sync_fs ++ .sync_fs = aufs_sync_fs, ++#ifdef CONFIG_AUFS_BDEV_LOOP ++ .real_loop = aufs_real_loop ++#endif + }; + + /* ---------------------------------------------------------------------- */ +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 5092a7e8f9e9..732bd5895903 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -2206,6 +2206,11 @@ struct super_operations { + long (*free_cached_objects)(struct super_block *, + struct shrink_control *); + void (*shutdown)(struct super_block *sb); ++ ++#if IS_ENABLED(CONFIG_BLK_DEV_LOOP) || IS_ENABLED(CONFIG_BLK_DEV_LOOP_MODULE) ++ /* and aufs */ ++ struct file *(*real_loop)(struct file *); ++#endif + }; + + /* diff --git a/aufs6-mmap.patch b/aufs6-mmap.patch new file mode 100644 index 00000000..8f7aa148 --- /dev/null +++ b/aufs6-mmap.patch @@ -0,0 +1,436 @@ +SPDX-License-Identifier: GPL-2.0 +aufs6.11 mmap patch + +diff --git a/fs/proc/base.c b/fs/proc/base.c +index 72a1acd03675..7970af6dde6b 100644 +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -2213,7 +2213,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 = *file_user_path(vma->vm_file); ++ *path = vma_pr_or_file(vma)->f_path; + path_get(path); + rc = 0; + } +diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c +index c6e7ebc63756..d7ccfd909764 100644 +--- a/fs/proc/nommu.c ++++ b/fs/proc/nommu.c +@@ -39,7 +39,10 @@ static int nommu_region_show(struct seq_file *m, struct vm_region *region) + file = region->vm_file; + + if (file) { +- struct inode *inode = file_inode(region->vm_file); ++ struct inode *inode; ++ ++ file = vmr_pr_or_file(region); ++ inode = file_inode(file); + dev = inode->i_sb->s_dev; + ino = inode->i_ino; + } +diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c +index 5f171ad7b436..6b10fe0d25d8 100644 +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -264,7 +264,8 @@ static void get_vma_name(struct vm_area_struct *vma, + *name_fmt = "[anon_shmem:%s]"; + *name = anon_name->name; + } else { +- *path = file_user_path(vma->vm_file); ++ struct file *f = vma_pr_or_file(vma); ++ *path = file_user_path(f); + } + return; + } +@@ -333,7 +334,8 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma) + dev_t dev = 0; + + if (vma->vm_file) { +- const struct inode *inode = file_user_inode(vma->vm_file); ++ const struct inode *inode ++ = file_inode(vma_pr_or_file(vma)); + + dev = inode->i_sb->s_dev; + ino = inode->i_ino; +@@ -3013,7 +3015,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; + char buffer[64]; + struct mempolicy *pol; +diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c +index bce674533000..b12b5a75c799 100644 +--- a/fs/proc/task_nommu.c ++++ b/fs/proc/task_nommu.c +@@ -137,7 +137,10 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma) + file = vma->vm_file; + + if (file) { +- struct inode *inode = file_inode(vma->vm_file); ++ struct inode *inode; ++ ++ file = vma_pr_or_file(vma); ++ inode = file_inode(file); + dev = inode->i_sb->s_dev; + 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 147073601716..9de0f88adb93 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -2459,6 +2459,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); ++extern void vma_do_get_file(struct vm_area_struct *, const char[], int); ++extern void vma_do_fput(struct vm_area_struct *, const char[], int); ++ ++#define vma_file_update_time(vma) vma_do_file_update_time(vma, __func__, \ ++ __LINE__) ++#define vma_pr_or_file(vma) vma_do_pr_or_file(vma, __func__, \ ++ __LINE__) ++#define vma_get_file(vma) vma_do_get_file(vma, __func__, __LINE__) ++#define vma_fput(vma) vma_do_fput(vma, __func__, __LINE__) ++ ++#ifndef CONFIG_MMU ++extern struct file *vmr_do_pr_or_file(struct vm_region *, const char[], int); ++extern void vmr_do_fput(struct vm_region *, const char[], int); ++ ++#define vmr_pr_or_file(region) vmr_do_pr_or_file(region, __func__, \ ++ __LINE__) ++#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 485424979254..952e89999a0c 100644 +--- a/include/linux/mm_types.h ++++ b/include/linux/mm_types.h +@@ -572,6 +572,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 +@@ -736,6 +739,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_ANON_VMA_NAME +diff --git a/kernel/fork.c b/kernel/fork.c +index cc760491f201..2ef841e2f774 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -733,7 +733,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); + i_mmap_lock_write(mapping); + if (vma_is_shared_maywrite(tmp)) + mapping_allow_writable(mapping); +diff --git a/mm/Makefile b/mm/Makefile +index d2915f8c9dc0..b07f11a62f7c 100644 +--- a/mm/Makefile ++++ b/mm/Makefile +@@ -141,3 +141,4 @@ obj-$(CONFIG_HAVE_BOOTMEM_INFO_NODE) += bootmem_info.o + obj-$(CONFIG_GENERIC_IOREMAP) += ioremap.o + obj-$(CONFIG_SHRINKER_DEBUG) += shrinker_debug.o + obj-$(CONFIG_EXECMEM) += execmem.o ++obj-y += prfile.o +diff --git a/mm/filemap.c b/mm/filemap.c +index 0ca9c1377b68..beacce26df57 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -3673,7 +3673,7 @@ vm_fault_t filemap_page_mkwrite(struct vm_fault *vmf) + vm_fault_t ret = VM_FAULT_LOCKED; + + sb_start_pagefault(mapping->host->i_sb); +- file_update_time(vmf->vma->vm_file); ++ vma_file_update_time(vmf->vma); + folio_lock(folio); + if (folio->mapping != mapping) { + folio_unlock(folio); +diff --git a/mm/mmap.c b/mm/mmap.c +index d0dfc85b209b..9cf97aae7e6a 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -181,7 +181,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)); + if (unreachable) + __vm_area_free(vma); +@@ -598,7 +598,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 (vp->remove->anon_vma) + anon_vma_merge(vp->vma, vp->remove); +@@ -2487,7 +2487,7 @@ static int __split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma, + goto out_free_mpol; + + if (new->vm_file) +- get_file(new->vm_file); ++ vma_get_file(new); + + if (new->vm_ops && new->vm_ops->open) + new->vm_ops->open(new); +@@ -2991,7 +2991,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. */ +@@ -3077,7 +3077,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); +@@ -3139,6 +3139,9 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, + unsigned long populate = 0; + unsigned long ret = -EINVAL; + 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/mm/remap_file_pages.rst.\n", + current->comm, current->pid); +@@ -3197,10 +3200,34 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, + if (vma->vm_flags & VM_LOCKED) + flags |= MAP_LOCKED; + ++#if 1 /* IS_ENABLED(CONFIG_AUFS_FS) */ ++ vma_get_file(vma); ++ file = vma->vm_file; ++ prfile = vma->vm_prfile; ++ ret = do_mmap(vma->vm_file, start, size, ++ prot, flags, /*vm_flags*/0, 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 (prfile) ++ get_file(prfile); ++ } ++ /* ++ * two fput()s instead of vma_fput(vma), ++ * coz vma may not be available anymore. ++ */ ++ 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: + mmap_write_unlock(mm); + if (populate) +@@ -3551,7 +3578,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) +- get_file(new_vma->vm_file); ++ vma_get_file(new_vma); + if (new_vma->vm_ops && new_vma->vm_ops->open) + new_vma->vm_ops->open(new_vma); + if (vma_link(mm, new_vma)) +@@ -3565,7 +3592,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 7296e775e04e..8d0180a7b370 100644 +--- a/mm/nommu.c ++++ b/mm/nommu.c +@@ -507,7 +507,7 @@ static void __put_nommu_region(struct vm_region *region) + up_write(&nommu_region_sem); + + if (region->vm_file) +- fput(region->vm_file); ++ vmr_fput(region); + + /* IO memory and memory shared directly out of the pagecache + * from ramfs/tmpfs mustn't be released here */ +@@ -587,7 +587,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) +- fput(vma->vm_file); ++ vma_fput(vma); + put_nommu_region(vma->vm_region); + vm_area_free(vma); + } +@@ -1119,7 +1119,7 @@ unsigned long do_mmap(struct file *file, + goto error_just_free; + } + } +- fput(region->vm_file); ++ vmr_fput(region); + kmem_cache_free(vm_region_jar, region); + region = pregion; + result = start; +@@ -1205,10 +1205,10 @@ unsigned long do_mmap(struct file *file, + error: + vma_iter_free(&vmi); + if (region->vm_file) +- fput(region->vm_file); ++ vmr_fput(region); + kmem_cache_free(vm_region_jar, region); + if (vma->vm_file) +- fput(vma->vm_file); ++ vma_fput(vma); + vm_area_free(vma); + return ret; + +diff --git a/mm/prfile.c b/mm/prfile.c +new file mode 100644 +index 000000000000..8f820a235364 +--- /dev/null ++++ b/mm/prfile.c +@@ -0,0 +1,86 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Mainly for aufs which mmap(2) different file and wants to print different ++ * path in /proc/PID/maps. ++ * Call these functions via macros defined in linux/mm.h. ++ * ++ * See Documentation/filesystems/aufs/design/06mmap.txt ++ * ++ * Copyright (c) 2014-2022 Junjro R. Okajima ++ * Copyright (c) 2014 Ian Campbell ++ */ ++ ++#include ++#include ++#include ++ ++/* #define PRFILE_TRACE */ ++static inline void prfile_trace(struct file *f, struct file *pr, ++ const char func[], int line, const char func2[]) ++{ ++#ifdef PRFILE_TRACE ++ if (pr) ++ pr_info("%s:%d: %s, %pD2\n", func, line, func2, f); ++#endif ++} ++ ++void vma_do_file_update_time(struct vm_area_struct *vma, const char func[], ++ int line) ++{ ++ struct file *f = vma->vm_file, *pr = vma->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ file_update_time(f); ++ if (f && pr) ++ file_update_time(pr); ++} ++ ++struct file *vma_do_pr_or_file(struct vm_area_struct *vma, const char func[], ++ int line) ++{ ++ struct file *f = vma->vm_file, *pr = vma->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ return (f && pr) ? pr : f; ++} ++ ++void vma_do_get_file(struct vm_area_struct *vma, const char func[], int line) ++{ ++ struct file *f = vma->vm_file, *pr = vma->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ get_file(f); ++ if (f && pr) ++ get_file(pr); ++} ++ ++void vma_do_fput(struct vm_area_struct *vma, const char func[], int line) ++{ ++ struct file *f = vma->vm_file, *pr = vma->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ fput(f); ++ if (f && pr) ++ fput(pr); ++} ++ ++#ifndef CONFIG_MMU ++struct file *vmr_do_pr_or_file(struct vm_region *region, const char func[], ++ int line) ++{ ++ struct file *f = region->vm_file, *pr = region->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ return (f && pr) ? pr : f; ++} ++ ++void vmr_do_fput(struct vm_region *region, const char func[], int line) ++{ ++ struct file *f = region->vm_file, *pr = region->vm_prfile; ++ ++ prfile_trace(f, pr, func, line, __func__); ++ fput(f); ++ if (f && pr) ++ fput(pr); ++} ++#endif /* !CONFIG_MMU */ diff --git a/aufs6-standalone.patch b/aufs6-standalone.patch new file mode 100644 index 00000000..c684faf5 --- /dev/null +++ b/aufs6-standalone.patch @@ -0,0 +1,252 @@ +SPDX-License-Identifier: GPL-2.0 +aufs6.11 standalone patch + +diff --git a/fs/dcache.c b/fs/dcache.c +index e5f57c3cfbfc..529be26e381d 100644 +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -1333,6 +1333,7 @@ void d_walk(struct dentry *parent, void *data, + seq = 1; + goto again; + } ++EXPORT_SYMBOL_GPL(d_walk); + + struct check_mount { + struct vfsmount *mnt; +@@ -2897,6 +2898,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 50e76cc633c4..9c5f68105979 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -114,6 +114,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 3f927cbf63b3..9a6faf9fb36d 100644 +--- a/fs/fcntl.c ++++ b/fs/fcntl.c +@@ -88,6 +88,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 ca7843dde56d..0ce507e96f3a 100644 +--- a/fs/file_table.c ++++ b/fs/file_table.c +@@ -221,6 +221,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 e033b3d72b00..09bfecd15ba4 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -971,6 +971,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 +@@ -2173,6 +2174,7 @@ struct vfsmount *collect_mounts(const struct path *path) + return ERR_CAST(tree); + return &tree->mnt; + } ++EXPORT_SYMBOL_GPL(collect_mounts); + + static void free_mnt_ns(struct mnt_namespace *); + static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *, bool); +@@ -2203,6 +2205,7 @@ void drop_collected_mounts(struct vfsmount *mnt) + unlock_mount_hash(); + namespace_unlock(); + } ++EXPORT_SYMBOL_GPL(drop_collected_mounts); + + bool has_locked_children(struct mount *mnt, struct dentry *dentry) + { +@@ -2274,6 +2277,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 22adbef7ecc2..8a6cbb395ba9 100644 +--- a/fs/open.c ++++ b/fs/open.c +@@ -66,6 +66,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 90e283b31ca1..e85c2c6149ac 100644 +--- a/fs/read_write.c ++++ b/fs/read_write.c +@@ -483,6 +483,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) + { +@@ -598,6 +599,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 04af758d332c..06836fe2d101 100644 +--- a/fs/splice.c ++++ b/fs/splice.c +@@ -940,6 +940,7 @@ ssize_t 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 7672ce5486c5..b59504c73737 100644 +--- a/fs/xattr.c ++++ b/fs/xattr.c +@@ -405,6 +405,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 32be18a5ad55..fb8b368567f2 100644 +--- a/kernel/locking/lockdep.c ++++ b/kernel/locking/lockdep.c +@@ -238,6 +238,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 5d14d639ac71..d6b770a115b8 100644 +--- a/kernel/task_work.c ++++ b/kernel/task_work.c +@@ -231,3 +231,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 8cee5b6c6e6d..74c4b7013c46 100644 +--- a/security/security.c ++++ b/security/security.c +@@ -1840,6 +1840,7 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry) + return 0; + return call_int_hook(path_rmdir, dir, dentry); + } ++EXPORT_SYMBOL_GPL(security_path_rmdir); + + /** + * security_path_unlink() - Check if removing a hard link is allowed +@@ -1875,6 +1876,7 @@ int security_path_symlink(const struct path *dir, struct dentry *dentry, + return 0; + return call_int_hook(path_symlink, dir, dentry, old_name); + } ++EXPORT_SYMBOL_GPL(security_path_symlink); + + /** + * security_path_link - Check if creating a hard link is allowed +@@ -1893,6 +1895,7 @@ int security_path_link(struct dentry *old_dentry, const struct path *new_dir, + return 0; + return call_int_hook(path_link, old_dentry, new_dir, new_dentry); + } ++EXPORT_SYMBOL_GPL(security_path_link); + + /** + * security_path_rename() - Check if renaming a file is allowed +@@ -1954,6 +1957,7 @@ int security_path_chmod(const struct path *path, umode_t mode) + return 0; + return call_int_hook(path_chmod, path, mode); + } ++EXPORT_SYMBOL_GPL(security_path_chmod); + + /** + * security_path_chown() - Check if changing the file's owner/group is allowed +@@ -1971,6 +1975,7 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) + return 0; + return call_int_hook(path_chown, path, uid, gid); + } ++EXPORT_SYMBOL_GPL(security_path_chown); + + /** + * security_path_chroot() - Check if changing the root directory is allowed +@@ -2215,6 +2220,7 @@ int security_inode_permission(struct inode *inode, int mask) + return 0; + return call_int_hook(inode_permission, inode, mask); + } ++EXPORT_SYMBOL_GPL(security_inode_permission); + + /** + * security_inode_setattr() - Check if setting file attributes is allowed +@@ -2721,6 +2727,7 @@ int security_file_permission(struct file *file, int mask) + { + return call_int_hook(file_permission, file, mask); + } ++EXPORT_SYMBOL_GPL(security_file_permission); + + /** + * security_file_alloc() - Allocate and init a file's LSM blob +@@ -3023,6 +3030,7 @@ int security_file_truncate(struct file *file) + { + return call_int_hook(file_truncate, file); + } ++EXPORT_SYMBOL_GPL(security_file_truncate); + + /** + * security_task_alloc() - Allocate a task's LSM blob diff --git a/include/uapi/linux/aufs_type.h b/include/uapi/linux/aufs_type.h index 1fd17274..dc61f484 100644 --- a/include/uapi/linux/aufs_type.h +++ b/include/uapi/linux/aufs_type.h @@ -40,7 +40,7 @@ #include #endif /* __KERNEL__ */ -#define AUFS_VERSION "6.11" +#define AUFS_VERSION "6.11-20240923" /* todo? move this to linux-2.6.19/include/magic.h */ #define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's') diff --git a/lockdep-debug.patch b/lockdep-debug.patch new file mode 100644 index 00000000..87bdda47 --- /dev/null +++ b/lockdep-debug.patch @@ -0,0 +1,16 @@ +SPDX-License-Identifier: GPL-2.0 +aufs6.11 lockdep patch + +diff --git a/include/linux/lockdep_types.h b/include/linux/lockdep_types.h +index 9f361d3ab9d9..57efd6ffe7a4 100644 +--- a/include/linux/lockdep_types.h ++++ b/include/linux/lockdep_types.h +@@ -12,7 +12,7 @@ + + #include + +-#define MAX_LOCKDEP_SUBCLASSES 8UL ++#define MAX_LOCKDEP_SUBCLASSES (8UL + 4) + + enum lockdep_wait_type { + LD_WAIT_INV = 0, /* not checked, catch all */ diff --git a/tmpfs-idr.patch b/tmpfs-idr.patch new file mode 100644 index 00000000..516da6c1 --- /dev/null +++ b/tmpfs-idr.patch @@ -0,0 +1,217 @@ +SPDX-License-Identifier: GPL-2.0 + +diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h +index 1d06b1e5408a..78e3535f5ad2 100644 +--- a/include/linux/shmem_fs.h ++++ b/include/linux/shmem_fs.h +@@ -55,10 +55,13 @@ struct shmem_quota_limits { + }; + + struct shmem_sb_info { ++ struct mutex idr_lock; ++ bool idr_nouse; ++ struct idr idr; /* manages inode-number */ + unsigned long max_blocks; /* How many blocks are allowed */ + struct percpu_counter used_blocks; /* How many are allocated */ +- unsigned long max_inodes; /* How many inodes are allowed */ +- unsigned long free_ispace; /* How much ispace left for allocation */ ++ int max_inodes; /* How many inodes are allowed */ ++ unsigned long free_ispace; /* How many are left for allocation */ + raw_spinlock_t stat_lock; /* Serialize shmem_sb_info changes */ + umode_t mode; /* Mount mode for root directory */ + unsigned char huge; /* Whether to try for hugepages */ +diff --git a/mm/shmem.c b/mm/shmem.c +index 5a77acf6ac6a..09a23d534f22 100644 +--- a/mm/shmem.c ++++ b/mm/shmem.c +@@ -112,7 +112,7 @@ struct shmem_falloc { + + struct shmem_options { + unsigned long long blocks; +- unsigned long long inodes; ++ int inodes; + struct mempolicy *mpol; + kuid_t uid; + kgid_t gid; +@@ -144,12 +144,14 @@ static unsigned long shmem_default_max_blocks(void) + return totalram_pages() / 2; + } + +-static unsigned long shmem_default_max_inodes(void) ++static int shmem_default_max_inodes(void) + { + unsigned long nr_pages = totalram_pages(); ++ unsigned long ul; + +- return min3(nr_pages - totalhigh_pages(), nr_pages / 2, +- ULONG_MAX / BOGO_INODE_SIZE); ++ ul = INT_MAX; ++ ul = min3(ul, nr_pages - totalhigh_pages(), nr_pages / 2); ++ return ul; + } + #endif + +@@ -1279,6 +1281,11 @@ static void shmem_evict_inode(struct inode *inode) + } + + simple_xattrs_free(&info->xattrs, sbinfo->max_inodes ? &freed : NULL); ++ if (!sbinfo->idr_nouse && inode->i_ino) { ++ mutex_lock(&sbinfo->idr_lock); ++ idr_remove(&sbinfo->idr, inode->i_ino); ++ mutex_unlock(&sbinfo->idr_lock); ++ } + shmem_free_inode(inode->i_sb, freed); + WARN_ON(inode->i_blocks); + clear_inode(inode); +@@ -2714,6 +2721,25 @@ static struct inode *__shmem_get_inode(struct mnt_idmap *idmap, + break; + } + ++ if (!sbinfo->idr_nouse) { ++ /* inum 0 and 1 are unused */ ++ mutex_lock(&sbinfo->idr_lock); ++ ino = idr_alloc(&sbinfo->idr, inode, 2, INT_MAX, ++ GFP_NOFS); ++ if (ino > 0) { ++ inode->i_ino = ino; ++ mutex_unlock(&sbinfo->idr_lock); ++ __insert_inode_hash(inode, inode->i_ino); ++ } else { ++ inode->i_ino = 0; ++ mutex_unlock(&sbinfo->idr_lock); ++ iput(inode); ++ /* shmem_free_inode() will be called */ ++ inode = NULL; ++ } ++ } else ++ inode->i_ino = ino; ++ + lockdep_annotate_inode_mutex_key(inode); + return inode; + } +@@ -3959,8 +3985,7 @@ static struct dentry *shmem_get_parent(struct dentry *child) + static int shmem_match(struct inode *ino, void *vfh) + { + __u32 *fh = vfh; +- __u64 inum = fh[2]; +- inum = (inum << 32) | fh[1]; ++ __u64 inum = fh[1]; + return ino->i_ino == inum && fh[0] == ino->i_generation; + } + +@@ -3979,14 +4004,11 @@ static struct dentry *shmem_fh_to_dentry(struct super_block *sb, + struct dentry *dentry = NULL; + u64 inum; + +- if (fh_len < 3) ++ if (fh_len < 2) + return NULL; + +- inum = fid->raw[2]; +- inum = (inum << 32) | fid->raw[1]; +- +- inode = ilookup5(sb, (unsigned long)(inum + fid->raw[0]), +- shmem_match, fid->raw); ++ inum = fid->raw[1]; ++ inode = ilookup5(sb, inum, shmem_match, fid->raw); + if (inode) { + dentry = shmem_find_alias(inode); + iput(inode); +@@ -3998,30 +4020,15 @@ static struct dentry *shmem_fh_to_dentry(struct super_block *sb, + static int shmem_encode_fh(struct inode *inode, __u32 *fh, int *len, + struct inode *parent) + { +- if (*len < 3) { +- *len = 3; ++ if (*len < 2) { ++ *len = 2; + return FILEID_INVALID; + } + +- if (inode_unhashed(inode)) { +- /* Unfortunately insert_inode_hash is not idempotent, +- * so as we hash inodes here rather than at creation +- * time, we need a lock to ensure we only try +- * to do it once +- */ +- static DEFINE_SPINLOCK(lock); +- spin_lock(&lock); +- if (inode_unhashed(inode)) +- __insert_inode_hash(inode, +- inode->i_ino + inode->i_generation); +- spin_unlock(&lock); +- } +- + fh[0] = inode->i_generation; + fh[1] = inode->i_ino; +- fh[2] = ((__u64)inode->i_ino) >> 32; + +- *len = 3; ++ *len = 2; + return 1; + } + +@@ -4120,7 +4127,7 @@ static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param) + break; + case Opt_nr_inodes: + ctx->inodes = memparse(param->string, &rest); +- if (*rest || ctx->inodes > ULONG_MAX / BOGO_INODE_SIZE) ++ if (*rest || ctx->inodes < 2 || ctx->inodes > INT_MAX) + goto bad_value; + ctx->seen |= SHMEM_SEEN_INODES; + break; +@@ -4402,7 +4409,7 @@ static int shmem_show_options(struct seq_file *seq, struct dentry *root) + if (sbinfo->max_blocks != shmem_default_max_blocks()) + seq_printf(seq, ",size=%luk", K(sbinfo->max_blocks)); + if (sbinfo->max_inodes != shmem_default_max_inodes()) +- seq_printf(seq, ",nr_inodes=%lu", sbinfo->max_inodes); ++ seq_printf(seq, ",nr_inodes=%d", sbinfo->max_inodes); + if (sbinfo->mode != (0777 | S_ISVTX)) + seq_printf(seq, ",mode=%03ho", sbinfo->mode); + if (!uid_eq(sbinfo->uid, GLOBAL_ROOT_UID)) +@@ -4474,6 +4481,8 @@ static void shmem_put_super(struct super_block *sb) + #ifdef CONFIG_TMPFS_QUOTA + shmem_disable_quotas(sb); + #endif ++ if (!sbinfo->idr_nouse) ++ idr_destroy(&sbinfo->idr); + free_percpu(sbinfo->ino_batch); + percpu_counter_destroy(&sbinfo->used_blocks); + mpol_put(sbinfo->mpol); +@@ -4518,9 +4527,11 @@ static int shmem_fill_super(struct super_block *sb, struct fs_context *fc) + #else + sb->s_flags |= SB_NOUSER; + #endif ++ mutex_init(&sbinfo->idr_lock); ++ idr_init(&sbinfo->idr); + sbinfo->max_blocks = ctx->blocks; + sbinfo->max_inodes = ctx->inodes; +- sbinfo->free_ispace = sbinfo->max_inodes * BOGO_INODE_SIZE; ++ sbinfo->free_ispace = (unsigned long)sbinfo->max_inodes * BOGO_INODE_SIZE; + if (sb->s_flags & SB_KERNMOUNT) { + sbinfo->ino_batch = alloc_percpu(ino_t); + if (!sbinfo->ino_batch) +@@ -4665,6 +4676,15 @@ static int shmem_error_remove_folio(struct address_space *mapping, + return 0; + } + ++static __init void shmem_no_idr(struct super_block *sb) ++{ ++ struct shmem_sb_info *sbinfo; ++ ++ sbinfo = SHMEM_SB(sb); ++ sbinfo->idr_nouse = true; ++ idr_destroy(&sbinfo->idr); ++} ++ + static const struct address_space_operations shmem_aops = { + .writepage = shmem_writepage, + .dirty_folio = noop_dirty_folio, +@@ -4833,6 +4853,7 @@ void __init shmem_init(void) + pr_err("Could not kern_mount tmpfs\n"); + goto out1; + } ++ shmem_no_idr(shm_mnt->mnt_sb); + + #ifdef CONFIG_TRANSPARENT_HUGEPAGE + if (has_transparent_hugepage() && shmem_huge > SHMEM_HUGE_DENY) diff --git a/vfs-ino.patch b/vfs-ino.patch new file mode 100644 index 00000000..fb29f8d1 --- /dev/null +++ b/vfs-ino.patch @@ -0,0 +1,24 @@ +SPDX-License-Identifier: GPL-2.0 + +diff --git a/fs/inode.c b/fs/inode.c +index 10c4619faeef..2f4422c7bd7e 100644 +--- a/fs/inode.c ++++ b/fs/inode.c +@@ -1039,6 +1039,8 @@ unsigned int get_next_ino(void) + unsigned int *p = &get_cpu_var(last_ino); + unsigned int res = *p; + ++start: ++ + #ifdef CONFIG_SMP + if (unlikely((res & (LAST_INO_BATCH-1)) == 0)) { + static atomic_t shared_last_ino; +@@ -1051,7 +1053,7 @@ unsigned int get_next_ino(void) + res++; + /* get_next_ino should not provide a 0 inode number */ + if (unlikely(!res)) +- res++; ++ goto start; + *p = res; + put_cpu_var(last_ino); + return res;