X-Git-Url: http://git.pld-linux.org/?a=blobdiff_plain;f=kernel-aufs4.patch;h=8b5e8f8c715e8a39216d349e6b2fcba543b26287;hb=1c60b727338bd05e415668bde455f1029ff88814;hp=16f65cba11a7c76dd1d7cc62a77312fd9fa04d0a;hpb=f2c43d5f9be66527e3189ec126a8f04f1f4d2107;p=packages%2Fkernel.git diff --git a/kernel-aufs4.patch b/kernel-aufs4.patch index 16f65cba..8b5e8f8c 100644 --- a/kernel-aufs4.patch +++ b/kernel-aufs4.patch @@ -1,7 +1,7 @@ -aufs4.9 kbuild patch +aufs4.x-rcN kbuild patch diff --git a/fs/Kconfig b/fs/Kconfig -index 4bd03a2..620e01b 100644 +index b0e42b6..7fa4b68 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -249,6 +249,7 @@ source "fs/pstore/Kconfig" @@ -13,33 +13,21 @@ index 4bd03a2..620e01b 100644 endif # MISC_FILESYSTEMS diff --git a/fs/Makefile b/fs/Makefile -index ed2b632..aa6d14b 100644 +index 7bbaca9..a026491 100644 --- a/fs/Makefile +++ b/fs/Makefile -@@ -129,3 +129,4 @@ obj-y += exofs/ # Multiple modules +@@ -128,3 +128,4 @@ obj-y += exofs/ # Multiple modules obj-$(CONFIG_CEPH_FS) += ceph/ obj-$(CONFIG_PSTORE) += pstore/ obj-$(CONFIG_EFIVAR_FS) += efivarfs/ +obj-$(CONFIG_AUFS_FS) += aufs/ -diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild -index cd2be1c..78f3c68 100644 ---- a/include/uapi/linux/Kbuild -+++ b/include/uapi/linux/Kbuild -@@ -59,6 +59,7 @@ header-y += atmsvc.h - header-y += atm_tcp.h - header-y += atm_zatm.h - header-y += audit.h -+header-y += aufs_type.h - header-y += auto_fs4.h - header-y += auto_fs.h - header-y += auxvec.h -aufs4.9 base patch +aufs4.x-rcN base patch diff --git a/MAINTAINERS b/MAINTAINERS -index 63cefa6..d78b954 100644 +index 09b5ab6..6640ab1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -2293,6 +2293,19 @@ F: include/linux/audit.h +@@ -2348,6 +2348,19 @@ F: include/linux/audit.h F: include/uapi/linux/audit.h F: kernel/audit* @@ -60,10 +48,10 @@ index 63cefa6..d78b954 100644 M: Miguel Ojeda Sandonis W: http://miguelojeda.es/auxdisplay.htm diff --git a/drivers/block/loop.c b/drivers/block/loop.c -index fa1b7a9..6ee9235 100644 +index ebbd0c3..6b8a6a4c 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c -@@ -701,6 +701,24 @@ static inline int is_loop_device(struct file *file) +@@ -700,6 +700,24 @@ static inline int is_loop_device(struct file *file) return i && S_ISBLK(i->i_mode) && MAJOR(i->i_rdev) == LOOP_MAJOR; } @@ -89,7 +77,7 @@ index fa1b7a9..6ee9235 100644 static ssize_t loop_attr_show(struct device *dev, char *page, diff --git a/fs/dcache.c b/fs/dcache.c -index 5c7cc95..df0268c 100644 +index a9f995f..3458af5 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1164,7 +1164,7 @@ enum d_walk_ret { @@ -102,10 +90,10 @@ index 5c7cc95..df0268c 100644 void (*finish)(void *)) { diff --git a/fs/fcntl.c b/fs/fcntl.c -index 350a2c8..6f42279 100644 +index f4e7267..d39404c 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c -@@ -29,7 +29,7 @@ +@@ -31,7 +31,7 @@ #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME) @@ -114,7 +102,7 @@ index 350a2c8..6f42279 100644 { struct inode * inode = file_inode(filp); int error = 0; -@@ -60,6 +60,8 @@ static int setfl(int fd, struct file * filp, unsigned long arg) +@@ -62,6 +62,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); @@ -124,10 +112,10 @@ index 350a2c8..6f42279 100644 return error; diff --git a/fs/inode.c b/fs/inode.c -index 88110fd..9a9ba3a 100644 +index db59147..69cbe9c 100644 --- a/fs/inode.c +++ b/fs/inode.c -@@ -1642,7 +1642,7 @@ int generic_update_time(struct inode *inode, struct timespec *time, int flags) +@@ -1640,7 +1640,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. */ @@ -137,10 +125,10 @@ index 88110fd..9a9ba3a 100644 int (*update_time)(struct inode *, struct timespec *, int); diff --git a/fs/read_write.c b/fs/read_write.c -index 190e0d36..4052813 100644 +index 19d4d88..05033f7 100644 --- a/fs/read_write.c +++ b/fs/read_write.c -@@ -515,6 +515,28 @@ ssize_t __vfs_write(struct file *file, const char __user *p, size_t count, +@@ -513,6 +513,28 @@ ssize_t __vfs_write(struct file *file, const char __user *p, size_t count, } EXPORT_SYMBOL(__vfs_write); @@ -170,10 +158,10 @@ index 190e0d36..4052813 100644 { mm_segment_t old_fs; diff --git a/fs/splice.c b/fs/splice.c -index 5a7750b..28160a7 100644 +index 540c4a4..4a0bc62 100644 --- a/fs/splice.c +++ b/fs/splice.c -@@ -855,8 +855,8 @@ ssize_t generic_splice_sendpage(struct pipe_inode_info *pipe, struct file *out, +@@ -853,8 +853,8 @@ EXPORT_SYMBOL(generic_splice_sendpage); /* * Attempt to initiate a splice from pipe to file. */ @@ -184,7 +172,7 @@ index 5a7750b..28160a7 100644 { ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); -@@ -872,9 +872,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, +@@ -870,9 +870,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. */ @@ -197,23 +185,36 @@ index 5a7750b..28160a7 100644 { 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 11ba023..abf6a5d 100644 +--- a/fs/sync.c ++++ b/fs/sync.c +@@ -27,7 +27,7 @@ + * wait == 1 case since in that case write_inode() functions do + * sync_dirty_buffer() and thus effectively write one block at a time. + */ +-static int __sync_filesystem(struct super_block *sb, int wait) ++int __sync_filesystem(struct super_block *sb, int wait) + { + if (wait) + sync_inodes_sb(sb); diff --git a/include/linux/file.h b/include/linux/file.h -index 7444f5f..bdac0be 100644 +index 61eb82c..e700888 100644 --- a/include/linux/file.h +++ b/include/linux/file.h -@@ -19,6 +19,7 @@ +@@ -19,6 +19,7 @@ struct dentry; struct path; - extern struct file *alloc_file(struct path *, fmode_t mode, + extern struct file *alloc_file(const struct path *, fmode_t mode, const struct file_operations *fop); +extern struct file *get_empty_filp(void); static inline void fput_light(struct file *file, int fput_needed) { diff --git a/include/linux/fs.h b/include/linux/fs.h -index dc0478c..27c05e7 100644 +index 803e5a9..22d2910 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h -@@ -1291,6 +1291,7 @@ struct fasync_struct { +@@ -1248,6 +1248,7 @@ extern void fasync_free(struct fasync_struct *); /* can be called from interrupts */ extern void kill_fasync(struct fasync_struct **, int, int); @@ -221,7 +222,7 @@ index dc0478c..27c05e7 100644 extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int force); extern void f_setown(struct file *filp, unsigned long arg, int force); extern void f_delown(struct file *filp); -@@ -1715,6 +1716,7 @@ struct file_operations { +@@ -1674,6 +1675,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); @@ -229,7 +230,7 @@ index dc0478c..27c05e7 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); -@@ -1768,6 +1770,12 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, +@@ -1750,6 +1752,12 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, struct iovec *fast_pointer, struct iovec **ret_pointer); @@ -242,7 +243,7 @@ index dc0478c..27c05e7 100644 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 *); extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *); -@@ -2140,6 +2148,7 @@ extern int iterate_mounts(int (*)(struct vfsmount *, void *), void *, +@@ -2131,6 +2139,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 timespec *, int); @@ -250,11 +251,19 @@ index dc0478c..27c05e7 100644 /* /sys/fs */ extern struct kobject *fs_kobj; +@@ -2411,6 +2420,7 @@ static inline bool sb_is_blkdev_sb(struct super_block *sb) + return false; + } + #endif ++extern int __sync_filesystem(struct super_block *, int); + extern int sync_filesystem(struct super_block *); + extern const struct file_operations def_blk_fops; + extern const struct file_operations def_chr_fops; diff --git a/include/linux/splice.h b/include/linux/splice.h -index 00a2116..1f0a4a2 100644 +index db42746..12f3a5a 100644 --- a/include/linux/splice.h +++ b/include/linux/splice.h -@@ -86,4 +86,10 @@ extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *, +@@ -86,4 +86,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; @@ -265,13 +274,13 @@ index 00a2116..1f0a4a2 100644 + struct pipe_inode_info *pipe, size_t len, + unsigned int flags); #endif -aufs4.9 mmap patch +aufs4.x-rcN mmap patch diff --git a/fs/proc/base.c b/fs/proc/base.c -index ca651ac..0e8551a 100644 +index f1e1927..7b5af0c 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c -@@ -1953,7 +1953,7 @@ static int map_files_get_link(struct dentry *dentry, struct path *path) +@@ -1943,7 +1943,7 @@ static int map_files_get_link(struct dentry *dentry, struct path *path) down_read(&mm->mmap_sem); vma = find_exact_vma(mm, vm_start, vm_end); if (vma && vma->vm_file) { @@ -281,7 +290,7 @@ index ca651ac..0e8551a 100644 rc = 0; } diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c -index f8595e8..cb8eda0 100644 +index 7563437..7c0dc0f 100644 --- a/fs/proc/nommu.c +++ b/fs/proc/nommu.c @@ -45,7 +45,10 @@ static int nommu_region_show(struct seq_file *m, struct vm_region *region) @@ -297,10 +306,10 @@ index f8595e8..cb8eda0 100644 ino = inode->i_ino; } diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c -index 35b92d8..5b981db 100644 +index 520802d..61a037d 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c -@@ -291,7 +291,10 @@ static int is_stack(struct proc_maps_private *priv, +@@ -292,7 +292,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid) const char *name = NULL; if (file) { @@ -312,7 +321,7 @@ index 35b92d8..5b981db 100644 dev = inode->i_sb->s_dev; ino = inode->i_ino; pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT; -@@ -1627,7 +1630,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid) +@@ -1638,7 +1641,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid) struct proc_maps_private *proc_priv = &numa_priv->proc_maps; struct vm_area_struct *vma = v; struct numa_maps *md = &numa_priv->md; @@ -322,10 +331,10 @@ index 35b92d8..5b981db 100644 struct mm_walk walk = { .hugetlb_entry = gather_hugetlb_stats, diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c -index 3717562..6a328f1 100644 +index 23266694..58e59b6 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, +@@ -157,7 +157,10 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma, file = vma->vm_file; if (file) { @@ -338,10 +347,10 @@ index 3717562..6a328f1 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 a92c8d7..1d83a2a 100644 +index 6f543a4..696494b 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h -@@ -1266,6 +1266,28 @@ static inline int fixup_user_fault(struct task_struct *tsk, +@@ -1306,6 +1306,28 @@ static inline int fixup_user_fault(struct task_struct *tsk, } #endif @@ -371,10 +380,10 @@ index a92c8d7..1d83a2a 100644 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 4a8aced..badd16b 100644 +index 45cdb27..1a40012 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h -@@ -275,6 +275,7 @@ struct vm_region { +@@ -259,6 +259,7 @@ struct vm_region { unsigned long vm_top; /* region allocated to here */ unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */ struct file *vm_file; /* the backing file or NULL */ @@ -382,7 +391,7 @@ index 4a8aced..badd16b 100644 int vm_usage; /* region usage count (access under nommu_region_sem) */ bool vm_icache_flushed : 1; /* true if the icache has been flushed for -@@ -349,6 +350,7 @@ struct vm_area_struct { +@@ -333,6 +334,7 @@ struct vm_area_struct { unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE units */ struct file * vm_file; /* File we map to (can be NULL). */ @@ -391,10 +400,10 @@ index 4a8aced..badd16b 100644 #ifndef CONFIG_MMU diff --git a/kernel/fork.c b/kernel/fork.c -index 997ac1d..4d0131b 100644 +index e53770d..cdf7516 100644 --- a/kernel/fork.c +++ b/kernel/fork.c -@@ -624,7 +624,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, +@@ -665,7 +665,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, struct inode *inode = file_inode(file); struct address_space *mapping = file->f_mapping; @@ -404,12 +413,12 @@ index 997ac1d..4d0131b 100644 atomic_dec(&inode->i_writecount); i_mmap_lock_write(mapping); diff --git a/mm/Makefile b/mm/Makefile -index 295bd7a..14fa1c8 100644 +index 026f6a8..723da17 100644 --- a/mm/Makefile +++ b/mm/Makefile -@@ -37,7 +37,7 @@ obj-y := filemap.o mempool.o oom_kill.o \ +@@ -39,7 +39,7 @@ obj-y := filemap.o mempool.o oom_kill.o \ mm_init.o mmu_context.o percpu.o slab_common.o \ - compaction.o vmacache.o \ + compaction.o vmacache.o swap_slots.o \ interval_tree.o list_lru.o workingset.o \ - debug.o $(mmu-y) + prfile.o debug.o $(mmu-y) @@ -417,33 +426,20 @@ index 295bd7a..14fa1c8 100644 obj-y += init-mm.o diff --git a/mm/filemap.c b/mm/filemap.c -index 50b52fe..9e607f9 100644 +index 6f1be57..69a8d94 100644 --- a/mm/filemap.c +++ b/mm/filemap.c -@@ -2304,7 +2304,7 @@ int filemap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) +@@ -2408,7 +2408,7 @@ int filemap_page_mkwrite(struct vm_fault *vmf) int ret = VM_FAULT_LOCKED; sb_start_pagefault(inode->i_sb); -- file_update_time(vma->vm_file); -+ vma_file_update_time(vma); +- file_update_time(vmf->vma->vm_file); ++ vma_file_update_time(vmf->vma); lock_page(page); if (page->mapping != inode->i_mapping) { unlock_page(page); -diff --git a/mm/memory.c b/mm/memory.c -index e18c57b..7be4a39 100644 ---- a/mm/memory.c -+++ b/mm/memory.c -@@ -2117,7 +2117,7 @@ static inline int wp_page_reuse(struct fault_env *fe, pte_t orig_pte, - } - - if (!page_mkwrite) -- file_update_time(vma->vm_file); -+ vma_file_update_time(vma); - } - - return VM_FAULT_WRITE; diff --git a/mm/mmap.c b/mm/mmap.c -index 1af87c1..95b0ff4 100644 +index a5e3dcd..a5d908c 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -170,7 +170,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma) @@ -455,7 +451,7 @@ index 1af87c1..95b0ff4 100644 mpol_put(vma_policy(vma)); kmem_cache_free(vm_area_cachep, vma); return next; -@@ -879,7 +879,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start, +@@ -895,7 +895,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); @@ -464,7 +460,7 @@ index 1af87c1..95b0ff4 100644 } if (next->anon_vma) anon_vma_merge(vma, next); -@@ -1727,8 +1727,8 @@ unsigned long mmap_region(struct file *file, unsigned long addr, +@@ -1745,8 +1745,8 @@ unsigned long mmap_region(struct file *file, unsigned long addr, return addr; unmap_and_free_vma: @@ -474,7 +470,7 @@ index 1af87c1..95b0ff4 100644 /* Undo any partial mapping done by a device driver. */ unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end); -@@ -2533,7 +2533,7 @@ static int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -2571,7 +2571,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, goto out_free_mpol; if (new->vm_file) @@ -483,7 +479,7 @@ index 1af87c1..95b0ff4 100644 if (new->vm_ops && new->vm_ops->open) new->vm_ops->open(new); -@@ -2552,7 +2552,7 @@ static int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma, +@@ -2590,7 +2590,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) @@ -492,7 +488,7 @@ index 1af87c1..95b0ff4 100644 unlink_anon_vmas(new); out_free_mpol: mpol_put(vma_policy(new)); -@@ -2703,7 +2703,7 @@ int vm_munmap(unsigned long start, size_t len) +@@ -2744,7 +2744,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, struct vm_area_struct *vma; unsigned long populate = 0; unsigned long ret = -EINVAL; @@ -501,7 +497,7 @@ index 1af87c1..95b0ff4 100644 pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/vm/remap_file_pages.txt.\n", current->comm, current->pid); -@@ -2778,10 +2778,27 @@ int vm_munmap(unsigned long start, size_t len) +@@ -2819,10 +2819,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, } } @@ -510,7 +506,7 @@ index 1af87c1..95b0ff4 100644 + file = vma->vm_file; + prfile = vma->vm_prfile; ret = do_mmap_pgoff(vma->vm_file, start, size, - prot, flags, pgoff, &populate); + prot, flags, pgoff, &populate, NULL); + if (!IS_ERR_VALUE(ret) && file && prfile) { + struct vm_area_struct *new_vma; + @@ -530,7 +526,7 @@ index 1af87c1..95b0ff4 100644 out: up_write(&mm->mmap_sem); if (populate) -@@ -3056,7 +3073,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, +@@ -3113,7 +3130,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) @@ -540,10 +536,10 @@ index 1af87c1..95b0ff4 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 8b8faaf..5d26ed94 100644 +index fc184f5..637ea81 100644 --- a/mm/nommu.c +++ b/mm/nommu.c -@@ -636,7 +636,7 @@ static void __put_nommu_region(struct vm_region *region) +@@ -641,7 +641,7 @@ static void __put_nommu_region(struct vm_region *region) up_write(&nommu_region_sem); if (region->vm_file) @@ -552,7 +548,7 @@ index 8b8faaf..5d26ed94 100644 /* IO memory and memory shared directly out of the pagecache * from ramfs/tmpfs mustn't be released here */ -@@ -794,7 +794,7 @@ static void delete_vma(struct mm_struct *mm, struct vm_area_struct *vma) +@@ -799,7 +799,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) @@ -561,7 +557,7 @@ index 8b8faaf..5d26ed94 100644 put_nommu_region(vma->vm_region); kmem_cache_free(vm_area_cachep, vma); } -@@ -1320,7 +1320,7 @@ unsigned long do_mmap(struct file *file, +@@ -1326,7 +1326,7 @@ unsigned long do_mmap(struct file *file, goto error_just_free; } } @@ -570,7 +566,7 @@ index 8b8faaf..5d26ed94 100644 kmem_cache_free(vm_region_jar, region); region = pregion; result = start; -@@ -1395,10 +1395,10 @@ unsigned long do_mmap(struct file *file, +@@ -1401,10 +1401,10 @@ unsigned long do_mmap(struct file *file, up_write(&nommu_region_sem); error: if (region->vm_file) @@ -585,18 +581,18 @@ index 8b8faaf..5d26ed94 100644 diff --git a/mm/prfile.c b/mm/prfile.c new file mode 100644 -index 0000000..b323b8a +index 0000000..1ef053b --- /dev/null +++ b/mm/prfile.c -@@ -0,0 +1,86 @@ +@@ -0,0 +1,85 @@ +/* -+ * Mainly for aufs which mmap(2) diffrent file and wants to print different path -+ * in /proc/PID/maps. ++ * Mainly for aufs which mmap(2) different file and wants to print different ++ * path in /proc/PID/maps. + * Call these functions via macros defined in linux/mm.h. + * + * See Documentation/filesystems/aufs/design/06mmap.txt + * -+ * Copyright (c) 2014 Junjro R. Okajima ++ * Copyright (c) 2014-2017 Junjro R. Okajima + * Copyright (c) 2014 Ian Campbell + */ + @@ -610,8 +606,7 @@ index 0000000..b323b8a +{ +#ifdef PRFILE_TRACE + if (pr) -+ pr_info("%s:%d: %s, %s\n", func, line, func2, -+ f ? (char *)f->f_path.dentry->d_name.name : "(null)"); ++ pr_info("%s:%d: %s, %pD2\n", func, line, func2, f); +#endif +} + @@ -675,10 +670,10 @@ index 0000000..b323b8a + fput(pr); +} +#endif /* !CONFIG_MMU */ -aufs4.9 standalone patch +aufs4.x-rcN standalone patch diff --git a/fs/dcache.c b/fs/dcache.c -index df0268c..755fea1 100644 +index 3458af5..5fd25bb 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1272,6 +1272,7 @@ void d_walk(struct dentry *parent, void *data, @@ -687,9 +682,9 @@ index df0268c..755fea1 100644 } +EXPORT_SYMBOL_GPL(d_walk); - /* - * Search for at least 1 mount point in the dentry's subdirs. -@@ -2855,6 +2856,7 @@ void d_exchange(struct dentry *dentry1, struct dentry *dentry2) + struct check_mount { + struct vfsmount *mnt; +@@ -2862,6 +2863,7 @@ void d_exchange(struct dentry *dentry1, struct dentry *dentry2) write_sequnlock(&rename_lock); } @@ -698,10 +693,10 @@ index df0268c..755fea1 100644 /** * d_ancestor - search for an ancestor diff --git a/fs/exec.c b/fs/exec.c -index 4e497b9..e27d323 100644 +index 9041990..31f14c6 100644 --- a/fs/exec.c +++ b/fs/exec.c -@@ -104,6 +104,7 @@ bool path_noexec(const struct path *path) +@@ -109,6 +109,7 @@ bool path_noexec(const struct path *path) return (path->mnt->mnt_flags & MNT_NOEXEC) || (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC); } @@ -710,10 +705,10 @@ index 4e497b9..e27d323 100644 #ifdef CONFIG_USELIB /* diff --git a/fs/fcntl.c b/fs/fcntl.c -index 6f42279..04fd33c 100644 +index d39404c..ac1dc66 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c -@@ -82,6 +82,7 @@ int setfl(int fd, struct file * filp, unsigned long arg) +@@ -84,6 +84,7 @@ int setfl(int fd, struct file * filp, unsigned long arg) out: return error; } @@ -722,10 +717,10 @@ index 6f42279..04fd33c 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 ad17e05..ae9f267 100644 +index 954d510..4fb5b10 100644 --- a/fs/file_table.c +++ b/fs/file_table.c -@@ -147,6 +147,7 @@ struct file *get_empty_filp(void) +@@ -148,6 +148,7 @@ struct file *get_empty_filp(void) } return ERR_PTR(-ENFILE); } @@ -733,7 +728,7 @@ index ad17e05..ae9f267 100644 /** * alloc_file - allocate and initialize a 'struct file' -@@ -258,6 +259,7 @@ void flush_delayed_fput(void) +@@ -259,6 +260,7 @@ void flush_delayed_fput(void) { delayed_fput(NULL); } @@ -741,7 +736,7 @@ index ad17e05..ae9f267 100644 static DECLARE_DELAYED_WORK(delayed_fput_work, delayed_fput); -@@ -300,6 +302,7 @@ void __fput_sync(struct file *file) +@@ -301,6 +303,7 @@ void __fput_sync(struct file *file) } EXPORT_SYMBOL(fput); @@ -749,7 +744,7 @@ index ad17e05..ae9f267 100644 void put_filp(struct file *file) { -@@ -308,6 +311,7 @@ void put_filp(struct file *file) +@@ -309,6 +312,7 @@ void put_filp(struct file *file) file_free(file); } } @@ -758,10 +753,10 @@ index ad17e05..ae9f267 100644 void __init files_init(void) { diff --git a/fs/inode.c b/fs/inode.c -index 9a9ba3a..a3a18d8 100644 +index 69cbe9c..764566d 100644 --- a/fs/inode.c +++ b/fs/inode.c -@@ -1651,6 +1651,7 @@ int update_time(struct inode *inode, struct timespec *time, int flags) +@@ -1649,6 +1649,7 @@ int update_time(struct inode *inode, struct timespec *time, int flags) return update_time(inode, time, flags); } @@ -770,10 +765,10 @@ index 9a9ba3a..a3a18d8 100644 /** * touch_atime - update the access time diff --git a/fs/namespace.c b/fs/namespace.c -index e6c234b..8d13f7b 100644 +index 5a44384..cc6f6fb 100644 --- a/fs/namespace.c +++ b/fs/namespace.c -@@ -466,6 +466,7 @@ void __mnt_drop_write(struct vfsmount *mnt) +@@ -462,6 +462,7 @@ void __mnt_drop_write(struct vfsmount *mnt) mnt_dec_writers(real_mount(mnt)); preempt_enable(); } @@ -781,7 +776,7 @@ index e6c234b..8d13f7b 100644 /** * mnt_drop_write - give up write access to a mount -@@ -1823,6 +1824,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg, +@@ -1881,6 +1882,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg, } return 0; } @@ -790,7 +785,7 @@ index e6c234b..8d13f7b 100644 static void cleanup_group_ids(struct mount *mnt, struct mount *end) { diff --git a/fs/notify/group.c b/fs/notify/group.c -index fbe3cbe..bdfc61e 100644 +index 3235753..14a2d48 100644 --- a/fs/notify/group.c +++ b/fs/notify/group.c @@ -22,6 +22,7 @@ @@ -801,7 +796,7 @@ index fbe3cbe..bdfc61e 100644 #include #include "fsnotify.h" -@@ -100,6 +101,7 @@ void fsnotify_get_group(struct fsnotify_group *group) +@@ -109,6 +110,7 @@ void fsnotify_get_group(struct fsnotify_group *group) { atomic_inc(&group->refcnt); } @@ -809,7 +804,7 @@ index fbe3cbe..bdfc61e 100644 /* * Drop a reference to a group. Free it if it's through. -@@ -109,6 +111,7 @@ void fsnotify_put_group(struct fsnotify_group *group) +@@ -118,6 +120,7 @@ void fsnotify_put_group(struct fsnotify_group *group) if (atomic_dec_and_test(&group->refcnt)) fsnotify_final_destroy_group(group); } @@ -817,7 +812,7 @@ index fbe3cbe..bdfc61e 100644 /* * Create a new fsnotify_group and hold a reference for the group returned. -@@ -137,6 +140,7 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops) +@@ -147,6 +150,7 @@ struct fsnotify_group *fsnotify_alloc_group(const struct fsnotify_ops *ops) return group; } @@ -826,43 +821,43 @@ index fbe3cbe..bdfc61e 100644 int fsnotify_fasync(int fd, struct file *file, int on) { diff --git a/fs/notify/mark.c b/fs/notify/mark.c -index d3fea0b..5fc06ad 100644 +index 9991f88..117042c 100644 --- a/fs/notify/mark.c +++ b/fs/notify/mark.c -@@ -113,6 +113,7 @@ void fsnotify_put_mark(struct fsnotify_mark *mark) - mark->free_mark(mark); - } +@@ -118,6 +118,7 @@ static bool fsnotify_get_mark_safe(struct fsnotify_mark *mark) + { + return atomic_inc_not_zero(&mark->refcnt); } +EXPORT_SYMBOL_GPL(fsnotify_put_mark); - /* Calculate mask of events for a list of marks */ - u32 fsnotify_recalc_mask(struct hlist_head *head) -@@ -230,6 +231,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark, + static void __fsnotify_recalc_mask(struct fsnotify_mark_connector *conn) + { +@@ -395,6 +396,7 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark, mutex_unlock(&group->mark_mutex); fsnotify_free_mark(mark); } +EXPORT_SYMBOL_GPL(fsnotify_destroy_mark); - void fsnotify_destroy_marks(struct hlist_head *head, spinlock_t *lock) - { -@@ -415,6 +417,7 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark, - + /* + * Sorting function for lists of fsnotify marks. +@@ -607,6 +609,7 @@ int fsnotify_add_mark_locked(struct fsnotify_mark *mark, struct inode *inode, + fsnotify_put_mark(mark); return ret; } +EXPORT_SYMBOL_GPL(fsnotify_add_mark); - int fsnotify_add_mark(struct fsnotify_mark *mark, struct fsnotify_group *group, - struct inode *inode, struct vfsmount *mnt, int allow_dups) -@@ -533,6 +536,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark, - atomic_set(&mark->refcnt, 1); - mark->free_mark = free_mark; + int fsnotify_add_mark(struct fsnotify_mark *mark, struct inode *inode, + struct vfsmount *mnt, int allow_dups) +@@ -742,6 +745,7 @@ void fsnotify_init_mark(struct fsnotify_mark *mark, + fsnotify_get_group(group); + mark->group = group; } +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 d3ed817..20d2494 100644 +index cd0c5be..491442a 100644 --- a/fs/open.c +++ b/fs/open.c @@ -64,6 +64,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, @@ -873,7 +868,7 @@ index d3ed817..20d2494 100644 long vfs_truncate(const struct path *path, loff_t length) { -@@ -695,6 +696,7 @@ int open_check_o_direct(struct file *f) +@@ -691,6 +692,7 @@ int open_check_o_direct(struct file *f) } return 0; } @@ -882,10 +877,10 @@ index d3ed817..20d2494 100644 static int do_dentry_open(struct file *f, struct inode *inode, diff --git a/fs/read_write.c b/fs/read_write.c -index 4052813..7dfd732 100644 +index 05033f7..ce062e8 100644 --- a/fs/read_write.c +++ b/fs/read_write.c -@@ -525,6 +525,7 @@ vfs_readf_t vfs_readf(struct file *file) +@@ -523,6 +523,7 @@ vfs_readf_t vfs_readf(struct file *file) return new_sync_read; return ERR_PTR(-ENOSYS); } @@ -893,7 +888,7 @@ index 4052813..7dfd732 100644 vfs_writef_t vfs_writef(struct file *file) { -@@ -536,6 +537,7 @@ vfs_writef_t vfs_writef(struct file *file) +@@ -534,6 +535,7 @@ vfs_writef_t vfs_writef(struct file *file) return new_sync_write; return ERR_PTR(-ENOSYS); } @@ -902,10 +897,10 @@ index 4052813..7dfd732 100644 ssize_t __kernel_write(struct file *file, const char *buf, size_t count, loff_t *pos) { diff --git a/fs/splice.c b/fs/splice.c -index 28160a7..98c1902 100644 +index 4a0bc62..21d7893 100644 --- a/fs/splice.c +++ b/fs/splice.c -@@ -868,6 +868,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out, +@@ -866,6 +866,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out, return splice_write(pipe, out, ppos, len, flags); } @@ -913,7 +908,7 @@ index 28160a7..98c1902 100644 /* * Attempt to initiate a splice from a file to a pipe. -@@ -897,6 +898,7 @@ long do_splice_to(struct file *in, loff_t *ppos, +@@ -895,6 +896,7 @@ long do_splice_to(struct file *in, loff_t *ppos, return splice_read(in, ppos, pipe, len, flags); } @@ -921,11 +916,23 @@ index 28160a7..98c1902 100644 /** * splice_direct_to_actor - splices data directly between two non-pipes +diff --git a/fs/sync.c b/fs/sync.c +index abf6a5d..c86fe9c 100644 +--- a/fs/sync.c ++++ b/fs/sync.c +@@ -38,6 +38,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 2d13b4e..41c2bcd 100644 +index 464c94b..0234d49 100644 --- a/fs/xattr.c +++ b/fs/xattr.c -@@ -296,6 +296,7 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name, +@@ -296,6 +296,7 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value, *xattr_value = value; return error; } @@ -943,10 +950,10 @@ index d513051..e056d54 100644 } +EXPORT_SYMBOL_GPL(task_work_run); diff --git a/security/commoncap.c b/security/commoncap.c -index 8df676f..6b5cc07 100644 +index 7abebd7..c079ce4 100644 --- a/security/commoncap.c +++ b/security/commoncap.c -@@ -1061,12 +1061,14 @@ int cap_mmap_addr(unsigned long addr) +@@ -1062,12 +1062,14 @@ int cap_mmap_addr(unsigned long addr) } return ret; } @@ -982,10 +989,10 @@ index 03c1652..f88c84b 100644 int devcgroup_inode_mknod(int mode, dev_t dev) { diff --git a/security/security.c b/security/security.c -index f825304..8dd441d 100644 +index b9fea39..afa97dd 100644 --- a/security/security.c +++ b/security/security.c -@@ -443,6 +443,7 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry) +@@ -492,6 +492,7 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry) return 0; return call_int_hook(path_rmdir, 0, dir, dentry); } @@ -993,7 +1000,7 @@ index f825304..8dd441d 100644 int security_path_unlink(const struct path *dir, struct dentry *dentry) { -@@ -459,6 +460,7 @@ int security_path_symlink(const struct path *dir, struct dentry *dentry, +@@ -508,6 +509,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); } @@ -1001,7 +1008,7 @@ index f825304..8dd441d 100644 int security_path_link(struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry) -@@ -467,6 +469,7 @@ int security_path_link(struct dentry *old_dentry, const struct path *new_dir, +@@ -516,6 +518,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); } @@ -1009,7 +1016,7 @@ index f825304..8dd441d 100644 int security_path_rename(const struct path *old_dir, struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry, -@@ -494,6 +497,7 @@ int security_path_truncate(const struct path *path) +@@ -543,6 +546,7 @@ int security_path_truncate(const struct path *path) return 0; return call_int_hook(path_truncate, 0, path); } @@ -1017,7 +1024,7 @@ index f825304..8dd441d 100644 int security_path_chmod(const struct path *path, umode_t mode) { -@@ -501,6 +505,7 @@ int security_path_chmod(const struct path *path, umode_t mode) +@@ -550,6 +554,7 @@ int security_path_chmod(const struct path *path, umode_t mode) return 0; return call_int_hook(path_chmod, 0, path, mode); } @@ -1025,7 +1032,7 @@ index f825304..8dd441d 100644 int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) { -@@ -508,6 +513,7 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) +@@ -557,6 +562,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); } @@ -1033,7 +1040,7 @@ index f825304..8dd441d 100644 int security_path_chroot(const struct path *path) { -@@ -593,6 +599,7 @@ int security_inode_readlink(struct dentry *dentry) +@@ -642,6 +648,7 @@ int security_inode_readlink(struct dentry *dentry) return 0; return call_int_hook(inode_readlink, 0, dentry); } @@ -1041,7 +1048,7 @@ index f825304..8dd441d 100644 int security_inode_follow_link(struct dentry *dentry, struct inode *inode, bool rcu) -@@ -608,6 +615,7 @@ int security_inode_permission(struct inode *inode, int mask) +@@ -657,6 +664,7 @@ int security_inode_permission(struct inode *inode, int mask) return 0; return call_int_hook(inode_permission, 0, inode, mask); } @@ -1049,7 +1056,7 @@ index f825304..8dd441d 100644 int security_inode_setattr(struct dentry *dentry, struct iattr *attr) { -@@ -779,6 +787,7 @@ int security_file_permission(struct file *file, int mask) +@@ -828,6 +836,7 @@ int security_file_permission(struct file *file, int mask) return fsnotify_perm(file, mask); } @@ -1057,7 +1064,7 @@ index f825304..8dd441d 100644 int security_file_alloc(struct file *file) { -@@ -838,6 +847,7 @@ int security_mmap_file(struct file *file, unsigned long prot, +@@ -887,6 +896,7 @@ int security_mmap_file(struct file *file, unsigned long prot, return ret; return ima_file_mmap(file, prot); } @@ -1067,7 +1074,7 @@ index f825304..8dd441d 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 2016-10-09 16:55:36.476034536 +0200 ++++ linux/Documentation/ABI/testing/debugfs-aufs 2017-07-29 12:14:25.893041746 +0200 @@ -0,0 +1,50 @@ +What: /debug/aufs/si_/ +Date: March 2009 @@ -1121,7 +1128,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 2016-10-09 16:55:36.476034536 +0200 ++++ linux/Documentation/ABI/testing/sysfs-aufs 2017-07-29 12:14:25.893041746 +0200 @@ -0,0 +1,31 @@ +What: /sys/fs/aufs/si_/ +Date: March 2009 @@ -1156,10 +1163,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 2016-10-09 16:55:36.479367956 +0200 -@@ -0,0 +1,170 @@ ++++ linux/Documentation/filesystems/aufs/design/01intro.txt 2017-07-29 12:14:25.893041746 +0200 +@@ -0,0 +1,171 @@ + -+# Copyright (C) 2005-2016 Junjiro R. Okajima ++# Copyright (C) 2005-2017 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 @@ -1183,6 +1190,7 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt lin +3. abbrev. for "auf das" in German which means "on the" in English. + Ex. "Butter aufs Brot"(G) means "butter onto bread"(E). + But "Filesystem aufs Filesystem" is hard to understand. ++4. abbrev. for "African Urban Fashion Show". + +AUFS is a filesystem with features: +- multi layered stackable unification filesystem, the member directory @@ -1330,10 +1338,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 2016-10-09 16:55:36.479367956 +0200 ++++ linux/Documentation/filesystems/aufs/design/02struct.txt 2017-07-29 12:14:25.893041746 +0200 @@ -0,0 +1,258 @@ + -+# Copyright (C) 2005-2016 Junjiro R. Okajima ++# Copyright (C) 2005-2017 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 @@ -1592,10 +1600,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 2016-10-09 16:55:36.479367956 +0200 ++++ linux/Documentation/filesystems/aufs/design/03atomic_open.txt 2017-07-29 12:14:25.893041746 +0200 @@ -0,0 +1,85 @@ + -+# Copyright (C) 2015-2016 Junjiro R. Okajima ++# Copyright (C) 2015-2017 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 @@ -1681,10 +1689,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 2016-10-09 16:55:36.479367956 +0200 ++++ linux/Documentation/filesystems/aufs/design/03lookup.txt 2017-07-29 12:14:25.893041746 +0200 @@ -0,0 +1,113 @@ + -+# Copyright (C) 2005-2016 Junjiro R. Okajima ++# Copyright (C) 2005-2017 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 @@ -1798,10 +1806,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 2016-10-09 16:55:36.482701377 +0200 ++++ linux/Documentation/filesystems/aufs/design/04branch.txt 2017-07-29 12:14:25.893041746 +0200 @@ -0,0 +1,74 @@ + -+# Copyright (C) 2005-2016 Junjiro R. Okajima ++# Copyright (C) 2005-2017 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 @@ -1876,10 +1884,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 2016-10-09 16:55:36.482701377 +0200 ++++ linux/Documentation/filesystems/aufs/design/05wbr_policy.txt 2017-07-29 12:14:25.893041746 +0200 @@ -0,0 +1,64 @@ + -+# Copyright (C) 2005-2016 Junjiro R. Okajima ++# Copyright (C) 2005-2017 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 @@ -1944,10 +1952,10 @@ diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.tx + copyup policy. 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 2016-10-09 16:55:36.482701377 +0200 ++++ linux/Documentation/filesystems/aufs/design/06fhsm.txt 2017-07-29 12:14:25.896375188 +0200 @@ -0,0 +1,120 @@ + -+# Copyright (C) 2011-2016 Junjiro R. Okajima ++# Copyright (C) 2011-2017 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 @@ -2068,10 +2076,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 2016-10-09 16:55:36.482701377 +0200 ++++ linux/Documentation/filesystems/aufs/design/06mmap.txt 2017-07-29 12:14:25.896375188 +0200 @@ -0,0 +1,72 @@ + -+# Copyright (C) 2005-2016 Junjiro R. Okajima ++# Copyright (C) 2005-2017 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 @@ -2144,10 +2152,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 2016-10-09 16:55:36.482701377 +0200 ++++ linux/Documentation/filesystems/aufs/design/06xattr.txt 2017-07-29 12:14:25.896375188 +0200 @@ -0,0 +1,96 @@ + -+# Copyright (C) 2014-2016 Junjiro R. Okajima ++# Copyright (C) 2014-2017 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 @@ -2244,10 +2252,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 2016-10-09 16:55:36.482701377 +0200 ++++ linux/Documentation/filesystems/aufs/design/07export.txt 2017-07-29 12:14:25.896375188 +0200 @@ -0,0 +1,58 @@ + -+# Copyright (C) 2005-2016 Junjiro R. Okajima ++# Copyright (C) 2005-2017 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 @@ -2306,10 +2314,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 2016-10-09 16:55:36.482701377 +0200 ++++ linux/Documentation/filesystems/aufs/design/08shwh.txt 2017-07-29 12:14:25.896375188 +0200 @@ -0,0 +1,52 @@ + -+# Copyright (C) 2005-2016 Junjiro R. Okajima ++# Copyright (C) 2005-2017 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 @@ -2362,10 +2370,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 2016-10-09 16:55:36.482701377 +0200 ++++ linux/Documentation/filesystems/aufs/design/10dynop.txt 2017-07-29 12:14:25.896375188 +0200 @@ -0,0 +1,47 @@ + -+# Copyright (C) 2010-2016 Junjiro R. Okajima ++# Copyright (C) 2010-2017 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 @@ -2413,7 +2421,7 @@ 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 2016-12-17 12:28:17.595211562 +0100 ++++ linux/Documentation/filesystems/aufs/README 2017-07-29 12:14:25.893041746 +0200 @@ -0,0 +1,393 @@ + +Aufs4 -- advanced multi layered unification filesystem version 4.x @@ -2810,10 +2818,10 @@ 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 2016-10-09 16:55:36.486034798 +0200 ++++ linux/fs/aufs/aufs.h 2017-07-29 12:14:25.896375188 +0200 @@ -0,0 +1,59 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -2873,10 +2881,10 @@ 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 2016-10-09 16:55:38.886097714 +0200 -@@ -0,0 +1,1412 @@ ++++ linux/fs/aufs/branch.c 2017-07-29 12:14:25.896375188 +0200 +@@ -0,0 +1,1422 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -2913,7 +2921,9 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c + + if (br->br_xino.xi_file) + fput(br->br_xino.xi_file); -+ mutex_destroy(&br->br_xino.xi_nondir_mtx); ++ for (i = br->br_xino.xi_nondir.total - 1; i >= 0; i--) ++ AuDebugOn(br->br_xino.xi_nondir.array[i]); ++ kfree(br->br_xino.xi_nondir.array); + + AuDebugOn(au_br_count(br)); + au_br_count_fin(br); @@ -2928,7 +2938,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c + + if (br->br_fhsm) { + au_br_fhsm_fin(br->br_fhsm); -+ au_delayed_kfree(br->br_fhsm); ++ kfree(br->br_fhsm); + } + + key = br->br_dykey; @@ -2942,9 +2952,8 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c + lockdep_off(); + path_put(&br->br_path); + lockdep_on(); -+ if (wbr) -+ au_delayed_kfree(wbr); -+ au_delayed_kfree(br); ++ kfree(wbr); ++ kfree(br); +} + +/* @@ -3008,14 +3017,19 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c + int err; + + err = -ENOMEM; -+ root = sb->s_root; + add_branch = kzalloc(sizeof(*add_branch), GFP_NOFS); + if (unlikely(!add_branch)) + goto out; ++ add_branch->br_xino.xi_nondir.total = 8; /* initial size */ ++ add_branch->br_xino.xi_nondir.array ++ = kzalloc(sizeof(ino_t) * add_branch->br_xino.xi_nondir.total, ++ GFP_NOFS); ++ if (unlikely(!add_branch->br_xino.xi_nondir.array)) ++ goto out_br; + + err = au_hnotify_init_br(add_branch, perm); + if (unlikely(err)) -+ goto out_br; ++ goto out_xinondir; + + if (au_br_writable(perm)) { + /* may be freed separately at changing the branch permission */ @@ -3031,23 +3045,26 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c + goto out_wbr; + } + ++ root = sb->s_root; + err = au_sbr_realloc(au_sbi(sb), new_nbranch, /*may_shrink*/0); + if (!err) + err = au_di_realloc(au_di(root), new_nbranch, /*may_shrink*/0); + if (!err) { + inode = d_inode(root); -+ err = au_hinode_realloc(au_ii(inode), new_nbranch, /*may_shrink*/0); ++ err = au_hinode_realloc(au_ii(inode), new_nbranch, ++ /*may_shrink*/0); + } + if (!err) + return add_branch; /* success */ + +out_wbr: -+ if (add_branch->br_wbr) -+ au_delayed_kfree(add_branch->br_wbr); ++ kfree(add_branch->br_wbr); +out_hnotify: + au_hnotify_fin_br(add_branch); ++out_xinondir: ++ kfree(add_branch->br_xino.xi_nondir.array); +out_br: -+ au_delayed_kfree(add_branch); ++ kfree(add_branch); +out: + return ERR_PTR(err); +} @@ -3213,7 +3230,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c + br->br_perm = old_perm; + + if (!err && wbr && !au_br_writable(new_perm)) { -+ au_delayed_kfree(wbr); ++ kfree(wbr); + br->br_wbr = NULL; + } + @@ -3259,7 +3276,8 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c + struct inode *h_inode; + + err = 0; -+ mutex_init(&br->br_xino.xi_nondir_mtx); ++ spin_lock_init(&br->br_xino.xi_nondir.spin); ++ init_waitqueue_head(&br->br_xino.xi_nondir.wqh); + br->br_perm = add->perm; + br->br_path = add->path; /* set first, path_get() later */ + spin_lock_init(&br->br_dykey_lock); @@ -4239,7 +4257,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c + if (br->br_wbr) { + err = au_wbr_init(br, sb, mod->perm); + if (unlikely(err)) { -+ au_delayed_kfree(br->br_wbr); ++ kfree(br->br_wbr); + br->br_wbr = NULL; + } + } @@ -4251,7 +4269,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c + if (!au_br_fhsm(mod->perm)) { + /* fhsm --> non-fhsm */ + au_br_fhsm_fin(br->br_fhsm); -+ au_delayed_kfree(br->br_fhsm); ++ kfree(br->br_fhsm); + br->br_fhsm = NULL; + } + } else if (au_br_fhsm(mod->perm)) @@ -4264,7 +4282,7 @@ diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c + +out_bf: + if (bf) -+ au_delayed_kfree(bf); ++ kfree(bf); +out: + AuTraceErr(err); + return err; @@ -4289,10 +4307,10 @@ 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 2016-10-09 16:55:36.486034798 +0200 -@@ -0,0 +1,309 @@ ++++ linux/fs/aufs/branch.h 2017-07-29 12:14:25.896375188 +0200 +@@ -0,0 +1,321 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -4327,7 +4345,14 @@ diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h +/* a xino file */ +struct au_xino_file { + struct file *xi_file; -+ struct mutex xi_nondir_mtx; ++ struct { ++ spinlock_t spin; ++ ino_t *array; ++ int total; ++ /* reserved for future use */ ++ /* unsigned long *bitmap; */ ++ wait_queue_head_t wqh; ++ } xi_nondir; + + /* todo: make xino files an array to support huge inode number */ + @@ -4526,6 +4551,11 @@ diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h +struct file *au_xino_def(struct super_block *sb); +int au_xino_path(struct seq_file *seq, struct file *file); + ++void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex, ++ ino_t h_ino, int idx); ++int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, ++ int *idx); ++ +/* ---------------------------------------------------------------------- */ + +/* Superblock to branch */ @@ -4602,7 +4632,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 2016-10-09 16:55:36.486034798 +0200 ++++ linux/fs/aufs/conf.mk 2017-07-29 12:14:25.899708630 +0200 @@ -0,0 +1,38 @@ + +AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS} @@ -4644,10 +4674,10 @@ 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 2016-12-17 12:28:17.595211562 +0100 -@@ -0,0 +1,1394 @@ ++++ linux/fs/aufs/cpup.c 2017-07-29 12:14:25.899708630 +0200 +@@ -0,0 +1,1442 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -5005,11 +5035,64 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c + dst->f_pos = 0; + err = au_do_copy_file(dst, src, len, buf, blksize); + if (do_kfree) -+ au_delayed_kfree(buf); ++ kfree(buf); + else -+ au_delayed_free_page((unsigned long)buf); ++ free_page((unsigned long)buf); ++ ++out: ++ return err; ++} ++ ++static int au_do_copy(struct file *dst, struct file *src, loff_t len) ++{ ++ int err; ++ struct super_block *h_src_sb; ++ struct inode *h_src_inode; ++ ++ h_src_inode = file_inode(src); ++ h_src_sb = h_src_inode->i_sb; ++ ++ /* XFS acquires inode_lock */ ++ if (!au_test_xfs(h_src_sb)) ++ err = au_copy_file(dst, src, len); ++ else { ++ inode_unlock(h_src_inode); ++ err = au_copy_file(dst, src, len); ++ inode_lock(h_src_inode); ++ } ++ ++ return err; ++} ++ ++static int au_clone_or_copy(struct file *dst, struct file *src, loff_t len) ++{ ++ int err; ++ struct super_block *h_src_sb; ++ struct inode *h_src_inode; ++ ++ h_src_inode = file_inode(src); ++ h_src_sb = h_src_inode->i_sb; ++ if (h_src_sb != file_inode(dst)->i_sb ++ || !dst->f_op->clone_file_range) { ++ err = au_do_copy(dst, src, len); ++ goto out; ++ } ++ ++ if (!au_test_nfs(h_src_sb)) { ++ inode_unlock(h_src_inode); ++ err = vfsub_clone_file_range(src, dst, len); ++ inode_lock(h_src_inode); ++ } else ++ err = vfsub_clone_file_range(src, dst, len); ++ /* older XFS has a condition in cloning */ ++ if (unlikely(err != -EOPNOTSUPP)) ++ goto out; ++ ++ /* the backend fs on NFS may not support cloning */ ++ err = au_do_copy(dst, src, len); + +out: ++ AuTraceErr(err); + return err; +} + @@ -5041,7 +5124,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c + .label = &&out_src + } + }; -+ struct super_block *sb; ++ struct super_block *sb, *h_src_sb; + struct inode *h_src_inode; + struct task_struct *tsk = current; + @@ -5059,9 +5142,10 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c + + /* try stopping to update while we copyup */ + h_src_inode = d_inode(file[SRC].dentry); -+ if (!au_test_nfs(h_src_inode->i_sb)) ++ h_src_sb = h_src_inode->i_sb; ++ if (!au_test_nfs(h_src_sb)) + IMustLock(h_src_inode); -+ err = au_copy_file(file[DST].file, file[SRC].file, cpg->len); ++ err = au_clone_or_copy(file[DST].file, file[SRC].file, cpg->len); + + /* i wonder if we had O_NO_DELAY_FPUT flag */ + if (tsk->flags & PF_KTHREAD) @@ -5109,10 +5193,10 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c + h_path.mnt = au_sbr_mnt(cpg->dentry->d_sb, cpg->bsrc); + h_src_attr->iflags = h_src_inode->i_flags; + if (!au_test_nfs(h_src_inode->i_sb)) -+ err = vfs_getattr(&h_path, &h_src_attr->st); ++ err = vfsub_getattr(&h_path, &h_src_attr->st); + else { + inode_unlock(h_src_inode); -+ err = vfs_getattr(&h_path, &h_src_attr->st); ++ err = vfsub_getattr(&h_path, &h_src_attr->st); + inode_lock_nested(h_src_inode, AuLsc_I_CHILD); + } + if (unlikely(err)) { @@ -5152,12 +5236,6 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c + char *k; + char __user *u; + } sym; -+ struct inode *h_inode = d_inode(h_src); -+ const struct inode_operations *h_iop = h_inode->i_op; -+ -+ err = -ENOSYS; -+ if (unlikely(!h_iop->readlink)) -+ goto out; + + err = -ENOMEM; + sym.k = (void *)__get_free_page(GFP_NOFS); @@ -5167,7 +5245,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c + /* unnecessary to support mmap_sem since symlink is not mmap-able */ + old_fs = get_fs(); + set_fs(KERNEL_DS); -+ symlen = h_iop->readlink(h_src, sym.u, PATH_MAX); ++ symlen = vfs_readlink(h_src, sym.u, PATH_MAX); + err = symlen; + set_fs(old_fs); + @@ -5175,7 +5253,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c + sym.k[symlen] = 0; + err = vfsub_symlink(h_dir, h_path, sym.k); + } -+ au_delayed_free_page((unsigned long)sym.k); ++ free_page((unsigned long)sym.k); + +out: + return err; @@ -5549,7 +5627,7 @@ diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c + } +out_parent: + dput(dst_parent); -+ au_delayed_kfree(a); ++ kfree(a); +out: + return err; +} @@ -6042,10 +6120,10 @@ 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 2016-10-09 16:55:36.486034798 +0200 ++++ linux/fs/aufs/cpup.h 2017-07-29 12:14:25.899708630 +0200 @@ -0,0 +1,94 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -6140,10 +6218,10 @@ 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 2016-10-09 16:55:38.886097714 +0200 ++++ linux/fs/aufs/dbgaufs.c 2017-07-29 12:14:25.899708630 +0200 @@ -0,0 +1,438 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -6185,7 +6263,7 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c +static int dbgaufs_xi_release(struct inode *inode __maybe_unused, + struct file *file) +{ -+ au_delayed_kfree(file->private_data); ++ kfree(file->private_data); + return 0; +} + @@ -6206,15 +6284,15 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c + if (!xf) + goto out; + -+ err = vfs_getattr(&xf->f_path, &st); ++ err = vfsub_getattr(&xf->f_path, &st); + if (!err) { + if (do_fcnt) + p->n = snprintf -+ (p->a, sizeof(p->a), "%ld, %llux%lu %lld\n", ++ (p->a, sizeof(p->a), "%ld, %llux%u %lld\n", + (long)file_count(xf), st.blocks, st.blksize, + (long long)st.size); + else -+ p->n = snprintf(p->a, sizeof(p->a), "%llux%lu %lld\n", ++ p->n = snprintf(p->a, sizeof(p->a), "%llux%u %lld\n", + st.blocks, st.blksize, + (long long)st.size); + AuDebugOn(p->n >= sizeof(p->a)); @@ -6247,7 +6325,7 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c +static int dbgaufs_plink_release(struct inode *inode __maybe_unused, + struct file *file) +{ -+ au_delayed_free_page((unsigned long)file->private_data); ++ free_page((unsigned long)file->private_data); + return 0; +} + @@ -6311,7 +6389,7 @@ diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c + goto out; /* success */ + +out_free: -+ au_delayed_free_page((unsigned long)p); ++ free_page((unsigned long)p); +out: + return err; +} @@ -6582,10 +6660,10 @@ 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 2016-10-09 16:55:36.486034798 +0200 ++++ linux/fs/aufs/dbgaufs.h 2017-07-29 12:14:25.899708630 +0200 @@ -0,0 +1,48 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -6634,10 +6712,10 @@ 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 2016-10-09 16:55:38.886097714 +0200 ++++ linux/fs/aufs/dcsub.c 2017-07-29 12:14:25.899708630 +0200 @@ -0,0 +1,225 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -6667,7 +6745,7 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c + p = dpage->dentries; + for (i = 0; i < dpage->ndentry; i++) + dput(*p++); -+ au_delayed_free_page((unsigned long)dpage->dentries); ++ free_page((unsigned long)dpage->dentries); +} + +int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp) @@ -6690,7 +6768,7 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c + return 0; /* success */ + +out_dpages: -+ au_delayed_kfree(dpages->dpages); ++ kfree(dpages->dpages); +out: + return err; +} @@ -6703,7 +6781,7 @@ diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c + p = dpages->dpages; + for (i = 0; i < dpages->ndpage; i++) + au_dpage_free(p++); -+ au_delayed_kfree(dpages->dpages); ++ kfree(dpages->dpages); +} + +static int au_dpages_append(struct au_dcsub_pages *dpages, @@ -6863,10 +6941,10 @@ 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 2016-10-09 16:55:36.486034798 +0200 ++++ linux/fs/aufs/dcsub.h 2017-07-29 12:14:25.899708630 +0200 @@ -0,0 +1,136 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -7003,10 +7081,10 @@ 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 2016-10-09 16:55:36.486034798 +0200 ++++ linux/fs/aufs/debug.c 2017-07-29 12:14:25.899708630 +0200 @@ -0,0 +1,440 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -7343,7 +7421,7 @@ diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c + au_br_count_init(&a->fake); + err = do_pri_br(-1, &a->fake); + au_br_count_fin(&a->fake); -+ au_delayed_kfree(a); ++ kfree(a); + dpri("dev 0x%x\n", sb->s_dev); + if (err || !au_test_aufs(sb)) + return; @@ -7353,7 +7431,7 @@ diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c + return; + dpri("nw %d, gen %u, kobj %d\n", + atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation, -+ atomic_read(&sbinfo->si_kobj.kref.refcount)); ++ kref_read(&sbinfo->si_kobj.kref)); + for (bindex = 0; bindex <= sbinfo->si_bbot; bindex++) + do_pri_br(bindex, sbinfo->si_branch[0 + bindex]); +} @@ -7447,10 +7525,10 @@ 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 2016-10-09 16:55:36.486034798 +0200 ++++ linux/fs/aufs/debug.h 2017-07-29 12:14:25.899708630 +0200 @@ -0,0 +1,225 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -7676,10 +7754,10 @@ 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 2016-10-09 16:55:38.889431135 +0200 ++++ linux/fs/aufs/dentry.c 2017-07-29 12:14:25.899708630 +0200 @@ -0,0 +1,1130 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -7894,7 +7972,7 @@ diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c + +out_parent: + dput(parent); -+ au_delayed_kfree(whname.name); ++ kfree(whname.name); +out: + return err; +} @@ -8810,10 +8888,10 @@ 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 2016-10-09 16:55:38.889431135 +0200 -@@ -0,0 +1,255 @@ ++++ linux/fs/aufs/dentry.h 2017-07-29 12:14:25.899708630 +0200 +@@ -0,0 +1,252 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -8852,10 +8930,7 @@ diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h + struct au_rwsem di_rwsem; + aufs_bindex_t di_btop, di_bbot, di_bwh, di_bdiropq; + unsigned char di_tmpfile; /* to allow the different name */ -+ union { -+ struct au_hdentry *di_hdentry; -+ struct llist_node di_lnode; /* delayed free */ -+ }; ++ struct au_hdentry *di_hdentry; +} ____cacheline_aligned_in_smp; + +/* ---------------------------------------------------------------------- */ @@ -9069,10 +9144,10 @@ 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 2016-10-09 16:55:38.889431135 +0200 ++++ linux/fs/aufs/dinfo.c 2017-07-29 12:14:25.899708630 +0200 @@ -0,0 +1,553 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -9126,7 +9201,7 @@ diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c + goto out; + } + -+ au_cache_dfree_dinfo(dinfo); ++ au_cache_free_dinfo(dinfo); + dinfo = NULL; + +out: @@ -9146,8 +9221,8 @@ diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c + while (bindex++ <= bbot) + au_hdput(p++); + } -+ au_delayed_kfree(dinfo->di_hdentry); -+ au_cache_dfree_dinfo(dinfo); ++ kfree(dinfo->di_hdentry); ++ au_cache_free_dinfo(dinfo); +} + +void au_di_swap(struct au_dinfo *a, struct au_dinfo *b) @@ -9349,11 +9424,11 @@ diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c + || d_inode(d1) == d_inode(d2) + || d1->d_sb != d2->d_sb); + -+ if (isdir && au_test_subdir(d1, d2)) { ++ if ((isdir && au_test_subdir(d1, d2)) ++ || d1 < d2) { + di_write_lock_child(d1); + di_write_lock_child2(d2); + } else { -+ /* there should be no races */ + di_write_lock_child(d2); + di_write_lock_child2(d1); + } @@ -9365,11 +9440,11 @@ diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c + || d_inode(d1) == d_inode(d2) + || d1->d_sb != d2->d_sb); + -+ if (isdir && au_test_subdir(d1, d2)) { ++ if ((isdir && au_test_subdir(d1, d2)) ++ || d1 < d2) { + di_write_lock_parent(d1); + di_write_lock_parent2(d2); + } else { -+ /* there should be no races */ + di_write_lock_parent(d2); + di_write_lock_parent2(d1); + } @@ -9626,10 +9701,10 @@ 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 2016-10-09 16:55:36.489368218 +0200 -@@ -0,0 +1,762 @@ ++++ linux/fs/aufs/dir.c 2017-07-29 12:14:25.899708630 +0200 +@@ -0,0 +1,759 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -9786,7 +9861,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c +out: + dput(a->dentry); + au_nwt_done(&au_sbi(sb)->si_nowait); -+ au_delayed_kfree(arg); ++ kfree(arg); +} + +void au_dir_ts(struct inode *dir, aufs_bindex_t bindex) @@ -9822,7 +9897,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c + if (unlikely(wkq_err)) { + pr_err("wkq %d\n", wkq_err); + dput(dentry); -+ au_delayed_kfree(arg); ++ kfree(arg); + } + +out: @@ -9941,7 +10016,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c + }; + err = au_do_open(file, &args); + if (unlikely(err)) -+ au_delayed_kfree(fidir); ++ kfree(fidir); + } + si_read_unlock(sb); + return err; @@ -9955,9 +10030,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c + struct au_fidir *fidir; + struct au_hfile *hf; + aufs_bindex_t bindex, bbot; -+ int execed, delayed; + -+ delayed = (current->flags & PF_KTHREAD) || in_interrupt(); + finfo = au_fi(file); + fidir = finfo->fi_hdir; + if (fidir) { @@ -9965,11 +10038,10 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c + &au_sbi(file->f_path.dentry->d_sb)->si_files); + vdir_cache = fidir->fd_vdir_cache; /* lock-free */ + if (vdir_cache) -+ au_vdir_free(vdir_cache, delayed); ++ au_vdir_free(vdir_cache); + + bindex = finfo->fi_btop; + if (bindex >= 0) { -+ execed = vfsub_file_execed(file); + hf = fidir->fd_hfile + bindex; + /* + * calls fput() instead of filp_close(), @@ -9978,12 +10050,12 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c + bbot = fidir->fd_bbot; + for (; bindex <= bbot; bindex++, hf++) + if (hf->hf_file) -+ au_hfput(hf, execed); ++ au_hfput(hf, /*execed*/0); + } -+ au_delayed_kfree(fidir); ++ kfree(fidir); + finfo->fi_hdir = NULL; + } -+ au_finfo_fin(file, delayed); ++ au_finfo_fin(file); + return 0; +} + @@ -10048,7 +10120,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c + struct super_block *sb; + struct inode *inode; + -+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1); ++ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0); + if (unlikely(err)) + goto out; + @@ -10117,7 +10189,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c + + sb = dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH); -+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1); ++ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0); + if (unlikely(err)) + goto out; + err = au_alive_dir(dentry); @@ -10392,10 +10464,10 @@ 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 2016-10-09 16:55:36.489368218 +0200 -@@ -0,0 +1,137 @@ ++++ linux/fs/aufs/dir.h 2017-07-29 12:14:25.899708630 +0200 +@@ -0,0 +1,131 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -10438,10 +10510,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h + +struct au_vdir_dehstr { + struct hlist_node hash; -+ union { -+ struct au_vdir_destr *str; -+ struct llist_node lnode; /* delayed free */ -+ }; ++ struct au_vdir_destr *str; +} ____cacheline_aligned_in_smp; + +struct au_vdir_de { @@ -10479,10 +10548,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h + + unsigned long vd_version; + unsigned int vd_deblk_sz; -+ union { -+ unsigned long vd_jiffy; -+ struct llist_node vd_lnode; /* delayed free */ -+ }; ++ unsigned long vd_jiffy; +} ____cacheline_aligned_in_smp; + +/* ---------------------------------------------------------------------- */ @@ -10506,7 +10572,7 @@ diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h +int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino, + unsigned int d_type, aufs_bindex_t bindex, + unsigned char shwh); -+void au_vdir_free(struct au_vdir *vdir, int atonce); ++void au_vdir_free(struct au_vdir *vdir); +int au_vdir_init(struct file *file); +int au_vdir_fill_de(struct file *file, struct dir_context *ctx); + @@ -10533,10 +10599,10 @@ 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/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 2016-10-09 16:55:36.489368218 +0200 ++++ linux/fs/aufs/dynop.c 2017-07-29 12:14:25.899708630 +0200 @@ -0,0 +1,371 @@ +/* -+ * Copyright (C) 2010-2016 Junjiro R. Okajima ++ * Copyright (C) 2010-2017 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 @@ -10651,7 +10717,7 @@ diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c + + key = container_of(rcu, struct au_dykey, dk_rcu); + DyPrSym(key); -+ kfree(key); /* not delayed */ ++ kfree(key); +} + +static void dy_free(struct kref *kref) @@ -10779,7 +10845,7 @@ diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c + p->set(key, op->dy_hop, au_br_sb(br)); + old = dy_gadd(sphl, key); + if (old) { -+ au_delayed_kfree(key); ++ kfree(key); + key = old; + } + @@ -10908,10 +10974,10 @@ 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 2016-10-09 16:55:36.489368218 +0200 ++++ linux/fs/aufs/dynop.h 2017-07-29 12:14:25.899708630 +0200 @@ -0,0 +1,74 @@ +/* -+ * Copyright (C) 2010-2016 Junjiro R. Okajima ++ * Copyright (C) 2010-2017 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 @@ -10986,10 +11052,10 @@ 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 2016-12-17 12:28:17.595211562 +0100 ++++ linux/fs/aufs/export.c 2017-07-29 12:14:25.903042072 +0200 @@ -0,0 +1,836 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -11406,7 +11472,7 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c + } + +out_name: -+ au_delayed_free_page((unsigned long)arg.name); ++ free_page((unsigned long)arg.name); +out_file: + fput(file); +out: @@ -11560,7 +11626,7 @@ diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c + dentry = ERR_PTR(-ESTALE); + } +out_pathname: -+ au_delayed_free_page((unsigned long)pathname); ++ free_page((unsigned long)pathname); +out_h_parent: + dput(h_parent); +out: @@ -11826,10 +11892,10 @@ 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 2016-10-09 16:55:36.489368218 +0200 ++++ linux/fs/aufs/fhsm.c 2017-07-29 12:14:25.903042072 +0200 @@ -0,0 +1,426 @@ +/* -+ * Copyright (C) 2011-2016 Junjiro R. Okajima ++ * Copyright (C) 2011-2017 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 @@ -12256,10 +12322,10 @@ 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 2016-10-09 16:55:38.889431135 +0200 -@@ -0,0 +1,857 @@ ++++ linux/fs/aufs/file.c 2017-07-29 12:14:25.903042072 +0200 +@@ -0,0 +1,858 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -12533,7 +12599,7 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c + } + if (unlikely(err)) { + finfo->fi_hdir = NULL; -+ au_finfo_fin(file, /*atonce*/0); ++ au_finfo_fin(file); + } + +out: @@ -12853,7 +12919,6 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c + +static void au_do_refresh_dir(struct file *file) +{ -+ int execed; + aufs_bindex_t bindex, bbot, new_bindex, brid; + struct au_hfile *p, tmp, *q; + struct au_finfo *finfo; @@ -12892,7 +12957,6 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c + } + } + -+ execed = vfsub_file_execed(file); + p = fidir->fd_hfile; + if (!au_test_mmapped(file) && !d_unlinked(file->f_path.dentry)) { + bbot = au_sbbot(sb); @@ -12901,14 +12965,14 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c + if (p->hf_file) { + if (file_inode(p->hf_file)) + break; -+ au_hfput(p, execed); ++ au_hfput(p, /*execed*/0); + } + } else { + bbot = au_br_index(sb, brid); + for (finfo->fi_btop = 0; finfo->fi_btop < bbot; + finfo->fi_btop++, p++) + if (p->hf_file) -+ au_hfput(p, execed); ++ au_hfput(p, /*execed*/0); + bbot = au_sbbot(sb); + } + @@ -12918,7 +12982,7 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c + if (p->hf_file) { + if (file_inode(p->hf_file)) + break; -+ au_hfput(p, execed); ++ au_hfput(p, /*execed*/0); + } + AuDebugOn(fidir->fd_bbot < finfo->fi_btop); +} @@ -12980,7 +13044,7 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c + +/* common function to regular file and dir */ +int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file), -+ int wlock) ++ int wlock, unsigned int fi_lsc) +{ + int err; + unsigned int sigen, figen; @@ -12993,9 +13057,12 @@ diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c + dentry = file->f_path.dentry; + inode = d_inode(dentry); + sigen = au_sigen(dentry->d_sb); -+ fi_write_lock(file); ++ fi_write_lock_nested(file, fi_lsc); + figen = au_figen(file); -+ di_write_lock_child(dentry); ++ if (!fi_lsc) ++ di_write_lock_child(dentry); ++ else ++ di_write_lock_child2(dentry); + btop = au_dbtop(dentry); + pseudo_link = (btop != au_ibtop(inode)); + if (sigen == figen && !pseudo_link && au_fbtop(file) == btop) { @@ -13117,10 +13184,10 @@ 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 2016-10-09 16:55:38.889431135 +0200 -@@ -0,0 +1,294 @@ ++++ linux/fs/aufs/file.h 2017-07-29 12:14:25.903042072 +0200 +@@ -0,0 +1,330 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -13184,10 +13251,7 @@ diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h + struct au_fidir *fi_hdir; /* for dir only */ + + struct hlist_node fi_hlist; -+ union { -+ struct file *fi_file; /* very ugly */ -+ struct llist_node fi_lnode; /* delayed free */ -+ }; ++ struct file *fi_file; /* very ugly */ +} ____cacheline_aligned_in_smp; + +/* ---------------------------------------------------------------------- */ @@ -13209,7 +13273,7 @@ diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h +struct au_pin; +int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin); +int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file), -+ int wlock); ++ int wlock, unsigned int fi_lsc); +int au_do_flush(struct file *file, fl_owner_t id, + int (*flush)(struct file *file, fl_owner_t id)); + @@ -13235,7 +13299,7 @@ diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h +extern const struct file_operations aufs_file_fop; +int au_do_open_nondir(struct file *file, int flags, struct file *h_file); +int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file); -+struct file *au_read_pre(struct file *file, int keep_fi); ++struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc); + +/* finfo.c */ +void au_hfput(struct au_hfile *hf, int execed); @@ -13247,7 +13311,7 @@ diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h +int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink); + +void au_fi_init_once(void *_fi); -+void au_finfo_fin(struct file *file, int atonce); ++void au_finfo_fin(struct file *file); +int au_finfo_init(struct file *file, struct au_fidir *fidir); + +/* ioctl.c */ @@ -13274,6 +13338,45 @@ diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h + */ +AuSimpleRwsemFuncs(fi, struct file *f, &au_fi(f)->fi_rwsem); + ++/* lock subclass for finfo */ ++enum { ++ AuLsc_FI_1, ++ AuLsc_FI_2 ++}; ++ ++static inline void fi_read_lock_nested(struct file *f, unsigned int lsc) ++{ ++ au_rw_read_lock_nested(&au_fi(f)->fi_rwsem, lsc); ++} ++ ++static inline void fi_write_lock_nested(struct file *f, unsigned int lsc) ++{ ++ au_rw_write_lock_nested(&au_fi(f)->fi_rwsem, lsc); ++} ++ ++/* ++ * fi_read_lock_1, fi_write_lock_1, ++ * fi_read_lock_2, fi_write_lock_2 ++ */ ++#define AuReadLockFunc(name) \ ++static inline void fi_read_lock_##name(struct file *f) \ ++{ fi_read_lock_nested(f, AuLsc_FI_##name); } ++ ++#define AuWriteLockFunc(name) \ ++static inline void fi_write_lock_##name(struct file *f) \ ++{ fi_write_lock_nested(f, AuLsc_FI_##name); } ++ ++#define AuRWLockFuncs(name) \ ++ AuReadLockFunc(name) \ ++ AuWriteLockFunc(name) ++ ++AuRWLockFuncs(1); ++AuRWLockFuncs(2); ++ ++#undef AuReadLockFunc ++#undef AuWriteLockFunc ++#undef AuRWLockFuncs ++ +#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem) +#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem) +#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem) @@ -13415,10 +13518,10 @@ 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 2016-10-09 16:55:38.889431135 +0200 -@@ -0,0 +1,151 @@ ++++ linux/fs/aufs/finfo.c 2017-07-29 12:14:25.903042072 +0200 +@@ -0,0 +1,148 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -13521,7 +13624,7 @@ diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c + +/* ---------------------------------------------------------------------- */ + -+void au_finfo_fin(struct file *file, int atonce) ++void au_finfo_fin(struct file *file) +{ + struct au_finfo *finfo; + @@ -13530,10 +13633,7 @@ diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c + finfo = au_fi(file); + AuDebugOn(finfo->fi_hdir); + AuRwDestroy(&finfo->fi_rwsem); -+ if (!atonce) -+ au_cache_dfree_finfo(finfo); -+ else -+ au_cache_free_finfo(finfo); ++ au_cache_free_finfo(finfo); +} + +void au_fi_init_once(void *_finfo) @@ -13570,10 +13670,10 @@ 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 2016-12-17 12:28:17.595211562 +0100 -@@ -0,0 +1,723 @@ ++++ linux/fs/aufs/f_op.c 2017-07-29 12:14:25.903042072 +0200 +@@ -0,0 +1,817 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -13673,7 +13773,6 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c +{ + struct au_finfo *finfo; + aufs_bindex_t bindex; -+ int delayed; + + finfo = au_fi(file); + au_sphl_del(&finfo->fi_hlist, @@ -13682,8 +13781,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + if (bindex >= 0) + au_set_h_fptr(file, bindex, NULL); + -+ delayed = (current->flags & PF_KTHREAD) || in_interrupt(); -+ au_finfo_fin(file, delayed); ++ au_finfo_fin(file); + return 0; +} + @@ -13716,12 +13814,12 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + */ + +/* Callers should call au_read_post() or fput() in the end */ -+struct file *au_read_pre(struct file *file, int keep_fi) ++struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc) +{ + struct file *h_file; + int err; + -+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0); ++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0, lsc); + if (!err) { + di_read_unlock(file->f_path.dentry, AuLock_IR); + h_file = au_hf_top(file); @@ -13742,6 +13840,10 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c +} + +struct au_write_pre { ++ /* input */ ++ unsigned int lsc; ++ ++ /* output */ + blkcnt_t blks; + aufs_bindex_t btop; +}; @@ -13757,9 +13859,13 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + struct file *h_file; + struct dentry *dentry; + int err; ++ unsigned int lsc; + struct au_pin pin; + -+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1); ++ lsc = 0; ++ if (wpre) ++ lsc = wpre->lsc; ++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, lsc); + h_file = ERR_PTR(err); + if (unlikely(err)) + goto out; @@ -13801,12 +13907,11 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + h_inode = file_inode(h_file); + inode->i_mode = h_inode->i_mode; + ii_write_unlock(inode); -+ fput(h_file); -+ + /* AuDbg("blks %llu, %llu\n", (u64)blks, (u64)h_inode->i_blocks); */ + if (written > 0) + au_fhsm_wrote(inode->i_sb, wpre->btop, + /*force*/h_inode->i_blocks > wpre->blks); ++ fput(h_file); +} + +static ssize_t aufs_read(struct file *file, char __user *buf, size_t count, @@ -13821,7 +13926,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + sb = inode->i_sb; + si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); + -+ h_file = au_read_pre(file, /*keep_fi*/0); ++ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); + err = PTR_ERR(h_file); + if (IS_ERR(h_file)) + goto out; @@ -13871,6 +13976,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + 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)) @@ -13930,7 +14036,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + sb = inode->i_sb; + si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); + -+ h_file = au_read_pre(file, /*keep_fi*/1); ++ h_file = au_read_pre(file, /*keep_fi*/1, /*lsc*/0); + err = PTR_ERR(h_file); + if (IS_ERR(h_file)) + goto out; @@ -13965,6 +14071,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + 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)) @@ -13992,7 +14099,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + sb = inode->i_sb; + si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); + -+ h_file = au_read_pre(file, /*keep_fi*/0); ++ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); + err = PTR_ERR(h_file); + if (IS_ERR(h_file)) + goto out; @@ -14019,6 +14126,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + 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)) @@ -14044,6 +14152,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + 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)) @@ -14060,6 +14169,88 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + return err; +} + ++static ssize_t aufs_copy_file_range(struct file *src, loff_t src_pos, ++ struct file *dst, loff_t dst_pos, ++ size_t len, unsigned int flags) ++{ ++ ssize_t err; ++ struct au_write_pre wpre; ++ enum { SRC, DST }; ++ struct { ++ struct inode *inode; ++ struct file *h_file; ++ struct super_block *h_sb; ++ } a[2]; ++#define a_src a[SRC] ++#define a_dst a[DST] ++ ++ err = -EINVAL; ++ a_src.inode = file_inode(src); ++ if (unlikely(!S_ISREG(a_src.inode->i_mode))) ++ goto out; ++ a_dst.inode = file_inode(dst); ++ if (unlikely(!S_ISREG(a_dst.inode->i_mode))) ++ goto out; ++ ++ au_mtx_and_read_lock(a_dst.inode); ++ /* ++ * in order to match the order in di_write_lock2_{child,parent}(), ++ * use f_path.dentry for this comparision. ++ */ ++ if (src->f_path.dentry < dst->f_path.dentry) { ++ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_1); ++ err = PTR_ERR(a_src.h_file); ++ if (IS_ERR(a_src.h_file)) ++ goto out_si; ++ ++ wpre.lsc = AuLsc_FI_2; ++ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre); ++ err = PTR_ERR(a_dst.h_file); ++ if (IS_ERR(a_dst.h_file)) { ++ au_read_post(a_src.inode, a_src.h_file); ++ goto out_si; ++ } ++ } else { ++ wpre.lsc = AuLsc_FI_1; ++ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre); ++ err = PTR_ERR(a_dst.h_file); ++ if (IS_ERR(a_dst.h_file)) ++ goto out_si; ++ ++ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_2); ++ err = PTR_ERR(a_src.h_file); ++ if (IS_ERR(a_src.h_file)) { ++ au_write_post(a_dst.inode, a_dst.h_file, &wpre, ++ /*written*/0); ++ goto out_si; ++ } ++ } ++ ++ err = -EXDEV; ++ a_src.h_sb = file_inode(a_src.h_file)->i_sb; ++ a_dst.h_sb = file_inode(a_dst.h_file)->i_sb; ++ if (unlikely(a_src.h_sb != a_dst.h_sb)) { ++ AuDbgFile(src); ++ AuDbgFile(dst); ++ goto out_file; ++ } ++ ++ err = vfsub_copy_file_range(a_src.h_file, src_pos, a_dst.h_file, ++ dst_pos, len, flags); ++ ++out_file: ++ au_write_post(a_dst.inode, a_dst.h_file, &wpre, err); ++ fi_read_unlock(src); ++ au_read_post(a_src.inode, a_src.h_file); ++out_si: ++ si_read_unlock(a_dst.inode->i_sb); ++ inode_unlock(a_dst.inode); ++out: ++ return err; ++#undef a_src ++#undef a_dst ++} ++ +/* ---------------------------------------------------------------------- */ + +/* @@ -14150,7 +14341,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + * au_flag_conv(vma->vm_flags)); + */ + if (!err) -+ err = h_file->f_op->mmap(h_file, vma); ++ err = call_mmap(h_file, vma); + if (!err) { + au_vm_prfile_set(vma, file); + fsstack_copy_attr_atime(inode, file_inode(h_file)); @@ -14189,6 +14380,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + 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)) @@ -14213,7 +14405,7 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + sb = file->f_path.dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); + -+ h_file = au_read_pre(file, /*keep_fi*/0); ++ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); + err = PTR_ERR(h_file); + if (IS_ERR(h_file)) + goto out; @@ -14236,12 +14428,13 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + sb = file->f_path.dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); + -+ h_file = au_read_pre(file, /*keep_fi*/0); ++ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); + err = PTR_ERR(h_file); + if (IS_ERR(h_file)) + goto out; + -+ arg |= vfsub_file_flags(file) & FASYNC; /* stop calling h_file->fasync */ ++ /* stop calling h_file->fasync */ ++ arg |= vfsub_file_flags(file) & FASYNC; + err = setfl(/*unused fd*/-1, h_file, arg); + fput(h_file); /* instead of au_read_post() */ + @@ -14293,14 +14486,15 @@ diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c + .aio_splice_write = aufs_aio_splice_write, + .aio_splice_read = aufs_aio_splice_read, +#endif -+ .fallocate = aufs_fallocate ++ .fallocate = aufs_fallocate, ++ .copy_file_range = aufs_copy_file_range +}; 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 2016-10-09 16:55:36.492701639 +0200 ++++ linux/fs/aufs/fstype.h 2017-07-29 12:14:25.903042072 +0200 @@ -0,0 +1,400 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -14701,10 +14895,10 @@ 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/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 2016-10-09 16:55:36.492701639 +0200 -@@ -0,0 +1,287 @@ ++++ linux/fs/aufs/hfsnotify.c 2017-07-29 12:14:32.526591175 +0200 +@@ -0,0 +1,289 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -14737,7 +14931,7 @@ diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c + struct au_hnotify *hn = container_of(mark, struct au_hnotify, + hn_mark); + /* AuDbg("here\n"); */ -+ au_cache_dfree_hnotify(hn); ++ au_cache_free_hnotify(hn); + smp_mb__before_atomic(); + if (atomic64_dec_and_test(&au_hfsn_ifree)) + wake_up(&au_hfsn_wq); @@ -14759,15 +14953,15 @@ diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c + AuDebugOn(!br->br_hfsn); + + mark = &hn->hn_mark; -+ fsnotify_init_mark(mark, au_hfsn_free_mark); ++ fsnotify_init_mark(mark, br->br_hfsn->hfsn_group); + mark->mask = AuHfsnMask; + /* + * by udba rename or rmdir, aufs assign a new inode to the known + * h_inode, so specify 1 to allow dups. + */ + lockdep_off(); -+ err = fsnotify_add_mark(mark, br->br_hfsn->hfsn_group, hinode->hi_inode, -+ /*mnt*/NULL, /*allow_dups*/1); ++ err = fsnotify_add_mark(mark, hinode->hi_inode, /*mnt*/NULL, ++ /*allow_dups*/1); + lockdep_on(); + + return err; @@ -14861,15 +15055,16 @@ diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c + struct au_br_hfsnotify *hfsn = group->private; + + /* AuDbg("here\n"); */ -+ au_delayed_kfree(hfsn); ++ kfree(hfsn); +} + +static int au_hfsn_handle_event(struct fsnotify_group *group, + struct inode *inode, + struct fsnotify_mark *inode_mark, + struct fsnotify_mark *vfsmount_mark, -+ u32 mask, void *data, int data_type, -+ const unsigned char *file_name, u32 cookie) ++ u32 mask, const void *data, int data_type, ++ const unsigned char *file_name, u32 cookie, ++ struct fsnotify_iter_info *iter_info) +{ + int err; + struct au_hnotify *hnotify; @@ -14908,7 +15103,8 @@ diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c + +static struct fsnotify_ops au_hfsn_ops = { + .handle_event = au_hfsn_handle_event, -+ .free_group_priv = au_hfsn_free_group ++ .free_group_priv = au_hfsn_free_group, ++ .free_mark = au_hfsn_free_mark +}; + +/* ---------------------------------------------------------------------- */ @@ -14955,7 +15151,7 @@ diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c + goto out; /* success */ + +out_hfsn: -+ au_delayed_kfree(hfsn); ++ kfree(hfsn); +out: + return err; +} @@ -14992,10 +15188,10 @@ 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 2016-10-09 16:55:36.492701639 +0200 ++++ linux/fs/aufs/hfsplus.c 2017-07-29 12:14:25.903042072 +0200 @@ -0,0 +1,56 @@ +/* -+ * Copyright (C) 2010-2016 Junjiro R. Okajima ++ * Copyright (C) 2010-2017 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 @@ -15052,10 +15248,10 @@ 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 2016-10-09 16:55:36.492701639 +0200 -@@ -0,0 +1,723 @@ ++++ linux/fs/aufs/hnotify.c 2017-07-29 12:14:25.903042072 +0200 +@@ -0,0 +1,711 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -15091,7 +15287,7 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c + AuTraceErr(err); + if (unlikely(err)) { + hinode->hi_notify = NULL; -+ au_cache_dfree_hnotify(hn); ++ au_cache_free_hnotify(hn); + /* + * The upper dir was removed by udba, but the same named + * dir left. In this case, aufs assignes a new inode @@ -15115,7 +15311,7 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c + if (hn) { + hinode->hi_notify = NULL; + if (au_hnotify_op.free(hinode, hn)) -+ au_cache_dfree_hnotify(hn); ++ au_cache_free_hnotify(hn); + } +} + @@ -15588,7 +15784,7 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c + iput(a->dir); + si_write_unlock(sb); + au_nwt_done(&sbinfo->si_nowait); -+ au_delayed_kfree(a); ++ kfree(a); +} + +/* ---------------------------------------------------------------------- */ @@ -15694,7 +15890,7 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c + iput(args->h_child_inode); + iput(args->h_dir); + iput(args->dir); -+ au_delayed_kfree(args); ++ kfree(args); + } + +out: @@ -15735,26 +15931,17 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c + +static void au_hn_destroy_cache(void) +{ -+ struct au_cache *cp; -+ -+ flush_delayed_work(&au_dfree.dwork); -+ cp = au_dfree.cache + AuCache_HNOTIFY; -+ AuDebugOn(!llist_empty(&cp->llist)); -+ kmem_cache_destroy(cp->cache); -+ cp->cache = NULL; ++ kmem_cache_destroy(au_cache[AuCache_HNOTIFY]); ++ au_cache[AuCache_HNOTIFY] = NULL; +} + -+AU_CACHE_DFREE_FUNC(hnotify, HNOTIFY, hn_lnode); -+ +int __init au_hnotify_init(void) +{ + int err; -+ struct au_cache *cp; + + err = -ENOMEM; -+ cp = au_dfree.cache + AuCache_HNOTIFY; -+ cp->cache = AuCache(au_hnotify); -+ if (cp->cache) { ++ au_cache[AuCache_HNOTIFY] = AuCache(au_hnotify); ++ if (au_cache[AuCache_HNOTIFY]) { + err = 0; + if (au_hnotify_op.init) + err = au_hnotify_op.init(); @@ -15767,22 +15954,19 @@ diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c + +void au_hnotify_fin(void) +{ -+ struct au_cache *cp; -+ + if (au_hnotify_op.fin) + au_hnotify_op.fin(); + + /* cf. au_cache_fin() */ -+ cp = au_dfree.cache + AuCache_HNOTIFY; -+ if (cp->cache) ++ if (au_cache[AuCache_HNOTIFY]) + au_hn_destroy_cache(); +} 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 2016-10-09 16:55:38.889431135 +0200 ++++ linux/fs/aufs/iinfo.c 2017-07-29 12:14:25.903042072 +0200 @@ -0,0 +1,285 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -16051,7 +16235,7 @@ diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c + + iinfo = au_ii(inode); + if (iinfo->ii_vdir) -+ au_vdir_free(iinfo->ii_vdir, /*atonce*/0); ++ au_vdir_free(iinfo->ii_vdir); + + bindex = iinfo->ii_btop; + if (bindex >= 0) { @@ -16063,15 +16247,15 @@ diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c + hi++; + } + } -+ au_delayed_kfree(iinfo->ii_hinode); ++ kfree(iinfo->ii_hinode); + AuRwDestroy(&iinfo->ii_rwsem); +} 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 2016-10-09 16:55:38.889431135 +0200 -@@ -0,0 +1,519 @@ ++++ linux/fs/aufs/inode.c 2017-07-29 12:14:25.903042072 +0200 +@@ -0,0 +1,527 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -16407,32 +16591,34 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c +int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, + unsigned int d_type, ino_t *ino) +{ -+ int err; -+ struct mutex *mtx; ++ int err, idx; ++ const int isnondir = d_type != DT_DIR; + + /* prevent hardlinked inode number from race condition */ -+ mtx = NULL; -+ if (d_type != DT_DIR) { -+ mtx = &au_sbr(sb, bindex)->br_xino.xi_nondir_mtx; -+ mutex_lock(mtx); ++ if (isnondir) { ++ err = au_xinondir_enter(sb, bindex, h_ino, &idx); ++ if (unlikely(err)) ++ goto out; + } ++ + err = au_xino_read(sb, bindex, h_ino, ino); + if (unlikely(err)) -+ goto out; ++ goto out_xinondir; + + if (!*ino) { + err = -EIO; + *ino = au_xino_new_ino(sb); + if (unlikely(!*ino)) -+ goto out; ++ goto out_xinondir; + err = au_xino_write(sb, bindex, h_ino, *ino); + if (unlikely(err)) -+ goto out; ++ goto out_xinondir; + } + ++out_xinondir: ++ if (isnondir && idx >= 0) ++ au_xinondir_leave(sb, bindex, h_ino, idx); +out: -+ if (mtx) -+ mutex_unlock(mtx); + return err; +} + @@ -16443,9 +16629,8 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c + struct inode *inode, *h_inode; + struct dentry *h_dentry; + struct super_block *sb; -+ struct mutex *mtx; + ino_t h_ino, ino; -+ int err; ++ int err, idx, hlinked; + aufs_bindex_t btop; + + sb = dentry->d_sb; @@ -16453,28 +16638,30 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c + h_dentry = au_h_dptr(dentry, btop); + h_inode = d_inode(h_dentry); + h_ino = h_inode->i_ino; ++ hlinked = !d_is_dir(h_dentry) && h_inode->i_nlink > 1; + ++new_ino: + /* + * stop 'race'-ing between hardlinks under different + * parents. + */ -+ mtx = NULL; -+ if (!d_is_dir(h_dentry)) -+ mtx = &au_sbr(sb, btop)->br_xino.xi_nondir_mtx; ++ if (hlinked) { ++ err = au_xinondir_enter(sb, btop, h_ino, &idx); ++ inode = ERR_PTR(err); ++ if (unlikely(err)) ++ goto out; ++ } + -+new_ino: -+ if (mtx) -+ mutex_lock(mtx); + err = au_xino_read(sb, btop, h_ino, &ino); + inode = ERR_PTR(err); + if (unlikely(err)) -+ goto out; ++ goto out_xinondir; + + if (!ino) { + ino = au_xino_new_ino(sb); + if (unlikely(!ino)) { + inode = ERR_PTR(-EIO); -+ goto out; ++ goto out_xinondir; + } + } + @@ -16482,7 +16669,7 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c + inode = au_iget_locked(sb, ino); + err = PTR_ERR(inode); + if (IS_ERR(inode)) -+ goto out; ++ goto out_xinondir; + + AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW)); + if (inode->i_state & I_NEW) { @@ -16490,7 +16677,7 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c + err = set_inode(inode, dentry); + if (!err) { + unlock_new_inode(inode); -+ goto out; /* success */ ++ goto out_xinondir; /* success */ + } + + /* @@ -16509,19 +16696,23 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c + * horrible race condition between lookup, readdir and copyup + * (or something). + */ -+ if (mtx) -+ mutex_unlock(mtx); ++ if (hlinked && idx >= 0) ++ au_xinondir_leave(sb, btop, h_ino, idx); + err = reval_inode(inode, dentry); + if (unlikely(err < 0)) { -+ mtx = NULL; ++ hlinked = 0; + goto out_iput; + } -+ -+ if (!err) { -+ mtx = NULL; ++ if (!err) + goto out; /* success */ -+ } else if (mtx) -+ mutex_lock(mtx); ++ else if (hlinked && idx >= 0) { ++ err = au_xinondir_enter(sb, btop, h_ino, &idx); ++ if (unlikely(err)) { ++ iput(inode); ++ inode = ERR_PTR(err); ++ goto out; ++ } ++ } + } + + if (unlikely(au_test_fs_unique_ino(h_inode))) @@ -16533,17 +16724,18 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c + err = au_xino_write(sb, btop, h_ino, /*ino*/0); + if (!err) { + iput(inode); -+ if (mtx) -+ mutex_unlock(mtx); ++ if (hlinked && idx >= 0) ++ au_xinondir_leave(sb, btop, h_ino, idx); + goto new_ino; + } + +out_iput: + iput(inode); + inode = ERR_PTR(err); ++out_xinondir: ++ if (hlinked && idx >= 0) ++ au_xinondir_leave(sb, btop, h_ino, idx); +out: -+ if (mtx) -+ mutex_unlock(mtx); + return inode; +} + @@ -16591,10 +16783,10 @@ diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c +} 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 2016-12-17 12:28:17.595211562 +0100 -@@ -0,0 +1,691 @@ ++++ linux/fs/aufs/inode.h 2017-07-29 12:14:25.903042072 +0200 +@@ -0,0 +1,686 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -16630,10 +16822,7 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h + /* never use fsnotify_add_vfsmount_mark() */ + struct fsnotify_mark hn_mark; +#endif -+ union { -+ struct inode *hn_aufs_inode; /* no get/put */ -+ struct llist_node hn_lnode; /* delayed free */ -+ }; ++ struct inode *hn_aufs_inode; /* no get/put */ +#endif +} ____cacheline_aligned_in_smp; + @@ -16676,10 +16865,7 @@ diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h +struct au_icntnr { + struct au_iinfo iinfo; + struct inode vfs_inode; -+ union { -+ struct hlist_node plink; -+ struct llist_node lnode; /* delayed free */ -+ }; ++ struct hlist_node plink; +} ____cacheline_aligned_in_smp; + +/* au_pin flags */ @@ -16805,7 +16991,8 @@ 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 au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path, ++ int locked); + +/* i_op_add.c */ +int au_may_add(struct dentry *dentry, aufs_bindex_t bindex, @@ -17286,10 +17473,10 @@ 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 2016-10-09 16:55:36.492701639 +0200 ++++ linux/fs/aufs/ioctl.c 2017-07-29 12:14:25.903042072 +0200 @@ -0,0 +1,219 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -17509,10 +17696,10 @@ 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 2016-12-17 12:28:17.595211562 +0100 -@@ -0,0 +1,928 @@ ++++ linux/fs/aufs/i_op_add.c 2017-07-29 12:14:25.903042072 +0200 +@@ -0,0 +1,920 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -17858,7 +18045,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c + if (!try_aopen) + aufs_read_unlock(dentry, AuLock_DW); +out_free: -+ au_delayed_kfree(a); ++ kfree(a); +out: + return err; +} @@ -17968,18 +18155,11 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c + goto out_parent; + + h_parent = au_h_dptr(parent, bindex); -+ err = inode_permission(d_inode(h_parent), MAY_WRITE | MAY_EXEC); -+ if (unlikely(err)) -+ goto out_mnt; -+ -+ err = -ENOMEM; -+ h_dentry = d_alloc(h_parent, &dentry->d_name); -+ if (unlikely(!h_dentry)) ++ h_dentry = vfs_tmpfile(h_parent, mode, /*open_flag*/0); ++ if (IS_ERR(h_dentry)) { ++ err = PTR_ERR(h_dentry); + goto out_mnt; -+ -+ err = h_dir->i_op->tmpfile(h_dir, h_dentry, mode); -+ if (unlikely(err)) -+ goto out_dentry; ++ } + + au_set_dbtop(dentry, bindex); + au_set_dbbot(dentry, bindex); @@ -18000,9 +18180,8 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c + if (au_ibtop(dir) == au_dbtop(dentry)) + au_cpup_attr_timesizes(dir); + } -+ -+out_dentry: + dput(h_dentry); ++ +out_mnt: + vfsub_mnt_drop_write(h_mnt); +out_parent: @@ -18326,7 +18505,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c + } + aufs_read_and_write_unlock2(dentry, src_dentry); +out_kfree: -+ au_delayed_kfree(a); ++ kfree(a); +out: + AuTraceErr(err); + return err; @@ -18435,16 +18614,16 @@ diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c + } + aufs_read_unlock(dentry, AuLock_DW); +out_free: -+ au_delayed_kfree(a); ++ kfree(a); +out: + return err; +} 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 2016-12-17 12:28:17.595211562 +0100 -@@ -0,0 +1,1444 @@ ++++ linux/fs/aufs/i_op.c 2017-07-29 12:14:25.903042072 +0200 +@@ -0,0 +1,1452 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -19355,7 +19534,8 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c + /* currently ftruncate(2) only */ + AuDebugOn(!d_is_reg(dentry)); + file = ia->ia_file; -+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1); ++ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, ++ /*fi_lsc*/0); + if (unlikely(err)) + goto out_si; + ia->ia_file = au_hf_top(file); @@ -19445,7 +19625,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c +out_si: + si_read_unlock(sb); +out_kfree: -+ au_delayed_kfree(a); ++ kfree(a); +out: + AuTraceErr(err); + return err; @@ -19536,7 +19716,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c + di_write_unlock(dentry); + si_read_unlock(sb); +out_kfree: -+ au_delayed_kfree(a); ++ kfree(a); +out: + AuTraceErr(err); + return err; @@ -19577,7 +19757,8 @@ 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 au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path, ++ int locked) +{ + int err; + unsigned int mnt_flags, sigen; @@ -19594,6 +19775,9 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c + mnt_flags = au_mntflags(sb); + udba_none = !!au_opt_test(mnt_flags, UDBA_NONE); + ++ if (unlikely(locked)) ++ goto body; /* skip locking dinfo */ ++ + /* support fstat(2) */ + if (!d_unlinked(dentry) && !udba_none) { + sigen = au_sigen(sb); @@ -19621,6 +19805,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c + } else + di_read_lock_child(dentry, AuLock_IR); + ++body: + inode = d_inode(dentry); + bindex = au_ibtop(inode); + h_path->mnt = au_sbr_mnt(sb, bindex); @@ -19645,21 +19830,23 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c + return err; +} + -+static int aufs_getattr(struct vfsmount *mnt __maybe_unused, -+ struct dentry *dentry, struct kstat *st) ++static int aufs_getattr(const struct path *path, struct kstat *st, ++ u32 request, unsigned int query) +{ + int err; + unsigned char positive; + struct path h_path; ++ struct dentry *dentry; + struct inode *inode; + struct super_block *sb; + ++ dentry = path->dentry; + inode = d_inode(dentry); + sb = dentry->d_sb; + err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); + if (unlikely(err)) + goto out; -+ err = au_h_path_getattr(dentry, /*force*/0, &h_path); ++ err = au_h_path_getattr(dentry, /*force*/0, &h_path, /*locked*/0); + if (unlikely(err)) + goto out_si; + if (unlikely(!h_path.dentry)) @@ -19668,7 +19855,8 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c + + positive = d_is_positive(h_path.dentry); + if (positive) -+ err = vfs_getattr(&h_path, st); ++ /* no vfsub version */ ++ err = vfs_getattr(&h_path, st, request, query); + if (!err) { + if (positive) + au_refresh_iattr(inode, st, @@ -19837,7 +20025,6 @@ diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c + .listxattr = aufs_listxattr, +#endif + -+ .readlink = generic_readlink, + .get_link = aufs_get_link, + + /* .update_time = aufs_update_time */ @@ -19889,10 +20076,10 @@ 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 2016-10-09 16:55:36.492701639 +0200 ++++ linux/fs/aufs/i_op_del.c 2017-07-29 12:14:25.903042072 +0200 @@ -0,0 +1,511 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -20287,7 +20474,7 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c +out_unlock: + aufs_read_unlock(dentry, AuLock_DW); +out_free: -+ au_delayed_kfree(a); ++ kfree(a); +out: + return err; +} @@ -20397,17 +20584,17 @@ diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c +out_unlock: + aufs_read_unlock(dentry, AuLock_DW); +out_free: -+ au_delayed_kfree(a); ++ kfree(a); +out: + AuTraceErr(err); + return err; +} 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 2016-12-17 12:28:17.595211562 +0100 ++++ linux/fs/aufs/i_op_ren.c 2017-07-29 12:14:25.903042072 +0200 @@ -0,0 +1,1165 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -21566,14 +21753,14 @@ diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c + iput(a->dst_inode); + if (a->thargs) + au_whtmp_rmdir_free(a->thargs); -+ au_delayed_kfree(a); ++ kfree(a); +out: + AuTraceErr(err); + return err; +} 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 2016-10-09 16:55:36.482701377 +0200 ++++ linux/fs/aufs/Kconfig 2017-07-29 12:14:25.896375188 +0200 @@ -0,0 +1,185 @@ +config AUFS_FS + tristate "Aufs (Advanced multi layered unification filesystem) support" @@ -21762,10 +21949,10 @@ diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig +endif 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 2016-10-09 16:55:38.889431135 +0200 ++++ linux/fs/aufs/loop.c 2017-07-29 12:14:25.903042072 +0200 @@ -0,0 +1,147 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -21909,14 +22096,14 @@ diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c +{ + if (backing_file_func) + symbol_put(loop_backing_file); -+ au_delayed_kfree(au_warn_loopback_array); ++ kfree(au_warn_loopback_array); +} 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 2016-10-09 16:55:36.492701639 +0200 ++++ linux/fs/aufs/loop.h 2017-07-29 12:14:25.903042072 +0200 @@ -0,0 +1,52 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -21969,7 +22156,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 2016-10-09 16:55:36.492701639 +0200 ++++ linux/fs/aufs/magic.mk 2017-07-29 12:14:25.903042072 +0200 @@ -0,0 +1,30 @@ + +# defined in ${srctree}/fs/fuse/inode.c @@ -22003,7 +22190,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 2016-10-09 16:55:36.486034798 +0200 ++++ linux/fs/aufs/Makefile 2017-07-29 12:14:25.896375188 +0200 @@ -0,0 +1,44 @@ + +include ${src}/magic.mk @@ -22051,10 +22238,10 @@ 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 2016-10-09 16:55:38.889431135 +0200 -@@ -0,0 +1,333 @@ ++++ linux/fs/aufs/module.c 2017-07-29 12:14:25.903042072 +0200 +@@ -0,0 +1,266 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -22089,7 +22276,7 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c + if (p) { +#if 0 /* unused */ + if (!new_sz) { -+ au_delayed_kfree(p); ++ kfree(p); + p = NULL; + goto out; + } @@ -22113,7 +22300,7 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c + if (q) { + if (p) { + memcpy(q, p, new_sz); -+ au_delayed_kfree(p); ++ kfree(p); + } + p = q; + } else @@ -22137,61 +22324,11 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c +/* + * aufs caches + */ -+ -+struct au_dfree au_dfree; -+ -+/* delayed free */ -+static void au_do_dfree(struct work_struct *work __maybe_unused) -+{ -+ struct llist_head *head; -+ struct llist_node *node, *next; -+ -+#define AU_CACHE_DFREE_DO_BODY(name, idx, lnode) do { \ -+ head = &au_dfree.cache[AuCache_##idx].llist; \ -+ node = llist_del_all(head); \ -+ for (; node; node = next) { \ -+ struct au_##name *p \ -+ = llist_entry(node, struct au_##name, \ -+ lnode); \ -+ next = llist_next(node); \ -+ au_cache_free_##name(p); \ -+ } \ -+ } while (0) -+ -+ AU_CACHE_DFREE_DO_BODY(dinfo, DINFO, di_lnode); -+ AU_CACHE_DFREE_DO_BODY(icntnr, ICNTNR, lnode); -+ AU_CACHE_DFREE_DO_BODY(finfo, FINFO, fi_lnode); -+ AU_CACHE_DFREE_DO_BODY(vdir, VDIR, vd_lnode); -+ AU_CACHE_DFREE_DO_BODY(vdir_dehstr, DEHSTR, lnode); -+#ifdef CONFIG_AUFS_HNOTIFY -+ AU_CACHE_DFREE_DO_BODY(hnotify, HNOTIFY, hn_lnode); -+#endif -+ -+#define AU_DFREE_DO_BODY(llist, func) do { \ -+ node = llist_del_all(llist); \ -+ for (; node; node = next) { \ -+ next = llist_next(node); \ -+ func(node); \ -+ } \ -+ } while (0) -+ -+ AU_DFREE_DO_BODY(au_dfree.llist + AU_DFREE_KFREE, kfree); -+ AU_DFREE_DO_BODY(au_dfree.llist + AU_DFREE_FREE_PAGE, au_free_page); -+ -+#undef AU_CACHE_DFREE_DO_BODY -+#undef AU_DFREE_DO_BODY -+} -+ -+AU_CACHE_DFREE_FUNC(dinfo, DINFO, di_lnode); -+AU_CACHE_DFREE_FUNC(icntnr, ICNTNR, lnode); -+AU_CACHE_DFREE_FUNC(finfo, FINFO, fi_lnode); -+AU_CACHE_DFREE_FUNC(vdir, VDIR, vd_lnode); -+AU_CACHE_DFREE_FUNC(vdir_dehstr, DEHSTR, lnode); ++struct kmem_cache *au_cache[AuCache_Last]; + +static void au_cache_fin(void) +{ + int i; -+ struct au_cache *cp; + + /* + * Make sure all delayed rcu free inodes are flushed before we @@ -22201,33 +22338,27 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c + + /* excluding AuCache_HNOTIFY */ + BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last); -+ flush_delayed_work(&au_dfree.dwork); + for (i = 0; i < AuCache_HNOTIFY; i++) { -+ cp = au_dfree.cache + i; -+ AuDebugOn(!llist_empty(&cp->llist)); -+ kmem_cache_destroy(cp->cache); -+ cp->cache = NULL; ++ kmem_cache_destroy(au_cache[i]); ++ au_cache[i] = NULL; + } +} + +static int __init au_cache_init(void) +{ -+ struct au_cache *cp; -+ -+ cp = au_dfree.cache; -+ cp[AuCache_DINFO].cache = AuCacheCtor(au_dinfo, au_di_init_once); -+ if (cp[AuCache_DINFO].cache) ++ au_cache[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once); ++ if (au_cache[AuCache_DINFO]) + /* SLAB_DESTROY_BY_RCU */ -+ cp[AuCache_ICNTNR].cache = AuCacheCtor(au_icntnr, ++ au_cache[AuCache_ICNTNR] = AuCacheCtor(au_icntnr, + au_icntnr_init_once); -+ if (cp[AuCache_ICNTNR].cache) -+ cp[AuCache_FINFO].cache = AuCacheCtor(au_finfo, ++ if (au_cache[AuCache_ICNTNR]) ++ au_cache[AuCache_FINFO] = AuCacheCtor(au_finfo, + au_fi_init_once); -+ if (cp[AuCache_FINFO].cache) -+ cp[AuCache_VDIR].cache = AuCache(au_vdir); -+ if (cp[AuCache_VDIR].cache) -+ cp[AuCache_DEHSTR].cache = AuCache(au_vdir_dehstr); -+ if (cp[AuCache_DEHSTR].cache) ++ if (au_cache[AuCache_FINFO]) ++ au_cache[AuCache_VDIR] = AuCache(au_vdir); ++ if (au_cache[AuCache_VDIR]) ++ au_cache[AuCache_DEHSTR] = AuCache(au_vdir_dehstr); ++ if (au_cache[AuCache_DEHSTR]) + return 0; + + au_cache_fin(); @@ -22276,9 +22407,9 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c + int err; + + err = seq_path(seq, path, au_esc_chars); -+ if (err > 0) ++ if (err >= 0) + err = 0; -+ else if (err < 0) ++ else + err = -ENOMEM; + + return err; @@ -22290,7 +22421,6 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c +{ + int err, i; + char *p; -+ struct au_cache *cp; + + p = au_esc_chars; + for (i = 1; i <= ' '; i++) @@ -22305,15 +22435,7 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c + for (i = 0; i < AuIop_Last; i++) + aufs_iop_nogetattr[i].getattr = NULL; + -+ /* First, initialize au_dfree */ -+ for (i = 0; i < AuCache_Last; i++) { /* including hnotify */ -+ cp = au_dfree.cache + i; -+ cp->cache = NULL; -+ init_llist_head(&cp->llist); -+ } -+ for (i = 0; i < AU_DFREE_Last; i++) -+ init_llist_head(au_dfree.llist + i); -+ INIT_DELAYED_WORK(&au_dfree.dwork, au_do_dfree); ++ memset(au_cache, 0, sizeof(au_cache)); /* including hnotify */ + + au_sbilist_init(); + sysaufs_brs_init(); @@ -22365,7 +22487,6 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c +out_sysaufs: + sysaufs_fin(); + au_dy_fin(); -+ flush_delayed_work(&au_dfree.dwork); +out: + return err; +} @@ -22381,17 +22502,16 @@ diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c + au_procfs_fin(); + sysaufs_fin(); + au_dy_fin(); -+ flush_delayed_work(&au_dfree.dwork); +} + +module_init(aufs_init); +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 2016-10-09 16:55:38.889431135 +0200 -@@ -0,0 +1,156 @@ ++++ linux/fs/aufs/module.h 2017-07-29 12:14:25.903042072 +0200 +@@ -0,0 +1,101 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -22417,7 +22537,6 @@ diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h +#ifdef __KERNEL__ + +#include -+#include "debug.h" + +struct path; +struct seq_file; @@ -22456,7 +22575,7 @@ diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h + +/* ---------------------------------------------------------------------- */ + -+/* kmem cache and delayed free */ ++/* kmem cache */ +enum { + AuCache_DINFO, + AuCache_ICNTNR, @@ -22467,28 +22586,7 @@ diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h + AuCache_Last +}; + -+enum { -+ AU_DFREE_KFREE, -+ AU_DFREE_FREE_PAGE, -+ AU_DFREE_Last -+}; -+ -+struct au_cache { -+ struct kmem_cache *cache; -+ struct llist_head llist; /* delayed free */ -+}; -+ -+/* -+ * in order to reduce the cost of the internal timer, consolidate all the -+ * delayed free works into a single delayed_work. -+ */ -+struct au_dfree { -+ struct au_cache cache[AuCache_Last]; -+ struct llist_head llist[AU_DFREE_Last]; -+ struct delayed_work dwork; -+}; -+ -+extern struct au_dfree au_dfree; ++extern struct kmem_cache *au_cache[AuCache_Last]; + +#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD) +#define AuCache(type) KMEM_CACHE(type, AuCacheFlags) @@ -22496,25 +22594,11 @@ diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h + kmem_cache_create(#type, sizeof(struct type), \ + __alignof__(struct type), AuCacheFlags, ctor) + -+#define AU_DFREE_DELAY msecs_to_jiffies(10) -+#define AU_DFREE_BODY(lnode, llist) do { \ -+ if (llist_add(lnode, llist)) \ -+ schedule_delayed_work(&au_dfree.dwork, \ -+ AU_DFREE_DELAY); \ -+ } while (0) -+#define AU_CACHE_DFREE_FUNC(name, idx, lnode) \ -+ void au_cache_dfree_##name(struct au_##name *p) \ -+ { \ -+ struct au_cache *cp = au_dfree.cache + AuCache_##idx; \ -+ AU_DFREE_BODY(&p->lnode, &cp->llist); \ -+ } -+ +#define AuCacheFuncs(name, index) \ +static inline struct au_##name *au_cache_alloc_##name(void) \ -+{ return kmem_cache_alloc(au_dfree.cache[AuCache_##index].cache, GFP_NOFS); } \ ++{ return kmem_cache_alloc(au_cache[AuCache_##index], GFP_NOFS); } \ +static inline void au_cache_free_##name(struct au_##name *p) \ -+{ kmem_cache_free(au_dfree.cache[AuCache_##index].cache, p); } \ -+void au_cache_dfree_##name(struct au_##name *p) ++{ kmem_cache_free(au_cache[AuCache_##index], p); } + +AuCacheFuncs(dinfo, DINFO); +AuCacheFuncs(icntnr, ICNTNR); @@ -22525,33 +22609,14 @@ diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h +AuCacheFuncs(hnotify, HNOTIFY); +#endif + -+static inline void au_delayed_kfree(const void *p) -+{ -+ AuDebugOn(!p); -+ AuDebugOn(ksize(p) < sizeof(struct llist_node)); -+ -+ AU_DFREE_BODY((void *)p, au_dfree.llist + AU_DFREE_KFREE); -+} -+ -+/* cast only */ -+static inline void au_free_page(void *p) -+{ -+ free_page((unsigned long)p); -+} -+ -+static inline void au_delayed_free_page(unsigned long addr) -+{ -+ AU_DFREE_BODY((void *)addr, au_dfree.llist + AU_DFREE_FREE_PAGE); -+} -+ +#endif /* __KERNEL__ */ +#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 2016-10-09 16:55:36.492701639 +0200 ++++ linux/fs/aufs/mvdown.c 2017-07-29 12:14:25.903042072 +0200 @@ -0,0 +1,704 @@ +/* -+ * Copyright (C) 2011-2016 Junjiro R. Okajima ++ * Copyright (C) 2011-2017 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 @@ -23249,17 +23314,17 @@ diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c + e = copy_to_user(uarg, &args->mvdown, sizeof(args->mvdown)); + if (unlikely(e)) + err = -EFAULT; -+ au_delayed_kfree(args); ++ kfree(args); +out: + AuTraceErr(err); + return err; +} 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 2016-12-17 12:28:17.598545045 +0100 -@@ -0,0 +1,1870 @@ ++++ linux/fs/aufs/opts.c 2017-07-29 12:14:25.903042072 +0200 +@@ -0,0 +1,1846 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -23698,28 +23763,6 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + {-1, NULL} +}; + -+/* -+ * cf. linux/lib/parser.c and cmdline.c -+ * gave up calling memparse() since it uses simple_strtoull() instead of -+ * kstrto...(). -+ */ -+static int noinline_for_stack -+au_match_ull(substring_t *s, unsigned long long *result) -+{ -+ int err; -+ unsigned int len; -+ char a[32]; -+ -+ err = -ERANGE; -+ len = s->to - s->from; -+ if (len + 1 <= sizeof(a)) { -+ memcpy(a, s->from, len); -+ a[len] = '\0'; -+ err = kstrtoull(a, 0, result); -+ } -+ return err; -+} -+ +static int au_wbr_mfs_wmark(substring_t *arg, char *str, + struct au_opt_wbr_create *create) +{ @@ -23727,7 +23770,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + unsigned long long ull; + + err = 0; -+ if (!au_match_ull(arg, &ull)) ++ if (!match_u64(arg, &ull)) + create->mfsrr_watermark = ull; + else { + pr_err("bad integer in %s\n", str); @@ -24524,7 +24567,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + } + } + -+ au_delayed_kfree(a); ++ kfree(a); + dump_opts(opts); + if (unlikely(err)) + au_opts_free(opts); @@ -24787,7 +24830,6 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + } + break; + } -+ + return err; +} + @@ -24948,8 +24990,7 @@ diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c + au_hn_inode_unlock(hdir); + + if (!err && do_free) { -+ if (wbr) -+ au_delayed_kfree(wbr); ++ kfree(wbr); + br->br_wbr = NULL; + } + } @@ -25130,10 +25171,10 @@ 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 2016-12-17 12:28:17.598545045 +0100 -@@ -0,0 +1,213 @@ ++++ linux/fs/aufs/opts.h 2017-07-29 12:14:25.903042072 +0200 +@@ -0,0 +1,212 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -25161,7 +25202,6 @@ diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h +#include + +struct file; -+struct super_block; + +/* ---------------------------------------------------------------------- */ + @@ -25347,10 +25387,10 @@ diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h +#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 2016-10-09 16:55:36.496035060 +0200 ++++ linux/fs/aufs/plink.c 2017-07-29 12:14:25.903042072 +0200 @@ -0,0 +1,514 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -25865,10 +25905,10 @@ 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 2016-10-09 16:55:36.496035060 +0200 ++++ linux/fs/aufs/poll.c 2017-07-29 12:14:25.906375514 +0200 @@ -0,0 +1,52 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -25903,7 +25943,7 @@ diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c + sb = file->f_path.dentry->d_sb; + si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW); + -+ h_file = au_read_pre(file, /*keep_fi*/0); ++ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0); + err = PTR_ERR(h_file); + if (IS_ERR(h_file)) + goto out; @@ -25921,10 +25961,10 @@ 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 2016-12-17 12:28:17.598545045 +0100 -@@ -0,0 +1,98 @@ ++++ linux/fs/aufs/posix_acl.c 2017-07-29 12:14:25.906375514 +0200 +@@ -0,0 +1,102 @@ +/* -+ * Copyright (C) 2014-2016 Junjiro R. Okajima ++ * Copyright (C) 2014-2017 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 @@ -25974,6 +26014,8 @@ diff -urN /usr/share/empty/fs/aufs/posix_acl.c linux/fs/aufs/posix_acl.c + + /* always topmost only */ + acl = get_acl(h_inode, type); ++ if (!IS_ERR_OR_NULL(acl)) ++ set_cached_acl(inode, type, acl); + +out: + ii_read_unlock(inode); @@ -26015,18 +26057,20 @@ diff -urN /usr/share/empty/fs/aufs/posix_acl.c linux/fs/aufs/posix_acl.c + ssz = au_sxattr(dentry, inode, &arg); + 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 2016-10-09 16:55:36.496035060 +0200 ++++ linux/fs/aufs/procfs.c 2017-07-29 12:14:25.906375514 +0200 @@ -0,0 +1,169 @@ +/* -+ * Copyright (C) 2010-2016 Junjiro R. Okajima ++ * Copyright (C) 2010-2017 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 @@ -26196,10 +26240,10 @@ 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 2016-10-09 16:55:36.496035060 +0200 ++++ linux/fs/aufs/rdu.c 2017-07-29 12:14:25.906375514 +0200 @@ -0,0 +1,381 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -26581,10 +26625,10 @@ 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 2016-10-09 16:55:36.496035060 +0200 ++++ linux/fs/aufs/rwsem.h 2017-07-29 12:14:25.906375514 +0200 @@ -0,0 +1,198 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -26783,10 +26827,10 @@ 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 2016-10-09 16:55:38.889431135 +0200 -@@ -0,0 +1,355 @@ ++++ linux/fs/aufs/sbinfo.c 2017-07-29 12:14:25.906375514 +0200 +@@ -0,0 +1,304 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -26831,15 +26875,11 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c + au_br_free(sbinfo); + au_rw_write_unlock(&sbinfo->si_rwsem); + -+ au_delayed_kfree(sbinfo->si_branch); -+ for (i = 0; i < AU_NPIDMAP; i++) -+ if (sbinfo->au_si_pid.pid_bitmap[i]) -+ au_delayed_kfree(sbinfo->au_si_pid.pid_bitmap[i]); -+ mutex_destroy(&sbinfo->au_si_pid.pid_mtx); ++ kfree(sbinfo->si_branch); + mutex_destroy(&sbinfo->si_xib_mtx); + AuRwDestroy(&sbinfo->si_rwsem); + -+ au_delayed_kfree(sbinfo); ++ kfree(sbinfo); +} + +int au_si_alloc(struct super_block *sb) @@ -26863,7 +26903,6 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c + + au_nwt_init(&sbinfo->si_nowait); + au_rw_init_wlock(&sbinfo->si_rwsem); -+ mutex_init(&sbinfo->au_si_pid.pid_mtx); + + percpu_counter_init(&sbinfo->si_ninodes, 0, GFP_NOFS); + percpu_counter_init(&sbinfo->si_nfiles, 0, GFP_NOFS); @@ -26911,9 +26950,9 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c + return 0; /* success */ + +out_br: -+ au_delayed_kfree(sbinfo->si_branch); ++ kfree(sbinfo->si_branch); +out_sbinfo: -+ au_delayed_kfree(sbinfo); ++ kfree(sbinfo); +out: + return err; +} @@ -27094,58 +27133,12 @@ diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c + di_write_unlock2(d1, d2); + si_read_unlock(d1->d_sb); +} -+ -+/* ---------------------------------------------------------------------- */ -+ -+static void si_pid_alloc(struct au_si_pid *au_si_pid, int idx) -+{ -+ unsigned long *p; -+ -+ BUILD_BUG_ON(sizeof(unsigned long) != -+ sizeof(*au_si_pid->pid_bitmap)); -+ -+ mutex_lock(&au_si_pid->pid_mtx); -+ p = au_si_pid->pid_bitmap[idx]; -+ while (!p) { -+ /* -+ * bad approach. -+ * but keeping 'si_pid_set()' void is more important. -+ */ -+ p = kcalloc(BITS_TO_LONGS(AU_PIDSTEP), -+ sizeof(*au_si_pid->pid_bitmap), -+ GFP_NOFS); -+ if (p) -+ break; -+ cond_resched(); -+ } -+ au_si_pid->pid_bitmap[idx] = p; -+ mutex_unlock(&au_si_pid->pid_mtx); -+} -+ -+void si_pid_set(struct super_block *sb) -+{ -+ pid_t bit; -+ int idx; -+ unsigned long *bitmap; -+ struct au_si_pid *au_si_pid; -+ -+ si_pid_idx_bit(&idx, &bit); -+ au_si_pid = &au_sbi(sb)->au_si_pid; -+ bitmap = au_si_pid->pid_bitmap[idx]; -+ if (!bitmap) { -+ si_pid_alloc(au_si_pid, idx); -+ bitmap = au_si_pid->pid_bitmap[idx]; -+ } -+ AuDebugOn(test_bit(bit, bitmap)); -+ set_bit(bit, bitmap); -+ /* smp_mb(); */ -+} diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h --- /usr/share/empty/fs/aufs/spl.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux/fs/aufs/spl.h 2016-10-09 16:55:36.496035060 +0200 ++++ linux/fs/aufs/spl.h 2017-07-29 12:14:25.906375514 +0200 @@ -0,0 +1,113 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -27259,10 +27252,10 @@ diff -urN /usr/share/empty/fs/aufs/spl.h linux/fs/aufs/spl.h +#endif /* __AUFS_SPL_H__ */ 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 2016-12-17 12:28:17.598545045 +0100 -@@ -0,0 +1,1046 @@ ++++ linux/fs/aufs/super.c 2017-07-29 12:14:25.906375514 +0200 +@@ -0,0 +1,1044 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -27309,7 +27302,7 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c +{ + struct inode *inode = container_of(head, struct inode, i_rcu); + -+ au_cache_dfree_icntnr(container_of(inode, struct au_icntnr, vfs_inode)); ++ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode)); +} + +static void aufs_destroy_inode(struct inode *inode) @@ -27710,12 +27703,10 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c + continue; + + h_sb = au_sbr_sb(sb, bindex); -+ if (h_sb->s_op->sync_fs) { -+ e = h_sb->s_op->sync_fs(h_sb, wait); -+ if (unlikely(e && !err)) -+ err = e; -+ /* go on even if an error happens */ -+ } ++ e = vfsub_sync_filesystem(h_sb, wait); ++ if (unlikely(e && !err)) ++ err = e; ++ /* go on even if an error happens */ + } + si_read_unlock(sb); + @@ -28099,7 +28090,7 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c +out_mtx: + inode_unlock(inode); +out_opts: -+ au_delayed_free_page((unsigned long)opts.opt); ++ free_page((unsigned long)opts.opt); +out: + err = cvt_err(err); + AuTraceErr(err); @@ -28240,7 +28231,7 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c + kobject_put(&sbinfo->si_kobj); + sb->s_fs_info = NULL; +out_opts: -+ au_delayed_free_page((unsigned long)opts.opt); ++ free_page((unsigned long)opts.opt); +out: + AuTraceErr(err); + err = cvt_err(err); @@ -28309,10 +28300,10 @@ diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c +}; 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 2016-12-17 12:28:17.598545045 +0100 -@@ -0,0 +1,639 @@ ++++ linux/fs/aufs/super.h 2017-07-29 12:14:25.906375514 +0200 +@@ -0,0 +1,617 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -28392,13 +28383,6 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h +#endif +}; + -+#define AU_PIDSTEP (int)(BITS_TO_LONGS(PID_MAX_DEFAULT) * BITS_PER_LONG) -+#define AU_NPIDMAP (int)DIV_ROUND_UP(PID_MAX_LIMIT, AU_PIDSTEP) -+struct au_si_pid { -+ unsigned long *pid_bitmap[AU_NPIDMAP]; -+ struct mutex pid_mtx; -+}; -+ +struct au_branch; +struct au_sbinfo { + /* nowait tasks in the system-wide workqueue */ @@ -28410,9 +28394,6 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h + */ + struct au_rwsem si_rwsem; + -+ /* prevent recursive locking in deleting inode */ -+ struct au_si_pid au_si_pid; -+ + /* + * dirty approach to protect sb->sb_inodes and ->s_files (gone) from + * remount. @@ -28754,42 +28735,30 @@ diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h + +/* ---------------------------------------------------------------------- */ + -+static inline void si_pid_idx_bit(int *idx, pid_t *bit) -+{ -+ /* the origin of pid is 1, but the bitmap's is 0 */ -+ *bit = current->pid - 1; -+ *idx = *bit / AU_PIDSTEP; -+ *bit %= AU_PIDSTEP; -+} ++/* current->atomic_flags */ ++/* this value should never corrupt the ones defined in linux/sched.h */ ++#define PFA_AUFS 7 ++ ++TASK_PFA_TEST(AUFS, test_aufs) /* task_test_aufs */ ++TASK_PFA_SET(AUFS, aufs) /* task_set_aufs */ ++TASK_PFA_CLEAR(AUFS, aufs) /* task_clear_aufs */ + +static inline int si_pid_test(struct super_block *sb) +{ -+ pid_t bit; -+ int idx; -+ unsigned long *bitmap; -+ -+ si_pid_idx_bit(&idx, &bit); -+ bitmap = au_sbi(sb)->au_si_pid.pid_bitmap[idx]; -+ if (bitmap) -+ return test_bit(bit, bitmap); -+ return 0; ++ return !!task_test_aufs(current); +} + +static inline void si_pid_clr(struct super_block *sb) +{ -+ pid_t bit; -+ int idx; -+ unsigned long *bitmap; -+ -+ si_pid_idx_bit(&idx, &bit); -+ bitmap = au_sbi(sb)->au_si_pid.pid_bitmap[idx]; -+ BUG_ON(!bitmap); -+ AuDebugOn(!test_bit(bit, bitmap)); -+ clear_bit(bit, bitmap); -+ /* smp_mb(); */ ++ AuDebugOn(!task_test_aufs(current)); ++ task_clear_aufs(current); +} + -+void si_pid_set(struct super_block *sb); ++static inline void si_pid_set(struct super_block *sb) ++{ ++ AuDebugOn(task_test_aufs(current)); ++ task_set_aufs(current); ++} + +/* ---------------------------------------------------------------------- */ + @@ -28952,10 +28921,10 @@ 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 2016-10-09 16:55:36.496035060 +0200 ++++ linux/fs/aufs/sysaufs.c 2017-07-29 12:14:25.906375514 +0200 @@ -0,0 +1,104 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -29060,10 +29029,10 @@ 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 2016-10-09 16:55:36.496035060 +0200 ++++ linux/fs/aufs/sysaufs.h 2017-07-29 12:14:25.906375514 +0200 @@ -0,0 +1,101 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -29165,10 +29134,10 @@ 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 2016-10-09 16:55:36.496035060 +0200 ++++ linux/fs/aufs/sysfs.c 2017-07-29 12:14:25.906375514 +0200 @@ -0,0 +1,376 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -29378,7 +29347,7 @@ diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c + if (unlikely(err == PAGE_SIZE)) + err = -EFBIG; + } -+ au_delayed_kfree(seq); ++ kfree(seq); +out_unlock: + si_read_unlock(sb); +out: @@ -29449,9 +29418,9 @@ diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c + err = -EFAULT; + +out_seq: -+ au_delayed_kfree(seq); ++ kfree(seq); +out_buf: -+ au_delayed_free_page((unsigned long)buf); ++ free_page((unsigned long)buf); +out: + si_read_unlock(sb); + return err; @@ -29545,10 +29514,10 @@ 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 2016-10-09 16:55:36.496035060 +0200 ++++ linux/fs/aufs/sysrq.c 2017-07-29 12:14:25.906375514 +0200 @@ -0,0 +1,157 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -29706,10 +29675,10 @@ 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 2016-10-09 16:55:38.889431135 +0200 -@@ -0,0 +1,900 @@ ++++ linux/fs/aufs/vdir.c 2017-07-29 12:14:25.906375514 +0200 +@@ -0,0 +1,892 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -29820,7 +29789,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c + struct hlist_node *node; + + hlist_for_each_entry_safe(pos, node, head, wh_hash) -+ au_delayed_kfree(pos); ++ kfree(pos); +} + +static void au_nhash_de_do_free(struct hlist_head *head) @@ -29829,7 +29798,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c + struct hlist_node *node; + + hlist_for_each_entry_safe(pos, node, head, hash) -+ au_cache_dfree_vdir_dehstr(pos); ++ au_cache_free_vdir_dehstr(pos); +} + +static void au_nhash_do_free(struct au_nhash *nhash, @@ -29847,7 +29816,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c + nhash_count(head); + free(head++); + } -+ au_delayed_kfree(nhash->nh_head); ++ kfree(nhash->nh_head); +} + +void au_nhash_wh_free(struct au_nhash *whlist) @@ -30060,23 +30029,15 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c + +/* ---------------------------------------------------------------------- */ + -+void au_vdir_free(struct au_vdir *vdir, int atonce) ++void au_vdir_free(struct au_vdir *vdir) +{ + unsigned char **deblk; + + deblk = vdir->vd_deblk; -+ if (!atonce) { -+ while (vdir->vd_nblk--) -+ au_delayed_kfree(*deblk++); -+ au_delayed_kfree(vdir->vd_deblk); -+ au_cache_dfree_vdir(vdir); -+ } else { -+ /* not delayed */ -+ while (vdir->vd_nblk--) -+ kfree(*deblk++); -+ kfree(vdir->vd_deblk); -+ au_cache_free_vdir(vdir); -+ } ++ while (vdir->vd_nblk--) ++ kfree(*deblk++); ++ kfree(vdir->vd_deblk); ++ au_cache_free_vdir(vdir); +} + +static struct au_vdir *alloc_vdir(struct file *file) @@ -30110,10 +30071,10 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c + if (!err) + return vdir; /* success */ + -+ au_delayed_kfree(vdir->vd_deblk); ++ kfree(vdir->vd_deblk); + +out_free: -+ au_cache_dfree_vdir(vdir); ++ au_cache_free_vdir(vdir); +out: + vdir = ERR_PTR(err); + return vdir; @@ -30125,7 +30086,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c + union au_vdir_deblk_p p, deblk_end; + + while (vdir->vd_nblk > 1) { -+ au_delayed_kfree(vdir->vd_deblk[vdir->vd_nblk - 1]); ++ kfree(vdir->vd_deblk[vdir->vd_nblk - 1]); + /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */ + vdir->vd_nblk--; + } @@ -30256,7 +30217,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c + } + } + -+ au_delayed_free_page((unsigned long)o); ++ free_page((unsigned long)o); + +out: + AuTraceErr(err); @@ -30395,7 +30356,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c + if (allocated) + au_set_ivdir(inode, allocated); + } else if (allocated) -+ au_vdir_free(allocated, /*atonce*/0); ++ au_vdir_free(allocated); + +out: + return err; @@ -30490,7 +30451,7 @@ diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c + if (allocated) + au_set_fvdir_cache(file, allocated); + } else if (allocated) -+ au_vdir_free(allocated, /*atonce*/0); ++ au_vdir_free(allocated); + +out: + return err; @@ -30610,10 +30571,10 @@ 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 2016-12-17 12:28:17.598545045 +0100 -@@ -0,0 +1,886 @@ ++++ linux/fs/aufs/vfsub.c 2017-07-29 12:14:25.906375514 +0200 +@@ -0,0 +1,900 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -30656,6 +30617,19 @@ 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 err; ++ ++ lockdep_off(); ++ down_read(&h_sb->s_umount); ++ err = __sync_filesystem(h_sb, wait); ++ up_read(&h_sb->s_umount); ++ lockdep_on(); ++ ++ return err; ++} ++ +/* ---------------------------------------------------------------------- */ + +int vfsub_update_h_iattr(struct path *h_path, int *did) @@ -30673,7 +30647,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c + h_sb = h_path->dentry->d_sb; + *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb)); + if (*did) -+ err = vfs_getattr(h_path, &st); ++ err = vfsub_getattr(h_path, &st); + + return err; +} @@ -31199,6 +31173,7 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c + lockdep_on(); + if (err >= 0) + vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/ ++ + return err; +} + @@ -31500,10 +31475,10 @@ 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 2016-12-17 12:28:17.598545045 +0100 -@@ -0,0 +1,316 @@ ++++ linux/fs/aufs/vfsub.h 2017-07-29 12:14:25.906375514 +0200 +@@ -0,0 +1,353 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -31587,6 +31562,8 @@ 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_update_h_iattr(struct path *h_path, int *did); @@ -31768,6 +31745,36 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h + struct file *h_file); +int vfsub_fsync(struct file *file, struct path *path, int datasync); + ++/* ++ * re-use branch fs's ioctl(FICLONE) while aufs itself doesn't support such ++ * ioctl. ++ */ ++static inline int vfsub_clone_file_range(struct file *src, struct file *dst, ++ u64 len) ++{ ++ int err; ++ ++ lockdep_off(); ++ err = vfs_clone_file_range(src, 0, dst, 0, len); ++ lockdep_on(); ++ ++ return err; ++} ++ ++/* copy_file_range(2) is a systemcall */ ++static inline ssize_t vfsub_copy_file_range(struct file *src, loff_t src_pos, ++ struct file *dst, loff_t dst_pos, ++ size_t len, unsigned int flags) ++{ ++ ssize_t ssz; ++ ++ lockdep_off(); ++ ssz = vfs_copy_file_range(src, src_pos, dst, dst_pos, len, flags); ++ lockdep_on(); ++ ++ return ssz; ++} ++ +/* ---------------------------------------------------------------------- */ + +static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin) @@ -31791,6 +31798,11 @@ diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h +int vfsub_unlink(struct inode *dir, struct path *path, + struct inode **delegated_inode, int force); + ++static inline int vfsub_getattr(const struct path *path, struct kstat *st) ++{ ++ return vfs_getattr(path, st, STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT); ++} ++ +/* ---------------------------------------------------------------------- */ + +static inline int vfsub_setxattr(struct dentry *dentry, const char *name, @@ -31820,10 +31832,10 @@ 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 2016-12-17 12:28:17.598545045 +0100 ++++ linux/fs/aufs/wbr_policy.c 2017-07-29 12:14:25.906375514 +0200 @@ -0,0 +1,830 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -32285,7 +32297,7 @@ diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c + + mfs->mfsrr_bytes = bavail; + AuDbg("b%d\n", mfs->mfs_bindex); -+ au_delayed_kfree(st); ++ kfree(st); +} + +static int au_wbr_create_mfs(struct dentry *dentry, unsigned int flags) @@ -32654,10 +32666,10 @@ 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 2016-12-17 12:28:17.598545045 +0100 ++++ linux/fs/aufs/whout.c 2017-07-29 12:14:25.906375514 +0200 @@ -0,0 +1,1061 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -32820,7 +32832,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c + +out_name: + if (name != defname) -+ au_delayed_kfree(name); ++ kfree(name); +out: + AuTraceErrPtr(dentry); + return dentry; @@ -33260,7 +33272,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c + au_br_put(a->br); + si_write_unlock(a->sb); + au_nwt_done(&au_sbi(a->sb)->si_nowait); -+ au_delayed_kfree(arg); ++ kfree(arg); + if (unlikely(err)) + AuIOErr("err %d\n", err); +} @@ -33288,7 +33300,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c + if (unlikely(wkq_err)) { + atomic_dec(&br->br_wbr->wbr_wh_running); + au_br_put(br); -+ au_delayed_kfree(arg); ++ kfree(arg); + } + do_dec = 0; + } @@ -33447,7 +33459,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c + wh_dentry = ERR_PTR(err); + if (!err) { + wh_dentry = vfsub_lkup_one(&wh_name, h_parent); -+ au_delayed_kfree(wh_name.name); ++ kfree(wh_name.name); + } + return wh_dentry; +} @@ -33523,7 +33535,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c + break; + } + } -+ au_delayed_free_page((unsigned long)wh_name.name); ++ free_page((unsigned long)wh_name.name); + +out: + return err; @@ -33565,7 +33577,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c + rdhash = AUFS_RDHASH_DEF; + err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp); + if (unlikely(err)) { -+ au_delayed_kfree(whtmp); ++ kfree(whtmp); + whtmp = ERR_PTR(err); + } + @@ -33580,7 +33592,7 @@ diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c + dput(whtmp->wh_dentry); + iput(whtmp->dir); + au_nhash_wh_free(&whtmp->whlist); -+ au_delayed_kfree(whtmp); ++ kfree(whtmp); +} + +/* @@ -33719,10 +33731,10 @@ 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 2016-10-09 16:55:36.496035060 +0200 -@@ -0,0 +1,85 @@ ++++ linux/fs/aufs/whout.h 2017-07-29 12:14:25.906375514 +0200 +@@ -0,0 +1,84 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -33753,7 +33765,6 @@ diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h +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); -+struct au_branch; +struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br, + struct qstr *prefix); +int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br); @@ -33808,10 +33819,10 @@ 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 2016-10-09 16:55:36.496035060 +0200 ++++ linux/fs/aufs/wkq.c 2017-07-29 12:14:25.906375514 +0200 @@ -0,0 +1,213 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -33866,7 +33877,7 @@ diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c + else { + kobject_put(wkinfo->kobj); + module_put(THIS_MODULE); /* todo: ?? */ -+ au_delayed_kfree(wkinfo); ++ kfree(wkinfo); + } +} + @@ -33889,7 +33900,7 @@ diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c + +static void au_wkq_comp_free(struct completion *comp) +{ -+ au_delayed_kfree(comp); ++ kfree(comp); +} + +#else @@ -34025,10 +34036,10 @@ 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 2016-10-09 16:55:36.496035060 +0200 ++++ linux/fs/aufs/wkq.h 2017-07-29 12:14:25.906375514 +0200 @@ -0,0 +1,93 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -34122,10 +34133,10 @@ 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 2016-12-17 12:28:17.598545045 +0100 -@@ -0,0 +1,332 @@ ++++ linux/fs/aufs/xattr.c 2017-07-29 12:14:25.906375514 +0200 +@@ -0,0 +1,357 @@ +/* -+ * Copyright (C) 2014-2016 Junjiro R. Okajima ++ * Copyright (C) 2014-2017 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 @@ -34145,6 +34156,8 @@ diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c + * handling xattr functions + */ + ++#include ++#include +#include +#include "aufs.h" + @@ -34303,11 +34316,11 @@ diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c + } + + if (value) -+ au_delayed_kfree(value); ++ kfree(value); + +out_free: + if (o) -+ au_delayed_kfree(o); ++ kfree(o); +out: + if (!unlocked) + inode_unlock(h_isrc); @@ -34317,6 +34330,19 @@ 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) ++ /* ++ * as a part of lookup, smack_d_instantiate() is called, and it calls ++ * i_op->getxattr(). ouch. ++ */ ++ return si_pid_test(sb); ++#else ++ return 0; ++#endif ++} ++ +enum { + AU_XATTR_LIST, + AU_XATTR_GET @@ -34340,14 +34366,18 @@ diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c +static ssize_t au_lgxattr(struct dentry *dentry, struct au_lgxattr *arg) +{ + ssize_t err; ++ int reenter; + struct path h_path; + struct super_block *sb; + + sb = dentry->d_sb; -+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); -+ if (unlikely(err)) -+ goto out; -+ err = au_h_path_getattr(dentry, /*force*/1, &h_path); ++ reenter = au_smack_reentering(sb); ++ if (!reenter) { ++ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM); ++ if (unlikely(err)) ++ goto out; ++ } ++ err = au_h_path_getattr(dentry, /*force*/1, &h_path, reenter); + if (unlikely(err)) + goto out_si; + if (unlikely(!h_path.dentry)) @@ -34369,9 +34399,11 @@ diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c + } + +out_di: -+ di_read_unlock(dentry, AuLock_IR); ++ if (!reenter) ++ di_read_unlock(dentry, AuLock_IR); +out_si: -+ si_read_unlock(sb); ++ if (!reenter) ++ si_read_unlock(sb); +out: + AuTraceErr(err); + return err; @@ -34448,7 +34480,11 @@ diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c +}; + +static const struct xattr_handler *au_xattr_handlers[] = { -+ &au_xattr_handler, ++#ifdef CONFIG_FS_POSIX_ACL ++ &posix_acl_access_xattr_handler, ++ &posix_acl_default_xattr_handler, ++#endif ++ &au_xattr_handler, /* must be last */ + NULL +}; + @@ -34458,10 +34494,10 @@ 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 2016-10-09 16:55:36.496035060 +0200 -@@ -0,0 +1,1318 @@ ++++ linux/fs/aufs/xino.c 2017-07-29 12:14:25.906375514 +0200 +@@ -0,0 +1,1415 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -34800,7 +34836,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + AuErr1("statfs err %d, ignored\n", err); + +out_st: -+ au_delayed_kfree(st); ++ kfree(st); +out: + return err; +} @@ -34835,7 +34871,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + au_br_put(br); + si_write_unlock(sb); + au_nwt_done(&au_sbi(sb)->si_nowait); -+ au_delayed_kfree(args); ++ kfree(args); +} + +static int xino_trunc_test(struct super_block *sb, struct au_branch *br) @@ -34889,7 +34925,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + + pr_err("wkq %d\n", wkq_err); + au_br_put(br); -+ au_delayed_kfree(args); ++ kfree(args); + +out: + atomic_dec(&br->br_xino_running); @@ -35413,7 +35449,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + (sb, au_sbr(sb, bindex)->br_xino.xi_file, page); + else + AuDbg("b%d\n", bindex); -+ au_delayed_free_page((unsigned long)page); ++ free_page((unsigned long)page); + +out: + return err; @@ -35491,7 +35527,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + fput(sbinfo->si_xib); + sbinfo->si_xib = NULL; + if (sbinfo->si_xib_buf) -+ au_delayed_free_page((unsigned long)sbinfo->si_xib_buf); ++ free_page((unsigned long)sbinfo->si_xib_buf); + sbinfo->si_xib_buf = NULL; +} + @@ -35535,7 +35571,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + +out_free: + if (sbinfo->si_xib_buf) -+ au_delayed_free_page((unsigned long)sbinfo->si_xib_buf); ++ free_page((unsigned long)sbinfo->si_xib_buf); + sbinfo->si_xib_buf = NULL; + if (err >= 0) + err = -EIO; @@ -35628,7 +35664,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + fput(p->new); + else + break; -+ au_delayed_kfree(fpair); ++ kfree(fpair); +out: + return err; +} @@ -35739,7 +35775,7 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c + if (!IS_ERR(file)) + au_xino_brid_set(sb, br->br_id); + } -+ au_delayed_free_page((unsigned long)page); ++ free_page((unsigned long)page); + } else { + file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0); + if (IS_ERR(file)) @@ -35778,12 +35814,109 @@ diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c +out: + return err; +} ++ ++/* ---------------------------------------------------------------------- */ ++ ++void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex, ++ ino_t h_ino, int idx) ++{ ++ struct au_xino_file *xino; ++ ++ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO)); ++ xino = &au_sbr(sb, bindex)->br_xino; ++ AuDebugOn(idx < 0 || xino->xi_nondir.total <= idx); ++ ++ spin_lock(&xino->xi_nondir.spin); ++ AuDebugOn(xino->xi_nondir.array[idx] != h_ino); ++ xino->xi_nondir.array[idx] = 0; ++ spin_unlock(&xino->xi_nondir.spin); ++ wake_up_all(&xino->xi_nondir.wqh); ++} ++ ++static int au_xinondir_find(struct au_xino_file *xino, ino_t h_ino) ++{ ++ int found, total, i; ++ ++ found = -1; ++ total = xino->xi_nondir.total; ++ for (i = 0; i < total; i++) { ++ if (xino->xi_nondir.array[i] != h_ino) ++ continue; ++ found = i; ++ break; ++ } ++ ++ return found; ++} ++ ++static int au_xinondir_expand(struct au_xino_file *xino) ++{ ++ int err, sz; ++ ino_t *p; ++ ++ BUILD_BUG_ON(KMALLOC_MAX_SIZE > INT_MAX); ++ ++ err = -ENOMEM; ++ sz = xino->xi_nondir.total * sizeof(ino_t); ++ if (unlikely(sz > KMALLOC_MAX_SIZE / 2)) ++ goto out; ++ p = au_kzrealloc(xino->xi_nondir.array, sz, sz << 1, GFP_ATOMIC, ++ /*may_shrink*/0); ++ if (p) { ++ xino->xi_nondir.array = p; ++ xino->xi_nondir.total <<= 1; ++ AuDbg("xi_nondir.total %d\n", xino->xi_nondir.total); ++ err = 0; ++ } ++ ++out: ++ return err; ++} ++ ++int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino, ++ int *idx) ++{ ++ int err, found, empty; ++ struct au_xino_file *xino; ++ ++ err = 0; ++ *idx = -1; ++ if (!au_opt_test(au_mntflags(sb), XINO)) ++ goto out; /* no xino */ ++ ++ xino = &au_sbr(sb, bindex)->br_xino; ++ ++again: ++ spin_lock(&xino->xi_nondir.spin); ++ found = au_xinondir_find(xino, h_ino); ++ if (found == -1) { ++ empty = au_xinondir_find(xino, /*h_ino*/0); ++ if (empty == -1) { ++ empty = xino->xi_nondir.total; ++ err = au_xinondir_expand(xino); ++ if (unlikely(err)) ++ goto out_unlock; ++ } ++ xino->xi_nondir.array[empty] = h_ino; ++ *idx = empty; ++ } else { ++ spin_unlock(&xino->xi_nondir.spin); ++ wait_event(xino->xi_nondir.wqh, ++ xino->xi_nondir.array[found] != h_ino); ++ goto again; ++ } ++ ++out_unlock: ++ spin_unlock(&xino->xi_nondir.spin); ++out: ++ return err; ++} 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 2016-12-17 12:28:38.769494865 +0100 ++++ linux/include/uapi/linux/aufs_type.h 2017-07-29 12:14:32.526591175 +0200 @@ -0,0 +1,419 @@ +/* -+ * Copyright (C) 2005-2016 Junjiro R. Okajima ++ * Copyright (C) 2005-2017 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 @@ -35823,7 +35956,7 @@ diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/lin + +#include + -+#define AUFS_VERSION "4.9-20161219" ++#define AUFS_VERSION "4.x-rcN-20170703" + +/* todo? move this to linux-2.6.19/include/magic.h */ +#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's') @@ -36201,13 +36334,13 @@ diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/lin +#define AUFS_CTL_FHSM_FD _IOW(AuCtlType, AuCtl_FHSM_FD, int) + +#endif /* __AUFS_TYPE_H__ */ -aufs4.9 loopback patch +aufs4.x-rcN loopback patch diff --git a/drivers/block/loop.c b/drivers/block/loop.c -index 6ee9235..f64161f 100644 +index 6b8a6a4c..a80416e 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c -@@ -551,7 +551,7 @@ static int do_req_filebacked(struct loop_device *lo, struct request *rq) +@@ -547,7 +547,7 @@ static int do_req_filebacked(struct loop_device *lo, struct request *rq) } struct switch_request { @@ -36216,7 +36349,7 @@ index 6ee9235..f64161f 100644 struct completion wait; }; -@@ -577,6 +577,7 @@ static void do_loop_switch(struct loop_device *lo, struct switch_request *p) +@@ -573,6 +573,7 @@ static void do_loop_switch(struct loop_device *lo, struct switch_request *p) mapping = file->f_mapping; mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask); lo->lo_backing_file = file; @@ -36224,7 +36357,7 @@ index 6ee9235..f64161f 100644 lo->lo_blocksize = S_ISBLK(mapping->host->i_mode) ? mapping->host->i_bdev->bd_block_size : PAGE_SIZE; lo->old_gfp_mask = mapping_gfp_mask(mapping); -@@ -589,11 +590,13 @@ static void do_loop_switch(struct loop_device *lo, struct switch_request *p) +@@ -585,11 +586,13 @@ static void do_loop_switch(struct loop_device *lo, struct switch_request *p) * First it needs to flush existing IO, it does this by sending a magic * BIO down the pipe. The completion of this BIO does the actual switch. */ @@ -36239,14 +36372,10 @@ index 6ee9235..f64161f 100644 /* freeze queue and wait for completion of scheduled requests */ blk_mq_freeze_queue(lo->lo_queue); -@@ -612,7 +615,16 @@ static int loop_switch(struct loop_device *lo, struct file *file) - */ - static int loop_flush(struct loop_device *lo) - { -- return loop_switch(lo, NULL); -+ return loop_switch(lo, NULL, NULL); -+} -+ +@@ -614,6 +617,15 @@ static int loop_flush(struct loop_device *lo) + return loop_switch(lo, NULL); + } + +static struct file *loop_real_file(struct file *file) +{ + struct file *f = NULL; @@ -36254,10 +36383,12 @@ index 6ee9235..f64161f 100644 + if (file->f_path.dentry->d_sb->s_op->real_loop) + f = file->f_path.dentry->d_sb->s_op->real_loop(file); + return f; - } - ++} ++ static void loop_reread_partitions(struct loop_device *lo, -@@ -649,6 +661,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, + struct block_device *bdev) + { +@@ -648,6 +660,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, unsigned int arg) { struct file *file, *old_file; @@ -36265,7 +36396,7 @@ index 6ee9235..f64161f 100644 struct inode *inode; int error; -@@ -665,9 +678,16 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, +@@ -664,9 +677,16 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, file = fget(arg); if (!file) goto out; @@ -36282,7 +36413,7 @@ index 6ee9235..f64161f 100644 error = -EINVAL; -@@ -679,17 +699,21 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, +@@ -678,17 +698,21 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, goto out_putf; /* and ... switch */ @@ -36305,7 +36436,7 @@ index 6ee9235..f64161f 100644 out: return error; } -@@ -876,7 +900,7 @@ static int loop_prepare_queue(struct loop_device *lo) +@@ -875,7 +899,7 @@ static int loop_prepare_queue(struct loop_device *lo) static int loop_set_fd(struct loop_device *lo, fmode_t mode, struct block_device *bdev, unsigned int arg) { @@ -36314,7 +36445,7 @@ index 6ee9235..f64161f 100644 struct inode *inode; struct address_space *mapping; unsigned lo_blocksize; -@@ -891,6 +915,12 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, +@@ -890,6 +914,12 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, file = fget(arg); if (!file) goto out; @@ -36327,7 +36458,7 @@ index 6ee9235..f64161f 100644 error = -EBUSY; if (lo->lo_state != Lo_unbound) -@@ -943,6 +973,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, +@@ -942,6 +972,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, lo->lo_device = bdev; lo->lo_flags = lo_flags; lo->lo_backing_file = file; @@ -36335,7 +36466,7 @@ index 6ee9235..f64161f 100644 lo->transfer = NULL; lo->ioctl = NULL; lo->lo_sizelimit = 0; -@@ -975,6 +1006,8 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, +@@ -974,6 +1005,8 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, out_putf: fput(file); @@ -36344,7 +36475,7 @@ index 6ee9235..f64161f 100644 out: /* This is safe: open() is still holding a reference. */ module_put(THIS_MODULE); -@@ -1021,6 +1054,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, +@@ -1020,6 +1053,7 @@ loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer, static int loop_clr_fd(struct loop_device *lo) { struct file *filp = lo->lo_backing_file; @@ -36352,7 +36483,7 @@ index 6ee9235..f64161f 100644 gfp_t gfp = lo->old_gfp_mask; struct block_device *bdev = lo->lo_device; -@@ -1052,6 +1086,7 @@ static int loop_clr_fd(struct loop_device *lo) +@@ -1051,6 +1085,7 @@ static int loop_clr_fd(struct loop_device *lo) spin_lock_irq(&lo->lo_lock); lo->lo_state = Lo_rundown; lo->lo_backing_file = NULL; @@ -36360,7 +36491,7 @@ index 6ee9235..f64161f 100644 spin_unlock_irq(&lo->lo_lock); loop_release_xfer(lo); -@@ -1096,6 +1131,8 @@ static int loop_clr_fd(struct loop_device *lo) +@@ -1095,6 +1130,8 @@ static int loop_clr_fd(struct loop_device *lo) * bd_mutex which is usually taken before lo_ctl_mutex. */ fput(filp); @@ -36370,7 +36501,7 @@ index 6ee9235..f64161f 100644 } diff --git a/drivers/block/loop.h b/drivers/block/loop.h -index fb2237c..c3888c5 100644 +index fecd3f9..6b3a7c9 100644 --- a/drivers/block/loop.h +++ b/drivers/block/loop.h @@ -46,7 +46,7 @@ struct loop_device { @@ -36383,10 +36514,10 @@ index fb2237c..c3888c5 100644 unsigned lo_blocksize; void *key_data; diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c -index d2a9a1d..d7519d0 100644 +index 870717e..ea7fee0 100644 --- a/fs/aufs/f_op.c +++ b/fs/aufs/f_op.c -@@ -351,7 +351,7 @@ static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter) +@@ -357,7 +357,7 @@ static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter) if (IS_ERR(h_file)) goto out; @@ -36396,12 +36527,12 @@ index d2a9a1d..d7519d0 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 c3ca50f..a3dbdaf 100644 +index e35f015..b37f1ae 100644 --- a/fs/aufs/loop.c +++ b/fs/aufs/loop.c @@ -132,3 +132,19 @@ void au_loopback_fin(void) symbol_put(loop_backing_file); - au_delayed_kfree(au_warn_loopback_array); + kfree(au_warn_loopback_array); } + +/* ---------------------------------------------------------------------- */ @@ -36420,10 +36551,10 @@ index c3ca50f..a3dbdaf 100644 + return f; +} diff --git a/fs/aufs/loop.h b/fs/aufs/loop.h -index 48bf070..66afec7 100644 +index e2df495..36e5052 100644 --- a/fs/aufs/loop.h +++ b/fs/aufs/loop.h -@@ -25,7 +25,11 @@ +@@ -25,7 +25,11 @@ void au_warn_loopback(struct super_block *h_sb); int au_loopback_init(void); void au_loopback_fin(void); @@ -36435,7 +36566,7 @@ index 48bf070..66afec7 100644 AuStubInt0(au_test_loopback_overlap, struct super_block *sb, struct dentry *h_adding) AuStubInt0(au_test_loopback_kthread, void) -@@ -33,6 +37,8 @@ +@@ -33,6 +37,8 @@ AuStubVoid(au_warn_loopback, struct super_block *h_sb) AuStubInt0(au_loopback_init, void) AuStubVoid(au_loopback_fin, void) @@ -36445,10 +36576,10 @@ index 48bf070..66afec7 100644 #endif /* __KERNEL__ */ diff --git a/fs/aufs/super.c b/fs/aufs/super.c -index 0082ce4..5085378 100644 +index 5455fb1..8b9df60 100644 --- a/fs/aufs/super.c +++ b/fs/aufs/super.c -@@ -839,7 +839,10 @@ static int aufs_remount_fs(struct super_block *sb, int *flags, char *data) +@@ -837,7 +837,10 @@ static const struct super_operations aufs_sop = { .statfs = aufs_statfs, .put_super = aufs_put_super, .sync_fs = aufs_sync_fs, @@ -36461,10 +36592,10 @@ index 0082ce4..5085378 100644 /* ---------------------------------------------------------------------- */ diff --git a/include/linux/fs.h b/include/linux/fs.h -index a903bc3..db820e3 100644 +index 22d2910..d8db3fb 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h -@@ -1823,6 +1823,10 @@ struct super_operations { +@@ -1811,6 +1811,10 @@ struct super_operations { struct shrink_control *); long (*free_cached_objects)(struct super_block *, struct shrink_control *);