X-Git-Url: http://git.pld-linux.org/?a=blobdiff_plain;f=kernel-aufs5.patch;h=da23015a029da3de3b674caf2d603c06a3529f3c;hb=ecfb01fb9899ec9dc82a19355c0c02aa2994c9f9;hp=b096fed5cdd4f9920829a8ac424f8dccdf57bf8c;hpb=f9d788410a3a9f1306c97fd2b3ecd123112284e4;p=packages%2Fkernel.git diff --git a/kernel-aufs5.patch b/kernel-aufs5.patch index b096fed5..da23015a 100644 --- a/kernel-aufs5.patch +++ b/kernel-aufs5.patch @@ -1,59 +1,59 @@ SPDX-License-Identifier: GPL-2.0 -aufs5.x-rcN kbuild patch +aufs5.15.41 kbuild patch diff --git a/fs/Kconfig b/fs/Kconfig -index bfb1c6095c7a..bddba5bb307e 100644 +index a6313a969bc5..aca4b89d41a1 100644 --- a/fs/Kconfig +++ b/fs/Kconfig -@@ -261,6 +261,7 @@ source "fs/romfs/Kconfig" - source "fs/pstore/Kconfig" - source "fs/sysv/Kconfig" +@@ -312,6 +312,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 d60089fd689b..924c16a40b00 100644 +index 84c5e4cdfee5..b4fcdad8412e 100644 --- a/fs/Makefile +++ b/fs/Makefile -@@ -130,3 +130,4 @@ obj-$(CONFIG_F2FS_FS) += f2fs/ - obj-$(CONFIG_CEPH_FS) += ceph/ - obj-$(CONFIG_PSTORE) += pstore/ - obj-$(CONFIG_EFIVAR_FS) += efivarfs/ +@@ -138,3 +138,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/ SPDX-License-Identifier: GPL-2.0 -aufs5.x-rcN base patch +aufs5.15.41 base patch diff --git a/MAINTAINERS b/MAINTAINERS -index a50e97a63bc8..bd7c76319a85 100644 +index c8103e57a70b..e1b9eaca78fd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -2822,6 +2822,19 @@ F: include/linux/audit.h - F: include/uapi/linux/audit.h +@@ -3122,6 +3122,19 @@ F: include/uapi/linux/audit.h F: kernel/audit* + F: lib/*audit.c +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 -+S: Supported -+F: Documentation/filesystems/aufs/ +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 + M: Miguel Ojeda S: Maintained diff --git a/drivers/block/loop.c b/drivers/block/loop.c -index ab7ca5989097..80d06084b043 100644 +index 8cba10aafadb..7a9e40b97831 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c -@@ -738,6 +738,24 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, +@@ -799,6 +799,24 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, return error; } @@ -79,10 +79,10 @@ index ab7ca5989097..80d06084b043 100644 static ssize_t loop_attr_show(struct device *dev, char *page, diff --git a/fs/dcache.c b/fs/dcache.c -index e88cf0554e65..7ce4ccf5a51c 100644 +index cf871a81f4fd..bc5095b734f5 100644 --- a/fs/dcache.c +++ b/fs/dcache.c -@@ -1264,7 +1264,7 @@ enum d_walk_ret { +@@ -1320,7 +1320,7 @@ enum d_walk_ret { * * The @enter() callbacks are called with d_lock held. */ @@ -92,19 +92,19 @@ index e88cf0554e65..7ce4ccf5a51c 100644 { struct dentry *this_parent; diff --git a/fs/fcntl.c b/fs/fcntl.c -index 3d40771e8e7c..d62303c5472a 100644 +index 9c6c6a3e2de5..02382fa9bd34 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c -@@ -32,7 +32,7 @@ +@@ -33,7 +33,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) ++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) +@@ -64,6 +64,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); @@ -113,24 +113,11 @@ index 3d40771e8e7c..d62303c5472a 100644 if (error) return error; -diff --git a/fs/inode.c b/fs/inode.c -index 0f1e3b563c47..43df8452f97d 100644 ---- a/fs/inode.c -+++ b/fs/inode.c -@@ -1670,7 +1670,7 @@ EXPORT_SYMBOL(generic_update_time); - * This does the actual work of updating an inodes time or version. Must have - * had called mnt_want_write() before calling this. - */ --static int update_time(struct inode *inode, struct timespec64 *time, int flags) -+int update_time(struct inode *inode, struct timespec64 *time, int flags) - { - int (*update_time)(struct inode *, struct timespec64 *, int); - diff --git a/fs/namespace.c b/fs/namespace.c -index d28d30b13043..34c8093ddb1d 100644 +index b696543adab8..c45740054bc7 100644 --- a/fs/namespace.c +++ b/fs/namespace.c -@@ -776,6 +776,12 @@ static inline int check_mnt(struct mount *mnt) +@@ -808,6 +808,12 @@ static inline int check_mnt(struct mount *mnt) return mnt->mnt_ns == current->nsproxy->mnt_ns; } @@ -143,44 +130,11 @@ index d28d30b13043..34c8093ddb1d 100644 /* * vfsmount lock must be held for write */ -diff --git a/fs/read_write.c b/fs/read_write.c -index 5bbf587f5bc1..3265bb84f152 100644 ---- a/fs/read_write.c -+++ b/fs/read_write.c -@@ -498,6 +498,28 @@ static ssize_t __vfs_write(struct file *file, const char __user *p, - return -EINVAL; - } - -+vfs_readf_t vfs_readf(struct file *file) -+{ -+ const struct file_operations *fop = file->f_op; -+ -+ if (fop->read) -+ return fop->read; -+ if (fop->read_iter) -+ return new_sync_read; -+ return ERR_PTR(-ENOSYS); -+} -+ -+vfs_writef_t vfs_writef(struct file *file) -+{ -+ const struct file_operations *fop = file->f_op; -+ -+ if (fop->write) -+ return fop->write; -+ if (fop->write_iter) -+ return new_sync_write; -+ return ERR_PTR(-ENOSYS); -+} -+ - ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos) - { - mm_segment_t old_fs; diff --git a/fs/splice.c b/fs/splice.c -index 98412721f056..75b489fcb66f 100644 +index 5dbce4dcc1a7..3e6ba363b777 100644 --- a/fs/splice.c +++ b/fs/splice.c -@@ -834,8 +834,8 @@ EXPORT_SYMBOL(generic_splice_sendpage); +@@ -759,8 +759,8 @@ static int warn_unsupported(struct file *file, const char *op) /* * Attempt to initiate a splice from pipe to file. */ @@ -189,9 +143,9 @@ index 98412721f056..75b489fcb66f 100644 +long do_splice_from(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags) { - ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, - loff_t *, size_t, unsigned int); -@@ -851,9 +851,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, + if (unlikely(!out->f_op->splice_write)) + return warn_unsupported(out, "write"); +@@ -770,9 +770,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. */ @@ -202,34 +156,21 @@ index 98412721f056..75b489fcb66f 100644 + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) { - ssize_t (*splice_read)(struct file *, loff_t *, - struct pipe_inode_info *, size_t, unsigned int); -diff --git a/fs/sync.c b/fs/sync.c -index 4d1ff010bc5a..457f4e4a5cc1 100644 ---- a/fs/sync.c -+++ b/fs/sync.c -@@ -28,7 +28,7 @@ - * wait == 1 case since in that case write_inode() functions do - * sync_dirty_buffer() and thus effectively write one block at a time. - */ --static int __sync_filesystem(struct super_block *sb, int wait) -+int __sync_filesystem(struct super_block *sb, int wait) - { - if (wait) - sync_inodes_sb(sb); + unsigned int p_space; + int ret; diff --git a/include/linux/fs.h b/include/linux/fs.h -index 997a530ff4e9..3dbec51c2037 100644 +index 56eba723477e..e60d8ad85400 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h -@@ -1331,6 +1331,7 @@ extern void fasync_free(struct fasync_struct *); +@@ -1381,6 +1381,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 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); -@@ -1810,6 +1811,7 @@ struct file_operations { +@@ -2092,6 +2093,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); @@ -237,20 +178,7 @@ index 997a530ff4e9..3dbec51c2037 100644 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); -@@ -1880,6 +1882,12 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, - struct iovec *fast_pointer, - struct iovec **ret_pointer); - -+typedef ssize_t (*vfs_readf_t)(struct file *, char __user *, size_t, loff_t *); -+typedef ssize_t (*vfs_writef_t)(struct file *, const char __user *, size_t, -+ loff_t *); -+vfs_readf_t vfs_readf(struct file *file); -+vfs_writef_t vfs_writef(struct file *file); -+ - extern ssize_t __vfs_read(struct file *, char __user *, size_t, loff_t *); - extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *); - extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *); -@@ -2298,6 +2306,7 @@ extern int current_umask(void); +@@ -2615,6 +2617,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); @@ -258,19 +186,19 @@ index 997a530ff4e9..3dbec51c2037 100644 /* /sys/fs */ extern struct kobject *fs_kobj; -@@ -2586,6 +2595,7 @@ static inline bool sb_is_blkdev_sb(struct super_block *sb) - return false; +@@ -2778,6 +2781,7 @@ static inline bool sb_is_blkdev_sb(struct super_block *sb) } - #endif + + 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 0b0d7259276d..12d18e180348 100644 +index 9fe165beb0f9..e47f7e15eeaf 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h -@@ -334,6 +334,8 @@ static inline int lockdep_match_key(struct lockdep_map *lock, +@@ -248,6 +248,8 @@ static inline int lockdep_match_key(struct lockdep_map *lock, return lock->key == key; } @@ -279,27 +207,20 @@ index 0b0d7259276d..12d18e180348 100644 /* * Acquire a lock. * -@@ -476,6 +478,7 @@ struct lockdep_map { }; - - #define lockdep_depth(tsk) (0) - -+#define lockdep_is_held(lock) (1) - #define lockdep_is_held_type(l, r) (1) - - #define lockdep_assert_held(l) do { (void)(l); } while (0) diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h -index 35942084cd40..24f5fd1a789d 100644 +index 8f882f5881e8..6b9808f09843 100644 --- a/include/linux/mnt_namespace.h +++ b/include/linux/mnt_namespace.h -@@ -6,11 +6,14 @@ - struct mnt_namespace; +@@ -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); + @@ -307,10 +228,10 @@ index 35942084cd40..24f5fd1a789d 100644 extern const struct file_operations proc_mountinfo_operations; extern const struct file_operations proc_mountstats_operations; diff --git a/include/linux/splice.h b/include/linux/splice.h -index 74b4911ac16d..19789fbea567 100644 +index a55179fd60fc..8e21c53cf883 100644 --- a/include/linux/splice.h +++ b/include/linux/splice.h -@@ -87,4 +87,10 @@ extern void splice_shrink_spd(struct splice_pipe_desc *); +@@ -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; @@ -322,19 +243,19 @@ index 74b4911ac16d..19789fbea567 100644 + unsigned int flags); #endif diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c -index 4861cf8e274b..ec87ccf82025 100644 +index a30702b847ba..ce380d0abdf0 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c -@@ -153,7 +153,7 @@ static +@@ -187,7 +187,7 @@ unsigned long max_lock_class_idx; struct lock_class lock_classes[MAX_LOCKDEP_KEYS]; - static DECLARE_BITMAP(lock_classes_in_use, 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; -@@ -174,6 +174,7 @@ static inline struct lock_class *hlock_class(struct held_lock *hlock) +@@ -208,6 +208,7 @@ static inline struct lock_class *hlock_class(struct held_lock *hlock) */ return lock_classes + class_idx; } @@ -343,13 +264,13 @@ index 4861cf8e274b..ec87ccf82025 100644 #ifdef CONFIG_LOCK_STAT static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], cpu_lock_stats); SPDX-License-Identifier: GPL-2.0 -aufs5.x-rcN mmap patch +aufs5.15.41 mmap patch diff --git a/fs/proc/base.c b/fs/proc/base.c -index ebea9501afb8..dc7edc5f7267 100644 +index 1f394095eb88..93f2479ef319 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c -@@ -2037,7 +2037,7 @@ static int map_files_get_link(struct dentry *dentry, struct path *path) +@@ -2189,7 +2189,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) { @@ -359,10 +280,10 @@ index ebea9501afb8..dc7edc5f7267 100644 rc = 0; } diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c -index 14c2badb8fd9..65afe5287e43 100644 +index 13452b32e2bd..38acccfef9d4 100644 --- a/fs/proc/nommu.c +++ b/fs/proc/nommu.c -@@ -41,7 +41,10 @@ static int nommu_region_show(struct seq_file *m, struct vm_region *region) +@@ -40,7 +40,10 @@ static int nommu_region_show(struct seq_file *m, struct vm_region *region) file = region->vm_file; if (file) { @@ -375,10 +296,10 @@ index 14c2badb8fd9..65afe5287e43 100644 ino = inode->i_ino; } diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c -index 731642e0f5a0..e8d6259de65b 100644 +index 79ca4d69dfd6..3d3067c8d868 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c -@@ -309,7 +309,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma) +@@ -280,7 +280,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma) const char *name = NULL; if (file) { @@ -390,17 +311,17 @@ index 731642e0f5a0..e8d6259de65b 100644 dev = inode->i_sb->s_dev; ino = inode->i_ino; pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT; -@@ -1807,7 +1810,7 @@ static int show_numa_map(struct seq_file *m, void *v) +@@ -1888,7 +1891,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 mm_walk walk = { - .hugetlb_entry = gather_hugetlb_stats, + struct mempolicy *pol; + char buffer[64]; diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c -index 7907e6419e57..d17209cf52bc 100644 +index a6d21fc0033c..02c2de31196e 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) @@ -416,13 +337,14 @@ index 7907e6419e57..d17209cf52bc 100644 ino = inode->i_ino; pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT; diff --git a/include/linux/mm.h b/include/linux/mm.h -index 0334ca97c584..3bdae823daee 100644 +index 04345ff97f8c..4ab9bb75c894 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h -@@ -1538,6 +1538,28 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping, +@@ -1813,6 +1813,43 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping, unmap_mapping_range(mapping, holebegin, holelen, 0); } ++#if 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); @@ -444,74 +366,88 @@ index 0334ca97c584..3bdae823daee 100644 + __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 6a7a1083b6fb..461db8843e32 100644 +index 7f8ee09c711f..8fea872e08f7 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h -@@ -262,6 +262,7 @@ struct vm_region { +@@ -294,6 +294,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 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 -@@ -336,6 +337,7 @@ struct vm_area_struct { +@@ -373,6 +376,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 IS_ENABLED(CONFIG_AUFS_FS) + struct file *vm_prfile; /* shadow of vm_file */ ++#endif void * vm_private_data; /* was vm_pte (shared mem) */ #ifdef CONFIG_SWAP diff --git a/kernel/fork.c b/kernel/fork.c -index 541fd805fb88..3208fcf3b3c9 100644 +index 89475c994ca9..82f46f8f4090 100644 --- a/kernel/fork.c +++ b/kernel/fork.c -@@ -553,7 +553,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, - struct inode *inode = file_inode(file); +@@ -573,7 +573,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, + if (file) { struct address_space *mapping = file->f_mapping; - get_file(file); + vma_get_file(tmp); - if (tmp->vm_flags & VM_DENYWRITE) - atomic_dec(&inode->i_writecount); i_mmap_lock_write(mapping); + if (tmp->vm_flags & VM_SHARED) + mapping_allow_writable(mapping); diff --git a/mm/Makefile b/mm/Makefile -index d0b295c3b764..6156cd3d1ab0 100644 +index fc60a40ce954..d45773672730 100644 --- a/mm/Makefile +++ b/mm/Makefile -@@ -39,7 +39,7 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \ - mm_init.o mmu_context.o percpu.o slab_common.o \ - compaction.o vmacache.o \ - interval_tree.o list_lru.o workingset.o \ -- debug.o gup.o $(mmu-y) -+ prfile.o debug.o gup.o $(mmu-y) - - # Give 'page_alloc' its own module-parameter namespace - page-alloc-y := page_alloc.o +@@ -130,3 +130,4 @@ obj-$(CONFIG_PAGE_REPORTING) += page_reporting.o + obj-$(CONFIG_IO_MAPPING) += io-mapping.o + obj-$(CONFIG_HAVE_BOOTMEM_INFO_NODE) += bootmem_info.o + obj-$(CONFIG_GENERIC_IOREMAP) += ioremap.o ++obj-$(CONFIG_AUFS_FS:m=y) += prfile.o diff --git a/mm/filemap.c b/mm/filemap.c -index d0cf700bf201..5cac93e7bf67 100644 +index 00e391e75880..d8b52d814319 100644 --- a/mm/filemap.c +++ b/mm/filemap.c -@@ -2721,7 +2721,7 @@ vm_fault_t filemap_page_mkwrite(struct vm_fault *vmf) +@@ -3353,7 +3353,7 @@ vm_fault_t filemap_page_mkwrite(struct vm_fault *vmf) vm_fault_t ret = VM_FAULT_LOCKED; - sb_start_pagefault(inode->i_sb); + sb_start_pagefault(mapping->host->i_sb); - file_update_time(vmf->vma->vm_file); + vma_file_update_time(vmf->vma); lock_page(page); - if (page->mapping != inode->i_mapping) { + if (page->mapping != mapping) { unlock_page(page); diff --git a/mm/mmap.c b/mm/mmap.c -index 7e8c3e8ae75f..d8a903f61262 100644 +index 6bb553ed5c55..3f9d6d155171 100644 --- a/mm/mmap.c +++ b/mm/mmap.c -@@ -182,7 +182,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma) +@@ -183,7 +183,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) @@ -520,7 +456,7 @@ index 7e8c3e8ae75f..d8a903f61262 100644 mpol_put(vma_policy(vma)); vm_area_free(vma); return next; -@@ -931,7 +931,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, +@@ -952,7 +952,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); @@ -529,17 +465,16 @@ index 7e8c3e8ae75f..d8a903f61262 100644 } if (next->anon_vma) anon_vma_merge(vma, next); -@@ -1847,8 +1847,8 @@ unsigned long mmap_region(struct file *file, unsigned long addr, - return addr; - +@@ -1880,7 +1880,7 @@ close_and_free_vma: + if (vma->vm_ops && vma->vm_ops->close) + vma->vm_ops->close(vma); unmap_and_free_vma: -+ vma_fput(vma); +- fput(vma->vm_file); ++ 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); -@@ -2680,7 +2680,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -2723,7 +2723,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, goto out_free_mpol; if (new->vm_file) @@ -548,7 +483,7 @@ index 7e8c3e8ae75f..d8a903f61262 100644 if (new->vm_ops && new->vm_ops->open) new->vm_ops->open(new); -@@ -2699,7 +2699,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -2742,7 +2742,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) @@ -557,25 +492,26 @@ index 7e8c3e8ae75f..d8a903f61262 100644 unlink_anon_vmas(new); out_free_mpol: mpol_put(vma_policy(new)); -@@ -2890,7 +2890,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, - struct vm_area_struct *vma; +@@ -2938,6 +2938,9 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, unsigned long populate = 0; unsigned long ret = -EINVAL; -- struct file *file; -+ struct file *file, *prfile; + struct file *file; ++#if IS_ENABLED(CONFIG_AUFS_FS) ++ struct file *prfile; ++#endif pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/vm/remap_file_pages.rst.\n", current->comm, current->pid); -@@ -2965,10 +2965,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, - } - } +@@ -2993,10 +2996,34 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, + if (vma->vm_flags & VM_LOCKED) + flags |= MAP_LOCKED; -- file = get_file(vma->vm_file); ++#if IS_ENABLED(CONFIG_AUFS_FS) + vma_get_file(vma); + file = vma->vm_file; + prfile = vma->vm_prfile; - ret = do_mmap_pgoff(vma->vm_file, start, size, - prot, flags, pgoff, &populate, NULL); ++ ret = do_mmap(vma->vm_file, start, size, ++ prot, flags, pgoff, &populate, NULL); + if (!IS_ERR_VALUE(ret) && file && prfile) { + struct vm_area_struct *new_vma; + @@ -589,13 +525,19 @@ index 7e8c3e8ae75f..d8a903f61262 100644 + * two fput()s instead of vma_fput(vma), + * coz vma may not be available anymore. + */ - fput(file); ++ fput(file); + if (prfile) + fput(prfile); ++#else + file = get_file(vma->vm_file); + ret = do_mmap(vma->vm_file, start, size, + prot, flags, pgoff, &populate, NULL); + fput(file); ++#endif /* CONFIG_AUFS_FS */ out: - up_write(&mm->mmap_sem); + mmap_write_unlock(mm); if (populate) -@@ -3258,7 +3275,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, +@@ -3277,7 +3304,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) @@ -605,10 +547,10 @@ index 7e8c3e8ae75f..d8a903f61262 100644 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 fed1b6e9c89b..0d43b248ed54 100644 +index 02d2427b8f9e..a7419302ab4e 100644 --- a/mm/nommu.c +++ b/mm/nommu.c -@@ -552,7 +552,7 @@ static void __put_nommu_region(struct vm_region *region) +@@ -523,7 +523,7 @@ static void __put_nommu_region(struct vm_region *region) up_write(&nommu_region_sem); if (region->vm_file) @@ -617,7 +559,7 @@ index fed1b6e9c89b..0d43b248ed54 100644 /* IO memory and memory shared directly out of the pagecache * from ramfs/tmpfs mustn't be released here */ -@@ -690,7 +690,7 @@ static void delete_vma(struct mm_struct *mm, struct vm_area_struct *vma) +@@ -655,7 +655,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) @@ -626,7 +568,7 @@ index fed1b6e9c89b..0d43b248ed54 100644 put_nommu_region(vma->vm_region); vm_area_free(vma); } -@@ -1213,7 +1213,7 @@ unsigned long do_mmap(struct file *file, +@@ -1175,7 +1175,7 @@ unsigned long do_mmap(struct file *file, goto error_just_free; } } @@ -635,7 +577,7 @@ index fed1b6e9c89b..0d43b248ed54 100644 kmem_cache_free(vm_region_jar, region); region = pregion; result = start; -@@ -1290,10 +1290,10 @@ unsigned long do_mmap(struct file *file, +@@ -1252,10 +1252,10 @@ unsigned long do_mmap(struct file *file, up_write(&nommu_region_sem); error: if (region->vm_file) @@ -650,7 +592,7 @@ index fed1b6e9c89b..0d43b248ed54 100644 diff --git a/mm/prfile.c b/mm/prfile.c new file mode 100644 -index 000000000000..024cdcfae1b1 +index 000000000000..511543ab1b41 --- /dev/null +++ b/mm/prfile.c @@ -0,0 +1,86 @@ @@ -662,7 +604,7 @@ index 000000000000..024cdcfae1b1 + * + * See Documentation/filesystems/aufs/design/06mmap.txt + * -+ * Copyright (c) 2014-2019 Junjro R. Okajima ++ * Copyright (c) 2014-2021 Junjro R. Okajima + * Copyright (c) 2014 Ian Campbell + */ + @@ -741,13 +683,13 @@ index 000000000000..024cdcfae1b1 +} +#endif /* !CONFIG_MMU */ SPDX-License-Identifier: GPL-2.0 -aufs5.x-rcN standalone patch +aufs5.15.41 standalone patch diff --git a/fs/dcache.c b/fs/dcache.c -index 7ce4ccf5a51c..00d7e6a08026 100644 +index bc5095b734f5..9508bd57a3bc 100644 --- a/fs/dcache.c +++ b/fs/dcache.c -@@ -1369,6 +1369,7 @@ void d_walk(struct dentry *parent, void *data, +@@ -1425,6 +1425,7 @@ void d_walk(struct dentry *parent, void *data, seq = 1; goto again; } @@ -755,7 +697,7 @@ index 7ce4ccf5a51c..00d7e6a08026 100644 struct check_mount { struct vfsmount *mnt; -@@ -2914,6 +2915,7 @@ void d_exchange(struct dentry *dentry1, struct dentry *dentry2) +@@ -2970,6 +2971,7 @@ void d_exchange(struct dentry *dentry1, struct dentry *dentry2) write_sequnlock(&rename_lock); } @@ -764,10 +706,10 @@ index 7ce4ccf5a51c..00d7e6a08026 100644 /** * d_ancestor - search for an ancestor diff --git a/fs/exec.c b/fs/exec.c -index f7f6a140856a..1a740f3c42ba 100644 +index 29e865c59854..3ea36fa14622 100644 --- a/fs/exec.c +++ b/fs/exec.c -@@ -110,6 +110,7 @@ bool path_noexec(const struct path *path) +@@ -111,6 +111,7 @@ bool path_noexec(const struct path *path) return (path->mnt->mnt_flags & MNT_NOEXEC) || (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC); } @@ -776,10 +718,10 @@ index f7f6a140856a..1a740f3c42ba 100644 #ifdef CONFIG_USELIB /* diff --git a/fs/fcntl.c b/fs/fcntl.c -index d62303c5472a..d4ad34463848 100644 +index 02382fa9bd34..3418c60b9014 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c -@@ -85,6 +85,7 @@ int setfl(int fd, struct file * filp, unsigned long arg) +@@ -86,6 +86,7 @@ int setfl(int fd, struct file *filp, unsigned long arg) out: return error; } @@ -788,10 +730,10 @@ index d62303c5472a..d4ad34463848 100644 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 b07b53f24ff5..34b9bbf4c556 100644 +index e8c9016703ad..5e7a880830fb 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) +@@ -161,6 +161,7 @@ struct file *alloc_empty_file(int flags, const struct cred *cred) } return ERR_PTR(-ENFILE); } @@ -799,39 +741,11 @@ index b07b53f24ff5..34b9bbf4c556 100644 /* * Variant of alloc_empty_file() that doesn't check and modify nr_files. -@@ -327,6 +328,7 @@ void flush_delayed_fput(void) - { - delayed_fput(NULL); - } -+EXPORT_SYMBOL_GPL(flush_delayed_fput); - - static DECLARE_DELAYED_WORK(delayed_fput_work, delayed_fput); - -@@ -374,6 +376,7 @@ void __fput_sync(struct file *file) - } - - EXPORT_SYMBOL(fput); -+EXPORT_SYMBOL_GPL(__fput_sync); - - void __init files_init(void) - { -diff --git a/fs/inode.c b/fs/inode.c -index 43df8452f97d..8a5c14630ff0 100644 ---- a/fs/inode.c -+++ b/fs/inode.c -@@ -1679,6 +1679,7 @@ int update_time(struct inode *inode, struct timespec64 *time, int flags) - - return update_time(inode, time, flags); - } -+EXPORT_SYMBOL_GPL(update_time); - - /** - * touch_atime - update the access time diff --git a/fs/namespace.c b/fs/namespace.c -index 34c8093ddb1d..2b64af58b643 100644 +index c45740054bc7..d3d750635610 100644 --- a/fs/namespace.c +++ b/fs/namespace.c -@@ -431,6 +431,7 @@ void __mnt_drop_write(struct vfsmount *mnt) +@@ -439,6 +439,7 @@ void __mnt_drop_write(struct vfsmount *mnt) mnt_dec_writers(real_mount(mnt)); preempt_enable(); } @@ -839,7 +753,7 @@ index 34c8093ddb1d..2b64af58b643 100644 /** * mnt_drop_write - give up write access to a mount -@@ -781,6 +782,7 @@ int is_current_mnt_ns(struct vfsmount *mnt) +@@ -813,6 +814,7 @@ int is_current_mnt_ns(struct vfsmount *mnt) { return check_mnt(real_mount(mnt)); } @@ -847,7 +761,7 @@ index 34c8093ddb1d..2b64af58b643 100644 /* * vfsmount lock must be held for write -@@ -1900,6 +1902,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg, +@@ -2011,6 +2013,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg, } return 0; } @@ -856,10 +770,10 @@ index 34c8093ddb1d..2b64af58b643 100644 static void lock_mnt_tree(struct mount *mnt) { diff --git a/fs/notify/group.c b/fs/notify/group.c -index 0391190305cc..0b9f7f6d8390 100644 +index fb89c351295d..460ad19c2570 100644 --- a/fs/notify/group.c +++ b/fs/notify/group.c -@@ -99,6 +99,7 @@ void fsnotify_get_group(struct fsnotify_group *group) +@@ -100,6 +100,7 @@ void fsnotify_get_group(struct fsnotify_group *group) { refcount_inc(&group->refcnt); } @@ -867,63 +781,11 @@ index 0391190305cc..0b9f7f6d8390 100644 /* * Drop a reference to a group. Free it if it's through. -@@ -108,6 +109,7 @@ void fsnotify_put_group(struct fsnotify_group *group) - if (refcount_dec_and_test(&group->refcnt)) - fsnotify_final_destroy_group(group); - } -+EXPORT_SYMBOL_GPL(fsnotify_put_group); - - /* - * Create a new fsnotify_group and hold a reference for the group returned. -@@ -137,6 +139,7 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops) - - return group; - } -+EXPORT_SYMBOL_GPL(fsnotify_alloc_group); - - int fsnotify_fasync(int fd, struct file *file, int on) - { -diff --git a/fs/notify/mark.c b/fs/notify/mark.c -index 99ddd126f6f0..2154d69a2c7a 100644 ---- a/fs/notify/mark.c -+++ b/fs/notify/mark.c -@@ -276,6 +276,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark) - queue_delayed_work(system_unbound_wq, &reaper_work, - FSNOTIFY_REAPER_DELAY); - } -+EXPORT_SYMBOL_GPL(fsnotify_put_mark); - - /* - * Get mark reference when we found the mark via lockless traversal of object -@@ -430,6 +431,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark, - mutex_unlock(&group->mark_mutex); - fsnotify_free_mark(mark); - } -+EXPORT_SYMBOL_GPL(fsnotify_destroy_mark); - - /* - * Sorting function for lists of fsnotify marks. -@@ -685,6 +687,7 @@ int fsnotify_add_mark(struct fsnotify_mark *mark, fsnotify_connp_t *connp, - mutex_unlock(&group->mark_mutex); - return ret; - } -+EXPORT_SYMBOL_GPL(fsnotify_add_mark); - - /* - * Given a list of marks, find the mark associated with given group. If found -@@ -809,6 +812,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark, - mark->group = group; - WRITE_ONCE(mark->connector, NULL); - } -+EXPORT_SYMBOL_GPL(fsnotify_init_mark); - - /* - * Destroy all marks in destroy_list, waits for SRCU period to finish before diff --git a/fs/open.c b/fs/open.c -index a59abe3c669a..78809163ba03 100644 +index e0df1536eb69..81b2d7c83add 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, +@@ -65,6 +65,7 @@ int do_truncate(struct user_namespace *mnt_userns, struct dentry *dentry, inode_unlock(dentry->d_inode); return ret; } @@ -932,35 +794,19 @@ index a59abe3c669a..78809163ba03 100644 long vfs_truncate(const struct path *path, loff_t length) { diff --git a/fs/read_write.c b/fs/read_write.c -index 3265bb84f152..5b2dbddb0efe 100644 +index af057c57bdc6..76017f8331fb 100644 --- a/fs/read_write.c +++ b/fs/read_write.c -@@ -468,6 +468,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) - +@@ -492,6 +492,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) { -@@ -508,6 +509,7 @@ vfs_readf_t vfs_readf(struct file *file) - return new_sync_read; - return ERR_PTR(-ENOSYS); - } -+EXPORT_SYMBOL_GPL(vfs_readf); - - vfs_writef_t vfs_writef(struct file *file) - { -@@ -519,6 +521,7 @@ vfs_writef_t vfs_writef(struct file *file) - return new_sync_write; - return ERR_PTR(-ENOSYS); - } -+EXPORT_SYMBOL_GPL(vfs_writef); - - ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos) - { -@@ -588,6 +591,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_ - +@@ -602,6 +603,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); @@ -968,42 +814,30 @@ index 3265bb84f152..5b2dbddb0efe 100644 /* 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 75b489fcb66f..0a1f7498c22b 100644 +index 3e6ba363b777..7c1be373eb7c 100644 --- a/fs/splice.c +++ b/fs/splice.c -@@ -847,6 +847,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out, - - return splice_write(pipe, out, ppos, len, flags); +@@ -766,6 +766,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. -@@ -876,6 +877,7 @@ long do_splice_to(struct file *in, loff_t *ppos, - - return splice_read(in, ppos, pipe, len, flags); +@@ -795,6 +796,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 457f4e4a5cc1..67c66358f3fe 100644 ---- a/fs/sync.c -+++ b/fs/sync.c -@@ -39,6 +39,7 @@ int __sync_filesystem(struct super_block *sb, int wait) - sb->s_op->sync_fs(sb, wait); - return __sync_blockdev(sb->s_bdev, wait); - } -+EXPORT_SYMBOL_GPL(__sync_filesystem); - - /* - * Write out and wait upon all dirty data associated with this diff --git a/fs/xattr.c b/fs/xattr.c -index 90dd78f0eb27..40b01dd1b14a 100644 +index 5c8c5175b385..ff7e9ff774b7 100644 --- a/fs/xattr.c +++ b/fs/xattr.c -@@ -296,6 +296,7 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value, +@@ -384,6 +384,7 @@ vfs_getxattr_alloc(struct user_namespace *mnt_userns, struct dentry *dentry, *xattr_value = value; return error; } @@ -1012,10 +846,10 @@ index 90dd78f0eb27..40b01dd1b14a 100644 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 ec87ccf82025..739d1c8a81f5 100644 +index ce380d0abdf0..409c7d1a6803 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c -@@ -174,6 +174,7 @@ inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock) +@@ -208,6 +208,7 @@ inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock) */ return lock_classes + class_idx; } @@ -1024,28 +858,19 @@ index ec87ccf82025..739d1c8a81f5 100644 #ifdef CONFIG_LOCK_STAT diff --git a/kernel/task_work.c b/kernel/task_work.c -index 0fef395662a6..83fb1ecfc33d 100644 +index 1698fbe6f0e1..081b05acadf8 100644 --- a/kernel/task_work.c +++ b/kernel/task_work.c -@@ -116,3 +116,4 @@ void task_work_run(void) +@@ -167,3 +167,4 @@ void task_work_run(void) } while (work); } } +EXPORT_SYMBOL_GPL(task_work_run); -diff --git a/security/device_cgroup.c b/security/device_cgroup.c -index 725674f3276d..83f6494c52a2 100644 ---- a/security/device_cgroup.c -+++ b/security/device_cgroup.c -@@ -824,3 +824,4 @@ int __devcgroup_check_permission(short type, u32 major, u32 minor, - - return 0; - } -+EXPORT_SYMBOL_GPL(__devcgroup_check_permission); diff --git a/security/security.c b/security/security.c -index 250ee2d76406..2765042d4846 100644 +index da631339e969..894203de3bcb 100644 --- a/security/security.c +++ b/security/security.c -@@ -996,6 +996,7 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry) +@@ -1160,6 +1160,7 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry) return 0; return call_int_hook(path_rmdir, 0, dir, dentry); } @@ -1053,7 +878,7 @@ index 250ee2d76406..2765042d4846 100644 int security_path_unlink(const struct path *dir, struct dentry *dentry) { -@@ -1012,6 +1013,7 @@ int security_path_symlink(const struct path *dir, struct dentry *dentry, +@@ -1176,6 +1177,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); } @@ -1061,7 +886,7 @@ index 250ee2d76406..2765042d4846 100644 int security_path_link(struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry) -@@ -1020,6 +1022,7 @@ int security_path_link(struct dentry *old_dentry, const struct path *new_dir, +@@ -1184,6 +1186,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); } @@ -1069,7 +894,7 @@ index 250ee2d76406..2765042d4846 100644 int security_path_rename(const struct path *old_dir, struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry, -@@ -1047,6 +1050,7 @@ int security_path_truncate(const struct path *path) +@@ -1211,6 +1214,7 @@ int security_path_truncate(const struct path *path) return 0; return call_int_hook(path_truncate, 0, path); } @@ -1077,7 +902,7 @@ index 250ee2d76406..2765042d4846 100644 int security_path_chmod(const struct path *path, umode_t mode) { -@@ -1054,6 +1058,7 @@ int security_path_chmod(const struct path *path, umode_t mode) +@@ -1218,6 +1222,7 @@ int security_path_chmod(const struct path *path, umode_t mode) return 0; return call_int_hook(path_chmod, 0, path, mode); } @@ -1085,7 +910,7 @@ index 250ee2d76406..2765042d4846 100644 int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) { -@@ -1061,6 +1066,7 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) +@@ -1225,6 +1230,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); } @@ -1093,7 +918,7 @@ index 250ee2d76406..2765042d4846 100644 int security_path_chroot(const struct path *path) { -@@ -1161,6 +1167,7 @@ int security_inode_permission(struct inode *inode, int mask) +@@ -1325,6 +1331,7 @@ int security_inode_permission(struct inode *inode, int mask) return 0; return call_int_hook(inode_permission, 0, inode, mask); } @@ -1101,7 +926,7 @@ index 250ee2d76406..2765042d4846 100644 int security_inode_setattr(struct dentry *dentry, struct iattr *attr) { -@@ -1338,6 +1345,7 @@ int security_file_permission(struct file *file, int mask) +@@ -1522,6 +1529,7 @@ int security_file_permission(struct file *file, int mask) return fsnotify_perm(file, mask); } @@ -1111,7 +936,7 @@ index 250ee2d76406..2765042d4846 100644 { diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Documentation/ABI/testing/debugfs-aufs --- /usr/share/empty/Documentation/ABI/testing/debugfs-aufs 1970-01-01 01:00:00.000000000 +0100 -+++ linux/Documentation/ABI/testing/debugfs-aufs 2019-07-11 15:42:14.455570938 +0200 ++++ linux/Documentation/ABI/testing/debugfs-aufs 2022-10-26 22:30:38.455982192 +0200 @@ -0,0 +1,55 @@ +What: /debug/aufs/si_/ +Date: March 2009 @@ -1143,7 +968,7 @@ diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Document + When the aufs mount option 'noxino' is specified, it + will be empty. About XINO files, see the aufs manual. + -+What: /debug/aufs/si_/xi0, xi1 ... xiN and xiN-N ++What: /debug/aufs/si_/xi +Date: March 2009 +Contact: J. R. Okajima +Description: @@ -1170,7 +995,7 @@ diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Document + will be empty. About XINO files, see the aufs manual. diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentation/ABI/testing/sysfs-aufs --- /usr/share/empty/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100 -+++ linux/Documentation/ABI/testing/sysfs-aufs 2019-07-11 15:42:14.455570938 +0200 ++++ linux/Documentation/ABI/testing/sysfs-aufs 2022-10-26 22:30:38.455982192 +0200 @@ -0,0 +1,31 @@ +What: /sys/fs/aufs/si_/ +Date: March 2009 @@ -1180,14 +1005,14 @@ diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentat + per aufs mount, where is a unique id generated + internally. + -+What: /sys/fs/aufs/si_/br0, br1 ... brN ++What: /sys/fs/aufs/si_/br +Date: March 2009 +Contact: J. R. Okajima +Description: + It shows the abolute path of a member directory (which + is called branch) in aufs, and its permission. + -+What: /sys/fs/aufs/si_/brid0, brid1 ... bridN ++What: /sys/fs/aufs/si_/brid +Date: July 2013 +Contact: J. R. Okajima +Description: @@ -1205,10 +1030,10 @@ diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentat + will be empty. About XINO files, see the aufs manual. diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt linux/Documentation/filesystems/aufs/design/01intro.txt --- /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt 1970-01-01 01:00:00.000000000 +0100 -+++ linux/Documentation/filesystems/aufs/design/01intro.txt 2019-07-11 15:42:14.455570938 +0200 ++++ linux/Documentation/filesystems/aufs/design/01intro.txt 2022-10-26 22:30:38.459315526 +0200 @@ -0,0 +1,171 @@ + -+# Copyright (C) 2005-2019 Junjiro R. Okajima ++# Copyright (C) 2005-2021 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -1380,10 +1205,10 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt lin +about it. But currently I have implemented it in kernel space. diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt linux/Documentation/filesystems/aufs/design/02struct.txt --- /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt 1970-01-01 01:00:00.000000000 +0100 -+++ linux/Documentation/filesystems/aufs/design/02struct.txt 2019-07-11 15:42:14.455570938 +0200 ++++ linux/Documentation/filesystems/aufs/design/02struct.txt 2022-10-26 22:30:38.459315526 +0200 @@ -0,0 +1,258 @@ + -+# Copyright (C) 2005-2019 Junjiro R. Okajima ++# Copyright (C) 2005-2021 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -1642,10 +1467,10 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt li +For this purpose, use "aumvdown" command in aufs-util.git. diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/03atomic_open.txt linux/Documentation/filesystems/aufs/design/03atomic_open.txt --- /usr/share/empty/Documentation/filesystems/aufs/design/03atomic_open.txt 1970-01-01 01:00:00.000000000 +0100 -+++ linux/Documentation/filesystems/aufs/design/03atomic_open.txt 2019-07-11 15:42:14.458904362 +0200 ++++ linux/Documentation/filesystems/aufs/design/03atomic_open.txt 2022-10-26 22:30:38.459315526 +0200 @@ -0,0 +1,85 @@ + -+# Copyright (C) 2015-2019 Junjiro R. Okajima ++# Copyright (C) 2015-2021 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -1731,10 +1556,10 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/03atomic_open.t + be implemented in aufs, but not all I am afraid. diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt linux/Documentation/filesystems/aufs/design/03lookup.txt --- /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt 1970-01-01 01:00:00.000000000 +0100 -+++ linux/Documentation/filesystems/aufs/design/03lookup.txt 2019-07-11 15:42:14.458904362 +0200 ++++ linux/Documentation/filesystems/aufs/design/03lookup.txt 2022-10-26 22:30:38.459315526 +0200 @@ -0,0 +1,113 @@ + -+# Copyright (C) 2005-2019 Junjiro R. Okajima ++# Copyright (C) 2005-2021 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -1848,10 +1673,10 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt li + by over-mounting something (or another method). diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt linux/Documentation/filesystems/aufs/design/04branch.txt --- /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt 1970-01-01 01:00:00.000000000 +0100 -+++ linux/Documentation/filesystems/aufs/design/04branch.txt 2019-07-11 15:42:14.458904362 +0200 ++++ linux/Documentation/filesystems/aufs/design/04branch.txt 2022-10-26 22:30:38.459315526 +0200 @@ -0,0 +1,74 @@ + -+# Copyright (C) 2005-2019 Junjiro R. Okajima ++# Copyright (C) 2005-2021 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -1926,10 +1751,10 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt li + same named entry on the upper branch. diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt linux/Documentation/filesystems/aufs/design/05wbr_policy.txt --- /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt 1970-01-01 01:00:00.000000000 +0100 -+++ linux/Documentation/filesystems/aufs/design/05wbr_policy.txt 2019-07-11 15:42:14.458904362 +0200 ++++ linux/Documentation/filesystems/aufs/design/05wbr_policy.txt 2022-10-26 22:30:38.459315526 +0200 @@ -0,0 +1,64 @@ + -+# Copyright (C) 2005-2019 Junjiro R. Okajima ++# Copyright (C) 2005-2021 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -1994,7 +1819,7 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.tx + copyup policy. diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.dot linux/Documentation/filesystems/aufs/design/06dirren.dot --- /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.dot 1970-01-01 01:00:00.000000000 +0100 -+++ linux/Documentation/filesystems/aufs/design/06dirren.dot 2019-07-11 15:42:14.458904362 +0200 ++++ linux/Documentation/filesystems/aufs/design/06dirren.dot 2022-10-26 22:30:38.459315526 +0200 @@ -0,0 +1,31 @@ + +// to view this graph, run dot(1) command in GRAPHVIZ. @@ -2029,10 +1854,10 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.dot li +} diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.txt linux/Documentation/filesystems/aufs/design/06dirren.txt --- /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.txt 1970-01-01 01:00:00.000000000 +0100 -+++ linux/Documentation/filesystems/aufs/design/06dirren.txt 2019-07-11 15:42:14.458904362 +0200 ++++ linux/Documentation/filesystems/aufs/design/06dirren.txt 2022-10-26 22:30:38.459315526 +0200 @@ -0,0 +1,102 @@ + -+# Copyright (C) 2017-2019 Junjiro R. Okajima ++# Copyright (C) 2017-2021 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -2110,7 +1935,7 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.txt li +simply the inode-numbers on the branch. The file is created or updated +in removing the branch, and loaded in adding the branch. Its lifetime is +equal to the branch. -+The list is refered in lookup, and when the current target inode is ++The list is referred in lookup, and when the current target inode is +found in the list, the aufs tries loading the "detailed info per +directory" and get the changed and valid name of the dir. + @@ -2135,10 +1960,10 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.txt li +equivalen to udba=reval case. diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06fhsm.txt linux/Documentation/filesystems/aufs/design/06fhsm.txt --- /usr/share/empty/Documentation/filesystems/aufs/design/06fhsm.txt 1970-01-01 01:00:00.000000000 +0100 -+++ linux/Documentation/filesystems/aufs/design/06fhsm.txt 2019-07-11 15:42:14.458904362 +0200 ++++ linux/Documentation/filesystems/aufs/design/06fhsm.txt 2022-10-26 22:30:38.459315526 +0200 @@ -0,0 +1,120 @@ + -+# Copyright (C) 2011-2019 Junjiro R. Okajima ++# Copyright (C) 2011-2021 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -2259,10 +2084,10 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06fhsm.txt linu +should restore the original file state after an error happens. diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt linux/Documentation/filesystems/aufs/design/06mmap.txt --- /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt 1970-01-01 01:00:00.000000000 +0100 -+++ linux/Documentation/filesystems/aufs/design/06mmap.txt 2019-07-11 15:42:14.458904362 +0200 ++++ linux/Documentation/filesystems/aufs/design/06mmap.txt 2022-10-26 22:30:38.459315526 +0200 @@ -0,0 +1,72 @@ + -+# Copyright (C) 2005-2019 Junjiro R. Okajima ++# Copyright (C) 2005-2021 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -2335,10 +2160,10 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt linu +I have to give up this "looks-smater" approach. diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06xattr.txt linux/Documentation/filesystems/aufs/design/06xattr.txt --- /usr/share/empty/Documentation/filesystems/aufs/design/06xattr.txt 1970-01-01 01:00:00.000000000 +0100 -+++ linux/Documentation/filesystems/aufs/design/06xattr.txt 2019-07-11 15:42:14.458904362 +0200 ++++ linux/Documentation/filesystems/aufs/design/06xattr.txt 2022-10-26 22:30:38.459315526 +0200 @@ -0,0 +1,96 @@ + -+# Copyright (C) 2014-2019 Junjiro R. Okajima ++# Copyright (C) 2014-2021 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -2435,10 +2260,10 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06xattr.txt lin +now, aufs implements the branch attributes to ignore the error. diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt linux/Documentation/filesystems/aufs/design/07export.txt --- /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt 1970-01-01 01:00:00.000000000 +0100 -+++ linux/Documentation/filesystems/aufs/design/07export.txt 2019-07-11 15:42:14.458904362 +0200 ++++ linux/Documentation/filesystems/aufs/design/07export.txt 2022-10-26 22:30:38.459315526 +0200 @@ -0,0 +1,58 @@ + -+# Copyright (C) 2005-2019 Junjiro R. Okajima ++# Copyright (C) 2005-2021 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -2497,10 +2322,10 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt li + lookup_one_len(), vfs_getattr(), encode_fh() and others. diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt linux/Documentation/filesystems/aufs/design/08shwh.txt --- /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt 1970-01-01 01:00:00.000000000 +0100 -+++ linux/Documentation/filesystems/aufs/design/08shwh.txt 2019-07-11 15:42:14.458904362 +0200 ++++ linux/Documentation/filesystems/aufs/design/08shwh.txt 2022-10-26 22:30:38.459315526 +0200 @@ -0,0 +1,52 @@ + -+# Copyright (C) 2005-2019 Junjiro R. Okajima ++# Copyright (C) 2005-2021 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -2553,10 +2378,10 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt linu +initramfs will use it to replace the old one at the next boot. diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt linux/Documentation/filesystems/aufs/design/10dynop.txt --- /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt 1970-01-01 01:00:00.000000000 +0100 -+++ linux/Documentation/filesystems/aufs/design/10dynop.txt 2019-07-11 15:42:14.458904362 +0200 ++++ linux/Documentation/filesystems/aufs/design/10dynop.txt 2022-10-26 22:30:38.459315526 +0200 @@ -0,0 +1,47 @@ + -+# Copyright (C) 2010-2019 Junjiro R. Okajima ++# Copyright (C) 2010-2021 Junjiro R. Okajima +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by @@ -2604,8 +2429,8 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt lin +regular files only. diff -urN /usr/share/empty/Documentation/filesystems/aufs/README linux/Documentation/filesystems/aufs/README --- /usr/share/empty/Documentation/filesystems/aufs/README 1970-01-01 01:00:00.000000000 +0100 -+++ linux/Documentation/filesystems/aufs/README 2019-07-11 15:42:14.455570938 +0200 -@@ -0,0 +1,399 @@ ++++ linux/Documentation/filesystems/aufs/README 2022-10-26 22:30:38.455982192 +0200 +@@ -0,0 +1,397 @@ + +Aufs5 -- advanced multi layered unification filesystem version 5.x +http://aufs.sf.net @@ -2790,6 +2615,16 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/README linux/Documenta +For aufs5-linux tree, +- enable CONFIG_AUFS_FS. +- set other aufs configurations if necessary. ++- for aufs5.13 and later ++ Because aufs is not only an ordinary filesystem (callee of VFS), but ++ also a caller of VFS functions for branch filesystems, subclassing of ++ the internal locks for LOCKDEP is necessary. LOCKDEP is a debugging ++ feature of linux kernel. If you enable CONFIG_LOCKDEP, then you will ++ need to customize some LOCKDEP numbers. Here are what I use on my ++ test environment. ++ CONFIG_LOCKDEP_BITS=21 ++ CONFIG_LOCKDEP_CHAINS_BITS=21 ++ CONFIG_LOCKDEP_STACK_TRACE_BITS=24 + +For aufs5-standalone tree, +There are several ways to build. @@ -2857,13 +2692,6 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/README linux/Documenta + Supports a nested loopback mount in a branch-fs. This patch is + unnecessary until aufs produces a message like "you may want to try + another patch for loopback file". -+- proc_mounts.patch -+ When there are many mountpoints and many mount(2)/umount(2) are -+ running, then /proc/mounts may not show the all mountpoints. This -+ patch makes /proc/mounts always show the full mountpoints list. -+ If you don't want to apply this patch and meet such problem, then you -+ need to increase the value of 'ProcMounts_Times' make-variable in -+ aufs-util.git as a second best solution. +- vfs-ino.patch + Modifies a system global kernel internal function get_next_ino() in + order to stop assigning 0 for an inode-number. Not directly related to @@ -2874,13 +2702,6 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/README linux/Documenta + duplication of inode number, which is important for backup tools and + other utilities. When you find aufs XINO files for tmpfs branch + growing too much, try this patch. -+- lockdep-debug.patch -+ Because aufs is not only an ordinary filesystem (callee of VFS), but -+ also a caller of VFS functions for branch filesystems, subclassing of -+ the internal locks for LOCKDEP is necessary. LOCKDEP is a debugging -+ feature of linux kernel. If you enable CONFIG_LOCKDEP, then you will -+ need to apply this debug patch to expand several constant values. -+ If don't know what LOCKDEP is, then you don't have apply this patch. + + +4. Usage @@ -2930,6 +2751,7 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/README linux/Documenta + system, instead of the date you downloaded. +- configuration (define/undefine CONFIG_AUFS_xxx) +- kernel configuration or /proc/config.gz (if you have it) ++- LSM (linux security module, if you are using) +- behaviour which you think to be incorrect +- actual operation, reproducible one is better +- mailto: aufs-users at lists.sourceforge.net @@ -2980,7 +2802,7 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/README linux/Documenta +The Parted Magic Project made a donation (2013/9 and 11). +Pavel Barta made a donation (2013/10). +Nikolay Pertsev made a donation (2014/5). -+James B made a donation (2014/7 and 2015/7). ++James B made a donation (2014/7, 2015/7, and 2021/12). +Stefano Di Biase made a donation (2014/8). +Daniel Epellei made a donation (2015/1). +OmegaPhil made a donation (2016/1, 2018/4). @@ -2988,6 +2810,7 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/README linux/Documenta +James Burry made a donation (2016/12). +Carsten Rose made a donation (2018/9). +Porteus Kiosk made a donation (2018/10). ++Enya Quetzalli Gomez Rodriguez made a donation (2022/5). + +Thank you very much. +Donations are always, including future donations, very important and @@ -3007,11 +2830,11 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/README linux/Documenta +# End: ; diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h --- /usr/share/empty/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/aufs.h 2019-07-11 15:42:14.462237786 +0200 ++++ linux/fs/aufs/aufs.h 2022-10-26 22:30:38.459315526 +0200 @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -3073,11 +2896,11 @@ diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h +#endif /* __AUFS_H__ */ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c --- /usr/share/empty/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/branch.c 2019-09-16 09:38:43.216175640 +0200 -@@ -0,0 +1,1428 @@ ++++ linux/fs/aufs/branch.c 2022-10-26 22:30:38.462648858 +0200 +@@ -0,0 +1,1427 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -4356,7 +4179,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c + * file_release_write() for each file, because the branch + * attribute in aufs world is totally different from the native + * fs rw/ro mode. -+ */ ++ */ + /* fi_read_lock(file); */ + hfile = &au_fi(file)->fi_htop; + hf = hfile->hf_file; @@ -4367,11 +4190,10 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c + spin_unlock(&hf->f_lock); + if (writer) { + h_inode = file_inode(hf); ++ if (hf->f_mode & FMODE_READ) ++ i_readcount_inc(h_inode); + put_write_access(h_inode); + __mnt_drop_write(hf->f_path.mnt); -+ if ((hf->f_mode & (FMODE_READ | FMODE_WRITE)) -+ == FMODE_READ) -+ i_readcount_inc(h_inode); + } + } + @@ -4505,11 +4327,11 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c +} diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h --- /usr/share/empty/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/branch.h 2019-07-11 15:42:14.462237786 +0200 -@@ -0,0 +1,366 @@ ++++ linux/fs/aufs/branch.h 2022-10-26 22:30:38.462648858 +0200 +@@ -0,0 +1,375 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -4655,6 +4477,11 @@ diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h + return br->br_path.dentry; +} + ++static inline struct user_namespace *au_br_userns(struct au_branch *br) ++{ ++ return mnt_user_ns(br->br_path.mnt); ++} ++ +static inline struct super_block *au_br_sb(struct au_branch *br) +{ + return au_br_mnt(br)->mnt_sb; @@ -4750,10 +4577,8 @@ diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h + ino_t *ino); +int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, + ino_t ino); -+ssize_t xino_fread(vfs_readf_t func, struct file *file, void *buf, size_t size, -+ loff_t *pos); -+ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos); ++ssize_t xino_fread(struct file *file, void *buf, size_t size, loff_t *pos); ++ssize_t xino_fwrite(struct file *file, void *buf, size_t size, loff_t *pos); + +int au_xib_trunc(struct super_block *sb); +int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin); @@ -4816,6 +4641,12 @@ diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h +} + +static inline ++struct user_namespace *au_sbr_userns(struct super_block *sb, aufs_bindex_t bindex) ++{ ++ return au_br_userns(au_sbr(sb, bindex)); ++} ++ ++static inline +struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex) +{ + return au_br_sb(au_sbr(sb, bindex)); @@ -4875,7 +4706,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h +#endif /* __AUFS_BRANCH_H__ */ diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk --- /usr/share/empty/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/conf.mk 2019-07-11 15:42:14.462237786 +0200 ++++ linux/fs/aufs/conf.mk 2022-10-26 22:30:38.462648858 +0200 @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-2.0 + @@ -4919,11 +4750,11 @@ diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk +-include ${srctree}/${src}/conf_priv.mk diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c --- /usr/share/empty/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/cpup.c 2019-07-11 15:42:14.462237786 +0200 -@@ -0,0 +1,1458 @@ ++++ linux/fs/aufs/cpup.c 2022-10-26 22:30:38.462648858 +0200 +@@ -0,0 +1,1459 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -5087,7 +4918,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c +}; + +static noinline_for_stack -+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src, ++int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct path *h_src, + struct au_cpup_reg_attr *h_src_attr) +{ + int err, sbits, icex; @@ -5099,11 +4930,11 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c + struct kstat *h_st; + struct au_branch *br; + -+ h_path.dentry = au_h_dptr(dst, bindex); -+ h_idst = d_inode(h_path.dentry); + br = au_sbr(dst->d_sb, bindex); + h_path.mnt = au_br_mnt(br); -+ h_isrc = d_inode(h_src); ++ h_path.dentry = au_h_dptr(dst, bindex); ++ h_idst = d_inode(h_path.dentry); ++ h_isrc = d_inode(h_src->dentry); + ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID + | ATTR_ATIME | ATTR_MTIME + | ATTR_ATIME_SET | ATTR_MTIME_SET; @@ -5147,7 +4978,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c + if (!err) { + mnt_flags = au_mntflags(dst->d_sb); + verbose = !!au_opt_test(mnt_flags, VERBOSE); -+ err = au_cpup_xattr(h_path.dentry, h_src, icex, verbose); ++ err = au_cpup_xattr(&h_path, h_src, icex, verbose); + } + + return err; @@ -5492,32 +5323,19 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c +static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src, + struct inode *h_dir) +{ -+ int err, symlen; -+ mm_segment_t old_fs; -+ union { -+ char *k; -+ char __user *u; -+ } sym; ++ int err; ++ DEFINE_DELAYED_CALL(done); ++ const char *sym; + -+ err = -ENOMEM; -+ sym.k = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!sym.k)) ++ sym = vfs_get_link(h_src, &done); ++ err = PTR_ERR(sym); ++ if (IS_ERR(sym)) + goto out; + -+ /* unnecessary to support mmap_sem since symlink is not mmap-able */ -+ old_fs = get_fs(); -+ set_fs(KERNEL_DS); -+ symlen = vfs_readlink(h_src, sym.u, PATH_MAX); -+ err = symlen; -+ set_fs(old_fs); -+ -+ if (symlen > 0) { -+ sym.k[symlen] = 0; -+ err = vfsub_symlink(h_dir, h_path, sym.k); -+ } -+ free_page((unsigned long)sym.k); ++ err = vfsub_symlink(h_dir, h_path, sym); + +out: ++ do_delayed_call(&done); + return err; +} + @@ -5530,16 +5348,18 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c + int err; + struct dentry *h_dentry; + struct inode *h_inode; ++ struct user_namespace *h_userns; + ++ h_userns = mnt_user_ns(h_path->mnt); + h_dentry = h_path->dentry; + h_inode = d_inode(h_dentry); + /* forget_all_cached_acls(h_inode)); */ -+ err = vfsub_removexattr(h_dentry, XATTR_NAME_POSIX_ACL_ACCESS); ++ err = vfsub_removexattr(h_userns, h_dentry, XATTR_NAME_POSIX_ACL_ACCESS); + AuTraceErr(err); + if (err == -EOPNOTSUPP) + err = 0; + if (!err) -+ err = vfsub_acl_chmod(h_inode, mode); ++ err = vfsub_acl_chmod(h_userns, h_inode, mode); + + AuTraceErr(err); + return err; @@ -5550,8 +5370,11 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c +{ + int err; + struct inode *dir, *inode; ++ struct user_namespace *h_userns; + -+ err = vfsub_removexattr(h_path->dentry, XATTR_NAME_POSIX_ACL_DEFAULT); ++ h_userns = mnt_user_ns(h_path->mnt); ++ err = vfsub_removexattr(h_userns, h_path->dentry, ++ XATTR_NAME_POSIX_ACL_DEFAULT); + AuTraceErr(err); + if (err == -EOPNOTSUPP) + err = 0; @@ -5632,7 +5455,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c + case S_IFCHR: + case S_IFBLK: + AuDebugOn(!capable(CAP_MKNOD)); -+ /*FALLTHROUGH*/ ++ fallthrough; + case S_IFIFO: + case S_IFSOCK: + err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev); @@ -5676,11 +5499,13 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c +{ + int err; + struct dentry *dentry, *h_dentry, *h_parent, *parent; ++ struct path h_ppath; + struct inode *h_dir; + aufs_bindex_t bdst; + + dentry = cpg->dentry; + bdst = cpg->bdst; ++ h_ppath.mnt = au_sbr_mnt(dentry->d_sb, bdst); + h_dentry = au_h_dptr(dentry, bdst); + if (!au_ftest_cpup(cpg->flags, OVERWRITE)) { + dget(h_dentry); @@ -5692,9 +5517,9 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c + } else { + err = 0; + parent = dget_parent(dentry); -+ h_parent = au_h_dptr(parent, bdst); ++ h_ppath.dentry = au_h_dptr(parent, bdst); + dput(parent); -+ h_path->dentry = vfsub_lkup_one(&dentry->d_name, h_parent); ++ h_path->dentry = vfsub_lkup_one(&dentry->d_name, &h_ppath); + if (IS_ERR(h_path->dentry)) + err = PTR_ERR(h_path->dentry); + } @@ -5732,6 +5557,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c + struct inode *dst_inode, *h_dir, *inode, *delegated, *src_inode; + struct super_block *sb; + struct au_branch *br; ++ struct path h_src_path; + /* to reduce stack size */ + struct { + struct au_dtime dt; @@ -5823,7 +5649,9 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c + /* todo: necessary? */ + /* au_pin_hdir_unlock(cpg->pin); */ + -+ err = cpup_iattr(cpg->dentry, cpg->bdst, h_src, &a->h_src_attr); ++ h_src_path.dentry = h_src; ++ h_src_path.mnt = au_sbr_mnt(sb, cpg->bsrc); ++ err = cpup_iattr(cpg->dentry, cpg->bdst, &h_src_path, &a->h_src_attr); + if (unlikely(err)) { + /* todo: necessary? */ + /* au_pin_hdir_relock(cpg->pin); */ /* ignore an error */ @@ -6025,6 +5853,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c + struct dentry *dentry, *parent; + struct file *h_file; + struct inode *h_dir; ++ struct user_namespace *h_userns; + + dentry = cpg->dentry; + h_file = NULL; @@ -6038,7 +5867,8 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c + + parent = dget_parent(dentry); + h_dir = au_h_iptr(d_inode(parent), cpg->bdst); -+ if (!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE) ++ h_userns = au_sbr_userns(dentry->d_sb, cpg->bdst); ++ if (!au_test_h_perm_sio(h_userns, h_dir, MAY_EXEC | MAY_WRITE) + && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode)) + err = au_cpup_simple(cpg); + else { @@ -6208,6 +6038,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c + struct inode *dir, *h_dir, *h_tmpdir; + struct au_wbr *wbr; + struct au_pin wh_pin, *pin_orig; ++ struct user_namespace *h_userns; + + dentry = cpg->dentry; + bdst = cpg->bdst; @@ -6236,7 +6067,8 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c + cpg->pin = &wh_pin; + } + -+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE) ++ h_userns = au_sbr_userns(dentry->d_sb, bdst); ++ if (!au_test_h_perm_sio(h_userns, h_tmpdir, MAY_EXEC | MAY_WRITE) + && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode)) + err = au_cpup_wh(cpg, file); + else { @@ -6381,11 +6213,11 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c +} diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h --- /usr/share/empty/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/cpup.h 2019-07-11 15:42:14.462237786 +0200 ++++ linux/fs/aufs/cpup.h 2022-10-26 22:30:38.462648858 +0200 @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -6485,11 +6317,11 @@ diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h +#endif /* __AUFS_CPUP_H__ */ diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c --- /usr/share/empty/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/dbgaufs.c 2019-07-11 15:42:14.462237786 +0200 ++++ linux/fs/aufs/dbgaufs.c 2022-10-26 22:30:38.462648858 +0200 @@ -0,0 +1,526 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -7015,11 +6847,11 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c +} diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h --- /usr/share/empty/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/dbgaufs.h 2019-07-11 15:42:14.462237786 +0200 ++++ linux/fs/aufs/dbgaufs.h 2022-10-26 22:30:38.462648858 +0200 @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -7072,11 +6904,11 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h +#endif /* __DBGAUFS_H__ */ diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c --- /usr/share/empty/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/dcsub.c 2019-07-11 15:42:14.462237786 +0200 ++++ linux/fs/aufs/dcsub.c 2022-10-26 22:30:38.462648858 +0200 @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -7301,11 +7133,11 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c +} diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h --- /usr/share/empty/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/dcsub.h 2019-07-11 15:42:14.462237786 +0200 ++++ linux/fs/aufs/dcsub.h 2022-10-26 22:30:38.462648858 +0200 @@ -0,0 +1,137 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -7442,11 +7274,11 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h +#endif /* __AUFS_DCSUB_H__ */ diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c --- /usr/share/empty/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/debug.c 2019-07-11 15:42:14.462237786 +0200 -@@ -0,0 +1,441 @@ ++++ linux/fs/aufs/debug.c 2022-10-26 22:30:38.462648858 +0200 +@@ -0,0 +1,444 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -7493,7 +7325,7 @@ diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c + return sprintf(buffer, "%d", atomic_read(a)); +} + -+static struct kernel_param_ops param_ops_atomic_t = { ++static const struct kernel_param_ops param_ops_atomic_t = { + .set = param_atomic_t_set, + .get = param_atomic_t_get + /* void (*free)(void *arg) */ @@ -7829,7 +7661,10 @@ diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c + AuDbgDentry(dentry); + AuDbgInode(inode); + au_debug_off(); -+ BUG(); ++ if (au_test_fuse(h_inode->i_sb)) ++ WARN_ON_ONCE(1); ++ else ++ BUG(); + } + } +} @@ -7887,11 +7722,11 @@ diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c +} diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h --- /usr/share/empty/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/debug.h 2019-07-11 15:42:14.462237786 +0200 ++++ linux/fs/aufs/debug.h 2022-10-26 22:30:38.462648858 +0200 @@ -0,0 +1,226 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -8117,11 +7952,11 @@ diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h +#endif /* __AUFS_DEBUG_H__ */ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c --- /usr/share/empty/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/dentry.c 2019-07-11 15:42:14.462237786 +0200 -@@ -0,0 +1,1154 @@ ++++ linux/fs/aufs/dentry.c 2022-10-26 22:30:38.462648858 +0200 +@@ -0,0 +1,1168 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -8142,7 +7977,6 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c + */ + +#include -+#include +#include "aufs.h" + +/* @@ -8156,6 +7990,8 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c + struct dentry *h_dentry; + struct inode *h_inode; + struct au_branch *br; ++ struct user_namespace *h_userns; ++ struct path h_path; + int wh_found, opq; + unsigned char wh_able; + const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG); @@ -8164,9 +8000,13 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c + + wh_found = 0; + br = au_sbr(dentry->d_sb, bindex); ++ h_path.dentry = h_parent; ++ h_path.mnt = au_br_mnt(br); ++ h_userns = au_br_userns(br); + wh_able = !!au_br_whable(br->br_perm); + if (wh_able) -+ wh_found = au_wh_test(h_parent, &args->whname, ignore_perm); ++ wh_found = au_wh_test(h_userns, &h_path, &args->whname, ++ ignore_perm); + h_dentry = ERR_PTR(wh_found); + if (!wh_found) + goto real_lookup; @@ -8181,9 +8021,9 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c + +real_lookup: + if (!ignore_perm) -+ h_dentry = vfsub_lkup_one(args->name, h_parent); ++ h_dentry = vfsub_lkup_one(args->name, &h_path); + else -+ h_dentry = au_sio_lkup_one(args->name, h_parent); ++ h_dentry = au_sio_lkup_one(h_userns, args->name, &h_path); + if (IS_ERR(h_dentry)) { + if (PTR_ERR(h_dentry) == -ENAMETOOLONG + && !allow_neg) @@ -8217,8 +8057,9 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c + || (d_really_is_positive(dentry) && !d_is_dir(dentry))) + goto out; /* success */ + ++ h_path.dentry = h_dentry; + inode_lock_shared_nested(h_inode, AuLsc_I_CHILD); -+ opq = au_diropq_test(h_dentry); ++ opq = au_diropq_test(h_userns, &h_path); + inode_unlock_shared(h_inode); + if (opq > 0) + au_set_dbdiropq(dentry, bindex); @@ -8363,18 +8204,19 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c + return err; +} + -+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent) ++struct dentry *au_sio_lkup_one(struct user_namespace *userns, struct qstr *name, ++ struct path *ppath) +{ + struct dentry *dentry; + int wkq_err; + -+ if (!au_test_h_perm_sio(d_inode(parent), MAY_EXEC)) -+ dentry = vfsub_lkup_one(name, parent); ++ if (!au_test_h_perm_sio(userns, d_inode(ppath->dentry), MAY_EXEC)) ++ dentry = vfsub_lkup_one(name, ppath); + else { + struct vfsub_lkup_one_args args = { + .errp = &dentry, + .name = name, -+ .parent = parent ++ .ppath = ppath + }; + + wkq_err = au_wkq_wait(vfsub_call_lkup_one, &args); @@ -8391,16 +8233,20 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c +int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh) +{ + int err; -+ struct dentry *parent, *h_parent, *h_dentry; ++ struct dentry *parent, *h_dentry; + struct au_branch *br; ++ struct user_namespace *h_userns; ++ struct path h_ppath; + + parent = dget_parent(dentry); -+ h_parent = au_h_dptr(parent, bindex); + br = au_sbr(dentry->d_sb, bindex); ++ h_ppath.dentry = au_h_dptr(parent, bindex); ++ h_ppath.mnt = au_br_mnt(br); ++ h_userns = au_br_userns(br); + if (wh) -+ h_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name); ++ h_dentry = au_whtmp_lkup(h_ppath.dentry, br, &dentry->d_name); + else -+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent); ++ h_dentry = au_sio_lkup_one(h_userns, &dentry->d_name, &h_ppath); + err = PTR_ERR(h_dentry); + if (IS_ERR(h_dentry)) + goto out; @@ -8475,6 +8321,7 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c + struct inode *h_inode; + struct dentry *h_d; + struct super_block *h_sb; ++ struct path h_ppath; + + err = 0; + memset(&ia, -1, sizeof(ia)); @@ -8489,7 +8336,9 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c + goto out; + + /* main purpose is namei.c:cached_lookup() and d_revalidate */ -+ h_d = vfsub_lkup_one(&h_dentry->d_name, h_parent); ++ h_ppath.dentry = h_parent; ++ h_ppath.mnt = au_br_mnt(br); ++ h_d = vfsub_lkup_one(&h_dentry->d_name, &h_ppath); + err = PTR_ERR(h_d); + if (IS_ERR(h_d)) + goto out; @@ -9275,11 +9124,11 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c +}; diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h --- /usr/share/empty/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/dentry.h 2019-07-11 15:42:14.462237786 +0200 -@@ -0,0 +1,268 @@ ++++ linux/fs/aufs/dentry.h 2022-10-26 22:30:38.462648858 +0200 +@@ -0,0 +1,269 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -9352,7 +9201,8 @@ diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h +/* dentry.c */ +extern const struct dentry_operations aufs_dop, aufs_dop_noreval; +struct au_branch; -+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent); ++struct dentry *au_sio_lkup_one(struct user_namespace *userns, struct qstr *name, ++ struct path *ppath); +int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir, + struct dentry *h_parent, struct au_branch *br); + @@ -9547,11 +9397,11 @@ diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h +#endif /* __AUFS_DENTRY_H__ */ diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c --- /usr/share/empty/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/dinfo.c 2019-07-11 15:42:14.462237786 +0200 ++++ linux/fs/aufs/dinfo.c 2022-10-26 22:30:38.462648858 +0200 @@ -0,0 +1,554 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -10105,11 +9955,11 @@ diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c +} diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c --- /usr/share/empty/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/dir.c 2019-07-11 15:42:14.462237786 +0200 -@@ -0,0 +1,763 @@ ++++ linux/fs/aufs/dir.c 2022-10-26 22:30:38.462648858 +0200 +@@ -0,0 +1,765 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -10746,12 +10596,14 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c + int err, wkq_err; + struct dentry *h_dentry; + struct inode *h_inode; ++ struct user_namespace *h_userns; + ++ h_userns = au_sbr_userns(dentry->d_sb, arg->bindex); + h_dentry = au_h_dptr(dentry, arg->bindex); + h_inode = d_inode(h_dentry); + /* todo: i_mode changes anytime? */ + inode_lock_shared_nested(h_inode, AuLsc_I_CHILD); -+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ); ++ err = au_test_h_perm_sio(h_userns, h_inode, MAY_EXEC | MAY_READ); + inode_unlock_shared(h_inode); + if (!err) + err = do_test_empty(dentry, arg); @@ -10872,11 +10724,11 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c +}; diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h --- /usr/share/empty/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/dir.h 2019-07-11 15:42:14.462237786 +0200 ++++ linux/fs/aufs/dir.h 2022-10-26 22:30:38.462648858 +0200 @@ -0,0 +1,134 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -10914,7 +10766,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h + +struct au_vdir_destr { + unsigned char len; -+ unsigned char name[0]; ++ unsigned char name[]; +} __packed; + +struct au_vdir_dehstr { @@ -11010,11 +10862,11 @@ diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h +#endif /* __AUFS_DIR_H__ */ diff -urN /usr/share/empty/fs/aufs/dirren.c linux/fs/aufs/dirren.c --- /usr/share/empty/fs/aufs/dirren.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/dirren.c 2019-07-11 15:42:14.462237786 +0200 -@@ -0,0 +1,1316 @@ ++++ linux/fs/aufs/dirren.c 2022-10-26 22:30:38.462648858 +0200 +@@ -0,0 +1,1315 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2017-2019 Junjiro R. Okajima ++ * Copyright (C) 2017-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -11095,7 +10947,7 @@ diff -urN /usr/share/empty/fs/aufs/dirren.c linux/fs/aufs/dirren.c + found = 0; + idx = au_dr_ihash(ino); + hbl = dr->dr_h_ino + idx; -+#if 0 ++#if 0 /* debug print */ + { + struct hlist_bl_node *tmp; + @@ -11277,7 +11129,8 @@ diff -urN /usr/share/empty/fs/aufs/dirren.c linux/fs/aufs/dirren.c + dir = d_inode(path->dentry); + inode_lock_nested(dir, AuLsc_I_CHILD); + } -+ hinopath.dentry = vfsub_lkup_one(&hinoname, path->dentry); ++ hinopath.mnt = path->mnt; ++ hinopath.dentry = vfsub_lkup_one(&hinoname, (struct path *)path); + err = PTR_ERR(hinopath.dentry); + if (IS_ERR(hinopath.dentry)) + goto out_unlock; @@ -11311,7 +11164,6 @@ diff -urN /usr/share/empty/fs/aufs/dirren.c linux/fs/aufs/dirren.c + } + flags = O_WRONLY; + } -+ hinopath.mnt = path->mnt; + hinofile = vfsub_dentry_open(&hinopath, flags); + if (suspend) + au_hn_inode_unlock(hdir); @@ -11598,7 +11450,7 @@ diff -urN /usr/share/empty/fs/aufs/dirren.c linux/fs/aufs/dirren.c +struct au_drinfo_rev { + unsigned char already; + aufs_bindex_t nelm; -+ struct au_drinfo_rev_elm elm[0]; ++ struct au_drinfo_rev_elm elm[]; +}; + +/* todo: isn't it too large? */ @@ -11633,7 +11485,7 @@ diff -urN /usr/share/empty/fs/aufs/dirren.c linux/fs/aufs/dirren.c + AuDebugOn(elm + && memcmp(elm, page_address(ZERO_PAGE(0)), sizeof(*elm))); + -+ infopath.dentry = vfsub_lookup_one_len(w->whname, w->h_ppath.dentry, ++ infopath.dentry = vfsub_lookup_one_len(w->whname, &w->h_ppath, + w->whnamelen); + AuTraceErrPtr(infopath.dentry); + if (IS_ERR(infopath.dentry)) { @@ -12017,8 +11869,7 @@ diff -urN /usr/share/empty/fs/aufs/dirren.c linux/fs/aufs/dirren.c + unlocked = 0; + h_dir = d_inode(h_ppath->dentry); + inode_lock_shared_nested(h_dir, AuLsc_I_PARENT); -+ infopath.dentry = vfsub_lookup_one_len(whname, h_ppath->dentry, -+ whnamelen); ++ infopath.dentry = vfsub_lookup_one_len(whname, h_ppath, whnamelen); + if (IS_ERR(infopath.dentry)) { + drinfo = (void *)infopath.dentry; + goto out; @@ -12229,8 +12080,8 @@ diff -urN /usr/share/empty/fs/aufs/dirren.c linux/fs/aufs/dirren.c + err = 0; + if (!lkup->dirren.drinfo) + goto out; -+ AuDebugOn(lkup->dirren.ninfo < btgt + 1); -+ drinfo = lkup->dirren.drinfo[btgt + 1]; ++ AuDebugOn(lkup->dirren.ninfo <= btgt); ++ drinfo = lkup->dirren.drinfo[btgt]; + if (!drinfo) + goto out; + @@ -12259,8 +12110,8 @@ diff -urN /usr/share/empty/fs/aufs/dirren.c linux/fs/aufs/dirren.c + match = 1; + if (!lkup->dirren.drinfo) + goto out; -+ AuDebugOn(lkup->dirren.ninfo < bindex + 1); -+ drinfo = lkup->dirren.drinfo[bindex + 1]; ++ AuDebugOn(lkup->dirren.ninfo <= bindex); ++ drinfo = lkup->dirren.drinfo[bindex]; + if (!drinfo) + goto out; + @@ -12330,11 +12181,11 @@ diff -urN /usr/share/empty/fs/aufs/dirren.c linux/fs/aufs/dirren.c +} diff -urN /usr/share/empty/fs/aufs/dirren.h linux/fs/aufs/dirren.h --- /usr/share/empty/fs/aufs/dirren.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/dirren.h 2019-07-11 15:42:14.462237786 +0200 ++++ linux/fs/aufs/dirren.h 2022-10-26 22:30:38.465982192 +0200 @@ -0,0 +1,140 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2017-2019 Junjiro R. Okajima ++ * Copyright (C) 2017-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -12474,11 +12325,11 @@ diff -urN /usr/share/empty/fs/aufs/dirren.h linux/fs/aufs/dirren.h +#endif /* __AUFS_DIRREN_H__ */ diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c --- /usr/share/empty/fs/aufs/dynop.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/dynop.c 2019-07-11 15:42:14.465571210 +0200 -@@ -0,0 +1,367 @@ ++++ linux/fs/aufs/dynop.c 2022-10-26 22:30:38.465982192 +0200 +@@ -0,0 +1,368 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2010-2019 Junjiro R. Okajima ++ * Copyright (C) 2010-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -12658,6 +12509,7 @@ diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c + DySetAop(writepages); + DySetAop(set_page_dirty); + DySetAop(readpages); ++ DySetAop(readahead); + DySetAop(write_begin); + DySetAop(write_end); + DySetAop(bmap); @@ -12845,11 +12697,11 @@ diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c +} diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h --- /usr/share/empty/fs/aufs/dynop.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/dynop.h 2019-07-11 15:42:14.465571210 +0200 ++++ linux/fs/aufs/dynop.h 2022-10-26 22:30:38.465982192 +0200 @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2010-2019 Junjiro R. Okajima ++ * Copyright (C) 2010-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -12926,11 +12778,11 @@ diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h +#endif /* __AUFS_DYNOP_H__ */ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c --- /usr/share/empty/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/export.c 2019-07-11 15:42:14.465571210 +0200 -@@ -0,0 +1,838 @@ ++++ linux/fs/aufs/export.c 2022-10-26 22:30:38.465982192 +0200 +@@ -0,0 +1,830 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -12952,7 +12804,6 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c + +#include +#include -+#include +#include +#include +#include @@ -13051,8 +12902,7 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c + pos = inode->i_ino; + pos *= sizeof(igen); + igen = inode->i_generation + 1; -+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen, -+ sizeof(igen), &pos); ++ sz = xino_fwrite(sbinfo->si_xigen, &igen, sizeof(igen), &pos); + if (sz == sizeof(igen)) + return; /* success */ + @@ -13094,10 +12944,10 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c + if (vfsub_f_size_read(file) + < pos + sizeof(inode->i_generation)) { + inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next); -+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation, ++ sz = xino_fwrite(file, &inode->i_generation, + sizeof(inode->i_generation), &pos); + } else -+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation, ++ sz = xino_fread(file, &inode->i_generation, + sizeof(inode->i_generation), &pos); + if (sz == sizeof(inode->i_generation)) + goto out; /* success */ @@ -13337,7 +13187,7 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c + + /* do not call vfsub_lkup_one() */ + dir = d_inode(parent); -+ dentry = vfsub_lookup_one_len_unlocked(arg.name, parent, arg.namelen); ++ dentry = vfsub_lookup_one_len_unlocked(arg.name, path, arg.namelen); + AuTraceErrPtr(dentry); + if (IS_ERR(dentry)) + goto out_name; @@ -13725,14 +13575,8 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c + f = h_inode->i_sb->s_export_op->commit_metadata; + if (f) + err = f(h_inode); -+ else { -+ struct writeback_control wbc = { -+ .sync_mode = WB_SYNC_ALL, -+ .nr_to_write = 0 /* metadata only */ -+ }; -+ -+ err = sync_inode(h_inode, &wbc); -+ } ++ else ++ err = sync_inode_metadata(h_inode, /*wait*/1); + + au_cpup_attr_timesizes(inode); + ii_write_unlock(inode); @@ -13768,11 +13612,11 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c +} diff -urN /usr/share/empty/fs/aufs/fhsm.c linux/fs/aufs/fhsm.c --- /usr/share/empty/fs/aufs/fhsm.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/fhsm.c 2019-07-11 15:42:14.465571210 +0200 ++++ linux/fs/aufs/fhsm.c 2022-10-26 22:30:38.465982192 +0200 @@ -0,0 +1,427 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2011-2019 Junjiro R. Okajima ++ * Copyright (C) 2011-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -14199,11 +14043,11 @@ diff -urN /usr/share/empty/fs/aufs/fhsm.c linux/fs/aufs/fhsm.c +} diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c --- /usr/share/empty/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/file.c 2019-07-11 15:42:14.465571210 +0200 ++++ linux/fs/aufs/file.c 2022-10-26 22:30:38.465982192 +0200 @@ -0,0 +1,863 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -15066,11 +14910,11 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c +}; diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h --- /usr/share/empty/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/file.h 2019-07-11 15:42:14.465571210 +0200 ++++ linux/fs/aufs/file.h 2022-10-26 22:30:38.465982192 +0200 @@ -0,0 +1,342 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -15412,11 +15256,11 @@ diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h +#endif /* __AUFS_FILE_H__ */ diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c --- /usr/share/empty/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/finfo.c 2019-07-11 15:42:14.465571210 +0200 ++++ linux/fs/aufs/finfo.c 2022-10-26 22:30:38.465982192 +0200 @@ -0,0 +1,149 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -15565,11 +15409,11 @@ diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c +} diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c --- /usr/share/empty/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/f_op.c 2019-07-11 15:42:14.465571210 +0200 -@@ -0,0 +1,819 @@ ++++ linux/fs/aufs/f_op.c 2022-10-26 22:30:38.465982192 +0200 +@@ -0,0 +1,771 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -15811,34 +15655,6 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + fput(h_file); +} + -+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count, -+ loff_t *ppos) -+{ -+ ssize_t err; -+ struct inode *inode; -+ struct file *h_file; -+ struct super_block *sb; -+ -+ inode = file_inode(file); -+ sb = inode->i_sb; -+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); -+ -+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ /* filedata may be obsoleted by concurrent copyup, but no problem */ -+ err = vfsub_read_u(h_file, buf, count, ppos); -+ /* todo: necessary? */ -+ /* file->f_ra = h_file->f_ra; */ -+ au_read_post(inode, h_file); -+ -+out: -+ si_read_unlock(sb); -+ return err; -+} -+ +/* + * todo: very ugly + * it locks both of i_mutex and si_rwsem for read in safe. @@ -15861,33 +15677,6 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + } +} + -+static ssize_t aufs_write(struct file *file, const char __user *ubuf, -+ size_t count, loff_t *ppos) -+{ -+ ssize_t err; -+ struct au_write_pre wpre; -+ struct inode *inode; -+ struct file *h_file; -+ char __user *buf = (char __user *)ubuf; -+ -+ inode = file_inode(file); -+ au_mtx_and_read_lock(inode); -+ -+ wpre.lsc = 0; -+ h_file = au_write_pre(file, /*do_ready*/1, &wpre); -+ err = PTR_ERR(h_file); -+ if (IS_ERR(h_file)) -+ goto out; -+ -+ err = vfsub_write_u(h_file, buf, count, ppos); -+ au_write_post(inode, h_file, &wpre, err); -+ -+out: -+ si_read_unlock(inode->i_sb); -+ inode_unlock(inode); -+ return err; -+} -+ +static ssize_t au_do_iter(struct file *h_file, int rw, struct kiocb *kio, + struct iov_iter *iov_iter) +{ @@ -15899,7 +15688,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + if (unlikely(err)) + goto out; + -+ err = -ENOSYS; ++ err = -ENOSYS; /* the branch doesn't have its ->(read|write)_iter() */ + iter = NULL; + if (rw == MAY_READ) + iter = h_file->f_op->read_iter; @@ -15983,6 +15772,15 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + return err; +} + ++/* ++ * We may be able to remove aufs_splice_{read,write}() since almost all FSes ++ * don't have their own .splice_{read,write} implimentations, and they use ++ * generic_file_splice_read() and iter_file_splice_write() who can act like the ++ * simple converters to f_op->iter_read() and ->iter_write(). ++ * But we keep our own implementations because some non-mainlined FSes may have ++ * their own .splice_{read,write} implimentations and aufs doesn't want to take ++ * away an opportunity to co-work with aufs from them. ++ */ +static ssize_t aufs_splice_read(struct file *file, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) @@ -16343,7 +16141,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c +/* ---------------------------------------------------------------------- */ + +/* no one supports this operation, currently */ -+#if 0 ++#if 0 /* reserved for future use */ +static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset, + size_t len, loff_t *pos, int more) +{ @@ -16357,8 +16155,6 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + + .llseek = default_llseek, + -+ .read = aufs_read, -+ .write = aufs_write, + .read_iter = aufs_read_iter, + .write_iter = aufs_write_iter, + @@ -16379,20 +16175,1266 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + .setfl = aufs_setfl, + .splice_write = aufs_splice_write, + .splice_read = aufs_splice_read, -+#if 0 ++#if 0 /* reserved for future use */ + .aio_splice_write = aufs_aio_splice_write, + .aio_splice_read = aufs_aio_splice_read, +#endif + .fallocate = aufs_fallocate, + .copy_file_range = aufs_copy_file_range +}; +diff -urN /usr/share/empty/fs/aufs/fsctx.c linux/fs/aufs/fsctx.c +--- /usr/share/empty/fs/aufs/fsctx.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux/fs/aufs/fsctx.c 2022-10-26 22:30:38.465982192 +0200 +@@ -0,0 +1,1242 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * Copyright (C) 2022 Junjiro R. Okajima ++ * ++ * This program, aufs is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program. If not, see . ++ */ ++ ++/* ++ * fs context, aka new mount api ++ */ ++ ++#include ++#include "aufs.h" ++ ++struct au_fsctx_opts { ++ aufs_bindex_t bindex; ++ unsigned char skipped; ++ struct au_opt *opt, *opt_tail; ++ struct super_block *sb; ++ struct au_sbinfo *sbinfo; ++ struct au_opts opts; ++}; ++ ++/* stop extra interpretation of errno in mount(8), and strange error messages */ ++static int cvt_err(int err) ++{ ++ AuTraceErr(err); ++ ++ switch (err) { ++ case -ENOENT: ++ case -ENOTDIR: ++ case -EEXIST: ++ case -EIO: ++ err = -EINVAL; ++ } ++ return err; ++} ++ ++static int au_fsctx_reconfigure(struct fs_context *fc) ++{ ++ int err, do_dx; ++ unsigned int mntflags; ++ struct dentry *root; ++ struct super_block *sb; ++ struct inode *inode; ++ struct au_fsctx_opts *a = fc->fs_private; ++ ++ AuDbg("fc %p\n", fc); ++ ++ root = fc->root; ++ sb = root->d_sb; ++ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (!err) { ++ di_write_lock_child(root); ++ err = au_opts_verify(sb, fc->sb_flags, /*pending*/0); ++ aufs_write_unlock(root); ++ } ++ ++ inode = d_inode(root); ++ inode_lock(inode); ++ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (unlikely(err)) ++ goto out; ++ di_write_lock_child(root); ++ ++ /* au_opts_remount() may return an error */ ++ err = au_opts_remount(sb, &a->opts); ++ ++ if (au_ftest_opts(a->opts.flags, REFRESH)) ++ au_remount_refresh(sb, au_ftest_opts(a->opts.flags, ++ REFRESH_IDOP)); ++ ++ if (au_ftest_opts(a->opts.flags, REFRESH_DYAOP)) { ++ mntflags = au_mntflags(sb); ++ do_dx = !!au_opt_test(mntflags, DIO); ++ au_dy_arefresh(do_dx); ++ } ++ ++ au_fhsm_wrote_all(sb, /*force*/1); /* ?? */ ++ aufs_write_unlock(root); ++ ++out: ++ inode_unlock(inode); ++ err = cvt_err(err); ++ AuTraceErr(err); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static int au_fsctx_fill_super(struct super_block *sb, struct fs_context *fc) ++{ ++ int err; ++ struct au_fsctx_opts *a = fc->fs_private; ++ struct au_sbinfo *sbinfo = a->sbinfo; ++ struct dentry *root; ++ struct inode *inode; ++ ++ sbinfo->si_sb = sb; ++ sb->s_fs_info = sbinfo; ++ kobject_get(&sbinfo->si_kobj); ++ ++ __si_write_lock(sb); ++ si_pid_set(sb); ++ au_sbilist_add(sb); ++ ++ /* all timestamps always follow the ones on the branch */ ++ sb->s_flags |= SB_NOATIME | SB_NODIRATIME; ++ sb->s_flags |= SB_I_VERSION; /* do we really need this? */ ++ sb->s_op = &aufs_sop; ++ sb->s_d_op = &aufs_dop; ++ sb->s_magic = AUFS_SUPER_MAGIC; ++ sb->s_maxbytes = 0; ++ sb->s_stack_depth = 1; ++ au_export_init(sb); ++ au_xattr_init(sb); ++ ++ err = au_alloc_root(sb); ++ if (unlikely(err)) { ++ si_write_unlock(sb); ++ goto out; ++ } ++ root = sb->s_root; ++ inode = d_inode(root); ++ ii_write_lock_parent(inode); ++ aufs_write_unlock(root); ++ ++ /* lock vfs_inode first, then aufs. */ ++ inode_lock(inode); ++ aufs_write_lock(root); ++ err = au_opts_mount(sb, &a->opts); ++ AuTraceErr(err); ++ if (!err && au_ftest_si(sbinfo, NO_DREVAL)) { ++ sb->s_d_op = &aufs_dop_noreval; ++ /* infofc(fc, "%ps", sb->s_d_op); */ ++ pr_info("%ps\n", sb->s_d_op); ++ au_refresh_dop(root, /*force_reval*/0); ++ sbinfo->si_iop_array = aufs_iop_nogetattr; ++ au_refresh_iop(inode, /*force_getattr*/0); ++ } ++ aufs_write_unlock(root); ++ inode_unlock(inode); ++ if (!err) ++ goto out; /* success */ ++ ++ dput(root); ++ sb->s_root = NULL; ++ ++out: ++ if (unlikely(err)) ++ kobject_put(&sbinfo->si_kobj); ++ AuTraceErr(err); ++ err = cvt_err(err); ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_fsctx_get_tree(struct fs_context *fc) ++{ ++ int err; ++ ++ AuDbg("fc %p\n", fc); ++ err = get_tree_nodev(fc, au_fsctx_fill_super); ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void au_fsctx_dump(struct au_opts *opts) ++{ ++#ifdef CONFIG_AUFS_DEBUG ++ /* reduce stack space */ ++ union { ++ struct au_opt_add *add; ++ struct au_opt_del *del; ++ struct au_opt_mod *mod; ++ struct au_opt_xino *xino; ++ struct au_opt_xino_itrunc *xino_itrunc; ++ struct au_opt_wbr_create *create; ++ } u; ++ struct au_opt *opt; ++ ++ opt = opts->opt; ++ while (opt->type != Opt_tail) { ++ switch (opt->type) { ++ case Opt_add: ++ u.add = &opt->add; ++ AuDbg("add {b%d, %s, 0x%x, %p}\n", ++ u.add->bindex, u.add->pathname, u.add->perm, ++ u.add->path.dentry); ++ break; ++ case Opt_del: ++ fallthrough; ++ case Opt_idel: ++ u.del = &opt->del; ++ AuDbg("del {%s, %p}\n", ++ u.del->pathname, u.del->h_path.dentry); ++ break; ++ case Opt_mod: ++ fallthrough; ++ case Opt_imod: ++ u.mod = &opt->mod; ++ AuDbg("mod {%s, 0x%x, %p}\n", ++ u.mod->path, u.mod->perm, u.mod->h_root); ++ break; ++ case Opt_append: ++ u.add = &opt->add; ++ AuDbg("append {b%d, %s, 0x%x, %p}\n", ++ u.add->bindex, u.add->pathname, u.add->perm, ++ u.add->path.dentry); ++ break; ++ case Opt_prepend: ++ u.add = &opt->add; ++ AuDbg("prepend {b%d, %s, 0x%x, %p}\n", ++ u.add->bindex, u.add->pathname, u.add->perm, ++ u.add->path.dentry); ++ break; ++ ++ case Opt_dirwh: ++ AuDbg("dirwh %d\n", opt->dirwh); ++ break; ++ case Opt_rdcache: ++ AuDbg("rdcache %d\n", opt->rdcache); ++ break; ++ case Opt_rdblk: ++ AuDbg("rdblk %d\n", opt->rdblk); ++ break; ++ case Opt_rdhash: ++ AuDbg("rdhash %u\n", opt->rdhash); ++ break; ++ ++ case Opt_xino: ++ u.xino = &opt->xino; ++ AuDbg("xino {%s %pD}\n", u.xino->path, u.xino->file); ++ break; ++ ++#define au_fsctx_TF(name) \ ++ case Opt_##name: \ ++ if (opt->tf) \ ++ AuLabel(name); \ ++ else \ ++ AuLabel(no##name); \ ++ break; ++ ++ /* simple true/false flag */ ++ au_fsctx_TF(trunc_xino); ++ au_fsctx_TF(trunc_xib); ++ au_fsctx_TF(dirperm1); ++ au_fsctx_TF(plink); ++ au_fsctx_TF(shwh); ++ au_fsctx_TF(dio); ++ au_fsctx_TF(warn_perm); ++ au_fsctx_TF(verbose); ++ au_fsctx_TF(sum); ++ au_fsctx_TF(dirren); ++ au_fsctx_TF(acl); ++#undef au_fsctx_TF ++ ++ case Opt_trunc_xino_path: ++ fallthrough; ++ case Opt_itrunc_xino: ++ u.xino_itrunc = &opt->xino_itrunc; ++ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex); ++ break; ++ case Opt_noxino: ++ AuLabel(noxino); ++ break; ++ ++ case Opt_list_plink: ++ AuLabel(list_plink); ++ break; ++ case Opt_udba: ++ AuDbg("udba %d, %s\n", ++ opt->udba, au_optstr_udba(opt->udba)); ++ break; ++ case Opt_diropq_a: ++ AuLabel(diropq_a); ++ break; ++ case Opt_diropq_w: ++ AuLabel(diropq_w); ++ break; ++ case Opt_wsum: ++ AuLabel(wsum); ++ break; ++ case Opt_wbr_create: ++ u.create = &opt->wbr_create; ++ AuDbg("create %d, %s\n", u.create->wbr_create, ++ au_optstr_wbr_create(u.create->wbr_create)); ++ switch (u.create->wbr_create) { ++ case AuWbrCreate_MFSV: ++ fallthrough; ++ case AuWbrCreate_PMFSV: ++ AuDbg("%d sec\n", u.create->mfs_second); ++ break; ++ case AuWbrCreate_MFSRR: ++ fallthrough; ++ case AuWbrCreate_TDMFS: ++ AuDbg("%llu watermark\n", ++ u.create->mfsrr_watermark); ++ break; ++ case AuWbrCreate_MFSRRV: ++ fallthrough; ++ case AuWbrCreate_TDMFSV: ++ fallthrough; ++ case AuWbrCreate_PMFSRRV: ++ AuDbg("%llu watermark, %d sec\n", ++ u.create->mfsrr_watermark, ++ u.create->mfs_second); ++ break; ++ } ++ break; ++ case Opt_wbr_copyup: ++ AuDbg("copyup %d, %s\n", opt->wbr_copyup, ++ au_optstr_wbr_copyup(opt->wbr_copyup)); ++ break; ++ case Opt_fhsm_sec: ++ AuDbg("fhsm_sec %u\n", opt->fhsm_second); ++ break; ++ ++ default: ++ AuDbg("type %d\n", opt->type); ++ BUG(); ++ } ++ opt++; ++ } ++#endif ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++/* ++ * For conditionally compiled mount options. ++ * Instead of fsparam_flag_no(), use this macro to distinguish ignore_silent. ++ */ ++#define au_ignore_flag(name, action) \ ++ fsparam_flag(name, action), \ ++ fsparam_flag("no" name, Opt_ignore_silent) ++ ++const struct fs_parameter_spec aufs_fsctx_paramspec[] = { ++ fsparam_string("br", Opt_br), ++ ++ /* "add=%d:%s" or "ins=%d:%s" */ ++ fsparam_string("add", Opt_add), ++ fsparam_string("ins", Opt_add), ++ fsparam_path("append", Opt_append), ++ fsparam_path("prepend", Opt_prepend), ++ ++ fsparam_path("del", Opt_del), ++ /* fsparam_s32("idel", Opt_idel), */ ++ fsparam_path("mod", Opt_mod), ++ /* fsparam_string("imod", Opt_imod), */ ++ ++ fsparam_s32("dirwh", Opt_dirwh), ++ ++ fsparam_path("xino", Opt_xino), ++ fsparam_flag("noxino", Opt_noxino), ++ fsparam_flag_no("trunc_xino", Opt_trunc_xino), ++ /* "trunc_xino_v=%d:%d" */ ++ /* fsparam_string("trunc_xino_v", Opt_trunc_xino_v), */ ++ fsparam_path("trunc_xino", Opt_trunc_xino_path), ++ fsparam_s32("itrunc_xino", Opt_itrunc_xino), ++ /* fsparam_path("zxino", Opt_zxino), */ ++ fsparam_flag_no("trunc_xib", Opt_trunc_xib), ++ ++#ifdef CONFIG_PROC_FS ++ fsparam_flag_no("plink", Opt_plink), ++#else ++ au_ignore_flag("plink", Opt_ignore), ++#endif ++ ++#ifdef CONFIG_AUFS_DEBUG ++ fsparam_flag("list_plink", Opt_list_plink), ++#endif ++ ++ fsparam_string("udba", Opt_udba), ++ ++ fsparam_flag_no("dio", Opt_dio), ++ ++#ifdef CONFIG_AUFS_DIRREN ++ fsparam_flag_no("dirren", Opt_dirren), ++#else ++ au_ignore_flag("dirren", Opt_ignore), ++#endif ++ ++#ifdef CONFIG_AUFS_FHSM ++ fsparam_s32("fhsm_sec", Opt_fhsm_sec), ++#else ++ fsparam_s32("fhsm_sec", Opt_ignore), ++#endif ++ ++ /* always | a | whiteouted | w */ ++ fsparam_string("diropq", Opt_diropq), ++ ++ fsparam_flag_no("warn_perm", Opt_warn_perm), ++ ++#ifdef CONFIG_AUFS_SHWH ++ fsparam_flag_no("shwh", Opt_shwh), ++#else ++ au_ignore_flag("shwh", Opt_err), ++#endif ++ ++ fsparam_flag_no("dirperm1", Opt_dirperm1), ++ ++ fsparam_flag_no("verbose", Opt_verbose), ++ fsparam_flag("v", Opt_verbose), ++ fsparam_flag("quiet", Opt_noverbose), ++ fsparam_flag("q", Opt_noverbose), ++ /* user-space may handle this */ ++ fsparam_flag("silent", Opt_noverbose), ++ ++ fsparam_flag_no("sum", Opt_sum), ++ fsparam_flag("wsum", Opt_wsum), ++ ++ fsparam_s32("rdcache", Opt_rdcache), ++ /* "def" or s32 */ ++ fsparam_string("rdblk", Opt_rdblk), ++ /* "def" or s32 */ ++ fsparam_string("rdhash", Opt_rdhash), ++ ++ fsparam_string("create", Opt_wbr_create), ++ fsparam_string("create_policy", Opt_wbr_create), ++ fsparam_string("cpup", Opt_wbr_copyup), ++ fsparam_string("copyup", Opt_wbr_copyup), ++ fsparam_string("copyup_policy", Opt_wbr_copyup), ++ ++ /* generic VFS flag */ ++#ifdef CONFIG_FS_POSIX_ACL ++ fsparam_flag_no("acl", Opt_acl), ++#else ++ au_ignore_flag("acl", Opt_ignore), ++#endif ++ ++ /* internal use for the scripts */ ++ fsparam_string("si", Opt_ignore_silent), ++ ++ /* obsoleted, keep them temporary */ ++ fsparam_flag("nodlgt", Opt_ignore_silent), ++ fsparam_flag("clean_plink", Opt_ignore), ++ fsparam_string("dirs", Opt_br), ++ fsparam_u32("debug", Opt_ignore), ++ /* "whiteout" or "all" */ ++ fsparam_string("delete", Opt_ignore), ++ fsparam_string("imap", Opt_ignore), ++ ++ /* temporary workaround, due to old mount(8)? */ ++ fsparam_flag("relatime", Opt_ignore_silent), ++ ++ {} ++}; ++ ++static int au_fsctx_parse_do_add(struct fs_context *fc, struct au_opt *opt, ++ char *brspec, size_t speclen, ++ aufs_bindex_t bindex) ++{ ++ int err; ++ char *p; ++ ++ AuDbg("brspec %s\n", brspec); ++ ++ err = -ENOMEM; ++ if (!speclen) ++ speclen = strlen(brspec); ++ /* will be freed by au_fsctx_free() */ ++ p = kmemdup_nul(brspec, speclen, GFP_NOFS); ++ if (unlikely(!p)) { ++ errorfc(fc, "failed in %s", brspec); ++ goto out; ++ } ++ err = au_opt_add(opt, p, fc->sb_flags, bindex); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_fsctx_parse_br(struct fs_context *fc, char *brspec) ++{ ++ int err; ++ char *p; ++ struct au_fsctx_opts *a = fc->fs_private; ++ struct au_opt *opt = a->opt; ++ aufs_bindex_t bindex = a->bindex; ++ ++ AuDbg("brspec %s\n", brspec); ++ ++ err = -EINVAL; ++ while ((p = strsep(&brspec, ":")) && *p) { ++ err = au_fsctx_parse_do_add(fc, opt, p, /*len*/0, bindex); ++ AuTraceErr(err); ++ if (unlikely(err)) ++ break; ++ bindex++; ++ opt++; ++ if (unlikely(opt > a->opt_tail)) { ++ err = -E2BIG; ++ bindex--; ++ opt--; ++ break; ++ } ++ opt->type = Opt_tail; ++ a->skipped = 1; ++ } ++ a->bindex = bindex; ++ a->opt = opt; ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_fsctx_parse_add(struct fs_context *fc, char *addspec) ++{ ++ int err, n; ++ char *p; ++ struct au_fsctx_opts *a = fc->fs_private; ++ struct au_opt *opt = a->opt; ++ ++ err = -EINVAL; ++ p = strchr(addspec, ':'); ++ if (unlikely(!p)) { ++ errorfc(fc, "bad arg in %s", addspec); ++ goto out; ++ } ++ *p++ = '\0'; ++ err = kstrtoint(addspec, 0, &n); ++ if (unlikely(err)) { ++ errorfc(fc, "bad integer in %s", addspec); ++ goto out; ++ } ++ AuDbg("n %d\n", n); ++ err = au_fsctx_parse_do_add(fc, opt, p, /*len*/0, n); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_fsctx_parse_del(struct fs_context *fc, struct au_opt_del *del, ++ struct fs_parameter *param) ++{ ++ int err; ++ ++ err = -ENOMEM; ++ /* will be freed by au_fsctx_free() */ ++ del->pathname = kmemdup_nul(param->string, param->size, GFP_NOFS); ++ if (unlikely(!del->pathname)) ++ goto out; ++ AuDbg("del %s\n", del->pathname); ++ err = vfsub_kern_path(del->pathname, AuOpt_LkupDirFlags, &del->h_path); ++ if (unlikely(err)) ++ errorfc(fc, "lookup failed %s (%d)", del->pathname, err); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++#if 0 /* reserved for future use */ ++static int au_fsctx_parse_idel(struct fs_context *fc, struct au_opt_del *del, ++ aufs_bindex_t bindex) ++{ ++ int err; ++ struct super_block *sb; ++ struct dentry *root; ++ struct au_fsctx_opts *a = fc->fs_private; ++ ++ sb = a->sb; ++ AuDebugOn(!sb); ++ ++ err = -EINVAL; ++ root = sb->s_root; ++ aufs_read_lock(root, AuLock_FLUSH); ++ if (bindex < 0 || au_sbbot(sb) < bindex) { ++ errorfc(fc, "out of bounds, %d", bindex); ++ goto out; ++ } ++ ++ err = 0; ++ del->h_path.dentry = dget(au_h_dptr(root, bindex)); ++ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex)); ++ ++out: ++ aufs_read_unlock(root, !AuLock_IR); ++ AuTraceErr(err); ++ return err; ++} ++#endif ++ ++static int au_fsctx_parse_mod(struct fs_context *fc, struct au_opt_mod *mod, ++ struct fs_parameter *param) ++{ ++ int err; ++ struct path path; ++ char *p; ++ ++ err = -ENOMEM; ++ /* will be freed by au_fsctx_free() */ ++ mod->path = kmemdup_nul(param->string, param->size, GFP_NOFS); ++ if (unlikely(!mod->path)) ++ goto out; ++ ++ err = -EINVAL; ++ p = strchr(mod->path, '='); ++ if (unlikely(!p)) { ++ errorfc(fc, "no permission %s", mod->path); ++ goto out; ++ } ++ ++ *p++ = 0; ++ err = vfsub_kern_path(mod->path, AuOpt_LkupDirFlags, &path); ++ if (unlikely(err)) { ++ errorfc(fc, "lookup failed %s (%d)", mod->path, err); ++ goto out; ++ } ++ ++ mod->perm = au_br_perm_val(p); ++ AuDbg("mod path %s, perm 0x%x, %s", mod->path, mod->perm, p); ++ mod->h_root = dget(path.dentry); ++ path_put(&path); ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++#if 0 /* reserved for future use */ ++static int au_fsctx_parse_imod(struct fs_context *fc, struct au_opt_mod *mod, ++ char *ibrspec) ++{ ++ int err, n; ++ char *p; ++ struct super_block *sb; ++ struct dentry *root; ++ struct au_fsctx_opts *a = fc->fs_private; ++ ++ sb = a->sb; ++ AuDebugOn(!sb); ++ ++ err = -EINVAL; ++ p = strchr(ibrspec, ':'); ++ if (unlikely(!p)) { ++ errorfc(fc, "no index, %s", ibrspec); ++ goto out; ++ } ++ *p++ = '\0'; ++ err = kstrtoint(ibrspec, 0, &n); ++ if (unlikely(err)) { ++ errorfc(fc, "bad integer in %s", ibrspec); ++ goto out; ++ } ++ AuDbg("n %d\n", n); ++ ++ root = sb->s_root; ++ aufs_read_lock(root, AuLock_FLUSH); ++ if (n < 0 || au_sbbot(sb) < n) { ++ errorfc(fc, "out of bounds, %d", bindex); ++ goto out_root; ++ } ++ ++ err = 0; ++ mod->perm = au_br_perm_val(p); ++ AuDbg("mod path %s, perm 0x%x, %s\n", ++ mod->path, mod->perm, p); ++ mod->h_root = dget(au_h_dptr(root, bindex)); ++ ++out_root: ++ aufs_read_unlock(root, !AuLock_IR); ++out: ++ AuTraceErr(err); ++ return err; ++} ++#endif ++ ++static int au_fsctx_parse_xino(struct fs_context *fc, ++ struct au_opt_xino *xino, ++ struct fs_parameter *param) ++{ ++ int err; ++ struct au_fsctx_opts *a = fc->fs_private; ++ ++ err = -ENOMEM; ++ /* will be freed by au_opts_free() */ ++ xino->path = kmemdup_nul(param->string, param->size, GFP_NOFS); ++ if (unlikely(!xino->path)) ++ goto out; ++ AuDbg("path %s\n", xino->path); ++ ++ xino->file = au_xino_create(a->sb, xino->path, /*silent*/0, ++ /*wbrtop*/0); ++ err = PTR_ERR(xino->file); ++ if (IS_ERR(xino->file)) { ++ xino->file = NULL; ++ goto out; ++ } ++ ++ err = 0; ++ if (unlikely(a->sb && xino->file->f_path.dentry->d_sb == a->sb)) { ++ err = -EINVAL; ++ errorfc(fc, "%s must be outside", xino->path); ++ } ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static ++int au_fsctx_parse_xino_itrunc_path(struct fs_context *fc, ++ struct au_opt_xino_itrunc *xino_itrunc, ++ char *pathname) ++{ ++ int err; ++ aufs_bindex_t bbot, bindex; ++ struct path path; ++ struct dentry *root; ++ struct au_fsctx_opts *a = fc->fs_private; ++ ++ AuDebugOn(!a->sb); ++ ++ err = vfsub_kern_path(pathname, AuOpt_LkupDirFlags, &path); ++ if (unlikely(err)) { ++ errorfc(fc, "lookup failed %s (%d)", pathname, err); ++ goto out; ++ } ++ ++ xino_itrunc->bindex = -1; ++ root = a->sb->s_root; ++ aufs_read_lock(root, AuLock_FLUSH); ++ bbot = au_sbbot(a->sb); ++ for (bindex = 0; bindex <= bbot; bindex++) { ++ if (au_h_dptr(root, bindex) == path.dentry) { ++ xino_itrunc->bindex = bindex; ++ break; ++ } ++ } ++ aufs_read_unlock(root, !AuLock_IR); ++ path_put(&path); ++ ++ if (unlikely(xino_itrunc->bindex < 0)) { ++ err = -EINVAL; ++ errorfc(fc, "no such branch %s", pathname); ++ } ++ ++out: ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_fsctx_parse_xino_itrunc(struct fs_context *fc, ++ struct au_opt_xino_itrunc *xino_itrunc, ++ unsigned int bindex) ++{ ++ int err; ++ aufs_bindex_t bbot; ++ struct super_block *sb; ++ struct au_fsctx_opts *a = fc->fs_private; ++ ++ sb = a->sb; ++ AuDebugOn(!sb); ++ ++ err = 0; ++ si_noflush_read_lock(sb); ++ bbot = au_sbbot(sb); ++ si_read_unlock(sb); ++ if (bindex <= bbot) ++ xino_itrunc->bindex = bindex; ++ else { ++ err = -EINVAL; ++ errorfc(fc, "out of bounds, %u", bindex); ++ } ++ ++ AuTraceErr(err); ++ return err; ++} ++ ++static int au_fsctx_parse_param(struct fs_context *fc, struct fs_parameter *param) ++{ ++ int err, token; ++ struct fs_parse_result result; ++ struct au_fsctx_opts *a = fc->fs_private; ++ struct au_opt *opt = a->opt; ++ ++ AuDbg("fc %p, param {key %s, string %s}\n", ++ fc, param->key, param->string); ++ err = fs_parse(fc, aufs_fsctx_paramspec, param, &result); ++ if (unlikely(err < 0)) ++ goto out; ++ token = err; ++ AuDbg("token %d, res{negated %d, uint64 %llu}\n", ++ token, result.negated, result.uint_64); ++ ++ err = -EINVAL; ++ a->skipped = 0; ++ switch (token) { ++ case Opt_br: ++ err = au_fsctx_parse_br(fc, param->string); ++ break; ++ case Opt_add: ++ err = au_fsctx_parse_add(fc, param->string); ++ break; ++ case Opt_append: ++ err = au_fsctx_parse_do_add(fc, opt, param->string, param->size, ++ /*dummy bindex*/1); ++ break; ++ case Opt_prepend: ++ err = au_fsctx_parse_do_add(fc, opt, param->string, param->size, ++ /*bindex*/0); ++ break; ++ ++ case Opt_del: ++ err = au_fsctx_parse_del(fc, &opt->del, param); ++ break; ++#if 0 /* reserved for future use */ ++ case Opt_idel: ++ if (!a->sb) { ++ err = 0; ++ a->skipped = 1; ++ break; ++ } ++ del->pathname = "(indexed)"; ++ err = au_opts_parse_idel(fc, &opt->del, result.uint_32); ++ break; ++#endif ++ ++ case Opt_mod: ++ err = au_fsctx_parse_mod(fc, &opt->mod, param); ++ break; ++#ifdef IMOD /* reserved for future use */ ++ case Opt_imod: ++ if (!a->sb) { ++ err = 0; ++ a->skipped = 1; ++ break; ++ } ++ u.mod->path = "(indexed)"; ++ err = au_opts_parse_imod(fc, &opt->mod, param->string); ++ break; ++#endif ++ ++ case Opt_xino: ++ err = au_fsctx_parse_xino(fc, &opt->xino, param); ++ break; ++ case Opt_trunc_xino_path: ++ if (!a->sb) { ++ errorfc(fc, "no such branch %s", param->string); ++ break; ++ } ++ err = au_fsctx_parse_xino_itrunc_path(fc, &opt->xino_itrunc, ++ param->string); ++ break; ++#if 0 ++ case Opt_trunc_xino_v: ++ if (!a->sb) { ++ err = 0; ++ a->skipped = 1; ++ break; ++ } ++ err = au_fsctx_parse_xino_itrunc_path(fc, &opt->xino_itrunc, ++ param->string); ++ break; ++#endif ++ case Opt_itrunc_xino: ++ if (!a->sb) { ++ errorfc(fc, "out of bounds %s", param->string); ++ break; ++ } ++ err = au_fsctx_parse_xino_itrunc(fc, &opt->xino_itrunc, ++ result.int_32); ++ break; ++ ++ case Opt_dirwh: ++ err = 0; ++ opt->dirwh = result.int_32; ++ break; ++ ++ case Opt_rdcache: ++ if (unlikely(result.int_32 > AUFS_RDCACHE_MAX)) { ++ errorfc(fc, "rdcache must be smaller than %d", ++ AUFS_RDCACHE_MAX); ++ break; ++ } ++ err = 0; ++ opt->rdcache = result.int_32; ++ break; ++ ++ case Opt_rdblk: ++ err = 0; ++ opt->rdblk = AUFS_RDBLK_DEF; ++ if (!strcmp(param->string, "def")) ++ break; ++ ++ err = kstrtoint(param->string, 0, &result.int_32); ++ if (unlikely(err)) { ++ errorfc(fc, "bad value in %s", param->key); ++ break; ++ } ++ err = -EINVAL; ++ if (unlikely(result.int_32 < 0 ++ || result.int_32 > KMALLOC_MAX_SIZE)) { ++ errorfc(fc, "bad value in %s", param->key); ++ break; ++ } ++ if (unlikely(result.int_32 && result.int_32 < NAME_MAX)) { ++ errorfc(fc, "rdblk must be larger than %d", NAME_MAX); ++ break; ++ } ++ err = 0; ++ opt->rdblk = result.int_32; ++ break; ++ ++ case Opt_rdhash: ++ err = 0; ++ opt->rdhash = AUFS_RDHASH_DEF; ++ if (!strcmp(param->string, "def")) ++ break; ++ ++ err = kstrtoint(param->string, 0, &result.int_32); ++ if (unlikely(err)) { ++ errorfc(fc, "bad value in %s", param->key); ++ break; ++ } ++ /* how about zero? */ ++ if (result.int_32 < 0 ++ || result.int_32 * sizeof(struct hlist_head) ++ > KMALLOC_MAX_SIZE) { ++ err = -EINVAL; ++ errorfc(fc, "bad integer in %s", param->key); ++ break; ++ } ++ opt->rdhash = result.int_32; ++ break; ++ ++ case Opt_diropq: ++ /* ++ * As other options, fs/aufs/opts.c can handle these strings by ++ * match_token(). But "diropq=" is deprecated now and will ++ * never have other value. So simple strcmp() is enough here. ++ */ ++ if (!strcmp(param->string, "a") || ++ !strcmp(param->string, "always")) { ++ err = 0; ++ opt->type = Opt_diropq_a; ++ } else if (!strcmp(param->string, "w") || ++ !strcmp(param->string, "whiteouted")) { ++ err = 0; ++ opt->type = Opt_diropq_w; ++ } else ++ errorfc(fc, "unknown value %s", param->string); ++ break; ++ ++ case Opt_udba: ++ opt->udba = au_udba_val(param->string); ++ if (opt->udba >= 0) ++ err = 0; ++ else ++ errorf(fc, "wrong value, %s", param->string); ++ break; ++ ++ case Opt_wbr_create: ++ opt->wbr_create.wbr_create ++ = au_wbr_create_val(param->string, &opt->wbr_create); ++ if (opt->wbr_create.wbr_create >= 0) ++ err = 0; ++ else ++ errorf(fc, "wrong value, %s", param->key); ++ break; ++ ++ case Opt_wbr_copyup: ++ opt->wbr_copyup = au_wbr_copyup_val(param->string); ++ if (opt->wbr_copyup >= 0) ++ err = 0; ++ else ++ errorfc(fc, "wrong value, %s", param->key); ++ break; ++ ++ case Opt_fhsm_sec: ++ if (unlikely(result.int_32 < 0)) { ++ errorfc(fc, "bad integer in %s\n", param->key); ++ break; ++ } ++ err = 0; ++ if (sysaufs_brs) ++ opt->fhsm_second = result.int_32; ++ else ++ warnfc(fc, "ignored %s %s", param->key, param->string); ++ break; ++ ++ /* simple true/false flag */ ++#define au_fsctx_TF(name) \ ++ case Opt_##name: \ ++ err = 0; \ ++ opt->tf = !result.negated; \ ++ break ++ au_fsctx_TF(trunc_xino); ++ au_fsctx_TF(trunc_xib); ++ au_fsctx_TF(dirperm1); ++ au_fsctx_TF(plink); ++ au_fsctx_TF(shwh); ++ au_fsctx_TF(dio); ++ au_fsctx_TF(warn_perm); ++ au_fsctx_TF(verbose); ++ au_fsctx_TF(sum); ++ au_fsctx_TF(dirren); ++ au_fsctx_TF(acl); ++#undef au_fsctx_TF ++ ++ case Opt_noverbose: ++ err = 0; ++ opt->type = Opt_verbose; ++ opt->tf = false; ++ break; ++ ++ case Opt_noxino: ++ fallthrough; ++ case Opt_list_plink: ++ fallthrough; ++ case Opt_wsum: ++ err = 0; ++ break; ++ ++ case Opt_ignore: ++ warnfc(fc, "ignored %s", param->key); ++ fallthrough; ++ case Opt_ignore_silent: ++ a->skipped = 1; ++ err = 0; ++ break; ++ default: ++ a->skipped = 1; ++ err = -ENOPARAM; ++ break; ++ } ++ if (unlikely(err)) ++ goto out; ++ if (a->skipped) ++ goto out; ++ ++ switch (token) { ++ case Opt_br: ++ fallthrough; ++ case Opt_noverbose: ++ fallthrough; ++ case Opt_diropq: ++ break; ++ default: ++ opt->type = token; ++ break; ++ } ++ opt++; ++ if (unlikely(opt > a->opt_tail)) { ++ err = -E2BIG; ++ opt--; ++ } ++ opt->type = Opt_tail; ++ a->opt = opt; ++ ++out: ++ return err; ++} ++ ++/* ++ * these options accept both 'name=val' and 'name:val' form. ++ * some accept optional '=' in its value. ++ * eg. br:/br1=rw:/br2=ro and br=/br1=rw:/br2=ro ++ */ ++static inline unsigned int is_colonopt(char *str) ++{ ++#define do_test(name) \ ++ if (!strncmp(str, name ":", sizeof(name))) \ ++ return sizeof(name) - 1 ++ do_test("br"); ++ do_test("add"); ++ do_test("ins"); ++ do_test("append"); ++ do_test("prepend"); ++ do_test("del"); ++ /* do_test("idel"); */ ++ do_test("mod"); ++ /* do_test("imod"); */ ++#undef do_test ++ ++ return 0; ++} ++ ++static int au_fsctx_parse_monolithic(struct fs_context *fc, void *data) ++{ ++ int err; ++ unsigned int u; ++ char *str; ++ struct au_fsctx_opts *a = fc->fs_private; ++ ++ str = data; ++ AuDbg("str %s\n", str); ++ while (str) { ++ u = is_colonopt(str); ++ if (u) ++ str[u] = '='; ++ str = strchr(str, ','); ++ if (!str) ++ break; ++ str++; ++ } ++ str = data; ++ AuDbg("str %s\n", str); ++ ++ err = generic_parse_monolithic(fc, str); ++ AuTraceErr(err); ++ au_fsctx_dump(&a->opts); ++ ++ return err; ++} ++ ++/* ---------------------------------------------------------------------- */ ++ ++static void au_fsctx_opts_free(struct au_opts *opts) ++{ ++ struct au_opt *opt; ++ ++ opt = opts->opt; ++ while (opt->type != Opt_tail) { ++ switch (opt->type) { ++ case Opt_add: ++ fallthrough; ++ case Opt_append: ++ fallthrough; ++ case Opt_prepend: ++ kfree(opt->add.pathname); ++ path_put(&opt->add.path); ++ break; ++ case Opt_del: ++ kfree(opt->del.pathname); ++ fallthrough; ++ case Opt_idel: ++ path_put(&opt->del.h_path); ++ break; ++ case Opt_mod: ++ kfree(opt->mod.path); ++ fallthrough; ++ case Opt_imod: ++ dput(opt->mod.h_root); ++ break; ++ case Opt_xino: ++ kfree(opt->xino.path); ++ fput(opt->xino.file); ++ break; ++ } ++ opt++; ++ } ++} ++ ++static void au_fsctx_free(struct fs_context *fc) ++{ ++ struct au_fsctx_opts *a = fc->fs_private; ++ ++ /* fs_type=%p, root=%pD */ ++ AuDbg("fc %p{sb_flags 0x%x, sb_flags_mask 0x%x, purpose %u\n", ++ fc, fc->sb_flags, fc->sb_flags_mask, fc->purpose); ++ ++ kobject_put(&a->sbinfo->si_kobj); ++ au_fsctx_opts_free(&a->opts); ++ free_page((unsigned long)a->opts.opt); ++ au_kfree_rcu(a); ++} ++ ++static const struct fs_context_operations au_fsctx_ops = { ++ .free = au_fsctx_free, ++ .parse_param = au_fsctx_parse_param, ++ .parse_monolithic = au_fsctx_parse_monolithic, ++ .get_tree = au_fsctx_get_tree, ++ .reconfigure = au_fsctx_reconfigure ++ /* ++ * nfs4 requires ->dup()? No. ++ * I don't know what is this ->dup() for. ++ */ ++}; ++ ++int aufs_fsctx_init(struct fs_context *fc) ++{ ++ int err; ++ struct au_fsctx_opts *a; ++ ++ /* fs_type=%p, root=%pD */ ++ AuDbg("fc %p{sb_flags 0x%x, sb_flags_mask 0x%x, purpose %u\n", ++ fc, fc->sb_flags, fc->sb_flags_mask, fc->purpose); ++ ++ /* they will be freed by au_fsctx_free() */ ++ err = -ENOMEM; ++ a = kzalloc(sizeof(*a), GFP_NOFS); ++ if (unlikely(!a)) ++ goto out; ++ a->bindex = 0; ++ a->opts.opt = (void *)__get_free_page(GFP_NOFS); ++ if (unlikely(!a->opts.opt)) ++ goto out_a; ++ a->opt = a->opts.opt; ++ a->opt->type = Opt_tail; ++ a->opts.max_opt = PAGE_SIZE / sizeof(*a->opts.opt); ++ a->opt_tail = a->opt + a->opts.max_opt - 1; ++ a->opts.sb_flags = fc->sb_flags; ++ ++ a->sb = NULL; ++ if (fc->root) { ++ AuDebugOn(fc->purpose != FS_CONTEXT_FOR_RECONFIGURE); ++ a->opts.flags = AuOpts_REMOUNT; ++ a->sb = fc->root->d_sb; ++ a->sbinfo = au_sbi(a->sb); ++ kobject_get(&a->sbinfo->si_kobj); ++ } else { ++ a->sbinfo = au_si_alloc(a->sb); ++ AuDebugOn(!a->sbinfo); ++ err = PTR_ERR(a->sbinfo); ++ if (IS_ERR(a->sbinfo)) ++ goto out_opt; ++ au_rw_write_unlock(&a->sbinfo->si_rwsem); ++ } ++ ++ err = 0; ++ fc->fs_private = a; ++ fc->ops = &au_fsctx_ops; ++ goto out; /* success */ ++ ++out_opt: ++ free_page((unsigned long)a->opts.opt); ++out_a: ++ au_kfree_rcu(a); ++out: ++ AuTraceErr(err); ++ return err; ++} diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h --- /usr/share/empty/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/fstype.h 2019-07-11 15:42:14.465571210 +0200 ++++ linux/fs/aufs/fstype.h 2022-10-26 22:30:38.465982192 +0200 @@ -0,0 +1,401 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -16793,11 +17835,11 @@ diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h +#endif /* __AUFS_FSTYPE_H__ */ diff -urN /usr/share/empty/fs/aufs/hbl.h linux/fs/aufs/hbl.h --- /usr/share/empty/fs/aufs/hbl.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/hbl.h 2019-07-11 15:42:14.465571210 +0200 ++++ linux/fs/aufs/hbl.h 2022-10-26 22:30:38.465982192 +0200 @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2017-2019 Junjiro R. Okajima ++ * Copyright (C) 2017-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -16862,11 +17904,11 @@ diff -urN /usr/share/empty/fs/aufs/hbl.h linux/fs/aufs/hbl.h +#endif /* __AUFS_HBL_H__ */ diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c --- /usr/share/empty/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/hfsnotify.c 2019-07-11 15:42:14.465571210 +0200 ++++ linux/fs/aufs/hfsnotify.c 2022-10-26 22:30:38.465982192 +0200 @@ -0,0 +1,288 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -17026,8 +18068,8 @@ diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c +} + +static int au_hfsn_handle_event(struct fsnotify_group *group, -+ struct inode *inode, + u32 mask, const void *data, int data_type, ++ struct inode *dir, + const struct qstr *file_name, u32 cookie, + struct fsnotify_iter_info *iter_info) +{ @@ -17044,7 +18086,7 @@ diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c + if (mask & (FS_IN_IGNORED | FS_UNMOUNT)) + goto out; + -+ h_dir = inode; ++ h_dir = dir; + h_inode = NULL; +#ifdef AuDbgHnotify + au_debug_on(); @@ -17154,11 +18196,11 @@ diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c +}; diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c --- /usr/share/empty/fs/aufs/hfsplus.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/hfsplus.c 2019-07-11 15:42:14.465571210 +0200 ++++ linux/fs/aufs/hfsplus.c 2022-10-26 22:30:38.465982192 +0200 @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2010-2019 Junjiro R. Okajima ++ * Copyright (C) 2010-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -17218,11 +18260,11 @@ diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c +} diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c --- /usr/share/empty/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/hnotify.c 2019-07-11 15:42:14.465571210 +0200 -@@ -0,0 +1,721 @@ ++++ linux/fs/aufs/hnotify.c 2022-10-26 22:30:38.465982192 +0200 +@@ -0,0 +1,715 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -17404,12 +18446,6 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c + +out_dpages: + au_dpages_free(&dpages); -+ -+#if 0 -+ /* discard children */ -+ dentry_unhash(dentry); -+ dput(dentry); -+#endif +out: + return err; +} @@ -17812,7 +18848,7 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c + case FS_MOVED_TO: + au_fset_hnjob(flags[AuHn_CHILD], XINO0); + au_fset_hnjob(flags[AuHn_CHILD], MNTPNT); -+ /*FALLTHROUGH*/ ++ fallthrough; + case FS_CREATE: + AuDebugOn(!h_child_name); + break; @@ -17943,11 +18979,11 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c +} diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c --- /usr/share/empty/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/iinfo.c 2019-07-11 15:42:14.468904634 +0200 ++++ linux/fs/aufs/iinfo.c 2022-10-26 22:30:38.469315525 +0200 @@ -0,0 +1,286 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -18233,11 +19269,11 @@ diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c +} diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c --- /usr/share/empty/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/inode.c 2019-07-11 15:42:14.468904634 +0200 -@@ -0,0 +1,529 @@ ++++ linux/fs/aufs/inode.c 2022-10-26 22:30:38.469315525 +0200 +@@ -0,0 +1,531 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -18449,7 +19485,7 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c + struct dentry *h_dentry; + struct inode *h_inode; + struct au_iinfo *iinfo; -+ struct inode_operations *iop; ++ const struct inode_operations *iop; + + IiMustWriteLock(inode); + @@ -18749,28 +19785,30 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c + return err; +} + -+int au_test_h_perm(struct inode *h_inode, int mask) ++int au_test_h_perm(struct user_namespace *h_userns, struct inode *h_inode, ++ int mask) +{ + if (uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) + return 0; -+ return inode_permission(h_inode, mask); ++ return inode_permission(h_userns, h_inode, mask); +} + -+int au_test_h_perm_sio(struct inode *h_inode, int mask) ++int au_test_h_perm_sio(struct user_namespace *h_userns, struct inode *h_inode, ++ int mask) +{ + if (au_test_nfs(h_inode->i_sb) + && (mask & MAY_WRITE) + && S_ISDIR(h_inode->i_mode)) + mask |= MAY_READ; /* force permission check */ -+ return au_test_h_perm(h_inode, mask); ++ return au_test_h_perm(h_userns, h_inode, mask); +} diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h --- /usr/share/empty/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/inode.h 2019-07-11 15:42:14.468904634 +0200 -@@ -0,0 +1,698 @@ ++++ linux/fs/aufs/inode.h 2022-10-26 22:30:38.469315525 +0200 +@@ -0,0 +1,705 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -18907,8 +19945,10 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h +struct inode *au_new_inode(struct dentry *dentry, int must_new); +int au_test_ro(struct super_block *sb, aufs_bindex_t bindex, + struct inode *inode); -+int au_test_h_perm(struct inode *h_inode, int mask); -+int au_test_h_perm_sio(struct inode *h_inode, int mask); ++int au_test_h_perm(struct user_namespace *h_userns, struct inode *h_inode, ++ int mask); ++int au_test_h_perm_sio(struct user_namespace *h_userns, struct inode *h_inode, ++ int mask); + +static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex, + ino_t h_ino, unsigned int d_type, ino_t *ino) @@ -18927,7 +19967,7 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h + AuIop_OTHER, + AuIop_Last +}; -+extern struct inode_operations aufs_iop[AuIop_Last], ++extern struct inode_operations aufs_iop[AuIop_Last], /* not const */ + aufs_iop_nogetattr[AuIop_Last]; + +/* au_wr_dir flags */ @@ -18977,24 +20017,27 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h +int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia, + struct au_icpup_args *a); + -+int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path, -+ int locked); ++int au_h_path_getattr(struct dentry *dentry, struct inode *inode, int force, ++ struct path *h_path, int locked); + +/* i_op_add.c */ +int au_may_add(struct dentry *dentry, aufs_bindex_t bindex, + struct dentry *h_parent, int isdir); -+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, -+ dev_t dev); -+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname); -+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode, -+ bool want_excl); ++int aufs_mknod(struct user_namespace *userns, struct inode *dir, ++ struct dentry *dentry, umode_t mode, dev_t dev); ++int aufs_symlink(struct user_namespace *userns, struct inode *dir, ++ struct dentry *dentry, const char *symname); ++int aufs_create(struct user_namespace *userns, struct inode *dir, ++ struct dentry *dentry, umode_t mode, bool want_excl); +struct vfsub_aopen_args; +int au_aopen_or_create(struct inode *dir, struct dentry *dentry, + struct vfsub_aopen_args *args); -+int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode); ++int aufs_tmpfile(struct user_namespace *userns, struct inode *dir, ++ struct dentry *dentry, umode_t mode); +int aufs_link(struct dentry *src_dentry, struct inode *dir, + struct dentry *dentry); -+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode); ++int aufs_mkdir(struct user_namespace *userns, struct inode *dir, ++ struct dentry *dentry, umode_t mode); + +/* i_op_del.c */ +int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup); @@ -19005,9 +20048,10 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h + +/* i_op_ren.c */ +int au_wbr(struct dentry *dentry, aufs_bindex_t btgt); -+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry, -+ struct inode *dir, struct dentry *dentry, -+ unsigned int flags); ++int aufs_rename(struct user_namespace *userns, ++ struct inode *_src_dir, struct dentry *_src_dentry, ++ struct inode *_dst_dir, struct dentry *_dst_dentry, ++ unsigned int _flags); + +/* iinfo.c */ +struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex); @@ -19077,19 +20121,20 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h + +#ifdef CONFIG_AUFS_XATTR +/* xattr.c */ -+int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags, ++int au_cpup_xattr(struct path *h_dst, struct path *h_src, int ignore_flags, + unsigned int verbose); +ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size); +void au_xattr_init(struct super_block *sb); +#else -+AuStubInt0(au_cpup_xattr, struct dentry *h_dst, struct dentry *h_src, ++AuStubInt0(au_cpup_xattr, struct path *h_dst, struct path *h_src, + int ignore_flags, unsigned int verbose); +AuStubVoid(au_xattr_init, struct super_block *sb); +#endif + +#ifdef CONFIG_FS_POSIX_ACL -+struct posix_acl *aufs_get_acl(struct inode *inode, int type); -+int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type); ++struct posix_acl *aufs_get_acl(struct inode *inode, int type, bool rcu); ++int aufs_set_acl(struct user_namespace *userns, struct inode *inode, ++ struct posix_acl *acl, int type); +#endif + +#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL) @@ -19363,7 +20408,7 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h + int (*alloc)(struct au_hinode *hinode); + + /* -+ * if it returns true, the the caller should free hinode->hi_notify, ++ * if it returns true, the caller should free hinode->hi_notify, + * otherwise ->free() frees it. + */ + int (*free)(struct au_hinode *hinode, @@ -19468,11 +20513,11 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h +#endif /* __AUFS_INODE_H__ */ diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c --- /usr/share/empty/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/ioctl.c 2019-07-11 15:42:14.468904634 +0200 ++++ linux/fs/aufs/ioctl.c 2022-10-26 22:30:38.469315525 +0200 @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -19692,11 +20737,11 @@ diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c +#endif diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c --- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/i_op_add.c 2019-07-11 15:42:14.468904634 +0200 -@@ -0,0 +1,936 @@ ++++ linux/fs/aufs/i_op_add.c 2022-10-26 22:30:38.469315525 +0200 +@@ -0,0 +1,941 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -20062,8 +21107,8 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c + return err; +} + -+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, -+ dev_t dev) ++int aufs_mknod(struct user_namespace *userns, struct inode *dir, ++ struct dentry *dentry, umode_t mode, dev_t dev) +{ + struct simple_arg arg = { + .type = Mknod, @@ -20075,7 +21120,8 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c + return add_simple(dir, dentry, &arg); +} + -+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) ++int aufs_symlink(struct user_namespace *userns, struct inode *dir, ++ struct dentry *dentry, const char *symname) +{ + struct simple_arg arg = { + .type = Symlink, @@ -20084,8 +21130,8 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c + return add_simple(dir, dentry, &arg); +} + -+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode, -+ bool want_excl) ++int aufs_create(struct user_namespace *userns, struct inode *dir, ++ struct dentry *dentry, umode_t mode, bool want_excl) +{ + struct simple_arg arg = { + .type = Creat, @@ -20112,7 +21158,8 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c + return add_simple(dir, dentry, &arg); +} + -+int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) ++int aufs_tmpfile(struct user_namespace *userns, struct inode *dir, ++ struct dentry *dentry, umode_t mode) +{ + int err; + aufs_bindex_t bindex; @@ -20120,6 +21167,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c + struct dentry *parent, *h_parent, *h_dentry; + struct inode *h_dir, *inode; + struct vfsmount *h_mnt; ++ struct user_namespace *h_userns; + struct au_wr_dir_args wr_dir_args = { + .force_btgt = -1, + .flags = AuWrDir_TMPFILE @@ -20166,8 +21214,9 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c + if (unlikely(err)) + goto out_parent; + ++ h_userns = mnt_user_ns(h_mnt); + h_parent = au_h_dptr(parent, bindex); -+ h_dentry = vfs_tmpfile(h_parent, mode, /*open_flag*/0); ++ h_dentry = vfs_tmpfile(h_userns, h_parent, mode, /*open_flag*/0); + if (IS_ERR(h_dentry)) { + err = PTR_ERR(h_dentry); + goto out_mnt; @@ -20523,7 +21572,8 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c + return err; +} + -+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) ++int aufs_mkdir(struct user_namespace *userns, struct inode *dir, ++ struct dentry *dentry, umode_t mode) +{ + int err, rerr; + aufs_bindex_t bindex; @@ -20632,11 +21682,11 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c +} diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c --- /usr/share/empty/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/i_op.c 2019-09-16 09:38:43.216175640 +0200 -@@ -0,0 +1,1505 @@ ++++ linux/fs/aufs/i_op.c 2022-10-26 22:30:38.469315525 +0200 +@@ -0,0 +1,1512 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -20659,7 +21709,6 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c +#include +#include +#include -+#include +#include +#include "aufs.h" + @@ -20668,6 +21717,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c +{ + int err; + const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND)); ++ struct user_namespace *h_userns; + + err = -EPERM; + if (write_mask && IS_IMMUTABLE(h_inode)) @@ -20687,19 +21737,21 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c + * - nfs always sets SB_POSIXACL regardless its mount option 'noacl.' + * in this case, generic_permission() returns -EOPNOTSUPP. + */ ++ h_userns = mnt_user_ns(h_path->mnt); + if ((write_mask && !au_br_writable(brperm)) + || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode) + && write_mask && !(mask & MAY_READ)) + || !h_inode->i_op->permission) { + /* AuLabel(generic_permission); */ + /* AuDbg("get_acl %ps\n", h_inode->i_op->get_acl); */ -+ err = generic_permission(h_inode, mask); ++ err = generic_permission(h_userns, h_inode, mask); + if (err == -EOPNOTSUPP && au_test_nfs_noacl(h_inode)) -+ err = h_inode->i_op->permission(h_inode, mask); ++ err = h_inode->i_op->permission(h_userns, h_inode, ++ mask); + AuTraceErr(err); + } else { + /* AuLabel(h_inode->permission); */ -+ err = h_inode->i_op->permission(h_inode, mask); ++ err = h_inode->i_op->permission(h_userns, h_inode, mask); + AuTraceErr(err); + } + @@ -20708,24 +21760,12 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c + if (!err) + err = security_inode_permission(h_inode, mask); + -+#if 0 -+ if (!err) { -+ /* todo: do we need to call ima_path_check()? */ -+ struct path h_path = { -+ .dentry = -+ .mnt = h_mnt -+ }; -+ err = ima_path_check(&h_path, -+ mask & (MAY_READ | MAY_WRITE | MAY_EXEC), -+ IMA_COUNT_LEAVE); -+ } -+#endif -+ +out: + return err; +} + -+static int aufs_permission(struct inode *inode, int mask) ++static int aufs_permission(struct user_namespace *userns, struct inode *inode, ++ int mask) +{ + int err; + aufs_bindex_t bindex, bbot; @@ -20742,7 +21782,13 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c + sb = inode->i_sb; + si_read_lock(sb, AuLock_FLUSH); + ii_read_lock_child(inode); -+#if 0 ++#if 0 /* reserved for future use */ ++ /* ++ * This test may be rather 'too much' since the test is essentially done ++ * in the aufs_lookup(). Theoretically it is possible that the inode ++ * generation doesn't match to the superblock's here. But it isn't a ++ * big deal I suppose. ++ */ + err = au_iigen_test(inode, au_sigen(sb)); + if (unlikely(err)) + goto out; @@ -20860,7 +21906,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c + if (inode) + atomic_inc(&inode->i_count); + ret = d_splice_alias(inode, dentry); -+#if 0 ++#if 0 /* reserved for future use */ + if (unlikely(d_need_lookup(dentry))) { + spin_lock(&dentry->d_lock); + dentry->d_flags &= ~DCACHE_NEED_LOOKUP; @@ -21292,7 +22338,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c +{ + if (p->hdir) { + au_pin_hdir_set_owner(p, p->task); -+ rwsem_release(&p->hdir->hi_inode->i_rwsem.dep_map, 1, _RET_IP_); ++ rwsem_release(&p->hdir->hi_inode->i_rwsem.dep_map, _RET_IP_); + } +} + @@ -21567,18 +22613,20 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c + return err; +} + -+static int aufs_setattr(struct dentry *dentry, struct iattr *ia) ++static int aufs_setattr(struct user_namespace *userns, struct dentry *dentry, ++ struct iattr *ia) +{ + int err; + struct inode *inode, *delegated; + struct super_block *sb; + struct file *file; + struct au_icpup_args *a; ++ struct user_namespace *h_userns; + + inode = d_inode(dentry); + IMustLock(inode); + -+ err = setattr_prepare(dentry, ia); ++ err = setattr_prepare(userns, dentry, ia); + if (unlikely(err)) + goto out; + @@ -21671,8 +22719,10 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c + * regardless aufs 'acl' option setting. + * why don't all acl-aware fs call this func from their ->setattr()? + */ -+ if (!err && (ia->ia_valid & ATTR_MODE)) -+ err = vfsub_acl_chmod(a->h_inode, ia->ia_mode); ++ if (!err && (ia->ia_valid & ATTR_MODE)) { ++ h_userns = mnt_user_ns(a->h_path.mnt); ++ err = vfsub_acl_chmod(h_userns, a->h_inode, ia->ia_mode); ++ } + if (!err) + au_cpup_attr_changeable(inode); + @@ -21734,6 +22784,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c + struct super_block *sb; + struct au_icpup_args *a; + struct inode *h_inode; ++ struct user_namespace *h_userns; + + IMustLock(inode); + @@ -21752,23 +22803,25 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c + err = au_h_path_to_set_attr(dentry, a, &h_path); + if (unlikely(err)) + goto out_di; ++ h_userns = mnt_user_ns(h_path.mnt); + + inode_unlock(a->h_inode); + switch (arg->type) { + case AU_XATTR_SET: + AuDebugOn(d_is_negative(h_path.dentry)); -+ err = vfsub_setxattr(h_path.dentry, ++ err = vfsub_setxattr(h_userns, h_path.dentry, + arg->u.set.name, arg->u.set.value, + arg->u.set.size, arg->u.set.flags); + break; + case AU_ACL_SET: + err = -EOPNOTSUPP; + h_inode = d_inode(h_path.dentry); -+ if (h_inode->i_op->set_acl) ++ if (h_inode->i_op->set_acl) { + /* this will call posix_acl_update_mode */ -+ err = h_inode->i_op->set_acl(h_inode, ++ err = h_inode->i_op->set_acl(h_userns, h_inode, + arg->u.acl_set.acl, + arg->u.acl_set.type); ++ } + break; + } + if (!err) @@ -21823,15 +22876,14 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c + * returns zero or negative (an error). + * @dentry will be read-locked in success. + */ -+int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path, -+ int locked) ++int au_h_path_getattr(struct dentry *dentry, struct inode *inode, int force, ++ struct path *h_path, int locked) +{ + int err; + unsigned int mnt_flags, sigen; + unsigned char udba_none; + aufs_bindex_t bindex; + struct super_block *sb, *h_sb; -+ struct inode *inode; + + h_path->mnt = NULL; + h_path->dentry = NULL; @@ -21872,7 +22924,11 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c + di_read_lock_child(dentry, AuLock_IR); + +body: -+ inode = d_inode(dentry); ++ if (!inode) { ++ inode = d_inode(dentry); ++ if (unlikely(!inode)) ++ goto out; ++ } + bindex = au_ibtop(inode); + h_path->mnt = au_sbr_mnt(sb, bindex); + h_sb = h_path->mnt->mnt_sb; @@ -21896,8 +22952,8 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c + return err; +} + -+static int aufs_getattr(const struct path *path, struct kstat *st, -+ u32 request, unsigned int query) ++static int aufs_getattr(struct user_namespace *userns, const struct path *path, ++ struct kstat *st, u32 request, unsigned int query) +{ + int err; + unsigned char positive; @@ -21912,7 +22968,8 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c + err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); + if (unlikely(err)) + goto out; -+ err = au_h_path_getattr(dentry, /*force*/0, &h_path, /*locked*/0); ++ err = au_h_path_getattr(dentry, /*inode*/NULL, /*force*/0, &h_path, ++ /*locked*/0); + if (unlikely(err)) + goto out_si; + if (unlikely(!h_path.dentry)) @@ -21933,7 +22990,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c + goto out_di; + +out_fill: -+ generic_fillattr(inode, st); ++ generic_fillattr(userns, inode, st); +out_di: + di_read_unlock(dentry, AuLock_IR); +out_si: @@ -22141,11 +23198,11 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c +}; diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c --- /usr/share/empty/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/i_op_del.c 2019-07-11 15:42:14.468904634 +0200 -@@ -0,0 +1,513 @@ ++++ linux/fs/aufs/i_op_del.c 2022-10-26 22:30:38.469315525 +0200 +@@ -0,0 +1,522 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -22239,6 +23296,10 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c + umode_t h_mode; + struct dentry *h_dentry, *h_latest; + struct inode *h_inode; ++ struct path h_ppath; ++ struct super_block *sb; ++ struct au_branch *br; ++ struct user_namespace *h_userns; + + h_dentry = au_h_dptr(dentry, bindex); + if (d_really_is_positive(dentry)) { @@ -22276,12 +23337,17 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c + * let's try heavy test. + */ + err = -EACCES; -+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1) -+ && au_test_h_perm(d_inode(h_parent), ++ sb = dentry->d_sb; ++ br = au_sbr(sb, bindex); ++ h_userns = au_br_userns(br); ++ if (unlikely(!au_opt_test(au_mntflags(sb), DIRPERM1) ++ && au_test_h_perm(h_userns, d_inode(h_parent), + MAY_EXEC | MAY_WRITE))) + goto out; + -+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent); ++ h_ppath.dentry = h_parent; ++ h_ppath.mnt = au_br_mnt(br); ++ h_latest = au_sio_lkup_one(h_userns, &dentry->d_name, &h_ppath); + err = -EIO; + if (IS_ERR(h_latest)) + goto out; @@ -22658,11 +23724,11 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c +} diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c --- /usr/share/empty/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/i_op_ren.c 2019-07-11 15:42:14.468904634 +0200 -@@ -0,0 +1,1250 @@ ++++ linux/fs/aufs/i_op_ren.c 2022-10-26 22:30:38.469315525 +0200 +@@ -0,0 +1,1257 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -22812,9 +23878,12 @@ diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c +{ + int rerr; + struct inode *delegated; ++ struct path h_ppath = { ++ .dentry = a->src_h_parent, ++ .mnt = a->h_path.mnt ++ }; + -+ a->h_path.dentry = vfsub_lkup_one(&a->src_dentry->d_name, -+ a->src_h_parent); ++ a->h_path.dentry = vfsub_lkup_one(&a->src_dentry->d_name, &h_ppath); + rerr = PTR_ERR(a->h_path.dentry); + if (IS_ERR(a->h_path.dentry)) { + RevertFailure("lkup one %pd", a->src_dentry); @@ -22841,9 +23910,12 @@ diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c +{ + int rerr; + struct inode *delegated; ++ struct path h_ppath = { ++ .dentry = a->dst_h_parent, ++ .mnt = a->h_path.mnt ++ }; + -+ a->h_path.dentry = vfsub_lkup_one(&a->dst_dentry->d_name, -+ a->dst_h_parent); ++ a->h_path.dentry = vfsub_lkup_one(&a->dst_dentry->d_name, &h_ppath); + rerr = PTR_ERR(a->h_path.dentry); + if (IS_ERR(a->h_path.dentry)) { + RevertFailure("lkup one %pd", a->dst_dentry); @@ -23077,7 +24149,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c + } + + BUG_ON(d_is_positive(a->dst_h_dentry) && a->src_btop != a->btgt); -+#if 0 ++#if 0 /* debugging */ + BUG_ON(!au_ftest_ren(a->auren_flags, DIRREN) + && d_is_positive(a->dst_h_dentry) + && a->src_btop != a->btgt); @@ -23615,7 +24687,8 @@ diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c + +/* ---------------------------------------------------------------------- */ + -+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry, ++int aufs_rename(struct user_namespace *userns, ++ struct inode *_src_dir, struct dentry *_src_dentry, + struct inode *_dst_dir, struct dentry *_dst_dentry, + unsigned int _flags) +{ @@ -23912,7 +24985,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c +} diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig --- /usr/share/empty/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/Kconfig 2019-07-11 15:42:14.458904362 +0200 ++++ linux/fs/aufs/Kconfig 2022-10-26 22:30:38.459315526 +0200 @@ -0,0 +1,199 @@ +# SPDX-License-Identifier: GPL-2.0 +config AUFS_FS @@ -24040,7 +25113,7 @@ diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig + his child on the lower branch, since it is a bad idea to issue + rename(2) internally for every lower branch. But user may not + accept this behaviour. So here is a workaround to allow such -+ rename(2) and store some extra infromation on the writable ++ rename(2) and store some extra information on the writable + branch. Obviously this costs high (and I don't like it). + To use this feature, you need to enable this configuration AND + to specify the mount option `dirren.' @@ -24115,11 +25188,11 @@ diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig +endif diff -urN /usr/share/empty/fs/aufs/lcnt.h linux/fs/aufs/lcnt.h --- /usr/share/empty/fs/aufs/lcnt.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/lcnt.h 2019-07-11 15:42:14.468904634 +0200 ++++ linux/fs/aufs/lcnt.h 2022-10-26 22:30:38.469315525 +0200 @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2018-2019 Junjiro R. Okajima ++ * Copyright (C) 2018-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -24305,11 +25378,11 @@ diff -urN /usr/share/empty/fs/aufs/lcnt.h linux/fs/aufs/lcnt.h +#endif /* __AUFS_LCNT_H__ */ diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c --- /usr/share/empty/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/loop.c 2019-07-11 15:42:14.468904634 +0200 ++++ linux/fs/aufs/loop.c 2022-10-26 22:30:38.469315525 +0200 @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -24457,11 +25530,11 @@ diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c +} diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h --- /usr/share/empty/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/loop.h 2019-07-11 15:42:14.468904634 +0200 ++++ linux/fs/aufs/loop.h 2022-10-26 22:30:38.469315525 +0200 @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -24516,7 +25589,7 @@ diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h +#endif /* __AUFS_LOOP_H__ */ diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk --- /usr/share/empty/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/magic.mk 2019-07-11 15:42:14.468904634 +0200 ++++ linux/fs/aufs/magic.mk 2022-10-26 22:30:38.469315525 +0200 @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-2.0 + @@ -24551,7 +25624,7 @@ diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk +endif diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile --- /usr/share/empty/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/Makefile 2019-07-11 15:42:14.462237786 +0200 ++++ linux/fs/aufs/Makefile 2022-10-26 22:30:38.459315526 +0200 @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: GPL-2.0 + @@ -24572,7 +25645,7 @@ diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile +endif + +obj-$(CONFIG_AUFS_FS) += aufs.o -+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \ ++aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o fsctx.o \ + wkq.o vfsub.o dcsub.o \ + cpup.o whout.o wbr_policy.o \ + dinfo.o dentry.o \ @@ -24601,11 +25674,11 @@ diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile +aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c --- /usr/share/empty/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/module.c 2019-07-11 15:42:14.468904634 +0200 ++++ linux/fs/aufs/module.c 2022-10-26 22:30:38.469315525 +0200 @@ -0,0 +1,273 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -24878,11 +25951,11 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c +module_exit(aufs_exit); diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h --- /usr/share/empty/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/module.h 2019-07-11 15:42:14.468904634 +0200 ++++ linux/fs/aufs/module.h 2022-10-26 22:30:38.469315525 +0200 @@ -0,0 +1,166 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -24979,7 +26052,7 @@ diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h +static inline int au_kmidx_sub(size_t sz, size_t new_sz) +{ +#ifndef CONFIG_SLOB -+ return kmalloc_index(sz) - kmalloc_index(new_sz); ++ return __kmalloc_index(sz, false) - __kmalloc_index(new_sz, false); +#else + return -1; /* SLOB is untested */ +#endif @@ -25048,11 +26121,11 @@ diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h +#endif /* __AUFS_MODULE_H__ */ diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c --- /usr/share/empty/fs/aufs/mvdown.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/mvdown.c 2019-07-11 15:42:14.472238057 +0200 ++++ linux/fs/aufs/mvdown.c 2022-10-26 22:30:38.469315525 +0200 @@ -0,0 +1,706 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2011-2019 Junjiro R. Okajima ++ * Copyright (C) 2011-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -25758,11 +26831,11 @@ diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c +} diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c --- /usr/share/empty/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/opts.c 2019-09-16 09:38:43.216175640 +0200 -@@ -0,0 +1,1880 @@ ++++ linux/fs/aufs/opts.c 2022-10-26 22:30:38.469315525 +0200 +@@ -0,0 +1,1032 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -25782,172 +26855,12 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + * mount options/flags + */ + -+#include +#include /* a distribution requires */ +#include +#include "aufs.h" + +/* ---------------------------------------------------------------------- */ + -+enum { -+ Opt_br, -+ Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend, -+ Opt_idel, Opt_imod, -+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, -+ Opt_rdblk_def, Opt_rdhash_def, -+ Opt_xino, Opt_noxino, -+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino, -+ Opt_trunc_xino_path, Opt_itrunc_xino, -+ Opt_trunc_xib, Opt_notrunc_xib, -+ Opt_shwh, Opt_noshwh, -+ Opt_plink, Opt_noplink, Opt_list_plink, -+ Opt_udba, -+ Opt_dio, Opt_nodio, -+ Opt_diropq_a, Opt_diropq_w, -+ Opt_warn_perm, Opt_nowarn_perm, -+ Opt_wbr_copyup, Opt_wbr_create, -+ Opt_fhsm_sec, -+ Opt_verbose, Opt_noverbose, -+ Opt_sum, Opt_nosum, Opt_wsum, -+ Opt_dirperm1, Opt_nodirperm1, -+ Opt_dirren, Opt_nodirren, -+ Opt_acl, Opt_noacl, -+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err -+}; -+ -+static match_table_t options = { -+ {Opt_br, "br=%s"}, -+ {Opt_br, "br:%s"}, -+ -+ {Opt_add, "add=%d:%s"}, -+ {Opt_add, "add:%d:%s"}, -+ {Opt_add, "ins=%d:%s"}, -+ {Opt_add, "ins:%d:%s"}, -+ {Opt_append, "append=%s"}, -+ {Opt_append, "append:%s"}, -+ {Opt_prepend, "prepend=%s"}, -+ {Opt_prepend, "prepend:%s"}, -+ -+ {Opt_del, "del=%s"}, -+ {Opt_del, "del:%s"}, -+ /* {Opt_idel, "idel:%d"}, */ -+ {Opt_mod, "mod=%s"}, -+ {Opt_mod, "mod:%s"}, -+ /* {Opt_imod, "imod:%d:%s"}, */ -+ -+ {Opt_dirwh, "dirwh=%d"}, -+ -+ {Opt_xino, "xino=%s"}, -+ {Opt_noxino, "noxino"}, -+ {Opt_trunc_xino, "trunc_xino"}, -+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"}, -+ {Opt_notrunc_xino, "notrunc_xino"}, -+ {Opt_trunc_xino_path, "trunc_xino=%s"}, -+ {Opt_itrunc_xino, "itrunc_xino=%d"}, -+ /* {Opt_zxino, "zxino=%s"}, */ -+ {Opt_trunc_xib, "trunc_xib"}, -+ {Opt_notrunc_xib, "notrunc_xib"}, -+ -+#ifdef CONFIG_PROC_FS -+ {Opt_plink, "plink"}, -+#else -+ {Opt_ignore_silent, "plink"}, -+#endif -+ -+ {Opt_noplink, "noplink"}, -+ -+#ifdef CONFIG_AUFS_DEBUG -+ {Opt_list_plink, "list_plink"}, -+#endif -+ -+ {Opt_udba, "udba=%s"}, -+ -+ {Opt_dio, "dio"}, -+ {Opt_nodio, "nodio"}, -+ -+#ifdef CONFIG_AUFS_DIRREN -+ {Opt_dirren, "dirren"}, -+ {Opt_nodirren, "nodirren"}, -+#else -+ {Opt_ignore, "dirren"}, -+ {Opt_ignore_silent, "nodirren"}, -+#endif -+ -+#ifdef CONFIG_AUFS_FHSM -+ {Opt_fhsm_sec, "fhsm_sec=%d"}, -+#else -+ {Opt_ignore, "fhsm_sec=%d"}, -+#endif -+ -+ {Opt_diropq_a, "diropq=always"}, -+ {Opt_diropq_a, "diropq=a"}, -+ {Opt_diropq_w, "diropq=whiteouted"}, -+ {Opt_diropq_w, "diropq=w"}, -+ -+ {Opt_warn_perm, "warn_perm"}, -+ {Opt_nowarn_perm, "nowarn_perm"}, -+ -+ /* keep them temporary */ -+ {Opt_ignore_silent, "nodlgt"}, -+ {Opt_ignore, "clean_plink"}, -+ -+#ifdef CONFIG_AUFS_SHWH -+ {Opt_shwh, "shwh"}, -+#endif -+ {Opt_noshwh, "noshwh"}, -+ -+ {Opt_dirperm1, "dirperm1"}, -+ {Opt_nodirperm1, "nodirperm1"}, -+ -+ {Opt_verbose, "verbose"}, -+ {Opt_verbose, "v"}, -+ {Opt_noverbose, "noverbose"}, -+ {Opt_noverbose, "quiet"}, -+ {Opt_noverbose, "q"}, -+ {Opt_noverbose, "silent"}, -+ -+ {Opt_sum, "sum"}, -+ {Opt_nosum, "nosum"}, -+ {Opt_wsum, "wsum"}, -+ -+ {Opt_rdcache, "rdcache=%d"}, -+ {Opt_rdblk, "rdblk=%d"}, -+ {Opt_rdblk_def, "rdblk=def"}, -+ {Opt_rdhash, "rdhash=%d"}, -+ {Opt_rdhash_def, "rdhash=def"}, -+ -+ {Opt_wbr_create, "create=%s"}, -+ {Opt_wbr_create, "create_policy=%s"}, -+ {Opt_wbr_copyup, "cpup=%s"}, -+ {Opt_wbr_copyup, "copyup=%s"}, -+ {Opt_wbr_copyup, "copyup_policy=%s"}, -+ -+ /* generic VFS flag */ -+#ifdef CONFIG_FS_POSIX_ACL -+ {Opt_acl, "acl"}, -+ {Opt_noacl, "noacl"}, -+#else -+ {Opt_ignore, "acl"}, -+ {Opt_ignore_silent, "noacl"}, -+#endif -+ -+ /* internal use for the scripts */ -+ {Opt_ignore_silent, "si=%s"}, -+ -+ {Opt_br, "dirs=%s"}, -+ {Opt_ignore, "debug=%d"}, -+ {Opt_ignore, "delete=whiteout"}, -+ {Opt_ignore, "delete=all"}, -+ {Opt_ignore, "imap=%s"}, -+ -+ /* temporary workaround, due to old mount(8)? */ -+ {Opt_ignore_silent, "relatime"}, -+ -+ {Opt_err, NULL} -+}; -+ -+/* ---------------------------------------------------------------------- */ -+ +static const char *au_parser_pattern(int val, match_table_t tbl) +{ + struct match_token *p; @@ -26079,7 +26992,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + return q - str->a; +} + -+static int noinline_for_stack br_perm_val(char *perm) ++int au_br_perm_val(char *perm) +{ + int val, bad, sz; + char *p; @@ -26172,7 +27085,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + {-1, NULL} +}; + -+static int noinline_for_stack udba_val(char *str) ++int au_udba_val(char *str) +{ + substring_t args[MAX_OPT_ARGS]; + @@ -26243,8 +27156,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + return err; +} + -+static int noinline_for_stack -+au_wbr_create_val(char *str, struct au_opt_wbr_create *create) ++int au_wbr_create_val(char *str, struct au_opt_wbr_create *create) +{ + int err, e; + substring_t args[MAX_OPT_ARGS]; @@ -26269,7 +27181,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + err = e; + break; + } -+ /*FALLTHROUGH*/ ++ fallthrough; + case AuWbrCreate_MFS: + case AuWbrCreate_PMFS: + create->mfs_second = AUFS_MFS_DEF_SEC; @@ -26300,7 +27212,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + {-1, NULL} +}; + -+static int noinline_for_stack au_wbr_copyup_val(char *str) ++int au_wbr_copyup_val(char *str) +{ + substring_t args[MAX_OPT_ARGS]; + @@ -26314,235 +27226,8 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + +/* ---------------------------------------------------------------------- */ + -+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY; -+ -+static void dump_opts(struct au_opts *opts) -+{ -+#ifdef CONFIG_AUFS_DEBUG -+ /* reduce stack space */ -+ union { -+ struct au_opt_add *add; -+ struct au_opt_del *del; -+ struct au_opt_mod *mod; -+ struct au_opt_xino *xino; -+ struct au_opt_xino_itrunc *xino_itrunc; -+ struct au_opt_wbr_create *create; -+ } u; -+ struct au_opt *opt; -+ -+ opt = opts->opt; -+ while (opt->type != Opt_tail) { -+ switch (opt->type) { -+ case Opt_add: -+ u.add = &opt->add; -+ AuDbg("add {b%d, %s, 0x%x, %p}\n", -+ u.add->bindex, u.add->pathname, u.add->perm, -+ u.add->path.dentry); -+ break; -+ case Opt_del: -+ case Opt_idel: -+ u.del = &opt->del; -+ AuDbg("del {%s, %p}\n", -+ u.del->pathname, u.del->h_path.dentry); -+ break; -+ case Opt_mod: -+ case Opt_imod: -+ u.mod = &opt->mod; -+ AuDbg("mod {%s, 0x%x, %p}\n", -+ u.mod->path, u.mod->perm, u.mod->h_root); -+ break; -+ case Opt_append: -+ u.add = &opt->add; -+ AuDbg("append {b%d, %s, 0x%x, %p}\n", -+ u.add->bindex, u.add->pathname, u.add->perm, -+ u.add->path.dentry); -+ break; -+ case Opt_prepend: -+ u.add = &opt->add; -+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n", -+ u.add->bindex, u.add->pathname, u.add->perm, -+ u.add->path.dentry); -+ break; -+ case Opt_dirwh: -+ AuDbg("dirwh %d\n", opt->dirwh); -+ break; -+ case Opt_rdcache: -+ AuDbg("rdcache %d\n", opt->rdcache); -+ break; -+ case Opt_rdblk: -+ AuDbg("rdblk %u\n", opt->rdblk); -+ break; -+ case Opt_rdblk_def: -+ AuDbg("rdblk_def\n"); -+ break; -+ case Opt_rdhash: -+ AuDbg("rdhash %u\n", opt->rdhash); -+ break; -+ case Opt_rdhash_def: -+ AuDbg("rdhash_def\n"); -+ break; -+ case Opt_xino: -+ u.xino = &opt->xino; -+ AuDbg("xino {%s %pD}\n", u.xino->path, u.xino->file); -+ break; -+ case Opt_trunc_xino: -+ AuLabel(trunc_xino); -+ break; -+ case Opt_notrunc_xino: -+ AuLabel(notrunc_xino); -+ break; -+ case Opt_trunc_xino_path: -+ case Opt_itrunc_xino: -+ u.xino_itrunc = &opt->xino_itrunc; -+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex); -+ break; -+ case Opt_noxino: -+ AuLabel(noxino); -+ break; -+ case Opt_trunc_xib: -+ AuLabel(trunc_xib); -+ break; -+ case Opt_notrunc_xib: -+ AuLabel(notrunc_xib); -+ break; -+ case Opt_shwh: -+ AuLabel(shwh); -+ break; -+ case Opt_noshwh: -+ AuLabel(noshwh); -+ break; -+ case Opt_dirperm1: -+ AuLabel(dirperm1); -+ break; -+ case Opt_nodirperm1: -+ AuLabel(nodirperm1); -+ break; -+ case Opt_plink: -+ AuLabel(plink); -+ break; -+ case Opt_noplink: -+ AuLabel(noplink); -+ break; -+ case Opt_list_plink: -+ AuLabel(list_plink); -+ break; -+ case Opt_udba: -+ AuDbg("udba %d, %s\n", -+ opt->udba, au_optstr_udba(opt->udba)); -+ break; -+ case Opt_dio: -+ AuLabel(dio); -+ break; -+ case Opt_nodio: -+ AuLabel(nodio); -+ break; -+ case Opt_diropq_a: -+ AuLabel(diropq_a); -+ break; -+ case Opt_diropq_w: -+ AuLabel(diropq_w); -+ break; -+ case Opt_warn_perm: -+ AuLabel(warn_perm); -+ break; -+ case Opt_nowarn_perm: -+ AuLabel(nowarn_perm); -+ break; -+ case Opt_verbose: -+ AuLabel(verbose); -+ break; -+ case Opt_noverbose: -+ AuLabel(noverbose); -+ break; -+ case Opt_sum: -+ AuLabel(sum); -+ break; -+ case Opt_nosum: -+ AuLabel(nosum); -+ break; -+ case Opt_wsum: -+ AuLabel(wsum); -+ break; -+ case Opt_wbr_create: -+ u.create = &opt->wbr_create; -+ AuDbg("create %d, %s\n", u.create->wbr_create, -+ au_optstr_wbr_create(u.create->wbr_create)); -+ switch (u.create->wbr_create) { -+ case AuWbrCreate_MFSV: -+ case AuWbrCreate_PMFSV: -+ AuDbg("%d sec\n", u.create->mfs_second); -+ break; -+ case AuWbrCreate_MFSRR: -+ case AuWbrCreate_TDMFS: -+ AuDbg("%llu watermark\n", -+ u.create->mfsrr_watermark); -+ break; -+ case AuWbrCreate_MFSRRV: -+ case AuWbrCreate_TDMFSV: -+ case AuWbrCreate_PMFSRRV: -+ AuDbg("%llu watermark, %d sec\n", -+ u.create->mfsrr_watermark, -+ u.create->mfs_second); -+ break; -+ } -+ break; -+ case Opt_wbr_copyup: -+ AuDbg("copyup %d, %s\n", opt->wbr_copyup, -+ au_optstr_wbr_copyup(opt->wbr_copyup)); -+ break; -+ case Opt_fhsm_sec: -+ AuDbg("fhsm_sec %u\n", opt->fhsm_second); -+ break; -+ case Opt_dirren: -+ AuLabel(dirren); -+ break; -+ case Opt_nodirren: -+ AuLabel(nodirren); -+ break; -+ case Opt_acl: -+ AuLabel(acl); -+ break; -+ case Opt_noacl: -+ AuLabel(noacl); -+ break; -+ default: -+ BUG(); -+ } -+ opt++; -+ } -+#endif -+} -+ -+void au_opts_free(struct au_opts *opts) -+{ -+ struct au_opt *opt; -+ -+ opt = opts->opt; -+ while (opt->type != Opt_tail) { -+ switch (opt->type) { -+ case Opt_add: -+ case Opt_append: -+ case Opt_prepend: -+ path_put(&opt->add.path); -+ break; -+ case Opt_del: -+ case Opt_idel: -+ path_put(&opt->del.h_path); -+ break; -+ case Opt_mod: -+ case Opt_imod: -+ dput(opt->mod.h_root); -+ break; -+ case Opt_xino: -+ fput(opt->xino.file); -+ break; -+ } -+ opt++; -+ } -+} -+ -+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags, -+ aufs_bindex_t bindex) ++int au_opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags, ++ aufs_bindex_t bindex) +{ + int err; + struct au_opt_add *add = &opt->add; @@ -26555,10 +27240,10 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + if (p) { + *p++ = 0; + if (*p) -+ add->perm = br_perm_val(p); ++ add->perm = au_br_perm_val(p); + } + -+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path); ++ err = vfsub_kern_path(add->pathname, AuOpt_LkupDirFlags, &add->path); + if (!err) { + if (!p) { + add->perm = AuBrPerm_RO; @@ -26577,460 +27262,6 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + return err; +} + -+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[]) -+{ -+ int err; -+ -+ del->pathname = args[0].from; -+ AuDbg("del path %s\n", del->pathname); -+ -+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path); -+ if (unlikely(err)) -+ pr_err("lookup failed %s (%d)\n", del->pathname, err); -+ -+ return err; -+} -+ -+#if 0 /* reserved for future use */ -+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex, -+ struct au_opt_del *del, substring_t args[]) -+{ -+ int err; -+ struct dentry *root; -+ -+ err = -EINVAL; -+ root = sb->s_root; -+ aufs_read_lock(root, AuLock_FLUSH); -+ if (bindex < 0 || au_sbbot(sb) < bindex) { -+ pr_err("out of bounds, %d\n", bindex); -+ goto out; -+ } -+ -+ err = 0; -+ del->h_path.dentry = dget(au_h_dptr(root, bindex)); -+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex)); -+ -+out: -+ aufs_read_unlock(root, !AuLock_IR); -+ return err; -+} -+#endif -+ -+static int noinline_for_stack -+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[]) -+{ -+ int err; -+ struct path path; -+ char *p; -+ -+ err = -EINVAL; -+ mod->path = args[0].from; -+ p = strchr(mod->path, '='); -+ if (unlikely(!p)) { -+ pr_err("no permission %s\n", args[0].from); -+ goto out; -+ } -+ -+ *p++ = 0; -+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path); -+ if (unlikely(err)) { -+ pr_err("lookup failed %s (%d)\n", mod->path, err); -+ goto out; -+ } -+ -+ mod->perm = br_perm_val(p); -+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p); -+ mod->h_root = dget(path.dentry); -+ path_put(&path); -+ -+out: -+ return err; -+} -+ -+#if 0 /* reserved for future use */ -+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex, -+ struct au_opt_mod *mod, substring_t args[]) -+{ -+ int err; -+ struct dentry *root; -+ -+ err = -EINVAL; -+ root = sb->s_root; -+ aufs_read_lock(root, AuLock_FLUSH); -+ if (bindex < 0 || au_sbbot(sb) < bindex) { -+ pr_err("out of bounds, %d\n", bindex); -+ goto out; -+ } -+ -+ err = 0; -+ mod->perm = br_perm_val(args[1].from); -+ AuDbg("mod path %s, perm 0x%x, %s\n", -+ mod->path, mod->perm, args[1].from); -+ mod->h_root = dget(au_h_dptr(root, bindex)); -+ -+out: -+ aufs_read_unlock(root, !AuLock_IR); -+ return err; -+} -+#endif -+ -+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino, -+ substring_t args[]) -+{ -+ int err; -+ struct file *file; -+ -+ file = au_xino_create(sb, args[0].from, /*silent*/0, /*wbrtop*/0); -+ err = PTR_ERR(file); -+ if (IS_ERR(file)) -+ goto out; -+ -+ err = -EINVAL; -+ if (unlikely(file->f_path.dentry->d_sb == sb)) { -+ fput(file); -+ pr_err("%s must be outside\n", args[0].from); -+ goto out; -+ } -+ -+ err = 0; -+ xino->file = file; -+ xino->path = args[0].from; -+ -+out: -+ return err; -+} -+ -+static int noinline_for_stack -+au_opts_parse_xino_itrunc_path(struct super_block *sb, -+ struct au_opt_xino_itrunc *xino_itrunc, -+ substring_t args[]) -+{ -+ int err; -+ aufs_bindex_t bbot, bindex; -+ struct path path; -+ struct dentry *root; -+ -+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path); -+ if (unlikely(err)) { -+ pr_err("lookup failed %s (%d)\n", args[0].from, err); -+ goto out; -+ } -+ -+ xino_itrunc->bindex = -1; -+ root = sb->s_root; -+ aufs_read_lock(root, AuLock_FLUSH); -+ bbot = au_sbbot(sb); -+ for (bindex = 0; bindex <= bbot; bindex++) { -+ if (au_h_dptr(root, bindex) == path.dentry) { -+ xino_itrunc->bindex = bindex; -+ break; -+ } -+ } -+ aufs_read_unlock(root, !AuLock_IR); -+ path_put(&path); -+ -+ if (unlikely(xino_itrunc->bindex < 0)) { -+ pr_err("no such branch %s\n", args[0].from); -+ err = -EINVAL; -+ } -+ -+out: -+ return err; -+} -+ -+/* called without aufs lock */ -+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts) -+{ -+ int err, n, token; -+ aufs_bindex_t bindex; -+ unsigned char skipped; -+ struct dentry *root; -+ struct au_opt *opt, *opt_tail; -+ char *opt_str; -+ /* reduce the stack space */ -+ union { -+ struct au_opt_xino_itrunc *xino_itrunc; -+ struct au_opt_wbr_create *create; -+ } u; -+ struct { -+ substring_t args[MAX_OPT_ARGS]; -+ } *a; -+ -+ err = -ENOMEM; -+ a = kmalloc(sizeof(*a), GFP_NOFS); -+ if (unlikely(!a)) -+ goto out; -+ -+ root = sb->s_root; -+ err = 0; -+ bindex = 0; -+ opt = opts->opt; -+ opt_tail = opt + opts->max_opt - 1; -+ opt->type = Opt_tail; -+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) { -+ err = -EINVAL; -+ skipped = 0; -+ token = match_token(opt_str, options, a->args); -+ switch (token) { -+ case Opt_br: -+ err = 0; -+ while (!err && (opt_str = strsep(&a->args[0].from, ":")) -+ && *opt_str) { -+ err = opt_add(opt, opt_str, opts->sb_flags, -+ bindex++); -+ if (unlikely(!err && ++opt > opt_tail)) { -+ err = -E2BIG; -+ break; -+ } -+ opt->type = Opt_tail; -+ skipped = 1; -+ } -+ break; -+ case Opt_add: -+ if (unlikely(match_int(&a->args[0], &n))) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ bindex = n; -+ err = opt_add(opt, a->args[1].from, opts->sb_flags, -+ bindex); -+ if (!err) -+ opt->type = token; -+ break; -+ case Opt_append: -+ err = opt_add(opt, a->args[0].from, opts->sb_flags, -+ /*dummy bindex*/1); -+ if (!err) -+ opt->type = token; -+ break; -+ case Opt_prepend: -+ err = opt_add(opt, a->args[0].from, opts->sb_flags, -+ /*bindex*/0); -+ if (!err) -+ opt->type = token; -+ break; -+ case Opt_del: -+ err = au_opts_parse_del(&opt->del, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+#if 0 /* reserved for future use */ -+ case Opt_idel: -+ del->pathname = "(indexed)"; -+ if (unlikely(match_int(&args[0], &n))) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ err = au_opts_parse_idel(sb, n, &opt->del, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+#endif -+ case Opt_mod: -+ err = au_opts_parse_mod(&opt->mod, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+#ifdef IMOD /* reserved for future use */ -+ case Opt_imod: -+ u.mod->path = "(indexed)"; -+ if (unlikely(match_int(&a->args[0], &n))) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+#endif -+ case Opt_xino: -+ err = au_opts_parse_xino(sb, &opt->xino, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+ -+ case Opt_trunc_xino_path: -+ err = au_opts_parse_xino_itrunc_path -+ (sb, &opt->xino_itrunc, a->args); -+ if (!err) -+ opt->type = token; -+ break; -+ -+ case Opt_itrunc_xino: -+ u.xino_itrunc = &opt->xino_itrunc; -+ if (unlikely(match_int(&a->args[0], &n))) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ u.xino_itrunc->bindex = n; -+ aufs_read_lock(root, AuLock_FLUSH); -+ if (n < 0 || au_sbbot(sb) < n) { -+ pr_err("out of bounds, %d\n", n); -+ aufs_read_unlock(root, !AuLock_IR); -+ break; -+ } -+ aufs_read_unlock(root, !AuLock_IR); -+ err = 0; -+ opt->type = token; -+ break; -+ -+ case Opt_dirwh: -+ if (unlikely(match_int(&a->args[0], &opt->dirwh))) -+ break; -+ err = 0; -+ opt->type = token; -+ break; -+ -+ case Opt_rdcache: -+ if (unlikely(match_int(&a->args[0], &n))) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ if (unlikely(n > AUFS_RDCACHE_MAX)) { -+ pr_err("rdcache must be smaller than %d\n", -+ AUFS_RDCACHE_MAX); -+ break; -+ } -+ opt->rdcache = n; -+ err = 0; -+ opt->type = token; -+ break; -+ case Opt_rdblk: -+ if (unlikely(match_int(&a->args[0], &n) -+ || n < 0 -+ || n > KMALLOC_MAX_SIZE)) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ if (unlikely(n && n < NAME_MAX)) { -+ pr_err("rdblk must be larger than %d\n", -+ NAME_MAX); -+ break; -+ } -+ opt->rdblk = n; -+ err = 0; -+ opt->type = token; -+ break; -+ case Opt_rdhash: -+ if (unlikely(match_int(&a->args[0], &n) -+ || n < 0 -+ || n * sizeof(struct hlist_head) -+ > KMALLOC_MAX_SIZE)) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ opt->rdhash = n; -+ err = 0; -+ opt->type = token; -+ break; -+ -+ case Opt_trunc_xino: -+ case Opt_notrunc_xino: -+ case Opt_noxino: -+ case Opt_trunc_xib: -+ case Opt_notrunc_xib: -+ case Opt_shwh: -+ case Opt_noshwh: -+ case Opt_dirperm1: -+ case Opt_nodirperm1: -+ case Opt_plink: -+ case Opt_noplink: -+ case Opt_list_plink: -+ case Opt_dio: -+ case Opt_nodio: -+ case Opt_diropq_a: -+ case Opt_diropq_w: -+ case Opt_warn_perm: -+ case Opt_nowarn_perm: -+ case Opt_verbose: -+ case Opt_noverbose: -+ case Opt_sum: -+ case Opt_nosum: -+ case Opt_wsum: -+ case Opt_rdblk_def: -+ case Opt_rdhash_def: -+ case Opt_dirren: -+ case Opt_nodirren: -+ case Opt_acl: -+ case Opt_noacl: -+ err = 0; -+ opt->type = token; -+ break; -+ -+ case Opt_udba: -+ opt->udba = udba_val(a->args[0].from); -+ if (opt->udba >= 0) { -+ err = 0; -+ opt->type = token; -+ } else -+ pr_err("wrong value, %s\n", opt_str); -+ break; -+ -+ case Opt_wbr_create: -+ u.create = &opt->wbr_create; -+ u.create->wbr_create -+ = au_wbr_create_val(a->args[0].from, u.create); -+ if (u.create->wbr_create >= 0) { -+ err = 0; -+ opt->type = token; -+ } else -+ pr_err("wrong value, %s\n", opt_str); -+ break; -+ case Opt_wbr_copyup: -+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from); -+ if (opt->wbr_copyup >= 0) { -+ err = 0; -+ opt->type = token; -+ } else -+ pr_err("wrong value, %s\n", opt_str); -+ break; -+ -+ case Opt_fhsm_sec: -+ if (unlikely(match_int(&a->args[0], &n) -+ || n < 0)) { -+ pr_err("bad integer in %s\n", opt_str); -+ break; -+ } -+ if (sysaufs_brs) { -+ opt->fhsm_second = n; -+ opt->type = token; -+ } else -+ pr_warn("ignored %s\n", opt_str); -+ err = 0; -+ break; -+ -+ case Opt_ignore: -+ pr_warn("ignored %s\n", opt_str); -+ /*FALLTHROUGH*/ -+ case Opt_ignore_silent: -+ skipped = 1; -+ err = 0; -+ break; -+ case Opt_err: -+ pr_err("unknown option %s\n", opt_str); -+ break; -+ } -+ -+ if (!err && !skipped) { -+ if (unlikely(++opt > opt_tail)) { -+ err = -E2BIG; -+ opt--; -+ opt->type = Opt_tail; -+ break; -+ } -+ opt->type = Opt_tail; -+ } -+ } -+ -+ au_kfree_rcu(a); -+ dump_opts(opts); -+ if (unlikely(err)) -+ au_opts_free(opts); -+ -+out: -+ return err; -+} -+ +static int au_opt_wbr_create(struct super_block *sb, + struct au_opt_wbr_create *create) +{ @@ -27057,7 +27288,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + case AuWbrCreate_PMFSRR: + case AuWbrCreate_PMFSRRV: + sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark; -+ /*FALLTHROUGH*/ ++ fallthrough; + case AuWbrCreate_MFS: + case AuWbrCreate_MFSV: + case AuWbrCreate_PMFS: @@ -27096,12 +27327,13 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + break; + + case Opt_plink: -+ au_opt_set(sbinfo->si_mntflags, PLINK); -+ break; -+ case Opt_noplink: -+ if (au_opt_test(sbinfo->si_mntflags, PLINK)) -+ au_plink_put(sb, /*verbose*/1); -+ au_opt_clr(sbinfo->si_mntflags, PLINK); ++ if (opt->tf) ++ au_opt_set(sbinfo->si_mntflags, PLINK); ++ else { ++ if (au_opt_test(sbinfo->si_mntflags, PLINK)) ++ au_plink_put(sb, /*verbose*/1); ++ au_opt_clr(sbinfo->si_mntflags, PLINK); ++ } + break; + case Opt_list_plink: + if (au_opt_test(sbinfo->si_mntflags, PLINK)) @@ -27109,12 +27341,13 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + break; + + case Opt_dio: -+ au_opt_set(sbinfo->si_mntflags, DIO); -+ au_fset_opts(opts->flags, REFRESH_DYAOP); -+ break; -+ case Opt_nodio: -+ au_opt_clr(sbinfo->si_mntflags, DIO); -+ au_fset_opts(opts->flags, REFRESH_DYAOP); ++ if (opt->tf) { ++ au_opt_set(sbinfo->si_mntflags, DIO); ++ au_fset_opts(opts->flags, REFRESH_DYAOP); ++ } else { ++ au_opt_clr(sbinfo->si_mntflags, DIO); ++ au_fset_opts(opts->flags, REFRESH_DYAOP); ++ } + break; + + case Opt_fhsm_sec: @@ -27129,30 +27362,31 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + break; + + case Opt_warn_perm: -+ au_opt_set(sbinfo->si_mntflags, WARN_PERM); -+ break; -+ case Opt_nowarn_perm: -+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM); ++ if (opt->tf) ++ au_opt_set(sbinfo->si_mntflags, WARN_PERM); ++ else ++ au_opt_clr(sbinfo->si_mntflags, WARN_PERM); + break; + + case Opt_verbose: -+ au_opt_set(sbinfo->si_mntflags, VERBOSE); -+ break; -+ case Opt_noverbose: -+ au_opt_clr(sbinfo->si_mntflags, VERBOSE); ++ if (opt->tf) ++ au_opt_set(sbinfo->si_mntflags, VERBOSE); ++ else ++ au_opt_clr(sbinfo->si_mntflags, VERBOSE); + break; + + case Opt_sum: -+ au_opt_set(sbinfo->si_mntflags, SUM); ++ if (opt->tf) ++ au_opt_set(sbinfo->si_mntflags, SUM); ++ else { ++ au_opt_clr(sbinfo->si_mntflags, SUM); ++ au_opt_clr(sbinfo->si_mntflags, SUM_W); ++ } + break; + case Opt_wsum: + au_opt_clr(sbinfo->si_mntflags, SUM); + au_opt_set(sbinfo->si_mntflags, SUM_W); + break; -+ case Opt_nosum: -+ au_opt_clr(sbinfo->si_mntflags, SUM); -+ au_opt_clr(sbinfo->si_mntflags, SUM_W); -+ break; + + case Opt_wbr_create: + err = au_opt_wbr_create(sb, &opt->wbr_create); @@ -27173,35 +27407,29 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + case Opt_rdblk: + sbinfo->si_rdblk = opt->rdblk; + break; -+ case Opt_rdblk_def: -+ sbinfo->si_rdblk = AUFS_RDBLK_DEF; -+ break; + case Opt_rdhash: + sbinfo->si_rdhash = opt->rdhash; + break; -+ case Opt_rdhash_def: -+ sbinfo->si_rdhash = AUFS_RDHASH_DEF; -+ break; + + case Opt_shwh: -+ au_opt_set(sbinfo->si_mntflags, SHWH); -+ break; -+ case Opt_noshwh: -+ au_opt_clr(sbinfo->si_mntflags, SHWH); ++ if (opt->tf) ++ au_opt_set(sbinfo->si_mntflags, SHWH); ++ else ++ au_opt_clr(sbinfo->si_mntflags, SHWH); + break; + + case Opt_dirperm1: -+ au_opt_set(sbinfo->si_mntflags, DIRPERM1); -+ break; -+ case Opt_nodirperm1: -+ au_opt_clr(sbinfo->si_mntflags, DIRPERM1); ++ if (opt->tf) ++ au_opt_set(sbinfo->si_mntflags, DIRPERM1); ++ else ++ au_opt_clr(sbinfo->si_mntflags, DIRPERM1); + break; + + case Opt_trunc_xino: -+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO); -+ break; -+ case Opt_notrunc_xino: -+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO); ++ if (opt->tf) ++ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO); ++ else ++ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO); + break; + + case Opt_trunc_xino_path: @@ -27213,39 +27441,39 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + break; + + case Opt_trunc_xib: -+ au_fset_opts(opts->flags, TRUNC_XIB); -+ break; -+ case Opt_notrunc_xib: -+ au_fclr_opts(opts->flags, TRUNC_XIB); ++ if (opt->tf) ++ au_fset_opts(opts->flags, TRUNC_XIB); ++ else ++ au_fclr_opts(opts->flags, TRUNC_XIB); + break; + + case Opt_dirren: + err = 1; -+ if (!au_opt_test(sbinfo->si_mntflags, DIRREN)) { -+ err = au_dr_opt_set(sb); -+ if (!err) -+ err = 1; -+ } -+ if (err == 1) -+ au_opt_set(sbinfo->si_mntflags, DIRREN); -+ break; -+ case Opt_nodirren: -+ err = 1; -+ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) { -+ err = au_dr_opt_clr(sb, au_ftest_opts(opts->flags, -+ DR_FLUSHED)); -+ if (!err) -+ err = 1; ++ if (opt->tf) { ++ if (!au_opt_test(sbinfo->si_mntflags, DIRREN)) { ++ err = au_dr_opt_set(sb); ++ if (!err) ++ err = 1; ++ } ++ if (err == 1) ++ au_opt_set(sbinfo->si_mntflags, DIRREN); ++ } else { ++ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) { ++ err = au_dr_opt_clr(sb, au_ftest_opts(opts->flags, ++ DR_FLUSHED)); ++ if (!err) ++ err = 1; ++ } ++ if (err == 1) ++ au_opt_clr(sbinfo->si_mntflags, DIRREN); + } -+ if (err == 1) -+ au_opt_clr(sbinfo->si_mntflags, DIRREN); + break; + + case Opt_acl: -+ sb->s_flags |= SB_POSIXACL; -+ break; -+ case Opt_noacl: -+ sb->s_flags &= ~SB_POSIXACL; ++ if (opt->tf) ++ sb->s_flags |= SB_POSIXACL; ++ else ++ sb->s_flags &= ~SB_POSIXACL; + break; + + default: @@ -27277,7 +27505,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + /* Always goto add, not fallthrough */ + case Opt_prepend: + opt->add.bindex = 0; -+ /* fallthrough */ ++ fallthrough; + add: /* indented label */ + case Opt_add: + err = au_br_add(sb, &opt->add, @@ -27325,12 +27553,9 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + case Opt_xino: + err = au_xino_set(sb, &opt->xino, + !!au_ftest_opts(opts->flags, REMOUNT)); -+ if (unlikely(err)) -+ break; -+ -+ *opt_xino = &opt->xino; ++ if (!err) ++ *opt_xino = &opt->xino; + break; -+ + case Opt_noxino: + au_xino_clr(sb); + *opt_xino = (void *)-1; @@ -27389,7 +27614,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + if ((br->br_perm & AuBrAttr_ICEX) + && !h_dir->i_op->listxattr) + br->br_perm &= ~AuBrAttr_ICEX; -+#if 0 ++#if 0 /* untested */ + if ((br->br_perm & AuBrAttr_ICEX_SEC) + && (au_br_sb(br)->s_flags & SB_NOSEC)) + br->br_perm &= ~AuBrAttr_ICEX_SEC; @@ -27642,11 +27867,11 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c +} diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h --- /usr/share/empty/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/opts.h 2019-07-11 15:42:14.472238057 +0200 -@@ -0,0 +1,225 @@ ++++ linux/fs/aufs/opts.h 2022-10-26 22:30:38.469315525 +0200 +@@ -0,0 +1,263 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -27671,9 +27896,34 @@ diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h + +#ifdef __KERNEL__ + ++#include ++#include +#include + -+struct file; ++enum { ++ Opt_br, ++ Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend, ++ Opt_idel, Opt_imod, ++ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash, ++ Opt_xino, Opt_noxino, ++ Opt_trunc_xino, Opt_trunc_xino_v, ++ Opt_trunc_xino_path, Opt_itrunc_xino, ++ Opt_trunc_xib, ++ Opt_shwh, ++ Opt_plink, Opt_list_plink, ++ Opt_udba, ++ Opt_dio, ++ Opt_diropq, Opt_diropq_a, Opt_diropq_w, ++ Opt_warn_perm, ++ Opt_wbr_copyup, Opt_wbr_create, ++ Opt_fhsm_sec, ++ Opt_verbose, Opt_noverbose, ++ Opt_sum, Opt_wsum, ++ Opt_dirperm1, ++ Opt_dirren, ++ Opt_acl, ++ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err ++}; + +/* ---------------------------------------------------------------------- */ + @@ -27718,6 +27968,8 @@ diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h + | AuOpt_UDBA_REVAL \ + | AuOpt_UDBA_HNOTIFY) + ++#define AuOpt_LkupDirFlags (LOOKUP_FOLLOW | LOOKUP_DIRECTORY) ++ +#define au_opt_test(flags, name) (flags & AuOpt_##name) +#define au_opt_set(flags, name) do { \ + BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \ @@ -27770,6 +28022,8 @@ diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h + +/* ---------------------------------------------------------------------- */ + ++struct file; ++ +struct au_opt_add { + aufs_bindex_t bindex; + char *pathname; @@ -27819,6 +28073,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h + struct au_opt_wbr_create wbr_create; + int wbr_copyup; + unsigned int fhsm_second; ++ bool tf; /* generic flag, true or false */ + }; +}; + @@ -27852,14 +28107,18 @@ diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h +/* ---------------------------------------------------------------------- */ + +/* opts.c */ ++int au_br_perm_val(char *perm); +void au_optstr_br_perm(au_br_perm_str_t *str, int perm); ++int au_udba_val(char *str); +const char *au_optstr_udba(int udba); -+const char *au_optstr_wbr_copyup(int wbr_copyup); ++int au_wbr_create_val(char *str, struct au_opt_wbr_create *create); +const char *au_optstr_wbr_create(int wbr_create); ++int au_wbr_copyup_val(char *str); ++const char *au_optstr_wbr_copyup(int wbr_copyup); + -+void au_opts_free(struct au_opts *opts); ++int au_opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags, ++ aufs_bindex_t bindex); +struct super_block; -+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts); +int au_opts_verify(struct super_block *sb, unsigned long sb_flags, + unsigned int pending); +int au_opts_mount(struct super_block *sb, struct au_opts *opts); @@ -27867,15 +28126,19 @@ diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h + +unsigned int au_opt_udba(struct super_block *sb); + ++/* fsctx.c */ ++int aufs_fsctx_init(struct fs_context *fc); ++extern const struct fs_parameter_spec aufs_fsctx_paramspec[]; ++ +#endif /* __KERNEL__ */ +#endif /* __AUFS_OPTS_H__ */ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c --- /usr/share/empty/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/plink.c 2019-07-11 15:42:14.472238057 +0200 ++++ linux/fs/aufs/plink.c 2022-10-26 22:30:38.469315525 +0200 @@ -0,0 +1,516 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -28081,35 +28344,35 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c +struct au_do_plink_lkup_args { + struct dentry **errp; + struct qstr *tgtname; -+ struct dentry *h_parent; -+ struct au_branch *br; ++ struct path *h_ppath; +}; + +static struct dentry *au_do_plink_lkup(struct qstr *tgtname, -+ struct dentry *h_parent, -+ struct au_branch *br) ++ struct path *h_ppath) +{ + struct dentry *h_dentry; + struct inode *h_inode; + -+ h_inode = d_inode(h_parent); ++ h_inode = d_inode(h_ppath->dentry); + inode_lock_shared_nested(h_inode, AuLsc_I_CHILD2); -+ h_dentry = vfsub_lkup_one(tgtname, h_parent); ++ h_dentry = vfsub_lkup_one(tgtname, h_ppath); + inode_unlock_shared(h_inode); ++ + return h_dentry; +} + +static void au_call_do_plink_lkup(void *args) +{ + struct au_do_plink_lkup_args *a = args; -+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br); ++ *a->errp = au_do_plink_lkup(a->tgtname, a->h_ppath); +} + +/* lookup the plink-ed @inode under the branch at @bindex */ +struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex) +{ -+ struct dentry *h_dentry, *h_parent; ++ struct dentry *h_dentry; + struct au_branch *br; ++ struct path h_ppath; + int wkq_err; + char a[PLINK_NAME_LEN]; + struct qstr tgtname = QSTR_INIT(a, 0); @@ -28117,40 +28380,39 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c + AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM)); + + br = au_sbr(inode->i_sb, bindex); -+ h_parent = br->br_wbr->wbr_plink; ++ h_ppath.dentry = br->br_wbr->wbr_plink; ++ h_ppath.mnt = au_br_mnt(br); + tgtname.len = plink_name(a, sizeof(a), inode, bindex); + + if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) { + struct au_do_plink_lkup_args args = { + .errp = &h_dentry, + .tgtname = &tgtname, -+ .h_parent = h_parent, -+ .br = br ++ .h_ppath = &h_ppath + }; + + wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args); + if (unlikely(wkq_err)) + h_dentry = ERR_PTR(wkq_err); + } else -+ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br); ++ h_dentry = au_do_plink_lkup(&tgtname, &h_ppath); + + return h_dentry; +} + +/* create a pseudo-link */ -+static int do_whplink(struct qstr *tgt, struct dentry *h_parent, -+ struct dentry *h_dentry, struct au_branch *br) ++static int do_whplink(struct qstr *tgt, struct path *h_ppath, ++ struct dentry *h_dentry) +{ + int err; -+ struct path h_path = { -+ .mnt = au_br_mnt(br) -+ }; ++ struct path h_path; + struct inode *h_dir, *delegated; + -+ h_dir = d_inode(h_parent); ++ h_dir = d_inode(h_ppath->dentry); + inode_lock_nested(h_dir, AuLsc_I_CHILD2); ++ h_path.mnt = h_ppath->mnt; +again: -+ h_path.dentry = vfsub_lkup_one(tgt, h_parent); ++ h_path.dentry = vfsub_lkup_one(tgt, h_ppath); + err = PTR_ERR(h_path.dentry); + if (IS_ERR(h_path.dentry)) + goto out; @@ -28191,28 +28453,30 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c +struct do_whplink_args { + int *errp; + struct qstr *tgt; -+ struct dentry *h_parent; ++ struct path *h_ppath; + struct dentry *h_dentry; -+ struct au_branch *br; +}; + +static void call_do_whplink(void *args) +{ + struct do_whplink_args *a = args; -+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br); ++ *a->errp = do_whplink(a->tgt, a->h_ppath, a->h_dentry); +} + +static int whplink(struct dentry *h_dentry, struct inode *inode, -+ aufs_bindex_t bindex, struct au_branch *br) ++ aufs_bindex_t bindex) +{ + int err, wkq_err; ++ struct au_branch *br; + struct au_wbr *wbr; -+ struct dentry *h_parent; ++ struct path h_ppath; + char a[PLINK_NAME_LEN]; + struct qstr tgtname = QSTR_INIT(a, 0); + -+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr; -+ h_parent = wbr->wbr_plink; ++ br = au_sbr(inode->i_sb, bindex); ++ wbr = br->br_wbr; ++ h_ppath.dentry = wbr->wbr_plink; ++ h_ppath.mnt = au_br_mnt(br); + tgtname.len = plink_name(a, sizeof(a), inode, bindex); + + /* always superio. */ @@ -28220,15 +28484,14 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c + struct do_whplink_args args = { + .errp = &err, + .tgt = &tgtname, -+ .h_parent = h_parent, -+ .h_dentry = h_dentry, -+ .br = br ++ .h_ppath = &h_ppath, ++ .h_dentry = h_dentry + }; + wkq_err = au_wkq_wait(call_do_whplink, &args); + if (unlikely(wkq_err)) + err = wkq_err; + } else -+ err = do_whplink(&tgtname, h_parent, h_dentry, br); ++ err = do_whplink(&tgtname, &h_ppath, h_dentry); + + return err; +} @@ -28278,7 +28541,7 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c + if (cnt > AUFS_PLINK_WARN) + AuWarn1(msg ", %d\n", cnt); +#undef msg -+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex)); ++ err = whplink(h_dentry, inode, bindex); + if (unlikely(err)) { + pr_warn("err %d, damaged pseudo link.\n", err); + au_hbl_del(&icntnr->plink, hbl); @@ -28391,11 +28654,11 @@ diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c +} diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c --- /usr/share/empty/fs/aufs/poll.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/poll.c 2019-07-11 15:42:14.472238057 +0200 ++++ linux/fs/aufs/poll.c 2022-10-26 22:30:38.469315525 +0200 @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -28446,11 +28709,11 @@ diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c +} diff -urN /usr/share/empty/fs/aufs/posix_acl.c linux/fs/aufs/posix_acl.c --- /usr/share/empty/fs/aufs/posix_acl.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/posix_acl.c 2019-07-11 15:42:14.472238057 +0200 -@@ -0,0 +1,103 @@ ++++ linux/fs/aufs/posix_acl.c 2022-10-26 22:30:38.469315525 +0200 +@@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2014-2019 Junjiro R. Okajima ++ * Copyright (C) 2014-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -28473,7 +28736,7 @@ diff -urN /usr/share/empty/fs/aufs/posix_acl.c linux/fs/aufs/posix_acl.c +#include +#include "aufs.h" + -+struct posix_acl *aufs_get_acl(struct inode *inode, int type) ++struct posix_acl *aufs_get_acl(struct inode *inode, int type, bool rcu) +{ + struct posix_acl *acl; + int err; @@ -28481,12 +28744,16 @@ diff -urN /usr/share/empty/fs/aufs/posix_acl.c linux/fs/aufs/posix_acl.c + struct inode *h_inode; + struct super_block *sb; + ++ acl = ERR_PTR(-ECHILD); ++ if (rcu) ++ goto out; ++ + acl = NULL; + sb = inode->i_sb; + si_read_lock(sb, AuLock_FLUSH); + ii_read_lock_child(inode); + if (!(sb->s_flags & SB_POSIXACL)) -+ goto out; ++ goto unlock; + + bindex = au_ibtop(inode); + h_inode = au_h_iptr(inode, bindex); @@ -28495,23 +28762,27 @@ diff -urN /usr/share/empty/fs/aufs/posix_acl.c linux/fs/aufs/posix_acl.c + != (inode->i_mode & S_IFMT)))) { + err = au_busy_or_stale(); + acl = ERR_PTR(err); -+ goto out; ++ goto unlock; + } + + /* always topmost only */ + acl = get_acl(h_inode, type); -+ if (!IS_ERR_OR_NULL(acl)) ++ if (IS_ERR(acl)) ++ forget_cached_acl(inode, type); ++ else + set_cached_acl(inode, type, acl); + -+out: ++unlock: + ii_read_unlock(inode); + si_read_unlock(sb); + ++out: + AuTraceErrPtr(acl); + return acl; +} + -+int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type) ++int aufs_set_acl(struct user_namespace *userns, struct inode *inode, ++ struct posix_acl *acl, int type) +{ + int err; + ssize_t ssz; @@ -28541,23 +28812,23 @@ diff -urN /usr/share/empty/fs/aufs/posix_acl.c linux/fs/aufs/posix_acl.c + } + + ssz = au_sxattr(dentry, inode, &arg); ++ /* forget even it if succeeds since the branch might set differently */ ++ forget_cached_acl(inode, type); + dput(dentry); + err = ssz; -+ if (ssz >= 0) { ++ if (ssz >= 0) + err = 0; -+ set_cached_acl(inode, type, acl); -+ } + +out: + return err; +} diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c --- /usr/share/empty/fs/aufs/procfs.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/procfs.c 2019-07-11 15:42:14.472238057 +0200 -@@ -0,0 +1,171 @@ ++++ linux/fs/aufs/procfs.c 2022-10-26 22:30:38.469315525 +0200 +@@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2010-2019 Junjiro R. Okajima ++ * Copyright (C) 2010-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -28686,10 +28957,9 @@ diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c + return err; +} + -+static const struct file_operations au_procfs_plm_fop = { -+ .write = au_procfs_plm_write, -+ .release = au_procfs_plm_release, -+ .owner = THIS_MODULE ++static const struct proc_ops au_procfs_plm_op = { ++ .proc_write = au_procfs_plm_write, ++ .proc_release = au_procfs_plm_release +}; + +/* ---------------------------------------------------------------------- */ @@ -28713,7 +28983,7 @@ diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c + goto out; + + entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | 0200, -+ au_procfs_dir, &au_procfs_plm_fop); ++ au_procfs_dir, &au_procfs_plm_op); + if (unlikely(!entry)) + goto out_dir; + @@ -28728,11 +28998,11 @@ diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c +} diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c --- /usr/share/empty/fs/aufs/rdu.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/rdu.c 2019-07-11 15:42:14.472238057 +0200 ++++ linux/fs/aufs/rdu.c 2022-10-26 22:30:38.472648858 +0200 @@ -0,0 +1,384 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -29116,11 +29386,11 @@ diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c +#endif diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h --- /usr/share/empty/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/rwsem.h 2019-07-11 15:42:14.472238057 +0200 -@@ -0,0 +1,73 @@ ++++ linux/fs/aufs/rwsem.h 2022-10-26 22:30:38.472648858 +0200 +@@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -29152,19 +29422,31 @@ diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h + +/* to debug easier, do not make them inlined functions */ +#define AuRwMustNoWaiters(rw) AuDebugOn(rwsem_is_contended(rw)) ++ ++#ifdef CONFIG_LOCKDEP +/* rwsem_is_locked() is unusable */ -+#define AuRwMustReadLock(rw) AuDebugOn(!lockdep_recursing(current) \ -+ && debug_locks \ ++#define AuRwMustReadLock(rw) AuDebugOn(IS_ENABLED(CONFIG_LOCKDEP) \ ++ && !lockdep_recursing(current) \ ++ && debug_locks \ + && !lockdep_is_held_type(rw, 1)) -+#define AuRwMustWriteLock(rw) AuDebugOn(!lockdep_recursing(current) \ -+ && debug_locks \ ++#define AuRwMustWriteLock(rw) AuDebugOn(IS_ENABLED(CONFIG_LOCKDEP) \ ++ && !lockdep_recursing(current) \ ++ && debug_locks \ + && !lockdep_is_held_type(rw, 0)) -+#define AuRwMustAnyLock(rw) AuDebugOn(!lockdep_recursing(current) \ -+ && debug_locks \ ++#define AuRwMustAnyLock(rw) AuDebugOn(IS_ENABLED(CONFIG_LOCKDEP) \ ++ && !lockdep_recursing(current) \ ++ && debug_locks \ + && !lockdep_is_held(rw)) -+#define AuRwDestroy(rw) AuDebugOn(!lockdep_recursing(current) \ -+ && debug_locks \ ++#define AuRwDestroy(rw) AuDebugOn(IS_ENABLED(CONFIG_LOCKDEP) \ ++ && !lockdep_recursing(current) \ ++ && debug_locks \ + && lockdep_is_held(rw)) ++#else ++#define AuRwMustReadLock(rw) do {} while (0) ++#define AuRwMustWriteLock(rw) do {} while (0) ++#define AuRwMustAnyLock(rw) do {} while (0) ++#define AuRwDestroy(rw) do {} while (0) ++#endif + +#define au_rw_init(rw) init_rwsem(rw) + @@ -29193,11 +29475,11 @@ diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h +#endif /* __AUFS_RWSEM_H__ */ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c --- /usr/share/empty/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/sbinfo.c 2019-07-11 15:42:14.472238057 +0200 -@@ -0,0 +1,314 @@ ++++ linux/fs/aufs/sbinfo.c 2022-10-26 22:30:38.472648858 +0200 +@@ -0,0 +1,316 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -29253,10 +29535,10 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c + au_kfree_rcu(sbinfo); +} + -+int au_si_alloc(struct super_block *sb) ++struct au_sbinfo *au_si_alloc(struct super_block *sb) +{ -+ int err, i; + struct au_sbinfo *sbinfo; ++ int err, i; + + err = -ENOMEM; + sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS); @@ -29321,16 +29603,18 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c + + /* leave other members for sysaufs and si_mnt. */ + sbinfo->si_sb = sb; -+ sb->s_fs_info = sbinfo; -+ si_pid_set(sb); -+ return 0; /* success */ ++ if (sb) { ++ sb->s_fs_info = sbinfo; ++ si_pid_set(sb); ++ } ++ return sbinfo; /* success */ + +out_br: + au_kfree_try_rcu(sbinfo->si_branch); +out_sbinfo: + au_kfree_rcu(sbinfo); +out: -+ return err; ++ return ERR_PTR(err); +} + +int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink) @@ -29511,11 +29795,11 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c +} diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c --- /usr/share/empty/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/super.c 2019-07-11 15:42:14.472238057 +0200 -@@ -0,0 +1,1047 @@ ++++ linux/fs/aufs/super.c 2022-10-26 22:30:38.472648858 +0200 +@@ -0,0 +1,871 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -29761,7 +30045,7 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c + sb = dentry->d_sb; + if (sb->s_flags & SB_POSIXACL) + seq_puts(m, ",acl"); -+#if 0 ++#if 0 /* reserved for future use */ + if (sb->s_flags & SB_I_VERSION) + seq_puts(m, ",i_version"); +#endif @@ -29968,7 +30252,7 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c + continue; + + h_sb = au_sbr_sb(sb, bindex); -+ e = vfsub_sync_filesystem(h_sb, wait); ++ e = vfsub_sync_filesystem(h_sb); + if (unlikely(e && !err)) + err = e; + /* go on even if an error happens */ @@ -30216,7 +30500,7 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c + return err; +} + -+static void au_remount_refresh(struct super_block *sb, unsigned int do_idop) ++void au_remount_refresh(struct super_block *sb, unsigned int do_idop) +{ + int err, e; + unsigned int udba; @@ -30277,92 +30561,7 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c + AuIOErr("refresh failed, ignored, %d\n", err); +} + -+/* stop extra interpretation of errno in mount(8), and strange error messages */ -+static int cvt_err(int err) -+{ -+ AuTraceErr(err); -+ -+ switch (err) { -+ case -ENOENT: -+ case -ENOTDIR: -+ case -EEXIST: -+ case -EIO: -+ err = -EINVAL; -+ } -+ return err; -+} -+ -+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data) -+{ -+ int err, do_dx; -+ unsigned int mntflags; -+ struct au_opts opts = { -+ .opt = NULL -+ }; -+ struct dentry *root; -+ struct inode *inode; -+ struct au_sbinfo *sbinfo; -+ -+ err = 0; -+ root = sb->s_root; -+ if (!data || !*data) { -+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (!err) { -+ di_write_lock_child(root); -+ err = au_opts_verify(sb, *flags, /*pending*/0); -+ aufs_write_unlock(root); -+ } -+ goto out; -+ } -+ -+ err = -ENOMEM; -+ opts.opt = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!opts.opt)) -+ goto out; -+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt); -+ opts.flags = AuOpts_REMOUNT; -+ opts.sb_flags = *flags; -+ -+ /* parse it before aufs lock */ -+ err = au_opts_parse(sb, data, &opts); -+ if (unlikely(err)) -+ goto out_opts; -+ -+ sbinfo = au_sbi(sb); -+ inode = d_inode(root); -+ inode_lock(inode); -+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out_mtx; -+ di_write_lock_child(root); -+ -+ /* au_opts_remount() may return an error */ -+ err = au_opts_remount(sb, &opts); -+ au_opts_free(&opts); -+ -+ if (au_ftest_opts(opts.flags, REFRESH)) -+ au_remount_refresh(sb, au_ftest_opts(opts.flags, REFRESH_IDOP)); -+ -+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) { -+ mntflags = au_mntflags(sb); -+ do_dx = !!au_opt_test(mntflags, DIO); -+ au_dy_arefresh(do_dx); -+ } -+ -+ au_fhsm_wrote_all(sb, /*force*/1); /* ?? */ -+ aufs_write_unlock(root); -+ -+out_mtx: -+ inode_unlock(inode); -+out_opts: -+ free_page((unsigned long)opts.opt); -+out: -+ err = cvt_err(err); -+ AuTraceErr(err); -+ return err; -+} -+ -+static const struct super_operations aufs_sop = { ++const struct super_operations aufs_sop = { + .alloc_inode = aufs_alloc_inode, + .destroy_inode = aufs_destroy_inode, + .free_inode = aufs_free_inode, @@ -30371,13 +30570,12 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c + .show_options = aufs_show_options, + .statfs = aufs_statfs, + .put_super = aufs_put_super, -+ .sync_fs = aufs_sync_fs, -+ .remount_fs = aufs_remount_fs ++ .sync_fs = aufs_sync_fs +}; + +/* ---------------------------------------------------------------------- */ + -+static int alloc_root(struct super_block *sb) ++int au_alloc_root(struct super_block *sb) +{ + int err; + struct inode *inode; @@ -30413,160 +30611,70 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c + return err; +} + -+static int aufs_fill_super(struct super_block *sb, void *raw_data, -+ int silent __maybe_unused) ++/* ---------------------------------------------------------------------- */ ++ ++static void aufs_kill_sb(struct super_block *sb) +{ -+ int err; -+ struct au_opts opts = { -+ .opt = NULL -+ }; + struct au_sbinfo *sbinfo; + struct dentry *root; -+ struct inode *inode; -+ char *arg = raw_data; -+ -+ if (unlikely(!arg || !*arg)) { -+ err = -EINVAL; -+ pr_err("no arg\n"); -+ goto out; -+ } + -+ err = -ENOMEM; -+ opts.opt = (void *)__get_free_page(GFP_NOFS); -+ if (unlikely(!opts.opt)) ++ sbinfo = au_sbi(sb); ++ if (!sbinfo) + goto out; -+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt); -+ opts.sb_flags = sb->s_flags; + -+ err = au_si_alloc(sb); -+ if (unlikely(err)) -+ goto out_opts; -+ sbinfo = au_sbi(sb); ++ au_sbilist_del(sb); + -+ /* all timestamps always follow the ones on the branch */ -+ sb->s_flags |= SB_NOATIME | SB_NODIRATIME; -+ sb->s_flags |= SB_I_VERSION; /* do we really need this? */ -+ sb->s_op = &aufs_sop; -+ sb->s_d_op = &aufs_dop; -+ sb->s_magic = AUFS_SUPER_MAGIC; -+ sb->s_maxbytes = 0; -+ sb->s_stack_depth = 1; -+ au_export_init(sb); -+ au_xattr_init(sb); -+ -+ err = alloc_root(sb); -+ if (unlikely(err)) { -+ si_write_unlock(sb); -+ goto out_info; -+ } + root = sb->s_root; -+ inode = d_inode(root); -+ -+ /* -+ * actually we can parse options regardless aufs lock here. -+ * but at remount time, parsing must be done before aufs lock. -+ * so we follow the same rule. -+ */ -+ ii_write_lock_parent(inode); -+ aufs_write_unlock(root); -+ err = au_opts_parse(sb, arg, &opts); -+ if (unlikely(err)) -+ goto out_root; ++ if (root) ++ aufs_write_lock(root); ++ else ++ __si_write_lock(sb); + -+ /* lock vfs_inode first, then aufs. */ -+ inode_lock(inode); -+ aufs_write_lock(root); -+ err = au_opts_mount(sb, &opts); -+ au_opts_free(&opts); -+ if (!err && au_ftest_si(sbinfo, NO_DREVAL)) { -+ sb->s_d_op = &aufs_dop_noreval; -+ pr_info("%ps\n", sb->s_d_op); -+ au_refresh_dop(root, /*force_reval*/0); -+ sbinfo->si_iop_array = aufs_iop_nogetattr; -+ au_refresh_iop(inode, /*force_getattr*/0); ++ au_fhsm_fin(sb); ++ if (sbinfo->si_wbr_create_ops->fin) ++ sbinfo->si_wbr_create_ops->fin(sb); ++ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) { ++ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE); ++ au_remount_refresh(sb, /*do_idop*/0); + } -+ aufs_write_unlock(root); -+ inode_unlock(inode); -+ if (!err) -+ goto out_opts; /* success */ -+ -+out_root: -+ dput(root); -+ sb->s_root = NULL; -+out_info: -+ kobject_put(&sbinfo->si_kobj); -+ sb->s_fs_info = NULL; -+out_opts: -+ free_page((unsigned long)opts.opt); -+out: -+ AuTraceErr(err); -+ err = cvt_err(err); -+ AuTraceErr(err); -+ return err; -+} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags, -+ const char *dev_name __maybe_unused, -+ void *raw_data) -+{ -+ struct dentry *root; ++ if (au_opt_test(sbinfo->si_mntflags, PLINK)) ++ au_plink_put(sb, /*verbose*/1); ++ au_xino_clr(sb); ++ if (root) ++ au_dr_opt_flush(sb); + -+ /* all timestamps always follow the ones on the branch */ -+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */ -+ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super); -+ if (IS_ERR(root)) -+ goto out; ++ if (root) ++ aufs_write_unlock(root); ++ else ++ __si_write_unlock(sb); + -+ au_sbilist_add(root->d_sb); ++ sbinfo->si_sb = NULL; ++ au_nwt_flush(&sbinfo->si_nowait); + +out: -+ return root; -+} -+ -+static void aufs_kill_sb(struct super_block *sb) -+{ -+ struct au_sbinfo *sbinfo; -+ -+ sbinfo = au_sbi(sb); -+ if (sbinfo) { -+ au_sbilist_del(sb); -+ aufs_write_lock(sb->s_root); -+ au_fhsm_fin(sb); -+ if (sbinfo->si_wbr_create_ops->fin) -+ sbinfo->si_wbr_create_ops->fin(sb); -+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) { -+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE); -+ au_remount_refresh(sb, /*do_idop*/0); -+ } -+ if (au_opt_test(sbinfo->si_mntflags, PLINK)) -+ au_plink_put(sb, /*verbose*/1); -+ au_xino_clr(sb); -+ au_dr_opt_flush(sb); -+ sbinfo->si_sb = NULL; -+ aufs_write_unlock(sb->s_root); -+ au_nwt_flush(&sbinfo->si_nowait); -+ } + kill_anon_super(sb); +} + +struct file_system_type aufs_fs_type = { + .name = AUFS_FSTYPE, + /* a race between rename and others */ -+ .fs_flags = FS_RENAME_DOES_D_MOVE, -+ .mount = aufs_mount, ++ .fs_flags = FS_RENAME_DOES_D_MOVE ++ /* untested */ ++ /*| FS_ALLOW_IDMAP*/ ++ , ++ .init_fs_context = aufs_fsctx_init, ++ .parameters = aufs_fsctx_paramspec, + .kill_sb = aufs_kill_sb, + /* no need to __module_get() and module_put(). */ + .owner = THIS_MODULE, +}; diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h --- /usr/share/empty/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/super.h 2019-07-11 15:42:14.472238057 +0200 -@@ -0,0 +1,589 @@ ++++ linux/fs/aufs/super.h 2022-10-26 22:30:38.472648858 +0200 +@@ -0,0 +1,592 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -30697,8 +30805,6 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h + unsigned int si_mntflags; + + /* external inode number (bitmap and translation table) */ -+ vfs_readf_t si_xread; -+ vfs_writef_t si_xwrite; + loff_t si_ximaxent; /* max entries in a xino */ + + struct file *si_xib; @@ -30745,7 +30851,7 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h + struct hlist_bl_head si_files; + + /* with/without getattr, brother of sb->s_d_op */ -+ struct inode_operations *si_iop_array; ++ const struct inode_operations *si_iop_array; + + /* + * sysfs and lifetime management. @@ -30829,8 +30935,8 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h +/* ---------------------------------------------------------------------- */ + +/* super.c */ -+extern struct file_system_type aufs_fs_type; +struct inode *au_iget_locked(struct super_block *sb, ino_t ino); ++ +typedef unsigned long long (*au_arraycb_t)(struct super_block *sb, void *array, + unsigned long long max, void *arg); +void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb, @@ -30838,9 +30944,14 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h +struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max); +void au_iarray_free(struct inode **a, unsigned long long max); + ++void au_remount_refresh(struct super_block *sb, unsigned int do_idop); ++extern const struct super_operations aufs_sop; ++int au_alloc_root(struct super_block *sb); ++extern struct file_system_type aufs_fs_type; ++ +/* sbinfo.c */ +void au_si_free(struct kobject *kobj); -+int au_si_alloc(struct super_block *sb); ++struct au_sbinfo *au_si_alloc(struct super_block *sb); +int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink); + +unsigned int au_sigen_inc(struct super_block *sb); @@ -31155,11 +31266,11 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h +#endif /* __AUFS_SUPER_H__ */ diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c --- /usr/share/empty/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/sysaufs.c 2019-07-11 15:42:14.472238057 +0200 ++++ linux/fs/aufs/sysaufs.c 2022-10-26 22:30:38.472648858 +0200 @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -31252,11 +31363,11 @@ diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c +} diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h --- /usr/share/empty/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/sysaufs.h 2019-07-11 15:42:14.475571481 +0200 ++++ linux/fs/aufs/sysaufs.h 2022-10-26 22:30:38.472648858 +0200 @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -31358,11 +31469,11 @@ diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h +#endif /* __SYSAUFS_H__ */ diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c --- /usr/share/empty/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/sysfs.c 2019-07-11 15:42:14.475571481 +0200 ++++ linux/fs/aufs/sysfs.c 2022-10-26 22:30:38.472648858 +0200 @@ -0,0 +1,374 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -31736,11 +31847,11 @@ diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c +} diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c --- /usr/share/empty/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/sysrq.c 2019-07-11 15:42:14.475571481 +0200 -@@ -0,0 +1,160 @@ ++++ linux/fs/aufs/sysrq.c 2022-10-26 22:30:38.472648858 +0200 +@@ -0,0 +1,149 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -31774,6 +31885,7 @@ diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c + struct hlist_bl_head *files; + struct hlist_bl_node *pos; + struct au_finfo *finfo; ++ struct inode *i; + + plevel = au_plevel; + au_plevel = KERN_WARNING; @@ -31786,14 +31898,7 @@ diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c + pr("superblock\n"); + au_dpri_sb(sb); + -+#if 0 -+ pr("root dentry\n"); -+ au_dpri_dentry(sb->s_root); -+ pr("root inode\n"); -+ au_dpri_inode(d_inode(sb->s_root)); -+#endif -+ -+#if 0 ++#if 0 /* reserved */ + do { + int err, i, j, ndentry; + struct au_dcsub_pages dpages; @@ -31814,21 +31919,16 @@ diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c + } while (0); +#endif + -+#if 1 -+ { -+ struct inode *i; -+ -+ pr("isolated inode\n"); -+ spin_lock(&sb->s_inode_list_lock); -+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) { -+ spin_lock(&i->i_lock); -+ if (1 || hlist_empty(&i->i_dentry)) -+ au_dpri_inode(i); -+ spin_unlock(&i->i_lock); -+ } -+ spin_unlock(&sb->s_inode_list_lock); ++ pr("isolated inode\n"); ++ spin_lock(&sb->s_inode_list_lock); ++ list_for_each_entry(i, &sb->s_inodes, i_sb_list) { ++ spin_lock(&i->i_lock); ++ if (hlist_empty(&i->i_dentry)) ++ au_dpri_inode(i); ++ spin_unlock(&i->i_lock); + } -+#endif ++ spin_unlock(&sb->s_inode_list_lock); ++ + pr("files\n"); + files = &au_sbi(sb)->si_files; + hlist_bl_lock(files); @@ -31900,11 +32000,11 @@ diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c +} diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c --- /usr/share/empty/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/vdir.c 2019-07-11 15:42:14.475571481 +0200 ++++ linux/fs/aufs/vdir.c 2022-10-26 22:30:38.472648858 +0200 @@ -0,0 +1,896 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -31999,7 +32099,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c + +static void nhash_count(struct hlist_head *head) +{ -+#if 0 ++#if 0 /* debugging */ + unsigned long n; + struct hlist_node *pos; + @@ -32800,11 +32900,11 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c +} diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c --- /usr/share/empty/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/vfsub.c 2019-07-11 15:42:14.475571481 +0200 -@@ -0,0 +1,902 @@ ++++ linux/fs/aufs/vfsub.c 2022-10-26 22:30:38.472648858 +0200 +@@ -0,0 +1,918 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -32825,7 +32925,6 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c + */ + +#include -+#include +#include +#include +#include @@ -32841,13 +32940,13 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c +} +#endif + -+int vfsub_sync_filesystem(struct super_block *h_sb, int wait) ++int vfsub_sync_filesystem(struct super_block *h_sb) +{ + int err; + + lockdep_off(); + down_read(&h_sb->s_umount); -+ err = __sync_filesystem(h_sb, wait); ++ err = sync_filesystem(h_sb); + up_read(&h_sb->s_umount); + lockdep_on(); + @@ -32862,6 +32961,11 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c + struct kstat st; + struct super_block *h_sb; + ++ /* ++ * Always needs h_path->mnt for LSM or FUSE branch. ++ */ ++ AuDebugOn(!h_path->mnt); ++ + /* for remote fs, leave work for its getattr or d_revalidate */ + /* for bad i_attr fs, handle them in aufs_getattr() */ + /* still some fs may acquire i_mutex. we need to skip them */ @@ -32880,15 +32984,8 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c + +struct file *vfsub_dentry_open(struct path *path, int flags) +{ -+ struct file *file; -+ -+ file = dentry_open(path, flags /* | __FMODE_NONOTIFY */, ++ return dentry_open(path, flags /* | __FMODE_NONOTIFY */, + current_cred()); -+ if (!IS_ERR_OR_NULL(file) -+ && (file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) -+ i_readcount_inc(d_inode(path->dentry)); -+ -+ return file; +} + +struct file *vfsub_filp_open(const char *path, int oflags, int mode) @@ -32977,38 +33074,38 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c +} + +struct dentry *vfsub_lookup_one_len_unlocked(const char *name, -+ struct dentry *parent, int len) ++ struct path *ppath, int len) +{ -+ struct path path = { -+ .mnt = NULL -+ }; ++ struct path path; + -+ path.dentry = lookup_one_len_unlocked(name, parent, len); ++ path.dentry = lookup_one_len_unlocked(name, ppath->dentry, len); + if (IS_ERR(path.dentry)) + goto out; -+ if (d_is_positive(path.dentry)) ++ if (d_is_positive(path.dentry)) { ++ path.mnt = ppath->mnt; + vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/ ++ } + +out: + AuTraceErrPtr(path.dentry); + return path.dentry; +} + -+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent, ++struct dentry *vfsub_lookup_one_len(const char *name, struct path *ppath, + int len) +{ -+ struct path path = { -+ .mnt = NULL -+ }; ++ struct path path; + + /* VFS checks it too, but by WARN_ON_ONCE() */ -+ IMustLock(d_inode(parent)); ++ IMustLock(d_inode(ppath->dentry)); + -+ path.dentry = lookup_one_len(name, parent, len); ++ path.dentry = lookup_one_len(name, ppath->dentry, len); + if (IS_ERR(path.dentry)) + goto out; -+ if (d_is_positive(path.dentry)) ++ if (d_is_positive(path.dentry)) { ++ path.mnt = ppath->mnt; + vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/ ++ } + +out: + AuTraceErrPtr(path.dentry); @@ -33018,7 +33115,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c +void vfsub_call_lkup_one(void *args) +{ + struct vfsub_lkup_one_args *a = args; -+ *a->errp = vfsub_lkup_one(a->name, a->parent); ++ *a->errp = vfsub_lkup_one(a->name, a->ppath); +} + +/* ---------------------------------------------------------------------- */ @@ -33055,6 +33152,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c +{ + int err; + struct dentry *d; ++ struct user_namespace *userns; + + IMustLock(dir); + @@ -33064,9 +33162,10 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c + path->dentry = d; + if (unlikely(err)) + goto out; ++ userns = mnt_user_ns(path->mnt); + + lockdep_off(); -+ err = vfs_create(dir, path->dentry, mode, want_excl); ++ err = vfs_create(userns, dir, path->dentry, mode, want_excl); + lockdep_on(); + if (!err) { + struct path tmp = *path; @@ -33088,6 +33187,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c +{ + int err; + struct dentry *d; ++ struct user_namespace *userns; + + IMustLock(dir); + @@ -33097,9 +33197,10 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c + path->dentry = d; + if (unlikely(err)) + goto out; ++ userns = mnt_user_ns(path->mnt); + + lockdep_off(); -+ err = vfs_symlink(dir, path->dentry, symname); ++ err = vfs_symlink(userns, dir, path->dentry, symname); + lockdep_on(); + if (!err) { + struct path tmp = *path; @@ -33121,6 +33222,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c +{ + int err; + struct dentry *d; ++ struct user_namespace *userns; + + IMustLock(dir); + @@ -33130,9 +33232,10 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c + path->dentry = d; + if (unlikely(err)) + goto out; ++ userns = mnt_user_ns(path->mnt); + + lockdep_off(); -+ err = vfs_mknod(dir, path->dentry, mode, dev); ++ err = vfs_mknod(userns, dir, path->dentry, mode, dev); + lockdep_on(); + if (!err) { + struct path tmp = *path; @@ -33165,6 +33268,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c +{ + int err; + struct dentry *d; ++ struct user_namespace *userns; + + IMustLock(dir); + @@ -33179,9 +33283,10 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c + path->dentry = d; + if (unlikely(err)) + goto out; ++ userns = mnt_user_ns(path->mnt); + + lockdep_off(); -+ err = vfs_link(src_dentry, dir, path->dentry, delegated_inode); ++ err = vfs_link(src_dentry, userns, dir, path->dentry, delegated_inode); + lockdep_on(); + if (!err) { + struct path tmp = *path; @@ -33207,6 +33312,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c + struct inode **delegated_inode, unsigned int flags) +{ + int err; ++ struct renamedata rd; + struct path tmp = { + .mnt = path->mnt + }; @@ -33223,9 +33329,16 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c + if (unlikely(err)) + goto out; + ++ rd.old_mnt_userns = mnt_user_ns(path->mnt); ++ rd.old_dir = src_dir; ++ rd.old_dentry = src_dentry; ++ rd.new_mnt_userns = rd.old_mnt_userns; ++ rd.new_dir = dir; ++ rd.new_dentry = path->dentry; ++ rd.delegated_inode = delegated_inode; ++ rd.flags = flags; + lockdep_off(); -+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry, -+ delegated_inode, flags); ++ err = vfs_rename(&rd); + lockdep_on(); + if (!err) { + int did; @@ -33249,6 +33362,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c +{ + int err; + struct dentry *d; ++ struct user_namespace *userns; + + IMustLock(dir); + @@ -33258,9 +33372,10 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c + path->dentry = d; + if (unlikely(err)) + goto out; ++ userns = mnt_user_ns(path->mnt); + + lockdep_off(); -+ err = vfs_mkdir(dir, path->dentry, mode); ++ err = vfs_mkdir(userns, dir, path->dentry, mode); + lockdep_on(); + if (!err) { + struct path tmp = *path; @@ -33282,6 +33397,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c +{ + int err; + struct dentry *d; ++ struct user_namespace *userns; + + IMustLock(dir); + @@ -33291,9 +33407,10 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c + path->dentry = d; + if (unlikely(err)) + goto out; ++ userns = mnt_user_ns(path->mnt); + + lockdep_off(); -+ err = vfs_rmdir(dir, path->dentry); ++ err = vfs_rmdir(userns, dir, path->dentry); + lockdep_on(); + if (!err) { + struct path tmp = { @@ -33324,22 +33441,17 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c + return err; +} + -+/* todo: kernel_read()? */ +ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, + loff_t *ppos) +{ + ssize_t err; -+ mm_segment_t oldfs; -+ union { -+ void *k; -+ char __user *u; -+ } buf; + -+ buf.k = kbuf; -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ err = vfsub_read_u(file, buf.u, count, ppos); -+ set_fs(oldfs); ++ lockdep_off(); ++ err = kernel_read(file, kbuf, count, ppos); ++ lockdep_on(); ++ AuTraceErr(err); ++ if (err >= 0) ++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ + return err; +} + @@ -33359,17 +33471,12 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c +ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos) +{ + ssize_t err; -+ mm_segment_t oldfs; -+ union { -+ void *k; -+ const char __user *u; -+ } buf; + -+ buf.k = kbuf; -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); -+ err = vfsub_write_u(file, buf.u, count, ppos); -+ set_fs(oldfs); ++ lockdep_off(); ++ err = kernel_write(file, kbuf, count, ppos); ++ lockdep_on(); ++ if (err >= 0) ++ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ + return err; +} + @@ -33461,6 +33568,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c + int err; + struct inode *h_inode; + struct super_block *h_sb; ++ struct user_namespace *h_userns; + + if (!h_file) { + err = vfsub_truncate(h_path, length); @@ -33472,12 +33580,12 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c + lockdep_off(); + sb_start_write(h_sb); + lockdep_on(); -+ err = locks_verify_truncate(h_inode, h_file, length); -+ if (!err) -+ err = security_path_truncate(h_path); ++ err = security_path_truncate(h_path); + if (!err) { ++ h_userns = mnt_user_ns(h_path->mnt); + lockdep_off(); -+ err = do_truncate(h_path->dentry, length, attr, h_file); ++ err = do_truncate(h_userns, h_path->dentry, length, attr, ++ h_file); + lockdep_on(); + } + lockdep_off(); @@ -33506,8 +33614,10 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c +int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode) +{ + int err, do_sio, wkq_err; ++ struct user_namespace *userns; + -+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE); ++ userns = mnt_user_ns(path->mnt); ++ do_sio = au_test_h_perm_sio(userns, dir, MAY_EXEC | MAY_WRITE); + if (!do_sio) { + lockdep_off(); + err = vfsub_mkdir(dir, path, mode); @@ -33542,8 +33652,10 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c +int vfsub_sio_rmdir(struct inode *dir, struct path *path) +{ + int err, do_sio, wkq_err; ++ struct user_namespace *userns; + -+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE); ++ userns = mnt_user_ns(path->mnt); ++ do_sio = au_test_h_perm_sio(userns, dir, MAY_EXEC | MAY_WRITE); + if (!do_sio) { + lockdep_off(); + err = vfsub_rmdir(dir, path); @@ -33575,14 +33687,16 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c +{ + struct notify_change_args *a = args; + struct inode *h_inode; ++ struct user_namespace *userns; + + h_inode = d_inode(a->path->dentry); + IMustLock(h_inode); + + *a->errp = -EPERM; + if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) { ++ userns = mnt_user_ns(a->path->mnt); + lockdep_off(); -+ *a->errp = notify_change(a->path->dentry, a->ia, ++ *a->errp = notify_change(userns, a->path->dentry, a->ia, + a->delegated_inode); + lockdep_on(); + if (!*a->errp) @@ -33639,6 +33753,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c + struct unlink_args *a = args; + struct dentry *d = a->path->dentry; + struct inode *h_inode; ++ struct user_namespace *userns; + const int stop_sillyrename = (au_test_nfs(d->d_sb) + && au_dcount(d) == 1); + @@ -33658,8 +33773,9 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c + ihold(h_inode); + } + ++ userns = mnt_user_ns(a->path->mnt); + lockdep_off(); -+ *a->errp = vfs_unlink(a->dir, d, a->delegated_inode); ++ *a->errp = vfs_unlink(userns, a->dir, d, a->delegated_inode); + lockdep_on(); + if (!*a->errp) { + struct path tmp = { @@ -33706,11 +33822,11 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c +} diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h --- /usr/share/empty/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/vfsub.h 2019-07-11 15:42:14.475571481 +0200 -@@ -0,0 +1,354 @@ ++++ linux/fs/aufs/vfsub.h 2022-10-26 22:30:38.472648858 +0200 +@@ -0,0 +1,358 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -33794,7 +33910,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h +AuStubInt0(vfsub_test_mntns, struct vfsmount *mnt, struct super_block *h_sb); +#endif + -+int vfsub_sync_filesystem(struct super_block *h_sb, int wait); ++int vfsub_sync_filesystem(struct super_block *h_sb); + +/* ---------------------------------------------------------------------- */ + @@ -33813,20 +33929,20 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h +int vfsub_kern_path(const char *name, unsigned int flags, struct path *path); + +struct dentry *vfsub_lookup_one_len_unlocked(const char *name, -+ struct dentry *parent, int len); -+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent, ++ struct path *ppath, int len); ++struct dentry *vfsub_lookup_one_len(const char *name, struct path *ppath, + int len); + +struct vfsub_lkup_one_args { + struct dentry **errp; + struct qstr *name; -+ struct dentry *parent; ++ struct path *ppath; +}; + +static inline struct dentry *vfsub_lkup_one(struct qstr *name, -+ struct dentry *parent) ++ struct path *ppath) +{ -+ return vfsub_lookup_one_len(name->name, parent, name->len); ++ return vfsub_lookup_one_len(name->name, ppath, name->len); +} + +void vfsub_call_lkup_one(void *args); @@ -33939,22 +34055,24 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h +static inline int vfsub_update_time(struct inode *h_inode, + struct timespec64 *ts, int flags) +{ -+ return update_time(h_inode, ts, flags); ++ return inode_update_time(h_inode, ts, flags); + /* no vfsub_update_h_iattr() since we don't have struct path */ +} + +#ifdef CONFIG_FS_POSIX_ACL -+static inline int vfsub_acl_chmod(struct inode *h_inode, umode_t h_mode) ++static inline int vfsub_acl_chmod(struct user_namespace *h_userns, ++ struct inode *h_inode, umode_t h_mode) +{ + int err; + -+ err = posix_acl_chmod(h_inode, h_mode); ++ err = posix_acl_chmod(h_userns, h_inode, h_mode); + if (err == -EOPNOTSUPP) + err = 0; + return err; +} +#else -+AuStubInt0(vfsub_acl_chmod, struct inode *h_inode, umode_t h_mode); ++AuStubInt0(vfsub_acl_chmod, struct user_namespace *h_userns, ++ struct inode *h_inode, umode_t h_mode); +#endif + +long vfsub_splice_to(struct file *in, loff_t *ppos, @@ -34037,24 +34155,26 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h + +/* ---------------------------------------------------------------------- */ + -+static inline int vfsub_setxattr(struct dentry *dentry, const char *name, ++static inline int vfsub_setxattr(struct user_namespace *userns, ++ struct dentry *dentry, const char *name, + const void *value, size_t size, int flags) +{ + int err; + + lockdep_off(); -+ err = vfs_setxattr(dentry, name, value, size, flags); ++ err = vfs_setxattr(userns, dentry, name, value, size, flags); + lockdep_on(); + + return err; +} + -+static inline int vfsub_removexattr(struct dentry *dentry, const char *name) ++static inline int vfsub_removexattr(struct user_namespace *userns, ++ struct dentry *dentry, const char *name) +{ + int err; + + lockdep_off(); -+ err = vfs_removexattr(dentry, name); ++ err = vfs_removexattr(userns, dentry, name); + lockdep_on(); + + return err; @@ -34064,11 +34184,11 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h +#endif /* __AUFS_VFSUB_H__ */ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c --- /usr/share/empty/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/wbr_policy.c 2019-07-11 15:42:14.475571481 +0200 ++++ linux/fs/aufs/wbr_policy.c 2022-10-26 22:30:38.472648858 +0200 @@ -0,0 +1,830 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -34898,11 +35018,11 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c +}; diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c --- /usr/share/empty/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/whout.c 2019-07-11 15:42:14.475571481 +0200 -@@ -0,0 +1,1062 @@ ++++ linux/fs/aufs/whout.c 2022-10-26 22:30:38.472648858 +0200 +@@ -0,0 +1,1072 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -34963,18 +35083,19 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c +/* ---------------------------------------------------------------------- */ + +/* -+ * test if the @wh_name exists under @h_parent. ++ * test if the @wh_name exists under @h_ppath. + * @try_sio specifies the necessary of super-io. + */ -+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio) ++int au_wh_test(struct user_namespace *h_userns, struct path *h_ppath, ++ struct qstr *wh_name, int try_sio) +{ + int err; + struct dentry *wh_dentry; + + if (!try_sio) -+ wh_dentry = vfsub_lkup_one(wh_name, h_parent); ++ wh_dentry = vfsub_lkup_one(wh_name, h_ppath); + else -+ wh_dentry = au_sio_lkup_one(wh_name, h_parent); ++ wh_dentry = au_sio_lkup_one(h_userns, wh_name, h_ppath); + err = PTR_ERR(wh_dentry); + if (IS_ERR(wh_dentry)) { + if (err == -ENAMETOOLONG) @@ -35001,16 +35122,16 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c +} + +/* -+ * test if the @h_dentry sets opaque or not. ++ * test if the @h_path->dentry sets opaque or not. + */ -+int au_diropq_test(struct dentry *h_dentry) ++int au_diropq_test(struct user_namespace *h_userns, struct path *h_path) +{ + int err; + struct inode *h_dir; + -+ h_dir = d_inode(h_dentry); -+ err = au_wh_test(h_dentry, &diropq_name, -+ au_test_h_perm_sio(h_dir, MAY_EXEC)); ++ h_dir = d_inode(h_path->dentry); ++ err = au_wh_test(h_userns, h_path, &diropq_name, ++ au_test_h_perm_sio(h_userns, h_dir, MAY_EXEC)); + return err; +} + @@ -35027,6 +35148,8 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c + /* strict atomic_t is unnecessary here */ + static unsigned short cnt; + struct qstr qs; ++ struct path h_ppath; ++ struct user_namespace *h_userns; + + BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN); + @@ -35050,10 +35173,13 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c + *p++ = '.'; + AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN); + ++ h_ppath.dentry = h_parent; ++ h_ppath.mnt = au_br_mnt(br); ++ h_userns = au_br_userns(br); + qs.name = name; + for (i = 0; i < 3; i++) { + sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++); -+ dentry = au_sio_lkup_one(&qs, h_parent); ++ dentry = au_sio_lkup_one(h_userns, &qs, &h_ppath); + if (IS_ERR(dentry) || d_is_negative(dentry)) + goto out_name; + dput(dentry); @@ -35147,21 +35273,20 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c + return err; +} + -+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh, -+ struct au_branch *br) ++static int unlink_wh_name(struct path *h_ppath, struct qstr *wh) +{ + int err; -+ struct path h_path = { -+ .mnt = au_br_mnt(br) -+ }; ++ struct path h_path; + + err = 0; -+ h_path.dentry = vfsub_lkup_one(wh, h_parent); ++ h_path.dentry = vfsub_lkup_one(wh, h_ppath); + if (IS_ERR(h_path.dentry)) + err = PTR_ERR(h_path.dentry); + else { -+ if (d_is_reg(h_path.dentry)) -+ err = do_unlink_wh(d_inode(h_parent), &h_path); ++ if (d_is_reg(h_path.dentry)) { ++ h_path.mnt = h_ppath->mnt; ++ err = do_unlink_wh(d_inode(h_ppath->dentry), &h_path); ++ } + dput(h_path.dentry); + } + @@ -35207,7 +35332,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c + + pr_err("%pd (%s) doesn't support link(2), use noplink and rw+nolwh\n", + h_root, au_sbtype(h_root->d_sb)); -+ return -ENOSYS; ++ return -ENOSYS; /* the branch doesn't have its ->link() */ +} + +/* todo: should this mkdir be done in /sbin/mount.aufs helper? */ @@ -35601,15 +35726,17 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c +static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex, + unsigned int flags) +{ -+ struct dentry *opq_dentry, *h_dentry; ++ struct dentry *opq_dentry; + struct super_block *sb; + struct au_branch *br; ++ struct path h_path; + int err; + + sb = dentry->d_sb; + br = au_sbr(sb, bindex); -+ h_dentry = au_h_dptr(dentry, bindex); -+ opq_dentry = vfsub_lkup_one(&diropq_name, h_dentry); ++ h_path.dentry = au_h_dptr(dentry, bindex); ++ h_path.mnt = au_br_mnt(br); ++ opq_dentry = vfsub_lkup_one(&diropq_name, &h_path); + if (IS_ERR(opq_dentry)) + goto out; + @@ -35620,11 +35747,8 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c + goto out; /* success */ + } + } else { -+ struct path tmp = { -+ .dentry = opq_dentry, -+ .mnt = au_br_mnt(br) -+ }; -+ err = do_unlink_wh(au_h_iptr(d_inode(dentry), bindex), &tmp); ++ h_path.dentry = opq_dentry; ++ err = do_unlink_wh(au_h_iptr(d_inode(dentry), bindex), &h_path); + if (!err) + au_set_dbdiropq(dentry, -1); + } @@ -35652,9 +35776,12 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c + unsigned int flags) +{ + struct dentry *diropq, *h_dentry; ++ struct user_namespace *h_userns; + ++ h_userns = au_sbr_userns(dentry->d_sb, bindex); + h_dentry = au_h_dptr(dentry, bindex); -+ if (!au_test_h_perm_sio(d_inode(h_dentry), MAY_EXEC | MAY_WRITE)) ++ if (!au_test_h_perm_sio(h_userns, d_inode(h_dentry), ++ MAY_EXEC | MAY_WRITE)) + diropq = do_diropq(dentry, bindex, flags); + else { + int wkq_err; @@ -35687,11 +35814,14 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c + int err; + struct qstr wh_name; + struct dentry *wh_dentry; ++ struct path h_path; + + err = au_wh_name_alloc(&wh_name, base_name); + wh_dentry = ERR_PTR(err); + if (!err) { -+ wh_dentry = vfsub_lkup_one(&wh_name, h_parent); ++ h_path.dentry = h_parent; ++ h_path.mnt = au_br_mnt(br); ++ wh_dentry = vfsub_lkup_one(&wh_name, &h_path); + au_kfree_try_rcu(wh_name.name); + } + return wh_dentry; @@ -35726,8 +35856,8 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c +/* ---------------------------------------------------------------------- */ + +/* Delete all whiteouts in this directory on branch bindex. */ -+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist, -+ aufs_bindex_t bindex, struct au_branch *br) ++static int del_wh_children(struct path *h_path, struct au_nhash *whlist, ++ aufs_bindex_t bindex) +{ + int err; + unsigned long ul, n; @@ -35757,7 +35887,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c + if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) { + memcpy(p, str->name, str->len); + wh_name.len = AUFS_WH_PFX_LEN + str->len; -+ err = unlink_wh_name(h_dentry, &wh_name, br); ++ err = unlink_wh_name(h_path, &wh_name); + if (!err) + continue; + break; @@ -35776,16 +35906,15 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c + +struct del_wh_children_args { + int *errp; -+ struct dentry *h_dentry; ++ struct path *h_path; + struct au_nhash *whlist; + aufs_bindex_t bindex; -+ struct au_branch *br; +}; + +static void call_del_wh_children(void *args) +{ + struct del_wh_children_args *a = args; -+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br); ++ *a->errp = del_wh_children(a->h_path, a->whlist, a->bindex); +} + +/* ---------------------------------------------------------------------- */ @@ -35837,14 +35966,18 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c +{ + int err; + unsigned int h_nlink; -+ struct path h_tmp; ++ struct path wh_path; + struct inode *wh_inode, *h_dir; + struct au_branch *br; ++ struct user_namespace *h_userns; + + h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */ + IMustLock(h_dir); + + br = au_sbr(dir->i_sb, bindex); ++ wh_path.dentry = wh_dentry; ++ wh_path.mnt = au_br_mnt(br); ++ h_userns = au_br_userns(br); + wh_inode = d_inode(wh_dentry); + inode_lock_nested(wh_inode, AuLsc_I_CHILD); + @@ -35852,16 +35985,15 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c + * someone else might change some whiteouts while we were sleeping. + * it means this whlist may have an obsoleted entry. + */ -+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE)) -+ err = del_wh_children(wh_dentry, whlist, bindex, br); ++ if (!au_test_h_perm_sio(h_userns, wh_inode, MAY_EXEC | MAY_WRITE)) ++ err = del_wh_children(&wh_path, whlist, bindex); + else { + int wkq_err; + struct del_wh_children_args args = { + .errp = &err, -+ .h_dentry = wh_dentry, ++ .h_path = &wh_path, + .whlist = whlist, -+ .bindex = bindex, -+ .br = br ++ .bindex = bindex + }; + + wkq_err = au_wkq_wait(call_del_wh_children, &args); @@ -35871,10 +36003,8 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c + inode_unlock(wh_inode); + + if (!err) { -+ h_tmp.dentry = wh_dentry; -+ h_tmp.mnt = au_br_mnt(br); + h_nlink = h_dir->i_nlink; -+ err = vfsub_rmdir(h_dir, &h_tmp); ++ err = vfsub_rmdir(h_dir, &wh_path); + /* some fs doesn't change the parent nlink in some cases */ + h_nlink -= h_dir->i_nlink; + } @@ -35964,11 +36094,11 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c +} diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h --- /usr/share/empty/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/whout.h 2019-07-11 15:42:14.475571481 +0200 -@@ -0,0 +1,86 @@ ++++ linux/fs/aufs/whout.h 2022-10-26 22:30:38.472648858 +0200 +@@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -35997,8 +36127,9 @@ diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h + +/* whout.c */ +int au_wh_name_alloc(struct qstr *wh, const struct qstr *name); -+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio); -+int au_diropq_test(struct dentry *h_dentry); ++int au_wh_test(struct user_namespace *h_userns, struct path *h_ppath, ++ struct qstr *wh_name, int try_sio); ++int au_diropq_test(struct user_namespace *h_userns, struct path *h_path); +struct au_branch; +struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br, + struct qstr *prefix); @@ -36054,11 +36185,11 @@ diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h +#endif /* __AUFS_WHOUT_H__ */ diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c --- /usr/share/empty/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/wkq.c 2019-07-11 15:42:14.475571481 +0200 -@@ -0,0 +1,392 @@ ++++ linux/fs/aufs/wkq.c 2022-10-26 22:30:38.472648858 +0200 +@@ -0,0 +1,372 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -36211,8 +36342,8 @@ diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c + goto out; + + err = 0; -+#if 0 -+ if (0 && au_debug_test()) /* left for debugging */ ++#if 0 /* left for debugging */ ++ if (0 && au_debug_test()) + lockdep_print_held_locks(curr); +#endif + held_locks = curr->held_locks; @@ -36263,7 +36394,7 @@ diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c + if (!hl) + return; + while ((p = *hl++)) /* assignment */ -+ rwsem_release(p->instance, 0, /*p->acquire_ip*/_RET_IP_); ++ rwsem_release(p->instance, /*p->acquire_ip*/_RET_IP_); +} +#endif + @@ -36289,7 +36420,6 @@ diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c +/* + * Since struct completion is large, try allocating it dynamically. + */ -+#if 1 /* defined(CONFIG_4KSTACKS) || defined(AuTest4KSTACKS) */ +#define AuWkqCompDeclare(name) struct completion *comp = NULL + +static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp) @@ -36308,25 +36438,6 @@ diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c + au_kfree_rcu(comp); +} + -+#else -+ -+/* no braces */ -+#define AuWkqCompDeclare(name) \ -+ DECLARE_COMPLETION_ONSTACK(_ ## name); \ -+ struct completion *comp = &_ ## name -+ -+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp) -+{ -+ wkinfo->comp = *comp; -+ return 0; -+} -+ -+static void au_wkq_comp_free(struct completion *comp __maybe_unused) -+{ -+ /* empty */ -+} -+#endif /* 4KSTACKS */ -+ +static void au_wkq_run(struct au_wkinfo *wkinfo) +{ + if (au_ftest_wkq(wkinfo->flags, NEST)) { @@ -36450,11 +36561,11 @@ diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c +} diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h --- /usr/share/empty/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/wkq.h 2019-07-11 15:42:14.475571481 +0200 ++++ linux/fs/aufs/wkq.h 2022-10-26 22:30:38.472648858 +0200 @@ -0,0 +1,89 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -36543,11 +36654,11 @@ diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h +#endif /* __AUFS_WKQ_H__ */ diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c --- /usr/share/empty/fs/aufs/xattr.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/xattr.c 2019-07-11 15:42:14.475571481 +0200 -@@ -0,0 +1,356 @@ ++++ linux/fs/aufs/xattr.c 2022-10-26 22:30:38.475982192 +0200 +@@ -0,0 +1,368 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2014-2019 Junjiro R. Okajima ++ * Copyright (C) 2014-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -36611,21 +36722,26 @@ diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c + +static const int au_xattr_out_of_list = AuBrAttr_ICEX_OTH << 1; + -+static int au_do_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, ++static int au_do_cpup_xattr(struct path *h_dst, struct path *h_src, + char *name, char **buf, unsigned int ignore_flags, + unsigned int verbose) +{ + int err; + ssize_t ssz; + struct inode *h_idst; ++ struct dentry *h_dst_dentry, *h_src_dentry; ++ struct user_namespace *h_dst_userns, *h_src_userns; + -+ ssz = vfs_getxattr_alloc(h_src, name, buf, 0, GFP_NOFS); ++ h_src_userns = mnt_user_ns(h_src->mnt); ++ h_src_dentry = h_src->dentry; ++ ssz = vfs_getxattr_alloc(h_src_userns, h_src_dentry, name, buf, 0, ++ GFP_NOFS); + err = ssz; + if (unlikely(err <= 0)) { + if (err == -ENODATA + || (err == -EOPNOTSUPP + && ((ignore_flags & au_xattr_out_of_list) -+ || (au_test_nfs_noacl(d_inode(h_src)) ++ || (au_test_nfs_noacl(d_inode(h_src_dentry)) + && (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS) + || !strcmp(name, + XATTR_NAME_POSIX_ACL_DEFAULT)))) @@ -36637,9 +36753,12 @@ diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c + } + + /* unlock it temporary */ -+ h_idst = d_inode(h_dst); ++ h_dst_userns = mnt_user_ns(h_dst->mnt); ++ h_dst_dentry = h_dst->dentry; ++ h_idst = d_inode(h_dst_dentry); + inode_unlock(h_idst); -+ err = vfsub_setxattr(h_dst, name, *buf, ssz, /*flags*/0); ++ err = vfsub_setxattr(h_dst_userns, h_dst_dentry, name, *buf, ssz, ++ /*flags*/0); + inode_lock_nested(h_idst, AuLsc_I_CHILD2); + if (unlikely(err)) { + if (verbose || au_debug_test()) @@ -36651,25 +36770,28 @@ diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c + return err; +} + -+int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags, ++int au_cpup_xattr(struct path *h_dst, struct path *h_src, int ignore_flags, + unsigned int verbose) +{ + int err, unlocked, acl_access, acl_default; + ssize_t ssz; ++ struct dentry *h_dst_dentry, *h_src_dentry; + struct inode *h_isrc, *h_idst; + char *value, *p, *o, *e; + + /* try stopping to update the source inode while we are referencing */ + /* there should not be the parent-child relationship between them */ -+ h_isrc = d_inode(h_src); -+ h_idst = d_inode(h_dst); ++ h_dst_dentry = h_dst->dentry; ++ h_idst = d_inode(h_dst_dentry); ++ h_src_dentry = h_src->dentry; ++ h_isrc = d_inode(h_src_dentry); + inode_unlock(h_idst); + inode_lock_shared_nested(h_isrc, AuLsc_I_CHILD); + inode_lock_nested(h_idst, AuLsc_I_CHILD2); + unlocked = 0; + + /* some filesystems don't list POSIX ACL, for example tmpfs */ -+ ssz = vfs_listxattr(h_src, NULL, 0); ++ ssz = vfs_listxattr(h_src_dentry, NULL, 0); + err = ssz; + if (unlikely(err < 0)) { + AuTraceErr(err); @@ -36688,7 +36810,7 @@ diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c + o = p; + if (unlikely(!p)) + goto out; -+ err = vfs_listxattr(h_src, p, ssz); ++ err = vfs_listxattr(h_src_dentry, p, ssz); + } + inode_unlock_shared(h_isrc); + unlocked = 1; @@ -36741,7 +36863,7 @@ diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c + +static int au_smack_reentering(struct super_block *sb) +{ -+#if IS_ENABLED(CONFIG_SECURITY_SMACK) ++#if IS_ENABLED(CONFIG_SECURITY_SMACK) || IS_ENABLED(CONFIG_SECURITY_SELINUX) + /* + * as a part of lookup, smack_d_instantiate() is called, and it calls + * i_op->getxattr(). ouch. @@ -36772,7 +36894,8 @@ diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c + } u; +}; + -+static ssize_t au_lgxattr(struct dentry *dentry, struct au_lgxattr *arg) ++static ssize_t au_lgxattr(struct dentry *dentry, struct inode *inode, ++ struct au_lgxattr *arg) +{ + ssize_t err; + int reenter; @@ -36786,7 +36909,7 @@ diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c + if (unlikely(err)) + goto out; + } -+ err = au_h_path_getattr(dentry, /*force*/1, &h_path, reenter); ++ err = au_h_path_getattr(dentry, inode, /*force*/1, &h_path, reenter); + if (unlikely(err)) + goto out_si; + if (unlikely(!h_path.dentry)) @@ -36801,7 +36924,7 @@ diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c + break; + case AU_XATTR_GET: + AuDebugOn(d_is_negative(h_path.dentry)); -+ err = vfs_getxattr(h_path.dentry, ++ err = vfs_getxattr(mnt_user_ns(h_path.mnt), h_path.dentry, + arg->u.get.name, arg->u.get.value, + arg->u.get.size); + break; @@ -36828,11 +36951,10 @@ diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c + }, + }; + -+ return au_lgxattr(dentry, &arg); ++ return au_lgxattr(dentry, /*inode*/NULL, &arg); +} + -+static ssize_t au_getxattr(struct dentry *dentry, -+ struct inode *inode __maybe_unused, ++static ssize_t au_getxattr(struct dentry *dentry, struct inode *inode, + const char *name, void *value, size_t size) +{ + struct au_lgxattr arg = { @@ -36844,7 +36966,7 @@ diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c + }, + }; + -+ return au_lgxattr(dentry, &arg); ++ return au_lgxattr(dentry, inode, &arg); +} + +static int au_setxattr(struct dentry *dentry, struct inode *inode, @@ -36874,6 +36996,7 @@ diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c +} + +static int au_xattr_set(const struct xattr_handler *handler, ++ struct user_namespace *userns, + struct dentry *dentry, struct inode *inode, + const char *name, const void *value, size_t size, + int flags) @@ -36903,11 +37026,11 @@ diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c +} diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c --- /usr/share/empty/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/xino.c 2019-07-11 15:42:14.475571481 +0200 -@@ -0,0 +1,1965 @@ ++++ linux/fs/aufs/xino.c 2022-10-26 22:30:38.475982192 +0200 +@@ -0,0 +1,1926 @@ +// SPDX-License-Identifier: GPL-2.0 +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -37116,7 +37239,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + } + + err = -EINVAL; -+ if (unlikely(sb == d->d_sb)) { ++ if (unlikely(sb && sb == d->d_sb)) { + if (!silent) + pr_err("%s must be outside\n", fpath); + goto out; @@ -37142,22 +37265,23 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + struct file *copy_src) +{ + struct file *file; -+ struct dentry *dentry, *parent; ++ struct dentry *dentry; + struct inode *dir, *delegated; + struct qstr *name; -+ struct path path; ++ struct path ppath, path; + int err, do_unlock; + struct au_xino_lock_dir ldir; + + do_unlock = 1; + au_xino_lock_dir(sb, base, &ldir); + dentry = base->dentry; -+ parent = dentry->d_parent; /* dir inode is locked */ -+ dir = d_inode(parent); ++ ppath.dentry = dentry->d_parent; /* dir inode is locked */ ++ ppath.mnt = base->mnt; ++ dir = d_inode(ppath.dentry); + IMustLock(dir); + + name = &dentry->d_name; -+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len); ++ path.dentry = vfsub_lookup_one_len(name->name, &ppath, name->len); + if (IS_ERR(path.dentry)) { + file = (void *)path.dentry; + pr_err("%pd lookup err %ld\n", dentry, PTR_ERR(path.dentry)); @@ -37165,7 +37289,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + } + + /* no need to mnt_want_write() since we call dentry_open() later */ -+ err = vfs_create(dir, path.dentry, 0666, NULL); ++ err = vfs_create(mnt_user_ns(base->mnt), dir, path.dentry, 0666, NULL); + if (unlikely(err)) { + file = ERR_PTR(err); + pr_err("%pd create err %d\n", dentry, err); @@ -37567,8 +37691,8 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + ino_t h_ino, ino; +}; + -+static int au_xino_do_write(vfs_writef_t write, struct file *file, -+ struct au_xi_calc *calc, ino_t ino); ++static int au_xino_do_write(struct file *file, struct au_xi_calc *calc, ++ ino_t ino); + +static void au_xino_call_do_new_async(void *args) +{ @@ -37597,7 +37721,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + + file = au_xino_file(br->br_xino, a->calc.idx); + AuDebugOn(!file); -+ err = au_xino_do_write(sbi->si_xwrite, file, &a->calc, a->ino); ++ err = au_xino_do_write(file, &a->calc, a->ino); + if (unlikely(err)) { + AuIOErr("err %d\n", err); + goto out; @@ -37698,7 +37822,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + return 0; /* no xino */ + + sbinfo = au_sbi(sb); -+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &calc.pos); ++ sz = xino_fread(file, ino, sizeof(*ino), &calc.pos); + if (sz == sizeof(*ino)) + return 0; /* success */ + @@ -37710,12 +37834,12 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + return err; +} + -+static int au_xino_do_write(vfs_writef_t write, struct file *file, -+ struct au_xi_calc *calc, ino_t ino) ++static int au_xino_do_write(struct file *file, struct au_xi_calc *calc, ++ ino_t ino) +{ + ssize_t sz; + -+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &calc->pos); ++ sz = xino_fwrite(file, &ino, sizeof(ino), &calc->pos); + if (sz == sizeof(ino)) + return 0; /* success */ + @@ -37765,7 +37889,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + goto out; + } + -+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, file, &calc, ino); ++ err = au_xino_do_write(file, &calc, ino); + if (!err) { + br = au_sbr(sb, bindex); + if (au_opt_test(mnt_flags, TRUNC_XINO) @@ -37779,40 +37903,27 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + return -EIO; +} + -+static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos); ++static ssize_t xino_fread_wkq(struct file *file, void *buf, size_t size, ++ loff_t *pos); + +/* todo: unnecessary to support mmap_sem since kernel-space? */ -+ssize_t xino_fread(vfs_readf_t func, struct file *file, void *kbuf, size_t size, -+ loff_t *pos) ++ssize_t xino_fread(struct file *file, void *kbuf, size_t size, loff_t *pos) +{ + ssize_t err; -+ mm_segment_t oldfs; -+ union { -+ void *k; -+ char __user *u; -+ } buf; + int i; + const int prevent_endless = 10; + + i = 0; -+ buf.k = kbuf; -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); + do { -+ err = func(file, buf.u, size, pos); ++ err = vfsub_read_k(file, kbuf, size, pos); + if (err == -EINTR + && !au_wkq_test() + && fatal_signal_pending(current)) { -+ set_fs(oldfs); -+ err = xino_fread_wkq(func, file, kbuf, size, pos); ++ err = xino_fread_wkq(file, kbuf, size, pos); + BUG_ON(err == -EINTR); -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); + } + } while (i++ < prevent_endless + && (err == -EAGAIN || err == -EINTR)); -+ set_fs(oldfs); + +#if 0 /* reserved for future use */ + if (err > 0) @@ -37824,7 +37935,6 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + +struct xino_fread_args { + ssize_t *errp; -+ vfs_readf_t func; + struct file *file; + void *buf; + size_t size; @@ -37834,17 +37944,16 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c +static void call_xino_fread(void *args) +{ + struct xino_fread_args *a = args; -+ *a->errp = xino_fread(a->func, a->file, a->buf, a->size, a->pos); ++ *a->errp = xino_fread(a->file, a->buf, a->size, a->pos); +} + -+static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos) ++static ssize_t xino_fread_wkq(struct file *file, void *buf, size_t size, ++ loff_t *pos) +{ + ssize_t err; + int wkq_err; + struct xino_fread_args args = { + .errp = &err, -+ .func = func, + .file = file, + .buf = buf, + .size = size, @@ -37858,39 +37967,27 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + return err; +} + -+static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos); ++static ssize_t xino_fwrite_wkq(struct file *file, void *buf, size_t size, ++ loff_t *pos); + -+static ssize_t do_xino_fwrite(vfs_writef_t func, struct file *file, void *kbuf, -+ size_t size, loff_t *pos) ++static ssize_t do_xino_fwrite(struct file *file, void *kbuf, size_t size, ++ loff_t *pos) +{ + ssize_t err; -+ mm_segment_t oldfs; -+ union { -+ void *k; -+ const char __user *u; -+ } buf; + int i; + const int prevent_endless = 10; + + i = 0; -+ buf.k = kbuf; -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); + do { -+ err = func(file, buf.u, size, pos); ++ err = vfsub_write_k(file, kbuf, size, pos); + if (err == -EINTR + && !au_wkq_test() + && fatal_signal_pending(current)) { -+ set_fs(oldfs); -+ err = xino_fwrite_wkq(func, file, kbuf, size, pos); ++ err = xino_fwrite_wkq(file, kbuf, size, pos); + BUG_ON(err == -EINTR); -+ oldfs = get_fs(); -+ set_fs(KERNEL_DS); + } + } while (i++ < prevent_endless + && (err == -EAGAIN || err == -EINTR)); -+ set_fs(oldfs); + +#if 0 /* reserved for future use */ + if (err > 0) @@ -37902,7 +37999,6 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + +struct do_xino_fwrite_args { + ssize_t *errp; -+ vfs_writef_t func; + struct file *file; + void *buf; + size_t size; @@ -37912,17 +38008,16 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c +static void call_do_xino_fwrite(void *args) +{ + struct do_xino_fwrite_args *a = args; -+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos); ++ *a->errp = do_xino_fwrite(a->file, a->buf, a->size, a->pos); +} + -+static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos) ++static ssize_t xino_fwrite_wkq(struct file *file, void *buf, size_t size, ++ loff_t *pos) +{ + ssize_t err; + int wkq_err; + struct do_xino_fwrite_args args = { + .errp = &err, -+ .func = func, + .file = file, + .buf = buf, + .size = size, @@ -37940,18 +38035,17 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + return err; +} + -+ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf, -+ size_t size, loff_t *pos) ++ssize_t xino_fwrite(struct file *file, void *buf, size_t size, loff_t *pos) +{ + ssize_t err; + + if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) { + lockdep_off(); -+ err = do_xino_fwrite(func, file, buf, size, pos); ++ err = do_xino_fwrite(file, buf, size, pos); + lockdep_on(); + } else { + lockdep_off(); -+ err = xino_fwrite_wkq(func, file, buf, size, pos); ++ err = xino_fwrite_wkq(file, buf, size, pos); + lockdep_on(); + } + @@ -38002,17 +38096,17 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + p = sbinfo->si_xib_buf; + pos = sbinfo->si_xib_last_pindex; + pos *= PAGE_SIZE; -+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos); ++ sz = xino_fwrite(xib, p, PAGE_SIZE, &pos); + if (unlikely(sz != PAGE_SIZE)) + goto out; + + pos = pindex; + pos *= PAGE_SIZE; + if (vfsub_f_size_read(xib) >= pos + PAGE_SIZE) -+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos); ++ sz = xino_fread(xib, p, PAGE_SIZE, &pos); + else { + memset(p, 0, PAGE_SIZE); -+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos); ++ sz = xino_fwrite(xib, p, PAGE_SIZE, &pos); + } + if (sz == PAGE_SIZE) { + sbinfo->si_xib_last_pindex = pindex; @@ -38063,7 +38157,6 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + unsigned long pindex; + loff_t pos, pend; + struct au_sbinfo *sbinfo; -+ vfs_readf_t func; + ino_t *ino; + unsigned long *p; + @@ -38071,11 +38164,10 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + sbinfo = au_sbi(sb); + MtxMustLock(&sbinfo->si_xib_mtx); + p = sbinfo->si_xib_buf; -+ func = sbinfo->si_xread; + pend = vfsub_f_size_read(file); + pos = 0; + while (pos < pend) { -+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos); ++ sz = xino_fread(file, page, PAGE_SIZE, &pos); + err = sz; + if (unlikely(sz <= 0)) + goto out; @@ -38164,7 +38256,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + p = sbinfo->si_xib_buf; + memset(p, 0, PAGE_SIZE); + pos = 0; -+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos); ++ sz = xino_fwrite(sbinfo->si_xib, p, PAGE_SIZE, &pos); + if (unlikely(sz != PAGE_SIZE)) { + err = sz; + AuIOErr("err %d\n", err); @@ -38262,9 +38354,10 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + if (unlikely(ul)) { + pr_warn("xi_writing %lu\n", ul); + hlist_bl_lock(hbl); -+ hlist_bl_for_each_entry_safe (p, pos, n, hbl, node) { ++ hlist_bl_for_each_entry_safe(p, pos, n, hbl, node) { + hlist_bl_del(&p->node); -+ au_kfree_rcu(p); ++ /* kmemleak reported au_kfree_rcu() doesn't free it */ ++ kfree(p); + } + hlist_bl_unlock(hbl); + } @@ -38302,7 +38395,6 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + SiMustWriteLock(sb); + + sbinfo = au_sbi(sb); -+ /* unnecessary to clear sbinfo->si_xread and ->si_xwrite */ + if (sbinfo->si_xib) + fput(sbinfo->si_xib); + sbinfo->si_xib = NULL; @@ -38329,8 +38421,6 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + if (sbinfo->si_xib) + fput(sbinfo->si_xib); + sbinfo->si_xib = file; -+ sbinfo->si_xread = vfs_readf(file); -+ sbinfo->si_xwrite = vfs_writef(file); + xi_sb = file_inode(file)->i_sb; + sbinfo->si_ximaxent = xi_sb->s_maxbytes; + if (unlikely(sbinfo->si_ximaxent < PAGE_SIZE)) { @@ -38351,8 +38441,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + sbinfo->si_xib_next_bit = 0; + if (vfsub_f_size_read(file) < PAGE_SIZE) { + pos = 0; -+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf, -+ PAGE_SIZE, &pos); ++ err = xino_fwrite(file, sbinfo->si_xib_buf, PAGE_SIZE, &pos); + if (unlikely(err != PAGE_SIZE)) + goto out_free; + } @@ -38403,7 +38492,6 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c +} + +struct au_xino_do_set_br { -+ vfs_writef_t writef; + struct au_branch *br; + ino_t h_ino; + aufs_bindex_t bshared; @@ -38445,7 +38533,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + goto out; + AuDebugOn(!file); + -+ err = au_xino_do_write(args->writef, file, &calc, AUFS_ROOT_INO); ++ err = au_xino_do_write(file, &calc, AUFS_ROOT_INO); + if (unlikely(err)) + au_xino_put(br); + @@ -38465,7 +38553,6 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + + bbot = au_sbbot(sb); + inode = d_inode(sb->s_root); -+ args.writef = au_sbi(sb)->si_xwrite; + for (bindex = 0; bindex <= bbot; bindex++) { + args.h_ino = au_h_iptr(inode, bindex)->i_ino; + args.br = au_sbr(sb, bindex); @@ -38620,7 +38707,6 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + .br = br + }; + -+ args.writef = au_sbi(sb)->si_xwrite; + args.bshared = sbr_find_shared(sb, /*btop*/0, au_sbbot(sb), + au_br_sb(br)); + err = au_xino_do_set_br(sb, base, &args); @@ -38704,7 +38790,6 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + struct au_hinode *hi; + struct inode *h_inode; + struct au_branch *br; -+ vfs_writef_t xwrite; + struct au_xi_calc calc; + struct file *file; + @@ -38726,7 +38811,6 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + if (bindex < 0) + return; + -+ xwrite = au_sbi(sb)->si_xwrite; + try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO); + hi = au_hinode(iinfo, bindex); + bbot = iinfo->ii_bbot; @@ -38747,7 +38831,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + if (IS_ERR_OR_NULL(file)) + continue; + -+ err = au_xino_do_write(xwrite, file, &calc, /*ino*/0); ++ err = au_xino_do_write(file, &calc, /*ino*/0); + if (!err && try_trunc + && au_test_fs_trunc_xino(au_br_sb(br))) + xino_try_trunc(sb, br); @@ -38872,11 +38956,11 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c +} diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/linux/aufs_type.h --- /usr/share/empty/include/uapi/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/include/uapi/linux/aufs_type.h 2019-10-08 20:39:02.730958260 +0200 ++++ linux/include/uapi/linux/aufs_type.h 2022-10-26 22:30:38.475982192 +0200 @@ -0,0 +1,452 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* -+ * Copyright (C) 2005-2019 Junjiro R. Okajima ++ * Copyright (C) 2005-2021 Junjiro R. Okajima + * + * This program, aufs is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by @@ -38909,20 +38993,21 @@ diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/lin +#define pr_fmt(fmt) \ + AUFS_NAME " %s:%d:%.*s[%d]: " fmt, __func__, __LINE__, \ + (int)sizeof(current->comm), current->comm, current->pid ++#include +#else +#include +#include ++#include +#endif /* __KERNEL__ */ + -+#include -+ -+#define AUFS_VERSION "5.x-rcN-20190923" ++#define AUFS_VERSION "5.15.41-20220620" + +/* todo? move this to linux-2.6.19/include/magic.h */ +#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's') + +/* ---------------------------------------------------------------------- */ + ++#ifdef __KERNEL__ +#ifdef CONFIG_AUFS_BRANCH_MAX_127 +typedef int8_t aufs_bindex_t; +#define AUFS_BRANCH_MAX 127 @@ -38937,7 +39022,6 @@ diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/lin +#endif +#endif + -+#ifdef __KERNEL__ +#ifndef AUFS_BRANCH_MAX +#error unknown CONFIG_AUFS_BRANCH_MAX value +#endif @@ -39163,7 +39247,7 @@ diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/lin + uint8_t type; + uint8_t nlen; + uint8_t wh; -+ char name[0]; ++ char name[]; +} __aligned(8); + +static inline int au_rdu_len(int nlen) @@ -39214,7 +39298,7 @@ diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/lin + uint8_t oldnamelen; + uint64_t _padding; + }; -+ uint8_t oldname[0]; ++ uint8_t oldname[]; +} __aligned(8); + +struct au_drinfo_fdata { @@ -39308,7 +39392,7 @@ diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/lin + struct { + int16_t id; + int perm; -+ char path[0]; ++ char path[]; + }; +} __aligned(8); + @@ -39327,14 +39411,14 @@ diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/lin + +#endif /* __AUFS_TYPE_H__ */ SPDX-License-Identifier: GPL-2.0 -aufs5.x-rcN loopback patch +aufs5.15.41 loopback patch diff --git a/drivers/block/loop.c b/drivers/block/loop.c -index 80d06084b043..a83cdfec7359 100644 +index 7a9e40b97831..5ed06240cc9c 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c -@@ -625,6 +625,15 @@ static inline void loop_update_dio(struct loop_device *lo) - lo->use_dio); +@@ -673,6 +673,15 @@ static inline void loop_update_dio(struct loop_device *lo) + lo->use_dio); } +static struct file *loop_real_file(struct file *file) @@ -39346,28 +39430,28 @@ index 80d06084b043..a83cdfec7359 100644 + return f; +} + - static void loop_reread_partitions(struct loop_device *lo, - struct block_device *bdev) + static void loop_reread_partitions(struct loop_device *lo) { -@@ -678,6 +687,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, - unsigned int arg) + int rc; +@@ -730,6 +739,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, { - struct file *file = NULL, *old_file; -+ struct file *f, *virt_file = NULL, *old_virt_file; - int error; - bool partscan; - -@@ -697,12 +707,19 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, - file = fget(arg); - if (!file) + 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; +@@ -749,11 +759,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; @@ -39377,7 +39461,7 @@ index 80d06084b043..a83cdfec7359 100644 error = -EINVAL; -@@ -714,6 +731,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, +@@ -766,6 +784,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; @@ -39385,64 +39469,64 @@ index 80d06084b043..a83cdfec7359 100644 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)); -@@ -727,6 +745,8 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, +@@ -788,6 +807,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); + loop_reread_partitions(lo); return 0; -@@ -735,6 +755,8 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, - mutex_unlock(&loop_ctl_mutex); - if (file) - fput(file); +@@ -796,6 +817,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); return error; } -@@ -939,7 +961,7 @@ static void loop_update_rotational(struct loop_device *lo) - static int loop_set_fd(struct loop_device *lo, fmode_t mode, - struct block_device *bdev, unsigned int arg) +@@ -1201,6 +1224,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, + const struct loop_config *config) { -- struct file *file; -+ struct file *file, *f, *virt_file = NULL; - struct inode *inode; + struct file *file = fget(config->fd); ++ struct file *f, *virt_file = NULL; + struct inode *inode; struct address_space *mapping; - struct block_device *claimed_bdev = NULL; -@@ -955,6 +977,12 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, - file = fget(arg); - if (!file) - goto out; + int error; +@@ -1216,6 +1240,13 @@ static int loop_configure(struct loop_device *lo, fmode_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 -@@ -1003,6 +1031,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, + * here to avoid changing device under exclusive owner. +@@ -1281,6 +1312,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_flags = lo_flags; lo->lo_backing_file = file; + lo->lo_backing_virt_file = virt_file; - lo->transfer = NULL; - lo->ioctl = NULL; - lo->lo_sizelimit = 0; -@@ -1046,6 +1075,8 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, - bd_abort_claiming(bdev, claimed_bdev, loop_set_fd); + lo->old_gfp_mask = mapping_gfp_mask(mapping); + mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS)); + +@@ -1331,6 +1363,8 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, + bd_abort_claiming(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); -@@ -1092,6 +1123,7 @@ loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer, + return error; +@@ -1339,6 +1373,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; @@ -39450,7 +39534,7 @@ index 80d06084b043..a83cdfec7359 100644 gfp_t gfp = lo->old_gfp_mask; struct block_device *bdev = lo->lo_device; int err = 0; -@@ -1115,6 +1147,7 @@ static int __loop_clr_fd(struct loop_device *lo, bool release) +@@ -1390,6 +1425,7 @@ static int __loop_clr_fd(struct loop_device *lo, bool release) spin_lock_irq(&lo->lo_lock); lo->lo_backing_file = NULL; @@ -39458,7 +39542,7 @@ index 80d06084b043..a83cdfec7359 100644 spin_unlock_irq(&lo->lo_lock); loop_release_xfer(lo); -@@ -1197,6 +1230,8 @@ static int __loop_clr_fd(struct loop_device *lo, bool release) +@@ -1470,6 +1506,8 @@ static int __loop_clr_fd(struct loop_device *lo, bool release) */ if (filp) fput(filp); @@ -39468,7 +39552,7 @@ index 80d06084b043..a83cdfec7359 100644 } diff --git a/drivers/block/loop.h b/drivers/block/loop.h -index af75a5ee4094..1e6ee5a4f623 100644 +index 04c88dd6eabd..0ff3ba22ee17 100644 --- a/drivers/block/loop.h +++ b/drivers/block/loop.h @@ -46,7 +46,7 @@ struct loop_device { @@ -39476,15 +39560,15 @@ index af75a5ee4094..1e6ee5a4f623 100644 unsigned long arg); - struct file * lo_backing_file; -+ struct file * lo_backing_file, *lo_backing_virt_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 0309f0d502ff..19feb4f3cb5f 100644 +index 99ceca144044..e49dfe855032 100644 --- a/fs/aufs/f_op.c +++ b/fs/aufs/f_op.c -@@ -359,7 +359,7 @@ static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter) +@@ -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; @@ -39494,7 +39578,7 @@ index 0309f0d502ff..19feb4f3cb5f 100644 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 9ba35a878ecd..4ed0ff03d5ab 100644 +index 74347bd75b38..5ef888a1d53f 100644 --- a/fs/aufs/loop.c +++ b/fs/aufs/loop.c @@ -133,3 +133,19 @@ void au_loopback_fin(void) @@ -39518,7 +39602,7 @@ index 9ba35a878ecd..4ed0ff03d5ab 100644 + return f; +} diff --git a/fs/aufs/loop.h b/fs/aufs/loop.h -index f31e40aff267..e13fb1a0717a 100644 +index 7293bee427f9..3345c098d0d4 100644 --- a/fs/aufs/loop.h +++ b/fs/aufs/loop.h @@ -26,6 +26,8 @@ void au_warn_loopback(struct super_block *h_sb); @@ -39540,15 +39624,15 @@ index f31e40aff267..e13fb1a0717a 100644 #endif /* __KERNEL__ */ diff --git a/fs/aufs/super.c b/fs/aufs/super.c -index a97e2921cb09..f74eb6962684 100644 +index 90043afec51c..0835f6da42d9 100644 --- a/fs/aufs/super.c +++ b/fs/aufs/super.c -@@ -844,7 +844,10 @@ static const struct super_operations aufs_sop = { +@@ -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, -- .remount_fs = aufs_remount_fs -+ .remount_fs = aufs_remount_fs, +- .sync_fs = aufs_sync_fs ++ .sync_fs = aufs_sync_fs, +#ifdef CONFIG_AUFS_BDEV_LOOP + .real_loop = aufs_real_loop +#endif @@ -39556,14 +39640,14 @@ index a97e2921cb09..f74eb6962684 100644 /* ---------------------------------------------------------------------- */ diff --git a/include/linux/fs.h b/include/linux/fs.h -index 3dbec51c2037..38ab7b6c7c6d 100644 +index e60d8ad85400..2ac5317f9b79 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h -@@ -1948,6 +1948,10 @@ struct super_operations { +@@ -2226,6 +2226,10 @@ struct super_operations { struct shrink_control *); long (*free_cached_objects)(struct super_block *, struct shrink_control *); -+#if defined(CONFIG_BLK_DEV_LOOP) || defined(CONFIG_BLK_DEV_LOOP_MODULE) ++#if IS_ENABLED(CONFIG_BLK_DEV_LOOP) || IS_ENABLED(CONFIG_BLK_DEV_LOOP_MODULE) + /* and aufs */ + struct file *(*real_loop)(struct file *); +#endif