diff --git a/aufs5-base.patch b/aufs5-base.patch new file mode 100644 index 00000000..97276ab0 --- /dev/null +++ b/aufs5-base.patch @@ -0,0 +1,262 @@ +SPDX-License-Identifier: GPL-2.0 +aufs5.10.82 base patch + +diff --git a/MAINTAINERS b/MAINTAINERS +index 4fef10dd29753..e013880d69f33 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -3009,6 +3009,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" ++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 DISPLAY DRIVERS + M: Miguel Ojeda Sandonis + S: Maintained +diff --git a/drivers/block/loop.c b/drivers/block/loop.c +index ee537a9f1d1a4..d09b1ef4a2b56 100644 +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -752,6 +752,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 ea0485861d937..ddca6240e0db4 100644 +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -1285,7 +1285,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 71b43538fa44c..7cd57fb4e8646 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/namespace.c b/fs/namespace.c +index 046b084136c51..a256f0f9c6c09 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -792,6 +792,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 866d5c2367b23..55b5356262085 100644 +--- a/fs/splice.c ++++ b/fs/splice.c +@@ -756,8 +756,8 @@ static int warn_unsupported(struct file *file, const char *op) + /* + * 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) + { + if (unlikely(!out->f_op->splice_write)) + return warn_unsupported(out, "write"); +@@ -767,9 +767,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) + { + int ret; + +diff --git a/fs/sync.c b/fs/sync.c +index 1373a610dc784..b7b5a0a0df6ff 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 42d246a942283..2cc1a02e444c4 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -1332,6 +1332,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); +@@ -1843,6 +1844,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); +@@ -2330,6 +2332,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; +@@ -2566,6 +2569,7 @@ static inline bool sb_is_blkdev_sb(struct super_block *sb) + } + + void emergency_thaw_all(void); ++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 20b6797babe2c..7888c04c3ffaf 100644 +--- a/include/linux/lockdep.h ++++ b/include/linux/lockdep.h +@@ -248,6 +248,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. + * +@@ -384,6 +386,7 @@ static inline void lockdep_unregister_key(struct lock_class_key *key) + + #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 8f882f5881e87..6b9808f098435 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 a55179fd60fc3..8e21c53cf8831 100644 +--- a/include/linux/splice.h ++++ b/include/linux/splice.h +@@ -93,4 +93,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 1f6a2f1226fa9..4550f7a021178 100644 +--- a/kernel/locking/lockdep.c ++++ b/kernel/locking/lockdep.c +@@ -188,7 +188,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; + +@@ -209,6 +209,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/aufs5-kbuild.patch b/aufs5-kbuild.patch new file mode 100644 index 00000000..da9440f6 --- /dev/null +++ b/aufs5-kbuild.patch @@ -0,0 +1,24 @@ +SPDX-License-Identifier: GPL-2.0 +aufs5.10.82 kbuild patch + +diff --git a/fs/Kconfig b/fs/Kconfig +index da524c4d7b7e0..50ab89368c2b5 100644 +--- a/fs/Kconfig ++++ b/fs/Kconfig +@@ -288,6 +288,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 999d1a23f036c..0cd76857ca764 100644 +--- a/fs/Makefile ++++ b/fs/Makefile +@@ -136,3 +136,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/aufs5-loopback.patch b/aufs5-loopback.patch new file mode 100644 index 00000000..6a3403ed --- /dev/null +++ b/aufs5-loopback.patch @@ -0,0 +1,244 @@ +SPDX-License-Identifier: GPL-2.0 +aufs5.10.82 loopback patch + +diff --git a/drivers/block/loop.c b/drivers/block/loop.c +index d09b1ef4a2b56..ee27ab8e34898 100644 +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -637,6 +637,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, + struct block_device *bdev) + { +@@ -692,6 +701,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, + unsigned int arg) + { + struct file *file = NULL, *old_file; ++ struct file *f, *virt_file = NULL, *old_virt_file; + int error; + bool partscan; + +@@ -711,12 +721,19 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, + file = fget(arg); + if (!file) + 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; + +@@ -728,6 +745,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)); +@@ -741,6 +759,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, bdev); + return 0; +@@ -749,6 +769,8 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, + mutex_unlock(&loop_ctl_mutex); + if (file) + fput(file); ++ if (virt_file) ++ fput(virt_file); + return error; + } + +@@ -1077,7 +1099,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, + struct block_device *bdev, + const struct loop_config *config) + { +- struct file *file; ++ struct file *file, *f, *virt_file = NULL; + struct inode *inode; + struct address_space *mapping; + struct block_device *claimed_bdev = NULL; +@@ -1093,6 +1115,12 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, + file = fget(config->fd); + if (!file) + goto out; ++ 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 +@@ -1148,6 +1176,7 @@ static int loop_configure(struct loop_device *lo, fmode_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)); + +@@ -1202,6 +1231,8 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, + bd_abort_claiming(bdev, claimed_bdev, loop_configure); + out_putf: + fput(file); ++ if (virt_file) ++ fput(virt_file); + out: + /* This is safe: open() is still holding a reference. */ + module_put(THIS_MODULE); +@@ -1211,6 +1242,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, + static int __loop_clr_fd(struct loop_device *lo, bool release) + { + struct file *filp = NULL; ++ struct file *virt_filp = lo->lo_backing_virt_file; + gfp_t gfp = lo->old_gfp_mask; + struct block_device *bdev = lo->lo_device; + int err = 0; +@@ -1237,6 +1269,7 @@ static int __loop_clr_fd(struct loop_device *lo, bool release) + + spin_lock_irq(&lo->lo_lock); + lo->lo_backing_file = NULL; ++ lo->lo_backing_virt_file = NULL; + spin_unlock_irq(&lo->lo_lock); + + loop_release_xfer(lo); +@@ -1320,6 +1353,8 @@ static int __loop_clr_fd(struct loop_device *lo, bool release) + */ + if (filp) + fput(filp); ++ if (virt_filp) ++ fput(virt_filp); + return err; + } + +diff --git a/drivers/block/loop.h b/drivers/block/loop.h +index af75a5ee40944..1d847cb194ff6 100644 +--- a/drivers/block/loop.h ++++ b/drivers/block/loop.h +@@ -46,7 +46,7 @@ struct loop_device { + int (*ioctl)(struct loop_device *, int cmd, + unsigned long arg); + +- struct file * lo_backing_file; ++ struct file *lo_backing_file, *lo_backing_virt_file; + struct block_device *lo_device; + void *key_data; + +diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c +index 99ceca1440449..e49dfe8550329 100644 +--- a/fs/aufs/f_op.c ++++ b/fs/aufs/f_op.c +@@ -304,7 +304,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 74347bd75b380..5ef888a1d53f4 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 7293bee427f96..3345c098d0d47 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 8e2d8464dac0e..ab6e940aac7ab 100644 +--- a/fs/aufs/super.c ++++ b/fs/aufs/super.c +@@ -844,7 +844,10 @@ static const struct super_operations aufs_sop = { + .statfs = aufs_statfs, + .put_super = aufs_put_super, + .sync_fs = aufs_sync_fs, +- .remount_fs = aufs_remount_fs ++ .remount_fs = aufs_remount_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 2cc1a02e444c4..e53241a43d244 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -1967,6 +1967,10 @@ struct super_operations { + struct shrink_control *); + long (*free_cached_objects)(struct super_block *, + struct shrink_control *); ++#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/aufs5-mmap.patch b/aufs5-mmap.patch new file mode 100644 index 00000000..1cf9ce01 --- /dev/null +++ b/aufs5-mmap.patch @@ -0,0 +1,398 @@ +SPDX-License-Identifier: GPL-2.0 +aufs5.10.82 mmap patch + +diff --git a/fs/proc/base.c b/fs/proc/base.c +index 5d52aea8d7e7d..2fbf0ad30eaa9 100644 +--- a/fs/proc/base.c ++++ b/fs/proc/base.c +@@ -2184,7 +2184,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_get(path); + rc = 0; + } +diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c +index 13452b32e2bd5..38acccfef9d49 100644 +--- a/fs/proc/nommu.c ++++ b/fs/proc/nommu.c +@@ -40,7 +40,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 3931f60e421f7..e5bf27de3f0bc 100644 +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -280,7 +280,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); ++ 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; +@@ -1863,7 +1866,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]; +diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c +index a6d21fc0033c6..02c2de31196e0 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) + 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 289c26f055cdd..63f3dca76b2eb 100644 +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -1730,6 +1730,28 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping, + unmap_mapping_range(mapping, holebegin, holelen, 0); + } + ++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 */ ++ + 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 4eb38918da8f8..facc9741d5701 100644 +--- a/include/linux/mm_types.h ++++ b/include/linux/mm_types.h +@@ -282,6 +282,7 @@ struct vm_region { + unsigned long vm_top; /* region allocated to here */ + unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */ + struct file *vm_file; /* the backing file or NULL */ ++ struct file *vm_prfile; /* the virtual backing file or NULL */ + + int vm_usage; /* region usage count (access under nommu_region_sem) */ + bool vm_icache_flushed : 1; /* true if the icache has been flushed for +@@ -361,6 +362,7 @@ struct vm_area_struct { + unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE + units */ + struct file * vm_file; /* File we map to (can be NULL). */ ++ struct file *vm_prfile; /* shadow of vm_file */ + void * vm_private_data; /* was vm_pte (shared mem) */ + + #ifdef CONFIG_SWAP +diff --git a/kernel/fork.c b/kernel/fork.c +index e465903abed9e..d1f00eaf675af 100644 +--- a/kernel/fork.c ++++ b/kernel/fork.c +@@ -554,7 +554,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, + struct inode *inode = file_inode(file); + struct address_space *mapping = file->f_mapping; + +- get_file(file); ++ vma_get_file(tmp); + if (tmp->vm_flags & VM_DENYWRITE) + put_write_access(inode); + i_mmap_lock_write(mapping); +diff --git a/mm/Makefile b/mm/Makefile +index d73aed0fc99c1..93076a66ad6a5 100644 +--- a/mm/Makefile ++++ b/mm/Makefile +@@ -52,7 +52,7 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \ + mm_init.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 +diff --git a/mm/filemap.c b/mm/filemap.c +index 125b69f59caad..00bfb23c599fd 100644 +--- a/mm/filemap.c ++++ b/mm/filemap.c +@@ -2913,7 +2913,7 @@ vm_fault_t filemap_page_mkwrite(struct vm_fault *vmf) + vm_fault_t ret = VM_FAULT_LOCKED; + + sb_start_pagefault(inode->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); +diff --git a/mm/mmap.c b/mm/mmap.c +index 5c8b4485860de..59f2f758d77e5 100644 +--- a/mm/mmap.c ++++ b/mm/mmap.c +@@ -179,7 +179,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma) + if (vma->vm_ops && vma->vm_ops->close) + vma->vm_ops->close(vma); + if (vma->vm_file) +- fput(vma->vm_file); ++ vma_fput(vma); + mpol_put(vma_policy(vma)); + vm_area_free(vma); + return next; +@@ -951,7 +951,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 (next->anon_vma) + anon_vma_merge(vma, next); +@@ -1897,8 +1897,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); +@@ -2757,7 +2757,7 @@ int __split_vma(struct mm_struct *mm, 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); +@@ -2776,7 +2776,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)); +@@ -2969,7 +2969,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, + struct vm_area_struct *vma; + unsigned long populate = 0; + unsigned long ret = -EINVAL; +- struct file *file; ++ struct file *file, *prfile; + + pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/vm/remap_file_pages.rst.\n", + current->comm, current->pid); +@@ -3044,10 +3044,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, + } + } + +- file = get_file(vma->vm_file); ++ vma_get_file(vma); ++ file = vma->vm_file; ++ prfile = vma->vm_prfile; + 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) ++ get_file(prfile); ++ } ++ /* ++ * two fput()s instead of vma_fput(vma), ++ * coz vma may not be available anymore. ++ */ + fput(file); ++ if (prfile) ++ fput(prfile); + out: + mmap_write_unlock(mm); + if (populate) +@@ -3334,7 +3351,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); + vma_link(mm, new_vma, prev, rb_link, rb_parent); +diff --git a/mm/nommu.c b/mm/nommu.c +index 0faf39b32cdb9..78ecad7204c86 100644 +--- a/mm/nommu.c ++++ b/mm/nommu.c +@@ -533,7 +533,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 */ +@@ -665,7 +665,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); + } +@@ -1188,7 +1188,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; +@@ -1265,10 +1265,10 @@ unsigned long do_mmap(struct file *file, + up_write(&nommu_region_sem); + error: + 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 0000000000000..511543ab1b418 +--- /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-2021 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/aufs5-standalone.patch b/aufs5-standalone.patch new file mode 100644 index 00000000..a1c82db9 --- /dev/null +++ b/aufs5-standalone.patch @@ -0,0 +1,272 @@ +SPDX-License-Identifier: GPL-2.0 +aufs5.10.82 standalone patch + +diff --git a/fs/dcache.c b/fs/dcache.c +index ddca6240e0db4..30dec552278dc 100644 +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -1390,6 +1390,7 @@ void d_walk(struct dentry *parent, void *data, + seq = 1; + goto again; + } ++EXPORT_SYMBOL_GPL(d_walk); + + struct check_mount { + struct vfsmount *mnt; +@@ -2935,6 +2936,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 ca89e0e3ef10f..666565bb411f6 100644 +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -113,6 +113,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 7cd57fb4e8646..96bc0e48b7467 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 709ada3151da5..27a3e3c9f2a82 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. +@@ -376,6 +377,7 @@ void __fput_sync(struct file *file) + } + + EXPORT_SYMBOL(fput); ++EXPORT_SYMBOL_GPL(__fput_sync); + + void __init files_init(void) + { +diff --git a/fs/namespace.c b/fs/namespace.c +index a256f0f9c6c09..5d6b3e723e913 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 +@@ -797,6 +798,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 +@@ -1998,6 +2000,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 a4a4b1c64d32a..86dc2efb1850c 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 3aaaad47d9cac..60ae17e35e125 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 75f764b434184..7582bb3fb634b 100644 +--- a/fs/read_write.c ++++ b/fs/read_write.c +@@ -503,6 +503,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) + { +@@ -613,6 +614,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 55b5356262085..c13ac0fbac318 100644 +--- a/fs/splice.c ++++ b/fs/splice.c +@@ -763,6 +763,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); + + /* + * Attempt to initiate a splice from a file to a pipe. +@@ -787,6 +788,7 @@ long do_splice_to(struct file *in, loff_t *ppos, + return warn_unsupported(in, "read"); + return in->f_op->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 b7b5a0a0df6ff..fa5c7fba7f1ba 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 cd7a563e8bcd4..7d989d57b0f0d 100644 +--- a/fs/xattr.c ++++ b/fs/xattr.c +@@ -360,6 +360,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 4550f7a021178..efc579b9a36d9 100644 +--- a/kernel/locking/lockdep.c ++++ b/kernel/locking/lockdep.c +@@ -209,6 +209,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 8d6e1217c451c..0e73637adda86 100644 +--- a/kernel/task_work.c ++++ b/kernel/task_work.c +@@ -154,3 +154,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 a864ff824dd3b..d919d763ade5a 100644 +--- a/security/security.c ++++ b/security/security.c +@@ -1094,6 +1094,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) + { +@@ -1110,6 +1111,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) +@@ -1118,6 +1120,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, +@@ -1145,6 +1148,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) + { +@@ -1152,6 +1156,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) + { +@@ -1159,6 +1164,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) + { +@@ -1259,6 +1265,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) + { +@@ -1451,6 +1458,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) + { diff --git a/include/uapi/linux/aufs_type.h b/include/uapi/linux/aufs_type.h index be97db75..1acea04b 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 "5.10.82" +#define AUFS_VERSION "5.10.82-20211129" /* 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..403234c1 --- /dev/null +++ b/lockdep-debug.patch @@ -0,0 +1,34 @@ +SPDX-License-Identifier: GPL-2.0 +aufs5.10.82 lockdep patch + +diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h +index 7888c04c3ffaf..f7724de6cbfb9 100644 +--- a/include/linux/lockdep.h ++++ b/include/linux/lockdep.h +diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c +index efc579b9a36d9..6f4fcbbe3b389 100644 +--- a/kernel/locking/lockdep.c ++++ b/kernel/locking/lockdep.c +diff --git a/kernel/locking/lockdep_internals.h b/kernel/locking/lockdep_internals.h +index de49f9e1c11ba..df5b79a3122b9 100644 +--- a/kernel/locking/lockdep_internals.h ++++ b/kernel/locking/lockdep_internals.h +@@ -99,15 +99,15 @@ static const unsigned long LOCKF_USED_IN_IRQ_READ = + #define MAX_STACK_TRACE_ENTRIES 262144UL + #define STACK_TRACE_HASH_SIZE 8192 + #else +-#define MAX_LOCKDEP_ENTRIES 32768UL ++#define MAX_LOCKDEP_ENTRIES (32768UL << 5) + +-#define MAX_LOCKDEP_CHAINS_BITS 16 ++#define MAX_LOCKDEP_CHAINS_BITS (16 + 5) + + /* + * Stack-trace: tightly packed array of stack backtrace + * addresses. Protected by the hash_lock. + */ +-#define MAX_STACK_TRACE_ENTRIES 524288UL ++#define MAX_STACK_TRACE_ENTRIES (524288UL << 5) + #define STACK_TRACE_HASH_SIZE 16384 + #endif + diff --git a/tmpfs-idr.patch b/tmpfs-idr.patch new file mode 100644 index 00000000..9fd347b2 --- /dev/null +++ b/tmpfs-idr.patch @@ -0,0 +1,229 @@ +SPDX-License-Identifier: GPL-2.0 + +diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h +index a5a5d1d4d7b1..390c6fc194a9 100644 +--- a/include/linux/shmem_fs.h ++++ b/include/linux/shmem_fs.h +@@ -27,10 +27,13 @@ struct shmem_inode_info { + }; + + 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_inodes; /* How many are left for allocation */ ++ int max_inodes; /* How many inodes are allowed */ ++ int free_inodes; /* How many are left for allocation */ + 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 ae8adca3b56d..225b665f2b75 100644 +--- a/mm/shmem.c ++++ b/mm/shmem.c +@@ -109,7 +109,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; +@@ -129,11 +129,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 min(nr_pages - totalhigh_pages(), nr_pages / 2); ++ ul = INT_MAX; ++ ul = min3(ul, nr_pages - totalhigh_pages(), nr_pages / 2); ++ return ul; + } + #endif + +@@ -1178,6 +1181,11 @@ static void shmem_evict_inode(struct inode *inode) + + simple_xattrs_free(&info->xattrs); + WARN_ON(inode->i_blocks); ++ 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); + clear_inode(inode); + } +@@ -2288,7 +2296,6 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode + + inode = new_inode(sb); + if (inode) { +- inode->i_ino = ino; + inode_init_owner(inode, dir, mode); + inode->i_blocks = 0; + inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); +@@ -2332,6 +2339,25 @@ static struct inode *shmem_get_inode(struct super_block *sb, const struct inode + 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); + } else + shmem_free_inode(sb); +@@ -3335,8 +3361,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; + } + +@@ -3356,14 +3381,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); +@@ -3375,30 +3397,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; + } + +@@ -3477,7 +3484,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) ++ if (*rest || ctx->inodes < 2) + goto bad_value; + ctx->seen |= SHMEM_SEEN_INODES; + break; +@@ -3587,7 +3594,7 @@ static int shmem_reconfigure(struct fs_context *fc) + { + struct shmem_options *ctx = fc->fs_private; + struct shmem_sb_info *sbinfo = SHMEM_SB(fc->root->d_sb); +- unsigned long inodes; ++ int inodes; + const char *err; + + spin_lock(&sbinfo->stat_lock); +@@ -3654,7 +3661,7 @@ static int shmem_show_options(struct seq_file *seq, struct dentry *root) + seq_printf(seq, ",size=%luk", + sbinfo->max_blocks << (PAGE_SHIFT - 10)); + 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)) +@@ -3701,6 +3708,8 @@ static void shmem_put_super(struct super_block *sb) + { + struct shmem_sb_info *sbinfo = SHMEM_SB(sb); + ++ if (!sbinfo->idr_nouse) ++ idr_destroy(&sbinfo->idr); + free_percpu(sbinfo->ino_batch); + percpu_counter_destroy(&sbinfo->used_blocks); + mpol_put(sbinfo->mpol); +@@ -3744,6 +3753,8 @@ 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->free_inodes = sbinfo->max_inodes = ctx->inodes; + if (sb->s_flags & SB_KERNMOUNT) { +@@ -3861,6 +3872,15 @@ static void shmem_destroy_inodecache(void) + kmem_cache_destroy(shmem_inode_cachep); + } + ++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, + .set_page_dirty = __set_page_dirty_no_writeback, +@@ -4001,6 +4021,7 @@ int __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..9f2a6c83 --- /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 638d5d5bf42d..7319d98ddb47 100644 +--- a/fs/inode.c ++++ b/fs/inode.c +@@ -896,6 +896,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; +@@ -908,7 +910,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;