]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs5.patch
include symbols in compiled device trees
[packages/kernel.git] / kernel-aufs5.patch
CommitLineData
2121bcd9 1SPDX-License-Identifier: GPL-2.0
0b2a12c6 2aufs5.12 kbuild patch
7f207e10 3
fbc438ed 4diff --git a/fs/Kconfig b/fs/Kconfig
0b2a12c6 5index a55bda4233bbe..c4984b5bf340f 100644
fbc438ed
JR
6--- a/fs/Kconfig
7+++ b/fs/Kconfig
42a736d3 8@@ -288,6 +288,7 @@ source "fs/sysv/Kconfig"
7e9cd9fe 9 source "fs/ufs/Kconfig"
9d41a5bf 10 source "fs/erofs/Kconfig"
394e211a 11 source "fs/vboxsf/Kconfig"
7f207e10
AM
12+source "fs/aufs/Kconfig"
13
14 endif # MISC_FILESYSTEMS
15
16diff --git a/fs/Makefile b/fs/Makefile
0b2a12c6 17index 3215fe205256d..7218277473b8f 100644
7f207e10
AM
18--- a/fs/Makefile
19+++ b/fs/Makefile
0b2a12c6 20@@ -135,3 +135,4 @@ obj-$(CONFIG_EFIVAR_FS) += efivarfs/
9d41a5bf 21 obj-$(CONFIG_EROFS_FS) += erofs/
394e211a
AM
22 obj-$(CONFIG_VBOXSF_FS) += vboxsf/
23 obj-$(CONFIG_ZONEFS_FS) += zonefs/
86dc4139 24+obj-$(CONFIG_AUFS_FS) += aufs/
2121bcd9 25SPDX-License-Identifier: GPL-2.0
0b2a12c6 26aufs5.12 base patch
7f207e10 27
c1595e42 28diff --git a/MAINTAINERS b/MAINTAINERS
0b2a12c6 29index 9450e052f1b13..f7db6edba5a37 100644
c1595e42
JR
30--- a/MAINTAINERS
31+++ b/MAINTAINERS
0b2a12c6 32@@ -2992,6 +2992,19 @@ F: include/linux/audit.h
c1595e42
JR
33 F: include/uapi/linux/audit.h
34 F: kernel/audit*
35
36+AUFS (advanced multi layered unification filesystem) FILESYSTEM
37+M: "J. R. Okajima" <hooanon05g@gmail.com>
c1595e42 38+L: aufs-users@lists.sourceforge.net (members only)
eca801bf 39+L: linux-unionfs@vger.kernel.org
42a736d3 40+S: Supported
c1595e42 41+W: http://aufs.sourceforge.net
5527c038 42+T: git://github.com/sfjro/aufs4-linux.git
c1595e42
JR
43+F: Documentation/ABI/testing/debugfs-aufs
44+F: Documentation/ABI/testing/sysfs-aufs
42a736d3 45+F: Documentation/filesystems/aufs/
c1595e42
JR
46+F: fs/aufs/
47+F: include/uapi/linux/aufs_type.h
48+
49 AUXILIARY DISPLAY DRIVERS
13f235e5 50 M: Miguel Ojeda <ojeda@kernel.org>
cd7a4cd9 51 S: Maintained
392086de 52diff --git a/drivers/block/loop.c b/drivers/block/loop.c
0b2a12c6 53index a370cde3ddd49..01ca256575fb2 100644
392086de
AM
54--- a/drivers/block/loop.c
55+++ b/drivers/block/loop.c
42a736d3 56@@ -761,6 +761,24 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
cd7a4cd9 57 return error;
392086de
AM
58 }
59
60+/*
61+ * for AUFS
62+ * no get/put for file.
63+ */
64+struct file *loop_backing_file(struct super_block *sb)
65+{
66+ struct file *ret;
67+ struct loop_device *l;
68+
69+ ret = NULL;
70+ if (MAJOR(sb->s_dev) == LOOP_MAJOR) {
71+ l = sb->s_bdev->bd_disk->private_data;
72+ ret = l->lo_backing_file;
73+ }
74+ return ret;
75+}
febd17d6 76+EXPORT_SYMBOL_GPL(loop_backing_file);
392086de
AM
77+
78 /* loop sysfs attributes */
79
80 static ssize_t loop_attr_show(struct device *dev, char *page,
c1595e42 81diff --git a/fs/dcache.c b/fs/dcache.c
0b2a12c6 82index 7d24ff7eb2068..3caa7ab4b84f1 100644
c1595e42
JR
83--- a/fs/dcache.c
84+++ b/fs/dcache.c
0b2a12c6 85@@ -1318,7 +1318,7 @@ enum d_walk_ret {
c1595e42 86 *
cd7a4cd9 87 * The @enter() callbacks are called with d_lock held.
c1595e42
JR
88 */
89-static void d_walk(struct dentry *parent, void *data,
90+void d_walk(struct dentry *parent, void *data,
cd7a4cd9 91 enum d_walk_ret (*enter)(void *, struct dentry *))
c1595e42 92 {
cd7a4cd9 93 struct dentry *this_parent;
febd17d6 94diff --git a/fs/fcntl.c b/fs/fcntl.c
0b2a12c6 95index dfc72f15be7fc..d8a12eb63961d 100644
febd17d6
JR
96--- a/fs/fcntl.c
97+++ b/fs/fcntl.c
0b2a12c6 98@@ -33,7 +33,7 @@
febd17d6
JR
99
100 #define SETFL_MASK (O_APPEND | O_NONBLOCK | O_NDELAY | O_DIRECT | O_NOATIME)
101
102-static int setfl(int fd, struct file * filp, unsigned long arg)
43982f53 103+int setfl(int fd, struct file *filp, unsigned long arg)
febd17d6
JR
104 {
105 struct inode * inode = file_inode(filp);
106 int error = 0;
0b2a12c6 107@@ -64,6 +64,8 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
febd17d6
JR
108
109 if (filp->f_op->check_flags)
110 error = filp->f_op->check_flags(arg);
111+ if (!error && filp->f_op->setfl)
112+ error = filp->f_op->setfl(filp, arg);
113 if (error)
114 return error;
115
5afbbe0d 116diff --git a/fs/inode.c b/fs/inode.c
0b2a12c6 117index a047ab306f9a8..ba1df0895b69f 100644
5afbbe0d
AM
118--- a/fs/inode.c
119+++ b/fs/inode.c
0b2a12c6 120@@ -1772,7 +1772,7 @@ EXPORT_SYMBOL(generic_update_time);
5afbbe0d
AM
121 * This does the actual work of updating an inodes time or version. Must have
122 * had called mnt_want_write() before calling this.
123 */
cd7a4cd9
AM
124-static int update_time(struct inode *inode, struct timespec64 *time, int flags)
125+int update_time(struct inode *inode, struct timespec64 *time, int flags)
5afbbe0d 126 {
394e211a
AM
127 if (inode->i_op->update_time)
128 return inode->i_op->update_time(inode, time, flags);
8b6a4947 129diff --git a/fs/namespace.c b/fs/namespace.c
0b2a12c6 130index 56bb5a5fdc0d0..540679d7e0434 100644
8b6a4947
AM
131--- a/fs/namespace.c
132+++ b/fs/namespace.c
0b2a12c6 133@@ -807,6 +807,12 @@ static inline int check_mnt(struct mount *mnt)
8b6a4947
AM
134 return mnt->mnt_ns == current->nsproxy->mnt_ns;
135 }
136
137+/* for aufs, CONFIG_AUFS_BR_FUSE */
138+int is_current_mnt_ns(struct vfsmount *mnt)
139+{
140+ return check_mnt(real_mount(mnt));
141+}
142+
143 /*
144 * vfsmount lock must be held for write
145 */
7f207e10 146diff --git a/fs/splice.c b/fs/splice.c
0b2a12c6 147index 5dbce4dcc1a7d..3e6ba363b7775 100644
7f207e10
AM
148--- a/fs/splice.c
149+++ b/fs/splice.c
0b2a12c6 150@@ -759,8 +759,8 @@ static int warn_unsupported(struct file *file, const char *op)
7f207e10
AM
151 /*
152 * Attempt to initiate a splice from pipe to file.
153 */
154-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
155- loff_t *ppos, size_t len, unsigned int flags)
156+long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
157+ loff_t *ppos, size_t len, unsigned int flags)
158 {
42a736d3
AM
159 if (unlikely(!out->f_op->splice_write))
160 return warn_unsupported(out, "write");
0b2a12c6 161@@ -770,9 +770,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
7f207e10
AM
162 /*
163 * Attempt to initiate a splice from a file to a pipe.
164 */
165-static long do_splice_to(struct file *in, loff_t *ppos,
166- struct pipe_inode_info *pipe, size_t len,
167- unsigned int flags)
168+long do_splice_to(struct file *in, loff_t *ppos,
169+ struct pipe_inode_info *pipe, size_t len,
170+ unsigned int flags)
171 {
13f235e5 172 unsigned int p_space;
42a736d3 173 int ret;
a2654f78 174diff --git a/fs/sync.c b/fs/sync.c
42a736d3 175index 1373a610dc784..b7b5a0a0df6ff 100644
a2654f78
AM
176--- a/fs/sync.c
177+++ b/fs/sync.c
2121bcd9 178@@ -28,7 +28,7 @@
a2654f78
AM
179 * wait == 1 case since in that case write_inode() functions do
180 * sync_dirty_buffer() and thus effectively write one block at a time.
181 */
182-static int __sync_filesystem(struct super_block *sb, int wait)
183+int __sync_filesystem(struct super_block *sb, int wait)
184 {
185 if (wait)
186 sync_inodes_sb(sb);
5527c038 187diff --git a/include/linux/fs.h b/include/linux/fs.h
0b2a12c6 188index ec8f3ddf4a6aa..4fa4b24535fde 100644
5527c038
JR
189--- a/include/linux/fs.h
190+++ b/include/linux/fs.h
0b2a12c6 191@@ -1332,6 +1332,7 @@ extern void fasync_free(struct fasync_struct *);
febd17d6
JR
192 /* can be called from interrupts */
193 extern void kill_fasync(struct fasync_struct **, int, int);
194
43982f53 195+extern int setfl(int fd, struct file *filp, unsigned long arg);
febd17d6 196 extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int force);
3c1bdaff 197 extern int f_setown(struct file *filp, unsigned long arg, int force);
febd17d6 198 extern void f_delown(struct file *filp);
0b2a12c6 199@@ -1909,6 +1910,7 @@ struct file_operations {
febd17d6
JR
200 ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
201 unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
202 int (*check_flags)(int);
203+ int (*setfl)(struct file *, unsigned long);
204 int (*flock) (struct file *, int, struct file_lock *);
205 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
206 ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
0b2a12c6 207@@ -2428,6 +2430,7 @@ extern int current_umask(void);
5afbbe0d
AM
208 extern void ihold(struct inode * inode);
209 extern void iput(struct inode *);
cd7a4cd9
AM
210 extern int generic_update_time(struct inode *, struct timespec64 *, int);
211+extern int update_time(struct inode *, struct timespec64 *, int);
5afbbe0d
AM
212
213 /* /sys/fs */
214 extern struct kobject *fs_kobj;
0b2a12c6 215@@ -2668,6 +2671,7 @@ static inline bool sb_is_blkdev_sb(struct super_block *sb)
a2654f78 216 }
6803432e
JR
217
218 void emergency_thaw_all(void);
a2654f78
AM
219+extern int __sync_filesystem(struct super_block *, int);
220 extern int sync_filesystem(struct super_block *);
221 extern const struct file_operations def_blk_fops;
222 extern const struct file_operations def_chr_fops;
8b6a4947 223diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
0b2a12c6 224index 7b7ebf2e28ec5..20c46305e057e 100644
8b6a4947
AM
225--- a/include/linux/lockdep.h
226+++ b/include/linux/lockdep.h
0b2a12c6 227@@ -248,6 +248,8 @@ static inline int lockdep_match_key(struct lockdep_map *lock,
8b6a4947
AM
228 return lock->key == key;
229 }
230
231+struct lock_class *lockdep_hlock_class(struct held_lock *hlock);
232+
233 /*
234 * Acquire a lock.
235 *
8b6a4947 236diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
42a736d3 237index 8f882f5881e87..6b9808f098435 100644
8b6a4947
AM
238--- a/include/linux/mnt_namespace.h
239+++ b/include/linux/mnt_namespace.h
42a736d3 240@@ -7,12 +7,15 @@ struct mnt_namespace;
8b6a4947
AM
241 struct fs_struct;
242 struct user_namespace;
f24b0ddd 243 struct ns_common;
8b6a4947
AM
244+struct vfsmount;
245
246 extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
247 struct user_namespace *, struct fs_struct *);
248 extern void put_mnt_ns(struct mnt_namespace *ns);
f24b0ddd 249 extern struct ns_common *from_mnt_ns(struct mnt_namespace *);
8b6a4947
AM
250
251+extern int is_current_mnt_ns(struct vfsmount *mnt);
252+
253 extern const struct file_operations proc_mounts_operations;
254 extern const struct file_operations proc_mountinfo_operations;
255 extern const struct file_operations proc_mountstats_operations;
1e00d052 256diff --git a/include/linux/splice.h b/include/linux/splice.h
42a736d3 257index a55179fd60fc3..8e21c53cf8831 100644
1e00d052
AM
258--- a/include/linux/splice.h
259+++ b/include/linux/splice.h
42a736d3 260@@ -93,4 +93,10 @@ extern void splice_shrink_spd(struct splice_pipe_desc *);
4b3da204
AM
261
262 extern const struct pipe_buf_operations page_cache_pipe_buf_ops;
106341ce 263 extern const struct pipe_buf_operations default_pipe_buf_ops;
1e00d052
AM
264+
265+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
266+ loff_t *ppos, size_t len, unsigned int flags);
267+extern long do_splice_to(struct file *in, loff_t *ppos,
268+ struct pipe_inode_info *pipe, size_t len,
269+ unsigned int flags);
270 #endif
8b6a4947 271diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
0b2a12c6 272index f160f1c97ca1e..fe71c2737eb9e 100644
8b6a4947
AM
273--- a/kernel/locking/lockdep.c
274+++ b/kernel/locking/lockdep.c
42a736d3 275@@ -188,7 +188,7 @@ static
9f237c51 276 struct lock_class lock_classes[MAX_LOCKDEP_KEYS];
eca34b5c 277 static DECLARE_BITMAP(lock_classes_in_use, MAX_LOCKDEP_KEYS);
8b6a4947
AM
278
279-static inline struct lock_class *hlock_class(struct held_lock *hlock)
280+inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock)
281 {
eca34b5c
AM
282 unsigned int class_idx = hlock->class_idx;
283
42a736d3 284@@ -209,6 +209,7 @@ static inline struct lock_class *hlock_class(struct held_lock *hlock)
eca34b5c
AM
285 */
286 return lock_classes + class_idx;
8b6a4947
AM
287 }
288+#define hlock_class(hlock) lockdep_hlock_class(hlock)
289
290 #ifdef CONFIG_LOCK_STAT
291 static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], cpu_lock_stats);
2121bcd9 292SPDX-License-Identifier: GPL-2.0
0b2a12c6 293aufs5.12 mmap patch
fb47a38f 294
c1595e42 295diff --git a/fs/proc/base.c b/fs/proc/base.c
0b2a12c6 296index 3851bfcdba56e..d632ddd5f5ee8 100644
c1595e42
JR
297--- a/fs/proc/base.c
298+++ b/fs/proc/base.c
0b2a12c6 299@@ -2183,7 +2183,7 @@ static int map_files_get_link(struct dentry *dentry, struct path *path)
eca34b5c 300 rc = -ENOENT;
c1595e42
JR
301 vma = find_exact_vma(mm, vm_start, vm_end);
302 if (vma && vma->vm_file) {
303- *path = vma->vm_file->f_path;
304+ *path = vma_pr_or_file(vma)->f_path;
305 path_get(path);
306 rc = 0;
307 }
fb47a38f 308diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c
42a736d3 309index 13452b32e2bd5..38acccfef9d49 100644
fb47a38f
JR
310--- a/fs/proc/nommu.c
311+++ b/fs/proc/nommu.c
42a736d3 312@@ -40,7 +40,10 @@ static int nommu_region_show(struct seq_file *m, struct vm_region *region)
fb47a38f
JR
313 file = region->vm_file;
314
315 if (file) {
316- struct inode *inode = file_inode(region->vm_file);
317+ struct inode *inode;
076b876e 318+
fb47a38f
JR
319+ file = vmr_pr_or_file(region);
320+ inode = file_inode(file);
321 dev = inode->i_sb->s_dev;
322 ino = inode->i_ino;
323 }
324diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
0b2a12c6 325index e862cab695838..5c45041943a6f 100644
fb47a38f
JR
326--- a/fs/proc/task_mmu.c
327+++ b/fs/proc/task_mmu.c
42b5c33a 328@@ -280,7 +280,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
fb47a38f
JR
329 const char *name = NULL;
330
331 if (file) {
332- struct inode *inode = file_inode(vma->vm_file);
333+ struct inode *inode;
076b876e 334+
fb47a38f
JR
335+ file = vma_pr_or_file(vma);
336+ inode = file_inode(file);
337 dev = inode->i_sb->s_dev;
338 ino = inode->i_ino;
339 pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
0b2a12c6 340@@ -1861,7 +1864,7 @@ static int show_numa_map(struct seq_file *m, void *v)
076b876e
AM
341 struct proc_maps_private *proc_priv = &numa_priv->proc_maps;
342 struct vm_area_struct *vma = v;
343 struct numa_maps *md = &numa_priv->md;
344- struct file *file = vma->vm_file;
345+ struct file *file = vma_pr_or_file(vma);
076b876e 346 struct mm_struct *mm = vma->vm_mm;
43982f53
AM
347 struct mempolicy *pol;
348 char buffer[64];
fb47a38f 349diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
42a736d3 350index a6d21fc0033c6..02c2de31196e0 100644
fb47a38f
JR
351--- a/fs/proc/task_nommu.c
352+++ b/fs/proc/task_nommu.c
acd2b654 353@@ -155,7 +155,10 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
fb47a38f
JR
354 file = vma->vm_file;
355
356 if (file) {
357- struct inode *inode = file_inode(vma->vm_file);
358+ struct inode *inode;
076b876e 359+
b912730e 360+ file = vma_pr_or_file(vma);
fb47a38f
JR
361+ inode = file_inode(file);
362 dev = inode->i_sb->s_dev;
363 ino = inode->i_ino;
364 pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
365diff --git a/include/linux/mm.h b/include/linux/mm.h
0b2a12c6 366index 8ba434287387b..6d23d40ad1523 100644
fb47a38f
JR
367--- a/include/linux/mm.h
368+++ b/include/linux/mm.h
0b2a12c6 369@@ -1759,6 +1759,28 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping,
a3232e84 370 unmap_mapping_range(mapping, holebegin, holelen, 0);
fb47a38f 371 }
fb47a38f 372
076b876e
AM
373+extern void vma_do_file_update_time(struct vm_area_struct *, const char[], int);
374+extern struct file *vma_do_pr_or_file(struct vm_area_struct *, const char[],
f2c43d5f 375+ int);
076b876e
AM
376+extern void vma_do_get_file(struct vm_area_struct *, const char[], int);
377+extern void vma_do_fput(struct vm_area_struct *, const char[], int);
fb47a38f 378+
f2c43d5f
AM
379+#define vma_file_update_time(vma) vma_do_file_update_time(vma, __func__, \
380+ __LINE__)
381+#define vma_pr_or_file(vma) vma_do_pr_or_file(vma, __func__, \
382+ __LINE__)
383+#define vma_get_file(vma) vma_do_get_file(vma, __func__, __LINE__)
384+#define vma_fput(vma) vma_do_fput(vma, __func__, __LINE__)
b912730e
AM
385+
386+#ifndef CONFIG_MMU
076b876e
AM
387+extern struct file *vmr_do_pr_or_file(struct vm_region *, const char[], int);
388+extern void vmr_do_fput(struct vm_region *, const char[], int);
389+
f2c43d5f
AM
390+#define vmr_pr_or_file(region) vmr_do_pr_or_file(region, __func__, \
391+ __LINE__)
392+#define vmr_fput(region) vmr_do_fput(region, __func__, __LINE__)
b912730e 393+#endif /* !CONFIG_MMU */
fb47a38f 394+
a3232e84
JR
395 extern int access_process_vm(struct task_struct *tsk, unsigned long addr,
396 void *buf, int len, unsigned int gup_flags);
fb47a38f 397 extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
fb47a38f 398diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
0b2a12c6 399index 6613b26a88946..e94df45b5483a 100644
fb47a38f
JR
400--- a/include/linux/mm_types.h
401+++ b/include/linux/mm_types.h
0b2a12c6 402@@ -279,6 +279,7 @@ struct vm_region {
fb47a38f
JR
403 unsigned long vm_top; /* region allocated to here */
404 unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */
405 struct file *vm_file; /* the backing file or NULL */
406+ struct file *vm_prfile; /* the virtual backing file or NULL */
407
408 int vm_usage; /* region usage count (access under nommu_region_sem) */
409 bool vm_icache_flushed : 1; /* true if the icache has been flushed for
0b2a12c6 410@@ -358,6 +359,7 @@ struct vm_area_struct {
fb47a38f 411 unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE
5afbbe0d 412 units */
fb47a38f
JR
413 struct file * vm_file; /* File we map to (can be NULL). */
414+ struct file *vm_prfile; /* shadow of vm_file */
415 void * vm_private_data; /* was vm_pte (shared mem) */
416
eca34b5c 417 #ifdef CONFIG_SWAP
fb47a38f 418diff --git a/kernel/fork.c b/kernel/fork.c
0b2a12c6 419index 426cd0c51f9eb..ea0ae494c6dde 100644
fb47a38f
JR
420--- a/kernel/fork.c
421+++ b/kernel/fork.c
42a736d3 422@@ -555,7 +555,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
fb47a38f
JR
423 struct inode *inode = file_inode(file);
424 struct address_space *mapping = file->f_mapping;
425
426- get_file(file);
427+ vma_get_file(tmp);
428 if (tmp->vm_flags & VM_DENYWRITE)
42a736d3 429 put_write_access(inode);
2000de60 430 i_mmap_lock_write(mapping);
076b876e 431diff --git a/mm/Makefile b/mm/Makefile
0b2a12c6 432index 72227b24a6168..5d03943b08e03 100644
076b876e
AM
433--- a/mm/Makefile
434+++ b/mm/Makefile
42a736d3
AM
435@@ -52,7 +52,7 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \
436 mm_init.o percpu.o slab_common.o \
b00004a5 437 compaction.o vmacache.o \
076b876e 438 interval_tree.o list_lru.o workingset.o \
42a736d3
AM
439- debug.o gup.o mmap_lock.o $(mmu-y)
440+ prfile.o debug.o gup.o mmap_lock.o $(mmu-y)
076b876e 441
fbc438ed
JR
442 # Give 'page_alloc' its own module-parameter namespace
443 page-alloc-y := page_alloc.o
fb47a38f 444diff --git a/mm/filemap.c b/mm/filemap.c
0b2a12c6 445index 6ce832dc59e73..8b7a71b6f0e6c 100644
fb47a38f
JR
446--- a/mm/filemap.c
447+++ b/mm/filemap.c
0b2a12c6 448@@ -3162,7 +3162,7 @@ vm_fault_t filemap_page_mkwrite(struct vm_fault *vmf)
cd7a4cd9 449 vm_fault_t ret = VM_FAULT_LOCKED;
fb47a38f 450
42a736d3 451 sb_start_pagefault(mapping->host->i_sb);
521ced18
JR
452- file_update_time(vmf->vma->vm_file);
453+ vma_file_update_time(vmf->vma);
fb47a38f 454 lock_page(page);
42a736d3 455 if (page->mapping != mapping) {
fb47a38f 456 unlock_page(page);
fb47a38f 457diff --git a/mm/mmap.c b/mm/mmap.c
0b2a12c6 458index 3f287599a7a30..eb36f1b18f048 100644
fb47a38f
JR
459--- a/mm/mmap.c
460+++ b/mm/mmap.c
42b5c33a 461@@ -179,7 +179,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma)
fb47a38f
JR
462 if (vma->vm_ops && vma->vm_ops->close)
463 vma->vm_ops->close(vma);
464 if (vma->vm_file)
465- fput(vma->vm_file);
466+ vma_fput(vma);
467 mpol_put(vma_policy(vma));
cd7a4cd9 468 vm_area_free(vma);
fb47a38f 469 return next;
0b2a12c6 470@@ -949,7 +949,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
fb47a38f
JR
471 if (remove_next) {
472 if (file) {
473 uprobe_munmap(next, next->vm_start, next->vm_end);
474- fput(file);
475+ vma_fput(vma);
476 }
477 if (next->anon_vma)
478 anon_vma_merge(vma, next);
0b2a12c6 479@@ -1895,7 +1895,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
35939ee7
JR
480 return addr;
481
fb47a38f 482 unmap_and_free_vma:
42a736d3 483- fput(vma->vm_file);
fb47a38f
JR
484+ vma_fput(vma);
485 vma->vm_file = NULL;
fb47a38f
JR
486
487 /* Undo any partial mapping done by a device driver. */
0b2a12c6 488@@ -2755,7 +2755,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
fb47a38f
JR
489 goto out_free_mpol;
490
491 if (new->vm_file)
492- get_file(new->vm_file);
493+ vma_get_file(new);
494
495 if (new->vm_ops && new->vm_ops->open)
496 new->vm_ops->open(new);
0b2a12c6 497@@ -2774,7 +2774,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
fb47a38f
JR
498 if (new->vm_ops && new->vm_ops->close)
499 new->vm_ops->close(new);
500 if (new->vm_file)
501- fput(new->vm_file);
502+ vma_fput(new);
503 unlink_anon_vmas(new);
504 out_free_mpol:
505 mpol_put(vma_policy(new));
0b2a12c6 506@@ -2967,7 +2967,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
7e9cd9fe
AM
507 struct vm_area_struct *vma;
508 unsigned long populate = 0;
509 unsigned long ret = -EINVAL;
510- struct file *file;
5afbbe0d 511+ struct file *file, *prfile;
7e9cd9fe 512
cd7a4cd9 513 pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/vm/remap_file_pages.rst.\n",
5afbbe0d 514 current->comm, current->pid);
0b2a12c6 515@@ -3042,10 +3042,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
febd17d6 516 }
7e9cd9fe
AM
517 }
518
519- file = get_file(vma->vm_file);
520+ vma_get_file(vma);
5afbbe0d
AM
521+ file = vma->vm_file;
522+ prfile = vma->vm_prfile;
6803432e 523 ret = do_mmap(vma->vm_file, start, size,
521ced18 524 prot, flags, pgoff, &populate, NULL);
5afbbe0d
AM
525+ if (!IS_ERR_VALUE(ret) && file && prfile) {
526+ struct vm_area_struct *new_vma;
527+
528+ new_vma = find_vma(mm, ret);
529+ if (!new_vma->vm_prfile)
530+ new_vma->vm_prfile = prfile;
531+ if (new_vma != vma)
532+ get_file(prfile);
533+ }
534+ /*
535+ * two fput()s instead of vma_fput(vma),
536+ * coz vma may not be available anymore.
537+ */
538 fput(file);
539+ if (prfile)
540+ fput(prfile);
7e9cd9fe 541 out:
42a736d3 542 mmap_write_unlock(mm);
7e9cd9fe 543 if (populate)
0b2a12c6 544@@ -3332,7 +3349,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
79b8bda9
AM
545 if (anon_vma_clone(new_vma, vma))
546 goto out_free_mempol;
547 if (new_vma->vm_file)
548- get_file(new_vma->vm_file);
549+ vma_get_file(new_vma);
550 if (new_vma->vm_ops && new_vma->vm_ops->open)
551 new_vma->vm_ops->open(new_vma);
552 vma_link(mm, new_vma, prev, rb_link, rb_parent);
fb47a38f 553diff --git a/mm/nommu.c b/mm/nommu.c
0b2a12c6 554index 5c9ab799c0e63..dd78905704c12 100644
fb47a38f
JR
555--- a/mm/nommu.c
556+++ b/mm/nommu.c
42a736d3 557@@ -533,7 +533,7 @@ static void __put_nommu_region(struct vm_region *region)
fb47a38f
JR
558 up_write(&nommu_region_sem);
559
560 if (region->vm_file)
561- fput(region->vm_file);
562+ vmr_fput(region);
563
564 /* IO memory and memory shared directly out of the pagecache
565 * from ramfs/tmpfs mustn't be released here */
42a736d3 566@@ -665,7 +665,7 @@ static void delete_vma(struct mm_struct *mm, struct vm_area_struct *vma)
fb47a38f
JR
567 if (vma->vm_ops && vma->vm_ops->close)
568 vma->vm_ops->close(vma);
569 if (vma->vm_file)
570- fput(vma->vm_file);
571+ vma_fput(vma);
572 put_nommu_region(vma->vm_region);
cd7a4cd9 573 vm_area_free(vma);
fb47a38f 574 }
42a736d3 575@@ -1188,7 +1188,7 @@ unsigned long do_mmap(struct file *file,
fb47a38f
JR
576 goto error_just_free;
577 }
578 }
579- fput(region->vm_file);
580+ vmr_fput(region);
581 kmem_cache_free(vm_region_jar, region);
582 region = pregion;
583 result = start;
42a736d3 584@@ -1265,10 +1265,10 @@ unsigned long do_mmap(struct file *file,
fb47a38f
JR
585 up_write(&nommu_region_sem);
586 error:
587 if (region->vm_file)
588- fput(region->vm_file);
589+ vmr_fput(region);
590 kmem_cache_free(vm_region_jar, region);
591 if (vma->vm_file)
eca801bf
AM
592- fput(vma->vm_file);
593+ vma_fput(vma);
594 vm_area_free(vma);
595 return ret;
596
076b876e
AM
597diff --git a/mm/prfile.c b/mm/prfile.c
598new file mode 100644
42b5c33a 599index 0000000000000..00d51187c3250
076b876e
AM
600--- /dev/null
601+++ b/mm/prfile.c
2121bcd9 602@@ -0,0 +1,86 @@
cd7a4cd9 603+// SPDX-License-Identifier: GPL-2.0
076b876e 604+/*
1c60b727
AM
605+ * Mainly for aufs which mmap(2) different file and wants to print different
606+ * path in /proc/PID/maps.
076b876e
AM
607+ * Call these functions via macros defined in linux/mm.h.
608+ *
609+ * See Documentation/filesystems/aufs/design/06mmap.txt
610+ *
d58c55f2 611+ * Copyright (c) 2014-2020 Junjro R. Okajima
076b876e
AM
612+ * Copyright (c) 2014 Ian Campbell
613+ */
614+
615+#include <linux/mm.h>
616+#include <linux/file.h>
617+#include <linux/fs.h>
618+
619+/* #define PRFILE_TRACE */
620+static inline void prfile_trace(struct file *f, struct file *pr,
621+ const char func[], int line, const char func2[])
622+{
623+#ifdef PRFILE_TRACE
624+ if (pr)
1c60b727 625+ pr_info("%s:%d: %s, %pD2\n", func, line, func2, f);
076b876e
AM
626+#endif
627+}
628+
076b876e
AM
629+void vma_do_file_update_time(struct vm_area_struct *vma, const char func[],
630+ int line)
631+{
632+ struct file *f = vma->vm_file, *pr = vma->vm_prfile;
633+
634+ prfile_trace(f, pr, func, line, __func__);
635+ file_update_time(f);
636+ if (f && pr)
637+ file_update_time(pr);
638+}
639+
640+struct file *vma_do_pr_or_file(struct vm_area_struct *vma, const char func[],
641+ int line)
642+{
643+ struct file *f = vma->vm_file, *pr = vma->vm_prfile;
644+
645+ prfile_trace(f, pr, func, line, __func__);
646+ return (f && pr) ? pr : f;
647+}
648+
649+void vma_do_get_file(struct vm_area_struct *vma, const char func[], int line)
650+{
651+ struct file *f = vma->vm_file, *pr = vma->vm_prfile;
652+
653+ prfile_trace(f, pr, func, line, __func__);
654+ get_file(f);
655+ if (f && pr)
656+ get_file(pr);
657+}
658+
659+void vma_do_fput(struct vm_area_struct *vma, const char func[], int line)
660+{
661+ struct file *f = vma->vm_file, *pr = vma->vm_prfile;
662+
663+ prfile_trace(f, pr, func, line, __func__);
664+ fput(f);
665+ if (f && pr)
666+ fput(pr);
667+}
b912730e
AM
668+
669+#ifndef CONFIG_MMU
076b876e
AM
670+struct file *vmr_do_pr_or_file(struct vm_region *region, const char func[],
671+ int line)
672+{
673+ struct file *f = region->vm_file, *pr = region->vm_prfile;
674+
675+ prfile_trace(f, pr, func, line, __func__);
676+ return (f && pr) ? pr : f;
677+}
678+
679+void vmr_do_fput(struct vm_region *region, const char func[], int line)
680+{
681+ struct file *f = region->vm_file, *pr = region->vm_prfile;
682+
683+ prfile_trace(f, pr, func, line, __func__);
684+ fput(f);
685+ if (f && pr)
686+ fput(pr);
687+}
b912730e 688+#endif /* !CONFIG_MMU */
2121bcd9 689SPDX-License-Identifier: GPL-2.0
0b2a12c6 690aufs5.12 standalone patch
7f207e10 691
c1595e42 692diff --git a/fs/dcache.c b/fs/dcache.c
0b2a12c6 693index 3caa7ab4b84f1..00e97c9ae7c45 100644
c1595e42
JR
694--- a/fs/dcache.c
695+++ b/fs/dcache.c
0b2a12c6 696@@ -1423,6 +1423,7 @@ void d_walk(struct dentry *parent, void *data,
c1595e42
JR
697 seq = 1;
698 goto again;
699 }
febd17d6 700+EXPORT_SYMBOL_GPL(d_walk);
c1595e42 701
a2654f78
AM
702 struct check_mount {
703 struct vfsmount *mnt;
0b2a12c6 704@@ -2968,6 +2969,7 @@ void d_exchange(struct dentry *dentry1, struct dentry *dentry2)
f2c43d5f
AM
705
706 write_sequnlock(&rename_lock);
707 }
708+EXPORT_SYMBOL_GPL(d_exchange);
709
710 /**
711 * d_ancestor - search for an ancestor
79b8bda9 712diff --git a/fs/exec.c b/fs/exec.c
0b2a12c6 713index 18594f11c31fe..ac38c0424d2a3 100644
79b8bda9
AM
714--- a/fs/exec.c
715+++ b/fs/exec.c
42a736d3 716@@ -114,6 +114,7 @@ bool path_noexec(const struct path *path)
79b8bda9
AM
717 return (path->mnt->mnt_flags & MNT_NOEXEC) ||
718 (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC);
719 }
febd17d6 720+EXPORT_SYMBOL_GPL(path_noexec);
79b8bda9
AM
721
722 #ifdef CONFIG_USELIB
723 /*
febd17d6 724diff --git a/fs/fcntl.c b/fs/fcntl.c
0b2a12c6 725index d8a12eb63961d..0532996186311 100644
febd17d6
JR
726--- a/fs/fcntl.c
727+++ b/fs/fcntl.c
0b2a12c6 728@@ -86,6 +86,7 @@ int setfl(int fd, struct file *filp, unsigned long arg)
febd17d6
JR
729 out:
730 return error;
731 }
732+EXPORT_SYMBOL_GPL(setfl);
733
734 static void f_modown(struct file *filp, struct pid *pid, enum pid_type type,
735 int force)
b912730e 736diff --git a/fs/file_table.c b/fs/file_table.c
42a736d3 737index 45437f8e1003e..786af52904fcf 100644
b912730e
AM
738--- a/fs/file_table.c
739+++ b/fs/file_table.c
42a736d3 740@@ -161,6 +161,7 @@ struct file *alloc_empty_file(int flags, const struct cred *cred)
b912730e
AM
741 }
742 return ERR_PTR(-ENFILE);
743 }
acd2b654 744+EXPORT_SYMBOL_GPL(alloc_empty_file);
b912730e 745
acd2b654
AM
746 /*
747 * Variant of alloc_empty_file() that doesn't check and modify nr_files.
43982f53 748@@ -375,6 +376,7 @@ void __fput_sync(struct file *file)
8cdd5066
JR
749 }
750
751 EXPORT_SYMBOL(fput);
febd17d6 752+EXPORT_SYMBOL_GPL(__fput_sync);
8cdd5066 753
79b8bda9 754 void __init files_init(void)
8b6a4947 755 {
5afbbe0d 756diff --git a/fs/inode.c b/fs/inode.c
0b2a12c6 757index ba1df0895b69f..0672530acf7dd 100644
5afbbe0d
AM
758--- a/fs/inode.c
759+++ b/fs/inode.c
0b2a12c6 760@@ -1778,6 +1778,7 @@ int update_time(struct inode *inode, struct timespec64 *time, int flags)
394e211a
AM
761 return inode->i_op->update_time(inode, time, flags);
762 return generic_update_time(inode, time, flags);
5afbbe0d
AM
763 }
764+EXPORT_SYMBOL_GPL(update_time);
765
766 /**
13f235e5 767 * atime_needs_update - update the access time
7f207e10 768diff --git a/fs/namespace.c b/fs/namespace.c
0b2a12c6 769index 540679d7e0434..74957d5edaa86 100644
7f207e10
AM
770--- a/fs/namespace.c
771+++ b/fs/namespace.c
0b2a12c6 772@@ -438,6 +438,7 @@ void __mnt_drop_write(struct vfsmount *mnt)
c06a8ce3
AM
773 mnt_dec_writers(real_mount(mnt));
774 preempt_enable();
775 }
776+EXPORT_SYMBOL_GPL(__mnt_drop_write);
777
778 /**
779 * mnt_drop_write - give up write access to a mount
0b2a12c6 780@@ -812,6 +813,7 @@ int is_current_mnt_ns(struct vfsmount *mnt)
8b6a4947
AM
781 {
782 return check_mnt(real_mount(mnt));
783 }
784+EXPORT_SYMBOL_GPL(is_current_mnt_ns);
785
786 /*
787 * vfsmount lock must be held for write
0b2a12c6 788@@ -1985,6 +1987,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
7f207e10
AM
789 }
790 return 0;
791 }
febd17d6 792+EXPORT_SYMBOL_GPL(iterate_mounts);
7f207e10 793
fbc438ed 794 static void lock_mnt_tree(struct mount *mnt)
7f207e10 795 {
43982f53 796diff --git a/fs/notify/group.c b/fs/notify/group.c
0b2a12c6 797index ffd723ffe46de..ec6172836b6f6 100644
43982f53
AM
798--- a/fs/notify/group.c
799+++ b/fs/notify/group.c
42a736d3 800@@ -100,6 +100,7 @@ void fsnotify_get_group(struct fsnotify_group *group)
1716fcea 801 {
2121bcd9 802 refcount_inc(&group->refcnt);
1716fcea 803 }
febd17d6 804+EXPORT_SYMBOL_GPL(fsnotify_get_group);
1716fcea
AM
805
806 /*
807 * Drop a reference to a group. Free it if it's through.
7f207e10 808diff --git a/fs/open.c b/fs/open.c
0b2a12c6 809index e53af13b5835f..f37da065e6544 100644
7f207e10
AM
810--- a/fs/open.c
811+++ b/fs/open.c
0b2a12c6 812@@ -65,6 +65,7 @@ int do_truncate(struct user_namespace *mnt_userns, struct dentry *dentry,
febd17d6 813 inode_unlock(dentry->d_inode);
7f207e10
AM
814 return ret;
815 }
febd17d6 816+EXPORT_SYMBOL_GPL(do_truncate);
7f207e10 817
5afbbe0d 818 long vfs_truncate(const struct path *path, loff_t length)
7f207e10 819 {
5527c038 820diff --git a/fs/read_write.c b/fs/read_write.c
0b2a12c6 821index 9db7adf160d20..8dc93a57a933f 100644
5527c038
JR
822--- a/fs/read_write.c
823+++ b/fs/read_write.c
42a736d3
AM
824@@ -503,6 +503,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
825 inc_syscr(current);
8b6a4947
AM
826 return ret;
827 }
828+EXPORT_SYMBOL_GPL(vfs_read);
829
830 static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
831 {
42a736d3
AM
832@@ -613,6 +614,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
833 file_end_write(file);
8b6a4947
AM
834 return ret;
835 }
836+EXPORT_SYMBOL_GPL(vfs_write);
837
fbc438ed
JR
838 /* file_ppos returns &file->f_pos or NULL if file is stream */
839 static inline loff_t *file_ppos(struct file *file)
7f207e10 840diff --git a/fs/splice.c b/fs/splice.c
0b2a12c6 841index 3e6ba363b7775..7c1be373eb7cd 100644
7f207e10
AM
842--- a/fs/splice.c
843+++ b/fs/splice.c
0b2a12c6 844@@ -766,6 +766,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
42a736d3
AM
845 return warn_unsupported(out, "write");
846 return out->f_op->splice_write(pipe, out, ppos, len, flags);
7f207e10 847 }
febd17d6 848+EXPORT_SYMBOL_GPL(do_splice_from);
7f207e10
AM
849
850 /*
851 * Attempt to initiate a splice from a file to a pipe.
0b2a12c6 852@@ -795,6 +796,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
42a736d3
AM
853 return warn_unsupported(in, "read");
854 return in->f_op->splice_read(in, ppos, pipe, len, flags);
7f207e10 855 }
febd17d6 856+EXPORT_SYMBOL_GPL(do_splice_to);
7f207e10
AM
857
858 /**
859 * splice_direct_to_actor - splices data directly between two non-pipes
a2654f78 860diff --git a/fs/sync.c b/fs/sync.c
42a736d3 861index b7b5a0a0df6ff..fa5c7fba7f1ba 100644
a2654f78
AM
862--- a/fs/sync.c
863+++ b/fs/sync.c
2121bcd9 864@@ -39,6 +39,7 @@ int __sync_filesystem(struct super_block *sb, int wait)
a2654f78
AM
865 sb->s_op->sync_fs(sb, wait);
866 return __sync_blockdev(sb->s_bdev, wait);
867 }
868+EXPORT_SYMBOL_GPL(__sync_filesystem);
869
870 /*
871 * Write out and wait upon all dirty data associated with this
c1595e42 872diff --git a/fs/xattr.c b/fs/xattr.c
0b2a12c6 873index b3444e06cded4..7b0f851b63d75 100644
c1595e42
JR
874--- a/fs/xattr.c
875+++ b/fs/xattr.c
0b2a12c6 876@@ -383,6 +383,7 @@ vfs_getxattr_alloc(struct user_namespace *mnt_userns, struct dentry *dentry,
c1595e42
JR
877 *xattr_value = value;
878 return error;
879 }
febd17d6 880+EXPORT_SYMBOL_GPL(vfs_getxattr_alloc);
c1595e42 881
febd17d6 882 ssize_t
f2c43d5f 883 __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
8b6a4947 884diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
0b2a12c6 885index fe71c2737eb9e..185531f89239a 100644
8b6a4947
AM
886--- a/kernel/locking/lockdep.c
887+++ b/kernel/locking/lockdep.c
42a736d3 888@@ -209,6 +209,7 @@ inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock)
eca34b5c
AM
889 */
890 return lock_classes + class_idx;
8b6a4947
AM
891 }
892+EXPORT_SYMBOL_GPL(lockdep_hlock_class);
893 #define hlock_class(hlock) lockdep_hlock_class(hlock)
894
895 #ifdef CONFIG_LOCK_STAT
8cdd5066 896diff --git a/kernel/task_work.c b/kernel/task_work.c
42a736d3 897index 9cde961875c0a..ac8c79dc81813 100644
8cdd5066
JR
898--- a/kernel/task_work.c
899+++ b/kernel/task_work.c
42a736d3 900@@ -143,3 +143,4 @@ void task_work_run(void)
8cdd5066
JR
901 } while (work);
902 }
903 }
febd17d6 904+EXPORT_SYMBOL_GPL(task_work_run);
7f207e10 905diff --git a/security/security.c b/security/security.c
0b2a12c6 906index 5ac96b16f8fab..46d334d6ac1f6 100644
7f207e10
AM
907--- a/security/security.c
908+++ b/security/security.c
0b2a12c6 909@@ -1102,6 +1102,7 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry)
7f207e10 910 return 0;
c2c0f25c 911 return call_int_hook(path_rmdir, 0, dir, dentry);
7f207e10 912 }
febd17d6 913+EXPORT_SYMBOL_GPL(security_path_rmdir);
7f207e10 914
5afbbe0d 915 int security_path_unlink(const struct path *dir, struct dentry *dentry)
7f207e10 916 {
0b2a12c6 917@@ -1118,6 +1119,7 @@ int security_path_symlink(const struct path *dir, struct dentry *dentry,
7f207e10 918 return 0;
c2c0f25c 919 return call_int_hook(path_symlink, 0, dir, dentry, old_name);
7f207e10 920 }
febd17d6 921+EXPORT_SYMBOL_GPL(security_path_symlink);
7f207e10 922
5afbbe0d 923 int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
7f207e10 924 struct dentry *new_dentry)
0b2a12c6 925@@ -1126,6 +1128,7 @@ int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
7f207e10 926 return 0;
c2c0f25c 927 return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry);
7f207e10 928 }
febd17d6 929+EXPORT_SYMBOL_GPL(security_path_link);
7f207e10 930
5afbbe0d
AM
931 int security_path_rename(const struct path *old_dir, struct dentry *old_dentry,
932 const struct path *new_dir, struct dentry *new_dentry,
0b2a12c6 933@@ -1153,6 +1156,7 @@ int security_path_truncate(const struct path *path)
7f207e10 934 return 0;
c2c0f25c 935 return call_int_hook(path_truncate, 0, path);
7f207e10 936 }
febd17d6 937+EXPORT_SYMBOL_GPL(security_path_truncate);
7f207e10 938
5afbbe0d 939 int security_path_chmod(const struct path *path, umode_t mode)
7eafdf33 940 {
0b2a12c6 941@@ -1160,6 +1164,7 @@ int security_path_chmod(const struct path *path, umode_t mode)
7f207e10 942 return 0;
c2c0f25c 943 return call_int_hook(path_chmod, 0, path, mode);
7f207e10 944 }
febd17d6 945+EXPORT_SYMBOL_GPL(security_path_chmod);
7f207e10 946
5afbbe0d 947 int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
7f207e10 948 {
0b2a12c6 949@@ -1167,6 +1172,7 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
7f207e10 950 return 0;
c2c0f25c 951 return call_int_hook(path_chown, 0, path, uid, gid);
7f207e10 952 }
febd17d6 953+EXPORT_SYMBOL_GPL(security_path_chown);
7f207e10 954
5afbbe0d 955 int security_path_chroot(const struct path *path)
7f207e10 956 {
0b2a12c6 957@@ -1267,6 +1273,7 @@ int security_inode_permission(struct inode *inode, int mask)
7f207e10 958 return 0;
c2c0f25c 959 return call_int_hook(inode_permission, 0, inode, mask);
7f207e10 960 }
febd17d6 961+EXPORT_SYMBOL_GPL(security_inode_permission);
7f207e10 962
1e00d052 963 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
7f207e10 964 {
0b2a12c6 965@@ -1464,6 +1471,7 @@ int security_file_permission(struct file *file, int mask)
7f207e10
AM
966
967 return fsnotify_perm(file, mask);
968 }
febd17d6 969+EXPORT_SYMBOL_GPL(security_file_permission);
7f207e10
AM
970
971 int security_file_alloc(struct file *file)
972 {
7f207e10 973diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Documentation/ABI/testing/debugfs-aufs
eca34b5c 974--- /usr/share/empty/Documentation/ABI/testing/debugfs-aufs 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 975+++ linux/Documentation/ABI/testing/debugfs-aufs 2021-05-02 20:15:14.666670785 +0200
062440b3 976@@ -0,0 +1,55 @@
7f207e10
AM
977+What: /debug/aufs/si_<id>/
978+Date: March 2009
f6b6e03d 979+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
980+Description:
981+ Under /debug/aufs, a directory named si_<id> is created
982+ per aufs mount, where <id> is a unique id generated
983+ internally.
1facf9fc 984+
86dc4139
AM
985+What: /debug/aufs/si_<id>/plink
986+Date: Apr 2013
f6b6e03d 987+Contact: J. R. Okajima <hooanon05g@gmail.com>
86dc4139
AM
988+Description:
989+ It has three lines and shows the information about the
990+ pseudo-link. The first line is a single number
991+ representing a number of buckets. The second line is a
992+ number of pseudo-links per buckets (separated by a
993+ blank). The last line is a single number representing a
994+ total number of psedo-links.
995+ When the aufs mount option 'noplink' is specified, it
996+ will show "1\n0\n0\n".
997+
7f207e10
AM
998+What: /debug/aufs/si_<id>/xib
999+Date: March 2009
f6b6e03d 1000+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
1001+Description:
1002+ It shows the consumed blocks by xib (External Inode Number
1003+ Bitmap), its block size and file size.
1004+ When the aufs mount option 'noxino' is specified, it
1005+ will be empty. About XINO files, see the aufs manual.
1006+
0b2a12c6 1007+What: /debug/aufs/si_<id>/xi<branch-index>
7f207e10 1008+Date: March 2009
f6b6e03d 1009+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
1010+Description:
1011+ It shows the consumed blocks by xino (External Inode Number
1012+ Translation Table), its link count, block size and file
1013+ size.
062440b3
AM
1014+ Due to the file size limit, there may exist multiple
1015+ xino files per branch. In this case, "-N" is added to
1016+ the filename and it corresponds to the index of the
1017+ internal xino array. "-0" is omitted.
1018+ When the aufs mount option 'noxino' is specified, Those
1019+ entries won't exist. About XINO files, see the aufs
1020+ manual.
7f207e10
AM
1021+
1022+What: /debug/aufs/si_<id>/xigen
1023+Date: March 2009
f6b6e03d 1024+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
1025+Description:
1026+ It shows the consumed blocks by xigen (External Inode
1027+ Generation Table), its block size and file size.
1028+ If CONFIG_AUFS_EXPORT is disabled, this entry will not
1029+ be created.
1030+ When the aufs mount option 'noxino' is specified, it
1031+ will be empty. About XINO files, see the aufs manual.
1032diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentation/ABI/testing/sysfs-aufs
eca34b5c 1033--- /usr/share/empty/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 1034+++ linux/Documentation/ABI/testing/sysfs-aufs 2021-05-02 20:15:14.666670785 +0200
392086de 1035@@ -0,0 +1,31 @@
7f207e10
AM
1036+What: /sys/fs/aufs/si_<id>/
1037+Date: March 2009
f6b6e03d 1038+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
1039+Description:
1040+ Under /sys/fs/aufs, a directory named si_<id> is created
1041+ per aufs mount, where <id> is a unique id generated
1042+ internally.
1043+
0b2a12c6 1044+What: /sys/fs/aufs/si_<id>/br<idx>
7f207e10 1045+Date: March 2009
f6b6e03d 1046+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
1047+Description:
1048+ It shows the abolute path of a member directory (which
1049+ is called branch) in aufs, and its permission.
1050+
0b2a12c6 1051+What: /sys/fs/aufs/si_<id>/brid<idx>
392086de 1052+Date: July 2013
f6b6e03d 1053+Contact: J. R. Okajima <hooanon05g@gmail.com>
392086de
AM
1054+Description:
1055+ It shows the id of a member directory (which is called
1056+ branch) in aufs.
1057+
7f207e10
AM
1058+What: /sys/fs/aufs/si_<id>/xi_path
1059+Date: March 2009
f6b6e03d 1060+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
1061+Description:
1062+ It shows the abolute path of XINO (External Inode Number
1063+ Bitmap, Translation Table and Generation Table) file
1064+ even if it is the default path.
1065+ When the aufs mount option 'noxino' is specified, it
1066+ will be empty. About XINO files, see the aufs manual.
53392da6 1067diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt linux/Documentation/filesystems/aufs/design/01intro.txt
eca34b5c 1068--- /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 1069+++ linux/Documentation/filesystems/aufs/design/01intro.txt 2021-05-02 20:15:14.666670785 +0200
1c60b727 1070@@ -0,0 +1,171 @@
53392da6 1071+
d58c55f2 1072+# Copyright (C) 2005-2020 Junjiro R. Okajima
53392da6
AM
1073+#
1074+# This program is free software; you can redistribute it and/or modify
1075+# it under the terms of the GNU General Public License as published by
1076+# the Free Software Foundation; either version 2 of the License, or
1077+# (at your option) any later version.
1078+#
1079+# This program is distributed in the hope that it will be useful,
1080+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1081+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1082+# GNU General Public License for more details.
1083+#
1084+# You should have received a copy of the GNU General Public License
523b37e3 1085+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1086+
1087+Introduction
1088+----------------------------------------
1089+
3c1bdaff 1090+aufs [ei ju: ef es] | /ey-yoo-ef-es/ | [a u f s]
53392da6
AM
1091+1. abbrev. for "advanced multi-layered unification filesystem".
1092+2. abbrev. for "another unionfs".
1093+3. abbrev. for "auf das" in German which means "on the" in English.
1094+ Ex. "Butter aufs Brot"(G) means "butter onto bread"(E).
1095+ But "Filesystem aufs Filesystem" is hard to understand.
1c60b727 1096+4. abbrev. for "African Urban Fashion Show".
53392da6
AM
1097+
1098+AUFS is a filesystem with features:
1099+- multi layered stackable unification filesystem, the member directory
1100+ is called as a branch.
1101+- branch permission and attribute, 'readonly', 'real-readonly',
7e9cd9fe 1102+ 'readwrite', 'whiteout-able', 'link-able whiteout', etc. and their
53392da6
AM
1103+ combination.
1104+- internal "file copy-on-write".
1105+- logical deletion, whiteout.
1106+- dynamic branch manipulation, adding, deleting and changing permission.
1107+- allow bypassing aufs, user's direct branch access.
1108+- external inode number translation table and bitmap which maintains the
1109+ persistent aufs inode number.
1110+- seekable directory, including NFS readdir.
1111+- file mapping, mmap and sharing pages.
1112+- pseudo-link, hardlink over branches.
1113+- loopback mounted filesystem as a branch.
1114+- several policies to select one among multiple writable branches.
1115+- revert a single systemcall when an error occurs in aufs.
1116+- and more...
1117+
1118+
1119+Multi Layered Stackable Unification Filesystem
1120+----------------------------------------------------------------------
1121+Most people already knows what it is.
1122+It is a filesystem which unifies several directories and provides a
1123+merged single directory. When users access a file, the access will be
1124+passed/re-directed/converted (sorry, I am not sure which English word is
1125+correct) to the real file on the member filesystem. The member
1126+filesystem is called 'lower filesystem' or 'branch' and has a mode
1127+'readonly' and 'readwrite.' And the deletion for a file on the lower
1128+readonly branch is handled by creating 'whiteout' on the upper writable
1129+branch.
1130+
1131+On LKML, there have been discussions about UnionMount (Jan Blunck,
1132+Bharata B Rao and Valerie Aurora) and Unionfs (Erez Zadok). They took
1133+different approaches to implement the merged-view.
1134+The former tries putting it into VFS, and the latter implements as a
1135+separate filesystem.
1136+(If I misunderstand about these implementations, please let me know and
1137+I shall correct it. Because it is a long time ago when I read their
1138+source files last time).
1139+
1140+UnionMount's approach will be able to small, but may be hard to share
1141+branches between several UnionMount since the whiteout in it is
1142+implemented in the inode on branch filesystem and always
1143+shared. According to Bharata's post, readdir does not seems to be
1144+finished yet.
1145+There are several missing features known in this implementations such as
1146+- for users, the inode number may change silently. eg. copy-up.
1147+- link(2) may break by copy-up.
1148+- read(2) may get an obsoleted filedata (fstat(2) too).
1149+- fcntl(F_SETLK) may be broken by copy-up.
1150+- unnecessary copy-up may happen, for example mmap(MAP_PRIVATE) after
1151+ open(O_RDWR).
1152+
7e9cd9fe
AM
1153+In linux-3.18, "overlay" filesystem (formerly known as "overlayfs") was
1154+merged into mainline. This is another implementation of UnionMount as a
1155+separated filesystem. All the limitations and known problems which
1156+UnionMount are equally inherited to "overlay" filesystem.
1157+
1158+Unionfs has a longer history. When I started implementing a stackable
1159+filesystem (Aug 2005), it already existed. It has virtual super_block,
1160+inode, dentry and file objects and they have an array pointing lower
1161+same kind objects. After contributing many patches for Unionfs, I
1162+re-started my project AUFS (Jun 2006).
53392da6
AM
1163+
1164+In AUFS, the structure of filesystem resembles to Unionfs, but I
1165+implemented my own ideas, approaches and enhancements and it became
1166+totally different one.
1167+
1168+Comparing DM snapshot and fs based implementation
1169+- the number of bytes to be copied between devices is much smaller.
1170+- the type of filesystem must be one and only.
1171+- the fs must be writable, no readonly fs, even for the lower original
1172+ device. so the compression fs will not be usable. but if we use
1173+ loopback mount, we may address this issue.
1174+ for instance,
1175+ mount /cdrom/squashfs.img /sq
1176+ losetup /sq/ext2.img
1177+ losetup /somewhere/cow
1178+ dmsetup "snapshot /dev/loop0 /dev/loop1 ..."
1179+- it will be difficult (or needs more operations) to extract the
1180+ difference between the original device and COW.
1181+- DM snapshot-merge may help a lot when users try merging. in the
1182+ fs-layer union, users will use rsync(1).
1183+
7e9cd9fe
AM
1184+You may want to read my old paper "Filesystems in LiveCD"
1185+(http://aufs.sourceforge.net/aufs2/report/sq/sq.pdf).
53392da6 1186+
7e9cd9fe
AM
1187+
1188+Several characters/aspects/persona of aufs
53392da6
AM
1189+----------------------------------------------------------------------
1190+
7e9cd9fe 1191+Aufs has several characters, aspects or persona.
53392da6
AM
1192+1. a filesystem, callee of VFS helper
1193+2. sub-VFS, caller of VFS helper for branches
1194+3. a virtual filesystem which maintains persistent inode number
1195+4. reader/writer of files on branches such like an application
1196+
1197+1. Callee of VFS Helper
1198+As an ordinary linux filesystem, aufs is a callee of VFS. For instance,
1199+unlink(2) from an application reaches sys_unlink() kernel function and
1200+then vfs_unlink() is called. vfs_unlink() is one of VFS helper and it
1201+calls filesystem specific unlink operation. Actually aufs implements the
1202+unlink operation but it behaves like a redirector.
1203+
1204+2. Caller of VFS Helper for Branches
1205+aufs_unlink() passes the unlink request to the branch filesystem as if
1206+it were called from VFS. So the called unlink operation of the branch
1207+filesystem acts as usual. As a caller of VFS helper, aufs should handle
1208+every necessary pre/post operation for the branch filesystem.
1209+- acquire the lock for the parent dir on a branch
1210+- lookup in a branch
1211+- revalidate dentry on a branch
1212+- mnt_want_write() for a branch
1213+- vfs_unlink() for a branch
1214+- mnt_drop_write() for a branch
1215+- release the lock on a branch
1216+
1217+3. Persistent Inode Number
1218+One of the most important issue for a filesystem is to maintain inode
1219+numbers. This is particularly important to support exporting a
1220+filesystem via NFS. Aufs is a virtual filesystem which doesn't have a
1221+backend block device for its own. But some storage is necessary to
7e9cd9fe
AM
1222+keep and maintain the inode numbers. It may be a large space and may not
1223+suit to keep in memory. Aufs rents some space from its first writable
1224+branch filesystem (by default) and creates file(s) on it. These files
1225+are created by aufs internally and removed soon (currently) keeping
1226+opened.
53392da6
AM
1227+Note: Because these files are removed, they are totally gone after
1228+ unmounting aufs. It means the inode numbers are not persistent
1229+ across unmount or reboot. I have a plan to make them really
1230+ persistent which will be important for aufs on NFS server.
1231+
1232+4. Read/Write Files Internally (copy-on-write)
1233+Because a branch can be readonly, when you write a file on it, aufs will
1234+"copy-up" it to the upper writable branch internally. And then write the
1235+originally requested thing to the file. Generally kernel doesn't
1236+open/read/write file actively. In aufs, even a single write may cause a
1237+internal "file copy". This behaviour is very similar to cp(1) command.
1238+
1239+Some people may think it is better to pass such work to user space
1240+helper, instead of doing in kernel space. Actually I am still thinking
1241+about it. But currently I have implemented it in kernel space.
1242diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt linux/Documentation/filesystems/aufs/design/02struct.txt
eca34b5c 1243--- /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 1244+++ linux/Documentation/filesystems/aufs/design/02struct.txt 2021-05-02 20:15:14.666670785 +0200
7e9cd9fe 1245@@ -0,0 +1,258 @@
53392da6 1246+
d58c55f2 1247+# Copyright (C) 2005-2020 Junjiro R. Okajima
53392da6
AM
1248+#
1249+# This program is free software; you can redistribute it and/or modify
1250+# it under the terms of the GNU General Public License as published by
1251+# the Free Software Foundation; either version 2 of the License, or
1252+# (at your option) any later version.
1253+#
1254+# This program is distributed in the hope that it will be useful,
1255+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1256+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1257+# GNU General Public License for more details.
1258+#
1259+# You should have received a copy of the GNU General Public License
523b37e3 1260+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1261+
1262+Basic Aufs Internal Structure
1263+
1264+Superblock/Inode/Dentry/File Objects
1265+----------------------------------------------------------------------
1266+As like an ordinary filesystem, aufs has its own
1267+superblock/inode/dentry/file objects. All these objects have a
1268+dynamically allocated array and store the same kind of pointers to the
1269+lower filesystem, branch.
1270+For example, when you build a union with one readwrite branch and one
1271+readonly, mounted /au, /rw and /ro respectively.
1272+- /au = /rw + /ro
1273+- /ro/fileA exists but /rw/fileA
1274+
1275+Aufs lookup operation finds /ro/fileA and gets dentry for that. These
1276+pointers are stored in a aufs dentry. The array in aufs dentry will be,
7e9cd9fe 1277+- [0] = NULL (because /rw/fileA doesn't exist)
53392da6
AM
1278+- [1] = /ro/fileA
1279+
1280+This style of an array is essentially same to the aufs
1281+superblock/inode/dentry/file objects.
1282+
1283+Because aufs supports manipulating branches, ie. add/delete/change
7e9cd9fe
AM
1284+branches dynamically, these objects has its own generation. When
1285+branches are changed, the generation in aufs superblock is
1286+incremented. And a generation in other object are compared when it is
1287+accessed. When a generation in other objects are obsoleted, aufs
1288+refreshes the internal array.
53392da6
AM
1289+
1290+
1291+Superblock
1292+----------------------------------------------------------------------
1293+Additionally aufs superblock has some data for policies to select one
1294+among multiple writable branches, XIB files, pseudo-links and kobject.
1295+See below in detail.
7e9cd9fe
AM
1296+About the policies which supports copy-down a directory, see
1297+wbr_policy.txt too.
53392da6
AM
1298+
1299+
1300+Branch and XINO(External Inode Number Translation Table)
1301+----------------------------------------------------------------------
1302+Every branch has its own xino (external inode number translation table)
1303+file. The xino file is created and unlinked by aufs internally. When two
1304+members of a union exist on the same filesystem, they share the single
1305+xino file.
1306+The struct of a xino file is simple, just a sequence of aufs inode
1307+numbers which is indexed by the lower inode number.
1308+In the above sample, assume the inode number of /ro/fileA is i111 and
1309+aufs assigns the inode number i999 for fileA. Then aufs writes 999 as
1310+4(8) bytes at 111 * 4(8) bytes offset in the xino file.
1311+
1312+When the inode numbers are not contiguous, the xino file will be sparse
1313+which has a hole in it and doesn't consume as much disk space as it
1314+might appear. If your branch filesystem consumes disk space for such
1315+holes, then you should specify 'xino=' option at mounting aufs.
1316+
7e9cd9fe
AM
1317+Aufs has a mount option to free the disk blocks for such holes in XINO
1318+files on tmpfs or ramdisk. But it is not so effective actually. If you
1319+meet a problem of disk shortage due to XINO files, then you should try
1320+"tmpfs-ino.patch" (and "vfs-ino.patch" too) in aufs4-standalone.git.
1321+The patch localizes the assignment inumbers per tmpfs-mount and avoid
1322+the holes in XINO files.
1323+
53392da6 1324+Also a writable branch has three kinds of "whiteout bases". All these
7e9cd9fe 1325+are existed when the branch is joined to aufs, and their names are
53392da6
AM
1326+whiteout-ed doubly, so that users will never see their names in aufs
1327+hierarchy.
7e9cd9fe 1328+1. a regular file which will be hardlinked to all whiteouts.
53392da6 1329+2. a directory to store a pseudo-link.
7e9cd9fe 1330+3. a directory to store an "orphan"-ed file temporary.
53392da6
AM
1331+
1332+1. Whiteout Base
1333+ When you remove a file on a readonly branch, aufs handles it as a
1334+ logical deletion and creates a whiteout on the upper writable branch
1335+ as a hardlink of this file in order not to consume inode on the
1336+ writable branch.
1337+2. Pseudo-link Dir
1338+ See below, Pseudo-link.
1339+3. Step-Parent Dir
1340+ When "fileC" exists on the lower readonly branch only and it is
1341+ opened and removed with its parent dir, and then user writes
1342+ something into it, then aufs copies-up fileC to this
1343+ directory. Because there is no other dir to store fileC. After
1344+ creating a file under this dir, the file is unlinked.
1345+
1346+Because aufs supports manipulating branches, ie. add/delete/change
7e9cd9fe
AM
1347+dynamically, a branch has its own id. When the branch order changes,
1348+aufs finds the new index by searching the branch id.
53392da6
AM
1349+
1350+
1351+Pseudo-link
1352+----------------------------------------------------------------------
1353+Assume "fileA" exists on the lower readonly branch only and it is
1354+hardlinked to "fileB" on the branch. When you write something to fileA,
1355+aufs copies-up it to the upper writable branch. Additionally aufs
1356+creates a hardlink under the Pseudo-link Directory of the writable
1357+branch. The inode of a pseudo-link is kept in aufs super_block as a
1358+simple list. If fileB is read after unlinking fileA, aufs returns
1359+filedata from the pseudo-link instead of the lower readonly
1360+branch. Because the pseudo-link is based upon the inode, to keep the
7e9cd9fe 1361+inode number by xino (see above) is essentially necessary.
53392da6
AM
1362+
1363+All the hardlinks under the Pseudo-link Directory of the writable branch
1364+should be restored in a proper location later. Aufs provides a utility
1365+to do this. The userspace helpers executed at remounting and unmounting
1366+aufs by default.
1367+During this utility is running, it puts aufs into the pseudo-link
1368+maintenance mode. In this mode, only the process which began the
1369+maintenance mode (and its child processes) is allowed to operate in
1370+aufs. Some other processes which are not related to the pseudo-link will
1371+be allowed to run too, but the rest have to return an error or wait
1372+until the maintenance mode ends. If a process already acquires an inode
1373+mutex (in VFS), it has to return an error.
1374+
1375+
1376+XIB(external inode number bitmap)
1377+----------------------------------------------------------------------
1378+Addition to the xino file per a branch, aufs has an external inode number
7e9cd9fe
AM
1379+bitmap in a superblock object. It is also an internal file such like a
1380+xino file.
53392da6
AM
1381+It is a simple bitmap to mark whether the aufs inode number is in-use or
1382+not.
1383+To reduce the file I/O, aufs prepares a single memory page to cache xib.
1384+
7e9cd9fe 1385+As well as XINO files, aufs has a feature to truncate/refresh XIB to
53392da6
AM
1386+reduce the number of consumed disk blocks for these files.
1387+
1388+
1389+Virtual or Vertical Dir, and Readdir in Userspace
1390+----------------------------------------------------------------------
1391+In order to support multiple layers (branches), aufs readdir operation
1392+constructs a virtual dir block on memory. For readdir, aufs calls
1393+vfs_readdir() internally for each dir on branches, merges their entries
1394+with eliminating the whiteout-ed ones, and sets it to file (dir)
1395+object. So the file object has its entry list until it is closed. The
1396+entry list will be updated when the file position is zero and becomes
7e9cd9fe 1397+obsoleted. This decision is made in aufs automatically.
53392da6
AM
1398+
1399+The dynamically allocated memory block for the name of entries has a
1400+unit of 512 bytes (by default) and stores the names contiguously (no
1401+padding). Another block for each entry is handled by kmem_cache too.
1402+During building dir blocks, aufs creates hash list and judging whether
1403+the entry is whiteouted by its upper branch or already listed.
1404+The merged result is cached in the corresponding inode object and
1405+maintained by a customizable life-time option.
1406+
1407+Some people may call it can be a security hole or invite DoS attack
1408+since the opened and once readdir-ed dir (file object) holds its entry
1409+list and becomes a pressure for system memory. But I'd say it is similar
1410+to files under /proc or /sys. The virtual files in them also holds a
1411+memory page (generally) while they are opened. When an idea to reduce
1412+memory for them is introduced, it will be applied to aufs too.
1413+For those who really hate this situation, I've developed readdir(3)
1414+library which operates this merging in userspace. You just need to set
1415+LD_PRELOAD environment variable, and aufs will not consume no memory in
1416+kernel space for readdir(3).
1417+
1418+
1419+Workqueue
1420+----------------------------------------------------------------------
1421+Aufs sometimes requires privilege access to a branch. For instance,
1422+in copy-up/down operation. When a user process is going to make changes
1423+to a file which exists in the lower readonly branch only, and the mode
1424+of one of ancestor directories may not be writable by a user
1425+process. Here aufs copy-up the file with its ancestors and they may
1426+require privilege to set its owner/group/mode/etc.
1427+This is a typical case of a application character of aufs (see
1428+Introduction).
1429+
1430+Aufs uses workqueue synchronously for this case. It creates its own
1431+workqueue. The workqueue is a kernel thread and has privilege. Aufs
1432+passes the request to call mkdir or write (for example), and wait for
1433+its completion. This approach solves a problem of a signal handler
1434+simply.
1435+If aufs didn't adopt the workqueue and changed the privilege of the
7e9cd9fe
AM
1436+process, then the process may receive the unexpected SIGXFSZ or other
1437+signals.
53392da6
AM
1438+
1439+Also aufs uses the system global workqueue ("events" kernel thread) too
1440+for asynchronous tasks, such like handling inotify/fsnotify, re-creating a
1441+whiteout base and etc. This is unrelated to a privilege.
1442+Most of aufs operation tries acquiring a rw_semaphore for aufs
1443+superblock at the beginning, at the same time waits for the completion
1444+of all queued asynchronous tasks.
1445+
1446+
1447+Whiteout
1448+----------------------------------------------------------------------
1449+The whiteout in aufs is very similar to Unionfs's. That is represented
1450+by its filename. UnionMount takes an approach of a file mode, but I am
1451+afraid several utilities (find(1) or something) will have to support it.
1452+
1453+Basically the whiteout represents "logical deletion" which stops aufs to
1454+lookup further, but also it represents "dir is opaque" which also stop
7e9cd9fe 1455+further lookup.
53392da6
AM
1456+
1457+In aufs, rmdir(2) and rename(2) for dir uses whiteout alternatively.
1458+In order to make several functions in a single systemcall to be
1459+revertible, aufs adopts an approach to rename a directory to a temporary
1460+unique whiteouted name.
1461+For example, in rename(2) dir where the target dir already existed, aufs
1462+renames the target dir to a temporary unique whiteouted name before the
7e9cd9fe 1463+actual rename on a branch, and then handles other actions (make it opaque,
53392da6
AM
1464+update the attributes, etc). If an error happens in these actions, aufs
1465+simply renames the whiteouted name back and returns an error. If all are
1466+succeeded, aufs registers a function to remove the whiteouted unique
1467+temporary name completely and asynchronously to the system global
1468+workqueue.
1469+
1470+
1471+Copy-up
1472+----------------------------------------------------------------------
1473+It is a well-known feature or concept.
1474+When user modifies a file on a readonly branch, aufs operate "copy-up"
1475+internally and makes change to the new file on the upper writable branch.
1476+When the trigger systemcall does not update the timestamps of the parent
1477+dir, aufs reverts it after copy-up.
c2b27bf2
AM
1478+
1479+
1480+Move-down (aufs3.9 and later)
1481+----------------------------------------------------------------------
1482+"Copy-up" is one of the essential feature in aufs. It copies a file from
1483+the lower readonly branch to the upper writable branch when a user
1484+changes something about the file.
1485+"Move-down" is an opposite action of copy-up. Basically this action is
1486+ran manually instead of automatically and internally.
076b876e
AM
1487+For desgin and implementation, aufs has to consider these issues.
1488+- whiteout for the file may exist on the lower branch.
1489+- ancestor directories may not exist on the lower branch.
1490+- diropq for the ancestor directories may exist on the upper branch.
1491+- free space on the lower branch will reduce.
1492+- another access to the file may happen during moving-down, including
7e9cd9fe 1493+ UDBA (see "Revalidate Dentry and UDBA").
076b876e
AM
1494+- the file should not be hard-linked nor pseudo-linked. they should be
1495+ handled by auplink utility later.
c2b27bf2
AM
1496+
1497+Sometimes users want to move-down a file from the upper writable branch
1498+to the lower readonly or writable branch. For instance,
1499+- the free space of the upper writable branch is going to run out.
1500+- create a new intermediate branch between the upper and lower branch.
1501+- etc.
1502+
1503+For this purpose, use "aumvdown" command in aufs-util.git.
b912730e 1504diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/03atomic_open.txt linux/Documentation/filesystems/aufs/design/03atomic_open.txt
eca34b5c 1505--- /usr/share/empty/Documentation/filesystems/aufs/design/03atomic_open.txt 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 1506+++ linux/Documentation/filesystems/aufs/design/03atomic_open.txt 2021-05-02 20:15:14.666670785 +0200
b912730e
AM
1507@@ -0,0 +1,85 @@
1508+
d58c55f2 1509+# Copyright (C) 2015-2020 Junjiro R. Okajima
b912730e
AM
1510+#
1511+# This program is free software; you can redistribute it and/or modify
1512+# it under the terms of the GNU General Public License as published by
1513+# the Free Software Foundation; either version 2 of the License, or
1514+# (at your option) any later version.
1515+#
1516+# This program is distributed in the hope that it will be useful,
1517+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1518+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1519+# GNU General Public License for more details.
1520+#
1521+# You should have received a copy of the GNU General Public License
1522+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1523+
1524+Support for a branch who has its ->atomic_open()
1525+----------------------------------------------------------------------
1526+The filesystems who implement its ->atomic_open() are not majority. For
1527+example NFSv4 does, and aufs should call NFSv4 ->atomic_open,
1528+particularly for open(O_CREAT|O_EXCL, 0400) case. Other than
1529+->atomic_open(), NFSv4 returns an error for this open(2). While I am not
1530+sure whether all filesystems who have ->atomic_open() behave like this,
1531+but NFSv4 surely returns the error.
1532+
1533+In order to support ->atomic_open() for aufs, there are a few
1534+approaches.
1535+
1536+A. Introduce aufs_atomic_open()
1537+ - calls one of VFS:do_last(), lookup_open() or atomic_open() for
1538+ branch fs.
1539+B. Introduce aufs_atomic_open() calling create, open and chmod. this is
1540+ an aufs user Pip Cet's approach
1541+ - calls aufs_create(), VFS finish_open() and notify_change().
1542+ - pass fake-mode to finish_open(), and then correct the mode by
1543+ notify_change().
1544+C. Extend aufs_open() to call branch fs's ->atomic_open()
1545+ - no aufs_atomic_open().
1546+ - aufs_lookup() registers the TID to an aufs internal object.
1547+ - aufs_create() does nothing when the matching TID is registered, but
1548+ registers the mode.
1549+ - aufs_open() calls branch fs's ->atomic_open() when the matching
1550+ TID is registered.
1551+D. Extend aufs_open() to re-try branch fs's ->open() with superuser's
1552+ credential
1553+ - no aufs_atomic_open().
1554+ - aufs_create() registers the TID to an internal object. this info
1555+ represents "this process created this file just now."
1556+ - when aufs gets EACCES from branch fs's ->open(), then confirm the
1557+ registered TID and re-try open() with superuser's credential.
1558+
1559+Pros and cons for each approach.
1560+
1561+A.
1562+ - straightforward but highly depends upon VFS internal.
1563+ - the atomic behavaiour is kept.
1564+ - some of parameters such as nameidata are hard to reproduce for
1565+ branch fs.
1566+ - large overhead.
1567+B.
1568+ - easy to implement.
1569+ - the atomic behavaiour is lost.
1570+C.
1571+ - the atomic behavaiour is kept.
1572+ - dirty and tricky.
1573+ - VFS checks whether the file is created correctly after calling
1574+ ->create(), which means this approach doesn't work.
1575+D.
1576+ - easy to implement.
1577+ - the atomic behavaiour is lost.
1578+ - to open a file with superuser's credential and give it to a user
1579+ process is a bad idea, since the file object keeps the credential
1580+ in it. It may affect LSM or something. This approach doesn't work
1581+ either.
1582+
1583+The approach A is ideal, but it hard to implement. So here is a
1584+variation of A, which is to be implemented.
1585+
1586+A-1. Introduce aufs_atomic_open()
1587+ - calls branch fs ->atomic_open() if exists. otherwise calls
1588+ vfs_create() and finish_open().
1589+ - the demerit is that the several checks after branch fs
1590+ ->atomic_open() are lost. in the ordinary case, the checks are
1591+ done by VFS:do_last(), lookup_open() and atomic_open(). some can
1592+ be implemented in aufs, but not all I am afraid.
53392da6 1593diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt linux/Documentation/filesystems/aufs/design/03lookup.txt
eca34b5c 1594--- /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 1595+++ linux/Documentation/filesystems/aufs/design/03lookup.txt 2021-05-02 20:15:14.666670785 +0200
7e9cd9fe 1596@@ -0,0 +1,113 @@
53392da6 1597+
d58c55f2 1598+# Copyright (C) 2005-2020 Junjiro R. Okajima
53392da6
AM
1599+#
1600+# This program is free software; you can redistribute it and/or modify
1601+# it under the terms of the GNU General Public License as published by
1602+# the Free Software Foundation; either version 2 of the License, or
1603+# (at your option) any later version.
1604+#
1605+# This program is distributed in the hope that it will be useful,
1606+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1607+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1608+# GNU General Public License for more details.
1609+#
1610+# You should have received a copy of the GNU General Public License
523b37e3 1611+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1612+
1613+Lookup in a Branch
1614+----------------------------------------------------------------------
1615+Since aufs has a character of sub-VFS (see Introduction), it operates
7e9cd9fe
AM
1616+lookup for branches as VFS does. It may be a heavy work. But almost all
1617+lookup operation in aufs is the simplest case, ie. lookup only an entry
1618+directly connected to its parent. Digging down the directory hierarchy
1619+is unnecessary. VFS has a function lookup_one_len() for that use, and
1620+aufs calls it.
1621+
1622+When a branch is a remote filesystem, aufs basically relies upon its
53392da6
AM
1623+->d_revalidate(), also aufs forces the hardest revalidate tests for
1624+them.
1625+For d_revalidate, aufs implements three levels of revalidate tests. See
1626+"Revalidate Dentry and UDBA" in detail.
1627+
1628+
076b876e
AM
1629+Test Only the Highest One for the Directory Permission (dirperm1 option)
1630+----------------------------------------------------------------------
1631+Let's try case study.
1632+- aufs has two branches, upper readwrite and lower readonly.
1633+ /au = /rw + /ro
1634+- "dirA" exists under /ro, but /rw. and its mode is 0700.
1635+- user invoked "chmod a+rx /au/dirA"
1636+- the internal copy-up is activated and "/rw/dirA" is created and its
7e9cd9fe 1637+ permission bits are set to world readable.
076b876e
AM
1638+- then "/au/dirA" becomes world readable?
1639+
1640+In this case, /ro/dirA is still 0700 since it exists in readonly branch,
1641+or it may be a natively readonly filesystem. If aufs respects the lower
1642+branch, it should not respond readdir request from other users. But user
1643+allowed it by chmod. Should really aufs rejects showing the entries
1644+under /ro/dirA?
1645+
7e9cd9fe
AM
1646+To be honest, I don't have a good solution for this case. So aufs
1647+implements 'dirperm1' and 'nodirperm1' mount options, and leave it to
1648+users.
076b876e
AM
1649+When dirperm1 is specified, aufs checks only the highest one for the
1650+directory permission, and shows the entries. Otherwise, as usual, checks
1651+every dir existing on all branches and rejects the request.
1652+
1653+As a side effect, dirperm1 option improves the performance of aufs
1654+because the number of permission check is reduced when the number of
1655+branch is many.
1656+
1657+
53392da6
AM
1658+Revalidate Dentry and UDBA (User's Direct Branch Access)
1659+----------------------------------------------------------------------
1660+Generally VFS helpers re-validate a dentry as a part of lookup.
1661+0. digging down the directory hierarchy.
1662+1. lock the parent dir by its i_mutex.
1663+2. lookup the final (child) entry.
1664+3. revalidate it.
1665+4. call the actual operation (create, unlink, etc.)
1666+5. unlock the parent dir
1667+
1668+If the filesystem implements its ->d_revalidate() (step 3), then it is
1669+called. Actually aufs implements it and checks the dentry on a branch is
1670+still valid.
1671+But it is not enough. Because aufs has to release the lock for the
1672+parent dir on a branch at the end of ->lookup() (step 2) and
1673+->d_revalidate() (step 3) while the i_mutex of the aufs dir is still
1674+held by VFS.
1675+If the file on a branch is changed directly, eg. bypassing aufs, after
1676+aufs released the lock, then the subsequent operation may cause
1677+something unpleasant result.
1678+
1679+This situation is a result of VFS architecture, ->lookup() and
1680+->d_revalidate() is separated. But I never say it is wrong. It is a good
1681+design from VFS's point of view. It is just not suitable for sub-VFS
1682+character in aufs.
1683+
1684+Aufs supports such case by three level of revalidation which is
1685+selectable by user.
1686+1. Simple Revalidate
1687+ Addition to the native flow in VFS's, confirm the child-parent
1688+ relationship on the branch just after locking the parent dir on the
1689+ branch in the "actual operation" (step 4). When this validation
1690+ fails, aufs returns EBUSY. ->d_revalidate() (step 3) in aufs still
1691+ checks the validation of the dentry on branches.
1692+2. Monitor Changes Internally by Inotify/Fsnotify
1693+ Addition to above, in the "actual operation" (step 4) aufs re-lookup
1694+ the dentry on the branch, and returns EBUSY if it finds different
1695+ dentry.
1696+ Additionally, aufs sets the inotify/fsnotify watch for every dir on branches
1697+ during it is in cache. When the event is notified, aufs registers a
1698+ function to kernel 'events' thread by schedule_work(). And the
1699+ function sets some special status to the cached aufs dentry and inode
1700+ private data. If they are not cached, then aufs has nothing to
1701+ do. When the same file is accessed through aufs (step 0-3) later,
1702+ aufs will detect the status and refresh all necessary data.
1703+ In this mode, aufs has to ignore the event which is fired by aufs
1704+ itself.
1705+3. No Extra Validation
1706+ This is the simplest test and doesn't add any additional revalidation
7e9cd9fe 1707+ test, and skip the revalidation in step 4. It is useful and improves
53392da6
AM
1708+ aufs performance when system surely hide the aufs branches from user,
1709+ by over-mounting something (or another method).
1710diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt linux/Documentation/filesystems/aufs/design/04branch.txt
eca34b5c 1711--- /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 1712+++ linux/Documentation/filesystems/aufs/design/04branch.txt 2021-05-02 20:15:14.670004120 +0200
7e9cd9fe 1713@@ -0,0 +1,74 @@
53392da6 1714+
d58c55f2 1715+# Copyright (C) 2005-2020 Junjiro R. Okajima
53392da6
AM
1716+#
1717+# This program is free software; you can redistribute it and/or modify
1718+# it under the terms of the GNU General Public License as published by
1719+# the Free Software Foundation; either version 2 of the License, or
1720+# (at your option) any later version.
1721+#
1722+# This program is distributed in the hope that it will be useful,
1723+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1724+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1725+# GNU General Public License for more details.
1726+#
1727+# You should have received a copy of the GNU General Public License
523b37e3 1728+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1729+
1730+Branch Manipulation
1731+
1732+Since aufs supports dynamic branch manipulation, ie. add/remove a branch
1733+and changing its permission/attribute, there are a lot of works to do.
1734+
1735+
1736+Add a Branch
1737+----------------------------------------------------------------------
1738+o Confirm the adding dir exists outside of aufs, including loopback
7e9cd9fe 1739+ mount, and its various attributes.
53392da6
AM
1740+o Initialize the xino file and whiteout bases if necessary.
1741+ See struct.txt.
1742+
1743+o Check the owner/group/mode of the directory
1744+ When the owner/group/mode of the adding directory differs from the
1745+ existing branch, aufs issues a warning because it may impose a
1746+ security risk.
1747+ For example, when a upper writable branch has a world writable empty
1748+ top directory, a malicious user can create any files on the writable
1749+ branch directly, like copy-up and modify manually. If something like
1750+ /etc/{passwd,shadow} exists on the lower readonly branch but the upper
1751+ writable branch, and the writable branch is world-writable, then a
1752+ malicious guy may create /etc/passwd on the writable branch directly
1753+ and the infected file will be valid in aufs.
7e9cd9fe 1754+ I am afraid it can be a security issue, but aufs can do nothing except
53392da6
AM
1755+ producing a warning.
1756+
1757+
1758+Delete a Branch
1759+----------------------------------------------------------------------
1760+o Confirm the deleting branch is not busy
1761+ To be general, there is one merit to adopt "remount" interface to
1762+ manipulate branches. It is to discard caches. At deleting a branch,
1763+ aufs checks the still cached (and connected) dentries and inodes. If
1764+ there are any, then they are all in-use. An inode without its
1765+ corresponding dentry can be alive alone (for example, inotify/fsnotify case).
1766+
1767+ For the cached one, aufs checks whether the same named entry exists on
1768+ other branches.
1769+ If the cached one is a directory, because aufs provides a merged view
1770+ to users, as long as one dir is left on any branch aufs can show the
1771+ dir to users. In this case, the branch can be removed from aufs.
1772+ Otherwise aufs rejects deleting the branch.
1773+
1774+ If any file on the deleting branch is opened by aufs, then aufs
1775+ rejects deleting.
1776+
1777+
1778+Modify the Permission of a Branch
1779+----------------------------------------------------------------------
1780+o Re-initialize or remove the xino file and whiteout bases if necessary.
1781+ See struct.txt.
1782+
1783+o rw --> ro: Confirm the modifying branch is not busy
1784+ Aufs rejects the request if any of these conditions are true.
1785+ - a file on the branch is mmap-ed.
1786+ - a regular file on the branch is opened for write and there is no
1787+ same named entry on the upper branch.
1788diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt linux/Documentation/filesystems/aufs/design/05wbr_policy.txt
eca34b5c 1789--- /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 1790+++ linux/Documentation/filesystems/aufs/design/05wbr_policy.txt 2021-05-02 20:15:14.670004120 +0200
523b37e3 1791@@ -0,0 +1,64 @@
53392da6 1792+
d58c55f2 1793+# Copyright (C) 2005-2020 Junjiro R. Okajima
53392da6
AM
1794+#
1795+# This program is free software; you can redistribute it and/or modify
1796+# it under the terms of the GNU General Public License as published by
1797+# the Free Software Foundation; either version 2 of the License, or
1798+# (at your option) any later version.
1799+#
1800+# This program is distributed in the hope that it will be useful,
1801+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1802+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1803+# GNU General Public License for more details.
1804+#
1805+# You should have received a copy of the GNU General Public License
523b37e3 1806+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1807+
1808+Policies to Select One among Multiple Writable Branches
1809+----------------------------------------------------------------------
1810+When the number of writable branch is more than one, aufs has to decide
1811+the target branch for file creation or copy-up. By default, the highest
1812+writable branch which has the parent (or ancestor) dir of the target
1813+file is chosen (top-down-parent policy).
1814+By user's request, aufs implements some other policies to select the
7e9cd9fe
AM
1815+writable branch, for file creation several policies, round-robin,
1816+most-free-space, and other policies. For copy-up, top-down-parent,
1817+bottom-up-parent, bottom-up and others.
53392da6
AM
1818+
1819+As expected, the round-robin policy selects the branch in circular. When
1820+you have two writable branches and creates 10 new files, 5 files will be
1821+created for each branch. mkdir(2) systemcall is an exception. When you
1822+create 10 new directories, all will be created on the same branch.
1823+And the most-free-space policy selects the one which has most free
1824+space among the writable branches. The amount of free space will be
1825+checked by aufs internally, and users can specify its time interval.
1826+
1827+The policies for copy-up is more simple,
1828+top-down-parent is equivalent to the same named on in create policy,
1829+bottom-up-parent selects the writable branch where the parent dir
1830+exists and the nearest upper one from the copyup-source,
1831+bottom-up selects the nearest upper writable branch from the
1832+copyup-source, regardless the existence of the parent dir.
1833+
1834+There are some rules or exceptions to apply these policies.
1835+- If there is a readonly branch above the policy-selected branch and
1836+ the parent dir is marked as opaque (a variation of whiteout), or the
1837+ target (creating) file is whiteout-ed on the upper readonly branch,
1838+ then the result of the policy is ignored and the target file will be
1839+ created on the nearest upper writable branch than the readonly branch.
1840+- If there is a writable branch above the policy-selected branch and
1841+ the parent dir is marked as opaque or the target file is whiteouted
1842+ on the branch, then the result of the policy is ignored and the target
1843+ file will be created on the highest one among the upper writable
1844+ branches who has diropq or whiteout. In case of whiteout, aufs removes
1845+ it as usual.
1846+- link(2) and rename(2) systemcalls are exceptions in every policy.
1847+ They try selecting the branch where the source exists as possible
1848+ since copyup a large file will take long time. If it can't be,
1849+ ie. the branch where the source exists is readonly, then they will
1850+ follow the copyup policy.
1851+- There is an exception for rename(2) when the target exists.
1852+ If the rename target exists, aufs compares the index of the branches
1853+ where the source and the target exists and selects the higher
1854+ one. If the selected branch is readonly, then aufs follows the
1855+ copyup policy.
8b6a4947 1856diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.dot linux/Documentation/filesystems/aufs/design/06dirren.dot
eca34b5c 1857--- /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.dot 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 1858+++ linux/Documentation/filesystems/aufs/design/06dirren.dot 2021-05-02 20:15:14.670004120 +0200
8b6a4947
AM
1859@@ -0,0 +1,31 @@
1860+
1861+// to view this graph, run dot(1) command in GRAPHVIZ.
1862+
1863+digraph G {
1864+node [shape=box];
1865+whinfo [label="detailed info file\n(lower_brid_root-hinum, h_inum, namelen, old name)"];
1866+
1867+node [shape=oval];
1868+
1869+aufs_rename -> whinfo [label="store/remove"];
1870+
1871+node [shape=oval];
1872+inode_list [label="h_inum list in branch\ncache"];
1873+
1874+node [shape=box];
1875+whinode [label="h_inum list file"];
1876+
1877+node [shape=oval];
1878+brmgmt [label="br_add/del/mod/umount"];
1879+
1880+brmgmt -> inode_list [label="create/remove"];
1881+brmgmt -> whinode [label="load/store"];
1882+
1883+inode_list -> whinode [style=dashed,dir=both];
1884+
1885+aufs_rename -> inode_list [label="add/del"];
1886+
1887+aufs_lookup -> inode_list [label="search"];
1888+
1889+aufs_lookup -> whinfo [label="load/remove"];
1890+}
1891diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.txt linux/Documentation/filesystems/aufs/design/06dirren.txt
eca34b5c 1892--- /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.txt 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 1893+++ linux/Documentation/filesystems/aufs/design/06dirren.txt 2021-05-02 20:15:14.670004120 +0200
8b6a4947
AM
1894@@ -0,0 +1,102 @@
1895+
d58c55f2 1896+# Copyright (C) 2017-2020 Junjiro R. Okajima
8b6a4947
AM
1897+#
1898+# This program is free software; you can redistribute it and/or modify
1899+# it under the terms of the GNU General Public License as published by
1900+# the Free Software Foundation; either version 2 of the License, or
1901+# (at your option) any later version.
1902+#
1903+# This program is distributed in the hope that it will be useful,
1904+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1905+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1906+# GNU General Public License for more details.
1907+#
1908+# You should have received a copy of the GNU General Public License
1909+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1910+
1911+Special handling for renaming a directory (DIRREN)
1912+----------------------------------------------------------------------
1913+First, let's assume we have a simple usecase.
1914+
1915+- /u = /rw + /ro
1916+- /rw/dirA exists
1917+- /ro/dirA and /ro/dirA/file exist too
1918+- there is no dirB on both branches
1919+- a user issues rename("dirA", "dirB")
1920+
1921+Now, what should aufs behave against this rename(2)?
1922+There are a few possible cases.
1923+
1924+A. returns EROFS.
1925+ since dirA exists on a readonly branch which cannot be renamed.
1926+B. returns EXDEV.
1927+ it is possible to copy-up dirA (only the dir itself), but the child
1928+ entries ("file" in this case) should not be. it must be a bad
1929+ approach to copy-up recursively.
1930+C. returns a success.
1931+ even the branch /ro is readonly, aufs tries renaming it. Obviously it
1932+ is a violation of aufs' policy.
1933+D. construct an extra information which indicates that /ro/dirA should
1934+ be handled as the name of dirB.
1935+ overlayfs has a similar feature called REDIRECT.
1936+
1937+Until now, aufs implements the case B only which returns EXDEV, and
1938+expects the userspace application behaves like mv(1) which tries
1939+issueing rename(2) recursively.
1940+
1941+A new aufs feature called DIRREN is introduced which implements the case
1942+D. There are several "extra information" added.
1943+
1944+1. detailed info per renamed directory
1945+ path: /rw/dirB/$AUFS_WH_DR_INFO_PFX.<lower branch-id>
1946+2. the inode-number list of directories on a branch
1947+ path: /rw/dirB/$AUFS_WH_DR_BRHINO
1948+
1949+The filename of "detailed info per directory" represents the lower
1950+branch, and its format is
1951+- a type of the branch id
1952+ one of these.
1953+ + uuid (not implemented yet)
1954+ + fsid
1955+ + dev
1956+- the inode-number of the branch root dir
1957+
1958+And it contains these info in a single regular file.
1959+- magic number
1960+- branch's inode-number of the logically renamed dir
1961+- the name of the before-renamed dir
1962+
1963+The "detailed info per directory" file is created in aufs rename(2), and
1964+loaded in any lookup.
1965+The info is considered in lookup for the matching case only. Here
1966+"matching" means that the root of branch (in the info filename) is same
1967+to the current looking-up branch. After looking-up the before-renamed
1968+name, the inode-number is compared. And the matched dentry is used.
1969+
1970+The "inode-number list of directories" is a regular file which contains
1971+simply the inode-numbers on the branch. The file is created or updated
1972+in removing the branch, and loaded in adding the branch. Its lifetime is
1973+equal to the branch.
1974+The list is refered in lookup, and when the current target inode is
1975+found in the list, the aufs tries loading the "detailed info per
1976+directory" and get the changed and valid name of the dir.
1977+
1978+Theoretically these "extra informaiton" may be able to be put into XATTR
1979+in the dir inode. But aufs doesn't choose this way because
1980+1. XATTR may not be supported by the branch (or its configuration)
1981+2. XATTR may have its size limit.
1982+3. XATTR may be less easy to convert than a regular file, when the
1983+ format of the info is changed in the future.
1984+At the same time, I agree that the regular file approach is much slower
1985+than XATTR approach. So, in the future, aufs may take the XATTR or other
1986+better approach.
1987+
1988+This DIRREN feature is enabled by aufs configuration, and is activated
1989+by a new mount option.
1990+
1991+For the more complicated case, there is a work with UDBA option, which
1992+is to dected the direct access to the branches (by-passing aufs) and to
1993+maintain the cashes in aufs. Since a single cached aufs dentry may
1994+contains two names, before- and after-rename, the name comparision in
1995+UDBA handler may not work correctly. In this case, the behaviour will be
1996+equivalen to udba=reval case.
076b876e 1997diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06fhsm.txt linux/Documentation/filesystems/aufs/design/06fhsm.txt
eca34b5c 1998--- /usr/share/empty/Documentation/filesystems/aufs/design/06fhsm.txt 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 1999+++ linux/Documentation/filesystems/aufs/design/06fhsm.txt 2021-05-02 20:15:14.670004120 +0200
076b876e
AM
2000@@ -0,0 +1,120 @@
2001+
d58c55f2 2002+# Copyright (C) 2011-2020 Junjiro R. Okajima
076b876e
AM
2003+#
2004+# This program is free software; you can redistribute it and/or modify
2005+# it under the terms of the GNU General Public License as published by
2006+# the Free Software Foundation; either version 2 of the License, or
2007+# (at your option) any later version.
2008+#
2009+# This program is distributed in the hope that it will be useful,
2010+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2011+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2012+# GNU General Public License for more details.
2013+#
2014+# You should have received a copy of the GNU General Public License
2015+# along with this program; if not, write to the Free Software
2016+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2017+
2018+
2019+File-based Hierarchical Storage Management (FHSM)
2020+----------------------------------------------------------------------
2021+Hierarchical Storage Management (or HSM) is a well-known feature in the
2022+storage world. Aufs provides this feature as file-based with multiple
7e9cd9fe 2023+writable branches, based upon the principle of "Colder, the Lower".
076b876e 2024+Here the word "colder" means that the less used files, and "lower" means
7e9cd9fe 2025+that the position in the order of the stacked branches vertically.
076b876e
AM
2026+These multiple writable branches are prioritized, ie. the topmost one
2027+should be the fastest drive and be used heavily.
2028+
2029+o Characters in aufs FHSM story
2030+- aufs itself and a new branch attribute.
2031+- a new ioctl interface to move-down and to establish a connection with
2032+ the daemon ("move-down" is a converse of "copy-up").
2033+- userspace tool and daemon.
2034+
2035+The userspace daemon establishes a connection with aufs and waits for
2036+the notification. The notified information is very similar to struct
2037+statfs containing the number of consumed blocks and inodes.
2038+When the consumed blocks/inodes of a branch exceeds the user-specified
2039+upper watermark, the daemon activates its move-down process until the
2040+consumed blocks/inodes reaches the user-specified lower watermark.
2041+
2042+The actual move-down is done by aufs based upon the request from
2043+user-space since we need to maintain the inode number and the internal
2044+pointer arrays in aufs.
2045+
2046+Currently aufs FHSM handles the regular files only. Additionally they
2047+must not be hard-linked nor pseudo-linked.
2048+
2049+
2050+o Cowork of aufs and the user-space daemon
2051+ During the userspace daemon established the connection, aufs sends a
2052+ small notification to it whenever aufs writes something into the
2053+ writable branch. But it may cost high since aufs issues statfs(2)
2054+ internally. So user can specify a new option to cache the
2055+ info. Actually the notification is controlled by these factors.
2056+ + the specified cache time.
2057+ + classified as "force" by aufs internally.
2058+ Until the specified time expires, aufs doesn't send the info
2059+ except the forced cases. When aufs decide forcing, the info is always
2060+ notified to userspace.
2061+ For example, the number of free inodes is generally large enough and
2062+ the shortage of it happens rarely. So aufs doesn't force the
2063+ notification when creating a new file, directory and others. This is
2064+ the typical case which aufs doesn't force.
2065+ When aufs writes the actual filedata and the files consumes any of new
2066+ blocks, the aufs forces notifying.
2067+
2068+
2069+o Interfaces in aufs
2070+- New branch attribute.
2071+ + fhsm
2072+ Specifies that the branch is managed by FHSM feature. In other word,
2073+ participant in the FHSM.
2074+ When nofhsm is set to the branch, it will not be the source/target
2075+ branch of the move-down operation. This attribute is set
2076+ independently from coo and moo attributes, and if you want full
2077+ FHSM, you should specify them as well.
2078+- New mount option.
2079+ + fhsm_sec
2080+ Specifies a second to suppress many less important info to be
2081+ notified.
2082+- New ioctl.
2083+ + AUFS_CTL_FHSM_FD
2084+ create a new file descriptor which userspace can read the notification
2085+ (a subset of struct statfs) from aufs.
2086+- Module parameter 'brs'
2087+ It has to be set to 1. Otherwise the new mount option 'fhsm' will not
2088+ be set.
2089+- mount helpers /sbin/mount.aufs and /sbin/umount.aufs
2090+ When there are two or more branches with fhsm attributes,
2091+ /sbin/mount.aufs invokes the user-space daemon and /sbin/umount.aufs
2092+ terminates it. As a result of remounting and branch-manipulation, the
2093+ number of branches with fhsm attribute can be one. In this case,
2094+ /sbin/mount.aufs will terminate the user-space daemon.
2095+
2096+
2097+Finally the operation is done as these steps in kernel-space.
2098+- make sure that,
2099+ + no one else is using the file.
2100+ + the file is not hard-linked.
2101+ + the file is not pseudo-linked.
2102+ + the file is a regular file.
2103+ + the parent dir is not opaqued.
2104+- find the target writable branch.
2105+- make sure the file is not whiteout-ed by the upper (than the target)
2106+ branch.
2107+- make the parent dir on the target branch.
2108+- mutex lock the inode on the branch.
2109+- unlink the whiteout on the target branch (if exists).
2110+- lookup and create the whiteout-ed temporary name on the target branch.
2111+- copy the file as the whiteout-ed temporary name on the target branch.
2112+- rename the whiteout-ed temporary name to the original name.
2113+- unlink the file on the source branch.
2114+- maintain the internal pointer array and the external inode number
2115+ table (XINO).
2116+- maintain the timestamps and other attributes of the parent dir and the
2117+ file.
2118+
2119+And of course, in every step, an error may happen. So the operation
2120+should restore the original file state after an error happens.
53392da6 2121diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt linux/Documentation/filesystems/aufs/design/06mmap.txt
eca34b5c 2122--- /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 2123+++ linux/Documentation/filesystems/aufs/design/06mmap.txt 2021-05-02 20:15:14.670004120 +0200
b912730e 2124@@ -0,0 +1,72 @@
53392da6 2125+
d58c55f2 2126+# Copyright (C) 2005-2020 Junjiro R. Okajima
53392da6
AM
2127+#
2128+# This program is free software; you can redistribute it and/or modify
2129+# it under the terms of the GNU General Public License as published by
2130+# the Free Software Foundation; either version 2 of the License, or
2131+# (at your option) any later version.
2132+#
2133+# This program is distributed in the hope that it will be useful,
2134+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2135+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2136+# GNU General Public License for more details.
2137+#
2138+# You should have received a copy of the GNU General Public License
523b37e3 2139+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
2140+
2141+mmap(2) -- File Memory Mapping
2142+----------------------------------------------------------------------
2143+In aufs, the file-mapped pages are handled by a branch fs directly, no
2144+interaction with aufs. It means aufs_mmap() calls the branch fs's
2145+->mmap().
2146+This approach is simple and good, but there is one problem.
7e9cd9fe 2147+Under /proc, several entries show the mmapped files by its path (with
53392da6
AM
2148+device and inode number), and the printed path will be the path on the
2149+branch fs's instead of virtual aufs's.
2150+This is not a problem in most cases, but some utilities lsof(1) (and its
2151+user) may expect the path on aufs.
2152+
2153+To address this issue, aufs adds a new member called vm_prfile in struct
2154+vm_area_struct (and struct vm_region). The original vm_file points to
2155+the file on the branch fs in order to handle everything correctly as
2156+usual. The new vm_prfile points to a virtual file in aufs, and the
2157+show-functions in procfs refers to vm_prfile if it is set.
2158+Also we need to maintain several other places where touching vm_file
2159+such like
2160+- fork()/clone() copies vma and the reference count of vm_file is
2161+ incremented.
2162+- merging vma maintains the ref count too.
2163+
7e9cd9fe 2164+This is not a good approach. It just fakes the printed path. But it
53392da6
AM
2165+leaves all behaviour around f_mapping unchanged. This is surely an
2166+advantage.
2167+Actually aufs had adopted another complicated approach which calls
2168+generic_file_mmap() and handles struct vm_operations_struct. In this
2169+approach, aufs met a hard problem and I could not solve it without
2170+switching the approach.
b912730e
AM
2171+
2172+There may be one more another approach which is
2173+- bind-mount the branch-root onto the aufs-root internally
2174+- grab the new vfsmount (ie. struct mount)
2175+- lazy-umount the branch-root internally
2176+- in open(2) the aufs-file, open the branch-file with the hidden
2177+ vfsmount (instead of the original branch's vfsmount)
2178+- ideally this "bind-mount and lazy-umount" should be done atomically,
2179+ but it may be possible from userspace by the mount helper.
2180+
2181+Adding the internal hidden vfsmount and using it in opening a file, the
2182+file path under /proc will be printed correctly. This approach looks
2183+smarter, but is not possible I am afraid.
2184+- aufs-root may be bind-mount later. when it happens, another hidden
2185+ vfsmount will be required.
2186+- it is hard to get the chance to bind-mount and lazy-umount
2187+ + in kernel-space, FS can have vfsmount in open(2) via
2188+ file->f_path, and aufs can know its vfsmount. But several locks are
2189+ already acquired, and if aufs tries to bind-mount and lazy-umount
2190+ here, then it may cause a deadlock.
2191+ + in user-space, bind-mount doesn't invoke the mount helper.
2192+- since /proc shows dev and ino, aufs has to give vma these info. it
2193+ means a new member vm_prinode will be necessary. this is essentially
2194+ equivalent to vm_prfile described above.
2195+
2196+I have to give up this "looks-smater" approach.
c1595e42 2197diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06xattr.txt linux/Documentation/filesystems/aufs/design/06xattr.txt
eca34b5c 2198--- /usr/share/empty/Documentation/filesystems/aufs/design/06xattr.txt 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 2199+++ linux/Documentation/filesystems/aufs/design/06xattr.txt 2021-05-02 20:15:14.670004120 +0200
c1595e42
JR
2200@@ -0,0 +1,96 @@
2201+
d58c55f2 2202+# Copyright (C) 2014-2020 Junjiro R. Okajima
c1595e42
JR
2203+#
2204+# This program is free software; you can redistribute it and/or modify
2205+# it under the terms of the GNU General Public License as published by
2206+# the Free Software Foundation; either version 2 of the License, or
2207+# (at your option) any later version.
2208+#
2209+# This program is distributed in the hope that it will be useful,
2210+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2211+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2212+# GNU General Public License for more details.
2213+#
2214+# You should have received a copy of the GNU General Public License
2215+# along with this program; if not, write to the Free Software
2216+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2217+
2218+
2219+Listing XATTR/EA and getting the value
2220+----------------------------------------------------------------------
2221+For the inode standard attributes (owner, group, timestamps, etc.), aufs
2222+shows the values from the topmost existing file. This behaviour is good
7e9cd9fe 2223+for the non-dir entries since the bahaviour exactly matches the shown
c1595e42
JR
2224+information. But for the directories, aufs considers all the same named
2225+entries on the lower branches. Which means, if one of the lower entry
2226+rejects readdir call, then aufs returns an error even if the topmost
2227+entry allows it. This behaviour is necessary to respect the branch fs's
2228+security, but can make users confused since the user-visible standard
2229+attributes don't match the behaviour.
2230+To address this issue, aufs has a mount option called dirperm1 which
2231+checks the permission for the topmost entry only, and ignores the lower
2232+entry's permission.
2233+
2234+A similar issue can happen around XATTR.
2235+getxattr(2) and listxattr(2) families behave as if dirperm1 option is
7e9cd9fe
AM
2236+always set. Otherwise these very unpleasant situation would happen.
2237+- listxattr(2) may return the duplicated entries.
c1595e42
JR
2238+- users may not be able to remove or reset the XATTR forever,
2239+
2240+
2241+XATTR/EA support in the internal (copy,move)-(up,down)
2242+----------------------------------------------------------------------
7e9cd9fe 2243+Generally the extended attributes of inode are categorized as these.
c1595e42
JR
2244+- "security" for LSM and capability.
2245+- "system" for posix ACL, 'acl' mount option is required for the branch
2246+ fs generally.
2247+- "trusted" for userspace, CAP_SYS_ADMIN is required.
2248+- "user" for userspace, 'user_xattr' mount option is required for the
2249+ branch fs generally.
2250+
2251+Moreover there are some other categories. Aufs handles these rather
2252+unpopular categories as the ordinary ones, ie. there is no special
2253+condition nor exception.
2254+
2255+In copy-up, the support for XATTR on the dst branch may differ from the
2256+src branch. In this case, the copy-up operation will get an error and
7e9cd9fe
AM
2257+the original user operation which triggered the copy-up will fail. It
2258+can happen that even all copy-up will fail.
c1595e42
JR
2259+When both of src and dst branches support XATTR and if an error occurs
2260+during copying XATTR, then the copy-up should fail obviously. That is a
2261+good reason and aufs should return an error to userspace. But when only
7e9cd9fe 2262+the src branch support that XATTR, aufs should not return an error.
c1595e42
JR
2263+For example, the src branch supports ACL but the dst branch doesn't
2264+because the dst branch may natively un-support it or temporary
2265+un-support it due to "noacl" mount option. Of course, the dst branch fs
2266+may NOT return an error even if the XATTR is not supported. It is
2267+totally up to the branch fs.
2268+
2269+Anyway when the aufs internal copy-up gets an error from the dst branch
2270+fs, then aufs tries removing the just copied entry and returns the error
2271+to the userspace. The worst case of this situation will be all copy-up
2272+will fail.
2273+
2274+For the copy-up operation, there two basic approaches.
2275+- copy the specified XATTR only (by category above), and return the
7e9cd9fe 2276+ error unconditionally if it happens.
c1595e42
JR
2277+- copy all XATTR, and ignore the error on the specified category only.
2278+
2279+In order to support XATTR and to implement the correct behaviour, aufs
7e9cd9fe
AM
2280+chooses the latter approach and introduces some new branch attributes,
2281+"icexsec", "icexsys", "icextr", "icexusr", and "icexoth".
c1595e42 2282+They correspond to the XATTR namespaces (see above). Additionally, to be
7e9cd9fe
AM
2283+convenient, "icex" is also provided which means all "icex*" attributes
2284+are set (here the word "icex" stands for "ignore copy-error on XATTR").
c1595e42
JR
2285+
2286+The meaning of these attributes is to ignore the error from setting
2287+XATTR on that branch.
2288+Note that aufs tries copying all XATTR unconditionally, and ignores the
2289+error from the dst branch according to the specified attributes.
2290+
2291+Some XATTR may have its default value. The default value may come from
2292+the parent dir or the environment. If the default value is set at the
2293+file creating-time, it will be overwritten by copy-up.
2294+Some contradiction may happen I am afraid.
2295+Do we need another attribute to stop copying XATTR? I am unsure. For
2296+now, aufs implements the branch attributes to ignore the error.
53392da6 2297diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt linux/Documentation/filesystems/aufs/design/07export.txt
eca34b5c 2298--- /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 2299+++ linux/Documentation/filesystems/aufs/design/07export.txt 2021-05-02 20:15:14.670004120 +0200
523b37e3 2300@@ -0,0 +1,58 @@
53392da6 2301+
d58c55f2 2302+# Copyright (C) 2005-2020 Junjiro R. Okajima
53392da6
AM
2303+#
2304+# This program is free software; you can redistribute it and/or modify
2305+# it under the terms of the GNU General Public License as published by
2306+# the Free Software Foundation; either version 2 of the License, or
2307+# (at your option) any later version.
2308+#
2309+# This program is distributed in the hope that it will be useful,
2310+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2311+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2312+# GNU General Public License for more details.
2313+#
2314+# You should have received a copy of the GNU General Public License
523b37e3 2315+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
2316+
2317+Export Aufs via NFS
2318+----------------------------------------------------------------------
2319+Here is an approach.
2320+- like xino/xib, add a new file 'xigen' which stores aufs inode
2321+ generation.
2322+- iget_locked(): initialize aufs inode generation for a new inode, and
2323+ store it in xigen file.
2324+- destroy_inode(): increment aufs inode generation and store it in xigen
2325+ file. it is necessary even if it is not unlinked, because any data of
2326+ inode may be changed by UDBA.
2327+- encode_fh(): for a root dir, simply return FILEID_ROOT. otherwise
2328+ build file handle by
2329+ + branch id (4 bytes)
2330+ + superblock generation (4 bytes)
2331+ + inode number (4 or 8 bytes)
2332+ + parent dir inode number (4 or 8 bytes)
2333+ + inode generation (4 bytes))
2334+ + return value of exportfs_encode_fh() for the parent on a branch (4
2335+ bytes)
2336+ + file handle for a branch (by exportfs_encode_fh())
2337+- fh_to_dentry():
2338+ + find the index of a branch from its id in handle, and check it is
2339+ still exist in aufs.
2340+ + 1st level: get the inode number from handle and search it in cache.
7e9cd9fe
AM
2341+ + 2nd level: if not found in cache, get the parent inode number from
2342+ the handle and search it in cache. and then open the found parent
2343+ dir, find the matching inode number by vfs_readdir() and get its
2344+ name, and call lookup_one_len() for the target dentry.
53392da6
AM
2345+ + 3rd level: if the parent dir is not cached, call
2346+ exportfs_decode_fh() for a branch and get the parent on a branch,
2347+ build a pathname of it, convert it a pathname in aufs, call
2348+ path_lookup(). now aufs gets a parent dir dentry, then handle it as
2349+ the 2nd level.
2350+ + to open the dir, aufs needs struct vfsmount. aufs keeps vfsmount
2351+ for every branch, but not itself. to get this, (currently) aufs
2352+ searches in current->nsproxy->mnt_ns list. it may not be a good
2353+ idea, but I didn't get other approach.
2354+ + test the generation of the gotten inode.
2355+- every inode operation: they may get EBUSY due to UDBA. in this case,
2356+ convert it into ESTALE for NFSD.
2357+- readdir(): call lockdep_on/off() because filldir in NFSD calls
2358+ lookup_one_len(), vfs_getattr(), encode_fh() and others.
2359diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt linux/Documentation/filesystems/aufs/design/08shwh.txt
eca34b5c 2360--- /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 2361+++ linux/Documentation/filesystems/aufs/design/08shwh.txt 2021-05-02 20:15:14.670004120 +0200
523b37e3 2362@@ -0,0 +1,52 @@
53392da6 2363+
d58c55f2 2364+# Copyright (C) 2005-2020 Junjiro R. Okajima
53392da6
AM
2365+#
2366+# This program is free software; you can redistribute it and/or modify
2367+# it under the terms of the GNU General Public License as published by
2368+# the Free Software Foundation; either version 2 of the License, or
2369+# (at your option) any later version.
2370+#
2371+# This program is distributed in the hope that it will be useful,
2372+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2373+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2374+# GNU General Public License for more details.
2375+#
2376+# You should have received a copy of the GNU General Public License
523b37e3 2377+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
2378+
2379+Show Whiteout Mode (shwh)
2380+----------------------------------------------------------------------
2381+Generally aufs hides the name of whiteouts. But in some cases, to show
2382+them is very useful for users. For instance, creating a new middle layer
2383+(branch) by merging existing layers.
2384+
2385+(borrowing aufs1 HOW-TO from a user, Michael Towers)
2386+When you have three branches,
2387+- Bottom: 'system', squashfs (underlying base system), read-only
2388+- Middle: 'mods', squashfs, read-only
2389+- Top: 'overlay', ram (tmpfs), read-write
2390+
2391+The top layer is loaded at boot time and saved at shutdown, to preserve
2392+the changes made to the system during the session.
2393+When larger changes have been made, or smaller changes have accumulated,
2394+the size of the saved top layer data grows. At this point, it would be
2395+nice to be able to merge the two overlay branches ('mods' and 'overlay')
2396+and rewrite the 'mods' squashfs, clearing the top layer and thus
2397+restoring save and load speed.
2398+
2399+This merging is simplified by the use of another aufs mount, of just the
2400+two overlay branches using the 'shwh' option.
2401+# mount -t aufs -o ro,shwh,br:/livesys/overlay=ro+wh:/livesys/mods=rr+wh \
2402+ aufs /livesys/merge_union
2403+
2404+A merged view of these two branches is then available at
2405+/livesys/merge_union, and the new feature is that the whiteouts are
2406+visible!
2407+Note that in 'shwh' mode the aufs mount must be 'ro', which will disable
2408+writing to all branches. Also the default mode for all branches is 'ro'.
2409+It is now possible to save the combined contents of the two overlay
2410+branches to a new squashfs, e.g.:
2411+# mksquashfs /livesys/merge_union /path/to/newmods.squash
2412+
2413+This new squashfs archive can be stored on the boot device and the
2414+initramfs will use it to replace the old one at the next boot.
2415diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt linux/Documentation/filesystems/aufs/design/10dynop.txt
eca34b5c 2416--- /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 2417+++ linux/Documentation/filesystems/aufs/design/10dynop.txt 2021-05-02 20:15:14.670004120 +0200
7e9cd9fe 2418@@ -0,0 +1,47 @@
53392da6 2419+
d58c55f2 2420+# Copyright (C) 2010-2020 Junjiro R. Okajima
53392da6
AM
2421+#
2422+# This program is free software; you can redistribute it and/or modify
2423+# it under the terms of the GNU General Public License as published by
2424+# the Free Software Foundation; either version 2 of the License, or
2425+# (at your option) any later version.
2426+#
2427+# This program is distributed in the hope that it will be useful,
2428+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2429+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2430+# GNU General Public License for more details.
2431+#
2432+# You should have received a copy of the GNU General Public License
523b37e3 2433+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
2434+
2435+Dynamically customizable FS operations
2436+----------------------------------------------------------------------
2437+Generally FS operations (struct inode_operations, struct
2438+address_space_operations, struct file_operations, etc.) are defined as
2439+"static const", but it never means that FS have only one set of
2440+operation. Some FS have multiple sets of them. For instance, ext2 has
2441+three sets, one for XIP, for NOBH, and for normal.
2442+Since aufs overrides and redirects these operations, sometimes aufs has
7e9cd9fe 2443+to change its behaviour according to the branch FS type. More importantly
53392da6
AM
2444+VFS acts differently if a function (member in the struct) is set or
2445+not. It means aufs should have several sets of operations and select one
2446+among them according to the branch FS definition.
2447+
7e9cd9fe 2448+In order to solve this problem and not to affect the behaviour of VFS,
53392da6 2449+aufs defines these operations dynamically. For instance, aufs defines
7e9cd9fe
AM
2450+dummy direct_IO function for struct address_space_operations, but it may
2451+not be set to the address_space_operations actually. When the branch FS
2452+doesn't have it, aufs doesn't set it to its address_space_operations
2453+while the function definition itself is still alive. So the behaviour
2454+itself will not change, and it will return an error when direct_IO is
2455+not set.
53392da6
AM
2456+
2457+The lifetime of these dynamically generated operation object is
2458+maintained by aufs branch object. When the branch is removed from aufs,
2459+the reference counter of the object is decremented. When it reaches
2460+zero, the dynamically generated operation object will be freed.
2461+
7e9cd9fe
AM
2462+This approach is designed to support AIO (io_submit), Direct I/O and
2463+XIP (DAX) mainly.
2464+Currently this approach is applied to address_space_operations for
2465+regular files only.
53392da6 2466diff -urN /usr/share/empty/Documentation/filesystems/aufs/README linux/Documentation/filesystems/aufs/README
eca34b5c 2467--- /usr/share/empty/Documentation/filesystems/aufs/README 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 2468+++ linux/Documentation/filesystems/aufs/README 2021-05-02 20:15:14.666670785 +0200
43982f53 2469@@ -0,0 +1,401 @@
53392da6 2470+
fbc438ed 2471+Aufs5 -- advanced multi layered unification filesystem version 5.x
53392da6
AM
2472+http://aufs.sf.net
2473+Junjiro R. Okajima
2474+
2475+
2476+0. Introduction
2477+----------------------------------------
2478+In the early days, aufs was entirely re-designed and re-implemented
7e9cd9fe 2479+Unionfs Version 1.x series. Adding many original ideas, approaches,
fbc438ed 2480+improvements and implementations, it became totally different from
53392da6 2481+Unionfs while keeping the basic features.
fbc438ed 2482+Later, Unionfs Version 2.x series began taking some of the same
53392da6 2483+approaches to aufs1's.
fbc438ed 2484+Unionfs was being developed by Professor Erez Zadok at Stony Brook
53392da6
AM
2485+University and his team.
2486+
fbc438ed
JR
2487+Aufs5 supports linux-v5.0 and later, If you want older kernel version
2488+support,
2489+- for linux-v4.x series, try aufs4-linux.git or aufs4-standalone.git
2490+- for linux-v3.x series, try aufs3-linux.git or aufs3-standalone.git
2491+- for linux-v2.6.16 and later, try aufs2-2.6.git, aufs2-standalone.git
2492+ or aufs1 from CVS on SourceForge.
53392da6
AM
2493+
2494+Note: it becomes clear that "Aufs was rejected. Let's give it up."
38d290e6
JR
2495+ According to Christoph Hellwig, linux rejects all union-type
2496+ filesystems but UnionMount.
53392da6
AM
2497+<http://marc.info/?l=linux-kernel&m=123938533724484&w=2>
2498+
38d290e6
JR
2499+PS. Al Viro seems have a plan to merge aufs as well as overlayfs and
2500+ UnionMount, and he pointed out an issue around a directory mutex
2501+ lock and aufs addressed it. But it is still unsure whether aufs will
2502+ be merged (or any other union solution).
076b876e 2503+<http://marc.info/?l=linux-kernel&m=136312705029295&w=1>
38d290e6 2504+
53392da6
AM
2505+
2506+1. Features
2507+----------------------------------------
2508+- unite several directories into a single virtual filesystem. The member
2509+ directory is called as a branch.
2510+- you can specify the permission flags to the branch, which are 'readonly',
2511+ 'readwrite' and 'whiteout-able.'
2512+- by upper writable branch, internal copyup and whiteout, files/dirs on
2513+ readonly branch are modifiable logically.
2514+- dynamic branch manipulation, add, del.
2515+- etc...
2516+
7e9cd9fe
AM
2517+Also there are many enhancements in aufs, such as:
2518+- test only the highest one for the directory permission (dirperm1)
2519+- copyup on open (coo=)
2520+- 'move' policy for copy-up between two writable branches, after
2521+ checking free space.
2522+- xattr, acl
53392da6
AM
2523+- readdir(3) in userspace.
2524+- keep inode number by external inode number table
2525+- keep the timestamps of file/dir in internal copyup operation
2526+- seekable directory, supporting NFS readdir.
2527+- whiteout is hardlinked in order to reduce the consumption of inodes
2528+ on branch
2529+- do not copyup, nor create a whiteout when it is unnecessary
2530+- revert a single systemcall when an error occurs in aufs
2531+- remount interface instead of ioctl
2532+- maintain /etc/mtab by an external command, /sbin/mount.aufs.
2533+- loopback mounted filesystem as a branch
2534+- kernel thread for removing the dir who has a plenty of whiteouts
2535+- support copyup sparse file (a file which has a 'hole' in it)
2536+- default permission flags for branches
2537+- selectable permission flags for ro branch, whether whiteout can
2538+ exist or not
2539+- export via NFS.
2540+- support <sysfs>/fs/aufs and <debugfs>/aufs.
2541+- support multiple writable branches, some policies to select one
2542+ among multiple writable branches.
2543+- a new semantics for link(2) and rename(2) to support multiple
2544+ writable branches.
2545+- no glibc changes are required.
2546+- pseudo hardlink (hardlink over branches)
2547+- allow a direct access manually to a file on branch, e.g. bypassing aufs.
2548+ including NFS or remote filesystem branch.
2549+- userspace wrapper for pathconf(3)/fpathconf(3) with _PC_LINK_MAX.
2550+- and more...
2551+
fbc438ed 2552+Currently these features are dropped temporary from aufs5.
53392da6 2553+See design/08plan.txt in detail.
53392da6
AM
2554+- nested mount, i.e. aufs as readonly no-whiteout branch of another aufs
2555+ (robr)
2556+- statistics of aufs thread (/sys/fs/aufs/stat)
53392da6
AM
2557+
2558+Features or just an idea in the future (see also design/*.txt),
2559+- reorder the branch index without del/re-add.
2560+- permanent xino files for NFSD
2561+- an option for refreshing the opened files after add/del branches
53392da6
AM
2562+- light version, without branch manipulation. (unnecessary?)
2563+- copyup in userspace
2564+- inotify in userspace
2565+- readv/writev
53392da6
AM
2566+
2567+
2568+2. Download
2569+----------------------------------------
fbc438ed
JR
2570+There are three GIT trees for aufs5, aufs5-linux.git,
2571+aufs5-standalone.git, and aufs-util.git. Note that there is no "5" in
1e00d052 2572+"aufs-util.git."
fbc438ed
JR
2573+While the aufs-util is always necessary, you need either of aufs5-linux
2574+or aufs5-standalone.
1e00d052 2575+
fbc438ed 2576+The aufs5-linux tree includes the whole linux mainline GIT tree,
1e00d052
AM
2577+git://git.kernel.org/.../torvalds/linux.git.
2578+And you cannot select CONFIG_AUFS_FS=m for this version, eg. you cannot
fbc438ed 2579+build aufs5 as an external kernel module.
2000de60 2580+Several extra patches are not included in this tree. Only
fbc438ed 2581+aufs5-standalone tree contains them. They are described in the later
2000de60 2582+section "Configuration and Compilation."
1e00d052 2583+
fbc438ed 2584+On the other hand, the aufs5-standalone tree has only aufs source files
53392da6 2585+and necessary patches, and you can select CONFIG_AUFS_FS=m.
2000de60 2586+But you need to apply all aufs patches manually.
53392da6 2587+
fbc438ed
JR
2588+You will find GIT branches whose name is in form of "aufs5.x" where "x"
2589+represents the linux kernel version, "linux-5.x". For instance,
2590+"aufs5.0" is for linux-5.0. For latest "linux-5.x-rcN", use
2591+"aufs5.x-rcN" branch.
1e00d052 2592+
fbc438ed 2593+o aufs5-linux tree
1e00d052 2594+$ git clone --reference /your/linux/git/tree \
fbc438ed 2595+ git://github.com/sfjro/aufs5-linux.git aufs5-linux.git
1e00d052 2596+- if you don't have linux GIT tree, then remove "--reference ..."
fbc438ed
JR
2597+$ cd aufs5-linux.git
2598+$ git checkout origin/aufs5.0
53392da6 2599+
2000de60
JR
2600+Or You may want to directly git-pull aufs into your linux GIT tree, and
2601+leave the patch-work to GIT.
2602+$ cd /your/linux/git/tree
fbc438ed
JR
2603+$ git remote add aufs5 git://github.com/sfjro/aufs5-linux.git
2604+$ git fetch aufs5
2605+$ git checkout -b my5.0 v5.0
5527c038 2606+$ (add your local change...)
fbc438ed
JR
2607+$ git pull aufs5 aufs5.0
2608+- now you have v5.0 + your_changes + aufs5.0 in you my5.0 branch.
2000de60 2609+- you may need to solve some conflicts between your_changes and
fbc438ed
JR
2610+ aufs5.0. in this case, git-rerere is recommended so that you can
2611+ solve the similar conflicts automatically when you upgrade to 5.1 or
2000de60
JR
2612+ later in the future.
2613+
fbc438ed
JR
2614+o aufs5-standalone tree
2615+$ git clone git://github.com/sfjro/aufs5-standalone.git aufs5-standalone.git
2616+$ cd aufs5-standalone.git
2617+$ git checkout origin/aufs5.0
53392da6
AM
2618+
2619+o aufs-util tree
5527c038
JR
2620+$ git clone git://git.code.sf.net/p/aufs/aufs-util aufs-util.git
2621+- note that the public aufs-util.git is on SourceForge instead of
2622+ GitHUB.
53392da6 2623+$ cd aufs-util.git
fbc438ed 2624+$ git checkout origin/aufs5.0
53392da6 2625+
fbc438ed
JR
2626+Note: The 5.x-rcN branch is to be used with `rc' kernel versions ONLY.
2627+The minor version number, 'x' in '5.x', of aufs may not always
9dbd164d
AM
2628+follow the minor version number of the kernel.
2629+Because changes in the kernel that cause the use of a new
2630+minor version number do not always require changes to aufs-util.
2631+
2632+Since aufs-util has its own minor version number, you may not be
2633+able to find a GIT branch in aufs-util for your kernel's
2634+exact minor version number.
2635+In this case, you should git-checkout the branch for the
53392da6 2636+nearest lower number.
9dbd164d
AM
2637+
2638+For (an unreleased) example:
fbc438ed
JR
2639+If you are using "linux-5.10" and the "aufs5.10" branch
2640+does not exist in aufs-util repository, then "aufs5.9", "aufs5.8"
9dbd164d
AM
2641+or something numerically smaller is the branch for your kernel.
2642+
53392da6
AM
2643+Also you can view all branches by
2644+ $ git branch -a
2645+
2646+
2647+3. Configuration and Compilation
2648+----------------------------------------
2649+Make sure you have git-checkout'ed the correct branch.
2650+
fbc438ed 2651+For aufs5-linux tree,
c06a8ce3 2652+- enable CONFIG_AUFS_FS.
1e00d052
AM
2653+- set other aufs configurations if necessary.
2654+
fbc438ed 2655+For aufs5-standalone tree,
53392da6
AM
2656+There are several ways to build.
2657+
2658+1.
fbc438ed
JR
2659+- apply ./aufs5-kbuild.patch to your kernel source files.
2660+- apply ./aufs5-base.patch too.
2661+- apply ./aufs5-mmap.patch too.
2662+- apply ./aufs5-standalone.patch too, if you have a plan to set
2663+ CONFIG_AUFS_FS=m. otherwise you don't need ./aufs5-standalone.patch.
537831f9
AM
2664+- copy ./{Documentation,fs,include/uapi/linux/aufs_type.h} files to your
2665+ kernel source tree. Never copy $PWD/include/uapi/linux/Kbuild.
c06a8ce3 2666+- enable CONFIG_AUFS_FS, you can select either
53392da6
AM
2667+ =m or =y.
2668+- and build your kernel as usual.
2669+- install the built kernel.
7eafdf33
AM
2670+- install the header files too by "make headers_install" to the
2671+ directory where you specify. By default, it is $PWD/usr.
b4510431 2672+ "make help" shows a brief note for headers_install.
53392da6
AM
2673+- and reboot your system.
2674+
2675+2.
2676+- module only (CONFIG_AUFS_FS=m).
fbc438ed
JR
2677+- apply ./aufs5-base.patch to your kernel source files.
2678+- apply ./aufs5-mmap.patch too.
2679+- apply ./aufs5-standalone.patch too.
53392da6
AM
2680+- build your kernel, don't forget "make headers_install", and reboot.
2681+- edit ./config.mk and set other aufs configurations if necessary.
b4510431 2682+ Note: You should read $PWD/fs/aufs/Kconfig carefully which describes
53392da6
AM
2683+ every aufs configurations.
2684+- build the module by simple "make".
2685+- you can specify ${KDIR} make variable which points to your kernel
2686+ source tree.
2687+- install the files
2688+ + run "make install" to install the aufs module, or copy the built
b4510431
AM
2689+ $PWD/aufs.ko to /lib/modules/... and run depmod -a (or reboot simply).
2690+ + run "make install_headers" (instead of headers_install) to install
2691+ the modified aufs header file (you can specify DESTDIR which is
2692+ available in aufs standalone version's Makefile only), or copy
2693+ $PWD/usr/include/linux/aufs_type.h to /usr/include/linux or wherever
2694+ you like manually. By default, the target directory is $PWD/usr.
fbc438ed 2695+- no need to apply aufs5-kbuild.patch, nor copying source files to your
53392da6
AM
2696+ kernel source tree.
2697+
b4510431 2698+Note: The header file aufs_type.h is necessary to build aufs-util
53392da6
AM
2699+ as well as "make headers_install" in the kernel source tree.
2700+ headers_install is subject to be forgotten, but it is essentially
2701+ necessary, not only for building aufs-util.
2702+ You may not meet problems without headers_install in some older
2703+ version though.
2704+
2705+And then,
2706+- read README in aufs-util, build and install it
9dbd164d
AM
2707+- note that your distribution may contain an obsoleted version of
2708+ aufs_type.h in /usr/include/linux or something. When you build aufs
2709+ utilities, make sure that your compiler refers the correct aufs header
2710+ file which is built by "make headers_install."
53392da6
AM
2711+- if you want to use readdir(3) in userspace or pathconf(3) wrapper,
2712+ then run "make install_ulib" too. And refer to the aufs manual in
2713+ detail.
2714+
fbc438ed 2715+There several other patches in aufs5-standalone.git. They are all
38d290e6 2716+optional. When you meet some problems, they will help you.
fbc438ed 2717+- aufs5-loopback.patch
38d290e6
JR
2718+ Supports a nested loopback mount in a branch-fs. This patch is
2719+ unnecessary until aufs produces a message like "you may want to try
2720+ another patch for loopback file".
83b672a5
AM
2721+- proc_mounts.patch
2722+ When there are many mountpoints and many mount(2)/umount(2) are
2723+ running, then /proc/mounts may not show the all mountpoints. This
2724+ patch makes /proc/mounts always show the full mountpoints list.
2725+ If you don't want to apply this patch and meet such problem, then you
2726+ need to increase the value of 'ProcMounts_Times' make-variable in
2727+ aufs-util.git as a second best solution.
38d290e6
JR
2728+- vfs-ino.patch
2729+ Modifies a system global kernel internal function get_next_ino() in
2730+ order to stop assigning 0 for an inode-number. Not directly related to
2731+ aufs, but recommended generally.
2732+- tmpfs-idr.patch
2733+ Keeps the tmpfs inode number as the lowest value. Effective to reduce
2734+ the size of aufs XINO files for tmpfs branch. Also it prevents the
2735+ duplication of inode number, which is important for backup tools and
2736+ other utilities. When you find aufs XINO files for tmpfs branch
2737+ growing too much, try this patch.
be52b249
AM
2738+- lockdep-debug.patch
2739+ Because aufs is not only an ordinary filesystem (callee of VFS), but
2740+ also a caller of VFS functions for branch filesystems, subclassing of
2741+ the internal locks for LOCKDEP is necessary. LOCKDEP is a debugging
2742+ feature of linux kernel. If you enable CONFIG_LOCKDEP, then you will
2743+ need to apply this debug patch to expand several constant values.
43982f53
AM
2744+ If you don't know what LOCKDEP is, then you don't have apply this
2745+ patch.
38d290e6 2746+
53392da6
AM
2747+
2748+4. Usage
2749+----------------------------------------
2750+At first, make sure aufs-util are installed, and please read the aufs
2751+manual, aufs.5 in aufs-util.git tree.
2752+$ man -l aufs.5
2753+
2754+And then,
2755+$ mkdir /tmp/rw /tmp/aufs
2756+# mount -t aufs -o br=/tmp/rw:${HOME} none /tmp/aufs
2757+
2758+Here is another example. The result is equivalent.
2759+# mount -t aufs -o br=/tmp/rw=rw:${HOME}=ro none /tmp/aufs
2760+ Or
2761+# mount -t aufs -o br:/tmp/rw none /tmp/aufs
2762+# mount -o remount,append:${HOME} /tmp/aufs
2763+
2764+Then, you can see whole tree of your home dir through /tmp/aufs. If
2765+you modify a file under /tmp/aufs, the one on your home directory is
2766+not affected, instead the same named file will be newly created under
2767+/tmp/rw. And all of your modification to a file will be applied to
2768+the one under /tmp/rw. This is called the file based Copy on Write
2769+(COW) method.
2770+Aufs mount options are described in aufs.5.
2771+If you run chroot or something and make your aufs as a root directory,
2772+then you need to customize the shutdown script. See the aufs manual in
2773+detail.
2774+
2775+Additionally, there are some sample usages of aufs which are a
2776+diskless system with network booting, and LiveCD over NFS.
2777+See sample dir in CVS tree on SourceForge.
2778+
2779+
2780+5. Contact
2781+----------------------------------------
2782+When you have any problems or strange behaviour in aufs, please let me
2783+know with:
2784+- /proc/mounts (instead of the output of mount(8))
2785+- /sys/module/aufs/*
2786+- /sys/fs/aufs/* (if you have them)
2787+- /debug/aufs/* (if you have them)
2788+- linux kernel version
2789+ if your kernel is not plain, for example modified by distributor,
2790+ the url where i can download its source is necessary too.
2791+- aufs version which was printed at loading the module or booting the
2792+ system, instead of the date you downloaded.
2793+- configuration (define/undefine CONFIG_AUFS_xxx)
2794+- kernel configuration or /proc/config.gz (if you have it)
43982f53 2795+- LSM (linux security module, if you are using)
53392da6
AM
2796+- behaviour which you think to be incorrect
2797+- actual operation, reproducible one is better
2798+- mailto: aufs-users at lists.sourceforge.net
2799+
2800+Usually, I don't watch the Public Areas(Bugs, Support Requests, Patches,
2801+and Feature Requests) on SourceForge. Please join and write to
2802+aufs-users ML.
2803+
2804+
2805+6. Acknowledgements
2806+----------------------------------------
2807+Thanks to everyone who have tried and are using aufs, whoever
2808+have reported a bug or any feedback.
2809+
2810+Especially donators:
2811+Tomas Matejicek(slax.org) made a donation (much more than once).
2812+ Since Apr 2010, Tomas M (the author of Slax and Linux Live
2813+ scripts) is making "doubling" donations.
2814+ Unfortunately I cannot list all of the donators, but I really
b4510431 2815+ appreciate.
53392da6
AM
2816+ It ends Aug 2010, but the ordinary donation URL is still available.
2817+ <http://sourceforge.net/donate/index.php?group_id=167503>
2818+Dai Itasaka made a donation (2007/8).
2819+Chuck Smith made a donation (2008/4, 10 and 12).
2820+Henk Schoneveld made a donation (2008/9).
2821+Chih-Wei Huang, ASUS, CTC donated Eee PC 4G (2008/10).
2822+Francois Dupoux made a donation (2008/11).
2823+Bruno Cesar Ribas and Luis Carlos Erpen de Bona, C3SL serves public
2824+ aufs2 GIT tree (2009/2).
2825+William Grant made a donation (2009/3).
2826+Patrick Lane made a donation (2009/4).
2827+The Mail Archive (mail-archive.com) made donations (2009/5).
2828+Nippy Networks (Ed Wildgoose) made a donation (2009/7).
2829+New Dream Network, LLC (www.dreamhost.com) made a donation (2009/11).
2830+Pavel Pronskiy made a donation (2011/2).
2831+Iridium and Inmarsat satellite phone retailer (www.mailasail.com), Nippy
2832+ Networks (Ed Wildgoose) made a donation for hardware (2011/3).
537831f9
AM
2833+Max Lekomcev (DOM-TV project) made a donation (2011/7, 12, 2012/3, 6 and
2834+11).
1e00d052 2835+Sam Liddicott made a donation (2011/9).
86dc4139
AM
2836+Era Scarecrow made a donation (2013/4).
2837+Bor Ratajc made a donation (2013/4).
2838+Alessandro Gorreta made a donation (2013/4).
2839+POIRETTE Marc made a donation (2013/4).
2840+Alessandro Gorreta made a donation (2013/4).
2841+lauri kasvandik made a donation (2013/5).
392086de 2842+"pemasu from Finland" made a donation (2013/7).
523b37e3
AM
2843+The Parted Magic Project made a donation (2013/9 and 11).
2844+Pavel Barta made a donation (2013/10).
38d290e6 2845+Nikolay Pertsev made a donation (2014/5).
c2c0f25c 2846+James B made a donation (2014/7 and 2015/7).
076b876e 2847+Stefano Di Biase made a donation (2014/8).
2000de60 2848+Daniel Epellei made a donation (2015/1).
c4adf169 2849+OmegaPhil made a donation (2016/1, 2018/4).
5afbbe0d 2850+Tomasz Szewczyk made a donation (2016/4).
f2c43d5f 2851+James Burry made a donation (2016/12).
acd2b654 2852+Carsten Rose made a donation (2018/9).
9f237c51 2853+Porteus Kiosk made a donation (2018/10).
53392da6
AM
2854+
2855+Thank you very much.
2856+Donations are always, including future donations, very important and
2857+helpful for me to keep on developing aufs.
2858+
2859+
2860+7.
2861+----------------------------------------
2862+If you are an experienced user, no explanation is needed. Aufs is
2863+just a linux filesystem.
2864+
2865+
2866+Enjoy!
2867+
2868+# Local variables: ;
2869+# mode: text;
2870+# End: ;
7f207e10 2871diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
eca34b5c 2872--- /usr/share/empty/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 2873+++ linux/fs/aufs/aufs.h 2021-05-02 20:15:14.670004120 +0200
acd2b654 2874@@ -0,0 +1,62 @@
062440b3 2875+/* SPDX-License-Identifier: GPL-2.0 */
7f207e10 2876+/*
d58c55f2 2877+ * Copyright (C) 2005-2020 Junjiro R. Okajima
7f207e10
AM
2878+ *
2879+ * This program, aufs is free software; you can redistribute it and/or modify
2880+ * it under the terms of the GNU General Public License as published by
2881+ * the Free Software Foundation; either version 2 of the License, or
2882+ * (at your option) any later version.
2883+ *
2884+ * This program is distributed in the hope that it will be useful,
2885+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2886+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2887+ * GNU General Public License for more details.
2888+ *
2889+ * You should have received a copy of the GNU General Public License
523b37e3 2890+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
7f207e10
AM
2891+ */
2892+
2893+/*
2894+ * all header files
2895+ */
2896+
2897+#ifndef __AUFS_H__
2898+#define __AUFS_H__
2899+
2900+#ifdef __KERNEL__
2901+
2902+#define AuStub(type, name, body, ...) \
2903+ static inline type name(__VA_ARGS__) { body; }
2904+
2905+#define AuStubVoid(name, ...) \
2906+ AuStub(void, name, , __VA_ARGS__)
2907+#define AuStubInt0(name, ...) \
2908+ AuStub(int, name, return 0, __VA_ARGS__)
2909+
2910+#include "debug.h"
2911+
2912+#include "branch.h"
2913+#include "cpup.h"
2914+#include "dcsub.h"
2915+#include "dbgaufs.h"
2916+#include "dentry.h"
2917+#include "dir.h"
8b6a4947 2918+#include "dirren.h"
7f207e10
AM
2919+#include "dynop.h"
2920+#include "file.h"
2921+#include "fstype.h"
8b6a4947 2922+#include "hbl.h"
7f207e10 2923+#include "inode.h"
acd2b654 2924+#include "lcnt.h"
7f207e10
AM
2925+#include "loop.h"
2926+#include "module.h"
7f207e10
AM
2927+#include "opts.h"
2928+#include "rwsem.h"
7f207e10
AM
2929+#include "super.h"
2930+#include "sysaufs.h"
2931+#include "vfsub.h"
2932+#include "whout.h"
2933+#include "wkq.h"
2934+
2935+#endif /* __KERNEL__ */
2936+#endif /* __AUFS_H__ */
2937diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
eca34b5c 2938--- /usr/share/empty/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 2939+++ linux/fs/aufs/branch.c 2021-05-02 20:15:14.670004120 +0200
42b5c33a 2940@@ -0,0 +1,1427 @@
cd7a4cd9 2941+// SPDX-License-Identifier: GPL-2.0
7f207e10 2942+/*
d58c55f2 2943+ * Copyright (C) 2005-2020 Junjiro R. Okajima
7f207e10
AM
2944+ *
2945+ * This program, aufs is free software; you can redistribute it and/or modify
2946+ * it under the terms of the GNU General Public License as published by
2947+ * the Free Software Foundation; either version 2 of the License, or
2948+ * (at your option) any later version.
2949+ *
2950+ * This program is distributed in the hope that it will be useful,
2951+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2952+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2953+ * GNU General Public License for more details.
2954+ *
2955+ * You should have received a copy of the GNU General Public License
523b37e3 2956+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
7f207e10
AM
2957+ */
2958+
2959+/*
2960+ * branch management
2961+ */
2962+
027c5e7a 2963+#include <linux/compat.h>
7f207e10
AM
2964+#include <linux/statfs.h>
2965+#include "aufs.h"
2966+
2967+/*
2968+ * free a single branch
1facf9fc 2969+ */
2970+static void au_br_do_free(struct au_branch *br)
2971+{
2972+ int i;
2973+ struct au_wbr *wbr;
4a4d8108 2974+ struct au_dykey **key;
1facf9fc 2975+
027c5e7a 2976+ au_hnotify_fin_br(br);
8b6a4947
AM
2977+ /* always, regardless the mount option */
2978+ au_dr_hino_free(&br->br_dirren);
062440b3 2979+ au_xino_put(br);
1facf9fc 2980+
acd2b654
AM
2981+ AuLCntZero(au_lcnt_read(&br->br_nfiles, /*do_rev*/0));
2982+ au_lcnt_fin(&br->br_nfiles, /*do_sync*/0);
2983+ AuLCntZero(au_lcnt_read(&br->br_count, /*do_rev*/0));
2984+ au_lcnt_fin(&br->br_count, /*do_sync*/0);
1facf9fc 2985+
2986+ wbr = br->br_wbr;
2987+ if (wbr) {
2988+ for (i = 0; i < AuBrWh_Last; i++)
2989+ dput(wbr->wbr_wh[i]);
2990+ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
dece6358 2991+ AuRwDestroy(&wbr->wbr_wh_rwsem);
1facf9fc 2992+ }
2993+
076b876e
AM
2994+ if (br->br_fhsm) {
2995+ au_br_fhsm_fin(br->br_fhsm);
9f237c51 2996+ au_kfree_try_rcu(br->br_fhsm);
076b876e
AM
2997+ }
2998+
4a4d8108
AM
2999+ key = br->br_dykey;
3000+ for (i = 0; i < AuBrDynOp; i++, key++)
3001+ if (*key)
3002+ au_dy_put(*key);
3003+ else
3004+ break;
3005+
537831f9 3006+ /* recursive lock, s_umount of branch's */
acd2b654 3007+ /* synchronize_rcu(); */ /* why? */
537831f9 3008+ lockdep_off();
86dc4139 3009+ path_put(&br->br_path);
537831f9 3010+ lockdep_on();
9f237c51 3011+ au_kfree_rcu(wbr);
acd2b654
AM
3012+ au_lcnt_wait_for_fin(&br->br_nfiles);
3013+ au_lcnt_wait_for_fin(&br->br_count);
3014+ /* I don't know why, but percpu_refcount requires this */
3015+ /* synchronize_rcu(); */
9f237c51 3016+ au_kfree_rcu(br);
1facf9fc 3017+}
3018+
3019+/*
3020+ * frees all branches
3021+ */
3022+void au_br_free(struct au_sbinfo *sbinfo)
3023+{
3024+ aufs_bindex_t bmax;
3025+ struct au_branch **br;
3026+
dece6358
AM
3027+ AuRwMustWriteLock(&sbinfo->si_rwsem);
3028+
5afbbe0d 3029+ bmax = sbinfo->si_bbot + 1;
1facf9fc 3030+ br = sbinfo->si_branch;
3031+ while (bmax--)
3032+ au_br_do_free(*br++);
3033+}
3034+
3035+/*
3036+ * find the index of a branch which is specified by @br_id.
3037+ */
3038+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
3039+{
5afbbe0d 3040+ aufs_bindex_t bindex, bbot;
1facf9fc 3041+
5afbbe0d
AM
3042+ bbot = au_sbbot(sb);
3043+ for (bindex = 0; bindex <= bbot; bindex++)
1facf9fc 3044+ if (au_sbr_id(sb, bindex) == br_id)
3045+ return bindex;
3046+ return -1;
3047+}
3048+
3049+/* ---------------------------------------------------------------------- */
3050+
3051+/*
3052+ * add a branch
3053+ */
3054+
b752ccd1
AM
3055+static int test_overlap(struct super_block *sb, struct dentry *h_adding,
3056+ struct dentry *h_root)
1facf9fc 3057+{
b752ccd1
AM
3058+ if (unlikely(h_adding == h_root
3059+ || au_test_loopback_overlap(sb, h_adding)))
1facf9fc 3060+ return 1;
b752ccd1
AM
3061+ if (h_adding->d_sb != h_root->d_sb)
3062+ return 0;
3063+ return au_test_subdir(h_adding, h_root)
3064+ || au_test_subdir(h_root, h_adding);
1facf9fc 3065+}
3066+
3067+/*
3068+ * returns a newly allocated branch. @new_nbranch is a number of branches
3069+ * after adding a branch.
3070+ */
3071+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
3072+ int perm)
3073+{
3074+ struct au_branch *add_branch;
3075+ struct dentry *root;
5527c038 3076+ struct inode *inode;
4a4d8108 3077+ int err;
1facf9fc 3078+
4a4d8108 3079+ err = -ENOMEM;
be52b249 3080+ add_branch = kzalloc(sizeof(*add_branch), GFP_NOFS);
1facf9fc 3081+ if (unlikely(!add_branch))
3082+ goto out;
acd2b654 3083+ add_branch->br_xino = au_xino_alloc(/*nfile*/1);
062440b3 3084+ if (unlikely(!add_branch->br_xino))
521ced18 3085+ goto out_br;
027c5e7a
AM
3086+ err = au_hnotify_init_br(add_branch, perm);
3087+ if (unlikely(err))
062440b3 3088+ goto out_xino;
027c5e7a 3089+
1facf9fc 3090+ if (au_br_writable(perm)) {
3091+ /* may be freed separately at changing the branch permission */
be52b249 3092+ add_branch->br_wbr = kzalloc(sizeof(*add_branch->br_wbr),
1facf9fc 3093+ GFP_NOFS);
3094+ if (unlikely(!add_branch->br_wbr))
027c5e7a 3095+ goto out_hnotify;
1facf9fc 3096+ }
3097+
076b876e
AM
3098+ if (au_br_fhsm(perm)) {
3099+ err = au_fhsm_br_alloc(add_branch);
3100+ if (unlikely(err))
3101+ goto out_wbr;
3102+ }
3103+
521ced18 3104+ root = sb->s_root;
e2f27e51 3105+ err = au_sbr_realloc(au_sbi(sb), new_nbranch, /*may_shrink*/0);
4a4d8108 3106+ if (!err)
e2f27e51 3107+ err = au_di_realloc(au_di(root), new_nbranch, /*may_shrink*/0);
5527c038
JR
3108+ if (!err) {
3109+ inode = d_inode(root);
1c60b727
AM
3110+ err = au_hinode_realloc(au_ii(inode), new_nbranch,
3111+ /*may_shrink*/0);
5527c038 3112+ }
4a4d8108
AM
3113+ if (!err)
3114+ return add_branch; /* success */
1facf9fc 3115+
076b876e 3116+out_wbr:
9f237c51 3117+ au_kfree_rcu(add_branch->br_wbr);
027c5e7a
AM
3118+out_hnotify:
3119+ au_hnotify_fin_br(add_branch);
062440b3
AM
3120+out_xino:
3121+ au_xino_put(add_branch);
4f0767ce 3122+out_br:
9f237c51 3123+ au_kfree_rcu(add_branch);
4f0767ce 3124+out:
4a4d8108 3125+ return ERR_PTR(err);
1facf9fc 3126+}
3127+
3128+/*
3129+ * test if the branch permission is legal or not.
3130+ */
3131+static int test_br(struct inode *inode, int brperm, char *path)
3132+{
3133+ int err;
3134+
4a4d8108
AM
3135+ err = (au_br_writable(brperm) && IS_RDONLY(inode));
3136+ if (!err)
3137+ goto out;
1facf9fc 3138+
4a4d8108
AM
3139+ err = -EINVAL;
3140+ pr_err("write permission for readonly mount or inode, %s\n", path);
3141+
4f0767ce 3142+out:
1facf9fc 3143+ return err;
3144+}
3145+
3146+/*
3147+ * returns:
3148+ * 0: success, the caller will add it
3149+ * plus: success, it is already unified, the caller should ignore it
3150+ * minus: error
3151+ */
3152+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
3153+{
3154+ int err;
5afbbe0d 3155+ aufs_bindex_t bbot, bindex;
5527c038 3156+ struct dentry *root, *h_dentry;
1facf9fc 3157+ struct inode *inode, *h_inode;
3158+
3159+ root = sb->s_root;
5afbbe0d
AM
3160+ bbot = au_sbbot(sb);
3161+ if (unlikely(bbot >= 0
1facf9fc 3162+ && au_find_dbindex(root, add->path.dentry) >= 0)) {
3163+ err = 1;
3164+ if (!remount) {
3165+ err = -EINVAL;
4a4d8108 3166+ pr_err("%s duplicated\n", add->pathname);
1facf9fc 3167+ }
3168+ goto out;
3169+ }
3170+
3171+ err = -ENOSPC; /* -E2BIG; */
3172+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
5afbbe0d 3173+ || AUFS_BRANCH_MAX - 1 <= bbot)) {
4a4d8108 3174+ pr_err("number of branches exceeded %s\n", add->pathname);
1facf9fc 3175+ goto out;
3176+ }
3177+
3178+ err = -EDOM;
5afbbe0d 3179+ if (unlikely(add->bindex < 0 || bbot + 1 < add->bindex)) {
4a4d8108 3180+ pr_err("bad index %d\n", add->bindex);
1facf9fc 3181+ goto out;
3182+ }
3183+
5527c038 3184+ inode = d_inode(add->path.dentry);
1facf9fc 3185+ err = -ENOENT;
3186+ if (unlikely(!inode->i_nlink)) {
4a4d8108 3187+ pr_err("no existence %s\n", add->pathname);
1facf9fc 3188+ goto out;
3189+ }
3190+
3191+ err = -EINVAL;
3192+ if (unlikely(inode->i_sb == sb)) {
4a4d8108 3193+ pr_err("%s must be outside\n", add->pathname);
1facf9fc 3194+ goto out;
3195+ }
3196+
3197+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
4a4d8108
AM
3198+ pr_err("unsupported filesystem, %s (%s)\n",
3199+ add->pathname, au_sbtype(inode->i_sb));
1facf9fc 3200+ goto out;
3201+ }
3202+
c1595e42
JR
3203+ if (unlikely(inode->i_sb->s_stack_depth)) {
3204+ pr_err("already stacked, %s (%s)\n",
3205+ add->pathname, au_sbtype(inode->i_sb));
3206+ goto out;
3207+ }
3208+
5527c038 3209+ err = test_br(d_inode(add->path.dentry), add->perm, add->pathname);
1facf9fc 3210+ if (unlikely(err))
3211+ goto out;
3212+
5afbbe0d 3213+ if (bbot < 0)
1facf9fc 3214+ return 0; /* success */
3215+
3216+ err = -EINVAL;
5afbbe0d 3217+ for (bindex = 0; bindex <= bbot; bindex++)
1facf9fc 3218+ if (unlikely(test_overlap(sb, add->path.dentry,
3219+ au_h_dptr(root, bindex)))) {
4a4d8108 3220+ pr_err("%s is overlapped\n", add->pathname);
1facf9fc 3221+ goto out;
3222+ }
3223+
3224+ err = 0;
3225+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
5527c038
JR
3226+ h_dentry = au_h_dptr(root, 0);
3227+ h_inode = d_inode(h_dentry);
1facf9fc 3228+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
0c3ec466
AM
3229+ || !uid_eq(h_inode->i_uid, inode->i_uid)
3230+ || !gid_eq(h_inode->i_gid, inode->i_gid))
3231+ pr_warn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
3232+ add->pathname,
3233+ i_uid_read(inode), i_gid_read(inode),
3234+ (inode->i_mode & S_IALLUGO),
3235+ i_uid_read(h_inode), i_gid_read(h_inode),
3236+ (h_inode->i_mode & S_IALLUGO));
1facf9fc 3237+ }
3238+
4f0767ce 3239+out:
1facf9fc 3240+ return err;
3241+}
3242+
3243+/*
3244+ * initialize or clean the whiteouts for an adding branch
3245+ */
3246+static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
86dc4139 3247+ int new_perm)
1facf9fc 3248+{
3249+ int err, old_perm;
3250+ aufs_bindex_t bindex;
febd17d6 3251+ struct inode *h_inode;
1facf9fc 3252+ struct au_wbr *wbr;
3253+ struct au_hinode *hdir;
5527c038 3254+ struct dentry *h_dentry;
1facf9fc 3255+
86dc4139
AM
3256+ err = vfsub_mnt_want_write(au_br_mnt(br));
3257+ if (unlikely(err))
3258+ goto out;
3259+
1facf9fc 3260+ wbr = br->br_wbr;
3261+ old_perm = br->br_perm;
3262+ br->br_perm = new_perm;
3263+ hdir = NULL;
febd17d6 3264+ h_inode = NULL;
1facf9fc 3265+ bindex = au_br_index(sb, br->br_id);
3266+ if (0 <= bindex) {
5527c038 3267+ hdir = au_hi(d_inode(sb->s_root), bindex);
5afbbe0d 3268+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 3269+ } else {
5527c038 3270+ h_dentry = au_br_dentry(br);
febd17d6
JR
3271+ h_inode = d_inode(h_dentry);
3272+ inode_lock_nested(h_inode, AuLsc_I_PARENT);
1facf9fc 3273+ }
3274+ if (!wbr)
86dc4139 3275+ err = au_wh_init(br, sb);
1facf9fc 3276+ else {
3277+ wbr_wh_write_lock(wbr);
86dc4139 3278+ err = au_wh_init(br, sb);
1facf9fc 3279+ wbr_wh_write_unlock(wbr);
3280+ }
3281+ if (hdir)
5afbbe0d 3282+ au_hn_inode_unlock(hdir);
1facf9fc 3283+ else
febd17d6 3284+ inode_unlock(h_inode);
86dc4139 3285+ vfsub_mnt_drop_write(au_br_mnt(br));
1facf9fc 3286+ br->br_perm = old_perm;
3287+
3288+ if (!err && wbr && !au_br_writable(new_perm)) {
9f237c51 3289+ au_kfree_rcu(wbr);
1facf9fc 3290+ br->br_wbr = NULL;
3291+ }
3292+
86dc4139 3293+out:
1facf9fc 3294+ return err;
3295+}
3296+
3297+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
86dc4139 3298+ int perm)
1facf9fc 3299+{
3300+ int err;
4a4d8108 3301+ struct kstatfs kst;
1facf9fc 3302+ struct au_wbr *wbr;
3303+
3304+ wbr = br->br_wbr;
dece6358 3305+ au_rw_init(&wbr->wbr_wh_rwsem);
1facf9fc 3306+ atomic_set(&wbr->wbr_wh_running, 0);
1facf9fc 3307+
4a4d8108
AM
3308+ /*
3309+ * a limit for rmdir/rename a dir
523b37e3 3310+ * cf. AUFS_MAX_NAMELEN in include/uapi/linux/aufs_type.h
4a4d8108 3311+ */
86dc4139 3312+ err = vfs_statfs(&br->br_path, &kst);
4a4d8108
AM
3313+ if (unlikely(err))
3314+ goto out;
3315+ err = -EINVAL;
3316+ if (kst.f_namelen >= NAME_MAX)
86dc4139 3317+ err = au_br_init_wh(sb, br, perm);
4a4d8108 3318+ else
523b37e3
AM
3319+ pr_err("%pd(%s), unsupported namelen %ld\n",
3320+ au_br_dentry(br),
86dc4139 3321+ au_sbtype(au_br_dentry(br)->d_sb), kst.f_namelen);
1facf9fc 3322+
4f0767ce 3323+out:
1facf9fc 3324+ return err;
3325+}
3326+
c1595e42 3327+/* initialize a new branch */
1facf9fc 3328+static int au_br_init(struct au_branch *br, struct super_block *sb,
3329+ struct au_opt_add *add)
3330+{
3331+ int err;
062440b3
AM
3332+ struct au_branch *brbase;
3333+ struct file *xf;
5527c038 3334+ struct inode *h_inode;
1facf9fc 3335+
3336+ err = 0;
1facf9fc 3337+ br->br_perm = add->perm;
86dc4139 3338+ br->br_path = add->path; /* set first, path_get() later */
4a4d8108 3339+ spin_lock_init(&br->br_dykey_lock);
acd2b654
AM
3340+ au_lcnt_init(&br->br_nfiles, /*release*/NULL);
3341+ au_lcnt_init(&br->br_count, /*release*/NULL);
1facf9fc 3342+ br->br_id = au_new_br_id(sb);
7f207e10 3343+ AuDebugOn(br->br_id < 0);
1facf9fc 3344+
8b6a4947
AM
3345+ /* always, regardless the given option */
3346+ err = au_dr_br_init(sb, br, &add->path);
3347+ if (unlikely(err))
3348+ goto out_err;
3349+
1facf9fc 3350+ if (au_br_writable(add->perm)) {
86dc4139 3351+ err = au_wbr_init(br, sb, add->perm);
1facf9fc 3352+ if (unlikely(err))
b752ccd1 3353+ goto out_err;
1facf9fc 3354+ }
3355+
3356+ if (au_opt_test(au_mntflags(sb), XINO)) {
062440b3 3357+ brbase = au_sbr(sb, 0);
acd2b654 3358+ xf = au_xino_file(brbase->br_xino, /*idx*/-1);
062440b3 3359+ AuDebugOn(!xf);
5527c038 3360+ h_inode = d_inode(add->path.dentry);
062440b3 3361+ err = au_xino_init_br(sb, br, h_inode->i_ino, &xf->f_path);
1facf9fc 3362+ if (unlikely(err)) {
acd2b654 3363+ AuDebugOn(au_xino_file(br->br_xino, /*idx*/-1));
b752ccd1 3364+ goto out_err;
1facf9fc 3365+ }
3366+ }
3367+
3368+ sysaufs_br_init(br);
86dc4139 3369+ path_get(&br->br_path);
b752ccd1 3370+ goto out; /* success */
1facf9fc 3371+
4f0767ce 3372+out_err:
86dc4139 3373+ memset(&br->br_path, 0, sizeof(br->br_path));
4f0767ce 3374+out:
1facf9fc 3375+ return err;
3376+}
3377+
3378+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
5afbbe0d 3379+ struct au_branch *br, aufs_bindex_t bbot,
1facf9fc 3380+ aufs_bindex_t amount)
3381+{
3382+ struct au_branch **brp;
3383+
dece6358
AM
3384+ AuRwMustWriteLock(&sbinfo->si_rwsem);
3385+
1facf9fc 3386+ brp = sbinfo->si_branch + bindex;
3387+ memmove(brp + 1, brp, sizeof(*brp) * amount);
3388+ *brp = br;
5afbbe0d
AM
3389+ sbinfo->si_bbot++;
3390+ if (unlikely(bbot < 0))
3391+ sbinfo->si_bbot = 0;
1facf9fc 3392+}
3393+
3394+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
5afbbe0d 3395+ aufs_bindex_t bbot, aufs_bindex_t amount)
1facf9fc 3396+{
3397+ struct au_hdentry *hdp;
3398+
1308ab2a 3399+ AuRwMustWriteLock(&dinfo->di_rwsem);
3400+
5afbbe0d 3401+ hdp = au_hdentry(dinfo, bindex);
1facf9fc 3402+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
3403+ au_h_dentry_init(hdp);
5afbbe0d
AM
3404+ dinfo->di_bbot++;
3405+ if (unlikely(bbot < 0))
3406+ dinfo->di_btop = 0;
1facf9fc 3407+}
3408+
3409+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
5afbbe0d 3410+ aufs_bindex_t bbot, aufs_bindex_t amount)
1facf9fc 3411+{
3412+ struct au_hinode *hip;
3413+
1308ab2a 3414+ AuRwMustWriteLock(&iinfo->ii_rwsem);
3415+
5afbbe0d 3416+ hip = au_hinode(iinfo, bindex);
1facf9fc 3417+ memmove(hip + 1, hip, sizeof(*hip) * amount);
5afbbe0d
AM
3418+ au_hinode_init(hip);
3419+ iinfo->ii_bbot++;
3420+ if (unlikely(bbot < 0))
3421+ iinfo->ii_btop = 0;
1facf9fc 3422+}
3423+
86dc4139
AM
3424+static void au_br_do_add(struct super_block *sb, struct au_branch *br,
3425+ aufs_bindex_t bindex)
1facf9fc 3426+{
86dc4139 3427+ struct dentry *root, *h_dentry;
5527c038 3428+ struct inode *root_inode, *h_inode;
5afbbe0d 3429+ aufs_bindex_t bbot, amount;
1facf9fc 3430+
3431+ root = sb->s_root;
5527c038 3432+ root_inode = d_inode(root);
5afbbe0d
AM
3433+ bbot = au_sbbot(sb);
3434+ amount = bbot + 1 - bindex;
86dc4139 3435+ h_dentry = au_br_dentry(br);
53392da6 3436+ au_sbilist_lock();
5afbbe0d
AM
3437+ au_br_do_add_brp(au_sbi(sb), bindex, br, bbot, amount);
3438+ au_br_do_add_hdp(au_di(root), bindex, bbot, amount);
3439+ au_br_do_add_hip(au_ii(root_inode), bindex, bbot, amount);
1facf9fc 3440+ au_set_h_dptr(root, bindex, dget(h_dentry));
5527c038
JR
3441+ h_inode = d_inode(h_dentry);
3442+ au_set_h_iptr(root_inode, bindex, au_igrab(h_inode), /*flags*/0);
53392da6 3443+ au_sbilist_unlock();
1facf9fc 3444+}
3445+
3446+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
3447+{
3448+ int err;
5afbbe0d 3449+ aufs_bindex_t bbot, add_bindex;
1facf9fc 3450+ struct dentry *root, *h_dentry;
3451+ struct inode *root_inode;
3452+ struct au_branch *add_branch;
3453+
3454+ root = sb->s_root;
5527c038 3455+ root_inode = d_inode(root);
1facf9fc 3456+ IMustLock(root_inode);
5afbbe0d 3457+ IiMustWriteLock(root_inode);
1facf9fc 3458+ err = test_add(sb, add, remount);
3459+ if (unlikely(err < 0))
3460+ goto out;
3461+ if (err) {
3462+ err = 0;
3463+ goto out; /* success */
3464+ }
3465+
5afbbe0d
AM
3466+ bbot = au_sbbot(sb);
3467+ add_branch = au_br_alloc(sb, bbot + 2, add->perm);
1facf9fc 3468+ err = PTR_ERR(add_branch);
3469+ if (IS_ERR(add_branch))
3470+ goto out;
3471+
3472+ err = au_br_init(add_branch, sb, add);
3473+ if (unlikely(err)) {
3474+ au_br_do_free(add_branch);
3475+ goto out;
3476+ }
3477+
3478+ add_bindex = add->bindex;
062440b3
AM
3479+ sysaufs_brs_del(sb, add_bindex); /* remove successors */
3480+ au_br_do_add(sb, add_branch, add_bindex);
3481+ sysaufs_brs_add(sb, add_bindex); /* append successors */
3482+ dbgaufs_brs_add(sb, add_bindex, /*topdown*/0); /* rename successors */
1facf9fc 3483+
86dc4139 3484+ h_dentry = add->path.dentry;
1308ab2a 3485+ if (!add_bindex) {
1facf9fc 3486+ au_cpup_attr_all(root_inode, /*force*/1);
1308ab2a 3487+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
3488+ } else
5527c038 3489+ au_add_nlink(root_inode, d_inode(h_dentry));
1facf9fc 3490+
4f0767ce 3491+out:
1facf9fc 3492+ return err;
3493+}
3494+
3495+/* ---------------------------------------------------------------------- */
3496+
79b8bda9 3497+static unsigned long long au_farray_cb(struct super_block *sb, void *a,
076b876e
AM
3498+ unsigned long long max __maybe_unused,
3499+ void *arg)
3500+{
3501+ unsigned long long n;
3502+ struct file **p, *f;
8b6a4947
AM
3503+ struct hlist_bl_head *files;
3504+ struct hlist_bl_node *pos;
076b876e 3505+ struct au_finfo *finfo;
076b876e
AM
3506+
3507+ n = 0;
3508+ p = a;
3509+ files = &au_sbi(sb)->si_files;
8b6a4947
AM
3510+ hlist_bl_lock(files);
3511+ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) {
076b876e
AM
3512+ f = finfo->fi_file;
3513+ if (file_count(f)
3514+ && !special_file(file_inode(f)->i_mode)) {
3515+ get_file(f);
3516+ *p++ = f;
3517+ n++;
3518+ AuDebugOn(n > max);
3519+ }
3520+ }
8b6a4947 3521+ hlist_bl_unlock(files);
076b876e
AM
3522+
3523+ return n;
3524+}
3525+
3526+static struct file **au_farray_alloc(struct super_block *sb,
3527+ unsigned long long *max)
3528+{
acd2b654
AM
3529+ struct au_sbinfo *sbi;
3530+
3531+ sbi = au_sbi(sb);
3532+ *max = au_lcnt_read(&sbi->si_nfiles, /*do_rev*/1);
79b8bda9 3533+ return au_array_alloc(max, au_farray_cb, sb, /*arg*/NULL);
076b876e
AM
3534+}
3535+
3536+static void au_farray_free(struct file **a, unsigned long long max)
3537+{
3538+ unsigned long long ull;
3539+
3540+ for (ull = 0; ull < max; ull++)
3541+ if (a[ull])
3542+ fput(a[ull]);
be52b249 3543+ kvfree(a);
076b876e
AM
3544+}
3545+
3546+/* ---------------------------------------------------------------------- */
3547+
1facf9fc 3548+/*
3549+ * delete a branch
3550+ */
3551+
3552+/* to show the line number, do not make it inlined function */
4a4d8108 3553+#define AuVerbose(do_info, fmt, ...) do { \
1facf9fc 3554+ if (do_info) \
4a4d8108 3555+ pr_info(fmt, ##__VA_ARGS__); \
1facf9fc 3556+} while (0)
3557+
5afbbe0d
AM
3558+static int au_test_ibusy(struct inode *inode, aufs_bindex_t btop,
3559+ aufs_bindex_t bbot)
027c5e7a 3560+{
5afbbe0d 3561+ return (inode && !S_ISDIR(inode->i_mode)) || btop == bbot;
027c5e7a
AM
3562+}
3563+
5afbbe0d
AM
3564+static int au_test_dbusy(struct dentry *dentry, aufs_bindex_t btop,
3565+ aufs_bindex_t bbot)
027c5e7a 3566+{
5afbbe0d 3567+ return au_test_ibusy(d_inode(dentry), btop, bbot);
027c5e7a
AM
3568+}
3569+
1facf9fc 3570+/*
3571+ * test if the branch is deletable or not.
3572+ */
3573+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
b752ccd1 3574+ unsigned int sigen, const unsigned int verbose)
1facf9fc 3575+{
3576+ int err, i, j, ndentry;
5afbbe0d 3577+ aufs_bindex_t btop, bbot;
1facf9fc 3578+ struct au_dcsub_pages dpages;
3579+ struct au_dpage *dpage;
3580+ struct dentry *d;
1facf9fc 3581+
3582+ err = au_dpages_init(&dpages, GFP_NOFS);
3583+ if (unlikely(err))
3584+ goto out;
3585+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
3586+ if (unlikely(err))
3587+ goto out_dpages;
3588+
1facf9fc 3589+ for (i = 0; !err && i < dpages.ndpage; i++) {
3590+ dpage = dpages.dpages + i;
3591+ ndentry = dpage->ndentry;
3592+ for (j = 0; !err && j < ndentry; j++) {
3593+ d = dpage->dentries[j];
c1595e42 3594+ AuDebugOn(au_dcount(d) <= 0);
027c5e7a 3595+ if (!au_digen_test(d, sigen)) {
1facf9fc 3596+ di_read_lock_child(d, AuLock_IR);
027c5e7a
AM
3597+ if (unlikely(au_dbrange_test(d))) {
3598+ di_read_unlock(d, AuLock_IR);
3599+ continue;
3600+ }
3601+ } else {
1facf9fc 3602+ di_write_lock_child(d);
027c5e7a
AM
3603+ if (unlikely(au_dbrange_test(d))) {
3604+ di_write_unlock(d);
3605+ continue;
3606+ }
1facf9fc 3607+ err = au_reval_dpath(d, sigen);
3608+ if (!err)
3609+ di_downgrade_lock(d, AuLock_IR);
3610+ else {
3611+ di_write_unlock(d);
3612+ break;
3613+ }
3614+ }
3615+
027c5e7a 3616+ /* AuDbgDentry(d); */
5afbbe0d
AM
3617+ btop = au_dbtop(d);
3618+ bbot = au_dbbot(d);
3619+ if (btop <= bindex
3620+ && bindex <= bbot
1facf9fc 3621+ && au_h_dptr(d, bindex)
5afbbe0d 3622+ && au_test_dbusy(d, btop, bbot)) {
1facf9fc 3623+ err = -EBUSY;
523b37e3 3624+ AuVerbose(verbose, "busy %pd\n", d);
027c5e7a 3625+ AuDbgDentry(d);
1facf9fc 3626+ }
3627+ di_read_unlock(d, AuLock_IR);
3628+ }
3629+ }
3630+
4f0767ce 3631+out_dpages:
1facf9fc 3632+ au_dpages_free(&dpages);
4f0767ce 3633+out:
1facf9fc 3634+ return err;
3635+}
3636+
3637+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
b752ccd1 3638+ unsigned int sigen, const unsigned int verbose)
1facf9fc 3639+{
3640+ int err;
7f207e10
AM
3641+ unsigned long long max, ull;
3642+ struct inode *i, **array;
5afbbe0d 3643+ aufs_bindex_t btop, bbot;
1facf9fc 3644+
7f207e10
AM
3645+ array = au_iarray_alloc(sb, &max);
3646+ err = PTR_ERR(array);
3647+ if (IS_ERR(array))
3648+ goto out;
3649+
1facf9fc 3650+ err = 0;
7f207e10
AM
3651+ AuDbg("b%d\n", bindex);
3652+ for (ull = 0; !err && ull < max; ull++) {
3653+ i = array[ull];
076b876e
AM
3654+ if (unlikely(!i))
3655+ break;
7f207e10 3656+ if (i->i_ino == AUFS_ROOT_INO)
1facf9fc 3657+ continue;
3658+
7f207e10 3659+ /* AuDbgInode(i); */
537831f9 3660+ if (au_iigen(i, NULL) == sigen)
1facf9fc 3661+ ii_read_lock_child(i);
3662+ else {
3663+ ii_write_lock_child(i);
027c5e7a
AM
3664+ err = au_refresh_hinode_self(i);
3665+ au_iigen_dec(i);
1facf9fc 3666+ if (!err)
3667+ ii_downgrade_lock(i);
3668+ else {
3669+ ii_write_unlock(i);
3670+ break;
3671+ }
3672+ }
3673+
5afbbe0d
AM
3674+ btop = au_ibtop(i);
3675+ bbot = au_ibbot(i);
3676+ if (btop <= bindex
3677+ && bindex <= bbot
1facf9fc 3678+ && au_h_iptr(i, bindex)
5afbbe0d 3679+ && au_test_ibusy(i, btop, bbot)) {
1facf9fc 3680+ err = -EBUSY;
3681+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
7f207e10 3682+ AuDbgInode(i);
1facf9fc 3683+ }
3684+ ii_read_unlock(i);
3685+ }
7f207e10 3686+ au_iarray_free(array, max);
1facf9fc 3687+
7f207e10 3688+out:
1facf9fc 3689+ return err;
3690+}
3691+
b752ccd1
AM
3692+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
3693+ const unsigned int verbose)
1facf9fc 3694+{
3695+ int err;
3696+ unsigned int sigen;
3697+
3698+ sigen = au_sigen(root->d_sb);
3699+ DiMustNoWaiters(root);
5527c038 3700+ IiMustNoWaiters(d_inode(root));
1facf9fc 3701+ di_write_unlock(root);
b752ccd1 3702+ err = test_dentry_busy(root, bindex, sigen, verbose);
1facf9fc 3703+ if (!err)
b752ccd1 3704+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose);
1facf9fc 3705+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
3706+
3707+ return err;
3708+}
3709+
076b876e
AM
3710+static int test_dir_busy(struct file *file, aufs_bindex_t br_id,
3711+ struct file **to_free, int *idx)
3712+{
3713+ int err;
c1595e42 3714+ unsigned char matched, root;
5afbbe0d 3715+ aufs_bindex_t bindex, bbot;
076b876e
AM
3716+ struct au_fidir *fidir;
3717+ struct au_hfile *hfile;
3718+
3719+ err = 0;
2000de60 3720+ root = IS_ROOT(file->f_path.dentry);
c1595e42
JR
3721+ if (root) {
3722+ get_file(file);
3723+ to_free[*idx] = file;
3724+ (*idx)++;
3725+ goto out;
3726+ }
3727+
076b876e 3728+ matched = 0;
076b876e
AM
3729+ fidir = au_fi(file)->fi_hdir;
3730+ AuDebugOn(!fidir);
5afbbe0d
AM
3731+ bbot = au_fbbot_dir(file);
3732+ for (bindex = au_fbtop(file); bindex <= bbot; bindex++) {
076b876e
AM
3733+ hfile = fidir->fd_hfile + bindex;
3734+ if (!hfile->hf_file)
3735+ continue;
3736+
c1595e42 3737+ if (hfile->hf_br->br_id == br_id) {
076b876e 3738+ matched = 1;
076b876e 3739+ break;
c1595e42 3740+ }
076b876e 3741+ }
c1595e42 3742+ if (matched)
076b876e
AM
3743+ err = -EBUSY;
3744+
3745+out:
3746+ return err;
3747+}
3748+
3749+static int test_file_busy(struct super_block *sb, aufs_bindex_t br_id,
3750+ struct file **to_free, int opened)
3751+{
3752+ int err, idx;
3753+ unsigned long long ull, max;
5afbbe0d 3754+ aufs_bindex_t btop;
076b876e 3755+ struct file *file, **array;
076b876e
AM
3756+ struct dentry *root;
3757+ struct au_hfile *hfile;
3758+
3759+ array = au_farray_alloc(sb, &max);
3760+ err = PTR_ERR(array);
3761+ if (IS_ERR(array))
3762+ goto out;
3763+
3764+ err = 0;
3765+ idx = 0;
3766+ root = sb->s_root;
3767+ di_write_unlock(root);
3768+ for (ull = 0; ull < max; ull++) {
3769+ file = array[ull];
3770+ if (unlikely(!file))
3771+ break;
3772+
3773+ /* AuDbg("%pD\n", file); */
3774+ fi_read_lock(file);
5afbbe0d 3775+ btop = au_fbtop(file);
2000de60 3776+ if (!d_is_dir(file->f_path.dentry)) {
076b876e
AM
3777+ hfile = &au_fi(file)->fi_htop;
3778+ if (hfile->hf_br->br_id == br_id)
3779+ err = -EBUSY;
3780+ } else
3781+ err = test_dir_busy(file, br_id, to_free, &idx);
3782+ fi_read_unlock(file);
3783+ if (unlikely(err))
3784+ break;
3785+ }
3786+ di_write_lock_child(root);
3787+ au_farray_free(array, max);
3788+ AuDebugOn(idx > opened);
3789+
3790+out:
3791+ return err;
3792+}
3793+
3794+static void br_del_file(struct file **to_free, unsigned long long opened,
062440b3 3795+ aufs_bindex_t br_id)
076b876e
AM
3796+{
3797+ unsigned long long ull;
5afbbe0d 3798+ aufs_bindex_t bindex, btop, bbot, bfound;
076b876e
AM
3799+ struct file *file;
3800+ struct au_fidir *fidir;
3801+ struct au_hfile *hfile;
3802+
3803+ for (ull = 0; ull < opened; ull++) {
3804+ file = to_free[ull];
3805+ if (unlikely(!file))
3806+ break;
3807+
3808+ /* AuDbg("%pD\n", file); */
2000de60 3809+ AuDebugOn(!d_is_dir(file->f_path.dentry));
076b876e
AM
3810+ bfound = -1;
3811+ fidir = au_fi(file)->fi_hdir;
3812+ AuDebugOn(!fidir);
3813+ fi_write_lock(file);
5afbbe0d
AM
3814+ btop = au_fbtop(file);
3815+ bbot = au_fbbot_dir(file);
3816+ for (bindex = btop; bindex <= bbot; bindex++) {
076b876e
AM
3817+ hfile = fidir->fd_hfile + bindex;
3818+ if (!hfile->hf_file)
3819+ continue;
3820+
3821+ if (hfile->hf_br->br_id == br_id) {
3822+ bfound = bindex;
3823+ break;
3824+ }
3825+ }
3826+ AuDebugOn(bfound < 0);
3827+ au_set_h_fptr(file, bfound, NULL);
5afbbe0d
AM
3828+ if (bfound == btop) {
3829+ for (btop++; btop <= bbot; btop++)
3830+ if (au_hf_dir(file, btop)) {
3831+ au_set_fbtop(file, btop);
076b876e
AM
3832+ break;
3833+ }
3834+ }
3835+ fi_write_unlock(file);
3836+ }
3837+}
3838+
1facf9fc 3839+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
3840+ const aufs_bindex_t bindex,
5afbbe0d 3841+ const aufs_bindex_t bbot)
1facf9fc 3842+{
3843+ struct au_branch **brp, **p;
3844+
dece6358
AM
3845+ AuRwMustWriteLock(&sbinfo->si_rwsem);
3846+
1facf9fc 3847+ brp = sbinfo->si_branch + bindex;
5afbbe0d
AM
3848+ if (bindex < bbot)
3849+ memmove(brp, brp + 1, sizeof(*brp) * (bbot - bindex));
3850+ sbinfo->si_branch[0 + bbot] = NULL;
3851+ sbinfo->si_bbot--;
1facf9fc 3852+
e2f27e51
AM
3853+ p = au_krealloc(sbinfo->si_branch, sizeof(*p) * bbot, AuGFP_SBILIST,
3854+ /*may_shrink*/1);
1facf9fc 3855+ if (p)
3856+ sbinfo->si_branch = p;
4a4d8108 3857+ /* harmless error */
1facf9fc 3858+}
3859+
3860+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
5afbbe0d 3861+ const aufs_bindex_t bbot)
1facf9fc 3862+{
3863+ struct au_hdentry *hdp, *p;
3864+
1308ab2a 3865+ AuRwMustWriteLock(&dinfo->di_rwsem);
3866+
5afbbe0d
AM
3867+ hdp = au_hdentry(dinfo, bindex);
3868+ if (bindex < bbot)
3869+ memmove(hdp, hdp + 1, sizeof(*hdp) * (bbot - bindex));
3870+ /* au_h_dentry_init(au_hdentry(dinfo, bbot); */
3871+ dinfo->di_bbot--;
1facf9fc 3872+
e2f27e51
AM
3873+ p = au_krealloc(dinfo->di_hdentry, sizeof(*p) * bbot, AuGFP_SBILIST,
3874+ /*may_shrink*/1);
1facf9fc 3875+ if (p)
3876+ dinfo->di_hdentry = p;
4a4d8108 3877+ /* harmless error */
1facf9fc 3878+}
3879+
3880+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
5afbbe0d 3881+ const aufs_bindex_t bbot)
1facf9fc 3882+{
3883+ struct au_hinode *hip, *p;
3884+
1308ab2a 3885+ AuRwMustWriteLock(&iinfo->ii_rwsem);
3886+
5afbbe0d
AM
3887+ hip = au_hinode(iinfo, bindex);
3888+ if (bindex < bbot)
3889+ memmove(hip, hip + 1, sizeof(*hip) * (bbot - bindex));
3890+ /* au_hinode_init(au_hinode(iinfo, bbot)); */
3891+ iinfo->ii_bbot--;
1facf9fc 3892+
e2f27e51
AM
3893+ p = au_krealloc(iinfo->ii_hinode, sizeof(*p) * bbot, AuGFP_SBILIST,
3894+ /*may_shrink*/1);
1facf9fc 3895+ if (p)
3896+ iinfo->ii_hinode = p;
4a4d8108 3897+ /* harmless error */
1facf9fc 3898+}
3899+
3900+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
3901+ struct au_branch *br)
3902+{
5afbbe0d 3903+ aufs_bindex_t bbot;
1facf9fc 3904+ struct au_sbinfo *sbinfo;
53392da6
AM
3905+ struct dentry *root, *h_root;
3906+ struct inode *inode, *h_inode;
3907+ struct au_hinode *hinode;
1facf9fc 3908+
dece6358
AM
3909+ SiMustWriteLock(sb);
3910+
1facf9fc 3911+ root = sb->s_root;
5527c038 3912+ inode = d_inode(root);
1facf9fc 3913+ sbinfo = au_sbi(sb);
5afbbe0d 3914+ bbot = sbinfo->si_bbot;
1facf9fc 3915+
53392da6
AM
3916+ h_root = au_h_dptr(root, bindex);
3917+ hinode = au_hi(inode, bindex);
3918+ h_inode = au_igrab(hinode->hi_inode);
3919+ au_hiput(hinode);
1facf9fc 3920+
53392da6 3921+ au_sbilist_lock();
5afbbe0d
AM
3922+ au_br_do_del_brp(sbinfo, bindex, bbot);
3923+ au_br_do_del_hdp(au_di(root), bindex, bbot);
3924+ au_br_do_del_hip(au_ii(inode), bindex, bbot);
53392da6
AM
3925+ au_sbilist_unlock();
3926+
8b6a4947
AM
3927+ /* ignore an error */
3928+ au_dr_br_fin(sb, br); /* always, regardless the mount option */
3929+
53392da6
AM
3930+ dput(h_root);
3931+ iput(h_inode);
3932+ au_br_do_free(br);
1facf9fc 3933+}
3934+
79b8bda9
AM
3935+static unsigned long long empty_cb(struct super_block *sb, void *array,
3936+ unsigned long long max, void *arg)
076b876e
AM
3937+{
3938+ return max;
3939+}
3940+
1facf9fc 3941+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
3942+{
3943+ int err, rerr, i;
076b876e 3944+ unsigned long long opened;
1facf9fc 3945+ unsigned int mnt_flags;
5afbbe0d 3946+ aufs_bindex_t bindex, bbot, br_id;
1facf9fc 3947+ unsigned char do_wh, verbose;
3948+ struct au_branch *br;
3949+ struct au_wbr *wbr;
076b876e
AM
3950+ struct dentry *root;
3951+ struct file **to_free;
1facf9fc 3952+
3953+ err = 0;
076b876e
AM
3954+ opened = 0;
3955+ to_free = NULL;
3956+ root = sb->s_root;
3957+ bindex = au_find_dbindex(root, del->h_path.dentry);
1facf9fc 3958+ if (bindex < 0) {
3959+ if (remount)
3960+ goto out; /* success */
3961+ err = -ENOENT;
4a4d8108 3962+ pr_err("%s no such branch\n", del->pathname);
1facf9fc 3963+ goto out;
3964+ }
3965+ AuDbg("bindex b%d\n", bindex);
3966+
3967+ err = -EBUSY;
3968+ mnt_flags = au_mntflags(sb);
3969+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
5afbbe0d
AM
3970+ bbot = au_sbbot(sb);
3971+ if (unlikely(!bbot)) {
1facf9fc 3972+ AuVerbose(verbose, "no more branches left\n");
3973+ goto out;
3974+ }
acd2b654 3975+
1facf9fc 3976+ br = au_sbr(sb, bindex);
86dc4139 3977+ AuDebugOn(!path_equal(&br->br_path, &del->h_path));
acd2b654
AM
3978+ if (unlikely(au_lcnt_read(&br->br_count, /*do_rev*/1))) {
3979+ AuVerbose(verbose, "br %pd2 is busy now\n", del->h_path.dentry);
3980+ goto out;
3981+ }
076b876e
AM
3982+
3983+ br_id = br->br_id;
acd2b654 3984+ opened = au_lcnt_read(&br->br_nfiles, /*do_rev*/1);
076b876e 3985+ if (unlikely(opened)) {
79b8bda9 3986+ to_free = au_array_alloc(&opened, empty_cb, sb, NULL);
076b876e
AM
3987+ err = PTR_ERR(to_free);
3988+ if (IS_ERR(to_free))
3989+ goto out;
3990+
3991+ err = test_file_busy(sb, br_id, to_free, opened);
3992+ if (unlikely(err)) {
3993+ AuVerbose(verbose, "%llu file(s) opened\n", opened);
3994+ goto out;
3995+ }
1facf9fc 3996+ }
3997+
3998+ wbr = br->br_wbr;
3999+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
4000+ if (do_wh) {
1308ab2a 4001+ /* instead of WbrWhMustWriteLock(wbr) */
4002+ SiMustWriteLock(sb);
1facf9fc 4003+ for (i = 0; i < AuBrWh_Last; i++) {
4004+ dput(wbr->wbr_wh[i]);
4005+ wbr->wbr_wh[i] = NULL;
4006+ }
4007+ }
4008+
076b876e 4009+ err = test_children_busy(root, bindex, verbose);
1facf9fc 4010+ if (unlikely(err)) {
4011+ if (do_wh)
4012+ goto out_wh;
4013+ goto out;
4014+ }
4015+
4016+ err = 0;
076b876e
AM
4017+ if (to_free) {
4018+ /*
4019+ * now we confirmed the branch is deletable.
4020+ * let's free the remaining opened dirs on the branch.
4021+ */
4022+ di_write_unlock(root);
4023+ br_del_file(to_free, opened, br_id);
4024+ di_write_lock_child(root);
4025+ }
4026+
062440b3
AM
4027+ sysaufs_brs_del(sb, bindex); /* remove successors */
4028+ dbgaufs_xino_del(br); /* remove one */
4029+ au_br_do_del(sb, bindex, br);
4030+ sysaufs_brs_add(sb, bindex); /* append successors */
4031+ dbgaufs_brs_add(sb, bindex, /*topdown*/1); /* rename successors */
1facf9fc 4032+
1308ab2a 4033+ if (!bindex) {
5527c038 4034+ au_cpup_attr_all(d_inode(root), /*force*/1);
1308ab2a 4035+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
4036+ } else
5527c038 4037+ au_sub_nlink(d_inode(root), d_inode(del->h_path.dentry));
1facf9fc 4038+ if (au_opt_test(mnt_flags, PLINK))
4039+ au_plink_half_refresh(sb, br_id);
4040+
1facf9fc 4041+ goto out; /* success */
4042+
4f0767ce 4043+out_wh:
1facf9fc 4044+ /* revert */
86dc4139 4045+ rerr = au_br_init_wh(sb, br, br->br_perm);
1facf9fc 4046+ if (rerr)
0c3ec466
AM
4047+ pr_warn("failed re-creating base whiteout, %s. (%d)\n",
4048+ del->pathname, rerr);
4f0767ce 4049+out:
076b876e
AM
4050+ if (to_free)
4051+ au_farray_free(to_free, opened);
1facf9fc 4052+ return err;
4053+}
4054+
4055+/* ---------------------------------------------------------------------- */
4056+
027c5e7a
AM
4057+static int au_ibusy(struct super_block *sb, struct aufs_ibusy __user *arg)
4058+{
4059+ int err;
5afbbe0d 4060+ aufs_bindex_t btop, bbot;
027c5e7a
AM
4061+ struct aufs_ibusy ibusy;
4062+ struct inode *inode, *h_inode;
4063+
4064+ err = -EPERM;
4065+ if (unlikely(!capable(CAP_SYS_ADMIN)))
4066+ goto out;
4067+
4068+ err = copy_from_user(&ibusy, arg, sizeof(ibusy));
4069+ if (!err)
ba1aed25
AM
4070+ /* VERIFY_WRITE */
4071+ err = !access_ok(&arg->h_ino, sizeof(arg->h_ino));
027c5e7a
AM
4072+ if (unlikely(err)) {
4073+ err = -EFAULT;
4074+ AuTraceErr(err);
4075+ goto out;
4076+ }
4077+
4078+ err = -EINVAL;
4079+ si_read_lock(sb, AuLock_FLUSH);
5afbbe0d 4080+ if (unlikely(ibusy.bindex < 0 || ibusy.bindex > au_sbbot(sb)))
027c5e7a
AM
4081+ goto out_unlock;
4082+
4083+ err = 0;
4084+ ibusy.h_ino = 0; /* invalid */
4085+ inode = ilookup(sb, ibusy.ino);
4086+ if (!inode
4087+ || inode->i_ino == AUFS_ROOT_INO
5afbbe0d 4088+ || au_is_bad_inode(inode))
027c5e7a
AM
4089+ goto out_unlock;
4090+
4091+ ii_read_lock_child(inode);
5afbbe0d
AM
4092+ btop = au_ibtop(inode);
4093+ bbot = au_ibbot(inode);
4094+ if (btop <= ibusy.bindex && ibusy.bindex <= bbot) {
027c5e7a 4095+ h_inode = au_h_iptr(inode, ibusy.bindex);
5afbbe0d 4096+ if (h_inode && au_test_ibusy(inode, btop, bbot))
027c5e7a
AM
4097+ ibusy.h_ino = h_inode->i_ino;
4098+ }
4099+ ii_read_unlock(inode);
4100+ iput(inode);
4101+
4102+out_unlock:
4103+ si_read_unlock(sb);
4104+ if (!err) {
4105+ err = __put_user(ibusy.h_ino, &arg->h_ino);
4106+ if (unlikely(err)) {
4107+ err = -EFAULT;
4108+ AuTraceErr(err);
4109+ }
4110+ }
4111+out:
4112+ return err;
4113+}
4114+
4115+long au_ibusy_ioctl(struct file *file, unsigned long arg)
4116+{
2000de60 4117+ return au_ibusy(file->f_path.dentry->d_sb, (void __user *)arg);
027c5e7a
AM
4118+}
4119+
4120+#ifdef CONFIG_COMPAT
4121+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg)
4122+{
2000de60 4123+ return au_ibusy(file->f_path.dentry->d_sb, compat_ptr(arg));
027c5e7a
AM
4124+}
4125+#endif
4126+
4127+/* ---------------------------------------------------------------------- */
4128+
1facf9fc 4129+/*
4130+ * change a branch permission
4131+ */
4132+
dece6358
AM
4133+static void au_warn_ima(void)
4134+{
4135+#ifdef CONFIG_IMA
1308ab2a 4136+ /* since it doesn't support mark_files_ro() */
027c5e7a 4137+ AuWarn1("RW -> RO makes IMA to produce wrong message\n");
dece6358
AM
4138+#endif
4139+}
4140+
1facf9fc 4141+static int do_need_sigen_inc(int a, int b)
4142+{
4143+ return au_br_whable(a) && !au_br_whable(b);
4144+}
4145+
4146+static int need_sigen_inc(int old, int new)
4147+{
4148+ return do_need_sigen_inc(old, new)
4149+ || do_need_sigen_inc(new, old);
4150+}
4151+
4152+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
4153+{
7f207e10 4154+ int err, do_warn;
027c5e7a 4155+ unsigned int mnt_flags;
7f207e10 4156+ unsigned long long ull, max;
e49829fe 4157+ aufs_bindex_t br_id;
38d290e6 4158+ unsigned char verbose, writer;
7f207e10 4159+ struct file *file, *hf, **array;
e49829fe 4160+ struct au_hfile *hfile;
eca34b5c 4161+ struct inode *h_inode;
1facf9fc 4162+
027c5e7a
AM
4163+ mnt_flags = au_mntflags(sb);
4164+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
4165+
7f207e10
AM
4166+ array = au_farray_alloc(sb, &max);
4167+ err = PTR_ERR(array);
4168+ if (IS_ERR(array))
1facf9fc 4169+ goto out;
4170+
7f207e10 4171+ do_warn = 0;
e49829fe 4172+ br_id = au_sbr_id(sb, bindex);
7f207e10
AM
4173+ for (ull = 0; ull < max; ull++) {
4174+ file = array[ull];
076b876e
AM
4175+ if (unlikely(!file))
4176+ break;
1facf9fc 4177+
523b37e3 4178+ /* AuDbg("%pD\n", file); */
1facf9fc 4179+ fi_read_lock(file);
4180+ if (unlikely(au_test_mmapped(file))) {
4181+ err = -EBUSY;
523b37e3 4182+ AuVerbose(verbose, "mmapped %pD\n", file);
7f207e10 4183+ AuDbgFile(file);
1facf9fc 4184+ FiMustNoWaiters(file);
4185+ fi_read_unlock(file);
7f207e10 4186+ goto out_array;
1facf9fc 4187+ }
4188+
e49829fe
JR
4189+ hfile = &au_fi(file)->fi_htop;
4190+ hf = hfile->hf_file;
7e9cd9fe 4191+ if (!d_is_reg(file->f_path.dentry)
1facf9fc 4192+ || !(file->f_mode & FMODE_WRITE)
e49829fe 4193+ || hfile->hf_br->br_id != br_id
7f207e10
AM
4194+ || !(hf->f_mode & FMODE_WRITE))
4195+ array[ull] = NULL;
4196+ else {
4197+ do_warn = 1;
4198+ get_file(file);
1facf9fc 4199+ }
4200+
1facf9fc 4201+ FiMustNoWaiters(file);
4202+ fi_read_unlock(file);
7f207e10
AM
4203+ fput(file);
4204+ }
1facf9fc 4205+
4206+ err = 0;
7f207e10 4207+ if (do_warn)
dece6358 4208+ au_warn_ima();
7f207e10
AM
4209+
4210+ for (ull = 0; ull < max; ull++) {
4211+ file = array[ull];
4212+ if (!file)
4213+ continue;
4214+
1facf9fc 4215+ /* todo: already flushed? */
523b37e3
AM
4216+ /*
4217+ * fs/super.c:mark_files_ro() is gone, but aufs keeps its
4218+ * approach which resets f_mode and calls mnt_drop_write() and
4219+ * file_release_write() for each file, because the branch
4220+ * attribute in aufs world is totally different from the native
4221+ * fs rw/ro mode.
4222+ */
7f207e10
AM
4223+ /* fi_read_lock(file); */
4224+ hfile = &au_fi(file)->fi_htop;
4225+ hf = hfile->hf_file;
4226+ /* fi_read_unlock(file); */
027c5e7a 4227+ spin_lock(&hf->f_lock);
38d290e6
JR
4228+ writer = !!(hf->f_mode & FMODE_WRITER);
4229+ hf->f_mode &= ~(FMODE_WRITE | FMODE_WRITER);
027c5e7a 4230+ spin_unlock(&hf->f_lock);
38d290e6 4231+ if (writer) {
eca34b5c 4232+ h_inode = file_inode(hf);
42b5c33a
AM
4233+ if (hf->f_mode & FMODE_READ)
4234+ i_readcount_inc(h_inode);
eca34b5c 4235+ put_write_access(h_inode);
c06a8ce3 4236+ __mnt_drop_write(hf->f_path.mnt);
1facf9fc 4237+ }
4238+ }
4239+
7f207e10
AM
4240+out_array:
4241+ au_farray_free(array, max);
4f0767ce 4242+out:
7f207e10 4243+ AuTraceErr(err);
1facf9fc 4244+ return err;
4245+}
4246+
4247+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 4248+ int *do_refresh)
1facf9fc 4249+{
4250+ int err, rerr;
4251+ aufs_bindex_t bindex;
4252+ struct dentry *root;
4253+ struct au_branch *br;
076b876e 4254+ struct au_br_fhsm *bf;
1facf9fc 4255+
4256+ root = sb->s_root;
1facf9fc 4257+ bindex = au_find_dbindex(root, mod->h_root);
4258+ if (bindex < 0) {
4259+ if (remount)
4260+ return 0; /* success */
4261+ err = -ENOENT;
4a4d8108 4262+ pr_err("%s no such branch\n", mod->path);
1facf9fc 4263+ goto out;
4264+ }
4265+ AuDbg("bindex b%d\n", bindex);
4266+
5527c038 4267+ err = test_br(d_inode(mod->h_root), mod->perm, mod->path);
1facf9fc 4268+ if (unlikely(err))
4269+ goto out;
4270+
4271+ br = au_sbr(sb, bindex);
86dc4139 4272+ AuDebugOn(mod->h_root != au_br_dentry(br));
1facf9fc 4273+ if (br->br_perm == mod->perm)
4274+ return 0; /* success */
4275+
076b876e
AM
4276+ /* pre-allocate for non-fhsm --> fhsm */
4277+ bf = NULL;
4278+ if (!au_br_fhsm(br->br_perm) && au_br_fhsm(mod->perm)) {
4279+ err = au_fhsm_br_alloc(br);
4280+ if (unlikely(err))
4281+ goto out;
4282+ bf = br->br_fhsm;
4283+ br->br_fhsm = NULL;
4284+ }
4285+
1facf9fc 4286+ if (au_br_writable(br->br_perm)) {
4287+ /* remove whiteout base */
86dc4139 4288+ err = au_br_init_wh(sb, br, mod->perm);
1facf9fc 4289+ if (unlikely(err))
076b876e 4290+ goto out_bf;
1facf9fc 4291+
4292+ if (!au_br_writable(mod->perm)) {
4293+ /* rw --> ro, file might be mmapped */
4294+ DiMustNoWaiters(root);
5527c038 4295+ IiMustNoWaiters(d_inode(root));
1facf9fc 4296+ di_write_unlock(root);
4297+ err = au_br_mod_files_ro(sb, bindex);
4298+ /* aufs_write_lock() calls ..._child() */
4299+ di_write_lock_child(root);
4300+
4301+ if (unlikely(err)) {
4302+ rerr = -ENOMEM;
be52b249 4303+ br->br_wbr = kzalloc(sizeof(*br->br_wbr),
1facf9fc 4304+ GFP_NOFS);
86dc4139
AM
4305+ if (br->br_wbr)
4306+ rerr = au_wbr_init(br, sb, br->br_perm);
1facf9fc 4307+ if (unlikely(rerr)) {
4308+ AuIOErr("nested error %d (%d)\n",
4309+ rerr, err);
4310+ br->br_perm = mod->perm;
4311+ }
4312+ }
4313+ }
4314+ } else if (au_br_writable(mod->perm)) {
4315+ /* ro --> rw */
4316+ err = -ENOMEM;
be52b249 4317+ br->br_wbr = kzalloc(sizeof(*br->br_wbr), GFP_NOFS);
1facf9fc 4318+ if (br->br_wbr) {
86dc4139 4319+ err = au_wbr_init(br, sb, mod->perm);
1facf9fc 4320+ if (unlikely(err)) {
9f237c51 4321+ au_kfree_rcu(br->br_wbr);
1facf9fc 4322+ br->br_wbr = NULL;
4323+ }
4324+ }
4325+ }
076b876e
AM
4326+ if (unlikely(err))
4327+ goto out_bf;
4328+
4329+ if (au_br_fhsm(br->br_perm)) {
4330+ if (!au_br_fhsm(mod->perm)) {
4331+ /* fhsm --> non-fhsm */
4332+ au_br_fhsm_fin(br->br_fhsm);
9f237c51 4333+ au_kfree_rcu(br->br_fhsm);
076b876e
AM
4334+ br->br_fhsm = NULL;
4335+ }
4336+ } else if (au_br_fhsm(mod->perm))
4337+ /* non-fhsm --> fhsm */
4338+ br->br_fhsm = bf;
4339+
076b876e
AM
4340+ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm);
4341+ br->br_perm = mod->perm;
4342+ goto out; /* success */
1facf9fc 4343+
076b876e 4344+out_bf:
9f237c51 4345+ au_kfree_try_rcu(bf);
076b876e
AM
4346+out:
4347+ AuTraceErr(err);
4348+ return err;
4349+}
4350+
4351+/* ---------------------------------------------------------------------- */
4352+
4353+int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs)
4354+{
4355+ int err;
4356+ struct kstatfs kstfs;
4357+
4358+ err = vfs_statfs(&br->br_path, &kstfs);
1facf9fc 4359+ if (!err) {
076b876e
AM
4360+ stfs->f_blocks = kstfs.f_blocks;
4361+ stfs->f_bavail = kstfs.f_bavail;
4362+ stfs->f_files = kstfs.f_files;
4363+ stfs->f_ffree = kstfs.f_ffree;
1facf9fc 4364+ }
4365+
1facf9fc 4366+ return err;
4367+}
7f207e10 4368diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
eca34b5c 4369--- /usr/share/empty/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6
JR
4370+++ linux/fs/aufs/branch.h 2021-05-02 20:15:14.670004120 +0200
4371@@ -0,0 +1,375 @@
062440b3 4372+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 4373+/*
d58c55f2 4374+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 4375+ *
4376+ * This program, aufs is free software; you can redistribute it and/or modify
4377+ * it under the terms of the GNU General Public License as published by
4378+ * the Free Software Foundation; either version 2 of the License, or
4379+ * (at your option) any later version.
dece6358
AM
4380+ *
4381+ * This program is distributed in the hope that it will be useful,
4382+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4383+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4384+ * GNU General Public License for more details.
4385+ *
4386+ * You should have received a copy of the GNU General Public License
523b37e3 4387+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 4388+ */
4389+
4390+/*
4391+ * branch filesystems and xino for them
4392+ */
4393+
4394+#ifndef __AUFS_BRANCH_H__
4395+#define __AUFS_BRANCH_H__
4396+
4397+#ifdef __KERNEL__
4398+
1facf9fc 4399+#include <linux/mount.h>
8b6a4947 4400+#include "dirren.h"
4a4d8108 4401+#include "dynop.h"
acd2b654 4402+#include "lcnt.h"
1facf9fc 4403+#include "rwsem.h"
4404+#include "super.h"
4405+
4406+/* ---------------------------------------------------------------------- */
4407+
4408+/* a xino file */
062440b3 4409+struct au_xino {
acd2b654
AM
4410+ struct file **xi_file;
4411+ unsigned int xi_nfile;
4412+
521ced18
JR
4413+ struct {
4414+ spinlock_t spin;
4415+ ino_t *array;
4416+ int total;
4417+ /* reserved for future use */
4418+ /* unsigned long *bitmap; */
4419+ wait_queue_head_t wqh;
4420+ } xi_nondir;
1facf9fc 4421+
acd2b654 4422+ struct mutex xi_mtx; /* protects xi_file array */
9f237c51 4423+ struct hlist_bl_head xi_writing;
acd2b654 4424+
062440b3 4425+ atomic_t xi_truncating;
1facf9fc 4426+
062440b3 4427+ struct kref xi_kref;
1facf9fc 4428+};
4429+
076b876e
AM
4430+/* File-based Hierarchical Storage Management */
4431+struct au_br_fhsm {
4432+#ifdef CONFIG_AUFS_FHSM
4433+ struct mutex bf_lock;
4434+ unsigned long bf_jiffy;
4435+ struct aufs_stfs bf_stfs;
4436+ int bf_readable;
4437+#endif
4438+};
4439+
1facf9fc 4440+/* members for writable branch only */
4441+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
4442+struct au_wbr {
dece6358 4443+ struct au_rwsem wbr_wh_rwsem;
1facf9fc 4444+ struct dentry *wbr_wh[AuBrWh_Last];
4a4d8108 4445+ atomic_t wbr_wh_running;
1facf9fc 4446+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
4447+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
4448+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
4449+
4450+ /* mfs mode */
4451+ unsigned long long wbr_bytes;
4452+};
4453+
4a4d8108
AM
4454+/* ext2 has 3 types of operations at least, ext3 has 4 */
4455+#define AuBrDynOp (AuDyLast * 4)
4456+
1716fcea
AM
4457+#ifdef CONFIG_AUFS_HFSNOTIFY
4458+/* support for asynchronous destruction */
4459+struct au_br_hfsnotify {
4460+ struct fsnotify_group *hfsn_group;
4461+};
4462+#endif
4463+
392086de
AM
4464+/* sysfs entries */
4465+struct au_brsysfs {
4466+ char name[16];
4467+ struct attribute attr;
4468+};
4469+
4470+enum {
4471+ AuBrSysfs_BR,
4472+ AuBrSysfs_BRID,
4473+ AuBrSysfs_Last
4474+};
4475+
1facf9fc 4476+/* protected by superblock rwsem */
4477+struct au_branch {
062440b3 4478+ struct au_xino *br_xino;
1facf9fc 4479+
4480+ aufs_bindex_t br_id;
4481+
4482+ int br_perm;
86dc4139 4483+ struct path br_path;
4a4d8108
AM
4484+ spinlock_t br_dykey_lock;
4485+ struct au_dykey *br_dykey[AuBrDynOp];
acd2b654
AM
4486+ au_lcnt_t br_nfiles; /* opened files */
4487+ au_lcnt_t br_count; /* in-use for other */
1facf9fc 4488+
4489+ struct au_wbr *br_wbr;
076b876e 4490+ struct au_br_fhsm *br_fhsm;
1facf9fc 4491+
027c5e7a 4492+#ifdef CONFIG_AUFS_HFSNOTIFY
1716fcea 4493+ struct au_br_hfsnotify *br_hfsn;
027c5e7a
AM
4494+#endif
4495+
1facf9fc 4496+#ifdef CONFIG_SYSFS
392086de
AM
4497+ /* entries under sysfs per mount-point */
4498+ struct au_brsysfs br_sysfs[AuBrSysfs_Last];
1facf9fc 4499+#endif
8b6a4947 4500+
062440b3
AM
4501+#ifdef CONFIG_DEBUG_FS
4502+ struct dentry *br_dbgaufs; /* xino */
4503+#endif
4504+
8b6a4947 4505+ struct au_dr_br br_dirren;
1facf9fc 4506+};
4507+
4508+/* ---------------------------------------------------------------------- */
4509+
86dc4139
AM
4510+static inline struct vfsmount *au_br_mnt(struct au_branch *br)
4511+{
4512+ return br->br_path.mnt;
4513+}
4514+
4515+static inline struct dentry *au_br_dentry(struct au_branch *br)
4516+{
4517+ return br->br_path.dentry;
4518+}
4519+
0b2a12c6
JR
4520+static inline struct user_namespace *au_br_userns(struct au_branch *br)
4521+{
4522+ return mnt_user_ns(br->br_path.mnt);
4523+}
4524+
86dc4139
AM
4525+static inline struct super_block *au_br_sb(struct au_branch *br)
4526+{
4527+ return au_br_mnt(br)->mnt_sb;
4528+}
4529+
1facf9fc 4530+static inline int au_br_rdonly(struct au_branch *br)
4531+{
8b6a4947 4532+ return (sb_rdonly(au_br_sb(br))
1facf9fc 4533+ || !au_br_writable(br->br_perm))
4534+ ? -EROFS : 0;
4535+}
4536+
4a4d8108 4537+static inline int au_br_hnotifyable(int brperm __maybe_unused)
1facf9fc 4538+{
4a4d8108 4539+#ifdef CONFIG_AUFS_HNOTIFY
1e00d052 4540+ return !(brperm & AuBrPerm_RR);
1facf9fc 4541+#else
4542+ return 0;
4543+#endif
4544+}
4545+
b912730e
AM
4546+static inline int au_br_test_oflag(int oflag, struct au_branch *br)
4547+{
4548+ int err, exec_flag;
4549+
4550+ err = 0;
4551+ exec_flag = oflag & __FMODE_EXEC;
79b8bda9 4552+ if (unlikely(exec_flag && path_noexec(&br->br_path)))
b912730e
AM
4553+ err = -EACCES;
4554+
4555+ return err;
4556+}
4557+
062440b3
AM
4558+static inline void au_xino_get(struct au_branch *br)
4559+{
4560+ struct au_xino *xi;
4561+
4562+ xi = br->br_xino;
4563+ if (xi)
4564+ kref_get(&xi->xi_kref);
4565+}
4566+
4567+static inline int au_xino_count(struct au_branch *br)
4568+{
4569+ int v;
4570+ struct au_xino *xi;
4571+
4572+ v = 0;
4573+ xi = br->br_xino;
4574+ if (xi)
4575+ v = kref_read(&xi->xi_kref);
4576+
4577+ return v;
4578+}
4579+
1facf9fc 4580+/* ---------------------------------------------------------------------- */
4581+
4582+/* branch.c */
4583+struct au_sbinfo;
4584+void au_br_free(struct au_sbinfo *sinfo);
4585+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
4586+struct au_opt_add;
4587+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
4588+struct au_opt_del;
4589+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
027c5e7a
AM
4590+long au_ibusy_ioctl(struct file *file, unsigned long arg);
4591+#ifdef CONFIG_COMPAT
4592+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg);
4593+#endif
1facf9fc 4594+struct au_opt_mod;
4595+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 4596+ int *do_refresh);
076b876e
AM
4597+struct aufs_stfs;
4598+int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs);
1facf9fc 4599+
4600+/* xino.c */
4601+static const loff_t au_loff_max = LLONG_MAX;
4602+
acd2b654 4603+aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry);
83b672a5
AM
4604+struct file *au_xino_create(struct super_block *sb, char *fpath, int silent,
4605+ int wbrtop);
062440b3
AM
4606+struct file *au_xino_create2(struct super_block *sb, struct path *base,
4607+ struct file *copy_src);
acd2b654
AM
4608+struct au_xi_new {
4609+ struct au_xino *xi; /* switch between xino and xigen */
4610+ int idx;
4611+ struct path *base;
4612+ struct file *copy_src;
4613+};
4614+struct file *au_xi_new(struct super_block *sb, struct au_xi_new *xinew);
062440b3
AM
4615+
4616+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
4617+ ino_t *ino);
4618+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
4619+ ino_t ino);
e37dd06a
AM
4620+ssize_t xino_fread(struct file *file, void *buf, size_t size, loff_t *pos);
4621+ssize_t xino_fwrite(struct file *file, void *buf, size_t size, loff_t *pos);
062440b3
AM
4622+
4623+int au_xib_trunc(struct super_block *sb);
acd2b654 4624+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin);
1facf9fc 4625+
acd2b654 4626+struct au_xino *au_xino_alloc(unsigned int nfile);
062440b3 4627+int au_xino_put(struct au_branch *br);
acd2b654 4628+struct file *au_xino_file1(struct au_xino *xi);
062440b3 4629+
1facf9fc 4630+struct au_opt_xino;
1facf9fc 4631+void au_xino_clr(struct super_block *sb);
062440b3 4632+int au_xino_set(struct super_block *sb, struct au_opt_xino *xiopt, int remount);
1facf9fc 4633+struct file *au_xino_def(struct super_block *sb);
062440b3
AM
4634+int au_xino_init_br(struct super_block *sb, struct au_branch *br, ino_t hino,
4635+ struct path *base);
4636+
4637+ino_t au_xino_new_ino(struct super_block *sb);
4638+void au_xino_delete_inode(struct inode *inode, const int unlinked);
1facf9fc 4639+
521ced18
JR
4640+void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex,
4641+ ino_t h_ino, int idx);
4642+int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
4643+ int *idx);
4644+
062440b3
AM
4645+int au_xino_path(struct seq_file *seq, struct file *file);
4646+
1facf9fc 4647+/* ---------------------------------------------------------------------- */
4648+
acd2b654
AM
4649+/* @idx is signed to accept -1 meaning the first file */
4650+static inline struct file *au_xino_file(struct au_xino *xi, int idx)
4651+{
4652+ struct file *file;
4653+
4654+ file = NULL;
4655+ if (!xi)
4656+ goto out;
4657+
4658+ if (idx >= 0) {
4659+ if (idx < xi->xi_nfile)
4660+ file = xi->xi_file[idx];
4661+ } else
4662+ file = au_xino_file1(xi);
4663+
4664+out:
4665+ return file;
4666+}
4667+
4668+/* ---------------------------------------------------------------------- */
4669+
1facf9fc 4670+/* Superblock to branch */
4671+static inline
4672+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
4673+{
4674+ return au_sbr(sb, bindex)->br_id;
4675+}
4676+
4677+static inline
4678+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
4679+{
86dc4139 4680+ return au_br_mnt(au_sbr(sb, bindex));
1facf9fc 4681+}
4682+
4683+static inline
0b2a12c6
JR
4684+struct user_namespace *au_sbr_userns(struct super_block *sb, aufs_bindex_t bindex)
4685+{
4686+ return au_br_userns(au_sbr(sb, bindex));
4687+}
4688+
4689+static inline
1facf9fc 4690+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
4691+{
86dc4139 4692+ return au_br_sb(au_sbr(sb, bindex));
1facf9fc 4693+}
4694+
1facf9fc 4695+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
4696+{
4697+ return au_sbr(sb, bindex)->br_perm;
4698+}
4699+
4700+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
4701+{
4702+ return au_br_whable(au_sbr_perm(sb, bindex));
4703+}
4704+
4705+/* ---------------------------------------------------------------------- */
4706+
8b6a4947
AM
4707+#define wbr_wh_read_lock(wbr) au_rw_read_lock(&(wbr)->wbr_wh_rwsem)
4708+#define wbr_wh_write_lock(wbr) au_rw_write_lock(&(wbr)->wbr_wh_rwsem)
4709+#define wbr_wh_read_trylock(wbr) au_rw_read_trylock(&(wbr)->wbr_wh_rwsem)
4710+#define wbr_wh_write_trylock(wbr) au_rw_write_trylock(&(wbr)->wbr_wh_rwsem)
1facf9fc 4711+/*
8b6a4947
AM
4712+#define wbr_wh_read_trylock_nested(wbr) \
4713+ au_rw_read_trylock_nested(&(wbr)->wbr_wh_rwsem)
4714+#define wbr_wh_write_trylock_nested(wbr) \
4715+ au_rw_write_trylock_nested(&(wbr)->wbr_wh_rwsem)
4716+*/
1facf9fc 4717+
8b6a4947
AM
4718+#define wbr_wh_read_unlock(wbr) au_rw_read_unlock(&(wbr)->wbr_wh_rwsem)
4719+#define wbr_wh_write_unlock(wbr) au_rw_write_unlock(&(wbr)->wbr_wh_rwsem)
4720+#define wbr_wh_downgrade_lock(wbr) au_rw_dgrade_lock(&(wbr)->wbr_wh_rwsem)
4721+
4722+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&(wbr)->wbr_wh_rwsem)
4723+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&(wbr)->wbr_wh_rwsem)
4724+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&(wbr)->wbr_wh_rwsem)
dece6358 4725+
076b876e
AM
4726+/* ---------------------------------------------------------------------- */
4727+
4728+#ifdef CONFIG_AUFS_FHSM
4729+static inline void au_br_fhsm_init(struct au_br_fhsm *brfhsm)
4730+{
4731+ mutex_init(&brfhsm->bf_lock);
4732+ brfhsm->bf_jiffy = 0;
4733+ brfhsm->bf_readable = 0;
4734+}
4735+
4736+static inline void au_br_fhsm_fin(struct au_br_fhsm *brfhsm)
4737+{
4738+ mutex_destroy(&brfhsm->bf_lock);
4739+}
4740+#else
4741+AuStubVoid(au_br_fhsm_init, struct au_br_fhsm *brfhsm)
4742+AuStubVoid(au_br_fhsm_fin, struct au_br_fhsm *brfhsm)
4743+#endif
4744+
1facf9fc 4745+#endif /* __KERNEL__ */
4746+#endif /* __AUFS_BRANCH_H__ */
7f207e10 4747diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
eca34b5c 4748--- /usr/share/empty/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 4749+++ linux/fs/aufs/conf.mk 2021-05-02 20:15:14.670004120 +0200
2121bcd9
AM
4750@@ -0,0 +1,40 @@
4751+# SPDX-License-Identifier: GPL-2.0
4a4d8108
AM
4752+
4753+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
4754+
4755+define AuConf
4756+ifdef ${1}
4757+AuConfStr += ${1}=${${1}}
4758+endif
4759+endef
4760+
b752ccd1 4761+AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
e49829fe 4762+ SBILIST \
7f207e10 4763+ HNOTIFY HFSNOTIFY \
4a4d8108 4764+ EXPORT INO_T_64 \
c1595e42 4765+ XATTR \
076b876e 4766+ FHSM \
4a4d8108 4767+ RDU \
8b6a4947 4768+ DIRREN \
4a4d8108
AM
4769+ SHWH \
4770+ BR_RAMFS \
4771+ BR_FUSE POLL \
4772+ BR_HFSPLUS \
4773+ BDEV_LOOP \
b752ccd1
AM
4774+ DEBUG MAGIC_SYSRQ
4775+$(foreach i, ${AuConfAll}, \
4a4d8108
AM
4776+ $(eval $(call AuConf,CONFIG_AUFS_${i})))
4777+
4778+AuConfName = ${obj}/conf.str
4779+${AuConfName}.tmp: FORCE
4780+ @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
4781+${AuConfName}: ${AuConfName}.tmp
4782+ @diff -q $< $@ > /dev/null 2>&1 || { \
4783+ echo ' GEN ' $@; \
4784+ cp -p $< $@; \
4785+ }
4786+FORCE:
4787+clean-files += ${AuConfName} ${AuConfName}.tmp
4788+${obj}/sysfs.o: ${AuConfName}
b752ccd1
AM
4789+
4790+-include ${srctree}/${src}/conf_priv.mk
7f207e10 4791diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
eca34b5c 4792--- /usr/share/empty/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6
JR
4793+++ linux/fs/aufs/cpup.c 2021-05-02 20:15:14.673337458 +0200
4794@@ -0,0 +1,1457 @@
cd7a4cd9 4795+// SPDX-License-Identifier: GPL-2.0
1facf9fc 4796+/*
d58c55f2 4797+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 4798+ *
4799+ * This program, aufs is free software; you can redistribute it and/or modify
4800+ * it under the terms of the GNU General Public License as published by
4801+ * the Free Software Foundation; either version 2 of the License, or
4802+ * (at your option) any later version.
dece6358
AM
4803+ *
4804+ * This program is distributed in the hope that it will be useful,
4805+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4806+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4807+ * GNU General Public License for more details.
4808+ *
4809+ * You should have received a copy of the GNU General Public License
523b37e3 4810+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 4811+ */
4812+
4813+/*
4814+ * copy-up functions, see wbr_policy.c for copy-down
4815+ */
4816+
4817+#include <linux/fs_stack.h>
dece6358 4818+#include <linux/mm.h>
8cdd5066 4819+#include <linux/task_work.h>
1facf9fc 4820+#include "aufs.h"
4821+
86dc4139 4822+void au_cpup_attr_flags(struct inode *dst, unsigned int iflags)
1facf9fc 4823+{
4824+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
367653fa 4825+ | S_NOATIME | S_NOCMTIME | S_AUTOMOUNT;
1facf9fc 4826+
86dc4139
AM
4827+ BUILD_BUG_ON(sizeof(iflags) != sizeof(dst->i_flags));
4828+
4829+ dst->i_flags |= iflags & ~mask;
1facf9fc 4830+ if (au_test_fs_notime(dst->i_sb))
4831+ dst->i_flags |= S_NOATIME | S_NOCMTIME;
4832+}
4833+
4834+void au_cpup_attr_timesizes(struct inode *inode)
4835+{
4836+ struct inode *h_inode;
4837+
5afbbe0d 4838+ h_inode = au_h_iptr(inode, au_ibtop(inode));
1facf9fc 4839+ fsstack_copy_attr_times(inode, h_inode);
4a4d8108 4840+ fsstack_copy_inode_size(inode, h_inode);
1facf9fc 4841+}
4842+
4843+void au_cpup_attr_nlink(struct inode *inode, int force)
4844+{
4845+ struct inode *h_inode;
4846+ struct super_block *sb;
5afbbe0d 4847+ aufs_bindex_t bindex, bbot;
1facf9fc 4848+
4849+ sb = inode->i_sb;
5afbbe0d 4850+ bindex = au_ibtop(inode);
1facf9fc 4851+ h_inode = au_h_iptr(inode, bindex);
4852+ if (!force
4853+ && !S_ISDIR(h_inode->i_mode)
4854+ && au_opt_test(au_mntflags(sb), PLINK)
4855+ && au_plink_test(inode))
4856+ return;
4857+
7eafdf33
AM
4858+ /*
4859+ * 0 can happen in revalidating.
38d290e6
JR
4860+ * h_inode->i_mutex may not be held here, but it is harmless since once
4861+ * i_nlink reaches 0, it will never become positive except O_TMPFILE
4862+ * case.
4863+ * todo: O_TMPFILE+linkat(AT_SYMLINK_FOLLOW) bypassing aufs may cause
4864+ * the incorrect link count.
7eafdf33 4865+ */
92d182d2 4866+ set_nlink(inode, h_inode->i_nlink);
1facf9fc 4867+
4868+ /*
4869+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
4870+ * it may includes whplink directory.
4871+ */
4872+ if (S_ISDIR(h_inode->i_mode)) {
5afbbe0d
AM
4873+ bbot = au_ibbot(inode);
4874+ for (bindex++; bindex <= bbot; bindex++) {
1facf9fc 4875+ h_inode = au_h_iptr(inode, bindex);
4876+ if (h_inode)
4877+ au_add_nlink(inode, h_inode);
4878+ }
4879+ }
4880+}
4881+
4882+void au_cpup_attr_changeable(struct inode *inode)
4883+{
4884+ struct inode *h_inode;
4885+
5afbbe0d 4886+ h_inode = au_h_iptr(inode, au_ibtop(inode));
1facf9fc 4887+ inode->i_mode = h_inode->i_mode;
4888+ inode->i_uid = h_inode->i_uid;
4889+ inode->i_gid = h_inode->i_gid;
4890+ au_cpup_attr_timesizes(inode);
86dc4139 4891+ au_cpup_attr_flags(inode, h_inode->i_flags);
1facf9fc 4892+}
4893+
4894+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
4895+{
4896+ struct au_iinfo *iinfo = au_ii(inode);
4897+
1308ab2a 4898+ IiMustWriteLock(inode);
4899+
1facf9fc 4900+ iinfo->ii_higen = h_inode->i_generation;
4901+ iinfo->ii_hsb1 = h_inode->i_sb;
4902+}
4903+
4904+void au_cpup_attr_all(struct inode *inode, int force)
4905+{
4906+ struct inode *h_inode;
4907+
5afbbe0d 4908+ h_inode = au_h_iptr(inode, au_ibtop(inode));
1facf9fc 4909+ au_cpup_attr_changeable(inode);
4910+ if (inode->i_nlink > 0)
4911+ au_cpup_attr_nlink(inode, force);
4912+ inode->i_rdev = h_inode->i_rdev;
4913+ inode->i_blkbits = h_inode->i_blkbits;
4914+ au_cpup_igen(inode, h_inode);
4915+}
4916+
4917+/* ---------------------------------------------------------------------- */
4918+
4919+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
4920+
4921+/* keep the timestamps of the parent dir when cpup */
4922+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
4923+ struct path *h_path)
4924+{
4925+ struct inode *h_inode;
4926+
4927+ dt->dt_dentry = dentry;
4928+ dt->dt_h_path = *h_path;
5527c038 4929+ h_inode = d_inode(h_path->dentry);
1facf9fc 4930+ dt->dt_atime = h_inode->i_atime;
4931+ dt->dt_mtime = h_inode->i_mtime;
4932+ /* smp_mb(); */
4933+}
4934+
4935+void au_dtime_revert(struct au_dtime *dt)
4936+{
4937+ struct iattr attr;
4938+ int err;
4939+
4940+ attr.ia_atime = dt->dt_atime;
4941+ attr.ia_mtime = dt->dt_mtime;
4942+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
4943+ | ATTR_ATIME | ATTR_ATIME_SET;
4944+
523b37e3
AM
4945+ /* no delegation since this is a directory */
4946+ err = vfsub_notify_change(&dt->dt_h_path, &attr, /*delegated*/NULL);
1facf9fc 4947+ if (unlikely(err))
0c3ec466 4948+ pr_warn("restoring timestamps failed(%d). ignored\n", err);
1facf9fc 4949+}
4950+
4951+/* ---------------------------------------------------------------------- */
4952+
86dc4139
AM
4953+/* internal use only */
4954+struct au_cpup_reg_attr {
4955+ int valid;
4956+ struct kstat st;
4957+ unsigned int iflags; /* inode->i_flags */
4958+};
4959+
1facf9fc 4960+static noinline_for_stack
0b2a12c6 4961+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct path *h_src,
86dc4139 4962+ struct au_cpup_reg_attr *h_src_attr)
1facf9fc 4963+{
c1595e42 4964+ int err, sbits, icex;
7e9cd9fe
AM
4965+ unsigned int mnt_flags;
4966+ unsigned char verbose;
1facf9fc 4967+ struct iattr ia;
4968+ struct path h_path;
1308ab2a 4969+ struct inode *h_isrc, *h_idst;
86dc4139 4970+ struct kstat *h_st;
c1595e42 4971+ struct au_branch *br;
1facf9fc 4972+
c1595e42
JR
4973+ br = au_sbr(dst->d_sb, bindex);
4974+ h_path.mnt = au_br_mnt(br);
0b2a12c6
JR
4975+ h_path.dentry = au_h_dptr(dst, bindex);
4976+ h_idst = d_inode(h_path.dentry);
4977+ h_isrc = d_inode(h_src->dentry);
1308ab2a 4978+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
1facf9fc 4979+ | ATTR_ATIME | ATTR_MTIME
4980+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
86dc4139
AM
4981+ if (h_src_attr && h_src_attr->valid) {
4982+ h_st = &h_src_attr->st;
4983+ ia.ia_uid = h_st->uid;
4984+ ia.ia_gid = h_st->gid;
4985+ ia.ia_atime = h_st->atime;
4986+ ia.ia_mtime = h_st->mtime;
4987+ if (h_idst->i_mode != h_st->mode
4988+ && !S_ISLNK(h_idst->i_mode)) {
4989+ ia.ia_valid |= ATTR_MODE;
4990+ ia.ia_mode = h_st->mode;
4991+ }
4992+ sbits = !!(h_st->mode & (S_ISUID | S_ISGID));
4993+ au_cpup_attr_flags(h_idst, h_src_attr->iflags);
4994+ } else {
4995+ ia.ia_uid = h_isrc->i_uid;
4996+ ia.ia_gid = h_isrc->i_gid;
4997+ ia.ia_atime = h_isrc->i_atime;
4998+ ia.ia_mtime = h_isrc->i_mtime;
4999+ if (h_idst->i_mode != h_isrc->i_mode
5000+ && !S_ISLNK(h_idst->i_mode)) {
5001+ ia.ia_valid |= ATTR_MODE;
5002+ ia.ia_mode = h_isrc->i_mode;
5003+ }
5004+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
5005+ au_cpup_attr_flags(h_idst, h_isrc->i_flags);
1308ab2a 5006+ }
523b37e3
AM
5007+ /* no delegation since it is just created */
5008+ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL);
1facf9fc 5009+
5010+ /* is this nfs only? */
5011+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
5012+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
5013+ ia.ia_mode = h_isrc->i_mode;
523b37e3 5014+ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL);
1facf9fc 5015+ }
5016+
c1595e42 5017+ icex = br->br_perm & AuBrAttr_ICEX;
7e9cd9fe
AM
5018+ if (!err) {
5019+ mnt_flags = au_mntflags(dst->d_sb);
5020+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
0b2a12c6 5021+ err = au_cpup_xattr(&h_path, h_src, icex, verbose);
7e9cd9fe 5022+ }
c1595e42 5023+
1facf9fc 5024+ return err;
5025+}
5026+
5027+/* ---------------------------------------------------------------------- */
5028+
5029+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
5030+ char *buf, unsigned long blksize)
5031+{
5032+ int err;
5033+ size_t sz, rbytes, wbytes;
5034+ unsigned char all_zero;
5035+ char *p, *zp;
febd17d6 5036+ struct inode *h_inode;
1facf9fc 5037+ /* reduce stack usage */
5038+ struct iattr *ia;
5039+
5040+ zp = page_address(ZERO_PAGE(0));
5041+ if (unlikely(!zp))
5042+ return -ENOMEM; /* possible? */
5043+
5044+ err = 0;
5045+ all_zero = 0;
5046+ while (len) {
5047+ AuDbg("len %lld\n", len);
5048+ sz = blksize;
5049+ if (len < blksize)
5050+ sz = len;
5051+
5052+ rbytes = 0;
5053+ /* todo: signal_pending? */
5054+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
5055+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
5056+ err = rbytes;
5057+ }
5058+ if (unlikely(err < 0))
5059+ break;
5060+
5061+ all_zero = 0;
5062+ if (len >= rbytes && rbytes == blksize)
5063+ all_zero = !memcmp(buf, zp, rbytes);
5064+ if (!all_zero) {
5065+ wbytes = rbytes;
5066+ p = buf;
5067+ while (wbytes) {
5068+ size_t b;
5069+
5070+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
5071+ err = b;
5072+ /* todo: signal_pending? */
5073+ if (unlikely(err == -EAGAIN || err == -EINTR))
5074+ continue;
5075+ if (unlikely(err < 0))
5076+ break;
5077+ wbytes -= b;
5078+ p += b;
5079+ }
392086de
AM
5080+ if (unlikely(err < 0))
5081+ break;
1facf9fc 5082+ } else {
5083+ loff_t res;
5084+
5085+ AuLabel(hole);
5086+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
5087+ err = res;
5088+ if (unlikely(res < 0))
5089+ break;
5090+ }
5091+ len -= rbytes;
5092+ err = 0;
5093+ }
5094+
5095+ /* the last block may be a hole */
5096+ if (!err && all_zero) {
5097+ AuLabel(last hole);
5098+
5099+ err = 1;
2000de60 5100+ if (au_test_nfs(dst->f_path.dentry->d_sb)) {
1facf9fc 5101+ /* nfs requires this step to make last hole */
5102+ /* is this only nfs? */
5103+ do {
5104+ /* todo: signal_pending? */
5105+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
5106+ } while (err == -EAGAIN || err == -EINTR);
5107+ if (err == 1)
5108+ dst->f_pos--;
5109+ }
5110+
5111+ if (err == 1) {
5112+ ia = (void *)buf;
5113+ ia->ia_size = dst->f_pos;
5114+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
5115+ ia->ia_file = dst;
febd17d6
JR
5116+ h_inode = file_inode(dst);
5117+ inode_lock_nested(h_inode, AuLsc_I_CHILD2);
523b37e3
AM
5118+ /* no delegation since it is just created */
5119+ err = vfsub_notify_change(&dst->f_path, ia,
5120+ /*delegated*/NULL);
febd17d6 5121+ inode_unlock(h_inode);
1facf9fc 5122+ }
5123+ }
5124+
5125+ return err;
5126+}
5127+
5128+int au_copy_file(struct file *dst, struct file *src, loff_t len)
5129+{
5130+ int err;
5131+ unsigned long blksize;
5132+ unsigned char do_kfree;
5133+ char *buf;
9f237c51 5134+ struct super_block *h_sb;
1facf9fc 5135+
5136+ err = -ENOMEM;
9f237c51
AM
5137+ h_sb = file_inode(dst)->i_sb;
5138+ blksize = h_sb->s_blocksize;
1facf9fc 5139+ if (!blksize || PAGE_SIZE < blksize)
5140+ blksize = PAGE_SIZE;
5141+ AuDbg("blksize %lu\n", blksize);
5142+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
5143+ if (do_kfree)
5144+ buf = kmalloc(blksize, GFP_NOFS);
5145+ else
5146+ buf = (void *)__get_free_page(GFP_NOFS);
5147+ if (unlikely(!buf))
5148+ goto out;
5149+
5150+ if (len > (1 << 22))
5151+ AuDbg("copying a large file %lld\n", (long long)len);
5152+
5153+ src->f_pos = 0;
5154+ dst->f_pos = 0;
5155+ err = au_do_copy_file(dst, src, len, buf, blksize);
9f237c51
AM
5156+ if (do_kfree) {
5157+ AuDebugOn(!au_kfree_do_sz_test(blksize));
5158+ au_kfree_do_rcu(buf);
5159+ } else
1c60b727 5160+ free_page((unsigned long)buf);
1facf9fc 5161+
4f0767ce 5162+out:
1facf9fc 5163+ return err;
5164+}
5165+
1c60b727
AM
5166+static int au_do_copy(struct file *dst, struct file *src, loff_t len)
5167+{
5168+ int err;
5169+ struct super_block *h_src_sb;
5170+ struct inode *h_src_inode;
5171+
5172+ h_src_inode = file_inode(src);
5173+ h_src_sb = h_src_inode->i_sb;
5174+
5175+ /* XFS acquires inode_lock */
5176+ if (!au_test_xfs(h_src_sb))
5177+ err = au_copy_file(dst, src, len);
5178+ else {
3c1bdaff 5179+ inode_unlock_shared(h_src_inode);
1c60b727 5180+ err = au_copy_file(dst, src, len);
be118d29 5181+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
1c60b727
AM
5182+ }
5183+
5184+ return err;
5185+}
5186+
5187+static int au_clone_or_copy(struct file *dst, struct file *src, loff_t len)
5188+{
5189+ int err;
9f237c51 5190+ loff_t lo;
1c60b727
AM
5191+ struct super_block *h_src_sb;
5192+ struct inode *h_src_inode;
5193+
5194+ h_src_inode = file_inode(src);
5195+ h_src_sb = h_src_inode->i_sb;
5196+ if (h_src_sb != file_inode(dst)->i_sb
9f237c51 5197+ || !dst->f_op->remap_file_range) {
1c60b727
AM
5198+ err = au_do_copy(dst, src, len);
5199+ goto out;
5200+ }
5201+
5202+ if (!au_test_nfs(h_src_sb)) {
3c1bdaff 5203+ inode_unlock_shared(h_src_inode);
9f237c51 5204+ lo = vfsub_clone_file_range(src, dst, len);
be118d29 5205+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
1c60b727 5206+ } else
9f237c51
AM
5207+ lo = vfsub_clone_file_range(src, dst, len);
5208+ if (lo == len) {
5209+ err = 0;
5210+ goto out; /* success */
5211+ } else if (lo >= 0)
5212+ /* todo: possible? */
5213+ /* paritially succeeded */
5214+ AuDbg("lo %lld, len %lld. Retrying.\n", lo, len);
5215+ else if (lo != -EOPNOTSUPP) {
5216+ /* older XFS has a condition in cloning */
5217+ err = lo;
1c60b727 5218+ goto out;
9f237c51 5219+ }
1c60b727
AM
5220+
5221+ /* the backend fs on NFS may not support cloning */
5222+ err = au_do_copy(dst, src, len);
5223+
5224+out:
5225+ AuTraceErr(err);
5226+ return err;
5227+}
5228+
1facf9fc 5229+/*
5230+ * to support a sparse file which is opened with O_APPEND,
5231+ * we need to close the file.
5232+ */
c2b27bf2 5233+static int au_cp_regular(struct au_cp_generic *cpg)
1facf9fc 5234+{
5235+ int err, i;
5236+ enum { SRC, DST };
5237+ struct {
5238+ aufs_bindex_t bindex;
5239+ unsigned int flags;
5240+ struct dentry *dentry;
392086de 5241+ int force_wr;
1facf9fc 5242+ struct file *file;
1facf9fc 5243+ } *f, file[] = {
5244+ {
c2b27bf2 5245+ .bindex = cpg->bsrc,
1facf9fc 5246+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
1facf9fc 5247+ },
5248+ {
c2b27bf2 5249+ .bindex = cpg->bdst,
1facf9fc 5250+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
392086de 5251+ .force_wr = !!au_ftest_cpup(cpg->flags, RWDST),
1facf9fc 5252+ }
5253+ };
acd2b654 5254+ struct au_branch *br;
521ced18 5255+ struct super_block *sb, *h_src_sb;
e2f27e51 5256+ struct inode *h_src_inode;
8cdd5066 5257+ struct task_struct *tsk = current;
1facf9fc 5258+
5259+ /* bsrc branch can be ro/rw. */
c2b27bf2 5260+ sb = cpg->dentry->d_sb;
1facf9fc 5261+ f = file;
5262+ for (i = 0; i < 2; i++, f++) {
c2b27bf2
AM
5263+ f->dentry = au_h_dptr(cpg->dentry, f->bindex);
5264+ f->file = au_h_open(cpg->dentry, f->bindex, f->flags,
392086de 5265+ /*file*/NULL, f->force_wr);
9f237c51
AM
5266+ if (IS_ERR(f->file)) {
5267+ err = PTR_ERR(f->file);
5268+ if (i == SRC)
5269+ goto out;
5270+ else
5271+ goto out_src;
5272+ }
1facf9fc 5273+ }
5274+
5275+ /* try stopping to update while we copyup */
e2f27e51 5276+ h_src_inode = d_inode(file[SRC].dentry);
521ced18
JR
5277+ h_src_sb = h_src_inode->i_sb;
5278+ if (!au_test_nfs(h_src_sb))
e2f27e51 5279+ IMustLock(h_src_inode);
1c60b727 5280+ err = au_clone_or_copy(file[DST].file, file[SRC].file, cpg->len);
1facf9fc 5281+
8cdd5066
JR
5282+ /* i wonder if we had O_NO_DELAY_FPUT flag */
5283+ if (tsk->flags & PF_KTHREAD)
5284+ __fput_sync(file[DST].file);
5285+ else {
062440b3 5286+ /* it happened actually */
8cdd5066
JR
5287+ fput(file[DST].file);
5288+ /*
5289+ * too bad.
5290+ * we have to call both since we don't know which place the file
5291+ * was added to.
5292+ */
5293+ task_work_run();
5294+ flush_delayed_fput();
5295+ }
acd2b654
AM
5296+ br = au_sbr(sb, file[DST].bindex);
5297+ au_lcnt_dec(&br->br_nfiles);
523b37e3 5298+
4f0767ce 5299+out_src:
1facf9fc 5300+ fput(file[SRC].file);
acd2b654
AM
5301+ br = au_sbr(sb, file[SRC].bindex);
5302+ au_lcnt_dec(&br->br_nfiles);
4f0767ce 5303+out:
1facf9fc 5304+ return err;
5305+}
5306+
c2b27bf2 5307+static int au_do_cpup_regular(struct au_cp_generic *cpg,
86dc4139 5308+ struct au_cpup_reg_attr *h_src_attr)
1facf9fc 5309+{
5310+ int err, rerr;
5311+ loff_t l;
86dc4139 5312+ struct path h_path;
38d290e6 5313+ struct inode *h_src_inode, *h_dst_inode;
1facf9fc 5314+
5315+ err = 0;
5527c038 5316+ h_src_inode = au_h_iptr(d_inode(cpg->dentry), cpg->bsrc);
86dc4139 5317+ l = i_size_read(h_src_inode);
c2b27bf2
AM
5318+ if (cpg->len == -1 || l < cpg->len)
5319+ cpg->len = l;
5320+ if (cpg->len) {
86dc4139 5321+ /* try stopping to update while we are referencing */
be118d29 5322+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
c2b27bf2 5323+ au_pin_hdir_unlock(cpg->pin);
1facf9fc 5324+
c2b27bf2
AM
5325+ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bsrc);
5326+ h_path.mnt = au_sbr_mnt(cpg->dentry->d_sb, cpg->bsrc);
86dc4139 5327+ h_src_attr->iflags = h_src_inode->i_flags;
5527c038 5328+ if (!au_test_nfs(h_src_inode->i_sb))
521ced18 5329+ err = vfsub_getattr(&h_path, &h_src_attr->st);
5527c038 5330+ else {
3c1bdaff 5331+ inode_unlock_shared(h_src_inode);
521ced18 5332+ err = vfsub_getattr(&h_path, &h_src_attr->st);
be118d29 5333+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
5527c038 5334+ }
86dc4139 5335+ if (unlikely(err)) {
3c1bdaff 5336+ inode_unlock_shared(h_src_inode);
86dc4139
AM
5337+ goto out;
5338+ }
5339+ h_src_attr->valid = 1;
e2f27e51
AM
5340+ if (!au_test_nfs(h_src_inode->i_sb)) {
5341+ err = au_cp_regular(cpg);
3c1bdaff 5342+ inode_unlock_shared(h_src_inode);
e2f27e51 5343+ } else {
3c1bdaff 5344+ inode_unlock_shared(h_src_inode);
e2f27e51
AM
5345+ err = au_cp_regular(cpg);
5346+ }
c2b27bf2 5347+ rerr = au_pin_hdir_relock(cpg->pin);
86dc4139
AM
5348+ if (!err && rerr)
5349+ err = rerr;
1facf9fc 5350+ }
38d290e6
JR
5351+ if (!err && (h_src_inode->i_state & I_LINKABLE)) {
5352+ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bdst);
5527c038 5353+ h_dst_inode = d_inode(h_path.dentry);
38d290e6
JR
5354+ spin_lock(&h_dst_inode->i_lock);
5355+ h_dst_inode->i_state |= I_LINKABLE;
5356+ spin_unlock(&h_dst_inode->i_lock);
5357+ }
1facf9fc 5358+
4f0767ce 5359+out:
1facf9fc 5360+ return err;
5361+}
5362+
5363+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
5364+ struct inode *h_dir)
5365+{
e37dd06a
AM
5366+ int err;
5367+ DEFINE_DELAYED_CALL(done);
5368+ const char *sym;
1facf9fc 5369+
e37dd06a
AM
5370+ sym = vfs_get_link(h_src, &done);
5371+ err = PTR_ERR(sym);
5372+ if (IS_ERR(sym))
1facf9fc 5373+ goto out;
5374+
e37dd06a 5375+ err = vfsub_symlink(h_dir, h_path, sym);
1facf9fc 5376+
4f0767ce 5377+out:
e37dd06a 5378+ do_delayed_call(&done);
1facf9fc 5379+ return err;
5380+}
5381+
8cdd5066
JR
5382+/*
5383+ * regardless 'acl' option, reset all ACL.
5384+ * All ACL will be copied up later from the original entry on the lower branch.
5385+ */
5386+static int au_reset_acl(struct inode *h_dir, struct path *h_path, umode_t mode)
5387+{
5388+ int err;
5389+ struct dentry *h_dentry;
5390+ struct inode *h_inode;
0b2a12c6 5391+ struct user_namespace *h_userns;
8cdd5066 5392+
0b2a12c6 5393+ h_userns = mnt_user_ns(h_path->mnt);
8cdd5066
JR
5394+ h_dentry = h_path->dentry;
5395+ h_inode = d_inode(h_dentry);
5396+ /* forget_all_cached_acls(h_inode)); */
0b2a12c6 5397+ err = vfsub_removexattr(h_userns, h_dentry, XATTR_NAME_POSIX_ACL_ACCESS);
8cdd5066
JR
5398+ AuTraceErr(err);
5399+ if (err == -EOPNOTSUPP)
5400+ err = 0;
5401+ if (!err)
0b2a12c6 5402+ err = vfsub_acl_chmod(h_userns, h_inode, mode);
8cdd5066
JR
5403+
5404+ AuTraceErr(err);
5405+ return err;
5406+}
5407+
5408+static int au_do_cpup_dir(struct au_cp_generic *cpg, struct dentry *dst_parent,
5409+ struct inode *h_dir, struct path *h_path)
5410+{
5411+ int err;
5412+ struct inode *dir, *inode;
0b2a12c6 5413+ struct user_namespace *h_userns;
8cdd5066 5414+
0b2a12c6
JR
5415+ h_userns = mnt_user_ns(h_path->mnt);
5416+ err = vfsub_removexattr(h_userns, h_path->dentry,
5417+ XATTR_NAME_POSIX_ACL_DEFAULT);
8cdd5066
JR
5418+ AuTraceErr(err);
5419+ if (err == -EOPNOTSUPP)
5420+ err = 0;
5421+ if (unlikely(err))
5422+ goto out;
5423+
5424+ /*
5425+ * strange behaviour from the users view,
acd2b654 5426+ * particularly setattr case
8cdd5066
JR
5427+ */
5428+ dir = d_inode(dst_parent);
5afbbe0d 5429+ if (au_ibtop(dir) == cpg->bdst)
8cdd5066
JR
5430+ au_cpup_attr_nlink(dir, /*force*/1);
5431+ inode = d_inode(cpg->dentry);
5432+ au_cpup_attr_nlink(inode, /*force*/1);
5433+
5434+out:
5435+ return err;
5436+}
5437+
1facf9fc 5438+static noinline_for_stack
c2b27bf2 5439+int cpup_entry(struct au_cp_generic *cpg, struct dentry *dst_parent,
86dc4139 5440+ struct au_cpup_reg_attr *h_src_attr)
1facf9fc 5441+{
5442+ int err;
5443+ umode_t mode;
5444+ unsigned int mnt_flags;
076b876e 5445+ unsigned char isdir, isreg, force;
c2b27bf2 5446+ const unsigned char do_dt = !!au_ftest_cpup(cpg->flags, DTIME);
1facf9fc 5447+ struct au_dtime dt;
5448+ struct path h_path;
5449+ struct dentry *h_src, *h_dst, *h_parent;
8cdd5066 5450+ struct inode *h_inode, *h_dir;
1facf9fc 5451+ struct super_block *sb;
5452+
5453+ /* bsrc branch can be ro/rw. */
c2b27bf2 5454+ h_src = au_h_dptr(cpg->dentry, cpg->bsrc);
5527c038
JR
5455+ h_inode = d_inode(h_src);
5456+ AuDebugOn(h_inode != au_h_iptr(d_inode(cpg->dentry), cpg->bsrc));
1facf9fc 5457+
5458+ /* try stopping to be referenced while we are creating */
c2b27bf2
AM
5459+ h_dst = au_h_dptr(cpg->dentry, cpg->bdst);
5460+ if (au_ftest_cpup(cpg->flags, RENAME))
86dc4139
AM
5461+ AuDebugOn(strncmp(h_dst->d_name.name, AUFS_WH_PFX,
5462+ AUFS_WH_PFX_LEN));
1facf9fc 5463+ h_parent = h_dst->d_parent; /* dir inode is locked */
5527c038 5464+ h_dir = d_inode(h_parent);
1facf9fc 5465+ IMustLock(h_dir);
5466+ AuDebugOn(h_parent != h_dst->d_parent);
5467+
c2b27bf2
AM
5468+ sb = cpg->dentry->d_sb;
5469+ h_path.mnt = au_sbr_mnt(sb, cpg->bdst);
1facf9fc 5470+ if (do_dt) {
5471+ h_path.dentry = h_parent;
5472+ au_dtime_store(&dt, dst_parent, &h_path);
5473+ }
5474+ h_path.dentry = h_dst;
5475+
076b876e 5476+ isreg = 0;
1facf9fc 5477+ isdir = 0;
5478+ mode = h_inode->i_mode;
5479+ switch (mode & S_IFMT) {
5480+ case S_IFREG:
076b876e 5481+ isreg = 1;
cd7a4cd9 5482+ err = vfsub_create(h_dir, &h_path, 0600, /*want_excl*/true);
1facf9fc 5483+ if (!err)
c2b27bf2 5484+ err = au_do_cpup_regular(cpg, h_src_attr);
1facf9fc 5485+ break;
5486+ case S_IFDIR:
5487+ isdir = 1;
5488+ err = vfsub_mkdir(h_dir, &h_path, mode);
8cdd5066
JR
5489+ if (!err)
5490+ err = au_do_cpup_dir(cpg, dst_parent, h_dir, &h_path);
1facf9fc 5491+ break;
5492+ case S_IFLNK:
5493+ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
5494+ break;
5495+ case S_IFCHR:
5496+ case S_IFBLK:
5497+ AuDebugOn(!capable(CAP_MKNOD));
42a736d3 5498+ fallthrough;
1facf9fc 5499+ case S_IFIFO:
5500+ case S_IFSOCK:
5501+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
5502+ break;
5503+ default:
5504+ AuIOErr("Unknown inode type 0%o\n", mode);
5505+ err = -EIO;
5506+ }
8cdd5066
JR
5507+ if (!err)
5508+ err = au_reset_acl(h_dir, &h_path, mode);
1facf9fc 5509+
5510+ mnt_flags = au_mntflags(sb);
5511+ if (!au_opt_test(mnt_flags, UDBA_NONE)
5512+ && !isdir
5513+ && au_opt_test(mnt_flags, XINO)
38d290e6
JR
5514+ && (h_inode->i_nlink == 1
5515+ || (h_inode->i_state & I_LINKABLE))
1facf9fc 5516+ /* todo: unnecessary? */
5527c038 5517+ /* && d_inode(cpg->dentry)->i_nlink == 1 */
c2b27bf2
AM
5518+ && cpg->bdst < cpg->bsrc
5519+ && !au_ftest_cpup(cpg->flags, KEEPLINO))
5520+ au_xino_write(sb, cpg->bsrc, h_inode->i_ino, /*ino*/0);
1facf9fc 5521+ /* ignore this error */
5522+
076b876e
AM
5523+ if (!err) {
5524+ force = 0;
5525+ if (isreg) {
5526+ force = !!cpg->len;
5527+ if (cpg->len == -1)
5528+ force = !!i_size_read(h_inode);
5529+ }
5530+ au_fhsm_wrote(sb, cpg->bdst, force);
5531+ }
5532+
1facf9fc 5533+ if (do_dt)
5534+ au_dtime_revert(&dt);
5535+ return err;
5536+}
5537+
392086de 5538+static int au_do_ren_after_cpup(struct au_cp_generic *cpg, struct path *h_path)
86dc4139
AM
5539+{
5540+ int err;
392086de 5541+ struct dentry *dentry, *h_dentry, *h_parent, *parent;
86dc4139 5542+ struct inode *h_dir;
392086de 5543+ aufs_bindex_t bdst;
86dc4139 5544+
392086de
AM
5545+ dentry = cpg->dentry;
5546+ bdst = cpg->bdst;
5547+ h_dentry = au_h_dptr(dentry, bdst);
5548+ if (!au_ftest_cpup(cpg->flags, OVERWRITE)) {
5549+ dget(h_dentry);
5550+ au_set_h_dptr(dentry, bdst, NULL);
5551+ err = au_lkup_neg(dentry, bdst, /*wh*/0);
5552+ if (!err)
5553+ h_path->dentry = dget(au_h_dptr(dentry, bdst));
86dc4139 5554+ au_set_h_dptr(dentry, bdst, h_dentry);
392086de
AM
5555+ } else {
5556+ err = 0;
5557+ parent = dget_parent(dentry);
5558+ h_parent = au_h_dptr(parent, bdst);
5559+ dput(parent);
5560+ h_path->dentry = vfsub_lkup_one(&dentry->d_name, h_parent);
5561+ if (IS_ERR(h_path->dentry))
5562+ err = PTR_ERR(h_path->dentry);
86dc4139 5563+ }
392086de
AM
5564+ if (unlikely(err))
5565+ goto out;
86dc4139 5566+
86dc4139 5567+ h_parent = h_dentry->d_parent; /* dir inode is locked */
5527c038 5568+ h_dir = d_inode(h_parent);
86dc4139 5569+ IMustLock(h_dir);
523b37e3
AM
5570+ AuDbg("%pd %pd\n", h_dentry, h_path->dentry);
5571+ /* no delegation since it is just created */
f2c43d5f
AM
5572+ err = vfsub_rename(h_dir, h_dentry, h_dir, h_path, /*delegated*/NULL,
5573+ /*flags*/0);
86dc4139
AM
5574+ dput(h_path->dentry);
5575+
5576+out:
5577+ return err;
5578+}
5579+
1facf9fc 5580+/*
5581+ * copyup the @dentry from @bsrc to @bdst.
5582+ * the caller must set the both of lower dentries.
5583+ * @len is for truncating when it is -1 copyup the entire file.
5584+ * in link/rename cases, @dst_parent may be different from the real one.
c2b27bf2 5585+ * basic->bsrc can be larger than basic->bdst.
f2c43d5f 5586+ * aufs doesn't touch the credential so
acd2b654 5587+ * security_inode_copy_up{,_xattr}() are unnecessary.
1facf9fc 5588+ */
c2b27bf2 5589+static int au_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent)
1facf9fc 5590+{
5591+ int err, rerr;
5afbbe0d 5592+ aufs_bindex_t old_ibtop;
1facf9fc 5593+ unsigned char isdir, plink;
1facf9fc 5594+ struct dentry *h_src, *h_dst, *h_parent;
5527c038 5595+ struct inode *dst_inode, *h_dir, *inode, *delegated, *src_inode;
1facf9fc 5596+ struct super_block *sb;
86dc4139 5597+ struct au_branch *br;
0b2a12c6 5598+ struct path h_src_path;
acd2b654 5599+ /* to reduce stack size */
c2b27bf2
AM
5600+ struct {
5601+ struct au_dtime dt;
5602+ struct path h_path;
5603+ struct au_cpup_reg_attr h_src_attr;
5604+ } *a;
1facf9fc 5605+
c2b27bf2
AM
5606+ err = -ENOMEM;
5607+ a = kmalloc(sizeof(*a), GFP_NOFS);
5608+ if (unlikely(!a))
5609+ goto out;
5610+ a->h_src_attr.valid = 0;
1facf9fc 5611+
c2b27bf2
AM
5612+ sb = cpg->dentry->d_sb;
5613+ br = au_sbr(sb, cpg->bdst);
5614+ a->h_path.mnt = au_br_mnt(br);
5615+ h_dst = au_h_dptr(cpg->dentry, cpg->bdst);
1facf9fc 5616+ h_parent = h_dst->d_parent; /* dir inode is locked */
5527c038 5617+ h_dir = d_inode(h_parent);
1facf9fc 5618+ IMustLock(h_dir);
5619+
c2b27bf2 5620+ h_src = au_h_dptr(cpg->dentry, cpg->bsrc);
5527c038 5621+ inode = d_inode(cpg->dentry);
1facf9fc 5622+
5623+ if (!dst_parent)
c2b27bf2 5624+ dst_parent = dget_parent(cpg->dentry);
1facf9fc 5625+ else
5626+ dget(dst_parent);
5627+
5628+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
c2b27bf2 5629+ dst_inode = au_h_iptr(inode, cpg->bdst);
1facf9fc 5630+ if (dst_inode) {
5631+ if (unlikely(!plink)) {
5632+ err = -EIO;
027c5e7a
AM
5633+ AuIOErr("hi%lu(i%lu) exists on b%d "
5634+ "but plink is disabled\n",
c2b27bf2
AM
5635+ dst_inode->i_ino, inode->i_ino, cpg->bdst);
5636+ goto out_parent;
1facf9fc 5637+ }
5638+
5639+ if (dst_inode->i_nlink) {
c2b27bf2 5640+ const int do_dt = au_ftest_cpup(cpg->flags, DTIME);
1facf9fc 5641+
c2b27bf2 5642+ h_src = au_plink_lkup(inode, cpg->bdst);
1facf9fc 5643+ err = PTR_ERR(h_src);
5644+ if (IS_ERR(h_src))
c2b27bf2 5645+ goto out_parent;
5527c038 5646+ if (unlikely(d_is_negative(h_src))) {
1facf9fc 5647+ err = -EIO;
79b8bda9 5648+ AuIOErr("i%lu exists on b%d "
027c5e7a 5649+ "but not pseudo-linked\n",
79b8bda9 5650+ inode->i_ino, cpg->bdst);
1facf9fc 5651+ dput(h_src);
c2b27bf2 5652+ goto out_parent;
1facf9fc 5653+ }
5654+
5655+ if (do_dt) {
c2b27bf2
AM
5656+ a->h_path.dentry = h_parent;
5657+ au_dtime_store(&a->dt, dst_parent, &a->h_path);
1facf9fc 5658+ }
86dc4139 5659+
c2b27bf2 5660+ a->h_path.dentry = h_dst;
523b37e3
AM
5661+ delegated = NULL;
5662+ err = vfsub_link(h_src, h_dir, &a->h_path, &delegated);
c2b27bf2 5663+ if (!err && au_ftest_cpup(cpg->flags, RENAME))
392086de 5664+ err = au_do_ren_after_cpup(cpg, &a->h_path);
1facf9fc 5665+ if (do_dt)
c2b27bf2 5666+ au_dtime_revert(&a->dt);
523b37e3
AM
5667+ if (unlikely(err == -EWOULDBLOCK)) {
5668+ pr_warn("cannot retry for NFSv4 delegation"
5669+ " for an internal link\n");
5670+ iput(delegated);
5671+ }
1facf9fc 5672+ dput(h_src);
c2b27bf2 5673+ goto out_parent;
1facf9fc 5674+ } else
5675+ /* todo: cpup_wh_file? */
5676+ /* udba work */
4a4d8108 5677+ au_update_ibrange(inode, /*do_put_zero*/1);
1facf9fc 5678+ }
5679+
86dc4139 5680+ isdir = S_ISDIR(inode->i_mode);
5afbbe0d 5681+ old_ibtop = au_ibtop(inode);
c2b27bf2 5682+ err = cpup_entry(cpg, dst_parent, &a->h_src_attr);
1facf9fc 5683+ if (unlikely(err))
86dc4139 5684+ goto out_rev;
5527c038 5685+ dst_inode = d_inode(h_dst);
febd17d6 5686+ inode_lock_nested(dst_inode, AuLsc_I_CHILD2);
86dc4139 5687+ /* todo: necessary? */
c2b27bf2 5688+ /* au_pin_hdir_unlock(cpg->pin); */
1facf9fc 5689+
0b2a12c6
JR
5690+ h_src_path.dentry = h_src;
5691+ h_src_path.mnt = au_sbr_mnt(sb, cpg->bsrc);
5692+ err = cpup_iattr(cpg->dentry, cpg->bdst, &h_src_path, &a->h_src_attr);
86dc4139
AM
5693+ if (unlikely(err)) {
5694+ /* todo: necessary? */
c2b27bf2 5695+ /* au_pin_hdir_relock(cpg->pin); */ /* ignore an error */
febd17d6 5696+ inode_unlock(dst_inode);
86dc4139
AM
5697+ goto out_rev;
5698+ }
5699+
5afbbe0d 5700+ if (cpg->bdst < old_ibtop) {
86dc4139 5701+ if (S_ISREG(inode->i_mode)) {
c2b27bf2 5702+ err = au_dy_iaop(inode, cpg->bdst, dst_inode);
86dc4139 5703+ if (unlikely(err)) {
c2b27bf2
AM
5704+ /* ignore an error */
5705+ /* au_pin_hdir_relock(cpg->pin); */
febd17d6 5706+ inode_unlock(dst_inode);
86dc4139 5707+ goto out_rev;
4a4d8108 5708+ }
4a4d8108 5709+ }
5afbbe0d 5710+ au_set_ibtop(inode, cpg->bdst);
c2b27bf2 5711+ } else
5afbbe0d 5712+ au_set_ibbot(inode, cpg->bdst);
c2b27bf2 5713+ au_set_h_iptr(inode, cpg->bdst, au_igrab(dst_inode),
86dc4139
AM
5714+ au_hi_flags(inode, isdir));
5715+
5716+ /* todo: necessary? */
c2b27bf2 5717+ /* err = au_pin_hdir_relock(cpg->pin); */
febd17d6 5718+ inode_unlock(dst_inode);
86dc4139
AM
5719+ if (unlikely(err))
5720+ goto out_rev;
5721+
5527c038 5722+ src_inode = d_inode(h_src);
86dc4139 5723+ if (!isdir
5527c038
JR
5724+ && (src_inode->i_nlink > 1
5725+ || src_inode->i_state & I_LINKABLE)
86dc4139 5726+ && plink)
c2b27bf2 5727+ au_plink_append(inode, cpg->bdst, h_dst);
86dc4139 5728+
c2b27bf2
AM
5729+ if (au_ftest_cpup(cpg->flags, RENAME)) {
5730+ a->h_path.dentry = h_dst;
392086de 5731+ err = au_do_ren_after_cpup(cpg, &a->h_path);
86dc4139
AM
5732+ }
5733+ if (!err)
c2b27bf2 5734+ goto out_parent; /* success */
1facf9fc 5735+
5736+ /* revert */
4a4d8108 5737+out_rev:
c2b27bf2
AM
5738+ a->h_path.dentry = h_parent;
5739+ au_dtime_store(&a->dt, dst_parent, &a->h_path);
5740+ a->h_path.dentry = h_dst;
86dc4139 5741+ rerr = 0;
5527c038 5742+ if (d_is_positive(h_dst)) {
523b37e3
AM
5743+ if (!isdir) {
5744+ /* no delegation since it is just created */
5745+ rerr = vfsub_unlink(h_dir, &a->h_path,
5746+ /*delegated*/NULL, /*force*/0);
5747+ } else
c2b27bf2 5748+ rerr = vfsub_rmdir(h_dir, &a->h_path);
86dc4139 5749+ }
c2b27bf2 5750+ au_dtime_revert(&a->dt);
1facf9fc 5751+ if (rerr) {
5752+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
5753+ err = -EIO;
5754+ }
c2b27bf2 5755+out_parent:
1facf9fc 5756+ dput(dst_parent);
9f237c51 5757+ au_kfree_rcu(a);
c2b27bf2 5758+out:
1facf9fc 5759+ return err;
5760+}
5761+
7e9cd9fe 5762+#if 0 /* reserved */
1facf9fc 5763+struct au_cpup_single_args {
5764+ int *errp;
c2b27bf2 5765+ struct au_cp_generic *cpg;
1facf9fc 5766+ struct dentry *dst_parent;
5767+};
5768+
5769+static void au_call_cpup_single(void *args)
5770+{
5771+ struct au_cpup_single_args *a = args;
86dc4139 5772+
c2b27bf2
AM
5773+ au_pin_hdir_acquire_nest(a->cpg->pin);
5774+ *a->errp = au_cpup_single(a->cpg, a->dst_parent);
5775+ au_pin_hdir_release(a->cpg->pin);
1facf9fc 5776+}
c2b27bf2 5777+#endif
1facf9fc 5778+
53392da6
AM
5779+/*
5780+ * prevent SIGXFSZ in copy-up.
5781+ * testing CAP_MKNOD is for generic fs,
5782+ * but CAP_FSETID is for xfs only, currently.
5783+ */
86dc4139 5784+static int au_cpup_sio_test(struct au_pin *pin, umode_t mode)
53392da6
AM
5785+{
5786+ int do_sio;
86dc4139
AM
5787+ struct super_block *sb;
5788+ struct inode *h_dir;
53392da6
AM
5789+
5790+ do_sio = 0;
86dc4139 5791+ sb = au_pinned_parent(pin)->d_sb;
53392da6
AM
5792+ if (!au_wkq_test()
5793+ && (!au_sbi(sb)->si_plink_maint_pid
5794+ || au_plink_maint(sb, AuLock_NOPLM))) {
5795+ switch (mode & S_IFMT) {
5796+ case S_IFREG:
5797+ /* no condition about RLIMIT_FSIZE and the file size */
5798+ do_sio = 1;
5799+ break;
5800+ case S_IFCHR:
5801+ case S_IFBLK:
5802+ do_sio = !capable(CAP_MKNOD);
5803+ break;
5804+ }
5805+ if (!do_sio)
5806+ do_sio = ((mode & (S_ISUID | S_ISGID))
5807+ && !capable(CAP_FSETID));
86dc4139
AM
5808+ /* this workaround may be removed in the future */
5809+ if (!do_sio) {
5810+ h_dir = au_pinned_h_dir(pin);
5811+ do_sio = h_dir->i_mode & S_ISVTX;
5812+ }
53392da6
AM
5813+ }
5814+
5815+ return do_sio;
5816+}
5817+
7e9cd9fe 5818+#if 0 /* reserved */
c2b27bf2 5819+int au_sio_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent)
1facf9fc 5820+{
5821+ int err, wkq_err;
1facf9fc 5822+ struct dentry *h_dentry;
5823+
c2b27bf2 5824+ h_dentry = au_h_dptr(cpg->dentry, cpg->bsrc);
5527c038 5825+ if (!au_cpup_sio_test(pin, d_inode(h_dentry)->i_mode))
c2b27bf2 5826+ err = au_cpup_single(cpg, dst_parent);
1facf9fc 5827+ else {
5828+ struct au_cpup_single_args args = {
5829+ .errp = &err,
c2b27bf2
AM
5830+ .cpg = cpg,
5831+ .dst_parent = dst_parent
1facf9fc 5832+ };
5833+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
5834+ if (unlikely(wkq_err))
5835+ err = wkq_err;
5836+ }
5837+
5838+ return err;
5839+}
c2b27bf2 5840+#endif
1facf9fc 5841+
5842+/*
5843+ * copyup the @dentry from the first active lower branch to @bdst,
5844+ * using au_cpup_single().
5845+ */
c2b27bf2 5846+static int au_cpup_simple(struct au_cp_generic *cpg)
1facf9fc 5847+{
5848+ int err;
c2b27bf2
AM
5849+ unsigned int flags_orig;
5850+ struct dentry *dentry;
5851+
5852+ AuDebugOn(cpg->bsrc < 0);
1facf9fc 5853+
c2b27bf2 5854+ dentry = cpg->dentry;
86dc4139 5855+ DiMustWriteLock(dentry);
1facf9fc 5856+
c2b27bf2 5857+ err = au_lkup_neg(dentry, cpg->bdst, /*wh*/1);
1facf9fc 5858+ if (!err) {
c2b27bf2
AM
5859+ flags_orig = cpg->flags;
5860+ au_fset_cpup(cpg->flags, RENAME);
5861+ err = au_cpup_single(cpg, NULL);
5862+ cpg->flags = flags_orig;
1facf9fc 5863+ if (!err)
5864+ return 0; /* success */
5865+
5866+ /* revert */
c2b27bf2 5867+ au_set_h_dptr(dentry, cpg->bdst, NULL);
5afbbe0d 5868+ au_set_dbtop(dentry, cpg->bsrc);
1facf9fc 5869+ }
5870+
5871+ return err;
5872+}
5873+
5874+struct au_cpup_simple_args {
5875+ int *errp;
c2b27bf2 5876+ struct au_cp_generic *cpg;
1facf9fc 5877+};
5878+
5879+static void au_call_cpup_simple(void *args)
5880+{
5881+ struct au_cpup_simple_args *a = args;
86dc4139 5882+
c2b27bf2
AM
5883+ au_pin_hdir_acquire_nest(a->cpg->pin);
5884+ *a->errp = au_cpup_simple(a->cpg);
5885+ au_pin_hdir_release(a->cpg->pin);
1facf9fc 5886+}
5887+
c2b27bf2 5888+static int au_do_sio_cpup_simple(struct au_cp_generic *cpg)
1facf9fc 5889+{
5890+ int err, wkq_err;
c2b27bf2
AM
5891+ struct dentry *dentry, *parent;
5892+ struct file *h_file;
1facf9fc 5893+ struct inode *h_dir;
0b2a12c6 5894+ struct user_namespace *h_userns;
1facf9fc 5895+
c2b27bf2
AM
5896+ dentry = cpg->dentry;
5897+ h_file = NULL;
5898+ if (au_ftest_cpup(cpg->flags, HOPEN)) {
5899+ AuDebugOn(cpg->bsrc < 0);
392086de 5900+ h_file = au_h_open_pre(dentry, cpg->bsrc, /*force_wr*/0);
c2b27bf2
AM
5901+ err = PTR_ERR(h_file);
5902+ if (IS_ERR(h_file))
5903+ goto out;
5904+ }
5905+
1facf9fc 5906+ parent = dget_parent(dentry);
5527c038 5907+ h_dir = au_h_iptr(d_inode(parent), cpg->bdst);
0b2a12c6
JR
5908+ h_userns = au_sbr_userns(dentry->d_sb, cpg->bdst);
5909+ if (!au_test_h_perm_sio(h_userns, h_dir, MAY_EXEC | MAY_WRITE)
5527c038 5910+ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode))
c2b27bf2 5911+ err = au_cpup_simple(cpg);
1facf9fc 5912+ else {
5913+ struct au_cpup_simple_args args = {
5914+ .errp = &err,
c2b27bf2 5915+ .cpg = cpg
1facf9fc 5916+ };
5917+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
5918+ if (unlikely(wkq_err))
5919+ err = wkq_err;
5920+ }
5921+
5922+ dput(parent);
c2b27bf2
AM
5923+ if (h_file)
5924+ au_h_open_post(dentry, cpg->bsrc, h_file);
5925+
5926+out:
1facf9fc 5927+ return err;
5928+}
5929+
c2b27bf2 5930+int au_sio_cpup_simple(struct au_cp_generic *cpg)
367653fa 5931+{
5afbbe0d 5932+ aufs_bindex_t bsrc, bbot;
c2b27bf2 5933+ struct dentry *dentry, *h_dentry;
367653fa 5934+
c2b27bf2
AM
5935+ if (cpg->bsrc < 0) {
5936+ dentry = cpg->dentry;
5afbbe0d
AM
5937+ bbot = au_dbbot(dentry);
5938+ for (bsrc = cpg->bdst + 1; bsrc <= bbot; bsrc++) {
c2b27bf2
AM
5939+ h_dentry = au_h_dptr(dentry, bsrc);
5940+ if (h_dentry) {
5527c038 5941+ AuDebugOn(d_is_negative(h_dentry));
c2b27bf2
AM
5942+ break;
5943+ }
5944+ }
5afbbe0d 5945+ AuDebugOn(bsrc > bbot);
c2b27bf2 5946+ cpg->bsrc = bsrc;
367653fa 5947+ }
c2b27bf2
AM
5948+ AuDebugOn(cpg->bsrc <= cpg->bdst);
5949+ return au_do_sio_cpup_simple(cpg);
5950+}
367653fa 5951+
c2b27bf2
AM
5952+int au_sio_cpdown_simple(struct au_cp_generic *cpg)
5953+{
5954+ AuDebugOn(cpg->bdst <= cpg->bsrc);
5955+ return au_do_sio_cpup_simple(cpg);
367653fa
AM
5956+}
5957+
1facf9fc 5958+/* ---------------------------------------------------------------------- */
5959+
5960+/*
5961+ * copyup the deleted file for writing.
5962+ */
c2b27bf2
AM
5963+static int au_do_cpup_wh(struct au_cp_generic *cpg, struct dentry *wh_dentry,
5964+ struct file *file)
1facf9fc 5965+{
5966+ int err;
c2b27bf2
AM
5967+ unsigned int flags_orig;
5968+ aufs_bindex_t bsrc_orig;
c2b27bf2 5969+ struct au_dinfo *dinfo;
5afbbe0d
AM
5970+ struct {
5971+ struct au_hdentry *hd;
5972+ struct dentry *h_dentry;
5973+ } hdst, hsrc;
1facf9fc 5974+
c2b27bf2 5975+ dinfo = au_di(cpg->dentry);
1308ab2a 5976+ AuRwMustWriteLock(&dinfo->di_rwsem);
5977+
c2b27bf2 5978+ bsrc_orig = cpg->bsrc;
5afbbe0d
AM
5979+ cpg->bsrc = dinfo->di_btop;
5980+ hdst.hd = au_hdentry(dinfo, cpg->bdst);
5981+ hdst.h_dentry = hdst.hd->hd_dentry;
5982+ hdst.hd->hd_dentry = wh_dentry;
5983+ dinfo->di_btop = cpg->bdst;
5984+
5985+ hsrc.h_dentry = NULL;
027c5e7a 5986+ if (file) {
5afbbe0d
AM
5987+ hsrc.hd = au_hdentry(dinfo, cpg->bsrc);
5988+ hsrc.h_dentry = hsrc.hd->hd_dentry;
5989+ hsrc.hd->hd_dentry = au_hf_top(file)->f_path.dentry;
027c5e7a 5990+ }
c2b27bf2
AM
5991+ flags_orig = cpg->flags;
5992+ cpg->flags = !AuCpup_DTIME;
5993+ err = au_cpup_single(cpg, /*h_parent*/NULL);
5994+ cpg->flags = flags_orig;
027c5e7a
AM
5995+ if (file) {
5996+ if (!err)
5997+ err = au_reopen_nondir(file);
5afbbe0d 5998+ hsrc.hd->hd_dentry = hsrc.h_dentry;
1facf9fc 5999+ }
5afbbe0d
AM
6000+ hdst.hd->hd_dentry = hdst.h_dentry;
6001+ dinfo->di_btop = cpg->bsrc;
c2b27bf2 6002+ cpg->bsrc = bsrc_orig;
1facf9fc 6003+
6004+ return err;
6005+}
6006+
c2b27bf2 6007+static int au_cpup_wh(struct au_cp_generic *cpg, struct file *file)
1facf9fc 6008+{
6009+ int err;
c2b27bf2 6010+ aufs_bindex_t bdst;
1facf9fc 6011+ struct au_dtime dt;
c2b27bf2 6012+ struct dentry *dentry, *parent, *h_parent, *wh_dentry;
1facf9fc 6013+ struct au_branch *br;
6014+ struct path h_path;
6015+
c2b27bf2
AM
6016+ dentry = cpg->dentry;
6017+ bdst = cpg->bdst;
1facf9fc 6018+ br = au_sbr(dentry->d_sb, bdst);
6019+ parent = dget_parent(dentry);
6020+ h_parent = au_h_dptr(parent, bdst);
6021+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
6022+ err = PTR_ERR(wh_dentry);
6023+ if (IS_ERR(wh_dentry))
6024+ goto out;
6025+
6026+ h_path.dentry = h_parent;
86dc4139 6027+ h_path.mnt = au_br_mnt(br);
1facf9fc 6028+ au_dtime_store(&dt, parent, &h_path);
c2b27bf2 6029+ err = au_do_cpup_wh(cpg, wh_dentry, file);
1facf9fc 6030+ if (unlikely(err))
6031+ goto out_wh;
6032+
6033+ dget(wh_dentry);
6034+ h_path.dentry = wh_dentry;
2000de60 6035+ if (!d_is_dir(wh_dentry)) {
523b37e3 6036+ /* no delegation since it is just created */
5527c038 6037+ err = vfsub_unlink(d_inode(h_parent), &h_path,
523b37e3
AM
6038+ /*delegated*/NULL, /*force*/0);
6039+ } else
5527c038 6040+ err = vfsub_rmdir(d_inode(h_parent), &h_path);
1facf9fc 6041+ if (unlikely(err)) {
523b37e3
AM
6042+ AuIOErr("failed remove copied-up tmp file %pd(%d)\n",
6043+ wh_dentry, err);
1facf9fc 6044+ err = -EIO;
6045+ }
6046+ au_dtime_revert(&dt);
5527c038 6047+ au_set_hi_wh(d_inode(dentry), bdst, wh_dentry);
1facf9fc 6048+
4f0767ce 6049+out_wh:
1facf9fc 6050+ dput(wh_dentry);
4f0767ce 6051+out:
1facf9fc 6052+ dput(parent);
6053+ return err;
6054+}
6055+
6056+struct au_cpup_wh_args {
6057+ int *errp;
c2b27bf2 6058+ struct au_cp_generic *cpg;
1facf9fc 6059+ struct file *file;
6060+};
6061+
6062+static void au_call_cpup_wh(void *args)
6063+{
6064+ struct au_cpup_wh_args *a = args;
86dc4139 6065+
c2b27bf2
AM
6066+ au_pin_hdir_acquire_nest(a->cpg->pin);
6067+ *a->errp = au_cpup_wh(a->cpg, a->file);
6068+ au_pin_hdir_release(a->cpg->pin);
1facf9fc 6069+}
6070+
c2b27bf2 6071+int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file)
1facf9fc 6072+{
6073+ int err, wkq_err;
c2b27bf2 6074+ aufs_bindex_t bdst;
c1595e42 6075+ struct dentry *dentry, *parent, *h_orph, *h_parent;
86dc4139 6076+ struct inode *dir, *h_dir, *h_tmpdir;
1facf9fc 6077+ struct au_wbr *wbr;
c2b27bf2 6078+ struct au_pin wh_pin, *pin_orig;
0b2a12c6 6079+ struct user_namespace *h_userns;
1facf9fc 6080+
c2b27bf2
AM
6081+ dentry = cpg->dentry;
6082+ bdst = cpg->bdst;
1facf9fc 6083+ parent = dget_parent(dentry);
5527c038 6084+ dir = d_inode(parent);
1facf9fc 6085+ h_orph = NULL;
6086+ h_parent = NULL;
6087+ h_dir = au_igrab(au_h_iptr(dir, bdst));
6088+ h_tmpdir = h_dir;
c2b27bf2 6089+ pin_orig = NULL;
1facf9fc 6090+ if (!h_dir->i_nlink) {
6091+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
6092+ h_orph = wbr->wbr_orph;
6093+
6094+ h_parent = dget(au_h_dptr(parent, bdst));
1facf9fc 6095+ au_set_h_dptr(parent, bdst, dget(h_orph));
5527c038 6096+ h_tmpdir = d_inode(h_orph);
1facf9fc 6097+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
6098+
febd17d6 6099+ inode_lock_nested(h_tmpdir, AuLsc_I_PARENT3);
4a4d8108 6100+ /* todo: au_h_open_pre()? */
86dc4139 6101+
c2b27bf2 6102+ pin_orig = cpg->pin;
86dc4139 6103+ au_pin_init(&wh_pin, dentry, bdst, AuLsc_DI_PARENT,
c2b27bf2
AM
6104+ AuLsc_I_PARENT3, cpg->pin->udba, AuPin_DI_LOCKED);
6105+ cpg->pin = &wh_pin;
1facf9fc 6106+ }
6107+
0b2a12c6
JR
6108+ h_userns = au_sbr_userns(dentry->d_sb, bdst);
6109+ if (!au_test_h_perm_sio(h_userns, h_tmpdir, MAY_EXEC | MAY_WRITE)
5527c038 6110+ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode))
c2b27bf2 6111+ err = au_cpup_wh(cpg, file);
1facf9fc 6112+ else {
6113+ struct au_cpup_wh_args args = {
6114+ .errp = &err,
c2b27bf2
AM
6115+ .cpg = cpg,
6116+ .file = file
1facf9fc 6117+ };
6118+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
6119+ if (unlikely(wkq_err))
6120+ err = wkq_err;
6121+ }
6122+
6123+ if (h_orph) {
febd17d6 6124+ inode_unlock(h_tmpdir);
4a4d8108 6125+ /* todo: au_h_open_post()? */
1facf9fc 6126+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
1facf9fc 6127+ au_set_h_dptr(parent, bdst, h_parent);
c2b27bf2
AM
6128+ AuDebugOn(!pin_orig);
6129+ cpg->pin = pin_orig;
1facf9fc 6130+ }
6131+ iput(h_dir);
6132+ dput(parent);
6133+
6134+ return err;
6135+}
6136+
6137+/* ---------------------------------------------------------------------- */
6138+
6139+/*
6140+ * generic routine for both of copy-up and copy-down.
6141+ */
6142+/* cf. revalidate function in file.c */
6143+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
6144+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 6145+ struct au_pin *pin,
1facf9fc 6146+ struct dentry *h_parent, void *arg),
6147+ void *arg)
6148+{
6149+ int err;
6150+ struct au_pin pin;
5527c038 6151+ struct dentry *d, *parent, *h_parent, *real_parent, *h_dentry;
1facf9fc 6152+
6153+ err = 0;
6154+ parent = dget_parent(dentry);
6155+ if (IS_ROOT(parent))
6156+ goto out;
6157+
6158+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
6159+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
6160+
6161+ /* do not use au_dpage */
6162+ real_parent = parent;
6163+ while (1) {
6164+ dput(parent);
6165+ parent = dget_parent(dentry);
6166+ h_parent = au_h_dptr(parent, bdst);
6167+ if (h_parent)
6168+ goto out; /* success */
6169+
6170+ /* find top dir which is necessary to cpup */
6171+ do {
6172+ d = parent;
6173+ dput(parent);
6174+ parent = dget_parent(d);
6175+ di_read_lock_parent3(parent, !AuLock_IR);
6176+ h_parent = au_h_dptr(parent, bdst);
6177+ di_read_unlock(parent, !AuLock_IR);
6178+ } while (!h_parent);
6179+
6180+ if (d != real_parent)
6181+ di_write_lock_child3(d);
6182+
6183+ /* somebody else might create while we were sleeping */
5527c038
JR
6184+ h_dentry = au_h_dptr(d, bdst);
6185+ if (!h_dentry || d_is_negative(h_dentry)) {
6186+ if (h_dentry)
5afbbe0d 6187+ au_update_dbtop(d);
1facf9fc 6188+
6189+ au_pin_set_dentry(&pin, d);
6190+ err = au_do_pin(&pin);
6191+ if (!err) {
86dc4139 6192+ err = cp(d, bdst, &pin, h_parent, arg);
1facf9fc 6193+ au_unpin(&pin);
6194+ }
6195+ }
6196+
6197+ if (d != real_parent)
6198+ di_write_unlock(d);
6199+ if (unlikely(err))
6200+ break;
6201+ }
6202+
4f0767ce 6203+out:
1facf9fc 6204+ dput(parent);
6205+ return err;
6206+}
6207+
6208+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 6209+ struct au_pin *pin,
2000de60 6210+ struct dentry *h_parent __maybe_unused,
1facf9fc 6211+ void *arg __maybe_unused)
6212+{
c2b27bf2
AM
6213+ struct au_cp_generic cpg = {
6214+ .dentry = dentry,
6215+ .bdst = bdst,
6216+ .bsrc = -1,
6217+ .len = 0,
6218+ .pin = pin,
6219+ .flags = AuCpup_DTIME
6220+ };
6221+ return au_sio_cpup_simple(&cpg);
1facf9fc 6222+}
6223+
6224+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
6225+{
6226+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
6227+}
6228+
6229+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
6230+{
6231+ int err;
6232+ struct dentry *parent;
6233+ struct inode *dir;
6234+
6235+ parent = dget_parent(dentry);
5527c038 6236+ dir = d_inode(parent);
1facf9fc 6237+ err = 0;
6238+ if (au_h_iptr(dir, bdst))
6239+ goto out;
6240+
6241+ di_read_unlock(parent, AuLock_IR);
6242+ di_write_lock_parent(parent);
6243+ /* someone else might change our inode while we were sleeping */
6244+ if (!au_h_iptr(dir, bdst))
6245+ err = au_cpup_dirs(dentry, bdst);
6246+ di_downgrade_lock(parent, AuLock_IR);
6247+
4f0767ce 6248+out:
1facf9fc 6249+ dput(parent);
6250+ return err;
6251+}
7f207e10 6252diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
eca34b5c 6253--- /usr/share/empty/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 6254+++ linux/fs/aufs/cpup.h 2021-05-02 20:15:14.673337458 +0200
062440b3
AM
6255@@ -0,0 +1,100 @@
6256+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 6257+/*
d58c55f2 6258+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 6259+ *
6260+ * This program, aufs is free software; you can redistribute it and/or modify
6261+ * it under the terms of the GNU General Public License as published by
6262+ * the Free Software Foundation; either version 2 of the License, or
6263+ * (at your option) any later version.
dece6358
AM
6264+ *
6265+ * This program is distributed in the hope that it will be useful,
6266+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6267+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6268+ * GNU General Public License for more details.
6269+ *
6270+ * You should have received a copy of the GNU General Public License
523b37e3 6271+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 6272+ */
6273+
6274+/*
6275+ * copy-up/down functions
6276+ */
6277+
6278+#ifndef __AUFS_CPUP_H__
6279+#define __AUFS_CPUP_H__
6280+
6281+#ifdef __KERNEL__
6282+
dece6358 6283+#include <linux/path.h>
1facf9fc 6284+
dece6358
AM
6285+struct inode;
6286+struct file;
86dc4139 6287+struct au_pin;
dece6358 6288+
86dc4139 6289+void au_cpup_attr_flags(struct inode *dst, unsigned int iflags);
1facf9fc 6290+void au_cpup_attr_timesizes(struct inode *inode);
6291+void au_cpup_attr_nlink(struct inode *inode, int force);
6292+void au_cpup_attr_changeable(struct inode *inode);
6293+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
6294+void au_cpup_attr_all(struct inode *inode, int force);
6295+
6296+/* ---------------------------------------------------------------------- */
6297+
c2b27bf2
AM
6298+struct au_cp_generic {
6299+ struct dentry *dentry;
6300+ aufs_bindex_t bdst, bsrc;
6301+ loff_t len;
6302+ struct au_pin *pin;
6303+ unsigned int flags;
6304+};
6305+
1facf9fc 6306+/* cpup flags */
392086de
AM
6307+#define AuCpup_DTIME 1 /* do dtime_store/revert */
6308+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
6309+ for link(2) */
6310+#define AuCpup_RENAME (1 << 2) /* rename after cpup */
6311+#define AuCpup_HOPEN (1 << 3) /* call h_open_pre/post() in
6312+ cpup */
6313+#define AuCpup_OVERWRITE (1 << 4) /* allow overwriting the
6314+ existing entry */
6315+#define AuCpup_RWDST (1 << 5) /* force write target even if
6316+ the branch is marked as RO */
c2b27bf2 6317+
8b6a4947
AM
6318+#ifndef CONFIG_AUFS_BR_HFSPLUS
6319+#undef AuCpup_HOPEN
6320+#define AuCpup_HOPEN 0
6321+#endif
6322+
1facf9fc 6323+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
7f207e10
AM
6324+#define au_fset_cpup(flags, name) \
6325+ do { (flags) |= AuCpup_##name; } while (0)
6326+#define au_fclr_cpup(flags, name) \
6327+ do { (flags) &= ~AuCpup_##name; } while (0)
1facf9fc 6328+
6329+int au_copy_file(struct file *dst, struct file *src, loff_t len);
c2b27bf2
AM
6330+int au_sio_cpup_simple(struct au_cp_generic *cpg);
6331+int au_sio_cpdown_simple(struct au_cp_generic *cpg);
6332+int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file);
1facf9fc 6333+
6334+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
6335+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 6336+ struct au_pin *pin,
1facf9fc 6337+ struct dentry *h_parent, void *arg),
6338+ void *arg);
6339+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
6340+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
6341+
6342+/* ---------------------------------------------------------------------- */
6343+
6344+/* keep timestamps when copyup */
6345+struct au_dtime {
6346+ struct dentry *dt_dentry;
6347+ struct path dt_h_path;
cd7a4cd9 6348+ struct timespec64 dt_atime, dt_mtime;
1facf9fc 6349+};
6350+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
6351+ struct path *h_path);
6352+void au_dtime_revert(struct au_dtime *dt);
6353+
6354+#endif /* __KERNEL__ */
6355+#endif /* __AUFS_CPUP_H__ */
7f207e10 6356diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
eca34b5c 6357--- /usr/share/empty/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 6358+++ linux/fs/aufs/dbgaufs.c 2021-05-02 20:15:14.673337458 +0200
9f237c51 6359@@ -0,0 +1,526 @@
cd7a4cd9 6360+// SPDX-License-Identifier: GPL-2.0
1facf9fc 6361+/*
d58c55f2 6362+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 6363+ *
6364+ * This program, aufs is free software; you can redistribute it and/or modify
6365+ * it under the terms of the GNU General Public License as published by
6366+ * the Free Software Foundation; either version 2 of the License, or
6367+ * (at your option) any later version.
dece6358
AM
6368+ *
6369+ * This program is distributed in the hope that it will be useful,
6370+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6371+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6372+ * GNU General Public License for more details.
6373+ *
6374+ * You should have received a copy of the GNU General Public License
523b37e3 6375+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 6376+ */
6377+
6378+/*
6379+ * debugfs interface
6380+ */
6381+
6382+#include <linux/debugfs.h>
6383+#include "aufs.h"
6384+
6385+#ifndef CONFIG_SYSFS
6386+#error DEBUG_FS depends upon SYSFS
6387+#endif
6388+
6389+static struct dentry *dbgaufs;
cd7a4cd9 6390+static const mode_t dbgaufs_mode = 0444;
1facf9fc 6391+
6392+/* 20 is max digits length of ulong 64 */
6393+struct dbgaufs_arg {
6394+ int n;
6395+ char a[20 * 4];
6396+};
6397+
6398+/*
6399+ * common function for all XINO files
6400+ */
6401+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
6402+ struct file *file)
6403+{
9f237c51
AM
6404+ void *p;
6405+
6406+ p = file->private_data;
6407+ if (p) {
6408+ /* this is struct dbgaufs_arg */
6409+ AuDebugOn(!au_kfree_sz_test(p));
6410+ au_kfree_do_rcu(p);
6411+ }
1facf9fc 6412+ return 0;
6413+}
6414+
062440b3
AM
6415+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt,
6416+ int cnt)
1facf9fc 6417+{
6418+ int err;
6419+ struct kstat st;
6420+ struct dbgaufs_arg *p;
6421+
6422+ err = -ENOMEM;
6423+ p = kmalloc(sizeof(*p), GFP_NOFS);
6424+ if (unlikely(!p))
6425+ goto out;
6426+
6427+ err = 0;
6428+ p->n = 0;
6429+ file->private_data = p;
6430+ if (!xf)
6431+ goto out;
6432+
521ced18 6433+ err = vfsub_getattr(&xf->f_path, &st);
1facf9fc 6434+ if (!err) {
6435+ if (do_fcnt)
6436+ p->n = snprintf
062440b3
AM
6437+ (p->a, sizeof(p->a), "%d, %llux%u %lld\n",
6438+ cnt, st.blocks, st.blksize,
1facf9fc 6439+ (long long)st.size);
6440+ else
521ced18 6441+ p->n = snprintf(p->a, sizeof(p->a), "%llux%u %lld\n",
1facf9fc 6442+ st.blocks, st.blksize,
6443+ (long long)st.size);
6444+ AuDebugOn(p->n >= sizeof(p->a));
6445+ } else {
6446+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
6447+ err = 0;
6448+ }
6449+
4f0767ce 6450+out:
1facf9fc 6451+ return err;
1facf9fc 6452+}
6453+
6454+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
6455+ size_t count, loff_t *ppos)
6456+{
6457+ struct dbgaufs_arg *p;
6458+
6459+ p = file->private_data;
6460+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
6461+}
6462+
6463+/* ---------------------------------------------------------------------- */
6464+
86dc4139
AM
6465+struct dbgaufs_plink_arg {
6466+ int n;
6467+ char a[];
6468+};
6469+
6470+static int dbgaufs_plink_release(struct inode *inode __maybe_unused,
6471+ struct file *file)
6472+{
1c60b727 6473+ free_page((unsigned long)file->private_data);
86dc4139
AM
6474+ return 0;
6475+}
6476+
6477+static int dbgaufs_plink_open(struct inode *inode, struct file *file)
6478+{
6479+ int err, i, limit;
6480+ unsigned long n, sum;
6481+ struct dbgaufs_plink_arg *p;
6482+ struct au_sbinfo *sbinfo;
6483+ struct super_block *sb;
8b6a4947 6484+ struct hlist_bl_head *hbl;
86dc4139
AM
6485+
6486+ err = -ENOMEM;
6487+ p = (void *)get_zeroed_page(GFP_NOFS);
6488+ if (unlikely(!p))
6489+ goto out;
6490+
6491+ err = -EFBIG;
6492+ sbinfo = inode->i_private;
6493+ sb = sbinfo->si_sb;
6494+ si_noflush_read_lock(sb);
6495+ if (au_opt_test(au_mntflags(sb), PLINK)) {
6496+ limit = PAGE_SIZE - sizeof(p->n);
6497+
6498+ /* the number of buckets */
6499+ n = snprintf(p->a + p->n, limit, "%d\n", AuPlink_NHASH);
6500+ p->n += n;
6501+ limit -= n;
6502+
6503+ sum = 0;
8b6a4947
AM
6504+ for (i = 0, hbl = sbinfo->si_plink; i < AuPlink_NHASH;
6505+ i++, hbl++) {
6506+ n = au_hbl_count(hbl);
86dc4139
AM
6507+ sum += n;
6508+
6509+ n = snprintf(p->a + p->n, limit, "%lu ", n);
6510+ p->n += n;
6511+ limit -= n;
6512+ if (unlikely(limit <= 0))
6513+ goto out_free;
6514+ }
6515+ p->a[p->n - 1] = '\n';
6516+
6517+ /* the sum of plinks */
6518+ n = snprintf(p->a + p->n, limit, "%lu\n", sum);
6519+ p->n += n;
6520+ limit -= n;
6521+ if (unlikely(limit <= 0))
6522+ goto out_free;
6523+ } else {
6524+#define str "1\n0\n0\n"
6525+ p->n = sizeof(str) - 1;
6526+ strcpy(p->a, str);
6527+#undef str
6528+ }
6529+ si_read_unlock(sb);
6530+
6531+ err = 0;
6532+ file->private_data = p;
6533+ goto out; /* success */
6534+
6535+out_free:
1c60b727 6536+ free_page((unsigned long)p);
86dc4139
AM
6537+out:
6538+ return err;
6539+}
6540+
6541+static ssize_t dbgaufs_plink_read(struct file *file, char __user *buf,
6542+ size_t count, loff_t *ppos)
6543+{
6544+ struct dbgaufs_plink_arg *p;
6545+
6546+ p = file->private_data;
6547+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
6548+}
6549+
6550+static const struct file_operations dbgaufs_plink_fop = {
6551+ .owner = THIS_MODULE,
6552+ .open = dbgaufs_plink_open,
6553+ .release = dbgaufs_plink_release,
6554+ .read = dbgaufs_plink_read
6555+};
6556+
6557+/* ---------------------------------------------------------------------- */
6558+
1facf9fc 6559+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
6560+{
6561+ int err;
6562+ struct au_sbinfo *sbinfo;
6563+ struct super_block *sb;
6564+
6565+ sbinfo = inode->i_private;
6566+ sb = sbinfo->si_sb;
6567+ si_noflush_read_lock(sb);
062440b3 6568+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0, /*cnt*/0);
1facf9fc 6569+ si_read_unlock(sb);
6570+ return err;
6571+}
6572+
6573+static const struct file_operations dbgaufs_xib_fop = {
4a4d8108 6574+ .owner = THIS_MODULE,
1facf9fc 6575+ .open = dbgaufs_xib_open,
6576+ .release = dbgaufs_xi_release,
6577+ .read = dbgaufs_xi_read
6578+};
6579+
6580+/* ---------------------------------------------------------------------- */
6581+
6582+#define DbgaufsXi_PREFIX "xi"
6583+
6584+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
6585+{
acd2b654 6586+ int err, idx;
1facf9fc 6587+ long l;
acd2b654
AM
6588+ aufs_bindex_t bindex;
6589+ char *p, a[sizeof(DbgaufsXi_PREFIX) + 8];
1facf9fc 6590+ struct au_sbinfo *sbinfo;
6591+ struct super_block *sb;
acd2b654 6592+ struct au_xino *xi;
1facf9fc 6593+ struct file *xf;
6594+ struct qstr *name;
062440b3 6595+ struct au_branch *br;
1facf9fc 6596+
6597+ err = -ENOENT;
2000de60 6598+ name = &file->f_path.dentry->d_name;
1facf9fc 6599+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
6600+ || memcmp(name->name, DbgaufsXi_PREFIX,
6601+ sizeof(DbgaufsXi_PREFIX) - 1)))
6602+ goto out;
acd2b654
AM
6603+
6604+ AuDebugOn(name->len >= sizeof(a));
6605+ memcpy(a, name->name, name->len);
6606+ a[name->len] = '\0';
6607+ p = strchr(a, '-');
6608+ if (p)
6609+ *p = '\0';
6610+ err = kstrtol(a + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
1facf9fc 6611+ if (unlikely(err))
6612+ goto out;
acd2b654
AM
6613+ bindex = l;
6614+ idx = 0;
6615+ if (p) {
6616+ err = kstrtol(p + 1, 10, &l);
6617+ if (unlikely(err))
6618+ goto out;
6619+ idx = l;
6620+ }
1facf9fc 6621+
acd2b654 6622+ err = -ENOENT;
1facf9fc 6623+ sbinfo = inode->i_private;
6624+ sb = sbinfo->si_sb;
6625+ si_noflush_read_lock(sb);
acd2b654
AM
6626+ if (unlikely(bindex < 0 || bindex > au_sbbot(sb)))
6627+ goto out_si;
6628+ br = au_sbr(sb, bindex);
6629+ xi = br->br_xino;
6630+ if (unlikely(idx >= xi->xi_nfile))
6631+ goto out_si;
6632+ xf = au_xino_file(xi, idx);
6633+ if (xf)
062440b3
AM
6634+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1,
6635+ au_xino_count(br));
1facf9fc 6636+
acd2b654
AM
6637+out_si:
6638+ si_read_unlock(sb);
4f0767ce 6639+out:
acd2b654 6640+ AuTraceErr(err);
1facf9fc 6641+ return err;
6642+}
6643+
6644+static const struct file_operations dbgaufs_xino_fop = {
4a4d8108 6645+ .owner = THIS_MODULE,
1facf9fc 6646+ .open = dbgaufs_xino_open,
6647+ .release = dbgaufs_xi_release,
6648+ .read = dbgaufs_xi_read
6649+};
6650+
062440b3
AM
6651+void dbgaufs_xino_del(struct au_branch *br)
6652+{
6653+ struct dentry *dbgaufs;
6654+
6655+ dbgaufs = br->br_dbgaufs;
6656+ if (!dbgaufs)
6657+ return;
6658+
6659+ br->br_dbgaufs = NULL;
6660+ /* debugfs acquires the parent i_mutex */
6661+ lockdep_off();
6662+ debugfs_remove(dbgaufs);
6663+ lockdep_on();
6664+}
6665+
1facf9fc 6666+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
6667+{
5afbbe0d 6668+ aufs_bindex_t bbot;
1facf9fc 6669+ struct au_branch *br;
1facf9fc 6670+
6671+ if (!au_sbi(sb)->si_dbgaufs)
6672+ return;
6673+
5afbbe0d
AM
6674+ bbot = au_sbbot(sb);
6675+ for (; bindex <= bbot; bindex++) {
1facf9fc 6676+ br = au_sbr(sb, bindex);
062440b3
AM
6677+ dbgaufs_xino_del(br);
6678+ }
6679+}
6680+
acd2b654
AM
6681+static void dbgaufs_br_do_add(struct super_block *sb, aufs_bindex_t bindex,
6682+ unsigned int idx, struct dentry *parent,
6683+ struct au_sbinfo *sbinfo)
062440b3
AM
6684+{
6685+ struct au_branch *br;
6686+ struct dentry *d;
acd2b654
AM
6687+ /* "xi" bindex(5) "-" idx(2) NULL */
6688+ char name[sizeof(DbgaufsXi_PREFIX) + 8];
062440b3 6689+
acd2b654
AM
6690+ if (!idx)
6691+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
6692+ else
6693+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d-%u",
6694+ bindex, idx);
062440b3
AM
6695+ br = au_sbr(sb, bindex);
6696+ if (br->br_dbgaufs) {
6697+ struct qstr qstr = QSTR_INIT(name, strlen(name));
6698+
6699+ if (!au_qstreq(&br->br_dbgaufs->d_name, &qstr)) {
6700+ /* debugfs acquires the parent i_mutex */
6701+ lockdep_off();
6702+ d = debugfs_rename(parent, br->br_dbgaufs, parent,
6703+ name);
6704+ lockdep_on();
6705+ if (unlikely(!d))
6706+ pr_warn("failed renaming %pd/%s, ignored.\n",
6707+ parent, name);
6708+ }
6709+ } else {
e2f27e51 6710+ lockdep_off();
062440b3
AM
6711+ br->br_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
6712+ sbinfo, &dbgaufs_xino_fop);
e2f27e51 6713+ lockdep_on();
062440b3 6714+ if (unlikely(!br->br_dbgaufs))
acd2b654 6715+ pr_warn("failed creating %pd/%s, ignored.\n",
062440b3 6716+ parent, name);
1facf9fc 6717+ }
6718+}
6719+
acd2b654
AM
6720+static void dbgaufs_br_add(struct super_block *sb, aufs_bindex_t bindex,
6721+ struct dentry *parent, struct au_sbinfo *sbinfo)
6722+{
6723+ struct au_branch *br;
6724+ struct au_xino *xi;
6725+ unsigned int u;
6726+
6727+ br = au_sbr(sb, bindex);
6728+ xi = br->br_xino;
6729+ for (u = 0; u < xi->xi_nfile; u++)
6730+ dbgaufs_br_do_add(sb, bindex, u, parent, sbinfo);
6731+}
6732+
062440b3 6733+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex, int topdown)
1facf9fc 6734+{
6735+ struct au_sbinfo *sbinfo;
6736+ struct dentry *parent;
5afbbe0d 6737+ aufs_bindex_t bbot;
062440b3
AM
6738+
6739+ if (!au_opt_test(au_mntflags(sb), XINO))
6740+ return;
1facf9fc 6741+
6742+ sbinfo = au_sbi(sb);
6743+ parent = sbinfo->si_dbgaufs;
6744+ if (!parent)
6745+ return;
6746+
5afbbe0d 6747+ bbot = au_sbbot(sb);
062440b3
AM
6748+ if (topdown)
6749+ for (; bindex <= bbot; bindex++)
6750+ dbgaufs_br_add(sb, bindex, parent, sbinfo);
6751+ else
6752+ for (; bbot >= bindex; bbot--)
6753+ dbgaufs_br_add(sb, bbot, parent, sbinfo);
1facf9fc 6754+}
6755+
6756+/* ---------------------------------------------------------------------- */
6757+
6758+#ifdef CONFIG_AUFS_EXPORT
6759+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
6760+{
6761+ int err;
6762+ struct au_sbinfo *sbinfo;
6763+ struct super_block *sb;
6764+
6765+ sbinfo = inode->i_private;
6766+ sb = sbinfo->si_sb;
6767+ si_noflush_read_lock(sb);
062440b3 6768+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0, /*cnt*/0);
1facf9fc 6769+ si_read_unlock(sb);
6770+ return err;
6771+}
6772+
6773+static const struct file_operations dbgaufs_xigen_fop = {
4a4d8108 6774+ .owner = THIS_MODULE,
1facf9fc 6775+ .open = dbgaufs_xigen_open,
6776+ .release = dbgaufs_xi_release,
6777+ .read = dbgaufs_xi_read
6778+};
6779+
6780+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
6781+{
6782+ int err;
6783+
dece6358 6784+ /*
c1595e42 6785+ * This function is a dynamic '__init' function actually,
dece6358
AM
6786+ * so the tiny check for si_rwsem is unnecessary.
6787+ */
6788+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
6789+
1facf9fc 6790+ err = -EIO;
6791+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
6792+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
6793+ &dbgaufs_xigen_fop);
6794+ if (sbinfo->si_dbgaufs_xigen)
6795+ err = 0;
6796+
6797+ return err;
6798+}
6799+#else
6800+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
6801+{
6802+ return 0;
6803+}
6804+#endif /* CONFIG_AUFS_EXPORT */
6805+
6806+/* ---------------------------------------------------------------------- */
6807+
6808+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
6809+{
dece6358 6810+ /*
7e9cd9fe 6811+ * This function is a dynamic '__fin' function actually,
dece6358
AM
6812+ * so the tiny check for si_rwsem is unnecessary.
6813+ */
6814+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
6815+
1facf9fc 6816+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
6817+ sbinfo->si_dbgaufs = NULL;
1facf9fc 6818+}
6819+
6820+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
6821+{
6822+ int err;
6823+ char name[SysaufsSiNameLen];
6824+
dece6358 6825+ /*
c1595e42 6826+ * This function is a dynamic '__init' function actually,
dece6358
AM
6827+ * so the tiny check for si_rwsem is unnecessary.
6828+ */
6829+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
6830+
1facf9fc 6831+ err = -ENOENT;
6832+ if (!dbgaufs) {
6833+ AuErr1("/debug/aufs is uninitialized\n");
6834+ goto out;
6835+ }
6836+
6837+ err = -EIO;
6838+ sysaufs_name(sbinfo, name);
6839+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
6840+ if (unlikely(!sbinfo->si_dbgaufs))
6841+ goto out;
1facf9fc 6842+
062440b3 6843+ /* regardless plink/noplink option */
86dc4139
AM
6844+ sbinfo->si_dbgaufs_plink = debugfs_create_file
6845+ ("plink", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
6846+ &dbgaufs_plink_fop);
6847+ if (unlikely(!sbinfo->si_dbgaufs_plink))
6848+ goto out_dir;
6849+
062440b3
AM
6850+ /* regardless xino/noxino option */
6851+ sbinfo->si_dbgaufs_xib = debugfs_create_file
6852+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
6853+ &dbgaufs_xib_fop);
6854+ if (unlikely(!sbinfo->si_dbgaufs_xib))
6855+ goto out_dir;
6856+
1facf9fc 6857+ err = dbgaufs_xigen_init(sbinfo);
6858+ if (!err)
6859+ goto out; /* success */
6860+
4f0767ce 6861+out_dir:
1facf9fc 6862+ dbgaufs_si_fin(sbinfo);
4f0767ce 6863+out:
062440b3
AM
6864+ if (unlikely(err))
6865+ pr_err("debugfs/aufs failed\n");
1facf9fc 6866+ return err;
6867+}
6868+
6869+/* ---------------------------------------------------------------------- */
6870+
6871+void dbgaufs_fin(void)
6872+{
6873+ debugfs_remove(dbgaufs);
6874+}
6875+
6876+int __init dbgaufs_init(void)
6877+{
6878+ int err;
6879+
6880+ err = -EIO;
6881+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
6882+ if (dbgaufs)
6883+ err = 0;
6884+ return err;
6885+}
7f207e10 6886diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
eca34b5c 6887--- /usr/share/empty/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 6888+++ linux/fs/aufs/dbgaufs.h 2021-05-02 20:15:14.673337458 +0200
062440b3
AM
6889@@ -0,0 +1,53 @@
6890+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 6891+/*
d58c55f2 6892+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 6893+ *
6894+ * This program, aufs is free software; you can redistribute it and/or modify
6895+ * it under the terms of the GNU General Public License as published by
6896+ * the Free Software Foundation; either version 2 of the License, or
6897+ * (at your option) any later version.
dece6358
AM
6898+ *
6899+ * This program is distributed in the hope that it will be useful,
6900+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6901+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6902+ * GNU General Public License for more details.
6903+ *
6904+ * You should have received a copy of the GNU General Public License
523b37e3 6905+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 6906+ */
6907+
6908+/*
6909+ * debugfs interface
6910+ */
6911+
6912+#ifndef __DBGAUFS_H__
6913+#define __DBGAUFS_H__
6914+
6915+#ifdef __KERNEL__
6916+
dece6358 6917+struct super_block;
1facf9fc 6918+struct au_sbinfo;
062440b3 6919+struct au_branch;
dece6358 6920+
1facf9fc 6921+#ifdef CONFIG_DEBUG_FS
6922+/* dbgaufs.c */
062440b3 6923+void dbgaufs_xino_del(struct au_branch *br);
1facf9fc 6924+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
062440b3 6925+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex, int topdown);
1facf9fc 6926+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
6927+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
6928+void dbgaufs_fin(void);
6929+int __init dbgaufs_init(void);
1facf9fc 6930+#else
062440b3 6931+AuStubVoid(dbgaufs_xino_del, struct au_branch *br)
4a4d8108 6932+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
062440b3
AM
6933+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex,
6934+ int topdown)
4a4d8108
AM
6935+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
6936+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
6937+AuStubVoid(dbgaufs_fin, void)
6938+AuStubInt0(__init dbgaufs_init, void)
1facf9fc 6939+#endif /* CONFIG_DEBUG_FS */
6940+
6941+#endif /* __KERNEL__ */
6942+#endif /* __DBGAUFS_H__ */
7f207e10 6943diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
eca34b5c 6944--- /usr/share/empty/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 6945+++ linux/fs/aufs/dcsub.c 2021-05-02 20:15:14.673337458 +0200
cd7a4cd9
AM
6946@@ -0,0 +1,225 @@
6947+// SPDX-License-Identifier: GPL-2.0
1facf9fc 6948+/*
d58c55f2 6949+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 6950+ *
6951+ * This program, aufs is free software; you can redistribute it and/or modify
6952+ * it under the terms of the GNU General Public License as published by
6953+ * the Free Software Foundation; either version 2 of the License, or
6954+ * (at your option) any later version.
dece6358
AM
6955+ *
6956+ * This program is distributed in the hope that it will be useful,
6957+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6958+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6959+ * GNU General Public License for more details.
6960+ *
6961+ * You should have received a copy of the GNU General Public License
523b37e3 6962+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 6963+ */
6964+
6965+/*
6966+ * sub-routines for dentry cache
6967+ */
6968+
6969+#include "aufs.h"
6970+
6971+static void au_dpage_free(struct au_dpage *dpage)
6972+{
6973+ int i;
6974+ struct dentry **p;
6975+
6976+ p = dpage->dentries;
6977+ for (i = 0; i < dpage->ndentry; i++)
6978+ dput(*p++);
1c60b727 6979+ free_page((unsigned long)dpage->dentries);
1facf9fc 6980+}
6981+
6982+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
6983+{
6984+ int err;
6985+ void *p;
6986+
6987+ err = -ENOMEM;
6988+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
6989+ if (unlikely(!dpages->dpages))
6990+ goto out;
6991+
6992+ p = (void *)__get_free_page(gfp);
6993+ if (unlikely(!p))
6994+ goto out_dpages;
6995+
6996+ dpages->dpages[0].ndentry = 0;
6997+ dpages->dpages[0].dentries = p;
6998+ dpages->ndpage = 1;
6999+ return 0; /* success */
7000+
4f0767ce 7001+out_dpages:
9f237c51 7002+ au_kfree_try_rcu(dpages->dpages);
4f0767ce 7003+out:
1facf9fc 7004+ return err;
7005+}
7006+
7007+void au_dpages_free(struct au_dcsub_pages *dpages)
7008+{
7009+ int i;
7010+ struct au_dpage *p;
7011+
7012+ p = dpages->dpages;
7013+ for (i = 0; i < dpages->ndpage; i++)
7014+ au_dpage_free(p++);
9f237c51 7015+ au_kfree_try_rcu(dpages->dpages);
1facf9fc 7016+}
7017+
7018+static int au_dpages_append(struct au_dcsub_pages *dpages,
7019+ struct dentry *dentry, gfp_t gfp)
7020+{
7021+ int err, sz;
7022+ struct au_dpage *dpage;
7023+ void *p;
7024+
7025+ dpage = dpages->dpages + dpages->ndpage - 1;
7026+ sz = PAGE_SIZE / sizeof(dentry);
7027+ if (unlikely(dpage->ndentry >= sz)) {
7028+ AuLabel(new dpage);
7029+ err = -ENOMEM;
7030+ sz = dpages->ndpage * sizeof(*dpages->dpages);
7031+ p = au_kzrealloc(dpages->dpages, sz,
e2f27e51
AM
7032+ sz + sizeof(*dpages->dpages), gfp,
7033+ /*may_shrink*/0);
1facf9fc 7034+ if (unlikely(!p))
7035+ goto out;
7036+
7037+ dpages->dpages = p;
7038+ dpage = dpages->dpages + dpages->ndpage;
7039+ p = (void *)__get_free_page(gfp);
7040+ if (unlikely(!p))
7041+ goto out;
7042+
7043+ dpage->ndentry = 0;
7044+ dpage->dentries = p;
7045+ dpages->ndpage++;
7046+ }
7047+
c1595e42 7048+ AuDebugOn(au_dcount(dentry) <= 0);
027c5e7a 7049+ dpage->dentries[dpage->ndentry++] = dget_dlock(dentry);
1facf9fc 7050+ return 0; /* success */
7051+
4f0767ce 7052+out:
1facf9fc 7053+ return err;
7054+}
7055+
c1595e42
JR
7056+/* todo: BAD approach */
7057+/* copied from linux/fs/dcache.c */
7058+enum d_walk_ret {
7059+ D_WALK_CONTINUE,
7060+ D_WALK_QUIT,
7061+ D_WALK_NORETRY,
7062+ D_WALK_SKIP,
7063+};
7064+
7065+extern void d_walk(struct dentry *parent, void *data,
cd7a4cd9 7066+ enum d_walk_ret (*enter)(void *, struct dentry *));
c1595e42
JR
7067+
7068+struct ac_dpages_arg {
1facf9fc 7069+ int err;
c1595e42
JR
7070+ struct au_dcsub_pages *dpages;
7071+ struct super_block *sb;
7072+ au_dpages_test test;
7073+ void *arg;
7074+};
1facf9fc 7075+
c1595e42
JR
7076+static enum d_walk_ret au_call_dpages_append(void *_arg, struct dentry *dentry)
7077+{
7078+ enum d_walk_ret ret;
7079+ struct ac_dpages_arg *arg = _arg;
1facf9fc 7080+
c1595e42
JR
7081+ ret = D_WALK_CONTINUE;
7082+ if (dentry->d_sb == arg->sb
7083+ && !IS_ROOT(dentry)
7084+ && au_dcount(dentry) > 0
7085+ && au_di(dentry)
7086+ && (!arg->test || arg->test(dentry, arg->arg))) {
7087+ arg->err = au_dpages_append(arg->dpages, dentry, GFP_ATOMIC);
7088+ if (unlikely(arg->err))
7089+ ret = D_WALK_QUIT;
1facf9fc 7090+ }
7091+
c1595e42
JR
7092+ return ret;
7093+}
027c5e7a 7094+
c1595e42
JR
7095+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
7096+ au_dpages_test test, void *arg)
7097+{
7098+ struct ac_dpages_arg args = {
7099+ .err = 0,
7100+ .dpages = dpages,
7101+ .sb = root->d_sb,
7102+ .test = test,
7103+ .arg = arg
7104+ };
027c5e7a 7105+
cd7a4cd9 7106+ d_walk(root, &args, au_call_dpages_append);
c1595e42
JR
7107+
7108+ return args.err;
1facf9fc 7109+}
7110+
7111+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
7112+ int do_include, au_dpages_test test, void *arg)
7113+{
7114+ int err;
7115+
7116+ err = 0;
027c5e7a
AM
7117+ write_seqlock(&rename_lock);
7118+ spin_lock(&dentry->d_lock);
7119+ if (do_include
c1595e42 7120+ && au_dcount(dentry) > 0
027c5e7a 7121+ && (!test || test(dentry, arg)))
1facf9fc 7122+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
7123+ spin_unlock(&dentry->d_lock);
7124+ if (unlikely(err))
7125+ goto out;
7126+
7127+ /*
523b37e3 7128+ * RCU for vfsmount is unnecessary since this is a traverse in a single
027c5e7a
AM
7129+ * mount
7130+ */
1facf9fc 7131+ while (!IS_ROOT(dentry)) {
027c5e7a
AM
7132+ dentry = dentry->d_parent; /* rename_lock is locked */
7133+ spin_lock(&dentry->d_lock);
c1595e42 7134+ if (au_dcount(dentry) > 0
027c5e7a 7135+ && (!test || test(dentry, arg)))
1facf9fc 7136+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
7137+ spin_unlock(&dentry->d_lock);
7138+ if (unlikely(err))
7139+ break;
1facf9fc 7140+ }
7141+
4f0767ce 7142+out:
027c5e7a 7143+ write_sequnlock(&rename_lock);
1facf9fc 7144+ return err;
7145+}
7146+
027c5e7a
AM
7147+static inline int au_dcsub_dpages_aufs(struct dentry *dentry, void *arg)
7148+{
7149+ return au_di(dentry) && dentry->d_sb == arg;
7150+}
7151+
7152+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
7153+ struct dentry *dentry, int do_include)
7154+{
7155+ return au_dcsub_pages_rev(dpages, dentry, do_include,
7156+ au_dcsub_dpages_aufs, dentry->d_sb);
7157+}
7158+
4a4d8108 7159+int au_test_subdir(struct dentry *d1, struct dentry *d2)
1facf9fc 7160+{
4a4d8108
AM
7161+ struct path path[2] = {
7162+ {
7163+ .dentry = d1
7164+ },
7165+ {
7166+ .dentry = d2
7167+ }
7168+ };
1facf9fc 7169+
4a4d8108 7170+ return path_is_under(path + 0, path + 1);
1facf9fc 7171+}
7f207e10 7172diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
eca34b5c 7173--- /usr/share/empty/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 7174+++ linux/fs/aufs/dcsub.h 2021-05-02 20:15:14.673337458 +0200
062440b3
AM
7175@@ -0,0 +1,137 @@
7176+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 7177+/*
d58c55f2 7178+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 7179+ *
7180+ * This program, aufs is free software; you can redistribute it and/or modify
7181+ * it under the terms of the GNU General Public License as published by
7182+ * the Free Software Foundation; either version 2 of the License, or
7183+ * (at your option) any later version.
dece6358
AM
7184+ *
7185+ * This program is distributed in the hope that it will be useful,
7186+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7187+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7188+ * GNU General Public License for more details.
7189+ *
7190+ * You should have received a copy of the GNU General Public License
523b37e3 7191+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7192+ */
7193+
7194+/*
7195+ * sub-routines for dentry cache
7196+ */
7197+
7198+#ifndef __AUFS_DCSUB_H__
7199+#define __AUFS_DCSUB_H__
7200+
7201+#ifdef __KERNEL__
7202+
7f207e10 7203+#include <linux/dcache.h>
027c5e7a 7204+#include <linux/fs.h>
dece6358 7205+
1facf9fc 7206+struct au_dpage {
7207+ int ndentry;
7208+ struct dentry **dentries;
7209+};
7210+
7211+struct au_dcsub_pages {
7212+ int ndpage;
7213+ struct au_dpage *dpages;
7214+};
7215+
7216+/* ---------------------------------------------------------------------- */
7217+
7f207e10 7218+/* dcsub.c */
1facf9fc 7219+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
7220+void au_dpages_free(struct au_dcsub_pages *dpages);
7221+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
7222+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
7223+ au_dpages_test test, void *arg);
7224+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
7225+ int do_include, au_dpages_test test, void *arg);
027c5e7a
AM
7226+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
7227+ struct dentry *dentry, int do_include);
4a4d8108 7228+int au_test_subdir(struct dentry *d1, struct dentry *d2);
1facf9fc 7229+
7f207e10
AM
7230+/* ---------------------------------------------------------------------- */
7231+
523b37e3
AM
7232+/*
7233+ * todo: in linux-3.13, several similar (but faster) helpers are added to
7234+ * include/linux/dcache.h. Try them (in the future).
7235+ */
7236+
027c5e7a
AM
7237+static inline int au_d_hashed_positive(struct dentry *d)
7238+{
7239+ int err;
5527c038 7240+ struct inode *inode = d_inode(d);
076b876e 7241+
027c5e7a 7242+ err = 0;
5527c038
JR
7243+ if (unlikely(d_unhashed(d)
7244+ || d_is_negative(d)
7245+ || !inode->i_nlink))
027c5e7a
AM
7246+ err = -ENOENT;
7247+ return err;
7248+}
7249+
38d290e6
JR
7250+static inline int au_d_linkable(struct dentry *d)
7251+{
7252+ int err;
5527c038 7253+ struct inode *inode = d_inode(d);
076b876e 7254+
38d290e6
JR
7255+ err = au_d_hashed_positive(d);
7256+ if (err
5527c038 7257+ && d_is_positive(d)
38d290e6
JR
7258+ && (inode->i_state & I_LINKABLE))
7259+ err = 0;
7260+ return err;
7261+}
7262+
027c5e7a
AM
7263+static inline int au_d_alive(struct dentry *d)
7264+{
7265+ int err;
7266+ struct inode *inode;
076b876e 7267+
027c5e7a
AM
7268+ err = 0;
7269+ if (!IS_ROOT(d))
7270+ err = au_d_hashed_positive(d);
7271+ else {
5527c038
JR
7272+ inode = d_inode(d);
7273+ if (unlikely(d_unlinked(d)
7274+ || d_is_negative(d)
7275+ || !inode->i_nlink))
027c5e7a
AM
7276+ err = -ENOENT;
7277+ }
7278+ return err;
7279+}
7280+
7281+static inline int au_alive_dir(struct dentry *d)
7f207e10 7282+{
027c5e7a 7283+ int err;
076b876e 7284+
027c5e7a 7285+ err = au_d_alive(d);
5527c038 7286+ if (unlikely(err || IS_DEADDIR(d_inode(d))))
027c5e7a
AM
7287+ err = -ENOENT;
7288+ return err;
7f207e10
AM
7289+}
7290+
38d290e6
JR
7291+static inline int au_qstreq(struct qstr *a, struct qstr *b)
7292+{
7293+ return a->len == b->len
7294+ && !memcmp(a->name, b->name, a->len);
7295+}
7296+
7e9cd9fe
AM
7297+/*
7298+ * by the commit
7299+ * 360f547 2015-01-25 dcache: let the dentry count go down to zero without
7300+ * taking d_lock
7301+ * the type of d_lockref.count became int, but the inlined function d_count()
7302+ * still returns unsigned int.
7303+ * I don't know why. Maybe it is for every d_count() users?
7304+ * Anyway au_dcount() lives on.
7305+ */
c1595e42
JR
7306+static inline int au_dcount(struct dentry *d)
7307+{
7308+ return (int)d_count(d);
7309+}
7310+
1facf9fc 7311+#endif /* __KERNEL__ */
7312+#endif /* __AUFS_DCSUB_H__ */
7f207e10 7313diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
eca34b5c 7314--- /usr/share/empty/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 7315+++ linux/fs/aufs/debug.c 2021-05-02 20:15:14.673337458 +0200
eca801bf 7316@@ -0,0 +1,441 @@
cd7a4cd9 7317+// SPDX-License-Identifier: GPL-2.0
1facf9fc 7318+/*
d58c55f2 7319+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 7320+ *
7321+ * This program, aufs is free software; you can redistribute it and/or modify
7322+ * it under the terms of the GNU General Public License as published by
7323+ * the Free Software Foundation; either version 2 of the License, or
7324+ * (at your option) any later version.
dece6358
AM
7325+ *
7326+ * This program is distributed in the hope that it will be useful,
7327+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7328+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7329+ * GNU General Public License for more details.
7330+ *
7331+ * You should have received a copy of the GNU General Public License
523b37e3 7332+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7333+ */
7334+
7335+/*
7336+ * debug print functions
7337+ */
7338+
eca801bf 7339+#include <linux/iversion.h>
1facf9fc 7340+#include "aufs.h"
7341+
392086de
AM
7342+/* Returns 0, or -errno. arg is in kp->arg. */
7343+static int param_atomic_t_set(const char *val, const struct kernel_param *kp)
7344+{
7345+ int err, n;
7346+
7347+ err = kstrtoint(val, 0, &n);
7348+ if (!err) {
7349+ if (n > 0)
7350+ au_debug_on();
7351+ else
7352+ au_debug_off();
7353+ }
7354+ return err;
7355+}
7356+
7357+/* Returns length written or -errno. Buffer is 4k (ie. be short!) */
7358+static int param_atomic_t_get(char *buffer, const struct kernel_param *kp)
7359+{
7360+ atomic_t *a;
7361+
7362+ a = kp->arg;
7363+ return sprintf(buffer, "%d", atomic_read(a));
7364+}
7365+
7366+static struct kernel_param_ops param_ops_atomic_t = {
7367+ .set = param_atomic_t_set,
7368+ .get = param_atomic_t_get
7369+ /* void (*free)(void *arg) */
7370+};
7371+
7372+atomic_t aufs_debug = ATOMIC_INIT(0);
1facf9fc 7373+MODULE_PARM_DESC(debug, "debug print");
cd7a4cd9 7374+module_param_named(debug, aufs_debug, atomic_t, 0664);
1facf9fc 7375+
c1595e42 7376+DEFINE_MUTEX(au_dbg_mtx); /* just to serialize the dbg msgs */
1facf9fc 7377+char *au_plevel = KERN_DEBUG;
e49829fe
JR
7378+#define dpri(fmt, ...) do { \
7379+ if ((au_plevel \
7380+ && strcmp(au_plevel, KERN_DEBUG)) \
7381+ || au_debug_test()) \
7382+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
1facf9fc 7383+} while (0)
7384+
7385+/* ---------------------------------------------------------------------- */
7386+
7387+void au_dpri_whlist(struct au_nhash *whlist)
7388+{
7389+ unsigned long ul, n;
7390+ struct hlist_head *head;
c06a8ce3 7391+ struct au_vdir_wh *pos;
1facf9fc 7392+
7393+ n = whlist->nh_num;
7394+ head = whlist->nh_head;
7395+ for (ul = 0; ul < n; ul++) {
c06a8ce3 7396+ hlist_for_each_entry(pos, head, wh_hash)
1facf9fc 7397+ dpri("b%d, %.*s, %d\n",
c06a8ce3
AM
7398+ pos->wh_bindex,
7399+ pos->wh_str.len, pos->wh_str.name,
7400+ pos->wh_str.len);
1facf9fc 7401+ head++;
7402+ }
7403+}
7404+
7405+void au_dpri_vdir(struct au_vdir *vdir)
7406+{
7407+ unsigned long ul;
7408+ union au_vdir_deblk_p p;
7409+ unsigned char *o;
7410+
7411+ if (!vdir || IS_ERR(vdir)) {
7412+ dpri("err %ld\n", PTR_ERR(vdir));
7413+ return;
7414+ }
7415+
be118d29 7416+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %llu\n",
1facf9fc 7417+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
7418+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
7419+ for (ul = 0; ul < vdir->vd_nblk; ul++) {
7420+ p.deblk = vdir->vd_deblk[ul];
7421+ o = p.deblk;
7422+ dpri("[%lu]: %p\n", ul, o);
7423+ }
7424+}
7425+
53392da6 7426+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode, int hn,
1facf9fc 7427+ struct dentry *wh)
7428+{
7429+ char *n = NULL;
7430+ int l = 0;
7431+
7432+ if (!inode || IS_ERR(inode)) {
7433+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
7434+ return -1;
7435+ }
7436+
c2b27bf2 7437+ /* the type of i_blocks depends upon CONFIG_LBDAF */
1facf9fc 7438+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
7439+ && sizeof(inode->i_blocks) != sizeof(u64));
7440+ if (wh) {
7441+ n = (void *)wh->d_name.name;
7442+ l = wh->d_name.len;
7443+ }
7444+
53392da6
AM
7445+ dpri("i%d: %p, i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
7446+ " hn %d, ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
7447+ bindex, inode,
1facf9fc 7448+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
7449+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
7450+ i_size_read(inode), (unsigned long long)inode->i_blocks,
cd7a4cd9 7451+ hn, (long long)timespec64_to_ns(&inode->i_ctime) & 0x0ffff,
1facf9fc 7452+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
be118d29 7453+ inode->i_state, inode->i_flags, inode_peek_iversion(inode),
b752ccd1 7454+ inode->i_generation,
1facf9fc 7455+ l ? ", wh " : "", l, n);
7456+ return 0;
7457+}
7458+
7459+void au_dpri_inode(struct inode *inode)
7460+{
7461+ struct au_iinfo *iinfo;
5afbbe0d 7462+ struct au_hinode *hi;
1facf9fc 7463+ aufs_bindex_t bindex;
53392da6 7464+ int err, hn;
1facf9fc 7465+
53392da6 7466+ err = do_pri_inode(-1, inode, -1, NULL);
5afbbe0d 7467+ if (err || !au_test_aufs(inode->i_sb) || au_is_bad_inode(inode))
1facf9fc 7468+ return;
7469+
7470+ iinfo = au_ii(inode);
5afbbe0d
AM
7471+ dpri("i-1: btop %d, bbot %d, gen %d\n",
7472+ iinfo->ii_btop, iinfo->ii_bbot, au_iigen(inode, NULL));
7473+ if (iinfo->ii_btop < 0)
1facf9fc 7474+ return;
53392da6 7475+ hn = 0;
5afbbe0d
AM
7476+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; bindex++) {
7477+ hi = au_hinode(iinfo, bindex);
7478+ hn = !!au_hn(hi);
7479+ do_pri_inode(bindex, hi->hi_inode, hn, hi->hi_whdentry);
53392da6 7480+ }
1facf9fc 7481+}
7482+
2cbb1c4b
JR
7483+void au_dpri_dalias(struct inode *inode)
7484+{
7485+ struct dentry *d;
7486+
7487+ spin_lock(&inode->i_lock);
c1595e42 7488+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias)
2cbb1c4b
JR
7489+ au_dpri_dentry(d);
7490+ spin_unlock(&inode->i_lock);
7491+}
7492+
1facf9fc 7493+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
7494+{
7495+ struct dentry *wh = NULL;
53392da6 7496+ int hn;
5afbbe0d 7497+ struct inode *inode;
076b876e 7498+ struct au_iinfo *iinfo;
5afbbe0d 7499+ struct au_hinode *hi;
1facf9fc 7500+
7501+ if (!dentry || IS_ERR(dentry)) {
7502+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
7503+ return -1;
7504+ }
7505+ /* do not call dget_parent() here */
027c5e7a 7506+ /* note: access d_xxx without d_lock */
523b37e3
AM
7507+ dpri("d%d: %p, %pd2?, %s, cnt %d, flags 0x%x, %shashed\n",
7508+ bindex, dentry, dentry,
1facf9fc 7509+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
c1595e42 7510+ au_dcount(dentry), dentry->d_flags,
523b37e3 7511+ d_unhashed(dentry) ? "un" : "");
53392da6 7512+ hn = -1;
5afbbe0d
AM
7513+ inode = NULL;
7514+ if (d_is_positive(dentry))
7515+ inode = d_inode(dentry);
7516+ if (inode
7517+ && au_test_aufs(dentry->d_sb)
7518+ && bindex >= 0
7519+ && !au_is_bad_inode(inode)) {
7520+ iinfo = au_ii(inode);
7521+ hi = au_hinode(iinfo, bindex);
7522+ hn = !!au_hn(hi);
7523+ wh = hi->hi_whdentry;
7524+ }
7525+ do_pri_inode(bindex, inode, hn, wh);
1facf9fc 7526+ return 0;
7527+}
7528+
7529+void au_dpri_dentry(struct dentry *dentry)
7530+{
7531+ struct au_dinfo *dinfo;
7532+ aufs_bindex_t bindex;
7533+ int err;
7534+
7535+ err = do_pri_dentry(-1, dentry);
7536+ if (err || !au_test_aufs(dentry->d_sb))
7537+ return;
7538+
7539+ dinfo = au_di(dentry);
7540+ if (!dinfo)
7541+ return;
5afbbe0d
AM
7542+ dpri("d-1: btop %d, bbot %d, bwh %d, bdiropq %d, gen %d, tmp %d\n",
7543+ dinfo->di_btop, dinfo->di_bbot,
38d290e6
JR
7544+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry),
7545+ dinfo->di_tmpfile);
5afbbe0d 7546+ if (dinfo->di_btop < 0)
1facf9fc 7547+ return;
5afbbe0d
AM
7548+ for (bindex = dinfo->di_btop; bindex <= dinfo->di_bbot; bindex++)
7549+ do_pri_dentry(bindex, au_hdentry(dinfo, bindex)->hd_dentry);
1facf9fc 7550+}
7551+
7552+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
7553+{
7554+ char a[32];
7555+
7556+ if (!file || IS_ERR(file)) {
7557+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
7558+ return -1;
7559+ }
7560+ a[0] = 0;
7561+ if (bindex < 0
b912730e 7562+ && !IS_ERR_OR_NULL(file->f_path.dentry)
2000de60 7563+ && au_test_aufs(file->f_path.dentry->d_sb)
1facf9fc 7564+ && au_fi(file))
e49829fe 7565+ snprintf(a, sizeof(a), ", gen %d, mmapped %d",
2cbb1c4b 7566+ au_figen(file), atomic_read(&au_fi(file)->fi_mmapped));
b752ccd1 7567+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
1facf9fc 7568+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
b752ccd1 7569+ file->f_version, file->f_pos, a);
b912730e 7570+ if (!IS_ERR_OR_NULL(file->f_path.dentry))
2000de60 7571+ do_pri_dentry(bindex, file->f_path.dentry);
1facf9fc 7572+ return 0;
7573+}
7574+
7575+void au_dpri_file(struct file *file)
7576+{
7577+ struct au_finfo *finfo;
4a4d8108
AM
7578+ struct au_fidir *fidir;
7579+ struct au_hfile *hfile;
1facf9fc 7580+ aufs_bindex_t bindex;
7581+ int err;
7582+
7583+ err = do_pri_file(-1, file);
2000de60 7584+ if (err
b912730e 7585+ || IS_ERR_OR_NULL(file->f_path.dentry)
2000de60 7586+ || !au_test_aufs(file->f_path.dentry->d_sb))
1facf9fc 7587+ return;
7588+
7589+ finfo = au_fi(file);
7590+ if (!finfo)
7591+ return;
4a4d8108 7592+ if (finfo->fi_btop < 0)
1facf9fc 7593+ return;
4a4d8108
AM
7594+ fidir = finfo->fi_hdir;
7595+ if (!fidir)
7596+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
7597+ else
e49829fe
JR
7598+ for (bindex = finfo->fi_btop;
7599+ bindex >= 0 && bindex <= fidir->fd_bbot;
4a4d8108
AM
7600+ bindex++) {
7601+ hfile = fidir->fd_hfile + bindex;
7602+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
7603+ }
1facf9fc 7604+}
7605+
7606+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
7607+{
7608+ struct vfsmount *mnt;
7609+ struct super_block *sb;
7610+
7611+ if (!br || IS_ERR(br))
7612+ goto out;
86dc4139 7613+ mnt = au_br_mnt(br);
1facf9fc 7614+ if (!mnt || IS_ERR(mnt))
7615+ goto out;
7616+ sb = mnt->mnt_sb;
7617+ if (!sb || IS_ERR(sb))
7618+ goto out;
7619+
acd2b654 7620+ dpri("s%d: {perm 0x%x, id %d, wbr %p}, "
b752ccd1 7621+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, "
1facf9fc 7622+ "xino %d\n",
acd2b654
AM
7623+ bindex, br->br_perm, br->br_id, br->br_wbr,
7624+ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
b752ccd1 7625+ sb->s_flags, sb->s_count,
acd2b654
AM
7626+ atomic_read(&sb->s_active),
7627+ !!au_xino_file(br->br_xino, /*idx*/-1));
1facf9fc 7628+ return 0;
7629+
4f0767ce 7630+out:
1facf9fc 7631+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
7632+ return -1;
7633+}
7634+
7635+void au_dpri_sb(struct super_block *sb)
7636+{
7637+ struct au_sbinfo *sbinfo;
7638+ aufs_bindex_t bindex;
7639+ int err;
acd2b654 7640+ /* to reduce stack size */
1facf9fc 7641+ struct {
7642+ struct vfsmount mnt;
7643+ struct au_branch fake;
7644+ } *a;
7645+
7646+ /* this function can be called from magic sysrq */
7647+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
7648+ if (unlikely(!a)) {
7649+ dpri("no memory\n");
7650+ return;
7651+ }
7652+
7653+ a->mnt.mnt_sb = sb;
86dc4139 7654+ a->fake.br_path.mnt = &a->mnt;
1facf9fc 7655+ err = do_pri_br(-1, &a->fake);
9f237c51 7656+ au_kfree_rcu(a);
1facf9fc 7657+ dpri("dev 0x%x\n", sb->s_dev);
7658+ if (err || !au_test_aufs(sb))
7659+ return;
7660+
7661+ sbinfo = au_sbi(sb);
7662+ if (!sbinfo)
7663+ return;
f0c0a007
AM
7664+ dpri("nw %d, gen %u, kobj %d\n",
7665+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
521ced18 7666+ kref_read(&sbinfo->si_kobj.kref));
5afbbe0d 7667+ for (bindex = 0; bindex <= sbinfo->si_bbot; bindex++)
1facf9fc 7668+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
7669+}
7670+
7671+/* ---------------------------------------------------------------------- */
7672+
027c5e7a
AM
7673+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line)
7674+{
5527c038 7675+ struct inode *h_inode, *inode = d_inode(dentry);
027c5e7a 7676+ struct dentry *h_dentry;
5afbbe0d 7677+ aufs_bindex_t bindex, bbot, bi;
027c5e7a
AM
7678+
7679+ if (!inode /* || au_di(dentry)->di_lsc == AuLsc_DI_TMP */)
7680+ return;
7681+
5afbbe0d
AM
7682+ bbot = au_dbbot(dentry);
7683+ bi = au_ibbot(inode);
7684+ if (bi < bbot)
7685+ bbot = bi;
7686+ bindex = au_dbtop(dentry);
7687+ bi = au_ibtop(inode);
027c5e7a
AM
7688+ if (bi > bindex)
7689+ bindex = bi;
7690+
5afbbe0d 7691+ for (; bindex <= bbot; bindex++) {
027c5e7a
AM
7692+ h_dentry = au_h_dptr(dentry, bindex);
7693+ if (!h_dentry)
7694+ continue;
7695+ h_inode = au_h_iptr(inode, bindex);
5527c038 7696+ if (unlikely(h_inode != d_inode(h_dentry))) {
392086de 7697+ au_debug_on();
027c5e7a
AM
7698+ AuDbg("b%d, %s:%d\n", bindex, func, line);
7699+ AuDbgDentry(dentry);
7700+ AuDbgInode(inode);
392086de 7701+ au_debug_off();
027c5e7a
AM
7702+ BUG();
7703+ }
7704+ }
7705+}
7706+
1facf9fc 7707+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
7708+{
7709+ int err, i, j;
7710+ struct au_dcsub_pages dpages;
7711+ struct au_dpage *dpage;
7712+ struct dentry **dentries;
7713+
7714+ err = au_dpages_init(&dpages, GFP_NOFS);
7715+ AuDebugOn(err);
027c5e7a 7716+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/1);
1facf9fc 7717+ AuDebugOn(err);
7718+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
7719+ dpage = dpages.dpages + i;
7720+ dentries = dpage->dentries;
7721+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
027c5e7a 7722+ AuDebugOn(au_digen_test(dentries[j], sigen));
1facf9fc 7723+ }
7724+ au_dpages_free(&dpages);
7725+}
7726+
1facf9fc 7727+void au_dbg_verify_kthread(void)
7728+{
53392da6 7729+ if (au_wkq_test()) {
1facf9fc 7730+ au_dbg_blocked();
1e00d052
AM
7731+ /*
7732+ * It may be recursive, but udba=notify between two aufs mounts,
7733+ * where a single ro branch is shared, is not a problem.
7734+ */
7735+ /* WARN_ON(1); */
1facf9fc 7736+ }
7737+}
7738+
7739+/* ---------------------------------------------------------------------- */
7740+
1facf9fc 7741+int __init au_debug_init(void)
7742+{
7743+ aufs_bindex_t bindex;
7744+ struct au_vdir_destr destr;
7745+
7746+ bindex = -1;
7747+ AuDebugOn(bindex >= 0);
7748+
7749+ destr.len = -1;
7750+ AuDebugOn(destr.len < NAME_MAX);
7751+
7752+#ifdef CONFIG_4KSTACKS
0c3ec466 7753+ pr_warn("CONFIG_4KSTACKS is defined.\n");
1facf9fc 7754+#endif
7755+
1facf9fc 7756+ return 0;
7757+}
7f207e10 7758diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
eca34b5c 7759--- /usr/share/empty/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 7760+++ linux/fs/aufs/debug.h 2021-05-02 20:15:14.673337458 +0200
062440b3
AM
7761@@ -0,0 +1,226 @@
7762+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 7763+/*
d58c55f2 7764+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 7765+ *
7766+ * This program, aufs is free software; you can redistribute it and/or modify
7767+ * it under the terms of the GNU General Public License as published by
7768+ * the Free Software Foundation; either version 2 of the License, or
7769+ * (at your option) any later version.
dece6358
AM
7770+ *
7771+ * This program is distributed in the hope that it will be useful,
7772+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7773+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7774+ * GNU General Public License for more details.
7775+ *
7776+ * You should have received a copy of the GNU General Public License
523b37e3 7777+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7778+ */
7779+
7780+/*
7781+ * debug print functions
7782+ */
7783+
7784+#ifndef __AUFS_DEBUG_H__
7785+#define __AUFS_DEBUG_H__
7786+
7787+#ifdef __KERNEL__
7788+
392086de 7789+#include <linux/atomic.h>
4a4d8108
AM
7790+#include <linux/module.h>
7791+#include <linux/kallsyms.h>
1facf9fc 7792+#include <linux/sysrq.h>
4a4d8108 7793+
1facf9fc 7794+#ifdef CONFIG_AUFS_DEBUG
7795+#define AuDebugOn(a) BUG_ON(a)
7796+
7797+/* module parameter */
392086de
AM
7798+extern atomic_t aufs_debug;
7799+static inline void au_debug_on(void)
1facf9fc 7800+{
392086de
AM
7801+ atomic_inc(&aufs_debug);
7802+}
7803+static inline void au_debug_off(void)
7804+{
7805+ atomic_dec_if_positive(&aufs_debug);
1facf9fc 7806+}
7807+
7808+static inline int au_debug_test(void)
7809+{
392086de 7810+ return atomic_read(&aufs_debug) > 0;
1facf9fc 7811+}
7812+#else
7813+#define AuDebugOn(a) do {} while (0)
392086de
AM
7814+AuStubVoid(au_debug_on, void)
7815+AuStubVoid(au_debug_off, void)
4a4d8108 7816+AuStubInt0(au_debug_test, void)
1facf9fc 7817+#endif /* CONFIG_AUFS_DEBUG */
7818+
392086de
AM
7819+#define param_check_atomic_t(name, p) __param_check(name, p, atomic_t)
7820+
1facf9fc 7821+/* ---------------------------------------------------------------------- */
7822+
7823+/* debug print */
7824+
4a4d8108 7825+#define AuDbg(fmt, ...) do { \
1facf9fc 7826+ if (au_debug_test()) \
4a4d8108 7827+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
1facf9fc 7828+} while (0)
4a4d8108
AM
7829+#define AuLabel(l) AuDbg(#l "\n")
7830+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__)
7831+#define AuWarn1(fmt, ...) do { \
1facf9fc 7832+ static unsigned char _c; \
7833+ if (!_c++) \
0c3ec466 7834+ pr_warn(fmt, ##__VA_ARGS__); \
1facf9fc 7835+} while (0)
7836+
4a4d8108 7837+#define AuErr1(fmt, ...) do { \
1facf9fc 7838+ static unsigned char _c; \
7839+ if (!_c++) \
4a4d8108 7840+ pr_err(fmt, ##__VA_ARGS__); \
1facf9fc 7841+} while (0)
7842+
4a4d8108 7843+#define AuIOErr1(fmt, ...) do { \
1facf9fc 7844+ static unsigned char _c; \
7845+ if (!_c++) \
4a4d8108 7846+ AuIOErr(fmt, ##__VA_ARGS__); \
1facf9fc 7847+} while (0)
7848+
7849+#define AuUnsupportMsg "This operation is not supported." \
7850+ " Please report this application to aufs-users ML."
4a4d8108
AM
7851+#define AuUnsupport(fmt, ...) do { \
7852+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
1facf9fc 7853+ dump_stack(); \
7854+} while (0)
7855+
7856+#define AuTraceErr(e) do { \
7857+ if (unlikely((e) < 0)) \
7858+ AuDbg("err %d\n", (int)(e)); \
7859+} while (0)
7860+
7861+#define AuTraceErrPtr(p) do { \
7862+ if (IS_ERR(p)) \
7863+ AuDbg("err %ld\n", PTR_ERR(p)); \
7864+} while (0)
7865+
7866+/* dirty macros for debug print, use with "%.*s" and caution */
7867+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
1facf9fc 7868+
7869+/* ---------------------------------------------------------------------- */
7870+
dece6358 7871+struct dentry;
1facf9fc 7872+#ifdef CONFIG_AUFS_DEBUG
c1595e42 7873+extern struct mutex au_dbg_mtx;
1facf9fc 7874+extern char *au_plevel;
7875+struct au_nhash;
7876+void au_dpri_whlist(struct au_nhash *whlist);
7877+struct au_vdir;
7878+void au_dpri_vdir(struct au_vdir *vdir);
dece6358 7879+struct inode;
1facf9fc 7880+void au_dpri_inode(struct inode *inode);
2cbb1c4b 7881+void au_dpri_dalias(struct inode *inode);
1facf9fc 7882+void au_dpri_dentry(struct dentry *dentry);
dece6358 7883+struct file;
1facf9fc 7884+void au_dpri_file(struct file *filp);
dece6358 7885+struct super_block;
1facf9fc 7886+void au_dpri_sb(struct super_block *sb);
7887+
027c5e7a
AM
7888+#define au_dbg_verify_dinode(d) __au_dbg_verify_dinode(d, __func__, __LINE__)
7889+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line);
1facf9fc 7890+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
1facf9fc 7891+void au_dbg_verify_kthread(void);
7892+
7893+int __init au_debug_init(void);
7e9cd9fe 7894+
1facf9fc 7895+#define AuDbgWhlist(w) do { \
c1595e42 7896+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7897+ AuDbg(#w "\n"); \
7898+ au_dpri_whlist(w); \
c1595e42 7899+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7900+} while (0)
7901+
7902+#define AuDbgVdir(v) do { \
c1595e42 7903+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7904+ AuDbg(#v "\n"); \
7905+ au_dpri_vdir(v); \
c1595e42 7906+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7907+} while (0)
7908+
7909+#define AuDbgInode(i) do { \
c1595e42 7910+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7911+ AuDbg(#i "\n"); \
7912+ au_dpri_inode(i); \
c1595e42 7913+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7914+} while (0)
7915+
2cbb1c4b 7916+#define AuDbgDAlias(i) do { \
c1595e42 7917+ mutex_lock(&au_dbg_mtx); \
2cbb1c4b
JR
7918+ AuDbg(#i "\n"); \
7919+ au_dpri_dalias(i); \
c1595e42 7920+ mutex_unlock(&au_dbg_mtx); \
2cbb1c4b
JR
7921+} while (0)
7922+
1facf9fc 7923+#define AuDbgDentry(d) do { \
c1595e42 7924+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7925+ AuDbg(#d "\n"); \
7926+ au_dpri_dentry(d); \
c1595e42 7927+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7928+} while (0)
7929+
7930+#define AuDbgFile(f) do { \
c1595e42 7931+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7932+ AuDbg(#f "\n"); \
7933+ au_dpri_file(f); \
c1595e42 7934+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7935+} while (0)
7936+
7937+#define AuDbgSb(sb) do { \
c1595e42 7938+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7939+ AuDbg(#sb "\n"); \
7940+ au_dpri_sb(sb); \
c1595e42 7941+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7942+} while (0)
7943+
4a4d8108
AM
7944+#define AuDbgSym(addr) do { \
7945+ char sym[KSYM_SYMBOL_LEN]; \
7946+ sprint_symbol(sym, (unsigned long)addr); \
7947+ AuDbg("%s\n", sym); \
7948+} while (0)
1facf9fc 7949+#else
027c5e7a 7950+AuStubVoid(au_dbg_verify_dinode, struct dentry *dentry)
4a4d8108
AM
7951+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
7952+AuStubVoid(au_dbg_verify_kthread, void)
7953+AuStubInt0(__init au_debug_init, void)
1facf9fc 7954+
1facf9fc 7955+#define AuDbgWhlist(w) do {} while (0)
7956+#define AuDbgVdir(v) do {} while (0)
7957+#define AuDbgInode(i) do {} while (0)
2cbb1c4b 7958+#define AuDbgDAlias(i) do {} while (0)
1facf9fc 7959+#define AuDbgDentry(d) do {} while (0)
7960+#define AuDbgFile(f) do {} while (0)
7961+#define AuDbgSb(sb) do {} while (0)
4a4d8108 7962+#define AuDbgSym(addr) do {} while (0)
1facf9fc 7963+#endif /* CONFIG_AUFS_DEBUG */
7964+
7965+/* ---------------------------------------------------------------------- */
7966+
7967+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
7968+int __init au_sysrq_init(void);
7969+void au_sysrq_fin(void);
7970+
7971+#ifdef CONFIG_HW_CONSOLE
7972+#define au_dbg_blocked() do { \
7973+ WARN_ON(1); \
0c5527e5 7974+ handle_sysrq('w'); \
1facf9fc 7975+} while (0)
7976+#else
4a4d8108 7977+AuStubVoid(au_dbg_blocked, void)
1facf9fc 7978+#endif
7979+
7980+#else
4a4d8108
AM
7981+AuStubInt0(__init au_sysrq_init, void)
7982+AuStubVoid(au_sysrq_fin, void)
7983+AuStubVoid(au_dbg_blocked, void)
1facf9fc 7984+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
7985+
7986+#endif /* __KERNEL__ */
7987+#endif /* __AUFS_DEBUG_H__ */
7f207e10 7988diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
eca34b5c 7989--- /usr/share/empty/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6
JR
7990+++ linux/fs/aufs/dentry.c 2021-05-02 20:15:14.673337458 +0200
7991@@ -0,0 +1,1160 @@
cd7a4cd9 7992+// SPDX-License-Identifier: GPL-2.0
1facf9fc 7993+/*
d58c55f2 7994+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 7995+ *
7996+ * This program, aufs is free software; you can redistribute it and/or modify
7997+ * it under the terms of the GNU General Public License as published by
7998+ * the Free Software Foundation; either version 2 of the License, or
7999+ * (at your option) any later version.
dece6358
AM
8000+ *
8001+ * This program is distributed in the hope that it will be useful,
8002+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8003+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8004+ * GNU General Public License for more details.
8005+ *
8006+ * You should have received a copy of the GNU General Public License
523b37e3 8007+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 8008+ */
8009+
8010+/*
8011+ * lookup and dentry operations
8012+ */
8013+
eca801bf 8014+#include <linux/iversion.h>
dece6358 8015+#include <linux/namei.h>
1facf9fc 8016+#include "aufs.h"
8017+
1facf9fc 8018+/*
8019+ * returns positive/negative dentry, NULL or an error.
8020+ * NULL means whiteout-ed or not-found.
8021+ */
8022+static struct dentry*
8023+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
8b6a4947 8024+ aufs_bindex_t bindex, struct au_do_lookup_args *args)
1facf9fc 8025+{
8026+ struct dentry *h_dentry;
2000de60 8027+ struct inode *h_inode;
1facf9fc 8028+ struct au_branch *br;
0b2a12c6 8029+ struct user_namespace *h_userns;
1facf9fc 8030+ int wh_found, opq;
8031+ unsigned char wh_able;
8032+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
076b876e
AM
8033+ const unsigned char ignore_perm = !!au_ftest_lkup(args->flags,
8034+ IGNORE_PERM);
1facf9fc 8035+
1facf9fc 8036+ wh_found = 0;
8037+ br = au_sbr(dentry->d_sb, bindex);
0b2a12c6 8038+ h_userns = au_br_userns(br);
1facf9fc 8039+ wh_able = !!au_br_whable(br->br_perm);
8040+ if (wh_able)
0b2a12c6
JR
8041+ wh_found = au_wh_test(h_userns, h_parent, &args->whname,
8042+ ignore_perm);
1facf9fc 8043+ h_dentry = ERR_PTR(wh_found);
8044+ if (!wh_found)
8045+ goto real_lookup;
8046+ if (unlikely(wh_found < 0))
8047+ goto out;
8048+
8049+ /* We found a whiteout */
5afbbe0d 8050+ /* au_set_dbbot(dentry, bindex); */
1facf9fc 8051+ au_set_dbwh(dentry, bindex);
8052+ if (!allow_neg)
8053+ return NULL; /* success */
8054+
4f0767ce 8055+real_lookup:
076b876e 8056+ if (!ignore_perm)
8b6a4947 8057+ h_dentry = vfsub_lkup_one(args->name, h_parent);
076b876e 8058+ else
0b2a12c6 8059+ h_dentry = au_sio_lkup_one(h_userns, args->name, h_parent);
2000de60
JR
8060+ if (IS_ERR(h_dentry)) {
8061+ if (PTR_ERR(h_dentry) == -ENAMETOOLONG
8062+ && !allow_neg)
8063+ h_dentry = NULL;
1facf9fc 8064+ goto out;
2000de60 8065+ }
1facf9fc 8066+
5527c038
JR
8067+ h_inode = d_inode(h_dentry);
8068+ if (d_is_negative(h_dentry)) {
1facf9fc 8069+ if (!allow_neg)
8070+ goto out_neg;
8071+ } else if (wh_found
8072+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
8073+ goto out_neg;
8b6a4947
AM
8074+ else if (au_ftest_lkup(args->flags, DIRREN)
8075+ /* && h_inode */
8076+ && !au_dr_lkup_h_ino(args, bindex, h_inode->i_ino)) {
8077+ AuDbg("b%d %pd ignored hi%llu\n", bindex, h_dentry,
8078+ (unsigned long long)h_inode->i_ino);
8079+ goto out_neg;
8080+ }
1facf9fc 8081+
5afbbe0d
AM
8082+ if (au_dbbot(dentry) <= bindex)
8083+ au_set_dbbot(dentry, bindex);
8084+ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry))
8085+ au_set_dbtop(dentry, bindex);
1facf9fc 8086+ au_set_h_dptr(dentry, bindex, h_dentry);
8087+
2000de60
JR
8088+ if (!d_is_dir(h_dentry)
8089+ || !wh_able
5527c038 8090+ || (d_really_is_positive(dentry) && !d_is_dir(dentry)))
1facf9fc 8091+ goto out; /* success */
8092+
be118d29 8093+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD);
0b2a12c6 8094+ opq = au_diropq_test(h_userns, h_dentry);
3c1bdaff 8095+ inode_unlock_shared(h_inode);
1facf9fc 8096+ if (opq > 0)
8097+ au_set_dbdiropq(dentry, bindex);
8098+ else if (unlikely(opq < 0)) {
8099+ au_set_h_dptr(dentry, bindex, NULL);
8100+ h_dentry = ERR_PTR(opq);
8101+ }
8102+ goto out;
8103+
4f0767ce 8104+out_neg:
1facf9fc 8105+ dput(h_dentry);
8106+ h_dentry = NULL;
4f0767ce 8107+out:
1facf9fc 8108+ return h_dentry;
8109+}
8110+
dece6358
AM
8111+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
8112+{
8113+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
8114+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
8115+ return -EPERM;
8116+ return 0;
8117+}
8118+
1facf9fc 8119+/*
8120+ * returns the number of lower positive dentries,
8121+ * otherwise an error.
8122+ * can be called at unlinking with @type is zero.
8123+ */
5afbbe0d
AM
8124+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop,
8125+ unsigned int flags)
1facf9fc 8126+{
8127+ int npositive, err;
8128+ aufs_bindex_t bindex, btail, bdiropq;
8b6a4947 8129+ unsigned char isdir, dirperm1, dirren;
1facf9fc 8130+ struct au_do_lookup_args args = {
8b6a4947
AM
8131+ .flags = flags,
8132+ .name = &dentry->d_name
1facf9fc 8133+ };
1facf9fc 8134+ struct dentry *parent;
076b876e 8135+ struct super_block *sb;
1facf9fc 8136+
076b876e 8137+ sb = dentry->d_sb;
8b6a4947 8138+ err = au_test_shwh(sb, args.name);
dece6358 8139+ if (unlikely(err))
1facf9fc 8140+ goto out;
8141+
8b6a4947 8142+ err = au_wh_name_alloc(&args.whname, args.name);
1facf9fc 8143+ if (unlikely(err))
8144+ goto out;
8145+
2000de60 8146+ isdir = !!d_is_dir(dentry);
076b876e 8147+ dirperm1 = !!au_opt_test(au_mntflags(sb), DIRPERM1);
8b6a4947
AM
8148+ dirren = !!au_opt_test(au_mntflags(sb), DIRREN);
8149+ if (dirren)
8150+ au_fset_lkup(args.flags, DIRREN);
1facf9fc 8151+
8152+ npositive = 0;
4a4d8108 8153+ parent = dget_parent(dentry);
1facf9fc 8154+ btail = au_dbtaildir(parent);
5afbbe0d 8155+ for (bindex = btop; bindex <= btail; bindex++) {
1facf9fc 8156+ struct dentry *h_parent, *h_dentry;
8157+ struct inode *h_inode, *h_dir;
8b6a4947 8158+ struct au_branch *br;
1facf9fc 8159+
8160+ h_dentry = au_h_dptr(dentry, bindex);
8161+ if (h_dentry) {
5527c038 8162+ if (d_is_positive(h_dentry))
1facf9fc 8163+ npositive++;
5afbbe0d 8164+ break;
1facf9fc 8165+ }
8166+ h_parent = au_h_dptr(parent, bindex);
2000de60 8167+ if (!h_parent || !d_is_dir(h_parent))
1facf9fc 8168+ continue;
8169+
8b6a4947
AM
8170+ if (dirren) {
8171+ /* if the inum matches, then use the prepared name */
8172+ err = au_dr_lkup_name(&args, bindex);
8173+ if (unlikely(err))
8174+ goto out_parent;
8175+ }
8176+
5527c038 8177+ h_dir = d_inode(h_parent);
be118d29 8178+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
8b6a4947 8179+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &args);
3c1bdaff 8180+ inode_unlock_shared(h_dir);
1facf9fc 8181+ err = PTR_ERR(h_dentry);
8182+ if (IS_ERR(h_dentry))
4a4d8108 8183+ goto out_parent;
2000de60
JR
8184+ if (h_dentry)
8185+ au_fclr_lkup(args.flags, ALLOW_NEG);
076b876e
AM
8186+ if (dirperm1)
8187+ au_fset_lkup(args.flags, IGNORE_PERM);
1facf9fc 8188+
79b8bda9 8189+ if (au_dbwh(dentry) == bindex)
1facf9fc 8190+ break;
8191+ if (!h_dentry)
8192+ continue;
5527c038 8193+ if (d_is_negative(h_dentry))
1facf9fc 8194+ continue;
5527c038 8195+ h_inode = d_inode(h_dentry);
1facf9fc 8196+ npositive++;
8197+ if (!args.type)
8198+ args.type = h_inode->i_mode & S_IFMT;
8199+ if (args.type != S_IFDIR)
8200+ break;
8201+ else if (isdir) {
8202+ /* the type of lower may be different */
8203+ bdiropq = au_dbdiropq(dentry);
8204+ if (bdiropq >= 0 && bdiropq <= bindex)
8205+ break;
8206+ }
8b6a4947
AM
8207+ br = au_sbr(sb, bindex);
8208+ if (dirren
8209+ && au_dr_hino_test_add(&br->br_dirren, h_inode->i_ino,
8210+ /*add_ent*/NULL)) {
8211+ /* prepare next name to lookup */
8212+ err = au_dr_lkup(&args, dentry, bindex);
8213+ if (unlikely(err))
8214+ goto out_parent;
8215+ }
1facf9fc 8216+ }
8217+
8218+ if (npositive) {
8219+ AuLabel(positive);
5afbbe0d 8220+ au_update_dbtop(dentry);
1facf9fc 8221+ }
8222+ err = npositive;
076b876e 8223+ if (unlikely(!au_opt_test(au_mntflags(sb), UDBA_NONE)
5afbbe0d 8224+ && au_dbtop(dentry) < 0)) {
1facf9fc 8225+ err = -EIO;
523b37e3
AM
8226+ AuIOErr("both of real entry and whiteout found, %pd, err %d\n",
8227+ dentry, err);
027c5e7a 8228+ }
1facf9fc 8229+
4f0767ce 8230+out_parent:
4a4d8108 8231+ dput(parent);
9f237c51 8232+ au_kfree_try_rcu(args.whname.name);
8b6a4947
AM
8233+ if (dirren)
8234+ au_dr_lkup_fin(&args);
4f0767ce 8235+out:
1facf9fc 8236+ return err;
8237+}
8238+
0b2a12c6
JR
8239+struct dentry *au_sio_lkup_one(struct user_namespace *userns, struct qstr *name,
8240+ struct dentry *parent)
1facf9fc 8241+{
8242+ struct dentry *dentry;
8243+ int wkq_err;
8244+
0b2a12c6 8245+ if (!au_test_h_perm_sio(userns, d_inode(parent), MAY_EXEC))
b4510431 8246+ dentry = vfsub_lkup_one(name, parent);
1facf9fc 8247+ else {
b4510431
AM
8248+ struct vfsub_lkup_one_args args = {
8249+ .errp = &dentry,
8250+ .name = name,
8251+ .parent = parent
1facf9fc 8252+ };
8253+
b4510431 8254+ wkq_err = au_wkq_wait(vfsub_call_lkup_one, &args);
1facf9fc 8255+ if (unlikely(wkq_err))
8256+ dentry = ERR_PTR(wkq_err);
8257+ }
8258+
8259+ return dentry;
8260+}
8261+
8262+/*
8263+ * lookup @dentry on @bindex which should be negative.
8264+ */
86dc4139 8265+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh)
1facf9fc 8266+{
8267+ int err;
8268+ struct dentry *parent, *h_parent, *h_dentry;
86dc4139 8269+ struct au_branch *br;
0b2a12c6 8270+ struct user_namespace *h_userns;
1facf9fc 8271+
1facf9fc 8272+ parent = dget_parent(dentry);
8273+ h_parent = au_h_dptr(parent, bindex);
86dc4139 8274+ br = au_sbr(dentry->d_sb, bindex);
0b2a12c6 8275+ h_userns = au_br_userns(br);
86dc4139
AM
8276+ if (wh)
8277+ h_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
8278+ else
0b2a12c6 8279+ h_dentry = au_sio_lkup_one(h_userns, &dentry->d_name, h_parent);
1facf9fc 8280+ err = PTR_ERR(h_dentry);
8281+ if (IS_ERR(h_dentry))
8282+ goto out;
5527c038 8283+ if (unlikely(d_is_positive(h_dentry))) {
1facf9fc 8284+ err = -EIO;
523b37e3 8285+ AuIOErr("%pd should be negative on b%d.\n", h_dentry, bindex);
1facf9fc 8286+ dput(h_dentry);
8287+ goto out;
8288+ }
8289+
4a4d8108 8290+ err = 0;
5afbbe0d
AM
8291+ if (bindex < au_dbtop(dentry))
8292+ au_set_dbtop(dentry, bindex);
8293+ if (au_dbbot(dentry) < bindex)
8294+ au_set_dbbot(dentry, bindex);
1facf9fc 8295+ au_set_h_dptr(dentry, bindex, h_dentry);
1facf9fc 8296+
4f0767ce 8297+out:
1facf9fc 8298+ dput(parent);
8299+ return err;
8300+}
8301+
8302+/* ---------------------------------------------------------------------- */
8303+
8304+/* subset of struct inode */
8305+struct au_iattr {
8306+ unsigned long i_ino;
8307+ /* unsigned int i_nlink; */
0c3ec466
AM
8308+ kuid_t i_uid;
8309+ kgid_t i_gid;
1facf9fc 8310+ u64 i_version;
8311+/*
8312+ loff_t i_size;
8313+ blkcnt_t i_blocks;
8314+*/
8315+ umode_t i_mode;
8316+};
8317+
8318+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
8319+{
8320+ ia->i_ino = h_inode->i_ino;
8321+ /* ia->i_nlink = h_inode->i_nlink; */
8322+ ia->i_uid = h_inode->i_uid;
8323+ ia->i_gid = h_inode->i_gid;
be118d29 8324+ ia->i_version = inode_query_iversion(h_inode);
1facf9fc 8325+/*
8326+ ia->i_size = h_inode->i_size;
8327+ ia->i_blocks = h_inode->i_blocks;
8328+*/
8329+ ia->i_mode = (h_inode->i_mode & S_IFMT);
8330+}
8331+
8332+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
8333+{
8334+ return ia->i_ino != h_inode->i_ino
8335+ /* || ia->i_nlink != h_inode->i_nlink */
0c3ec466 8336+ || !uid_eq(ia->i_uid, h_inode->i_uid)
2dfbb274 8337+ || !gid_eq(ia->i_gid, h_inode->i_gid)
be118d29 8338+ || !inode_eq_iversion(h_inode, ia->i_version)
1facf9fc 8339+/*
8340+ || ia->i_size != h_inode->i_size
8341+ || ia->i_blocks != h_inode->i_blocks
8342+*/
8343+ || ia->i_mode != (h_inode->i_mode & S_IFMT);
8344+}
8345+
8346+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
8347+ struct au_branch *br)
8348+{
8349+ int err;
8350+ struct au_iattr ia;
8351+ struct inode *h_inode;
8352+ struct dentry *h_d;
8353+ struct super_block *h_sb;
8354+
8355+ err = 0;
8356+ memset(&ia, -1, sizeof(ia));
8357+ h_sb = h_dentry->d_sb;
5527c038
JR
8358+ h_inode = NULL;
8359+ if (d_is_positive(h_dentry)) {
8360+ h_inode = d_inode(h_dentry);
1facf9fc 8361+ au_iattr_save(&ia, h_inode);
5527c038 8362+ } else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
1facf9fc 8363+ /* nfs d_revalidate may return 0 for negative dentry */
8364+ /* fuse d_revalidate always return 0 for negative dentry */
8365+ goto out;
8366+
8367+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
b4510431 8368+ h_d = vfsub_lkup_one(&h_dentry->d_name, h_parent);
1facf9fc 8369+ err = PTR_ERR(h_d);
8370+ if (IS_ERR(h_d))
8371+ goto out;
8372+
8373+ err = 0;
8374+ if (unlikely(h_d != h_dentry
5527c038 8375+ || d_inode(h_d) != h_inode
1facf9fc 8376+ || (h_inode && au_iattr_test(&ia, h_inode))))
8377+ err = au_busy_or_stale();
8378+ dput(h_d);
8379+
4f0767ce 8380+out:
1facf9fc 8381+ AuTraceErr(err);
8382+ return err;
8383+}
8384+
8385+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
8386+ struct dentry *h_parent, struct au_branch *br)
8387+{
8388+ int err;
8389+
8390+ err = 0;
027c5e7a
AM
8391+ if (udba == AuOpt_UDBA_REVAL
8392+ && !au_test_fs_remote(h_dentry->d_sb)) {
1facf9fc 8393+ IMustLock(h_dir);
5527c038 8394+ err = (d_inode(h_dentry->d_parent) != h_dir);
027c5e7a 8395+ } else if (udba != AuOpt_UDBA_NONE)
1facf9fc 8396+ err = au_h_verify_dentry(h_dentry, h_parent, br);
8397+
8398+ return err;
8399+}
8400+
8401+/* ---------------------------------------------------------------------- */
8402+
027c5e7a 8403+static int au_do_refresh_hdentry(struct dentry *dentry, struct dentry *parent)
1facf9fc 8404+{
027c5e7a 8405+ int err;
5afbbe0d 8406+ aufs_bindex_t new_bindex, bindex, bbot, bwh, bdiropq;
027c5e7a
AM
8407+ struct au_hdentry tmp, *p, *q;
8408+ struct au_dinfo *dinfo;
8409+ struct super_block *sb;
1facf9fc 8410+
027c5e7a 8411+ DiMustWriteLock(dentry);
1308ab2a 8412+
027c5e7a
AM
8413+ sb = dentry->d_sb;
8414+ dinfo = au_di(dentry);
5afbbe0d 8415+ bbot = dinfo->di_bbot;
1facf9fc 8416+ bwh = dinfo->di_bwh;
8417+ bdiropq = dinfo->di_bdiropq;
5afbbe0d
AM
8418+ bindex = dinfo->di_btop;
8419+ p = au_hdentry(dinfo, bindex);
8420+ for (; bindex <= bbot; bindex++, p++) {
027c5e7a 8421+ if (!p->hd_dentry)
1facf9fc 8422+ continue;
8423+
027c5e7a
AM
8424+ new_bindex = au_br_index(sb, p->hd_id);
8425+ if (new_bindex == bindex)
1facf9fc 8426+ continue;
1facf9fc 8427+
1facf9fc 8428+ if (dinfo->di_bwh == bindex)
8429+ bwh = new_bindex;
8430+ if (dinfo->di_bdiropq == bindex)
8431+ bdiropq = new_bindex;
8432+ if (new_bindex < 0) {
8433+ au_hdput(p);
8434+ p->hd_dentry = NULL;
8435+ continue;
8436+ }
8437+
8438+ /* swap two lower dentries, and loop again */
5afbbe0d 8439+ q = au_hdentry(dinfo, new_bindex);
1facf9fc 8440+ tmp = *q;
8441+ *q = *p;
8442+ *p = tmp;
8443+ if (tmp.hd_dentry) {
8444+ bindex--;
8445+ p--;
8446+ }
8447+ }
8448+
1facf9fc 8449+ dinfo->di_bwh = -1;
5afbbe0d 8450+ if (bwh >= 0 && bwh <= au_sbbot(sb) && au_sbr_whable(sb, bwh))
1facf9fc 8451+ dinfo->di_bwh = bwh;
8452+
8453+ dinfo->di_bdiropq = -1;
8454+ if (bdiropq >= 0
5afbbe0d 8455+ && bdiropq <= au_sbbot(sb)
1facf9fc 8456+ && au_sbr_whable(sb, bdiropq))
8457+ dinfo->di_bdiropq = bdiropq;
8458+
027c5e7a 8459+ err = -EIO;
5afbbe0d
AM
8460+ dinfo->di_btop = -1;
8461+ dinfo->di_bbot = -1;
8462+ bbot = au_dbbot(parent);
8463+ bindex = 0;
8464+ p = au_hdentry(dinfo, bindex);
8465+ for (; bindex <= bbot; bindex++, p++)
1facf9fc 8466+ if (p->hd_dentry) {
5afbbe0d 8467+ dinfo->di_btop = bindex;
1facf9fc 8468+ break;
8469+ }
8470+
5afbbe0d
AM
8471+ if (dinfo->di_btop >= 0) {
8472+ bindex = bbot;
8473+ p = au_hdentry(dinfo, bindex);
8474+ for (; bindex >= 0; bindex--, p--)
027c5e7a 8475+ if (p->hd_dentry) {
5afbbe0d 8476+ dinfo->di_bbot = bindex;
027c5e7a
AM
8477+ err = 0;
8478+ break;
8479+ }
8480+ }
8481+
8482+ return err;
1facf9fc 8483+}
8484+
027c5e7a 8485+static void au_do_hide(struct dentry *dentry)
1facf9fc 8486+{
027c5e7a 8487+ struct inode *inode;
1facf9fc 8488+
5527c038
JR
8489+ if (d_really_is_positive(dentry)) {
8490+ inode = d_inode(dentry);
8491+ if (!d_is_dir(dentry)) {
027c5e7a
AM
8492+ if (inode->i_nlink && !d_unhashed(dentry))
8493+ drop_nlink(inode);
8494+ } else {
8495+ clear_nlink(inode);
8496+ /* stop next lookup */
8497+ inode->i_flags |= S_DEAD;
8498+ }
8499+ smp_mb(); /* necessary? */
8500+ }
8501+ d_drop(dentry);
8502+}
1308ab2a 8503+
027c5e7a
AM
8504+static int au_hide_children(struct dentry *parent)
8505+{
8506+ int err, i, j, ndentry;
8507+ struct au_dcsub_pages dpages;
8508+ struct au_dpage *dpage;
8509+ struct dentry *dentry;
1facf9fc 8510+
027c5e7a 8511+ err = au_dpages_init(&dpages, GFP_NOFS);
1facf9fc 8512+ if (unlikely(err))
8513+ goto out;
027c5e7a
AM
8514+ err = au_dcsub_pages(&dpages, parent, NULL, NULL);
8515+ if (unlikely(err))
8516+ goto out_dpages;
1facf9fc 8517+
027c5e7a
AM
8518+ /* in reverse order */
8519+ for (i = dpages.ndpage - 1; i >= 0; i--) {
8520+ dpage = dpages.dpages + i;
8521+ ndentry = dpage->ndentry;
8522+ for (j = ndentry - 1; j >= 0; j--) {
8523+ dentry = dpage->dentries[j];
8524+ if (dentry != parent)
8525+ au_do_hide(dentry);
8526+ }
8527+ }
1facf9fc 8528+
027c5e7a
AM
8529+out_dpages:
8530+ au_dpages_free(&dpages);
4f0767ce 8531+out:
027c5e7a 8532+ return err;
1facf9fc 8533+}
8534+
027c5e7a 8535+static void au_hide(struct dentry *dentry)
1facf9fc 8536+{
027c5e7a 8537+ int err;
1facf9fc 8538+
027c5e7a 8539+ AuDbgDentry(dentry);
2000de60 8540+ if (d_is_dir(dentry)) {
027c5e7a
AM
8541+ /* shrink_dcache_parent(dentry); */
8542+ err = au_hide_children(dentry);
8543+ if (unlikely(err))
523b37e3
AM
8544+ AuIOErr("%pd, failed hiding children, ignored %d\n",
8545+ dentry, err);
027c5e7a
AM
8546+ }
8547+ au_do_hide(dentry);
8548+}
1facf9fc 8549+
027c5e7a
AM
8550+/*
8551+ * By adding a dirty branch, a cached dentry may be affected in various ways.
8552+ *
8553+ * a dirty branch is added
8554+ * - on the top of layers
8555+ * - in the middle of layers
8556+ * - to the bottom of layers
8557+ *
8558+ * on the added branch there exists
8559+ * - a whiteout
8560+ * - a diropq
8561+ * - a same named entry
8562+ * + exist
8563+ * * negative --> positive
8564+ * * positive --> positive
8565+ * - type is unchanged
8566+ * - type is changed
8567+ * + doesn't exist
8568+ * * negative --> negative
8569+ * * positive --> negative (rejected by au_br_del() for non-dir case)
8570+ * - none
8571+ */
8572+static int au_refresh_by_dinfo(struct dentry *dentry, struct au_dinfo *dinfo,
8573+ struct au_dinfo *tmp)
8574+{
8575+ int err;
5afbbe0d 8576+ aufs_bindex_t bindex, bbot;
027c5e7a
AM
8577+ struct {
8578+ struct dentry *dentry;
8579+ struct inode *inode;
8580+ mode_t mode;
be52b249
AM
8581+ } orig_h, tmp_h = {
8582+ .dentry = NULL
8583+ };
027c5e7a
AM
8584+ struct au_hdentry *hd;
8585+ struct inode *inode, *h_inode;
8586+ struct dentry *h_dentry;
8587+
8588+ err = 0;
5afbbe0d 8589+ AuDebugOn(dinfo->di_btop < 0);
027c5e7a 8590+ orig_h.mode = 0;
5afbbe0d 8591+ orig_h.dentry = au_hdentry(dinfo, dinfo->di_btop)->hd_dentry;
5527c038
JR
8592+ orig_h.inode = NULL;
8593+ if (d_is_positive(orig_h.dentry)) {
8594+ orig_h.inode = d_inode(orig_h.dentry);
027c5e7a 8595+ orig_h.mode = orig_h.inode->i_mode & S_IFMT;
5527c038 8596+ }
5afbbe0d
AM
8597+ if (tmp->di_btop >= 0) {
8598+ tmp_h.dentry = au_hdentry(tmp, tmp->di_btop)->hd_dentry;
5527c038
JR
8599+ if (d_is_positive(tmp_h.dentry)) {
8600+ tmp_h.inode = d_inode(tmp_h.dentry);
027c5e7a 8601+ tmp_h.mode = tmp_h.inode->i_mode & S_IFMT;
5527c038 8602+ }
027c5e7a
AM
8603+ }
8604+
5527c038
JR
8605+ inode = NULL;
8606+ if (d_really_is_positive(dentry))
8607+ inode = d_inode(dentry);
027c5e7a 8608+ if (!orig_h.inode) {
acd2b654 8609+ AuDbg("negative originally\n");
027c5e7a
AM
8610+ if (inode) {
8611+ au_hide(dentry);
8612+ goto out;
8613+ }
8614+ AuDebugOn(inode);
5afbbe0d 8615+ AuDebugOn(dinfo->di_btop != dinfo->di_bbot);
027c5e7a
AM
8616+ AuDebugOn(dinfo->di_bdiropq != -1);
8617+
8618+ if (!tmp_h.inode) {
8619+ AuDbg("negative --> negative\n");
8620+ /* should have only one negative lower */
5afbbe0d
AM
8621+ if (tmp->di_btop >= 0
8622+ && tmp->di_btop < dinfo->di_btop) {
8623+ AuDebugOn(tmp->di_btop != tmp->di_bbot);
8624+ AuDebugOn(dinfo->di_btop != dinfo->di_bbot);
8625+ au_set_h_dptr(dentry, dinfo->di_btop, NULL);
027c5e7a 8626+ au_di_cp(dinfo, tmp);
5afbbe0d
AM
8627+ hd = au_hdentry(tmp, tmp->di_btop);
8628+ au_set_h_dptr(dentry, tmp->di_btop,
027c5e7a
AM
8629+ dget(hd->hd_dentry));
8630+ }
8631+ au_dbg_verify_dinode(dentry);
8632+ } else {
8633+ AuDbg("negative --> positive\n");
8634+ /*
8635+ * similar to the behaviour of creating with bypassing
8636+ * aufs.
8637+ * unhash it in order to force an error in the
8638+ * succeeding create operation.
8639+ * we should not set S_DEAD here.
8640+ */
8641+ d_drop(dentry);
8642+ /* au_di_swap(tmp, dinfo); */
8643+ au_dbg_verify_dinode(dentry);
8644+ }
8645+ } else {
8646+ AuDbg("positive originally\n");
8647+ /* inode may be NULL */
8648+ AuDebugOn(inode && (inode->i_mode & S_IFMT) != orig_h.mode);
8649+ if (!tmp_h.inode) {
8650+ AuDbg("positive --> negative\n");
8651+ /* or bypassing aufs */
8652+ au_hide(dentry);
5afbbe0d 8653+ if (tmp->di_bwh >= 0 && tmp->di_bwh <= dinfo->di_btop)
027c5e7a
AM
8654+ dinfo->di_bwh = tmp->di_bwh;
8655+ if (inode)
8656+ err = au_refresh_hinode_self(inode);
8657+ au_dbg_verify_dinode(dentry);
8658+ } else if (orig_h.mode == tmp_h.mode) {
8659+ AuDbg("positive --> positive, same type\n");
8660+ if (!S_ISDIR(orig_h.mode)
5afbbe0d 8661+ && dinfo->di_btop > tmp->di_btop) {
027c5e7a
AM
8662+ /*
8663+ * similar to the behaviour of removing and
8664+ * creating.
8665+ */
8666+ au_hide(dentry);
8667+ if (inode)
8668+ err = au_refresh_hinode_self(inode);
8669+ au_dbg_verify_dinode(dentry);
8670+ } else {
8671+ /* fill empty slots */
5afbbe0d
AM
8672+ if (dinfo->di_btop > tmp->di_btop)
8673+ dinfo->di_btop = tmp->di_btop;
8674+ if (dinfo->di_bbot < tmp->di_bbot)
8675+ dinfo->di_bbot = tmp->di_bbot;
027c5e7a
AM
8676+ dinfo->di_bwh = tmp->di_bwh;
8677+ dinfo->di_bdiropq = tmp->di_bdiropq;
5afbbe0d
AM
8678+ bbot = dinfo->di_bbot;
8679+ bindex = tmp->di_btop;
8680+ hd = au_hdentry(tmp, bindex);
8681+ for (; bindex <= bbot; bindex++, hd++) {
027c5e7a
AM
8682+ if (au_h_dptr(dentry, bindex))
8683+ continue;
5afbbe0d 8684+ h_dentry = hd->hd_dentry;
027c5e7a
AM
8685+ if (!h_dentry)
8686+ continue;
5527c038
JR
8687+ AuDebugOn(d_is_negative(h_dentry));
8688+ h_inode = d_inode(h_dentry);
027c5e7a
AM
8689+ AuDebugOn(orig_h.mode
8690+ != (h_inode->i_mode
8691+ & S_IFMT));
8692+ au_set_h_dptr(dentry, bindex,
8693+ dget(h_dentry));
8694+ }
5afbbe0d
AM
8695+ if (inode)
8696+ err = au_refresh_hinode(inode, dentry);
027c5e7a
AM
8697+ au_dbg_verify_dinode(dentry);
8698+ }
8699+ } else {
8700+ AuDbg("positive --> positive, different type\n");
8701+ /* similar to the behaviour of removing and creating */
8702+ au_hide(dentry);
8703+ if (inode)
8704+ err = au_refresh_hinode_self(inode);
8705+ au_dbg_verify_dinode(dentry);
8706+ }
8707+ }
8708+
8709+out:
8710+ return err;
8711+}
8712+
79b8bda9
AM
8713+void au_refresh_dop(struct dentry *dentry, int force_reval)
8714+{
8715+ const struct dentry_operations *dop
8716+ = force_reval ? &aufs_dop : dentry->d_sb->s_d_op;
8717+ static const unsigned int mask
8718+ = DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE;
8719+
8720+ BUILD_BUG_ON(sizeof(mask) != sizeof(dentry->d_flags));
8721+
8722+ if (dentry->d_op == dop)
8723+ return;
8724+
8725+ AuDbg("%pd\n", dentry);
8726+ spin_lock(&dentry->d_lock);
8727+ if (dop == &aufs_dop)
8728+ dentry->d_flags |= mask;
8729+ else
8730+ dentry->d_flags &= ~mask;
8731+ dentry->d_op = dop;
8732+ spin_unlock(&dentry->d_lock);
8733+}
8734+
027c5e7a
AM
8735+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent)
8736+{
e2f27e51 8737+ int err, ebrange, nbr;
027c5e7a
AM
8738+ unsigned int sigen;
8739+ struct au_dinfo *dinfo, *tmp;
8740+ struct super_block *sb;
8741+ struct inode *inode;
8742+
8743+ DiMustWriteLock(dentry);
8744+ AuDebugOn(IS_ROOT(dentry));
5527c038 8745+ AuDebugOn(d_really_is_negative(parent));
027c5e7a
AM
8746+
8747+ sb = dentry->d_sb;
027c5e7a
AM
8748+ sigen = au_sigen(sb);
8749+ err = au_digen_test(parent, sigen);
8750+ if (unlikely(err))
8751+ goto out;
8752+
e2f27e51 8753+ nbr = au_sbbot(sb) + 1;
027c5e7a 8754+ dinfo = au_di(dentry);
e2f27e51 8755+ err = au_di_realloc(dinfo, nbr, /*may_shrink*/0);
027c5e7a
AM
8756+ if (unlikely(err))
8757+ goto out;
8758+ ebrange = au_dbrange_test(dentry);
8759+ if (!ebrange)
8760+ ebrange = au_do_refresh_hdentry(dentry, parent);
8761+
38d290e6 8762+ if (d_unhashed(dentry) || ebrange /* || dinfo->di_tmpfile */) {
5afbbe0d 8763+ AuDebugOn(au_dbtop(dentry) < 0 && au_dbbot(dentry) >= 0);
5527c038
JR
8764+ if (d_really_is_positive(dentry)) {
8765+ inode = d_inode(dentry);
027c5e7a 8766+ err = au_refresh_hinode_self(inode);
5527c038 8767+ }
027c5e7a
AM
8768+ au_dbg_verify_dinode(dentry);
8769+ if (!err)
8770+ goto out_dgen; /* success */
8771+ goto out;
8772+ }
8773+
8774+ /* temporary dinfo */
8775+ AuDbgDentry(dentry);
8776+ err = -ENOMEM;
8777+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
8778+ if (unlikely(!tmp))
8779+ goto out;
8780+ au_di_swap(tmp, dinfo);
8781+ /* returns the number of positive dentries */
8782+ /*
8783+ * if current working dir is removed, it returns an error.
8784+ * but the dentry is legal.
8785+ */
5afbbe0d 8786+ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG);
027c5e7a
AM
8787+ AuDbgDentry(dentry);
8788+ au_di_swap(tmp, dinfo);
8789+ if (err == -ENOENT)
8790+ err = 0;
8791+ if (err >= 0) {
8792+ /* compare/refresh by dinfo */
8793+ AuDbgDentry(dentry);
8794+ err = au_refresh_by_dinfo(dentry, dinfo, tmp);
8795+ au_dbg_verify_dinode(dentry);
8796+ AuTraceErr(err);
8797+ }
e2f27e51 8798+ au_di_realloc(dinfo, nbr, /*may_shrink*/1); /* harmless if err */
027c5e7a
AM
8799+ au_rw_write_unlock(&tmp->di_rwsem);
8800+ au_di_free(tmp);
8801+ if (unlikely(err))
8802+ goto out;
8803+
8804+out_dgen:
8805+ au_update_digen(dentry);
8806+out:
8807+ if (unlikely(err && !(dentry->d_flags & DCACHE_NFSFS_RENAMED))) {
523b37e3 8808+ AuIOErr("failed refreshing %pd, %d\n", dentry, err);
027c5e7a
AM
8809+ AuDbgDentry(dentry);
8810+ }
8811+ AuTraceErr(err);
8812+ return err;
8813+}
8814+
b4510431
AM
8815+static int au_do_h_d_reval(struct dentry *h_dentry, unsigned int flags,
8816+ struct dentry *dentry, aufs_bindex_t bindex)
027c5e7a
AM
8817+{
8818+ int err, valid;
027c5e7a
AM
8819+
8820+ err = 0;
8821+ if (!(h_dentry->d_flags & DCACHE_OP_REVALIDATE))
8822+ goto out;
027c5e7a
AM
8823+
8824+ AuDbg("b%d\n", bindex);
b4510431
AM
8825+ /*
8826+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
8827+ * due to whiteout and branch permission.
8828+ */
8829+ flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
8830+ | LOOKUP_FOLLOW | LOOKUP_EXCL);
8831+ /* it may return tri-state */
8832+ valid = h_dentry->d_op->d_revalidate(h_dentry, flags);
1facf9fc 8833+
8834+ if (unlikely(valid < 0))
8835+ err = valid;
8836+ else if (!valid)
8837+ err = -EINVAL;
8838+
4f0767ce 8839+out:
1facf9fc 8840+ AuTraceErr(err);
8841+ return err;
8842+}
8843+
8844+/* todo: remove this */
8845+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
8b6a4947 8846+ unsigned int flags, int do_udba, int dirren)
1facf9fc 8847+{
8848+ int err;
8849+ umode_t mode, h_mode;
5afbbe0d 8850+ aufs_bindex_t bindex, btail, btop, ibs, ibe;
38d290e6 8851+ unsigned char plus, unhashed, is_root, h_plus, h_nfs, tmpfile;
4a4d8108 8852+ struct inode *h_inode, *h_cached_inode;
1facf9fc 8853+ struct dentry *h_dentry;
8854+ struct qstr *name, *h_name;
8855+
8856+ err = 0;
8857+ plus = 0;
8858+ mode = 0;
1facf9fc 8859+ ibs = -1;
8860+ ibe = -1;
8861+ unhashed = !!d_unhashed(dentry);
8862+ is_root = !!IS_ROOT(dentry);
8863+ name = &dentry->d_name;
38d290e6 8864+ tmpfile = au_di(dentry)->di_tmpfile;
1facf9fc 8865+
8866+ /*
7f207e10
AM
8867+ * Theoretically, REVAL test should be unnecessary in case of
8868+ * {FS,I}NOTIFY.
8869+ * But {fs,i}notify doesn't fire some necessary events,
1facf9fc 8870+ * IN_ATTRIB for atime/nlink/pageio
1facf9fc 8871+ * Let's do REVAL test too.
8872+ */
8873+ if (do_udba && inode) {
8874+ mode = (inode->i_mode & S_IFMT);
8875+ plus = (inode->i_nlink > 0);
5afbbe0d
AM
8876+ ibs = au_ibtop(inode);
8877+ ibe = au_ibbot(inode);
1facf9fc 8878+ }
8879+
5afbbe0d
AM
8880+ btop = au_dbtop(dentry);
8881+ btail = btop;
1facf9fc 8882+ if (inode && S_ISDIR(inode->i_mode))
8883+ btail = au_dbtaildir(dentry);
5afbbe0d 8884+ for (bindex = btop; bindex <= btail; bindex++) {
1facf9fc 8885+ h_dentry = au_h_dptr(dentry, bindex);
8886+ if (!h_dentry)
8887+ continue;
8888+
523b37e3
AM
8889+ AuDbg("b%d, %pd\n", bindex, h_dentry);
8890+ h_nfs = !!au_test_nfs(h_dentry->d_sb);
027c5e7a 8891+ spin_lock(&h_dentry->d_lock);
1facf9fc 8892+ h_name = &h_dentry->d_name;
8893+ if (unlikely(do_udba
8894+ && !is_root
523b37e3
AM
8895+ && ((!h_nfs
8896+ && (unhashed != !!d_unhashed(h_dentry)
8b6a4947 8897+ || (!tmpfile && !dirren
38d290e6
JR
8898+ && !au_qstreq(name, h_name))
8899+ ))
523b37e3
AM
8900+ || (h_nfs
8901+ && !(flags & LOOKUP_OPEN)
8902+ && (h_dentry->d_flags
8903+ & DCACHE_NFSFS_RENAMED)))
1facf9fc 8904+ )) {
38d290e6
JR
8905+ int h_unhashed;
8906+
8907+ h_unhashed = d_unhashed(h_dentry);
027c5e7a 8908+ spin_unlock(&h_dentry->d_lock);
38d290e6
JR
8909+ AuDbg("unhash 0x%x 0x%x, %pd %pd\n",
8910+ unhashed, h_unhashed, dentry, h_dentry);
1facf9fc 8911+ goto err;
8912+ }
027c5e7a 8913+ spin_unlock(&h_dentry->d_lock);
1facf9fc 8914+
b4510431 8915+ err = au_do_h_d_reval(h_dentry, flags, dentry, bindex);
1facf9fc 8916+ if (unlikely(err))
8917+ /* do not goto err, to keep the errno */
8918+ break;
8919+
8920+ /* todo: plink too? */
8921+ if (!do_udba)
8922+ continue;
8923+
8924+ /* UDBA tests */
5527c038 8925+ if (unlikely(!!inode != d_is_positive(h_dentry)))
1facf9fc 8926+ goto err;
8927+
5527c038
JR
8928+ h_inode = NULL;
8929+ if (d_is_positive(h_dentry))
8930+ h_inode = d_inode(h_dentry);
1facf9fc 8931+ h_plus = plus;
8932+ h_mode = mode;
8933+ h_cached_inode = h_inode;
8934+ if (h_inode) {
8935+ h_mode = (h_inode->i_mode & S_IFMT);
8936+ h_plus = (h_inode->i_nlink > 0);
8937+ }
8938+ if (inode && ibs <= bindex && bindex <= ibe)
8939+ h_cached_inode = au_h_iptr(inode, bindex);
8940+
523b37e3 8941+ if (!h_nfs) {
38d290e6 8942+ if (unlikely(plus != h_plus && !tmpfile))
523b37e3
AM
8943+ goto err;
8944+ } else {
8945+ if (unlikely(!(h_dentry->d_flags & DCACHE_NFSFS_RENAMED)
8946+ && !is_root
8947+ && !IS_ROOT(h_dentry)
8948+ && unhashed != d_unhashed(h_dentry)))
8949+ goto err;
8950+ }
8951+ if (unlikely(mode != h_mode
1facf9fc 8952+ || h_cached_inode != h_inode))
8953+ goto err;
8954+ continue;
8955+
f6b6e03d 8956+err:
1facf9fc 8957+ err = -EINVAL;
8958+ break;
8959+ }
8960+
523b37e3 8961+ AuTraceErr(err);
1facf9fc 8962+ return err;
8963+}
8964+
027c5e7a 8965+/* todo: consolidate with do_refresh() and au_reval_for_attr() */
1facf9fc 8966+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
8967+{
8968+ int err;
8969+ struct dentry *parent;
1facf9fc 8970+
027c5e7a 8971+ if (!au_digen_test(dentry, sigen))
1facf9fc 8972+ return 0;
8973+
8974+ parent = dget_parent(dentry);
8975+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 8976+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 8977+ au_dbg_verify_gen(parent, sigen);
027c5e7a 8978+ err = au_refresh_dentry(dentry, parent);
1facf9fc 8979+ di_read_unlock(parent, AuLock_IR);
8980+ dput(parent);
027c5e7a 8981+ AuTraceErr(err);
1facf9fc 8982+ return err;
8983+}
8984+
8985+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
8986+{
8987+ int err;
8988+ struct dentry *d, *parent;
1facf9fc 8989+
027c5e7a 8990+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR))
1facf9fc 8991+ return simple_reval_dpath(dentry, sigen);
8992+
8993+ /* slow loop, keep it simple and stupid */
8994+ /* cf: au_cpup_dirs() */
8995+ err = 0;
8996+ parent = NULL;
027c5e7a 8997+ while (au_digen_test(dentry, sigen)) {
1facf9fc 8998+ d = dentry;
8999+ while (1) {
9000+ dput(parent);
9001+ parent = dget_parent(d);
027c5e7a 9002+ if (!au_digen_test(parent, sigen))
1facf9fc 9003+ break;
9004+ d = parent;
9005+ }
9006+
1facf9fc 9007+ if (d != dentry)
027c5e7a 9008+ di_write_lock_child2(d);
1facf9fc 9009+
9010+ /* someone might update our dentry while we were sleeping */
027c5e7a
AM
9011+ if (au_digen_test(d, sigen)) {
9012+ /*
9013+ * todo: consolidate with simple_reval_dpath(),
9014+ * do_refresh() and au_reval_for_attr().
9015+ */
1facf9fc 9016+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 9017+ err = au_refresh_dentry(d, parent);
1facf9fc 9018+ di_read_unlock(parent, AuLock_IR);
9019+ }
9020+
9021+ if (d != dentry)
9022+ di_write_unlock(d);
9023+ dput(parent);
9024+ if (unlikely(err))
9025+ break;
9026+ }
9027+
9028+ return err;
9029+}
9030+
9031+/*
9032+ * if valid returns 1, otherwise 0.
9033+ */
b4510431 9034+static int aufs_d_revalidate(struct dentry *dentry, unsigned int flags)
1facf9fc 9035+{
9036+ int valid, err;
9037+ unsigned int sigen;
8b6a4947 9038+ unsigned char do_udba, dirren;
1facf9fc 9039+ struct super_block *sb;
9040+ struct inode *inode;
9041+
027c5e7a 9042+ /* todo: support rcu-walk? */
b4510431 9043+ if (flags & LOOKUP_RCU)
027c5e7a
AM
9044+ return -ECHILD;
9045+
9046+ valid = 0;
9047+ if (unlikely(!au_di(dentry)))
9048+ goto out;
9049+
e49829fe 9050+ valid = 1;
1facf9fc 9051+ sb = dentry->d_sb;
e49829fe
JR
9052+ /*
9053+ * todo: very ugly
9054+ * i_mutex of parent dir may be held,
9055+ * but we should not return 'invalid' due to busy.
9056+ */
9057+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM);
9058+ if (unlikely(err)) {
9059+ valid = err;
027c5e7a 9060+ AuTraceErr(err);
e49829fe
JR
9061+ goto out;
9062+ }
5527c038
JR
9063+ inode = NULL;
9064+ if (d_really_is_positive(dentry))
9065+ inode = d_inode(dentry);
5afbbe0d 9066+ if (unlikely(inode && au_is_bad_inode(inode))) {
c1595e42
JR
9067+ err = -EINVAL;
9068+ AuTraceErr(err);
9069+ goto out_dgrade;
9070+ }
027c5e7a
AM
9071+ if (unlikely(au_dbrange_test(dentry))) {
9072+ err = -EINVAL;
9073+ AuTraceErr(err);
9074+ goto out_dgrade;
1facf9fc 9075+ }
027c5e7a
AM
9076+
9077+ sigen = au_sigen(sb);
9078+ if (au_digen_test(dentry, sigen)) {
1facf9fc 9079+ AuDebugOn(IS_ROOT(dentry));
027c5e7a
AM
9080+ err = au_reval_dpath(dentry, sigen);
9081+ if (unlikely(err)) {
9082+ AuTraceErr(err);
1facf9fc 9083+ goto out_dgrade;
027c5e7a 9084+ }
1facf9fc 9085+ }
9086+ di_downgrade_lock(dentry, AuLock_IR);
9087+
1facf9fc 9088+ err = -EINVAL;
c1595e42 9089+ if (!(flags & (LOOKUP_OPEN | LOOKUP_EMPTY))
523b37e3 9090+ && inode
38d290e6 9091+ && !(inode->i_state && I_LINKABLE)
79b8bda9
AM
9092+ && (IS_DEADDIR(inode) || !inode->i_nlink)) {
9093+ AuTraceErr(err);
027c5e7a 9094+ goto out_inval;
79b8bda9 9095+ }
027c5e7a 9096+
1facf9fc 9097+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
9098+ if (do_udba && inode) {
5afbbe0d 9099+ aufs_bindex_t btop = au_ibtop(inode);
027c5e7a 9100+ struct inode *h_inode;
1facf9fc 9101+
5afbbe0d
AM
9102+ if (btop >= 0) {
9103+ h_inode = au_h_iptr(inode, btop);
79b8bda9
AM
9104+ if (h_inode && au_test_higen(inode, h_inode)) {
9105+ AuTraceErr(err);
027c5e7a 9106+ goto out_inval;
79b8bda9 9107+ }
027c5e7a 9108+ }
1facf9fc 9109+ }
9110+
8b6a4947
AM
9111+ dirren = !!au_opt_test(au_mntflags(sb), DIRREN);
9112+ err = h_d_revalidate(dentry, inode, flags, do_udba, dirren);
5afbbe0d 9113+ if (unlikely(!err && do_udba && au_dbtop(dentry) < 0)) {
1facf9fc 9114+ err = -EIO;
523b37e3
AM
9115+ AuDbg("both of real entry and whiteout found, %p, err %d\n",
9116+ dentry, err);
027c5e7a 9117+ }
e49829fe 9118+ goto out_inval;
1facf9fc 9119+
4f0767ce 9120+out_dgrade:
1facf9fc 9121+ di_downgrade_lock(dentry, AuLock_IR);
e49829fe 9122+out_inval:
1facf9fc 9123+ aufs_read_unlock(dentry, AuLock_IR);
9124+ AuTraceErr(err);
9125+ valid = !err;
e49829fe 9126+out:
027c5e7a 9127+ if (!valid) {
523b37e3 9128+ AuDbg("%pd invalid, %d\n", dentry, valid);
027c5e7a
AM
9129+ d_drop(dentry);
9130+ }
1facf9fc 9131+ return valid;
9132+}
9133+
9134+static void aufs_d_release(struct dentry *dentry)
9135+{
027c5e7a 9136+ if (au_di(dentry)) {
4a4d8108
AM
9137+ au_di_fin(dentry);
9138+ au_hn_di_reinit(dentry);
1facf9fc 9139+ }
1facf9fc 9140+}
9141+
4a4d8108 9142+const struct dentry_operations aufs_dop = {
c06a8ce3
AM
9143+ .d_revalidate = aufs_d_revalidate,
9144+ .d_weak_revalidate = aufs_d_revalidate,
9145+ .d_release = aufs_d_release
1facf9fc 9146+};
79b8bda9
AM
9147+
9148+/* aufs_dop without d_revalidate */
9149+const struct dentry_operations aufs_dop_noreval = {
9150+ .d_release = aufs_d_release
9151+};
7f207e10 9152diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
eca34b5c 9153--- /usr/share/empty/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6
JR
9154+++ linux/fs/aufs/dentry.h 2021-05-02 20:15:14.673337458 +0200
9155@@ -0,0 +1,269 @@
062440b3 9156+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 9157+/*
d58c55f2 9158+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 9159+ *
9160+ * This program, aufs is free software; you can redistribute it and/or modify
9161+ * it under the terms of the GNU General Public License as published by
9162+ * the Free Software Foundation; either version 2 of the License, or
9163+ * (at your option) any later version.
dece6358
AM
9164+ *
9165+ * This program is distributed in the hope that it will be useful,
9166+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9167+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9168+ * GNU General Public License for more details.
9169+ *
9170+ * You should have received a copy of the GNU General Public License
523b37e3 9171+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 9172+ */
9173+
9174+/*
9175+ * lookup and dentry operations
9176+ */
9177+
9178+#ifndef __AUFS_DENTRY_H__
9179+#define __AUFS_DENTRY_H__
9180+
9181+#ifdef __KERNEL__
9182+
dece6358 9183+#include <linux/dcache.h>
8b6a4947 9184+#include "dirren.h"
1facf9fc 9185+#include "rwsem.h"
9186+
1facf9fc 9187+struct au_hdentry {
9188+ struct dentry *hd_dentry;
027c5e7a 9189+ aufs_bindex_t hd_id;
1facf9fc 9190+};
9191+
9192+struct au_dinfo {
9193+ atomic_t di_generation;
9194+
dece6358 9195+ struct au_rwsem di_rwsem;
5afbbe0d 9196+ aufs_bindex_t di_btop, di_bbot, di_bwh, di_bdiropq;
38d290e6 9197+ unsigned char di_tmpfile; /* to allow the different name */
1c60b727 9198+ struct au_hdentry *di_hdentry;
9f237c51 9199+ struct rcu_head rcu;
4a4d8108 9200+} ____cacheline_aligned_in_smp;
1facf9fc 9201+
9202+/* ---------------------------------------------------------------------- */
9203+
5afbbe0d
AM
9204+/* flags for au_lkup_dentry() */
9205+#define AuLkup_ALLOW_NEG 1
9206+#define AuLkup_IGNORE_PERM (1 << 1)
8b6a4947 9207+#define AuLkup_DIRREN (1 << 2)
5afbbe0d
AM
9208+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
9209+#define au_fset_lkup(flags, name) \
9210+ do { (flags) |= AuLkup_##name; } while (0)
9211+#define au_fclr_lkup(flags, name) \
9212+ do { (flags) &= ~AuLkup_##name; } while (0)
9213+
8b6a4947
AM
9214+#ifndef CONFIG_AUFS_DIRREN
9215+#undef AuLkup_DIRREN
9216+#define AuLkup_DIRREN 0
9217+#endif
9218+
9219+struct au_do_lookup_args {
9220+ unsigned int flags;
9221+ mode_t type;
9222+ struct qstr whname, *name;
9223+ struct au_dr_lookup dirren;
9224+};
9225+
5afbbe0d
AM
9226+/* ---------------------------------------------------------------------- */
9227+
1facf9fc 9228+/* dentry.c */
79b8bda9 9229+extern const struct dentry_operations aufs_dop, aufs_dop_noreval;
1facf9fc 9230+struct au_branch;
0b2a12c6
JR
9231+struct dentry *au_sio_lkup_one(struct user_namespace *userns, struct qstr *name,
9232+ struct dentry *parent);
1facf9fc 9233+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
9234+ struct dentry *h_parent, struct au_branch *br);
9235+
5afbbe0d
AM
9236+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop,
9237+ unsigned int flags);
86dc4139 9238+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh);
027c5e7a 9239+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent);
1facf9fc 9240+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
79b8bda9 9241+void au_refresh_dop(struct dentry *dentry, int force_reval);
1facf9fc 9242+
9243+/* dinfo.c */
4a4d8108 9244+void au_di_init_once(void *_di);
027c5e7a
AM
9245+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc);
9246+void au_di_free(struct au_dinfo *dinfo);
9247+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b);
9248+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src);
4a4d8108
AM
9249+int au_di_init(struct dentry *dentry);
9250+void au_di_fin(struct dentry *dentry);
e2f27e51 9251+int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink);
1facf9fc 9252+
9253+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
9254+void di_read_unlock(struct dentry *d, int flags);
9255+void di_downgrade_lock(struct dentry *d, int flags);
9256+void di_write_lock(struct dentry *d, unsigned int lsc);
9257+void di_write_unlock(struct dentry *d);
9258+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
9259+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
9260+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
9261+
9262+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
2cbb1c4b 9263+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex);
1facf9fc 9264+aufs_bindex_t au_dbtail(struct dentry *dentry);
9265+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
9266+
9267+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
9268+ struct dentry *h_dentry);
027c5e7a
AM
9269+int au_digen_test(struct dentry *dentry, unsigned int sigen);
9270+int au_dbrange_test(struct dentry *dentry);
1facf9fc 9271+void au_update_digen(struct dentry *dentry);
9272+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
5afbbe0d
AM
9273+void au_update_dbtop(struct dentry *dentry);
9274+void au_update_dbbot(struct dentry *dentry);
1facf9fc 9275+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
9276+
9277+/* ---------------------------------------------------------------------- */
9278+
9279+static inline struct au_dinfo *au_di(struct dentry *dentry)
9280+{
9281+ return dentry->d_fsdata;
9282+}
9283+
9284+/* ---------------------------------------------------------------------- */
9285+
9286+/* lock subclass for dinfo */
9287+enum {
9288+ AuLsc_DI_CHILD, /* child first */
4a4d8108 9289+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */
1facf9fc 9290+ AuLsc_DI_CHILD3, /* copyup dirs */
9291+ AuLsc_DI_PARENT,
9292+ AuLsc_DI_PARENT2,
027c5e7a
AM
9293+ AuLsc_DI_PARENT3,
9294+ AuLsc_DI_TMP /* temp for replacing dinfo */
1facf9fc 9295+};
9296+
9297+/*
9298+ * di_read_lock_child, di_write_lock_child,
9299+ * di_read_lock_child2, di_write_lock_child2,
9300+ * di_read_lock_child3, di_write_lock_child3,
9301+ * di_read_lock_parent, di_write_lock_parent,
9302+ * di_read_lock_parent2, di_write_lock_parent2,
9303+ * di_read_lock_parent3, di_write_lock_parent3,
9304+ */
9305+#define AuReadLockFunc(name, lsc) \
9306+static inline void di_read_lock_##name(struct dentry *d, int flags) \
9307+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
9308+
9309+#define AuWriteLockFunc(name, lsc) \
9310+static inline void di_write_lock_##name(struct dentry *d) \
9311+{ di_write_lock(d, AuLsc_DI_##lsc); }
9312+
9313+#define AuRWLockFuncs(name, lsc) \
9314+ AuReadLockFunc(name, lsc) \
9315+ AuWriteLockFunc(name, lsc)
9316+
9317+AuRWLockFuncs(child, CHILD);
9318+AuRWLockFuncs(child2, CHILD2);
9319+AuRWLockFuncs(child3, CHILD3);
9320+AuRWLockFuncs(parent, PARENT);
9321+AuRWLockFuncs(parent2, PARENT2);
9322+AuRWLockFuncs(parent3, PARENT3);
9323+
9324+#undef AuReadLockFunc
9325+#undef AuWriteLockFunc
9326+#undef AuRWLockFuncs
9327+
9328+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
dece6358
AM
9329+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
9330+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
1facf9fc 9331+
9332+/* ---------------------------------------------------------------------- */
9333+
9334+/* todo: memory barrier? */
9335+static inline unsigned int au_digen(struct dentry *d)
9336+{
9337+ return atomic_read(&au_di(d)->di_generation);
9338+}
9339+
9340+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
9341+{
9342+ hdentry->hd_dentry = NULL;
9343+}
9344+
5afbbe0d
AM
9345+static inline struct au_hdentry *au_hdentry(struct au_dinfo *di,
9346+ aufs_bindex_t bindex)
9347+{
9348+ return di->di_hdentry + bindex;
9349+}
9350+
1facf9fc 9351+static inline void au_hdput(struct au_hdentry *hd)
9352+{
4a4d8108
AM
9353+ if (hd)
9354+ dput(hd->hd_dentry);
1facf9fc 9355+}
9356+
5afbbe0d 9357+static inline aufs_bindex_t au_dbtop(struct dentry *dentry)
1facf9fc 9358+{
1308ab2a 9359+ DiMustAnyLock(dentry);
5afbbe0d 9360+ return au_di(dentry)->di_btop;
1facf9fc 9361+}
9362+
5afbbe0d 9363+static inline aufs_bindex_t au_dbbot(struct dentry *dentry)
1facf9fc 9364+{
1308ab2a 9365+ DiMustAnyLock(dentry);
5afbbe0d 9366+ return au_di(dentry)->di_bbot;
1facf9fc 9367+}
9368+
9369+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
9370+{
1308ab2a 9371+ DiMustAnyLock(dentry);
1facf9fc 9372+ return au_di(dentry)->di_bwh;
9373+}
9374+
9375+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
9376+{
1308ab2a 9377+ DiMustAnyLock(dentry);
1facf9fc 9378+ return au_di(dentry)->di_bdiropq;
9379+}
9380+
9381+/* todo: hard/soft set? */
5afbbe0d 9382+static inline void au_set_dbtop(struct dentry *dentry, aufs_bindex_t bindex)
1facf9fc 9383+{
1308ab2a 9384+ DiMustWriteLock(dentry);
5afbbe0d 9385+ au_di(dentry)->di_btop = bindex;
1facf9fc 9386+}
9387+
5afbbe0d 9388+static inline void au_set_dbbot(struct dentry *dentry, aufs_bindex_t bindex)
1facf9fc 9389+{
1308ab2a 9390+ DiMustWriteLock(dentry);
5afbbe0d 9391+ au_di(dentry)->di_bbot = bindex;
1facf9fc 9392+}
9393+
9394+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
9395+{
1308ab2a 9396+ DiMustWriteLock(dentry);
5afbbe0d 9397+ /* dbwh can be outside of btop - bbot range */
1facf9fc 9398+ au_di(dentry)->di_bwh = bindex;
9399+}
9400+
9401+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
9402+{
1308ab2a 9403+ DiMustWriteLock(dentry);
1facf9fc 9404+ au_di(dentry)->di_bdiropq = bindex;
9405+}
9406+
9407+/* ---------------------------------------------------------------------- */
9408+
4a4d8108 9409+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 9410+static inline void au_digen_dec(struct dentry *d)
9411+{
e49829fe 9412+ atomic_dec(&au_di(d)->di_generation);
1facf9fc 9413+}
9414+
4a4d8108 9415+static inline void au_hn_di_reinit(struct dentry *dentry)
1facf9fc 9416+{
9417+ dentry->d_fsdata = NULL;
9418+}
9419+#else
4a4d8108
AM
9420+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
9421+#endif /* CONFIG_AUFS_HNOTIFY */
1facf9fc 9422+
9423+#endif /* __KERNEL__ */
9424+#endif /* __AUFS_DENTRY_H__ */
7f207e10 9425diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
eca34b5c 9426--- /usr/share/empty/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 9427+++ linux/fs/aufs/dinfo.c 2021-05-02 20:15:14.673337458 +0200
062440b3 9428@@ -0,0 +1,554 @@
cd7a4cd9 9429+// SPDX-License-Identifier: GPL-2.0
1facf9fc 9430+/*
d58c55f2 9431+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 9432+ *
9433+ * This program, aufs is free software; you can redistribute it and/or modify
9434+ * it under the terms of the GNU General Public License as published by
9435+ * the Free Software Foundation; either version 2 of the License, or
9436+ * (at your option) any later version.
dece6358
AM
9437+ *
9438+ * This program is distributed in the hope that it will be useful,
9439+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9440+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9441+ * GNU General Public License for more details.
9442+ *
9443+ * You should have received a copy of the GNU General Public License
523b37e3 9444+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 9445+ */
9446+
9447+/*
9448+ * dentry private data
9449+ */
9450+
9451+#include "aufs.h"
9452+
e49829fe 9453+void au_di_init_once(void *_dinfo)
4a4d8108 9454+{
e49829fe 9455+ struct au_dinfo *dinfo = _dinfo;
4a4d8108 9456+
e49829fe 9457+ au_rw_init(&dinfo->di_rwsem);
4a4d8108
AM
9458+}
9459+
027c5e7a 9460+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc)
1facf9fc 9461+{
9462+ struct au_dinfo *dinfo;
027c5e7a 9463+ int nbr, i;
1facf9fc 9464+
9465+ dinfo = au_cache_alloc_dinfo();
9466+ if (unlikely(!dinfo))
9467+ goto out;
9468+
5afbbe0d 9469+ nbr = au_sbbot(sb) + 1;
1facf9fc 9470+ if (nbr <= 0)
9471+ nbr = 1;
9472+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
027c5e7a
AM
9473+ if (dinfo->di_hdentry) {
9474+ au_rw_write_lock_nested(&dinfo->di_rwsem, lsc);
5afbbe0d
AM
9475+ dinfo->di_btop = -1;
9476+ dinfo->di_bbot = -1;
027c5e7a
AM
9477+ dinfo->di_bwh = -1;
9478+ dinfo->di_bdiropq = -1;
38d290e6 9479+ dinfo->di_tmpfile = 0;
027c5e7a
AM
9480+ for (i = 0; i < nbr; i++)
9481+ dinfo->di_hdentry[i].hd_id = -1;
9482+ goto out;
9483+ }
1facf9fc 9484+
1c60b727 9485+ au_cache_free_dinfo(dinfo);
027c5e7a
AM
9486+ dinfo = NULL;
9487+
4f0767ce 9488+out:
027c5e7a 9489+ return dinfo;
1facf9fc 9490+}
9491+
027c5e7a 9492+void au_di_free(struct au_dinfo *dinfo)
4a4d8108 9493+{
4a4d8108 9494+ struct au_hdentry *p;
5afbbe0d 9495+ aufs_bindex_t bbot, bindex;
4a4d8108
AM
9496+
9497+ /* dentry may not be revalidated */
5afbbe0d 9498+ bindex = dinfo->di_btop;
4a4d8108 9499+ if (bindex >= 0) {
5afbbe0d
AM
9500+ bbot = dinfo->di_bbot;
9501+ p = au_hdentry(dinfo, bindex);
9502+ while (bindex++ <= bbot)
4a4d8108
AM
9503+ au_hdput(p++);
9504+ }
9f237c51 9505+ au_kfree_try_rcu(dinfo->di_hdentry);
1c60b727 9506+ au_cache_free_dinfo(dinfo);
027c5e7a
AM
9507+}
9508+
9509+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b)
9510+{
9511+ struct au_hdentry *p;
9512+ aufs_bindex_t bi;
9513+
9514+ AuRwMustWriteLock(&a->di_rwsem);
9515+ AuRwMustWriteLock(&b->di_rwsem);
9516+
9517+#define DiSwap(v, name) \
9518+ do { \
9519+ v = a->di_##name; \
9520+ a->di_##name = b->di_##name; \
9521+ b->di_##name = v; \
9522+ } while (0)
9523+
9524+ DiSwap(p, hdentry);
5afbbe0d
AM
9525+ DiSwap(bi, btop);
9526+ DiSwap(bi, bbot);
027c5e7a
AM
9527+ DiSwap(bi, bwh);
9528+ DiSwap(bi, bdiropq);
9529+ /* smp_mb(); */
9530+
9531+#undef DiSwap
9532+}
9533+
9534+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src)
9535+{
9536+ AuRwMustWriteLock(&dst->di_rwsem);
9537+ AuRwMustWriteLock(&src->di_rwsem);
9538+
5afbbe0d
AM
9539+ dst->di_btop = src->di_btop;
9540+ dst->di_bbot = src->di_bbot;
027c5e7a
AM
9541+ dst->di_bwh = src->di_bwh;
9542+ dst->di_bdiropq = src->di_bdiropq;
9543+ /* smp_mb(); */
9544+}
9545+
9546+int au_di_init(struct dentry *dentry)
9547+{
9548+ int err;
9549+ struct super_block *sb;
9550+ struct au_dinfo *dinfo;
9551+
9552+ err = 0;
9553+ sb = dentry->d_sb;
9554+ dinfo = au_di_alloc(sb, AuLsc_DI_CHILD);
9555+ if (dinfo) {
9556+ atomic_set(&dinfo->di_generation, au_sigen(sb));
9557+ /* smp_mb(); */ /* atomic_set */
9558+ dentry->d_fsdata = dinfo;
9559+ } else
9560+ err = -ENOMEM;
9561+
9562+ return err;
9563+}
9564+
9565+void au_di_fin(struct dentry *dentry)
9566+{
9567+ struct au_dinfo *dinfo;
9568+
9569+ dinfo = au_di(dentry);
9570+ AuRwDestroy(&dinfo->di_rwsem);
9571+ au_di_free(dinfo);
4a4d8108
AM
9572+}
9573+
e2f27e51 9574+int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink)
1facf9fc 9575+{
9576+ int err, sz;
9577+ struct au_hdentry *hdp;
9578+
1308ab2a 9579+ AuRwMustWriteLock(&dinfo->di_rwsem);
9580+
1facf9fc 9581+ err = -ENOMEM;
5afbbe0d 9582+ sz = sizeof(*hdp) * (dinfo->di_bbot + 1);
1facf9fc 9583+ if (!sz)
9584+ sz = sizeof(*hdp);
e2f27e51
AM
9585+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS,
9586+ may_shrink);
1facf9fc 9587+ if (hdp) {
9588+ dinfo->di_hdentry = hdp;
9589+ err = 0;
9590+ }
9591+
9592+ return err;
9593+}
9594+
9595+/* ---------------------------------------------------------------------- */
9596+
9597+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
9598+{
9599+ switch (lsc) {
9600+ case AuLsc_DI_CHILD:
9601+ ii_write_lock_child(inode);
9602+ break;
9603+ case AuLsc_DI_CHILD2:
9604+ ii_write_lock_child2(inode);
9605+ break;
9606+ case AuLsc_DI_CHILD3:
9607+ ii_write_lock_child3(inode);
9608+ break;
9609+ case AuLsc_DI_PARENT:
9610+ ii_write_lock_parent(inode);
9611+ break;
9612+ case AuLsc_DI_PARENT2:
9613+ ii_write_lock_parent2(inode);
9614+ break;
9615+ case AuLsc_DI_PARENT3:
9616+ ii_write_lock_parent3(inode);
9617+ break;
9618+ default:
9619+ BUG();
9620+ }
9621+}
9622+
9623+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
9624+{
9625+ switch (lsc) {
9626+ case AuLsc_DI_CHILD:
9627+ ii_read_lock_child(inode);
9628+ break;
9629+ case AuLsc_DI_CHILD2:
9630+ ii_read_lock_child2(inode);
9631+ break;
9632+ case AuLsc_DI_CHILD3:
9633+ ii_read_lock_child3(inode);
9634+ break;
9635+ case AuLsc_DI_PARENT:
9636+ ii_read_lock_parent(inode);
9637+ break;
9638+ case AuLsc_DI_PARENT2:
9639+ ii_read_lock_parent2(inode);
9640+ break;
9641+ case AuLsc_DI_PARENT3:
9642+ ii_read_lock_parent3(inode);
9643+ break;
9644+ default:
9645+ BUG();
9646+ }
9647+}
9648+
9649+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
9650+{
5527c038
JR
9651+ struct inode *inode;
9652+
dece6358 9653+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
5527c038
JR
9654+ if (d_really_is_positive(d)) {
9655+ inode = d_inode(d);
1facf9fc 9656+ if (au_ftest_lock(flags, IW))
5527c038 9657+ do_ii_write_lock(inode, lsc);
1facf9fc 9658+ else if (au_ftest_lock(flags, IR))
5527c038 9659+ do_ii_read_lock(inode, lsc);
1facf9fc 9660+ }
9661+}
9662+
9663+void di_read_unlock(struct dentry *d, int flags)
9664+{
5527c038
JR
9665+ struct inode *inode;
9666+
9667+ if (d_really_is_positive(d)) {
9668+ inode = d_inode(d);
027c5e7a
AM
9669+ if (au_ftest_lock(flags, IW)) {
9670+ au_dbg_verify_dinode(d);
5527c038 9671+ ii_write_unlock(inode);
027c5e7a
AM
9672+ } else if (au_ftest_lock(flags, IR)) {
9673+ au_dbg_verify_dinode(d);
5527c038 9674+ ii_read_unlock(inode);
027c5e7a 9675+ }
1facf9fc 9676+ }
dece6358 9677+ au_rw_read_unlock(&au_di(d)->di_rwsem);
1facf9fc 9678+}
9679+
9680+void di_downgrade_lock(struct dentry *d, int flags)
9681+{
5527c038
JR
9682+ if (d_really_is_positive(d) && au_ftest_lock(flags, IR))
9683+ ii_downgrade_lock(d_inode(d));
dece6358 9684+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
1facf9fc 9685+}
9686+
9687+void di_write_lock(struct dentry *d, unsigned int lsc)
9688+{
dece6358 9689+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
5527c038
JR
9690+ if (d_really_is_positive(d))
9691+ do_ii_write_lock(d_inode(d), lsc);
1facf9fc 9692+}
9693+
9694+void di_write_unlock(struct dentry *d)
9695+{
027c5e7a 9696+ au_dbg_verify_dinode(d);
5527c038
JR
9697+ if (d_really_is_positive(d))
9698+ ii_write_unlock(d_inode(d));
dece6358 9699+ au_rw_write_unlock(&au_di(d)->di_rwsem);
1facf9fc 9700+}
9701+
9702+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
9703+{
9704+ AuDebugOn(d1 == d2
5527c038 9705+ || d_inode(d1) == d_inode(d2)
1facf9fc 9706+ || d1->d_sb != d2->d_sb);
9707+
521ced18
JR
9708+ if ((isdir && au_test_subdir(d1, d2))
9709+ || d1 < d2) {
1facf9fc 9710+ di_write_lock_child(d1);
9711+ di_write_lock_child2(d2);
9712+ } else {
1facf9fc 9713+ di_write_lock_child(d2);
9714+ di_write_lock_child2(d1);
9715+ }
9716+}
9717+
9718+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
9719+{
9720+ AuDebugOn(d1 == d2
5527c038 9721+ || d_inode(d1) == d_inode(d2)
1facf9fc 9722+ || d1->d_sb != d2->d_sb);
9723+
521ced18
JR
9724+ if ((isdir && au_test_subdir(d1, d2))
9725+ || d1 < d2) {
1facf9fc 9726+ di_write_lock_parent(d1);
9727+ di_write_lock_parent2(d2);
9728+ } else {
1facf9fc 9729+ di_write_lock_parent(d2);
9730+ di_write_lock_parent2(d1);
9731+ }
9732+}
9733+
9734+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
9735+{
9736+ di_write_unlock(d1);
5527c038 9737+ if (d_inode(d1) == d_inode(d2))
dece6358 9738+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
1facf9fc 9739+ else
9740+ di_write_unlock(d2);
9741+}
9742+
9743+/* ---------------------------------------------------------------------- */
9744+
9745+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
9746+{
9747+ struct dentry *d;
9748+
1308ab2a 9749+ DiMustAnyLock(dentry);
9750+
5afbbe0d 9751+ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry))
1facf9fc 9752+ return NULL;
9753+ AuDebugOn(bindex < 0);
5afbbe0d 9754+ d = au_hdentry(au_di(dentry), bindex)->hd_dentry;
c1595e42 9755+ AuDebugOn(d && au_dcount(d) <= 0);
1facf9fc 9756+ return d;
9757+}
9758+
2cbb1c4b
JR
9759+/*
9760+ * extended version of au_h_dptr().
38d290e6
JR
9761+ * returns a hashed and positive (or linkable) h_dentry in bindex, NULL, or
9762+ * error.
2cbb1c4b
JR
9763+ */
9764+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex)
9765+{
9766+ struct dentry *h_dentry;
9767+ struct inode *inode, *h_inode;
9768+
5527c038 9769+ AuDebugOn(d_really_is_negative(dentry));
2cbb1c4b
JR
9770+
9771+ h_dentry = NULL;
5afbbe0d
AM
9772+ if (au_dbtop(dentry) <= bindex
9773+ && bindex <= au_dbbot(dentry))
2cbb1c4b 9774+ h_dentry = au_h_dptr(dentry, bindex);
38d290e6 9775+ if (h_dentry && !au_d_linkable(h_dentry)) {
2cbb1c4b
JR
9776+ dget(h_dentry);
9777+ goto out; /* success */
9778+ }
9779+
5527c038 9780+ inode = d_inode(dentry);
5afbbe0d
AM
9781+ AuDebugOn(bindex < au_ibtop(inode));
9782+ AuDebugOn(au_ibbot(inode) < bindex);
2cbb1c4b
JR
9783+ h_inode = au_h_iptr(inode, bindex);
9784+ h_dentry = d_find_alias(h_inode);
9785+ if (h_dentry) {
9786+ if (!IS_ERR(h_dentry)) {
38d290e6 9787+ if (!au_d_linkable(h_dentry))
2cbb1c4b
JR
9788+ goto out; /* success */
9789+ dput(h_dentry);
9790+ } else
9791+ goto out;
9792+ }
9793+
9794+ if (au_opt_test(au_mntflags(dentry->d_sb), PLINK)) {
9795+ h_dentry = au_plink_lkup(inode, bindex);
9796+ AuDebugOn(!h_dentry);
9797+ if (!IS_ERR(h_dentry)) {
9798+ if (!au_d_hashed_positive(h_dentry))
9799+ goto out; /* success */
9800+ dput(h_dentry);
9801+ h_dentry = NULL;
9802+ }
9803+ }
9804+
9805+out:
9806+ AuDbgDentry(h_dentry);
9807+ return h_dentry;
9808+}
9809+
1facf9fc 9810+aufs_bindex_t au_dbtail(struct dentry *dentry)
9811+{
5afbbe0d 9812+ aufs_bindex_t bbot, bwh;
1facf9fc 9813+
5afbbe0d
AM
9814+ bbot = au_dbbot(dentry);
9815+ if (0 <= bbot) {
1facf9fc 9816+ bwh = au_dbwh(dentry);
9817+ if (!bwh)
9818+ return bwh;
5afbbe0d 9819+ if (0 < bwh && bwh < bbot)
1facf9fc 9820+ return bwh - 1;
9821+ }
5afbbe0d 9822+ return bbot;
1facf9fc 9823+}
9824+
9825+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
9826+{
5afbbe0d 9827+ aufs_bindex_t bbot, bopq;
1facf9fc 9828+
5afbbe0d
AM
9829+ bbot = au_dbtail(dentry);
9830+ if (0 <= bbot) {
1facf9fc 9831+ bopq = au_dbdiropq(dentry);
5afbbe0d
AM
9832+ if (0 <= bopq && bopq < bbot)
9833+ bbot = bopq;
1facf9fc 9834+ }
5afbbe0d 9835+ return bbot;
1facf9fc 9836+}
9837+
9838+/* ---------------------------------------------------------------------- */
9839+
9840+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
9841+ struct dentry *h_dentry)
9842+{
5afbbe0d
AM
9843+ struct au_dinfo *dinfo;
9844+ struct au_hdentry *hd;
027c5e7a 9845+ struct au_branch *br;
1facf9fc 9846+
1308ab2a 9847+ DiMustWriteLock(dentry);
9848+
5afbbe0d
AM
9849+ dinfo = au_di(dentry);
9850+ hd = au_hdentry(dinfo, bindex);
4a4d8108 9851+ au_hdput(hd);
1facf9fc 9852+ hd->hd_dentry = h_dentry;
027c5e7a
AM
9853+ if (h_dentry) {
9854+ br = au_sbr(dentry->d_sb, bindex);
9855+ hd->hd_id = br->br_id;
9856+ }
9857+}
9858+
9859+int au_dbrange_test(struct dentry *dentry)
9860+{
9861+ int err;
5afbbe0d 9862+ aufs_bindex_t btop, bbot;
027c5e7a
AM
9863+
9864+ err = 0;
5afbbe0d
AM
9865+ btop = au_dbtop(dentry);
9866+ bbot = au_dbbot(dentry);
9867+ if (btop >= 0)
9868+ AuDebugOn(bbot < 0 && btop > bbot);
027c5e7a
AM
9869+ else {
9870+ err = -EIO;
5afbbe0d 9871+ AuDebugOn(bbot >= 0);
027c5e7a
AM
9872+ }
9873+
9874+ return err;
9875+}
9876+
9877+int au_digen_test(struct dentry *dentry, unsigned int sigen)
9878+{
9879+ int err;
9880+
9881+ err = 0;
9882+ if (unlikely(au_digen(dentry) != sigen
5527c038 9883+ || au_iigen_test(d_inode(dentry), sigen)))
027c5e7a
AM
9884+ err = -EIO;
9885+
9886+ return err;
1facf9fc 9887+}
9888+
9889+void au_update_digen(struct dentry *dentry)
9890+{
9891+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
9892+ /* smp_mb(); */ /* atomic_set */
9893+}
9894+
9895+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
9896+{
9897+ struct au_dinfo *dinfo;
9898+ struct dentry *h_d;
4a4d8108 9899+ struct au_hdentry *hdp;
5afbbe0d 9900+ aufs_bindex_t bindex, bbot;
1facf9fc 9901+
1308ab2a 9902+ DiMustWriteLock(dentry);
9903+
1facf9fc 9904+ dinfo = au_di(dentry);
5afbbe0d 9905+ if (!dinfo || dinfo->di_btop < 0)
1facf9fc 9906+ return;
9907+
9908+ if (do_put_zero) {
5afbbe0d
AM
9909+ bbot = dinfo->di_bbot;
9910+ bindex = dinfo->di_btop;
9911+ hdp = au_hdentry(dinfo, bindex);
9912+ for (; bindex <= bbot; bindex++, hdp++) {
9913+ h_d = hdp->hd_dentry;
5527c038 9914+ if (h_d && d_is_negative(h_d))
1facf9fc 9915+ au_set_h_dptr(dentry, bindex, NULL);
9916+ }
9917+ }
9918+
5afbbe0d
AM
9919+ dinfo->di_btop = 0;
9920+ hdp = au_hdentry(dinfo, dinfo->di_btop);
9921+ for (; dinfo->di_btop <= dinfo->di_bbot; dinfo->di_btop++, hdp++)
9922+ if (hdp->hd_dentry)
1facf9fc 9923+ break;
5afbbe0d
AM
9924+ if (dinfo->di_btop > dinfo->di_bbot) {
9925+ dinfo->di_btop = -1;
9926+ dinfo->di_bbot = -1;
1facf9fc 9927+ return;
9928+ }
9929+
5afbbe0d
AM
9930+ hdp = au_hdentry(dinfo, dinfo->di_bbot);
9931+ for (; dinfo->di_bbot >= 0; dinfo->di_bbot--, hdp--)
9932+ if (hdp->hd_dentry)
1facf9fc 9933+ break;
5afbbe0d 9934+ AuDebugOn(dinfo->di_btop > dinfo->di_bbot || dinfo->di_bbot < 0);
1facf9fc 9935+}
9936+
5afbbe0d 9937+void au_update_dbtop(struct dentry *dentry)
1facf9fc 9938+{
5afbbe0d 9939+ aufs_bindex_t bindex, bbot;
1facf9fc 9940+ struct dentry *h_dentry;
9941+
5afbbe0d
AM
9942+ bbot = au_dbbot(dentry);
9943+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) {
1facf9fc 9944+ h_dentry = au_h_dptr(dentry, bindex);
9945+ if (!h_dentry)
9946+ continue;
5527c038 9947+ if (d_is_positive(h_dentry)) {
5afbbe0d 9948+ au_set_dbtop(dentry, bindex);
1facf9fc 9949+ return;
9950+ }
9951+ au_set_h_dptr(dentry, bindex, NULL);
9952+ }
9953+}
9954+
5afbbe0d 9955+void au_update_dbbot(struct dentry *dentry)
1facf9fc 9956+{
5afbbe0d 9957+ aufs_bindex_t bindex, btop;
1facf9fc 9958+ struct dentry *h_dentry;
9959+
5afbbe0d
AM
9960+ btop = au_dbtop(dentry);
9961+ for (bindex = au_dbbot(dentry); bindex >= btop; bindex--) {
1facf9fc 9962+ h_dentry = au_h_dptr(dentry, bindex);
9963+ if (!h_dentry)
9964+ continue;
5527c038 9965+ if (d_is_positive(h_dentry)) {
5afbbe0d 9966+ au_set_dbbot(dentry, bindex);
1facf9fc 9967+ return;
9968+ }
9969+ au_set_h_dptr(dentry, bindex, NULL);
9970+ }
9971+}
9972+
9973+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
9974+{
5afbbe0d 9975+ aufs_bindex_t bindex, bbot;
1facf9fc 9976+
5afbbe0d
AM
9977+ bbot = au_dbbot(dentry);
9978+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++)
1facf9fc 9979+ if (au_h_dptr(dentry, bindex) == h_dentry)
9980+ return bindex;
9981+ return -1;
9982+}
7f207e10 9983diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
eca34b5c 9984--- /usr/share/empty/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6
JR
9985+++ linux/fs/aufs/dir.c 2021-05-02 20:15:14.673337458 +0200
9986@@ -0,0 +1,765 @@
cd7a4cd9 9987+// SPDX-License-Identifier: GPL-2.0
1facf9fc 9988+/*
d58c55f2 9989+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 9990+ *
9991+ * This program, aufs is free software; you can redistribute it and/or modify
9992+ * it under the terms of the GNU General Public License as published by
9993+ * the Free Software Foundation; either version 2 of the License, or
9994+ * (at your option) any later version.
dece6358
AM
9995+ *
9996+ * This program is distributed in the hope that it will be useful,
9997+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9998+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9999+ * GNU General Public License for more details.
10000+ *
10001+ * You should have received a copy of the GNU General Public License
523b37e3 10002+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 10003+ */
10004+
10005+/*
10006+ * directory operations
10007+ */
10008+
10009+#include <linux/fs_stack.h>
eca801bf 10010+#include <linux/iversion.h>
1facf9fc 10011+#include "aufs.h"
10012+
10013+void au_add_nlink(struct inode *dir, struct inode *h_dir)
10014+{
9dbd164d
AM
10015+ unsigned int nlink;
10016+
1facf9fc 10017+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
10018+
9dbd164d
AM
10019+ nlink = dir->i_nlink;
10020+ nlink += h_dir->i_nlink - 2;
1facf9fc 10021+ if (h_dir->i_nlink < 2)
9dbd164d 10022+ nlink += 2;
f6b6e03d 10023+ smp_mb(); /* for i_nlink */
7eafdf33 10024+ /* 0 can happen in revaliding */
92d182d2 10025+ set_nlink(dir, nlink);
1facf9fc 10026+}
10027+
10028+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
10029+{
9dbd164d
AM
10030+ unsigned int nlink;
10031+
1facf9fc 10032+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
10033+
9dbd164d
AM
10034+ nlink = dir->i_nlink;
10035+ nlink -= h_dir->i_nlink - 2;
1facf9fc 10036+ if (h_dir->i_nlink < 2)
9dbd164d 10037+ nlink -= 2;
f6b6e03d 10038+ smp_mb(); /* for i_nlink */
92d182d2 10039+ /* nlink == 0 means the branch-fs is broken */
9dbd164d 10040+ set_nlink(dir, nlink);
1facf9fc 10041+}
10042+
1308ab2a 10043+loff_t au_dir_size(struct file *file, struct dentry *dentry)
10044+{
10045+ loff_t sz;
5afbbe0d 10046+ aufs_bindex_t bindex, bbot;
1308ab2a 10047+ struct file *h_file;
10048+ struct dentry *h_dentry;
10049+
10050+ sz = 0;
10051+ if (file) {
2000de60 10052+ AuDebugOn(!d_is_dir(file->f_path.dentry));
1308ab2a 10053+
5afbbe0d
AM
10054+ bbot = au_fbbot_dir(file);
10055+ for (bindex = au_fbtop(file);
10056+ bindex <= bbot && sz < KMALLOC_MAX_SIZE;
1308ab2a 10057+ bindex++) {
4a4d8108 10058+ h_file = au_hf_dir(file, bindex);
c06a8ce3
AM
10059+ if (h_file && file_inode(h_file))
10060+ sz += vfsub_f_size_read(h_file);
1308ab2a 10061+ }
10062+ } else {
10063+ AuDebugOn(!dentry);
2000de60 10064+ AuDebugOn(!d_is_dir(dentry));
1308ab2a 10065+
5afbbe0d
AM
10066+ bbot = au_dbtaildir(dentry);
10067+ for (bindex = au_dbtop(dentry);
10068+ bindex <= bbot && sz < KMALLOC_MAX_SIZE;
1308ab2a 10069+ bindex++) {
10070+ h_dentry = au_h_dptr(dentry, bindex);
5527c038
JR
10071+ if (h_dentry && d_is_positive(h_dentry))
10072+ sz += i_size_read(d_inode(h_dentry));
1308ab2a 10073+ }
10074+ }
10075+ if (sz < KMALLOC_MAX_SIZE)
10076+ sz = roundup_pow_of_two(sz);
10077+ if (sz > KMALLOC_MAX_SIZE)
10078+ sz = KMALLOC_MAX_SIZE;
10079+ else if (sz < NAME_MAX) {
10080+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
10081+ sz = AUFS_RDBLK_DEF;
10082+ }
10083+ return sz;
10084+}
10085+
b912730e
AM
10086+struct au_dir_ts_arg {
10087+ struct dentry *dentry;
10088+ aufs_bindex_t brid;
10089+};
10090+
10091+static void au_do_dir_ts(void *arg)
10092+{
10093+ struct au_dir_ts_arg *a = arg;
10094+ struct au_dtime dt;
10095+ struct path h_path;
10096+ struct inode *dir, *h_dir;
10097+ struct super_block *sb;
10098+ struct au_branch *br;
10099+ struct au_hinode *hdir;
10100+ int err;
5afbbe0d 10101+ aufs_bindex_t btop, bindex;
b912730e
AM
10102+
10103+ sb = a->dentry->d_sb;
5527c038 10104+ if (d_really_is_negative(a->dentry))
b912730e 10105+ goto out;
5527c038 10106+ /* no dir->i_mutex lock */
b95c5147
AM
10107+ aufs_read_lock(a->dentry, AuLock_DW); /* noflush */
10108+
5527c038 10109+ dir = d_inode(a->dentry);
5afbbe0d 10110+ btop = au_ibtop(dir);
b912730e 10111+ bindex = au_br_index(sb, a->brid);
5afbbe0d 10112+ if (bindex < btop)
b912730e
AM
10113+ goto out_unlock;
10114+
10115+ br = au_sbr(sb, bindex);
10116+ h_path.dentry = au_h_dptr(a->dentry, bindex);
10117+ if (!h_path.dentry)
10118+ goto out_unlock;
10119+ h_path.mnt = au_br_mnt(br);
10120+ au_dtime_store(&dt, a->dentry, &h_path);
10121+
5afbbe0d 10122+ br = au_sbr(sb, btop);
b912730e
AM
10123+ if (!au_br_writable(br->br_perm))
10124+ goto out_unlock;
5afbbe0d 10125+ h_path.dentry = au_h_dptr(a->dentry, btop);
b912730e
AM
10126+ h_path.mnt = au_br_mnt(br);
10127+ err = vfsub_mnt_want_write(h_path.mnt);
10128+ if (err)
10129+ goto out_unlock;
5afbbe0d
AM
10130+ hdir = au_hi(dir, btop);
10131+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
10132+ h_dir = au_h_iptr(dir, btop);
b912730e 10133+ if (h_dir->i_nlink
cd7a4cd9 10134+ && timespec64_compare(&h_dir->i_mtime, &dt.dt_mtime) < 0) {
b912730e
AM
10135+ dt.dt_h_path = h_path;
10136+ au_dtime_revert(&dt);
10137+ }
5afbbe0d 10138+ au_hn_inode_unlock(hdir);
b912730e
AM
10139+ vfsub_mnt_drop_write(h_path.mnt);
10140+ au_cpup_attr_timesizes(dir);
10141+
10142+out_unlock:
10143+ aufs_read_unlock(a->dentry, AuLock_DW);
10144+out:
10145+ dput(a->dentry);
10146+ au_nwt_done(&au_sbi(sb)->si_nowait);
9f237c51 10147+ au_kfree_try_rcu(arg);
b912730e
AM
10148+}
10149+
10150+void au_dir_ts(struct inode *dir, aufs_bindex_t bindex)
10151+{
10152+ int perm, wkq_err;
5afbbe0d 10153+ aufs_bindex_t btop;
b912730e
AM
10154+ struct au_dir_ts_arg *arg;
10155+ struct dentry *dentry;
10156+ struct super_block *sb;
10157+
10158+ IMustLock(dir);
10159+
10160+ dentry = d_find_any_alias(dir);
10161+ AuDebugOn(!dentry);
10162+ sb = dentry->d_sb;
5afbbe0d
AM
10163+ btop = au_ibtop(dir);
10164+ if (btop == bindex) {
b912730e
AM
10165+ au_cpup_attr_timesizes(dir);
10166+ goto out;
10167+ }
10168+
5afbbe0d 10169+ perm = au_sbr_perm(sb, btop);
b912730e
AM
10170+ if (!au_br_writable(perm))
10171+ goto out;
10172+
10173+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
10174+ if (!arg)
10175+ goto out;
10176+
10177+ arg->dentry = dget(dentry); /* will be dput-ted by au_do_dir_ts() */
10178+ arg->brid = au_sbr_id(sb, bindex);
10179+ wkq_err = au_wkq_nowait(au_do_dir_ts, arg, sb, /*flags*/0);
10180+ if (unlikely(wkq_err)) {
10181+ pr_err("wkq %d\n", wkq_err);
10182+ dput(dentry);
9f237c51 10183+ au_kfree_try_rcu(arg);
b912730e
AM
10184+ }
10185+
10186+out:
10187+ dput(dentry);
10188+}
10189+
1facf9fc 10190+/* ---------------------------------------------------------------------- */
10191+
10192+static int reopen_dir(struct file *file)
10193+{
10194+ int err;
10195+ unsigned int flags;
5afbbe0d 10196+ aufs_bindex_t bindex, btail, btop;
1facf9fc 10197+ struct dentry *dentry, *h_dentry;
10198+ struct file *h_file;
10199+
10200+ /* open all lower dirs */
2000de60 10201+ dentry = file->f_path.dentry;
5afbbe0d
AM
10202+ btop = au_dbtop(dentry);
10203+ for (bindex = au_fbtop(file); bindex < btop; bindex++)
1facf9fc 10204+ au_set_h_fptr(file, bindex, NULL);
5afbbe0d 10205+ au_set_fbtop(file, btop);
1facf9fc 10206+
10207+ btail = au_dbtaildir(dentry);
5afbbe0d 10208+ for (bindex = au_fbbot_dir(file); btail < bindex; bindex--)
1facf9fc 10209+ au_set_h_fptr(file, bindex, NULL);
5afbbe0d 10210+ au_set_fbbot_dir(file, btail);
1facf9fc 10211+
4a4d8108 10212+ flags = vfsub_file_flags(file);
5afbbe0d 10213+ for (bindex = btop; bindex <= btail; bindex++) {
1facf9fc 10214+ h_dentry = au_h_dptr(dentry, bindex);
10215+ if (!h_dentry)
10216+ continue;
4a4d8108 10217+ h_file = au_hf_dir(file, bindex);
1facf9fc 10218+ if (h_file)
10219+ continue;
10220+
392086de 10221+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0);
1facf9fc 10222+ err = PTR_ERR(h_file);
10223+ if (IS_ERR(h_file))
10224+ goto out; /* close all? */
10225+ au_set_h_fptr(file, bindex, h_file);
10226+ }
10227+ au_update_figen(file);
10228+ /* todo: necessary? */
10229+ /* file->f_ra = h_file->f_ra; */
10230+ err = 0;
10231+
4f0767ce 10232+out:
1facf9fc 10233+ return err;
10234+}
10235+
b912730e 10236+static int do_open_dir(struct file *file, int flags, struct file *h_file)
1facf9fc 10237+{
10238+ int err;
10239+ aufs_bindex_t bindex, btail;
10240+ struct dentry *dentry, *h_dentry;
8cdd5066 10241+ struct vfsmount *mnt;
1facf9fc 10242+
1308ab2a 10243+ FiMustWriteLock(file);
b912730e 10244+ AuDebugOn(h_file);
1308ab2a 10245+
523b37e3 10246+ err = 0;
8cdd5066 10247+ mnt = file->f_path.mnt;
2000de60 10248+ dentry = file->f_path.dentry;
be118d29 10249+ file->f_version = inode_query_iversion(d_inode(dentry));
5afbbe0d
AM
10250+ bindex = au_dbtop(dentry);
10251+ au_set_fbtop(file, bindex);
1facf9fc 10252+ btail = au_dbtaildir(dentry);
5afbbe0d 10253+ au_set_fbbot_dir(file, btail);
1facf9fc 10254+ for (; !err && bindex <= btail; bindex++) {
10255+ h_dentry = au_h_dptr(dentry, bindex);
10256+ if (!h_dentry)
10257+ continue;
10258+
8cdd5066
JR
10259+ err = vfsub_test_mntns(mnt, h_dentry->d_sb);
10260+ if (unlikely(err))
10261+ break;
392086de 10262+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0);
1facf9fc 10263+ if (IS_ERR(h_file)) {
10264+ err = PTR_ERR(h_file);
10265+ break;
10266+ }
10267+ au_set_h_fptr(file, bindex, h_file);
10268+ }
10269+ au_update_figen(file);
10270+ /* todo: necessary? */
10271+ /* file->f_ra = h_file->f_ra; */
10272+ if (!err)
10273+ return 0; /* success */
10274+
10275+ /* close all */
5afbbe0d 10276+ for (bindex = au_fbtop(file); bindex <= btail; bindex++)
1facf9fc 10277+ au_set_h_fptr(file, bindex, NULL);
5afbbe0d
AM
10278+ au_set_fbtop(file, -1);
10279+ au_set_fbbot_dir(file, -1);
4a4d8108 10280+
1facf9fc 10281+ return err;
10282+}
10283+
10284+static int aufs_open_dir(struct inode *inode __maybe_unused,
10285+ struct file *file)
10286+{
4a4d8108
AM
10287+ int err;
10288+ struct super_block *sb;
10289+ struct au_fidir *fidir;
10290+
10291+ err = -ENOMEM;
2000de60 10292+ sb = file->f_path.dentry->d_sb;
4a4d8108 10293+ si_read_lock(sb, AuLock_FLUSH);
e49829fe 10294+ fidir = au_fidir_alloc(sb);
4a4d8108 10295+ if (fidir) {
b912730e
AM
10296+ struct au_do_open_args args = {
10297+ .open = do_open_dir,
10298+ .fidir = fidir
10299+ };
10300+ err = au_do_open(file, &args);
4a4d8108 10301+ if (unlikely(err))
9f237c51 10302+ au_kfree_rcu(fidir);
4a4d8108
AM
10303+ }
10304+ si_read_unlock(sb);
10305+ return err;
1facf9fc 10306+}
10307+
10308+static int aufs_release_dir(struct inode *inode __maybe_unused,
10309+ struct file *file)
10310+{
10311+ struct au_vdir *vdir_cache;
4a4d8108
AM
10312+ struct au_finfo *finfo;
10313+ struct au_fidir *fidir;
f0c0a007 10314+ struct au_hfile *hf;
5afbbe0d 10315+ aufs_bindex_t bindex, bbot;
1facf9fc 10316+
4a4d8108
AM
10317+ finfo = au_fi(file);
10318+ fidir = finfo->fi_hdir;
10319+ if (fidir) {
8b6a4947
AM
10320+ au_hbl_del(&finfo->fi_hlist,
10321+ &au_sbi(file->f_path.dentry->d_sb)->si_files);
4a4d8108
AM
10322+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */
10323+ if (vdir_cache)
1c60b727 10324+ au_vdir_free(vdir_cache);
4a4d8108
AM
10325+
10326+ bindex = finfo->fi_btop;
10327+ if (bindex >= 0) {
f0c0a007 10328+ hf = fidir->fd_hfile + bindex;
4a4d8108
AM
10329+ /*
10330+ * calls fput() instead of filp_close(),
10331+ * since no dnotify or lock for the lower file.
10332+ */
5afbbe0d 10333+ bbot = fidir->fd_bbot;
f0c0a007
AM
10334+ for (; bindex <= bbot; bindex++, hf++)
10335+ if (hf->hf_file)
1c60b727 10336+ au_hfput(hf, /*execed*/0);
4a4d8108 10337+ }
9f237c51 10338+ au_kfree_rcu(fidir);
4a4d8108 10339+ finfo->fi_hdir = NULL;
1facf9fc 10340+ }
1c60b727 10341+ au_finfo_fin(file);
1facf9fc 10342+ return 0;
10343+}
10344+
10345+/* ---------------------------------------------------------------------- */
10346+
4a4d8108
AM
10347+static int au_do_flush_dir(struct file *file, fl_owner_t id)
10348+{
10349+ int err;
5afbbe0d 10350+ aufs_bindex_t bindex, bbot;
4a4d8108
AM
10351+ struct file *h_file;
10352+
10353+ err = 0;
5afbbe0d
AM
10354+ bbot = au_fbbot_dir(file);
10355+ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) {
4a4d8108
AM
10356+ h_file = au_hf_dir(file, bindex);
10357+ if (h_file)
10358+ err = vfsub_flush(h_file, id);
10359+ }
10360+ return err;
10361+}
10362+
10363+static int aufs_flush_dir(struct file *file, fl_owner_t id)
10364+{
10365+ return au_do_flush(file, id, au_do_flush_dir);
10366+}
10367+
10368+/* ---------------------------------------------------------------------- */
10369+
1facf9fc 10370+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
10371+{
10372+ int err;
5afbbe0d 10373+ aufs_bindex_t bbot, bindex;
1facf9fc 10374+ struct inode *inode;
10375+ struct super_block *sb;
10376+
10377+ err = 0;
10378+ sb = dentry->d_sb;
5527c038 10379+ inode = d_inode(dentry);
1facf9fc 10380+ IMustLock(inode);
5afbbe0d
AM
10381+ bbot = au_dbbot(dentry);
10382+ for (bindex = au_dbtop(dentry); !err && bindex <= bbot; bindex++) {
1facf9fc 10383+ struct path h_path;
1facf9fc 10384+
10385+ if (au_test_ro(sb, bindex, inode))
10386+ continue;
10387+ h_path.dentry = au_h_dptr(dentry, bindex);
10388+ if (!h_path.dentry)
10389+ continue;
1facf9fc 10390+
1facf9fc 10391+ h_path.mnt = au_sbr_mnt(sb, bindex);
53392da6 10392+ err = vfsub_fsync(NULL, &h_path, datasync);
1facf9fc 10393+ }
10394+
10395+ return err;
10396+}
10397+
10398+static int au_do_fsync_dir(struct file *file, int datasync)
10399+{
10400+ int err;
5afbbe0d 10401+ aufs_bindex_t bbot, bindex;
1facf9fc 10402+ struct file *h_file;
10403+ struct super_block *sb;
10404+ struct inode *inode;
1facf9fc 10405+
521ced18 10406+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0);
1facf9fc 10407+ if (unlikely(err))
10408+ goto out;
10409+
c06a8ce3 10410+ inode = file_inode(file);
b912730e 10411+ sb = inode->i_sb;
5afbbe0d
AM
10412+ bbot = au_fbbot_dir(file);
10413+ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) {
4a4d8108 10414+ h_file = au_hf_dir(file, bindex);
1facf9fc 10415+ if (!h_file || au_test_ro(sb, bindex, inode))
10416+ continue;
10417+
53392da6 10418+ err = vfsub_fsync(h_file, &h_file->f_path, datasync);
1facf9fc 10419+ }
10420+
4f0767ce 10421+out:
1facf9fc 10422+ return err;
10423+}
10424+
10425+/*
10426+ * @file may be NULL
10427+ */
1e00d052
AM
10428+static int aufs_fsync_dir(struct file *file, loff_t start, loff_t end,
10429+ int datasync)
1facf9fc 10430+{
10431+ int err;
b752ccd1 10432+ struct dentry *dentry;
5527c038 10433+ struct inode *inode;
1facf9fc 10434+ struct super_block *sb;
1facf9fc 10435+
10436+ err = 0;
2000de60 10437+ dentry = file->f_path.dentry;
5527c038 10438+ inode = d_inode(dentry);
febd17d6 10439+ inode_lock(inode);
1facf9fc 10440+ sb = dentry->d_sb;
10441+ si_noflush_read_lock(sb);
10442+ if (file)
10443+ err = au_do_fsync_dir(file, datasync);
10444+ else {
10445+ di_write_lock_child(dentry);
10446+ err = au_do_fsync_dir_no_file(dentry, datasync);
10447+ }
5527c038 10448+ au_cpup_attr_timesizes(inode);
1facf9fc 10449+ di_write_unlock(dentry);
10450+ if (file)
10451+ fi_write_unlock(file);
10452+
10453+ si_read_unlock(sb);
febd17d6 10454+ inode_unlock(inode);
1facf9fc 10455+ return err;
10456+}
10457+
10458+/* ---------------------------------------------------------------------- */
10459+
5afbbe0d 10460+static int aufs_iterate_shared(struct file *file, struct dir_context *ctx)
1facf9fc 10461+{
10462+ int err;
10463+ struct dentry *dentry;
9dbd164d 10464+ struct inode *inode, *h_inode;
1facf9fc 10465+ struct super_block *sb;
10466+
062440b3 10467+ AuDbg("%pD, ctx{%ps, %llu}\n", file, ctx->actor, ctx->pos);
392086de 10468+
2000de60 10469+ dentry = file->f_path.dentry;
5527c038 10470+ inode = d_inode(dentry);
1facf9fc 10471+ IMustLock(inode);
10472+
10473+ sb = dentry->d_sb;
10474+ si_read_lock(sb, AuLock_FLUSH);
521ced18 10475+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0);
1facf9fc 10476+ if (unlikely(err))
10477+ goto out;
027c5e7a
AM
10478+ err = au_alive_dir(dentry);
10479+ if (!err)
10480+ err = au_vdir_init(file);
1facf9fc 10481+ di_downgrade_lock(dentry, AuLock_IR);
10482+ if (unlikely(err))
10483+ goto out_unlock;
10484+
5afbbe0d 10485+ h_inode = au_h_iptr(inode, au_ibtop(inode));
b752ccd1 10486+ if (!au_test_nfsd()) {
392086de 10487+ err = au_vdir_fill_de(file, ctx);
9dbd164d 10488+ fsstack_copy_attr_atime(inode, h_inode);
1facf9fc 10489+ } else {
10490+ /*
10491+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
10492+ * encode_fh() and others.
10493+ */
9dbd164d 10494+ atomic_inc(&h_inode->i_count);
1facf9fc 10495+ di_read_unlock(dentry, AuLock_IR);
10496+ si_read_unlock(sb);
392086de 10497+ err = au_vdir_fill_de(file, ctx);
1facf9fc 10498+ fsstack_copy_attr_atime(inode, h_inode);
10499+ fi_write_unlock(file);
9dbd164d 10500+ iput(h_inode);
1facf9fc 10501+
10502+ AuTraceErr(err);
10503+ return err;
10504+ }
10505+
4f0767ce 10506+out_unlock:
1facf9fc 10507+ di_read_unlock(dentry, AuLock_IR);
10508+ fi_write_unlock(file);
4f0767ce 10509+out:
1facf9fc 10510+ si_read_unlock(sb);
10511+ return err;
10512+}
10513+
10514+/* ---------------------------------------------------------------------- */
10515+
10516+#define AuTestEmpty_WHONLY 1
dece6358
AM
10517+#define AuTestEmpty_CALLED (1 << 1)
10518+#define AuTestEmpty_SHWH (1 << 2)
1facf9fc 10519+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
7f207e10
AM
10520+#define au_fset_testempty(flags, name) \
10521+ do { (flags) |= AuTestEmpty_##name; } while (0)
10522+#define au_fclr_testempty(flags, name) \
10523+ do { (flags) &= ~AuTestEmpty_##name; } while (0)
1facf9fc 10524+
dece6358
AM
10525+#ifndef CONFIG_AUFS_SHWH
10526+#undef AuTestEmpty_SHWH
10527+#define AuTestEmpty_SHWH 0
10528+#endif
10529+
1facf9fc 10530+struct test_empty_arg {
392086de 10531+ struct dir_context ctx;
1308ab2a 10532+ struct au_nhash *whlist;
1facf9fc 10533+ unsigned int flags;
10534+ int err;
10535+ aufs_bindex_t bindex;
10536+};
10537+
392086de
AM
10538+static int test_empty_cb(struct dir_context *ctx, const char *__name,
10539+ int namelen, loff_t offset __maybe_unused, u64 ino,
dece6358 10540+ unsigned int d_type)
1facf9fc 10541+{
392086de
AM
10542+ struct test_empty_arg *arg = container_of(ctx, struct test_empty_arg,
10543+ ctx);
1facf9fc 10544+ char *name = (void *)__name;
10545+
10546+ arg->err = 0;
10547+ au_fset_testempty(arg->flags, CALLED);
10548+ /* smp_mb(); */
10549+ if (name[0] == '.'
10550+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
10551+ goto out; /* success */
10552+
10553+ if (namelen <= AUFS_WH_PFX_LEN
10554+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
10555+ if (au_ftest_testempty(arg->flags, WHONLY)
1308ab2a 10556+ && !au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 10557+ arg->err = -ENOTEMPTY;
10558+ goto out;
10559+ }
10560+
10561+ name += AUFS_WH_PFX_LEN;
10562+ namelen -= AUFS_WH_PFX_LEN;
1308ab2a 10563+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 10564+ arg->err = au_nhash_append_wh
1308ab2a 10565+ (arg->whlist, name, namelen, ino, d_type, arg->bindex,
dece6358 10566+ au_ftest_testempty(arg->flags, SHWH));
1facf9fc 10567+
4f0767ce 10568+out:
1facf9fc 10569+ /* smp_mb(); */
10570+ AuTraceErr(arg->err);
10571+ return arg->err;
10572+}
10573+
10574+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
10575+{
10576+ int err;
10577+ struct file *h_file;
acd2b654 10578+ struct au_branch *br;
1facf9fc 10579+
10580+ h_file = au_h_open(dentry, arg->bindex,
10581+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
392086de 10582+ /*file*/NULL, /*force_wr*/0);
1facf9fc 10583+ err = PTR_ERR(h_file);
10584+ if (IS_ERR(h_file))
10585+ goto out;
10586+
10587+ err = 0;
10588+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
c06a8ce3 10589+ && !file_inode(h_file)->i_nlink)
1facf9fc 10590+ goto out_put;
10591+
10592+ do {
10593+ arg->err = 0;
10594+ au_fclr_testempty(arg->flags, CALLED);
10595+ /* smp_mb(); */
392086de 10596+ err = vfsub_iterate_dir(h_file, &arg->ctx);
1facf9fc 10597+ if (err >= 0)
10598+ err = arg->err;
10599+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
10600+
4f0767ce 10601+out_put:
1facf9fc 10602+ fput(h_file);
acd2b654
AM
10603+ br = au_sbr(dentry->d_sb, arg->bindex);
10604+ au_lcnt_dec(&br->br_nfiles);
4f0767ce 10605+out:
1facf9fc 10606+ return err;
10607+}
10608+
10609+struct do_test_empty_args {
10610+ int *errp;
10611+ struct dentry *dentry;
10612+ struct test_empty_arg *arg;
10613+};
10614+
10615+static void call_do_test_empty(void *args)
10616+{
10617+ struct do_test_empty_args *a = args;
10618+ *a->errp = do_test_empty(a->dentry, a->arg);
10619+}
10620+
10621+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
10622+{
10623+ int err, wkq_err;
10624+ struct dentry *h_dentry;
10625+ struct inode *h_inode;
0b2a12c6 10626+ struct user_namespace *h_userns;
1facf9fc 10627+
0b2a12c6 10628+ h_userns = au_sbr_userns(dentry->d_sb, arg->bindex);
1facf9fc 10629+ h_dentry = au_h_dptr(dentry, arg->bindex);
5527c038 10630+ h_inode = d_inode(h_dentry);
53392da6 10631+ /* todo: i_mode changes anytime? */
be118d29 10632+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD);
0b2a12c6 10633+ err = au_test_h_perm_sio(h_userns, h_inode, MAY_EXEC | MAY_READ);
3c1bdaff 10634+ inode_unlock_shared(h_inode);
1facf9fc 10635+ if (!err)
10636+ err = do_test_empty(dentry, arg);
10637+ else {
10638+ struct do_test_empty_args args = {
10639+ .errp = &err,
10640+ .dentry = dentry,
10641+ .arg = arg
10642+ };
10643+ unsigned int flags = arg->flags;
10644+
10645+ wkq_err = au_wkq_wait(call_do_test_empty, &args);
10646+ if (unlikely(wkq_err))
10647+ err = wkq_err;
10648+ arg->flags = flags;
10649+ }
10650+
10651+ return err;
10652+}
10653+
10654+int au_test_empty_lower(struct dentry *dentry)
10655+{
10656+ int err;
1308ab2a 10657+ unsigned int rdhash;
5afbbe0d 10658+ aufs_bindex_t bindex, btop, btail;
1308ab2a 10659+ struct au_nhash whlist;
392086de
AM
10660+ struct test_empty_arg arg = {
10661+ .ctx = {
2000de60 10662+ .actor = test_empty_cb
392086de
AM
10663+ }
10664+ };
076b876e 10665+ int (*test_empty)(struct dentry *dentry, struct test_empty_arg *arg);
1facf9fc 10666+
dece6358
AM
10667+ SiMustAnyLock(dentry->d_sb);
10668+
1308ab2a 10669+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
10670+ if (!rdhash)
10671+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
10672+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
dece6358 10673+ if (unlikely(err))
1facf9fc 10674+ goto out;
10675+
1facf9fc 10676+ arg.flags = 0;
1308ab2a 10677+ arg.whlist = &whlist;
5afbbe0d 10678+ btop = au_dbtop(dentry);
dece6358
AM
10679+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
10680+ au_fset_testempty(arg.flags, SHWH);
076b876e
AM
10681+ test_empty = do_test_empty;
10682+ if (au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1))
10683+ test_empty = sio_test_empty;
5afbbe0d 10684+ arg.bindex = btop;
076b876e 10685+ err = test_empty(dentry, &arg);
1facf9fc 10686+ if (unlikely(err))
10687+ goto out_whlist;
10688+
10689+ au_fset_testempty(arg.flags, WHONLY);
10690+ btail = au_dbtaildir(dentry);
5afbbe0d 10691+ for (bindex = btop + 1; !err && bindex <= btail; bindex++) {
1facf9fc 10692+ struct dentry *h_dentry;
10693+
10694+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 10695+ if (h_dentry && d_is_positive(h_dentry)) {
1facf9fc 10696+ arg.bindex = bindex;
076b876e 10697+ err = test_empty(dentry, &arg);
1facf9fc 10698+ }
10699+ }
10700+
4f0767ce 10701+out_whlist:
1308ab2a 10702+ au_nhash_wh_free(&whlist);
4f0767ce 10703+out:
1facf9fc 10704+ return err;
10705+}
10706+
10707+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
10708+{
10709+ int err;
392086de
AM
10710+ struct test_empty_arg arg = {
10711+ .ctx = {
2000de60 10712+ .actor = test_empty_cb
392086de
AM
10713+ }
10714+ };
1facf9fc 10715+ aufs_bindex_t bindex, btail;
10716+
10717+ err = 0;
1308ab2a 10718+ arg.whlist = whlist;
1facf9fc 10719+ arg.flags = AuTestEmpty_WHONLY;
dece6358
AM
10720+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
10721+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 10722+ btail = au_dbtaildir(dentry);
5afbbe0d 10723+ for (bindex = au_dbtop(dentry); !err && bindex <= btail; bindex++) {
1facf9fc 10724+ struct dentry *h_dentry;
10725+
10726+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 10727+ if (h_dentry && d_is_positive(h_dentry)) {
1facf9fc 10728+ arg.bindex = bindex;
10729+ err = sio_test_empty(dentry, &arg);
10730+ }
10731+ }
10732+
10733+ return err;
10734+}
10735+
10736+/* ---------------------------------------------------------------------- */
10737+
10738+const struct file_operations aufs_dir_fop = {
4a4d8108 10739+ .owner = THIS_MODULE,
027c5e7a 10740+ .llseek = default_llseek,
1facf9fc 10741+ .read = generic_read_dir,
5afbbe0d 10742+ .iterate_shared = aufs_iterate_shared,
1facf9fc 10743+ .unlocked_ioctl = aufs_ioctl_dir,
b752ccd1
AM
10744+#ifdef CONFIG_COMPAT
10745+ .compat_ioctl = aufs_compat_ioctl_dir,
10746+#endif
1facf9fc 10747+ .open = aufs_open_dir,
10748+ .release = aufs_release_dir,
4a4d8108 10749+ .flush = aufs_flush_dir,
1facf9fc 10750+ .fsync = aufs_fsync_dir
10751+};
7f207e10 10752diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
eca34b5c 10753--- /usr/share/empty/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 10754+++ linux/fs/aufs/dir.h 2021-05-02 20:15:14.673337458 +0200
9f237c51 10755@@ -0,0 +1,134 @@
062440b3 10756+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 10757+/*
d58c55f2 10758+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 10759+ *
10760+ * This program, aufs is free software; you can redistribute it and/or modify
10761+ * it under the terms of the GNU General Public License as published by
10762+ * the Free Software Foundation; either version 2 of the License, or
10763+ * (at your option) any later version.
dece6358
AM
10764+ *
10765+ * This program is distributed in the hope that it will be useful,
10766+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10767+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10768+ * GNU General Public License for more details.
10769+ *
10770+ * You should have received a copy of the GNU General Public License
523b37e3 10771+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 10772+ */
10773+
10774+/*
10775+ * directory operations
10776+ */
10777+
10778+#ifndef __AUFS_DIR_H__
10779+#define __AUFS_DIR_H__
10780+
10781+#ifdef __KERNEL__
10782+
10783+#include <linux/fs.h>
1facf9fc 10784+
10785+/* ---------------------------------------------------------------------- */
10786+
10787+/* need to be faster and smaller */
10788+
10789+struct au_nhash {
dece6358
AM
10790+ unsigned int nh_num;
10791+ struct hlist_head *nh_head;
1facf9fc 10792+};
10793+
10794+struct au_vdir_destr {
10795+ unsigned char len;
42b5c33a 10796+ unsigned char name[];
1facf9fc 10797+} __packed;
10798+
10799+struct au_vdir_dehstr {
10800+ struct hlist_node hash;
1c60b727 10801+ struct au_vdir_destr *str;
9f237c51 10802+ struct rcu_head rcu;
4a4d8108 10803+} ____cacheline_aligned_in_smp;
1facf9fc 10804+
10805+struct au_vdir_de {
10806+ ino_t de_ino;
10807+ unsigned char de_type;
10808+ /* caution: packed */
10809+ struct au_vdir_destr de_str;
10810+} __packed;
10811+
10812+struct au_vdir_wh {
10813+ struct hlist_node wh_hash;
dece6358
AM
10814+#ifdef CONFIG_AUFS_SHWH
10815+ ino_t wh_ino;
1facf9fc 10816+ aufs_bindex_t wh_bindex;
dece6358
AM
10817+ unsigned char wh_type;
10818+#else
10819+ aufs_bindex_t wh_bindex;
10820+#endif
10821+ /* caution: packed */
1facf9fc 10822+ struct au_vdir_destr wh_str;
10823+} __packed;
10824+
10825+union au_vdir_deblk_p {
10826+ unsigned char *deblk;
10827+ struct au_vdir_de *de;
10828+};
10829+
10830+struct au_vdir {
10831+ unsigned char **vd_deblk;
10832+ unsigned long vd_nblk;
1facf9fc 10833+ struct {
10834+ unsigned long ul;
10835+ union au_vdir_deblk_p p;
10836+ } vd_last;
10837+
be118d29 10838+ u64 vd_version;
dece6358 10839+ unsigned int vd_deblk_sz;
9f237c51
AM
10840+ unsigned long vd_jiffy;
10841+ struct rcu_head rcu;
4a4d8108 10842+} ____cacheline_aligned_in_smp;
1facf9fc 10843+
10844+/* ---------------------------------------------------------------------- */
10845+
10846+/* dir.c */
10847+extern const struct file_operations aufs_dir_fop;
10848+void au_add_nlink(struct inode *dir, struct inode *h_dir);
10849+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
1308ab2a 10850+loff_t au_dir_size(struct file *file, struct dentry *dentry);
b912730e 10851+void au_dir_ts(struct inode *dir, aufs_bindex_t bsrc);
1facf9fc 10852+int au_test_empty_lower(struct dentry *dentry);
10853+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
10854+
10855+/* vdir.c */
1308ab2a 10856+unsigned int au_rdhash_est(loff_t sz);
dece6358
AM
10857+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
10858+void au_nhash_wh_free(struct au_nhash *whlist);
1facf9fc 10859+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
10860+ int limit);
dece6358
AM
10861+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
10862+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
10863+ unsigned int d_type, aufs_bindex_t bindex,
10864+ unsigned char shwh);
1c60b727 10865+void au_vdir_free(struct au_vdir *vdir);
1facf9fc 10866+int au_vdir_init(struct file *file);
392086de 10867+int au_vdir_fill_de(struct file *file, struct dir_context *ctx);
1facf9fc 10868+
10869+/* ioctl.c */
10870+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
10871+
1308ab2a 10872+#ifdef CONFIG_AUFS_RDU
10873+/* rdu.c */
10874+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
10875+#ifdef CONFIG_COMPAT
10876+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
10877+ unsigned long arg);
10878+#endif
1308ab2a 10879+#else
c1595e42
JR
10880+AuStub(long, au_rdu_ioctl, return -EINVAL, struct file *file,
10881+ unsigned int cmd, unsigned long arg)
b752ccd1 10882+#ifdef CONFIG_COMPAT
c1595e42
JR
10883+AuStub(long, au_rdu_compat_ioctl, return -EINVAL, struct file *file,
10884+ unsigned int cmd, unsigned long arg)
b752ccd1 10885+#endif
1308ab2a 10886+#endif
10887+
1facf9fc 10888+#endif /* __KERNEL__ */
10889+#endif /* __AUFS_DIR_H__ */
8b6a4947 10890diff -urN /usr/share/empty/fs/aufs/dirren.c linux/fs/aufs/dirren.c
eca34b5c 10891--- /usr/share/empty/fs/aufs/dirren.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 10892+++ linux/fs/aufs/dirren.c 2021-05-02 20:15:14.673337458 +0200
062440b3 10893@@ -0,0 +1,1316 @@
cd7a4cd9 10894+// SPDX-License-Identifier: GPL-2.0
8b6a4947 10895+/*
d58c55f2 10896+ * Copyright (C) 2017-2020 Junjiro R. Okajima
8b6a4947
AM
10897+ *
10898+ * This program, aufs is free software; you can redistribute it and/or modify
10899+ * it under the terms of the GNU General Public License as published by
10900+ * the Free Software Foundation; either version 2 of the License, or
10901+ * (at your option) any later version.
10902+ *
10903+ * This program is distributed in the hope that it will be useful,
10904+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10905+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10906+ * GNU General Public License for more details.
10907+ *
10908+ * You should have received a copy of the GNU General Public License
10909+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
10910+ */
10911+
10912+/*
acd2b654 10913+ * special handling in renaming a directory
8b6a4947
AM
10914+ * in order to support looking-up the before-renamed name on the lower readonly
10915+ * branches
10916+ */
10917+
10918+#include <linux/byteorder/generic.h>
10919+#include "aufs.h"
10920+
10921+static void au_dr_hino_del(struct au_dr_br *dr, struct au_dr_hino *ent)
10922+{
10923+ int idx;
10924+
10925+ idx = au_dr_ihash(ent->dr_h_ino);
10926+ au_hbl_del(&ent->dr_hnode, dr->dr_h_ino + idx);
10927+}
10928+
10929+static int au_dr_hino_test_empty(struct au_dr_br *dr)
10930+{
10931+ int ret, i;
10932+ struct hlist_bl_head *hbl;
10933+
10934+ ret = 1;
10935+ for (i = 0; ret && i < AuDirren_NHASH; i++) {
10936+ hbl = dr->dr_h_ino + i;
10937+ hlist_bl_lock(hbl);
10938+ ret &= hlist_bl_empty(hbl);
10939+ hlist_bl_unlock(hbl);
10940+ }
10941+
10942+ return ret;
10943+}
10944+
10945+static struct au_dr_hino *au_dr_hino_find(struct au_dr_br *dr, ino_t ino)
10946+{
10947+ struct au_dr_hino *found, *ent;
10948+ struct hlist_bl_head *hbl;
10949+ struct hlist_bl_node *pos;
10950+ int idx;
10951+
10952+ found = NULL;
10953+ idx = au_dr_ihash(ino);
10954+ hbl = dr->dr_h_ino + idx;
10955+ hlist_bl_lock(hbl);
10956+ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode)
10957+ if (ent->dr_h_ino == ino) {
10958+ found = ent;
10959+ break;
10960+ }
10961+ hlist_bl_unlock(hbl);
10962+
10963+ return found;
10964+}
10965+
10966+int au_dr_hino_test_add(struct au_dr_br *dr, ino_t ino,
10967+ struct au_dr_hino *add_ent)
10968+{
10969+ int found, idx;
10970+ struct hlist_bl_head *hbl;
10971+ struct hlist_bl_node *pos;
10972+ struct au_dr_hino *ent;
10973+
10974+ found = 0;
10975+ idx = au_dr_ihash(ino);
10976+ hbl = dr->dr_h_ino + idx;
43982f53 10977+#if 0 /* debug print */
8b6a4947
AM
10978+ {
10979+ struct hlist_bl_node *tmp;
10980+
10981+ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode)
10982+ AuDbg("hi%llu\n", (unsigned long long)ent->dr_h_ino);
10983+ }
10984+#endif
10985+ hlist_bl_lock(hbl);
10986+ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode)
10987+ if (ent->dr_h_ino == ino) {
10988+ found = 1;
10989+ break;
10990+ }
10991+ if (!found && add_ent)
10992+ hlist_bl_add_head(&add_ent->dr_hnode, hbl);
10993+ hlist_bl_unlock(hbl);
10994+
10995+ if (!found && add_ent)
10996+ AuDbg("i%llu added\n", (unsigned long long)add_ent->dr_h_ino);
10997+
10998+ return found;
10999+}
11000+
11001+void au_dr_hino_free(struct au_dr_br *dr)
11002+{
11003+ int i;
11004+ struct hlist_bl_head *hbl;
11005+ struct hlist_bl_node *pos, *tmp;
11006+ struct au_dr_hino *ent;
11007+
11008+ /* SiMustWriteLock(sb); */
11009+
11010+ for (i = 0; i < AuDirren_NHASH; i++) {
11011+ hbl = dr->dr_h_ino + i;
11012+ /* no spinlock since sbinfo must be write-locked */
11013+ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode)
9f237c51 11014+ au_kfree_rcu(ent);
8b6a4947
AM
11015+ INIT_HLIST_BL_HEAD(hbl);
11016+ }
11017+}
11018+
11019+/* returns the number of inodes or an error */
11020+static int au_dr_hino_store(struct super_block *sb, struct au_branch *br,
11021+ struct file *hinofile)
11022+{
11023+ int err, i;
11024+ ssize_t ssz;
11025+ loff_t pos, oldsize;
11026+ __be64 u64;
11027+ struct inode *hinoinode;
11028+ struct hlist_bl_head *hbl;
11029+ struct hlist_bl_node *n1, *n2;
11030+ struct au_dr_hino *ent;
11031+
11032+ SiMustWriteLock(sb);
11033+ AuDebugOn(!au_br_writable(br->br_perm));
11034+
11035+ hinoinode = file_inode(hinofile);
11036+ oldsize = i_size_read(hinoinode);
11037+
11038+ err = 0;
11039+ pos = 0;
11040+ hbl = br->br_dirren.dr_h_ino;
11041+ for (i = 0; !err && i < AuDirren_NHASH; i++, hbl++) {
11042+ /* no bit-lock since sbinfo must be write-locked */
11043+ hlist_bl_for_each_entry_safe(ent, n1, n2, hbl, dr_hnode) {
11044+ AuDbg("hi%llu, %pD2\n",
11045+ (unsigned long long)ent->dr_h_ino, hinofile);
11046+ u64 = cpu_to_be64(ent->dr_h_ino);
11047+ ssz = vfsub_write_k(hinofile, &u64, sizeof(u64), &pos);
11048+ if (ssz == sizeof(u64))
11049+ continue;
11050+
11051+ /* write error */
11052+ pr_err("ssz %zd, %pD2\n", ssz, hinofile);
11053+ err = -ENOSPC;
11054+ if (ssz < 0)
11055+ err = ssz;
11056+ break;
11057+ }
11058+ }
11059+ /* regardless the error */
11060+ if (pos < oldsize) {
11061+ err = vfsub_trunc(&hinofile->f_path, pos, /*attr*/0, hinofile);
11062+ AuTraceErr(err);
11063+ }
11064+
11065+ AuTraceErr(err);
11066+ return err;
11067+}
11068+
11069+static int au_dr_hino_load(struct au_dr_br *dr, struct file *hinofile)
11070+{
11071+ int err, hidx;
11072+ ssize_t ssz;
11073+ size_t sz, n;
11074+ loff_t pos;
11075+ uint64_t u64;
11076+ struct au_dr_hino *ent;
11077+ struct inode *hinoinode;
11078+ struct hlist_bl_head *hbl;
11079+
11080+ err = 0;
11081+ pos = 0;
11082+ hbl = dr->dr_h_ino;
11083+ hinoinode = file_inode(hinofile);
11084+ sz = i_size_read(hinoinode);
11085+ AuDebugOn(sz % sizeof(u64));
11086+ n = sz / sizeof(u64);
11087+ while (n--) {
11088+ ssz = vfsub_read_k(hinofile, &u64, sizeof(u64), &pos);
11089+ if (unlikely(ssz != sizeof(u64))) {
11090+ pr_err("ssz %zd, %pD2\n", ssz, hinofile);
11091+ err = -EINVAL;
11092+ if (ssz < 0)
11093+ err = ssz;
11094+ goto out_free;
11095+ }
11096+
11097+ ent = kmalloc(sizeof(*ent), GFP_NOFS);
11098+ if (!ent) {
11099+ err = -ENOMEM;
11100+ AuTraceErr(err);
11101+ goto out_free;
11102+ }
11103+ ent->dr_h_ino = be64_to_cpu((__force __be64)u64);
11104+ AuDbg("hi%llu, %pD2\n",
11105+ (unsigned long long)ent->dr_h_ino, hinofile);
11106+ hidx = au_dr_ihash(ent->dr_h_ino);
11107+ au_hbl_add(&ent->dr_hnode, hbl + hidx);
11108+ }
11109+ goto out; /* success */
11110+
11111+out_free:
11112+ au_dr_hino_free(dr);
11113+out:
11114+ AuTraceErr(err);
11115+ return err;
11116+}
11117+
11118+/*
11119+ * @bindex/@br is a switch to distinguish whether suspending hnotify or not.
11120+ * @path is a switch to distinguish load and store.
11121+ */
11122+static int au_dr_hino(struct super_block *sb, aufs_bindex_t bindex,
11123+ struct au_branch *br, const struct path *path)
11124+{
11125+ int err, flags;
11126+ unsigned char load, suspend;
11127+ struct file *hinofile;
11128+ struct au_hinode *hdir;
11129+ struct inode *dir, *delegated;
11130+ struct path hinopath;
11131+ struct qstr hinoname = QSTR_INIT(AUFS_WH_DR_BRHINO,
11132+ sizeof(AUFS_WH_DR_BRHINO) - 1);
11133+
11134+ AuDebugOn(bindex < 0 && !br);
11135+ AuDebugOn(bindex >= 0 && br);
11136+
11137+ err = -EINVAL;
11138+ suspend = !br;
11139+ if (suspend)
11140+ br = au_sbr(sb, bindex);
11141+ load = !!path;
11142+ if (!load) {
11143+ path = &br->br_path;
11144+ AuDebugOn(!au_br_writable(br->br_perm));
11145+ if (unlikely(!au_br_writable(br->br_perm)))
11146+ goto out;
11147+ }
11148+
11149+ hdir = NULL;
11150+ if (suspend) {
11151+ dir = d_inode(sb->s_root);
11152+ hdir = au_hinode(au_ii(dir), bindex);
11153+ dir = hdir->hi_inode;
11154+ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD);
11155+ } else {
11156+ dir = d_inode(path->dentry);
11157+ inode_lock_nested(dir, AuLsc_I_CHILD);
11158+ }
11159+ hinopath.dentry = vfsub_lkup_one(&hinoname, path->dentry);
11160+ err = PTR_ERR(hinopath.dentry);
11161+ if (IS_ERR(hinopath.dentry))
11162+ goto out_unlock;
0b2a12c6 11163+ hinopath.mnt = path->mnt;
8b6a4947
AM
11164+
11165+ err = 0;
11166+ flags = O_RDONLY;
11167+ if (load) {
11168+ if (d_is_negative(hinopath.dentry))
11169+ goto out_dput; /* success */
11170+ } else {
11171+ if (au_dr_hino_test_empty(&br->br_dirren)) {
11172+ if (d_is_positive(hinopath.dentry)) {
11173+ delegated = NULL;
11174+ err = vfsub_unlink(dir, &hinopath, &delegated,
11175+ /*force*/0);
11176+ AuTraceErr(err);
11177+ if (unlikely(err))
11178+ pr_err("ignored err %d, %pd2\n",
11179+ err, hinopath.dentry);
11180+ if (unlikely(err == -EWOULDBLOCK))
11181+ iput(delegated);
11182+ err = 0;
11183+ }
11184+ goto out_dput;
11185+ } else if (!d_is_positive(hinopath.dentry)) {
11186+ err = vfsub_create(dir, &hinopath, 0600,
11187+ /*want_excl*/false);
11188+ AuTraceErr(err);
11189+ if (unlikely(err))
11190+ goto out_dput;
11191+ }
11192+ flags = O_WRONLY;
11193+ }
8b6a4947
AM
11194+ hinofile = vfsub_dentry_open(&hinopath, flags);
11195+ if (suspend)
11196+ au_hn_inode_unlock(hdir);
11197+ else
11198+ inode_unlock(dir);
11199+ dput(hinopath.dentry);
11200+ AuTraceErrPtr(hinofile);
11201+ if (IS_ERR(hinofile)) {
11202+ err = PTR_ERR(hinofile);
11203+ goto out;
11204+ }
11205+
11206+ if (load)
11207+ err = au_dr_hino_load(&br->br_dirren, hinofile);
11208+ else
11209+ err = au_dr_hino_store(sb, br, hinofile);
11210+ fput(hinofile);
11211+ goto out;
11212+
11213+out_dput:
11214+ dput(hinopath.dentry);
11215+out_unlock:
11216+ if (suspend)
11217+ au_hn_inode_unlock(hdir);
11218+ else
11219+ inode_unlock(dir);
11220+out:
11221+ AuTraceErr(err);
11222+ return err;
11223+}
11224+
11225+/* ---------------------------------------------------------------------- */
11226+
11227+static int au_dr_brid_init(struct au_dr_brid *brid, const struct path *path)
11228+{
11229+ int err;
11230+ struct kstatfs kstfs;
11231+ dev_t dev;
11232+ struct dentry *dentry;
11233+ struct super_block *sb;
11234+
11235+ err = vfs_statfs((void *)path, &kstfs);
11236+ AuTraceErr(err);
11237+ if (unlikely(err))
11238+ goto out;
11239+
11240+ /* todo: support for UUID */
11241+
11242+ if (kstfs.f_fsid.val[0] || kstfs.f_fsid.val[1]) {
11243+ brid->type = AuBrid_FSID;
11244+ brid->fsid = kstfs.f_fsid;
11245+ } else {
11246+ dentry = path->dentry;
11247+ sb = dentry->d_sb;
11248+ dev = sb->s_dev;
11249+ if (dev) {
11250+ brid->type = AuBrid_DEV;
11251+ brid->dev = dev;
11252+ }
11253+ }
11254+
11255+out:
11256+ return err;
11257+}
11258+
11259+int au_dr_br_init(struct super_block *sb, struct au_branch *br,
11260+ const struct path *path)
11261+{
11262+ int err, i;
11263+ struct au_dr_br *dr;
11264+ struct hlist_bl_head *hbl;
11265+
11266+ dr = &br->br_dirren;
11267+ hbl = dr->dr_h_ino;
11268+ for (i = 0; i < AuDirren_NHASH; i++, hbl++)
11269+ INIT_HLIST_BL_HEAD(hbl);
11270+
11271+ err = au_dr_brid_init(&dr->dr_brid, path);
11272+ if (unlikely(err))
11273+ goto out;
11274+
11275+ if (au_opt_test(au_mntflags(sb), DIRREN))
11276+ err = au_dr_hino(sb, /*bindex*/-1, br, path);
11277+
11278+out:
11279+ AuTraceErr(err);
11280+ return err;
11281+}
11282+
11283+int au_dr_br_fin(struct super_block *sb, struct au_branch *br)
11284+{
11285+ int err;
11286+
11287+ err = 0;
11288+ if (au_br_writable(br->br_perm))
11289+ err = au_dr_hino(sb, /*bindex*/-1, br, /*path*/NULL);
11290+ if (!err)
11291+ au_dr_hino_free(&br->br_dirren);
11292+
11293+ return err;
11294+}
11295+
11296+/* ---------------------------------------------------------------------- */
11297+
11298+static int au_brid_str(struct au_dr_brid *brid, struct inode *h_inode,
11299+ char *buf, size_t sz)
11300+{
11301+ int err;
11302+ unsigned int major, minor;
11303+ char *p;
11304+
11305+ p = buf;
11306+ err = snprintf(p, sz, "%d_", brid->type);
11307+ AuDebugOn(err > sz);
11308+ p += err;
11309+ sz -= err;
11310+ switch (brid->type) {
11311+ case AuBrid_Unset:
11312+ return -EINVAL;
11313+ case AuBrid_UUID:
11314+ err = snprintf(p, sz, "%pU", brid->uuid.b);
11315+ break;
11316+ case AuBrid_FSID:
11317+ err = snprintf(p, sz, "%08x-%08x",
11318+ brid->fsid.val[0], brid->fsid.val[1]);
11319+ break;
11320+ case AuBrid_DEV:
11321+ major = MAJOR(brid->dev);
11322+ minor = MINOR(brid->dev);
11323+ if (major <= 0xff && minor <= 0xff)
11324+ err = snprintf(p, sz, "%02x%02x", major, minor);
11325+ else
11326+ err = snprintf(p, sz, "%03x:%05x", major, minor);
11327+ break;
11328+ }
11329+ AuDebugOn(err > sz);
11330+ p += err;
11331+ sz -= err;
11332+ err = snprintf(p, sz, "_%llu", (unsigned long long)h_inode->i_ino);
11333+ AuDebugOn(err > sz);
11334+ p += err;
11335+ sz -= err;
11336+
11337+ return p - buf;
11338+}
11339+
11340+static int au_drinfo_name(struct au_branch *br, char *name, int len)
11341+{
11342+ int rlen;
11343+ struct dentry *br_dentry;
11344+ struct inode *br_inode;
11345+
11346+ br_dentry = au_br_dentry(br);
11347+ br_inode = d_inode(br_dentry);
11348+ rlen = au_brid_str(&br->br_dirren.dr_brid, br_inode, name, len);
11349+ AuDebugOn(rlen >= AUFS_DIRREN_ENV_VAL_SZ);
11350+ AuDebugOn(rlen > len);
11351+
11352+ return rlen;
11353+}
11354+
11355+/* ---------------------------------------------------------------------- */
11356+
11357+/*
11358+ * from the given @h_dentry, construct drinfo at @*fdata.
11359+ * when the size of @*fdata is not enough, reallocate and return new @fdata and
11360+ * @allocated.
11361+ */
11362+static int au_drinfo_construct(struct au_drinfo_fdata **fdata,
11363+ struct dentry *h_dentry,
11364+ unsigned char *allocated)
11365+{
11366+ int err, v;
11367+ struct au_drinfo_fdata *f, *p;
11368+ struct au_drinfo *drinfo;
11369+ struct inode *h_inode;
11370+ struct qstr *qname;
11371+
11372+ err = 0;
11373+ f = *fdata;
11374+ h_inode = d_inode(h_dentry);
11375+ qname = &h_dentry->d_name;
11376+ drinfo = &f->drinfo;
11377+ drinfo->ino = (__force uint64_t)cpu_to_be64(h_inode->i_ino);
11378+ drinfo->oldnamelen = qname->len;
11379+ if (*allocated < sizeof(*f) + qname->len) {
11380+ v = roundup_pow_of_two(*allocated + qname->len);
11381+ p = au_krealloc(f, v, GFP_NOFS, /*may_shrink*/0);
11382+ if (unlikely(!p)) {
11383+ err = -ENOMEM;
11384+ AuTraceErr(err);
11385+ goto out;
11386+ }
11387+ f = p;
11388+ *fdata = f;
11389+ *allocated = v;
11390+ drinfo = &f->drinfo;
11391+ }
11392+ memcpy(drinfo->oldname, qname->name, qname->len);
11393+ AuDbg("i%llu, %.*s\n",
11394+ be64_to_cpu((__force __be64)drinfo->ino), drinfo->oldnamelen,
11395+ drinfo->oldname);
11396+
11397+out:
11398+ AuTraceErr(err);
11399+ return err;
11400+}
11401+
11402+/* callers have to free the return value */
11403+static struct au_drinfo *au_drinfo_read_k(struct file *file, ino_t h_ino)
11404+{
11405+ struct au_drinfo *ret, *drinfo;
11406+ struct au_drinfo_fdata fdata;
11407+ int len;
11408+ loff_t pos;
11409+ ssize_t ssz;
11410+
11411+ ret = ERR_PTR(-EIO);
11412+ pos = 0;
11413+ ssz = vfsub_read_k(file, &fdata, sizeof(fdata), &pos);
11414+ if (unlikely(ssz != sizeof(fdata))) {
11415+ AuIOErr("ssz %zd, %u, %pD2\n",
11416+ ssz, (unsigned int)sizeof(fdata), file);
11417+ goto out;
11418+ }
11419+
11420+ fdata.magic = ntohl((__force __be32)fdata.magic);
11421+ switch (fdata.magic) {
11422+ case AUFS_DRINFO_MAGIC_V1:
11423+ break;
11424+ default:
11425+ AuIOErr("magic-num 0x%x, 0x%x, %pD2\n",
11426+ fdata.magic, AUFS_DRINFO_MAGIC_V1, file);
11427+ goto out;
11428+ }
11429+
11430+ drinfo = &fdata.drinfo;
11431+ len = drinfo->oldnamelen;
11432+ if (!len) {
11433+ AuIOErr("broken drinfo %pD2\n", file);
11434+ goto out;
11435+ }
11436+
11437+ ret = NULL;
11438+ drinfo->ino = be64_to_cpu((__force __be64)drinfo->ino);
11439+ if (unlikely(h_ino && drinfo->ino != h_ino)) {
11440+ AuDbg("ignored i%llu, i%llu, %pD2\n",
11441+ (unsigned long long)drinfo->ino,
11442+ (unsigned long long)h_ino, file);
11443+ goto out; /* success */
11444+ }
11445+
11446+ ret = kmalloc(sizeof(*ret) + len, GFP_NOFS);
11447+ if (unlikely(!ret)) {
11448+ ret = ERR_PTR(-ENOMEM);
11449+ AuTraceErrPtr(ret);
11450+ goto out;
11451+ }
11452+
11453+ *ret = *drinfo;
11454+ ssz = vfsub_read_k(file, (void *)ret->oldname, len, &pos);
11455+ if (unlikely(ssz != len)) {
9f237c51 11456+ au_kfree_rcu(ret);
8b6a4947
AM
11457+ ret = ERR_PTR(-EIO);
11458+ AuIOErr("ssz %zd, %u, %pD2\n", ssz, len, file);
11459+ goto out;
11460+ }
11461+
11462+ AuDbg("oldname %.*s\n", ret->oldnamelen, ret->oldname);
11463+
11464+out:
11465+ return ret;
11466+}
11467+
11468+/* ---------------------------------------------------------------------- */
11469+
11470+/* in order to be revertible */
11471+struct au_drinfo_rev_elm {
11472+ int created;
11473+ struct dentry *info_dentry;
11474+ struct au_drinfo *info_last;
11475+};
11476+
11477+struct au_drinfo_rev {
11478+ unsigned char already;
11479+ aufs_bindex_t nelm;
42b5c33a 11480+ struct au_drinfo_rev_elm elm[];
8b6a4947
AM
11481+};
11482+
11483+/* todo: isn't it too large? */
11484+struct au_drinfo_store {
11485+ struct path h_ppath;
11486+ struct dentry *h_dentry;
11487+ struct au_drinfo_fdata *fdata;
11488+ char *infoname; /* inside of whname, just after PFX */
11489+ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ];
11490+ aufs_bindex_t btgt, btail;
11491+ unsigned char no_sio,
11492+ allocated, /* current size of *fdata */
11493+ infonamelen, /* room size for p */
acd2b654 11494+ whnamelen, /* length of the generated name */
8b6a4947
AM
11495+ renameback; /* renamed back */
11496+};
11497+
11498+/* on rename(2) error, the caller should revert it using @elm */
11499+static int au_drinfo_do_store(struct au_drinfo_store *w,
11500+ struct au_drinfo_rev_elm *elm)
11501+{
11502+ int err, len;
11503+ ssize_t ssz;
11504+ loff_t pos;
11505+ struct path infopath = {
11506+ .mnt = w->h_ppath.mnt
11507+ };
11508+ struct inode *h_dir, *h_inode, *delegated;
11509+ struct file *infofile;
11510+ struct qstr *qname;
11511+
11512+ AuDebugOn(elm
11513+ && memcmp(elm, page_address(ZERO_PAGE(0)), sizeof(*elm)));
11514+
11515+ infopath.dentry = vfsub_lookup_one_len(w->whname, w->h_ppath.dentry,
11516+ w->whnamelen);
11517+ AuTraceErrPtr(infopath.dentry);
11518+ if (IS_ERR(infopath.dentry)) {
11519+ err = PTR_ERR(infopath.dentry);
11520+ goto out;
11521+ }
11522+
11523+ err = 0;
11524+ h_dir = d_inode(w->h_ppath.dentry);
11525+ if (elm && d_is_negative(infopath.dentry)) {
11526+ err = vfsub_create(h_dir, &infopath, 0600, /*want_excl*/true);
11527+ AuTraceErr(err);
11528+ if (unlikely(err))
11529+ goto out_dput;
11530+ elm->created = 1;
11531+ elm->info_dentry = dget(infopath.dentry);
11532+ }
11533+
11534+ infofile = vfsub_dentry_open(&infopath, O_RDWR);
11535+ AuTraceErrPtr(infofile);
11536+ if (IS_ERR(infofile)) {
11537+ err = PTR_ERR(infofile);
11538+ goto out_dput;
11539+ }
11540+
11541+ h_inode = d_inode(infopath.dentry);
11542+ if (elm && i_size_read(h_inode)) {
11543+ h_inode = d_inode(w->h_dentry);
11544+ elm->info_last = au_drinfo_read_k(infofile, h_inode->i_ino);
11545+ AuTraceErrPtr(elm->info_last);
11546+ if (IS_ERR(elm->info_last)) {
11547+ err = PTR_ERR(elm->info_last);
11548+ elm->info_last = NULL;
11549+ AuDebugOn(elm->info_dentry);
11550+ goto out_fput;
11551+ }
11552+ }
11553+
11554+ if (elm && w->renameback) {
11555+ delegated = NULL;
11556+ err = vfsub_unlink(h_dir, &infopath, &delegated, /*force*/0);
11557+ AuTraceErr(err);
11558+ if (unlikely(err == -EWOULDBLOCK))
11559+ iput(delegated);
11560+ goto out_fput;
11561+ }
11562+
11563+ pos = 0;
11564+ qname = &w->h_dentry->d_name;
11565+ len = sizeof(*w->fdata) + qname->len;
11566+ if (!elm)
11567+ len = sizeof(*w->fdata) + w->fdata->drinfo.oldnamelen;
11568+ ssz = vfsub_write_k(infofile, w->fdata, len, &pos);
11569+ if (ssz == len) {
11570+ AuDbg("hi%llu, %.*s\n", w->fdata->drinfo.ino,
11571+ w->fdata->drinfo.oldnamelen, w->fdata->drinfo.oldname);
11572+ goto out_fput; /* success */
11573+ } else {
11574+ err = -EIO;
11575+ if (ssz < 0)
11576+ err = ssz;
11577+ /* the caller should revert it using @elm */
11578+ }
11579+
11580+out_fput:
11581+ fput(infofile);
11582+out_dput:
11583+ dput(infopath.dentry);
11584+out:
11585+ AuTraceErr(err);
11586+ return err;
11587+}
11588+
11589+struct au_call_drinfo_do_store_args {
11590+ int *errp;
11591+ struct au_drinfo_store *w;
11592+ struct au_drinfo_rev_elm *elm;
11593+};
11594+
11595+static void au_call_drinfo_do_store(void *args)
11596+{
11597+ struct au_call_drinfo_do_store_args *a = args;
11598+
11599+ *a->errp = au_drinfo_do_store(a->w, a->elm);
11600+}
11601+
11602+static int au_drinfo_store_sio(struct au_drinfo_store *w,
11603+ struct au_drinfo_rev_elm *elm)
11604+{
11605+ int err, wkq_err;
11606+
11607+ if (w->no_sio)
11608+ err = au_drinfo_do_store(w, elm);
11609+ else {
11610+ struct au_call_drinfo_do_store_args a = {
11611+ .errp = &err,
11612+ .w = w,
11613+ .elm = elm
11614+ };
11615+ wkq_err = au_wkq_wait(au_call_drinfo_do_store, &a);
11616+ if (unlikely(wkq_err))
11617+ err = wkq_err;
11618+ }
11619+ AuTraceErr(err);
11620+
11621+ return err;
11622+}
11623+
11624+static int au_drinfo_store_work_init(struct au_drinfo_store *w,
11625+ aufs_bindex_t btgt)
11626+{
11627+ int err;
11628+
11629+ memset(w, 0, sizeof(*w));
11630+ w->allocated = roundup_pow_of_two(sizeof(*w->fdata) + 40);
11631+ strcpy(w->whname, AUFS_WH_DR_INFO_PFX);
11632+ w->infoname = w->whname + sizeof(AUFS_WH_DR_INFO_PFX) - 1;
11633+ w->infonamelen = sizeof(w->whname) - sizeof(AUFS_WH_DR_INFO_PFX);
11634+ w->btgt = btgt;
11635+ w->no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID);
11636+
11637+ err = -ENOMEM;
11638+ w->fdata = kcalloc(1, w->allocated, GFP_NOFS);
11639+ if (unlikely(!w->fdata)) {
11640+ AuTraceErr(err);
11641+ goto out;
11642+ }
11643+ w->fdata->magic = (__force uint32_t)htonl(AUFS_DRINFO_MAGIC_V1);
11644+ err = 0;
11645+
11646+out:
11647+ return err;
11648+}
11649+
11650+static void au_drinfo_store_work_fin(struct au_drinfo_store *w)
11651+{
9f237c51 11652+ au_kfree_rcu(w->fdata);
8b6a4947
AM
11653+}
11654+
11655+static void au_drinfo_store_rev(struct au_drinfo_rev *rev,
11656+ struct au_drinfo_store *w)
11657+{
11658+ struct au_drinfo_rev_elm *elm;
11659+ struct inode *h_dir, *delegated;
11660+ int err, nelm;
11661+ struct path infopath = {
11662+ .mnt = w->h_ppath.mnt
11663+ };
11664+
11665+ h_dir = d_inode(w->h_ppath.dentry);
11666+ IMustLock(h_dir);
11667+
11668+ err = 0;
11669+ elm = rev->elm;
11670+ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) {
11671+ AuDebugOn(elm->created && elm->info_last);
11672+ if (elm->created) {
11673+ AuDbg("here\n");
11674+ delegated = NULL;
11675+ infopath.dentry = elm->info_dentry;
11676+ err = vfsub_unlink(h_dir, &infopath, &delegated,
11677+ !w->no_sio);
11678+ AuTraceErr(err);
11679+ if (unlikely(err == -EWOULDBLOCK))
11680+ iput(delegated);
11681+ dput(elm->info_dentry);
11682+ } else if (elm->info_last) {
11683+ AuDbg("here\n");
11684+ w->fdata->drinfo = *elm->info_last;
11685+ memcpy(w->fdata->drinfo.oldname,
11686+ elm->info_last->oldname,
11687+ elm->info_last->oldnamelen);
11688+ err = au_drinfo_store_sio(w, /*elm*/NULL);
9f237c51 11689+ au_kfree_rcu(elm->info_last);
8b6a4947
AM
11690+ }
11691+ if (unlikely(err))
11692+ AuIOErr("%d, %s\n", err, w->whname);
11693+ /* go on even if err */
11694+ }
11695+}
11696+
11697+/* caller has to call au_dr_rename_fin() later */
11698+static int au_drinfo_store(struct dentry *dentry, aufs_bindex_t btgt,
11699+ struct qstr *dst_name, void *_rev)
11700+{
11701+ int err, sz, nelm;
11702+ aufs_bindex_t bindex, btail;
11703+ struct au_drinfo_store work;
11704+ struct au_drinfo_rev *rev, **p;
11705+ struct au_drinfo_rev_elm *elm;
11706+ struct super_block *sb;
11707+ struct au_branch *br;
11708+ struct au_hinode *hdir;
11709+
11710+ err = au_drinfo_store_work_init(&work, btgt);
11711+ AuTraceErr(err);
11712+ if (unlikely(err))
11713+ goto out;
11714+
11715+ err = -ENOMEM;
11716+ btail = au_dbtaildir(dentry);
11717+ nelm = btail - btgt;
11718+ sz = sizeof(*rev) + sizeof(*elm) * nelm;
11719+ rev = kcalloc(1, sz, GFP_NOFS);
11720+ if (unlikely(!rev)) {
11721+ AuTraceErr(err);
11722+ goto out_args;
11723+ }
11724+ rev->nelm = nelm;
11725+ elm = rev->elm;
11726+ p = _rev;
11727+ *p = rev;
11728+
11729+ err = 0;
11730+ sb = dentry->d_sb;
11731+ work.h_ppath.dentry = au_h_dptr(dentry, btgt);
11732+ work.h_ppath.mnt = au_sbr_mnt(sb, btgt);
11733+ hdir = au_hi(d_inode(dentry), btgt);
11734+ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD);
11735+ for (bindex = btgt + 1; bindex <= btail; bindex++, elm++) {
11736+ work.h_dentry = au_h_dptr(dentry, bindex);
11737+ if (!work.h_dentry)
11738+ continue;
11739+
11740+ err = au_drinfo_construct(&work.fdata, work.h_dentry,
11741+ &work.allocated);
11742+ AuTraceErr(err);
11743+ if (unlikely(err))
11744+ break;
11745+
11746+ work.renameback = au_qstreq(&work.h_dentry->d_name, dst_name);
11747+ br = au_sbr(sb, bindex);
11748+ work.whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1;
11749+ work.whnamelen += au_drinfo_name(br, work.infoname,
11750+ work.infonamelen);
11751+ AuDbg("whname %.*s, i%llu, %.*s\n",
11752+ work.whnamelen, work.whname,
11753+ be64_to_cpu((__force __be64)work.fdata->drinfo.ino),
11754+ work.fdata->drinfo.oldnamelen,
11755+ work.fdata->drinfo.oldname);
11756+
11757+ err = au_drinfo_store_sio(&work, elm);
11758+ AuTraceErr(err);
11759+ if (unlikely(err))
11760+ break;
11761+ }
11762+ if (unlikely(err)) {
11763+ /* revert all drinfo */
11764+ au_drinfo_store_rev(rev, &work);
9f237c51 11765+ au_kfree_try_rcu(rev);
8b6a4947
AM
11766+ *p = NULL;
11767+ }
11768+ au_hn_inode_unlock(hdir);
11769+
11770+out_args:
11771+ au_drinfo_store_work_fin(&work);
11772+out:
11773+ return err;
11774+}
11775+
11776+/* ---------------------------------------------------------------------- */
11777+
11778+int au_dr_rename(struct dentry *src, aufs_bindex_t bindex,
11779+ struct qstr *dst_name, void *_rev)
11780+{
11781+ int err, already;
11782+ ino_t ino;
11783+ struct super_block *sb;
11784+ struct au_branch *br;
11785+ struct au_dr_br *dr;
11786+ struct dentry *h_dentry;
11787+ struct inode *h_inode;
11788+ struct au_dr_hino *ent;
11789+ struct au_drinfo_rev *rev, **p;
11790+
11791+ AuDbg("bindex %d\n", bindex);
11792+
11793+ err = -ENOMEM;
11794+ ent = kmalloc(sizeof(*ent), GFP_NOFS);
11795+ if (unlikely(!ent))
11796+ goto out;
11797+
11798+ sb = src->d_sb;
11799+ br = au_sbr(sb, bindex);
11800+ dr = &br->br_dirren;
11801+ h_dentry = au_h_dptr(src, bindex);
11802+ h_inode = d_inode(h_dentry);
11803+ ino = h_inode->i_ino;
11804+ ent->dr_h_ino = ino;
11805+ already = au_dr_hino_test_add(dr, ino, ent);
11806+ AuDbg("b%d, hi%llu, already %d\n",
11807+ bindex, (unsigned long long)ino, already);
11808+
11809+ err = au_drinfo_store(src, bindex, dst_name, _rev);
11810+ AuTraceErr(err);
11811+ if (!err) {
11812+ p = _rev;
11813+ rev = *p;
11814+ rev->already = already;
11815+ goto out; /* success */
11816+ }
11817+
11818+ /* revert */
11819+ if (!already)
11820+ au_dr_hino_del(dr, ent);
9f237c51 11821+ au_kfree_rcu(ent);
8b6a4947
AM
11822+
11823+out:
11824+ AuTraceErr(err);
11825+ return err;
11826+}
11827+
11828+void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *_rev)
11829+{
11830+ struct au_drinfo_rev *rev;
11831+ struct au_drinfo_rev_elm *elm;
11832+ int nelm;
11833+
11834+ rev = _rev;
11835+ elm = rev->elm;
11836+ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) {
11837+ dput(elm->info_dentry);
9f237c51 11838+ au_kfree_rcu(elm->info_last);
8b6a4947 11839+ }
9f237c51 11840+ au_kfree_try_rcu(rev);
8b6a4947
AM
11841+}
11842+
11843+void au_dr_rename_rev(struct dentry *src, aufs_bindex_t btgt, void *_rev)
11844+{
11845+ int err;
11846+ struct au_drinfo_store work;
11847+ struct au_drinfo_rev *rev = _rev;
11848+ struct super_block *sb;
11849+ struct au_branch *br;
11850+ struct inode *h_inode;
11851+ struct au_dr_br *dr;
11852+ struct au_dr_hino *ent;
11853+
11854+ err = au_drinfo_store_work_init(&work, btgt);
11855+ if (unlikely(err))
11856+ goto out;
11857+
11858+ sb = src->d_sb;
11859+ br = au_sbr(sb, btgt);
11860+ work.h_ppath.dentry = au_h_dptr(src, btgt);
11861+ work.h_ppath.mnt = au_br_mnt(br);
11862+ au_drinfo_store_rev(rev, &work);
11863+ au_drinfo_store_work_fin(&work);
11864+ if (rev->already)
11865+ goto out;
11866+
11867+ dr = &br->br_dirren;
11868+ h_inode = d_inode(work.h_ppath.dentry);
11869+ ent = au_dr_hino_find(dr, h_inode->i_ino);
11870+ BUG_ON(!ent);
11871+ au_dr_hino_del(dr, ent);
9f237c51 11872+ au_kfree_rcu(ent);
8b6a4947
AM
11873+
11874+out:
9f237c51 11875+ au_kfree_try_rcu(rev);
8b6a4947
AM
11876+ if (unlikely(err))
11877+ pr_err("failed to remove dirren info\n");
11878+}
11879+
11880+/* ---------------------------------------------------------------------- */
11881+
11882+static struct au_drinfo *au_drinfo_do_load(struct path *h_ppath,
11883+ char *whname, int whnamelen,
11884+ struct dentry **info_dentry)
11885+{
11886+ struct au_drinfo *drinfo;
11887+ struct file *f;
11888+ struct inode *h_dir;
11889+ struct path infopath;
11890+ int unlocked;
11891+
11892+ AuDbg("%pd/%.*s\n", h_ppath->dentry, whnamelen, whname);
11893+
11894+ *info_dentry = NULL;
11895+ drinfo = NULL;
11896+ unlocked = 0;
11897+ h_dir = d_inode(h_ppath->dentry);
be118d29 11898+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
8b6a4947
AM
11899+ infopath.dentry = vfsub_lookup_one_len(whname, h_ppath->dentry,
11900+ whnamelen);
11901+ if (IS_ERR(infopath.dentry)) {
11902+ drinfo = (void *)infopath.dentry;
11903+ goto out;
11904+ }
11905+
11906+ if (d_is_negative(infopath.dentry))
11907+ goto out_dput; /* success */
11908+
11909+ infopath.mnt = h_ppath->mnt;
11910+ f = vfsub_dentry_open(&infopath, O_RDONLY);
11911+ inode_unlock_shared(h_dir);
11912+ unlocked = 1;
11913+ if (IS_ERR(f)) {
11914+ drinfo = (void *)f;
11915+ goto out_dput;
11916+ }
11917+
11918+ drinfo = au_drinfo_read_k(f, /*h_ino*/0);
11919+ if (IS_ERR_OR_NULL(drinfo))
11920+ goto out_fput;
11921+
11922+ AuDbg("oldname %.*s\n", drinfo->oldnamelen, drinfo->oldname);
11923+ *info_dentry = dget(infopath.dentry); /* keep it alive */
11924+
11925+out_fput:
11926+ fput(f);
11927+out_dput:
11928+ dput(infopath.dentry);
11929+out:
11930+ if (!unlocked)
11931+ inode_unlock_shared(h_dir);
11932+ AuTraceErrPtr(drinfo);
11933+ return drinfo;
11934+}
11935+
11936+struct au_drinfo_do_load_args {
11937+ struct au_drinfo **drinfop;
11938+ struct path *h_ppath;
11939+ char *whname;
11940+ int whnamelen;
11941+ struct dentry **info_dentry;
11942+};
11943+
11944+static void au_call_drinfo_do_load(void *args)
11945+{
11946+ struct au_drinfo_do_load_args *a = args;
11947+
11948+ *a->drinfop = au_drinfo_do_load(a->h_ppath, a->whname, a->whnamelen,
11949+ a->info_dentry);
11950+}
11951+
11952+struct au_drinfo_load {
11953+ struct path h_ppath;
11954+ struct qstr *qname;
11955+ unsigned char no_sio;
11956+
11957+ aufs_bindex_t ninfo;
11958+ struct au_drinfo **drinfo;
11959+};
11960+
11961+static int au_drinfo_load(struct au_drinfo_load *w, aufs_bindex_t bindex,
11962+ struct au_branch *br)
11963+{
11964+ int err, wkq_err, whnamelen, e;
11965+ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ]
11966+ = AUFS_WH_DR_INFO_PFX;
11967+ struct au_drinfo *drinfo;
11968+ struct qstr oldname;
11969+ struct inode *h_dir, *delegated;
11970+ struct dentry *info_dentry;
11971+ struct path infopath;
11972+
11973+ whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1;
11974+ whnamelen += au_drinfo_name(br, whname + whnamelen,
11975+ sizeof(whname) - whnamelen);
11976+ if (w->no_sio)
11977+ drinfo = au_drinfo_do_load(&w->h_ppath, whname, whnamelen,
11978+ &info_dentry);
11979+ else {
11980+ struct au_drinfo_do_load_args args = {
11981+ .drinfop = &drinfo,
11982+ .h_ppath = &w->h_ppath,
11983+ .whname = whname,
11984+ .whnamelen = whnamelen,
11985+ .info_dentry = &info_dentry
11986+ };
11987+ wkq_err = au_wkq_wait(au_call_drinfo_do_load, &args);
11988+ if (unlikely(wkq_err))
11989+ drinfo = ERR_PTR(wkq_err);
11990+ }
11991+ err = PTR_ERR(drinfo);
11992+ if (IS_ERR_OR_NULL(drinfo))
11993+ goto out;
11994+
11995+ err = 0;
11996+ oldname.len = drinfo->oldnamelen;
11997+ oldname.name = drinfo->oldname;
11998+ if (au_qstreq(w->qname, &oldname)) {
11999+ /* the name is renamed back */
9f237c51 12000+ au_kfree_rcu(drinfo);
8b6a4947
AM
12001+ drinfo = NULL;
12002+
12003+ infopath.dentry = info_dentry;
12004+ infopath.mnt = w->h_ppath.mnt;
12005+ h_dir = d_inode(w->h_ppath.dentry);
12006+ delegated = NULL;
12007+ inode_lock_nested(h_dir, AuLsc_I_PARENT);
12008+ e = vfsub_unlink(h_dir, &infopath, &delegated, !w->no_sio);
12009+ inode_unlock(h_dir);
12010+ if (unlikely(e))
12011+ AuIOErr("ignored %d, %pd2\n", e, &infopath.dentry);
12012+ if (unlikely(e == -EWOULDBLOCK))
12013+ iput(delegated);
12014+ }
9f237c51 12015+ au_kfree_rcu(w->drinfo[bindex]);
8b6a4947
AM
12016+ w->drinfo[bindex] = drinfo;
12017+ dput(info_dentry);
12018+
12019+out:
12020+ AuTraceErr(err);
12021+ return err;
12022+}
12023+
12024+/* ---------------------------------------------------------------------- */
12025+
12026+static void au_dr_lkup_free(struct au_drinfo **drinfo, int n)
12027+{
12028+ struct au_drinfo **p = drinfo;
12029+
12030+ while (n-- > 0)
9f237c51
AM
12031+ au_kfree_rcu(*drinfo++);
12032+ au_kfree_try_rcu(p);
8b6a4947
AM
12033+}
12034+
12035+int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry,
12036+ aufs_bindex_t btgt)
12037+{
12038+ int err, ninfo;
12039+ struct au_drinfo_load w;
12040+ aufs_bindex_t bindex, bbot;
12041+ struct au_branch *br;
12042+ struct inode *h_dir;
12043+ struct au_dr_hino *ent;
12044+ struct super_block *sb;
12045+
12046+ AuDbg("%.*s, name %.*s, whname %.*s, b%d\n",
12047+ AuLNPair(&dentry->d_name), AuLNPair(&lkup->dirren.dr_name),
12048+ AuLNPair(&lkup->whname), btgt);
12049+
12050+ sb = dentry->d_sb;
12051+ bbot = au_sbbot(sb);
12052+ w.ninfo = bbot + 1;
12053+ if (!lkup->dirren.drinfo) {
12054+ lkup->dirren.drinfo = kcalloc(w.ninfo,
12055+ sizeof(*lkup->dirren.drinfo),
12056+ GFP_NOFS);
12057+ if (unlikely(!lkup->dirren.drinfo)) {
12058+ err = -ENOMEM;
12059+ goto out;
12060+ }
12061+ lkup->dirren.ninfo = w.ninfo;
12062+ }
12063+ w.drinfo = lkup->dirren.drinfo;
12064+ w.no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID);
12065+ w.h_ppath.dentry = au_h_dptr(dentry, btgt);
12066+ AuDebugOn(!w.h_ppath.dentry);
12067+ w.h_ppath.mnt = au_sbr_mnt(sb, btgt);
12068+ w.qname = &dentry->d_name;
12069+
12070+ ninfo = 0;
12071+ for (bindex = btgt + 1; bindex <= bbot; bindex++) {
12072+ br = au_sbr(sb, bindex);
12073+ err = au_drinfo_load(&w, bindex, br);
12074+ if (unlikely(err))
12075+ goto out_free;
12076+ if (w.drinfo[bindex])
12077+ ninfo++;
12078+ }
12079+ if (!ninfo) {
12080+ br = au_sbr(sb, btgt);
12081+ h_dir = d_inode(w.h_ppath.dentry);
12082+ ent = au_dr_hino_find(&br->br_dirren, h_dir->i_ino);
12083+ AuDebugOn(!ent);
12084+ au_dr_hino_del(&br->br_dirren, ent);
9f237c51 12085+ au_kfree_rcu(ent);
8b6a4947
AM
12086+ }
12087+ goto out; /* success */
12088+
12089+out_free:
12090+ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo);
12091+ lkup->dirren.ninfo = 0;
12092+ lkup->dirren.drinfo = NULL;
12093+out:
12094+ AuTraceErr(err);
12095+ return err;
12096+}
12097+
12098+void au_dr_lkup_fin(struct au_do_lookup_args *lkup)
12099+{
12100+ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo);
12101+}
12102+
12103+int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt)
12104+{
12105+ int err;
12106+ struct au_drinfo *drinfo;
12107+
12108+ err = 0;
12109+ if (!lkup->dirren.drinfo)
12110+ goto out;
43982f53
AM
12111+ AuDebugOn(lkup->dirren.ninfo <= btgt);
12112+ drinfo = lkup->dirren.drinfo[btgt];
8b6a4947
AM
12113+ if (!drinfo)
12114+ goto out;
12115+
9f237c51 12116+ au_kfree_try_rcu(lkup->whname.name);
8b6a4947
AM
12117+ lkup->whname.name = NULL;
12118+ lkup->dirren.dr_name.len = drinfo->oldnamelen;
12119+ lkup->dirren.dr_name.name = drinfo->oldname;
12120+ lkup->name = &lkup->dirren.dr_name;
12121+ err = au_wh_name_alloc(&lkup->whname, lkup->name);
12122+ if (!err)
12123+ AuDbg("name %.*s, whname %.*s, b%d\n",
12124+ AuLNPair(lkup->name), AuLNPair(&lkup->whname),
12125+ btgt);
12126+
12127+out:
12128+ AuTraceErr(err);
12129+ return err;
12130+}
12131+
12132+int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex,
12133+ ino_t h_ino)
12134+{
12135+ int match;
12136+ struct au_drinfo *drinfo;
12137+
12138+ match = 1;
12139+ if (!lkup->dirren.drinfo)
12140+ goto out;
43982f53
AM
12141+ AuDebugOn(lkup->dirren.ninfo <= bindex);
12142+ drinfo = lkup->dirren.drinfo[bindex];
8b6a4947
AM
12143+ if (!drinfo)
12144+ goto out;
12145+
12146+ match = (drinfo->ino == h_ino);
12147+ AuDbg("match %d\n", match);
12148+
12149+out:
12150+ return match;
12151+}
12152+
12153+/* ---------------------------------------------------------------------- */
12154+
12155+int au_dr_opt_set(struct super_block *sb)
12156+{
12157+ int err;
12158+ aufs_bindex_t bindex, bbot;
12159+ struct au_branch *br;
12160+
12161+ err = 0;
12162+ bbot = au_sbbot(sb);
12163+ for (bindex = 0; !err && bindex <= bbot; bindex++) {
12164+ br = au_sbr(sb, bindex);
12165+ err = au_dr_hino(sb, bindex, /*br*/NULL, &br->br_path);
12166+ }
12167+
12168+ return err;
12169+}
12170+
12171+int au_dr_opt_flush(struct super_block *sb)
12172+{
12173+ int err;
12174+ aufs_bindex_t bindex, bbot;
12175+ struct au_branch *br;
12176+
12177+ err = 0;
12178+ bbot = au_sbbot(sb);
12179+ for (bindex = 0; !err && bindex <= bbot; bindex++) {
12180+ br = au_sbr(sb, bindex);
12181+ if (au_br_writable(br->br_perm))
12182+ err = au_dr_hino(sb, bindex, /*br*/NULL, /*path*/NULL);
12183+ }
12184+
12185+ return err;
12186+}
12187+
12188+int au_dr_opt_clr(struct super_block *sb, int no_flush)
12189+{
12190+ int err;
12191+ aufs_bindex_t bindex, bbot;
12192+ struct au_branch *br;
12193+
12194+ err = 0;
12195+ if (!no_flush) {
12196+ err = au_dr_opt_flush(sb);
12197+ if (unlikely(err))
12198+ goto out;
12199+ }
12200+
12201+ bbot = au_sbbot(sb);
12202+ for (bindex = 0; bindex <= bbot; bindex++) {
12203+ br = au_sbr(sb, bindex);
12204+ au_dr_hino_free(&br->br_dirren);
12205+ }
12206+
12207+out:
12208+ return err;
12209+}
12210diff -urN /usr/share/empty/fs/aufs/dirren.h linux/fs/aufs/dirren.h
eca34b5c 12211--- /usr/share/empty/fs/aufs/dirren.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 12212+++ linux/fs/aufs/dirren.h 2021-05-02 20:15:14.673337458 +0200
062440b3
AM
12213@@ -0,0 +1,140 @@
12214+/* SPDX-License-Identifier: GPL-2.0 */
8b6a4947 12215+/*
d58c55f2 12216+ * Copyright (C) 2017-2020 Junjiro R. Okajima
8b6a4947
AM
12217+ *
12218+ * This program, aufs is free software; you can redistribute it and/or modify
12219+ * it under the terms of the GNU General Public License as published by
12220+ * the Free Software Foundation; either version 2 of the License, or
12221+ * (at your option) any later version.
12222+ *
12223+ * This program is distributed in the hope that it will be useful,
12224+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12225+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12226+ * GNU General Public License for more details.
12227+ *
12228+ * You should have received a copy of the GNU General Public License
12229+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
12230+ */
12231+
12232+/*
12233+ * renamed dir info
12234+ */
12235+
12236+#ifndef __AUFS_DIRREN_H__
12237+#define __AUFS_DIRREN_H__
12238+
12239+#ifdef __KERNEL__
12240+
12241+#include <linux/dcache.h>
12242+#include <linux/statfs.h>
12243+#include <linux/uuid.h>
12244+#include "hbl.h"
12245+
12246+#define AuDirren_NHASH 100
12247+
12248+#ifdef CONFIG_AUFS_DIRREN
12249+enum au_brid_type {
12250+ AuBrid_Unset,
12251+ AuBrid_UUID,
12252+ AuBrid_FSID,
12253+ AuBrid_DEV
12254+};
12255+
12256+struct au_dr_brid {
12257+ enum au_brid_type type;
12258+ union {
12259+ uuid_t uuid; /* unimplemented yet */
12260+ fsid_t fsid;
12261+ dev_t dev;
12262+ };
12263+};
12264+
12265+/* 20 is the max digits length of ulong 64 */
12266+/* brid-type "_" uuid "_" inum */
12267+#define AUFS_DIRREN_FNAME_SZ (1 + 1 + UUID_STRING_LEN + 20)
12268+#define AUFS_DIRREN_ENV_VAL_SZ (AUFS_DIRREN_FNAME_SZ + 1 + 20)
12269+
12270+struct au_dr_hino {
12271+ struct hlist_bl_node dr_hnode;
12272+ ino_t dr_h_ino;
12273+};
12274+
12275+struct au_dr_br {
12276+ struct hlist_bl_head dr_h_ino[AuDirren_NHASH];
12277+ struct au_dr_brid dr_brid;
12278+};
12279+
12280+struct au_dr_lookup {
12281+ /* dr_name is pointed by struct au_do_lookup_args.name */
12282+ struct qstr dr_name; /* subset of dr_info */
12283+ aufs_bindex_t ninfo;
12284+ struct au_drinfo **drinfo;
12285+};
12286+#else
12287+struct au_dr_hino;
12288+/* empty */
12289+struct au_dr_br { };
12290+struct au_dr_lookup { };
12291+#endif
12292+
12293+/* ---------------------------------------------------------------------- */
12294+
12295+struct au_branch;
12296+struct au_do_lookup_args;
12297+struct au_hinode;
12298+#ifdef CONFIG_AUFS_DIRREN
12299+int au_dr_hino_test_add(struct au_dr_br *dr, ino_t h_ino,
12300+ struct au_dr_hino *add_ent);
12301+void au_dr_hino_free(struct au_dr_br *dr);
12302+int au_dr_br_init(struct super_block *sb, struct au_branch *br,
12303+ const struct path *path);
12304+int au_dr_br_fin(struct super_block *sb, struct au_branch *br);
12305+int au_dr_rename(struct dentry *src, aufs_bindex_t bindex,
12306+ struct qstr *dst_name, void *_rev);
12307+void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *rev);
12308+void au_dr_rename_rev(struct dentry *src, aufs_bindex_t bindex, void *rev);
12309+int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry,
12310+ aufs_bindex_t bindex);
12311+int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt);
12312+int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex,
12313+ ino_t h_ino);
12314+void au_dr_lkup_fin(struct au_do_lookup_args *lkup);
12315+int au_dr_opt_set(struct super_block *sb);
12316+int au_dr_opt_flush(struct super_block *sb);
12317+int au_dr_opt_clr(struct super_block *sb, int no_flush);
12318+#else
12319+AuStubInt0(au_dr_hino_test_add, struct au_dr_br *dr, ino_t h_ino,
12320+ struct au_dr_hino *add_ent);
12321+AuStubVoid(au_dr_hino_free, struct au_dr_br *dr);
12322+AuStubInt0(au_dr_br_init, struct super_block *sb, struct au_branch *br,
12323+ const struct path *path);
12324+AuStubInt0(au_dr_br_fin, struct super_block *sb, struct au_branch *br);
12325+AuStubInt0(au_dr_rename, struct dentry *src, aufs_bindex_t bindex,
12326+ struct qstr *dst_name, void *_rev);
12327+AuStubVoid(au_dr_rename_fin, struct dentry *src, aufs_bindex_t btgt, void *rev);
12328+AuStubVoid(au_dr_rename_rev, struct dentry *src, aufs_bindex_t bindex,
12329+ void *rev);
12330+AuStubInt0(au_dr_lkup, struct au_do_lookup_args *lkup, struct dentry *dentry,
12331+ aufs_bindex_t bindex);
12332+AuStubInt0(au_dr_lkup_name, struct au_do_lookup_args *lkup, aufs_bindex_t btgt);
12333+AuStubInt0(au_dr_lkup_h_ino, struct au_do_lookup_args *lkup,
12334+ aufs_bindex_t bindex, ino_t h_ino);
12335+AuStubVoid(au_dr_lkup_fin, struct au_do_lookup_args *lkup);
12336+AuStubInt0(au_dr_opt_set, struct super_block *sb);
12337+AuStubInt0(au_dr_opt_flush, struct super_block *sb);
12338+AuStubInt0(au_dr_opt_clr, struct super_block *sb, int no_flush);
12339+#endif
12340+
12341+/* ---------------------------------------------------------------------- */
12342+
12343+#ifdef CONFIG_AUFS_DIRREN
12344+static inline int au_dr_ihash(ino_t h_ino)
12345+{
12346+ return h_ino % AuDirren_NHASH;
12347+}
12348+#else
12349+AuStubInt0(au_dr_ihash, ino_t h_ino);
12350+#endif
12351+
12352+#endif /* __KERNEL__ */
12353+#endif /* __AUFS_DIRREN_H__ */
7f207e10 12354diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
eca34b5c 12355--- /usr/share/empty/fs/aufs/dynop.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 12356+++ linux/fs/aufs/dynop.c 2021-05-02 20:15:14.673337458 +0200
e37dd06a 12357@@ -0,0 +1,368 @@
cd7a4cd9 12358+// SPDX-License-Identifier: GPL-2.0
1facf9fc 12359+/*
d58c55f2 12360+ * Copyright (C) 2010-2020 Junjiro R. Okajima
1facf9fc 12361+ *
12362+ * This program, aufs is free software; you can redistribute it and/or modify
12363+ * it under the terms of the GNU General Public License as published by
12364+ * the Free Software Foundation; either version 2 of the License, or
12365+ * (at your option) any later version.
dece6358
AM
12366+ *
12367+ * This program is distributed in the hope that it will be useful,
12368+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12369+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12370+ * GNU General Public License for more details.
12371+ *
12372+ * You should have received a copy of the GNU General Public License
523b37e3 12373+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 12374+ */
12375+
12376+/*
4a4d8108 12377+ * dynamically customizable operations for regular files
1facf9fc 12378+ */
12379+
1facf9fc 12380+#include "aufs.h"
12381+
4a4d8108 12382+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop)
1facf9fc 12383+
4a4d8108
AM
12384+/*
12385+ * How large will these lists be?
12386+ * Usually just a few elements, 20-30 at most for each, I guess.
12387+ */
8b6a4947 12388+static struct hlist_bl_head dynop[AuDyLast];
4a4d8108 12389+
8b6a4947
AM
12390+static struct au_dykey *dy_gfind_get(struct hlist_bl_head *hbl,
12391+ const void *h_op)
1facf9fc 12392+{
4a4d8108 12393+ struct au_dykey *key, *tmp;
8b6a4947 12394+ struct hlist_bl_node *pos;
1facf9fc 12395+
4a4d8108 12396+ key = NULL;
8b6a4947
AM
12397+ hlist_bl_lock(hbl);
12398+ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode)
4a4d8108 12399+ if (tmp->dk_op.dy_hop == h_op) {
83b672a5
AM
12400+ if (kref_get_unless_zero(&tmp->dk_kref))
12401+ key = tmp;
4a4d8108
AM
12402+ break;
12403+ }
8b6a4947 12404+ hlist_bl_unlock(hbl);
4a4d8108
AM
12405+
12406+ return key;
1facf9fc 12407+}
12408+
4a4d8108 12409+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key)
1facf9fc 12410+{
4a4d8108
AM
12411+ struct au_dykey **k, *found;
12412+ const void *h_op = key->dk_op.dy_hop;
12413+ int i;
1facf9fc 12414+
4a4d8108
AM
12415+ found = NULL;
12416+ k = br->br_dykey;
12417+ for (i = 0; i < AuBrDynOp; i++)
12418+ if (k[i]) {
12419+ if (k[i]->dk_op.dy_hop == h_op) {
12420+ found = k[i];
12421+ break;
12422+ }
12423+ } else
12424+ break;
12425+ if (!found) {
12426+ spin_lock(&br->br_dykey_lock);
12427+ for (; i < AuBrDynOp; i++)
12428+ if (k[i]) {
12429+ if (k[i]->dk_op.dy_hop == h_op) {
12430+ found = k[i];
12431+ break;
12432+ }
12433+ } else {
12434+ k[i] = key;
12435+ break;
12436+ }
12437+ spin_unlock(&br->br_dykey_lock);
12438+ BUG_ON(i == AuBrDynOp); /* expand the array */
12439+ }
12440+
12441+ return found;
1facf9fc 12442+}
12443+
4a4d8108 12444+/* kref_get() if @key is already added */
8b6a4947 12445+static struct au_dykey *dy_gadd(struct hlist_bl_head *hbl, struct au_dykey *key)
4a4d8108
AM
12446+{
12447+ struct au_dykey *tmp, *found;
8b6a4947 12448+ struct hlist_bl_node *pos;
4a4d8108 12449+ const void *h_op = key->dk_op.dy_hop;
1facf9fc 12450+
4a4d8108 12451+ found = NULL;
8b6a4947
AM
12452+ hlist_bl_lock(hbl);
12453+ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode)
4a4d8108 12454+ if (tmp->dk_op.dy_hop == h_op) {
83b672a5
AM
12455+ if (kref_get_unless_zero(&tmp->dk_kref))
12456+ found = tmp;
4a4d8108
AM
12457+ break;
12458+ }
12459+ if (!found)
8b6a4947
AM
12460+ hlist_bl_add_head(&key->dk_hnode, hbl);
12461+ hlist_bl_unlock(hbl);
1facf9fc 12462+
4a4d8108
AM
12463+ if (!found)
12464+ DyPrSym(key);
12465+ return found;
12466+}
12467+
12468+static void dy_free_rcu(struct rcu_head *rcu)
1facf9fc 12469+{
4a4d8108
AM
12470+ struct au_dykey *key;
12471+
12472+ key = container_of(rcu, struct au_dykey, dk_rcu);
12473+ DyPrSym(key);
83b672a5 12474+ kfree(key);
1facf9fc 12475+}
12476+
4a4d8108
AM
12477+static void dy_free(struct kref *kref)
12478+{
12479+ struct au_dykey *key;
8b6a4947 12480+ struct hlist_bl_head *hbl;
1facf9fc 12481+
4a4d8108 12482+ key = container_of(kref, struct au_dykey, dk_kref);
8b6a4947
AM
12483+ hbl = dynop + key->dk_op.dy_type;
12484+ au_hbl_del(&key->dk_hnode, hbl);
4a4d8108
AM
12485+ call_rcu(&key->dk_rcu, dy_free_rcu);
12486+}
12487+
12488+void au_dy_put(struct au_dykey *key)
1facf9fc 12489+{
4a4d8108
AM
12490+ kref_put(&key->dk_kref, dy_free);
12491+}
1facf9fc 12492+
4a4d8108
AM
12493+/* ---------------------------------------------------------------------- */
12494+
12495+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *))
12496+
12497+#ifdef CONFIG_AUFS_DEBUG
12498+#define DyDbgDeclare(cnt) unsigned int cnt = 0
4f0767ce 12499+#define DyDbgInc(cnt) do { cnt++; } while (0)
4a4d8108
AM
12500+#else
12501+#define DyDbgDeclare(cnt) do {} while (0)
12502+#define DyDbgInc(cnt) do {} while (0)
12503+#endif
12504+
12505+#define DySet(func, dst, src, h_op, h_sb) do { \
12506+ DyDbgInc(cnt); \
12507+ if (h_op->func) { \
12508+ if (src.func) \
12509+ dst.func = src.func; \
12510+ else \
12511+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \
12512+ } \
12513+} while (0)
12514+
12515+#define DySetForce(func, dst, src) do { \
12516+ AuDebugOn(!src.func); \
12517+ DyDbgInc(cnt); \
12518+ dst.func = src.func; \
12519+} while (0)
12520+
12521+#define DySetAop(func) \
12522+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
12523+#define DySetAopForce(func) \
12524+ DySetForce(func, dyaop->da_op, aufs_aop)
12525+
12526+static void dy_aop(struct au_dykey *key, const void *h_op,
12527+ struct super_block *h_sb __maybe_unused)
12528+{
12529+ struct au_dyaop *dyaop = (void *)key;
12530+ const struct address_space_operations *h_aop = h_op;
12531+ DyDbgDeclare(cnt);
12532+
12533+ AuDbg("%s\n", au_sbtype(h_sb));
12534+
12535+ DySetAop(writepage);
12536+ DySetAopForce(readpage); /* force */
4a4d8108
AM
12537+ DySetAop(writepages);
12538+ DySetAop(set_page_dirty);
12539+ DySetAop(readpages);
e37dd06a 12540+ DySetAop(readahead);
4a4d8108
AM
12541+ DySetAop(write_begin);
12542+ DySetAop(write_end);
12543+ DySetAop(bmap);
12544+ DySetAop(invalidatepage);
12545+ DySetAop(releasepage);
027c5e7a 12546+ DySetAop(freepage);
7e9cd9fe 12547+ /* this one will be changed according to an aufs mount option */
4a4d8108 12548+ DySetAop(direct_IO);
4a4d8108 12549+ DySetAop(migratepage);
e2f27e51
AM
12550+ DySetAop(isolate_page);
12551+ DySetAop(putback_page);
4a4d8108
AM
12552+ DySetAop(launder_page);
12553+ DySetAop(is_partially_uptodate);
392086de 12554+ DySetAop(is_dirty_writeback);
4a4d8108 12555+ DySetAop(error_remove_page);
b4510431
AM
12556+ DySetAop(swap_activate);
12557+ DySetAop(swap_deactivate);
4a4d8108
AM
12558+
12559+ DyDbgSize(cnt, *h_aop);
4a4d8108
AM
12560+}
12561+
4a4d8108
AM
12562+/* ---------------------------------------------------------------------- */
12563+
12564+static void dy_bug(struct kref *kref)
12565+{
12566+ BUG();
12567+}
12568+
12569+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
12570+{
12571+ struct au_dykey *key, *old;
8b6a4947 12572+ struct hlist_bl_head *hbl;
b752ccd1 12573+ struct op {
4a4d8108 12574+ unsigned int sz;
b752ccd1
AM
12575+ void (*set)(struct au_dykey *key, const void *h_op,
12576+ struct super_block *h_sb __maybe_unused);
12577+ };
12578+ static const struct op a[] = {
4a4d8108
AM
12579+ [AuDy_AOP] = {
12580+ .sz = sizeof(struct au_dyaop),
b752ccd1 12581+ .set = dy_aop
4a4d8108 12582+ }
b752ccd1
AM
12583+ };
12584+ const struct op *p;
4a4d8108 12585+
8b6a4947
AM
12586+ hbl = dynop + op->dy_type;
12587+ key = dy_gfind_get(hbl, op->dy_hop);
4a4d8108
AM
12588+ if (key)
12589+ goto out_add; /* success */
12590+
12591+ p = a + op->dy_type;
12592+ key = kzalloc(p->sz, GFP_NOFS);
12593+ if (unlikely(!key)) {
12594+ key = ERR_PTR(-ENOMEM);
12595+ goto out;
12596+ }
12597+
12598+ key->dk_op.dy_hop = op->dy_hop;
12599+ kref_init(&key->dk_kref);
86dc4139 12600+ p->set(key, op->dy_hop, au_br_sb(br));
8b6a4947 12601+ old = dy_gadd(hbl, key);
4a4d8108 12602+ if (old) {
9f237c51 12603+ au_kfree_rcu(key);
4a4d8108
AM
12604+ key = old;
12605+ }
12606+
12607+out_add:
12608+ old = dy_bradd(br, key);
12609+ if (old)
12610+ /* its ref-count should never be zero here */
12611+ kref_put(&key->dk_kref, dy_bug);
12612+out:
12613+ return key;
12614+}
12615+
12616+/* ---------------------------------------------------------------------- */
12617+/*
acd2b654 12618+ * Aufs prohibits O_DIRECT by default even if the branch supports it.
c1595e42 12619+ * This behaviour is necessary to return an error from open(O_DIRECT) instead
4a4d8108
AM
12620+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
12621+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
12622+ * See the aufs manual in detail.
4a4d8108
AM
12623+ */
12624+static void dy_adx(struct au_dyaop *dyaop, int do_dx)
12625+{
7e9cd9fe 12626+ if (!do_dx)
4a4d8108 12627+ dyaop->da_op.direct_IO = NULL;
7e9cd9fe 12628+ else
4a4d8108 12629+ dyaop->da_op.direct_IO = aufs_aop.direct_IO;
4a4d8108
AM
12630+}
12631+
12632+static struct au_dyaop *dy_aget(struct au_branch *br,
12633+ const struct address_space_operations *h_aop,
12634+ int do_dx)
12635+{
12636+ struct au_dyaop *dyaop;
12637+ struct au_dynop op;
12638+
12639+ op.dy_type = AuDy_AOP;
12640+ op.dy_haop = h_aop;
12641+ dyaop = (void *)dy_get(&op, br);
12642+ if (IS_ERR(dyaop))
12643+ goto out;
12644+ dy_adx(dyaop, do_dx);
12645+
12646+out:
12647+ return dyaop;
12648+}
12649+
12650+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
12651+ struct inode *h_inode)
12652+{
12653+ int err, do_dx;
12654+ struct super_block *sb;
12655+ struct au_branch *br;
12656+ struct au_dyaop *dyaop;
12657+
12658+ AuDebugOn(!S_ISREG(h_inode->i_mode));
12659+ IiMustWriteLock(inode);
12660+
12661+ sb = inode->i_sb;
12662+ br = au_sbr(sb, bindex);
12663+ do_dx = !!au_opt_test(au_mntflags(sb), DIO);
12664+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx);
12665+ err = PTR_ERR(dyaop);
12666+ if (IS_ERR(dyaop))
12667+ /* unnecessary to call dy_fput() */
12668+ goto out;
12669+
12670+ err = 0;
12671+ inode->i_mapping->a_ops = &dyaop->da_op;
12672+
12673+out:
12674+ return err;
12675+}
12676+
b752ccd1
AM
12677+/*
12678+ * Is it safe to replace a_ops during the inode/file is in operation?
12679+ * Yes, I hope so.
12680+ */
12681+int au_dy_irefresh(struct inode *inode)
12682+{
12683+ int err;
5afbbe0d 12684+ aufs_bindex_t btop;
b752ccd1
AM
12685+ struct inode *h_inode;
12686+
12687+ err = 0;
12688+ if (S_ISREG(inode->i_mode)) {
5afbbe0d
AM
12689+ btop = au_ibtop(inode);
12690+ h_inode = au_h_iptr(inode, btop);
12691+ err = au_dy_iaop(inode, btop, h_inode);
b752ccd1
AM
12692+ }
12693+ return err;
12694+}
12695+
4a4d8108
AM
12696+void au_dy_arefresh(int do_dx)
12697+{
8b6a4947
AM
12698+ struct hlist_bl_head *hbl;
12699+ struct hlist_bl_node *pos;
4a4d8108
AM
12700+ struct au_dykey *key;
12701+
8b6a4947
AM
12702+ hbl = dynop + AuDy_AOP;
12703+ hlist_bl_lock(hbl);
12704+ hlist_bl_for_each_entry(key, pos, hbl, dk_hnode)
4a4d8108 12705+ dy_adx((void *)key, do_dx);
8b6a4947 12706+ hlist_bl_unlock(hbl);
4a4d8108
AM
12707+}
12708+
4a4d8108
AM
12709+/* ---------------------------------------------------------------------- */
12710+
12711+void __init au_dy_init(void)
12712+{
12713+ int i;
12714+
4a4d8108 12715+ for (i = 0; i < AuDyLast; i++)
8b6a4947 12716+ INIT_HLIST_BL_HEAD(dynop + i);
4a4d8108
AM
12717+}
12718+
12719+void au_dy_fin(void)
12720+{
12721+ int i;
12722+
12723+ for (i = 0; i < AuDyLast; i++)
8b6a4947 12724+ WARN_ON(!hlist_bl_empty(dynop + i));
4a4d8108 12725+}
7f207e10 12726diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
eca34b5c 12727--- /usr/share/empty/fs/aufs/dynop.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 12728+++ linux/fs/aufs/dynop.h 2021-05-02 20:15:14.673337458 +0200
fbc438ed 12729@@ -0,0 +1,77 @@
062440b3 12730+/* SPDX-License-Identifier: GPL-2.0 */
4a4d8108 12731+/*
d58c55f2 12732+ * Copyright (C) 2010-2020 Junjiro R. Okajima
4a4d8108
AM
12733+ *
12734+ * This program, aufs is free software; you can redistribute it and/or modify
12735+ * it under the terms of the GNU General Public License as published by
12736+ * the Free Software Foundation; either version 2 of the License, or
12737+ * (at your option) any later version.
12738+ *
12739+ * This program is distributed in the hope that it will be useful,
12740+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12741+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12742+ * GNU General Public License for more details.
12743+ *
12744+ * You should have received a copy of the GNU General Public License
523b37e3 12745+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
12746+ */
12747+
12748+/*
12749+ * dynamically customizable operations (for regular files only)
12750+ */
12751+
12752+#ifndef __AUFS_DYNOP_H__
12753+#define __AUFS_DYNOP_H__
12754+
12755+#ifdef __KERNEL__
12756+
7e9cd9fe
AM
12757+#include <linux/fs.h>
12758+#include <linux/kref.h>
4a4d8108 12759+
2cbb1c4b 12760+enum {AuDy_AOP, AuDyLast};
4a4d8108
AM
12761+
12762+struct au_dynop {
12763+ int dy_type;
12764+ union {
12765+ const void *dy_hop;
12766+ const struct address_space_operations *dy_haop;
4a4d8108
AM
12767+ };
12768+};
12769+
12770+struct au_dykey {
12771+ union {
8b6a4947 12772+ struct hlist_bl_node dk_hnode;
4a4d8108
AM
12773+ struct rcu_head dk_rcu;
12774+ };
12775+ struct au_dynop dk_op;
12776+
12777+ /*
12778+ * during I am in the branch local array, kref is gotten. when the
12779+ * branch is removed, kref is put.
12780+ */
12781+ struct kref dk_kref;
12782+};
12783+
12784+/* stop unioning since their sizes are very different from each other */
12785+struct au_dyaop {
12786+ struct au_dykey da_key;
12787+ struct address_space_operations da_op; /* not const */
4a4d8108 12788+};
fbc438ed
JR
12789+/* make sure that 'struct au_dykey *' can be any type */
12790+static_assert(!offsetof(struct au_dyaop, da_key));
4a4d8108 12791+
4a4d8108
AM
12792+/* ---------------------------------------------------------------------- */
12793+
12794+/* dynop.c */
12795+struct au_branch;
12796+void au_dy_put(struct au_dykey *key);
12797+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
12798+ struct inode *h_inode);
b752ccd1 12799+int au_dy_irefresh(struct inode *inode);
4a4d8108 12800+void au_dy_arefresh(int do_dio);
4a4d8108
AM
12801+
12802+void __init au_dy_init(void);
12803+void au_dy_fin(void);
12804+
4a4d8108
AM
12805+#endif /* __KERNEL__ */
12806+#endif /* __AUFS_DYNOP_H__ */
7f207e10 12807diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
eca34b5c 12808--- /usr/share/empty/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 12809+++ linux/fs/aufs/export.c 2021-05-02 20:15:14.673337458 +0200
e37dd06a 12810@@ -0,0 +1,837 @@
cd7a4cd9 12811+// SPDX-License-Identifier: GPL-2.0
4a4d8108 12812+/*
d58c55f2 12813+ * Copyright (C) 2005-2020 Junjiro R. Okajima
4a4d8108
AM
12814+ *
12815+ * This program, aufs is free software; you can redistribute it and/or modify
12816+ * it under the terms of the GNU General Public License as published by
12817+ * the Free Software Foundation; either version 2 of the License, or
12818+ * (at your option) any later version.
12819+ *
12820+ * This program is distributed in the hope that it will be useful,
12821+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12822+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12823+ * GNU General Public License for more details.
12824+ *
12825+ * You should have received a copy of the GNU General Public License
523b37e3 12826+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
12827+ */
12828+
12829+/*
12830+ * export via nfs
12831+ */
12832+
12833+#include <linux/exportfs.h>
7eafdf33 12834+#include <linux/fs_struct.h>
4a4d8108
AM
12835+#include <linux/namei.h>
12836+#include <linux/nsproxy.h>
12837+#include <linux/random.h>
12838+#include <linux/writeback.h>
12839+#include "aufs.h"
12840+
12841+union conv {
12842+#ifdef CONFIG_AUFS_INO_T_64
12843+ __u32 a[2];
12844+#else
12845+ __u32 a[1];
12846+#endif
12847+ ino_t ino;
12848+};
12849+
12850+static ino_t decode_ino(__u32 *a)
12851+{
12852+ union conv u;
12853+
12854+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
12855+ u.a[0] = a[0];
12856+#ifdef CONFIG_AUFS_INO_T_64
12857+ u.a[1] = a[1];
12858+#endif
12859+ return u.ino;
12860+}
12861+
12862+static void encode_ino(__u32 *a, ino_t ino)
12863+{
12864+ union conv u;
12865+
12866+ u.ino = ino;
12867+ a[0] = u.a[0];
12868+#ifdef CONFIG_AUFS_INO_T_64
12869+ a[1] = u.a[1];
12870+#endif
12871+}
12872+
12873+/* NFS file handle */
12874+enum {
12875+ Fh_br_id,
12876+ Fh_sigen,
12877+#ifdef CONFIG_AUFS_INO_T_64
12878+ /* support 64bit inode number */
12879+ Fh_ino1,
12880+ Fh_ino2,
12881+ Fh_dir_ino1,
12882+ Fh_dir_ino2,
12883+#else
12884+ Fh_ino1,
12885+ Fh_dir_ino1,
12886+#endif
12887+ Fh_igen,
12888+ Fh_h_type,
12889+ Fh_tail,
12890+
12891+ Fh_ino = Fh_ino1,
12892+ Fh_dir_ino = Fh_dir_ino1
12893+};
12894+
12895+static int au_test_anon(struct dentry *dentry)
12896+{
027c5e7a 12897+ /* note: read d_flags without d_lock */
4a4d8108
AM
12898+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
12899+}
12900+
a2a7ad62
AM
12901+int au_test_nfsd(void)
12902+{
12903+ int ret;
12904+ struct task_struct *tsk = current;
12905+ char comm[sizeof(tsk->comm)];
12906+
12907+ ret = 0;
12908+ if (tsk->flags & PF_KTHREAD) {
12909+ get_task_comm(comm, tsk);
12910+ ret = !strcmp(comm, "nfsd");
12911+ }
12912+
12913+ return ret;
12914+}
12915+
4a4d8108
AM
12916+/* ---------------------------------------------------------------------- */
12917+/* inode generation external table */
12918+
b752ccd1 12919+void au_xigen_inc(struct inode *inode)
4a4d8108 12920+{
4a4d8108
AM
12921+ loff_t pos;
12922+ ssize_t sz;
12923+ __u32 igen;
12924+ struct super_block *sb;
12925+ struct au_sbinfo *sbinfo;
12926+
4a4d8108 12927+ sb = inode->i_sb;
b752ccd1 12928+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
1facf9fc 12929+
b752ccd1 12930+ sbinfo = au_sbi(sb);
1facf9fc 12931+ pos = inode->i_ino;
12932+ pos *= sizeof(igen);
12933+ igen = inode->i_generation + 1;
e37dd06a 12934+ sz = xino_fwrite(sbinfo->si_xigen, &igen, sizeof(igen), &pos);
1facf9fc 12935+ if (sz == sizeof(igen))
b752ccd1 12936+ return; /* success */
1facf9fc 12937+
b752ccd1 12938+ if (unlikely(sz >= 0))
1facf9fc 12939+ AuIOErr("xigen error (%zd)\n", sz);
1facf9fc 12940+}
12941+
12942+int au_xigen_new(struct inode *inode)
12943+{
12944+ int err;
12945+ loff_t pos;
12946+ ssize_t sz;
12947+ struct super_block *sb;
12948+ struct au_sbinfo *sbinfo;
12949+ struct file *file;
12950+
12951+ err = 0;
12952+ /* todo: dirty, at mount time */
12953+ if (inode->i_ino == AUFS_ROOT_INO)
12954+ goto out;
12955+ sb = inode->i_sb;
dece6358 12956+ SiMustAnyLock(sb);
1facf9fc 12957+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
12958+ goto out;
12959+
12960+ err = -EFBIG;
12961+ pos = inode->i_ino;
12962+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
12963+ AuIOErr1("too large i%lld\n", pos);
12964+ goto out;
12965+ }
12966+ pos *= sizeof(inode->i_generation);
12967+
12968+ err = 0;
12969+ sbinfo = au_sbi(sb);
12970+ file = sbinfo->si_xigen;
12971+ BUG_ON(!file);
12972+
c06a8ce3 12973+ if (vfsub_f_size_read(file)
1facf9fc 12974+ < pos + sizeof(inode->i_generation)) {
12975+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
e37dd06a 12976+ sz = xino_fwrite(file, &inode->i_generation,
1facf9fc 12977+ sizeof(inode->i_generation), &pos);
12978+ } else
e37dd06a 12979+ sz = xino_fread(file, &inode->i_generation,
1facf9fc 12980+ sizeof(inode->i_generation), &pos);
12981+ if (sz == sizeof(inode->i_generation))
12982+ goto out; /* success */
12983+
12984+ err = sz;
12985+ if (unlikely(sz >= 0)) {
12986+ err = -EIO;
12987+ AuIOErr("xigen error (%zd)\n", sz);
12988+ }
12989+
4f0767ce 12990+out:
1facf9fc 12991+ return err;
12992+}
12993+
062440b3 12994+int au_xigen_set(struct super_block *sb, struct path *path)
1facf9fc 12995+{
12996+ int err;
12997+ struct au_sbinfo *sbinfo;
12998+ struct file *file;
12999+
dece6358
AM
13000+ SiMustWriteLock(sb);
13001+
1facf9fc 13002+ sbinfo = au_sbi(sb);
062440b3 13003+ file = au_xino_create2(sb, path, sbinfo->si_xigen);
1facf9fc 13004+ err = PTR_ERR(file);
13005+ if (IS_ERR(file))
13006+ goto out;
13007+ err = 0;
13008+ if (sbinfo->si_xigen)
13009+ fput(sbinfo->si_xigen);
13010+ sbinfo->si_xigen = file;
13011+
4f0767ce 13012+out:
062440b3 13013+ AuTraceErr(err);
1facf9fc 13014+ return err;
13015+}
13016+
13017+void au_xigen_clr(struct super_block *sb)
13018+{
13019+ struct au_sbinfo *sbinfo;
13020+
dece6358
AM
13021+ SiMustWriteLock(sb);
13022+
1facf9fc 13023+ sbinfo = au_sbi(sb);
13024+ if (sbinfo->si_xigen) {
13025+ fput(sbinfo->si_xigen);
13026+ sbinfo->si_xigen = NULL;
13027+ }
13028+}
13029+
13030+/* ---------------------------------------------------------------------- */
13031+
13032+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
13033+ ino_t dir_ino)
13034+{
13035+ struct dentry *dentry, *d;
13036+ struct inode *inode;
13037+ unsigned int sigen;
13038+
13039+ dentry = NULL;
13040+ inode = ilookup(sb, ino);
13041+ if (!inode)
13042+ goto out;
13043+
13044+ dentry = ERR_PTR(-ESTALE);
13045+ sigen = au_sigen(sb);
5afbbe0d 13046+ if (unlikely(au_is_bad_inode(inode)
1facf9fc 13047+ || IS_DEADDIR(inode)
537831f9 13048+ || sigen != au_iigen(inode, NULL)))
1facf9fc 13049+ goto out_iput;
13050+
13051+ dentry = NULL;
13052+ if (!dir_ino || S_ISDIR(inode->i_mode))
13053+ dentry = d_find_alias(inode);
13054+ else {
027c5e7a 13055+ spin_lock(&inode->i_lock);
c1595e42 13056+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) {
027c5e7a 13057+ spin_lock(&d->d_lock);
1facf9fc 13058+ if (!au_test_anon(d)
5527c038 13059+ && d_inode(d->d_parent)->i_ino == dir_ino) {
027c5e7a
AM
13060+ dentry = dget_dlock(d);
13061+ spin_unlock(&d->d_lock);
1facf9fc 13062+ break;
13063+ }
027c5e7a
AM
13064+ spin_unlock(&d->d_lock);
13065+ }
13066+ spin_unlock(&inode->i_lock);
1facf9fc 13067+ }
027c5e7a 13068+ if (unlikely(dentry && au_digen_test(dentry, sigen))) {
2cbb1c4b 13069+ /* need to refresh */
1facf9fc 13070+ dput(dentry);
2cbb1c4b 13071+ dentry = NULL;
1facf9fc 13072+ }
13073+
4f0767ce 13074+out_iput:
1facf9fc 13075+ iput(inode);
4f0767ce 13076+out:
2cbb1c4b 13077+ AuTraceErrPtr(dentry);
1facf9fc 13078+ return dentry;
13079+}
13080+
13081+/* ---------------------------------------------------------------------- */
13082+
13083+/* todo: dirty? */
13084+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
4a4d8108
AM
13085+
13086+struct au_compare_mnt_args {
13087+ /* input */
13088+ struct super_block *sb;
13089+
13090+ /* output */
13091+ struct vfsmount *mnt;
13092+};
13093+
13094+static int au_compare_mnt(struct vfsmount *mnt, void *arg)
13095+{
13096+ struct au_compare_mnt_args *a = arg;
13097+
13098+ if (mnt->mnt_sb != a->sb)
13099+ return 0;
13100+ a->mnt = mntget(mnt);
13101+ return 1;
13102+}
13103+
1facf9fc 13104+static struct vfsmount *au_mnt_get(struct super_block *sb)
13105+{
4a4d8108 13106+ int err;
7eafdf33 13107+ struct path root;
4a4d8108
AM
13108+ struct au_compare_mnt_args args = {
13109+ .sb = sb
13110+ };
1facf9fc 13111+
7eafdf33 13112+ get_fs_root(current->fs, &root);
523b37e3 13113+ rcu_read_lock();
7eafdf33 13114+ err = iterate_mounts(au_compare_mnt, &args, root.mnt);
523b37e3 13115+ rcu_read_unlock();
7eafdf33 13116+ path_put(&root);
4a4d8108
AM
13117+ AuDebugOn(!err);
13118+ AuDebugOn(!args.mnt);
13119+ return args.mnt;
1facf9fc 13120+}
13121+
13122+struct au_nfsd_si_lock {
4a4d8108 13123+ unsigned int sigen;
027c5e7a 13124+ aufs_bindex_t bindex, br_id;
1facf9fc 13125+ unsigned char force_lock;
13126+};
13127+
027c5e7a
AM
13128+static int si_nfsd_read_lock(struct super_block *sb,
13129+ struct au_nfsd_si_lock *nsi_lock)
1facf9fc 13130+{
027c5e7a 13131+ int err;
1facf9fc 13132+ aufs_bindex_t bindex;
13133+
13134+ si_read_lock(sb, AuLock_FLUSH);
13135+
13136+ /* branch id may be wrapped around */
027c5e7a 13137+ err = 0;
1facf9fc 13138+ bindex = au_br_index(sb, nsi_lock->br_id);
13139+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
13140+ goto out; /* success */
13141+
027c5e7a
AM
13142+ err = -ESTALE;
13143+ bindex = -1;
1facf9fc 13144+ if (!nsi_lock->force_lock)
13145+ si_read_unlock(sb);
1facf9fc 13146+
4f0767ce 13147+out:
027c5e7a
AM
13148+ nsi_lock->bindex = bindex;
13149+ return err;
1facf9fc 13150+}
13151+
13152+struct find_name_by_ino {
392086de 13153+ struct dir_context ctx;
1facf9fc 13154+ int called, found;
13155+ ino_t ino;
13156+ char *name;
13157+ int namelen;
13158+};
13159+
13160+static int
392086de
AM
13161+find_name_by_ino(struct dir_context *ctx, const char *name, int namelen,
13162+ loff_t offset, u64 ino, unsigned int d_type)
1facf9fc 13163+{
392086de
AM
13164+ struct find_name_by_ino *a = container_of(ctx, struct find_name_by_ino,
13165+ ctx);
1facf9fc 13166+
13167+ a->called++;
13168+ if (a->ino != ino)
13169+ return 0;
13170+
13171+ memcpy(a->name, name, namelen);
13172+ a->namelen = namelen;
13173+ a->found = 1;
13174+ return 1;
13175+}
13176+
13177+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
13178+ struct au_nfsd_si_lock *nsi_lock)
13179+{
13180+ struct dentry *dentry, *parent;
13181+ struct file *file;
13182+ struct inode *dir;
392086de
AM
13183+ struct find_name_by_ino arg = {
13184+ .ctx = {
2000de60 13185+ .actor = find_name_by_ino
392086de
AM
13186+ }
13187+ };
1facf9fc 13188+ int err;
13189+
13190+ parent = path->dentry;
13191+ if (nsi_lock)
13192+ si_read_unlock(parent->d_sb);
4a4d8108 13193+ file = vfsub_dentry_open(path, au_dir_roflags);
1facf9fc 13194+ dentry = (void *)file;
13195+ if (IS_ERR(file))
13196+ goto out;
13197+
13198+ dentry = ERR_PTR(-ENOMEM);
537831f9 13199+ arg.name = (void *)__get_free_page(GFP_NOFS);
1facf9fc 13200+ if (unlikely(!arg.name))
13201+ goto out_file;
13202+ arg.ino = ino;
13203+ arg.found = 0;
13204+ do {
13205+ arg.called = 0;
13206+ /* smp_mb(); */
392086de 13207+ err = vfsub_iterate_dir(file, &arg.ctx);
1facf9fc 13208+ } while (!err && !arg.found && arg.called);
13209+ dentry = ERR_PTR(err);
13210+ if (unlikely(err))
13211+ goto out_name;
1716fcea
AM
13212+ /* instead of ENOENT */
13213+ dentry = ERR_PTR(-ESTALE);
1facf9fc 13214+ if (!arg.found)
13215+ goto out_name;
13216+
b4510431 13217+ /* do not call vfsub_lkup_one() */
5527c038 13218+ dir = d_inode(parent);
febd17d6 13219+ dentry = vfsub_lookup_one_len_unlocked(arg.name, parent, arg.namelen);
1facf9fc 13220+ AuTraceErrPtr(dentry);
13221+ if (IS_ERR(dentry))
13222+ goto out_name;
13223+ AuDebugOn(au_test_anon(dentry));
5527c038 13224+ if (unlikely(d_really_is_negative(dentry))) {
1facf9fc 13225+ dput(dentry);
13226+ dentry = ERR_PTR(-ENOENT);
13227+ }
13228+
4f0767ce 13229+out_name:
1c60b727 13230+ free_page((unsigned long)arg.name);
4f0767ce 13231+out_file:
1facf9fc 13232+ fput(file);
4f0767ce 13233+out:
1facf9fc 13234+ if (unlikely(nsi_lock
13235+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
13236+ if (!IS_ERR(dentry)) {
13237+ dput(dentry);
13238+ dentry = ERR_PTR(-ESTALE);
13239+ }
13240+ AuTraceErrPtr(dentry);
13241+ return dentry;
13242+}
13243+
13244+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
13245+ ino_t dir_ino,
13246+ struct au_nfsd_si_lock *nsi_lock)
13247+{
13248+ struct dentry *dentry;
13249+ struct path path;
13250+
13251+ if (dir_ino != AUFS_ROOT_INO) {
13252+ path.dentry = decode_by_ino(sb, dir_ino, 0);
13253+ dentry = path.dentry;
13254+ if (!path.dentry || IS_ERR(path.dentry))
13255+ goto out;
13256+ AuDebugOn(au_test_anon(path.dentry));
13257+ } else
13258+ path.dentry = dget(sb->s_root);
13259+
13260+ path.mnt = au_mnt_get(sb);
13261+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
13262+ path_put(&path);
13263+
4f0767ce 13264+out:
1facf9fc 13265+ AuTraceErrPtr(dentry);
13266+ return dentry;
13267+}
13268+
13269+/* ---------------------------------------------------------------------- */
13270+
13271+static int h_acceptable(void *expv, struct dentry *dentry)
13272+{
13273+ return 1;
13274+}
13275+
13276+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
13277+ char *buf, int len, struct super_block *sb)
13278+{
13279+ char *p;
13280+ int n;
13281+ struct path path;
13282+
13283+ p = d_path(h_rootpath, buf, len);
13284+ if (IS_ERR(p))
13285+ goto out;
13286+ n = strlen(p);
13287+
13288+ path.mnt = h_rootpath->mnt;
13289+ path.dentry = h_parent;
13290+ p = d_path(&path, buf, len);
13291+ if (IS_ERR(p))
13292+ goto out;
13293+ if (n != 1)
13294+ p += n;
13295+
13296+ path.mnt = au_mnt_get(sb);
13297+ path.dentry = sb->s_root;
13298+ p = d_path(&path, buf, len - strlen(p));
13299+ mntput(path.mnt);
13300+ if (IS_ERR(p))
13301+ goto out;
13302+ if (n != 1)
13303+ p[strlen(p)] = '/';
13304+
4f0767ce 13305+out:
1facf9fc 13306+ AuTraceErrPtr(p);
13307+ return p;
13308+}
13309+
13310+static
027c5e7a
AM
13311+struct dentry *decode_by_path(struct super_block *sb, ino_t ino, __u32 *fh,
13312+ int fh_len, struct au_nfsd_si_lock *nsi_lock)
1facf9fc 13313+{
13314+ struct dentry *dentry, *h_parent, *root;
13315+ struct super_block *h_sb;
13316+ char *pathname, *p;
13317+ struct vfsmount *h_mnt;
13318+ struct au_branch *br;
13319+ int err;
13320+ struct path path;
13321+
027c5e7a 13322+ br = au_sbr(sb, nsi_lock->bindex);
86dc4139 13323+ h_mnt = au_br_mnt(br);
1facf9fc 13324+ h_sb = h_mnt->mnt_sb;
13325+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
5afbbe0d 13326+ lockdep_off();
1facf9fc 13327+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
13328+ fh_len - Fh_tail, fh[Fh_h_type],
13329+ h_acceptable, /*context*/NULL);
5afbbe0d 13330+ lockdep_on();
1facf9fc 13331+ dentry = h_parent;
13332+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
13333+ AuWarn1("%s decode_fh failed, %ld\n",
13334+ au_sbtype(h_sb), PTR_ERR(h_parent));
13335+ goto out;
13336+ }
13337+ dentry = NULL;
13338+ if (unlikely(au_test_anon(h_parent))) {
13339+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
13340+ au_sbtype(h_sb));
13341+ goto out_h_parent;
13342+ }
13343+
13344+ dentry = ERR_PTR(-ENOMEM);
13345+ pathname = (void *)__get_free_page(GFP_NOFS);
13346+ if (unlikely(!pathname))
13347+ goto out_h_parent;
13348+
13349+ root = sb->s_root;
13350+ path.mnt = h_mnt;
13351+ di_read_lock_parent(root, !AuLock_IR);
027c5e7a 13352+ path.dentry = au_h_dptr(root, nsi_lock->bindex);
1facf9fc 13353+ di_read_unlock(root, !AuLock_IR);
13354+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
13355+ dentry = (void *)p;
13356+ if (IS_ERR(p))
13357+ goto out_pathname;
13358+
13359+ si_read_unlock(sb);
13360+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
13361+ dentry = ERR_PTR(err);
13362+ if (unlikely(err))
13363+ goto out_relock;
13364+
13365+ dentry = ERR_PTR(-ENOENT);
13366+ AuDebugOn(au_test_anon(path.dentry));
5527c038 13367+ if (unlikely(d_really_is_negative(path.dentry)))
1facf9fc 13368+ goto out_path;
13369+
5527c038 13370+ if (ino != d_inode(path.dentry)->i_ino)
1facf9fc 13371+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
13372+ else
13373+ dentry = dget(path.dentry);
13374+
4f0767ce 13375+out_path:
1facf9fc 13376+ path_put(&path);
4f0767ce 13377+out_relock:
1facf9fc 13378+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
13379+ if (!IS_ERR(dentry)) {
13380+ dput(dentry);
13381+ dentry = ERR_PTR(-ESTALE);
13382+ }
4f0767ce 13383+out_pathname:
1c60b727 13384+ free_page((unsigned long)pathname);
4f0767ce 13385+out_h_parent:
1facf9fc 13386+ dput(h_parent);
4f0767ce 13387+out:
1facf9fc 13388+ AuTraceErrPtr(dentry);
13389+ return dentry;
13390+}
13391+
13392+/* ---------------------------------------------------------------------- */
13393+
13394+static struct dentry *
13395+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
13396+ int fh_type)
13397+{
13398+ struct dentry *dentry;
13399+ __u32 *fh = fid->raw;
027c5e7a 13400+ struct au_branch *br;
1facf9fc 13401+ ino_t ino, dir_ino;
1facf9fc 13402+ struct au_nfsd_si_lock nsi_lock = {
1facf9fc 13403+ .force_lock = 0
13404+ };
13405+
1facf9fc 13406+ dentry = ERR_PTR(-ESTALE);
4a4d8108
AM
13407+ /* it should never happen, but the file handle is unreliable */
13408+ if (unlikely(fh_len < Fh_tail))
13409+ goto out;
13410+ nsi_lock.sigen = fh[Fh_sigen];
13411+ nsi_lock.br_id = fh[Fh_br_id];
13412+
1facf9fc 13413+ /* branch id may be wrapped around */
027c5e7a
AM
13414+ br = NULL;
13415+ if (unlikely(si_nfsd_read_lock(sb, &nsi_lock)))
1facf9fc 13416+ goto out;
13417+ nsi_lock.force_lock = 1;
13418+
13419+ /* is this inode still cached? */
13420+ ino = decode_ino(fh + Fh_ino);
4a4d8108
AM
13421+ /* it should never happen */
13422+ if (unlikely(ino == AUFS_ROOT_INO))
8cdd5066 13423+ goto out_unlock;
4a4d8108 13424+
1facf9fc 13425+ dir_ino = decode_ino(fh + Fh_dir_ino);
13426+ dentry = decode_by_ino(sb, ino, dir_ino);
13427+ if (IS_ERR(dentry))
13428+ goto out_unlock;
13429+ if (dentry)
13430+ goto accept;
13431+
13432+ /* is the parent dir cached? */
027c5e7a 13433+ br = au_sbr(sb, nsi_lock.bindex);
acd2b654 13434+ au_lcnt_inc(&br->br_nfiles);
1facf9fc 13435+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
13436+ if (IS_ERR(dentry))
13437+ goto out_unlock;
13438+ if (dentry)
13439+ goto accept;
13440+
13441+ /* lookup path */
027c5e7a 13442+ dentry = decode_by_path(sb, ino, fh, fh_len, &nsi_lock);
1facf9fc 13443+ if (IS_ERR(dentry))
13444+ goto out_unlock;
13445+ if (unlikely(!dentry))
13446+ /* todo?: make it ESTALE */
13447+ goto out_unlock;
13448+
4f0767ce 13449+accept:
027c5e7a 13450+ if (!au_digen_test(dentry, au_sigen(sb))
5527c038 13451+ && d_inode(dentry)->i_generation == fh[Fh_igen])
1facf9fc 13452+ goto out_unlock; /* success */
13453+
13454+ dput(dentry);
13455+ dentry = ERR_PTR(-ESTALE);
4f0767ce 13456+out_unlock:
027c5e7a 13457+ if (br)
acd2b654 13458+ au_lcnt_dec(&br->br_nfiles);
1facf9fc 13459+ si_read_unlock(sb);
4f0767ce 13460+out:
1facf9fc 13461+ AuTraceErrPtr(dentry);
13462+ return dentry;
13463+}
13464+
13465+#if 0 /* reserved for future use */
13466+/* support subtreecheck option */
13467+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
13468+ int fh_len, int fh_type)
13469+{
13470+ struct dentry *parent;
13471+ __u32 *fh = fid->raw;
13472+ ino_t dir_ino;
13473+
13474+ dir_ino = decode_ino(fh + Fh_dir_ino);
13475+ parent = decode_by_ino(sb, dir_ino, 0);
13476+ if (IS_ERR(parent))
13477+ goto out;
13478+ if (!parent)
13479+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
13480+ dir_ino, fh, fh_len);
13481+
4f0767ce 13482+out:
1facf9fc 13483+ AuTraceErrPtr(parent);
13484+ return parent;
13485+}
13486+#endif
13487+
13488+/* ---------------------------------------------------------------------- */
13489+
0c3ec466
AM
13490+static int aufs_encode_fh(struct inode *inode, __u32 *fh, int *max_len,
13491+ struct inode *dir)
1facf9fc 13492+{
13493+ int err;
0c3ec466 13494+ aufs_bindex_t bindex;
1facf9fc 13495+ struct super_block *sb, *h_sb;
0c3ec466
AM
13496+ struct dentry *dentry, *parent, *h_parent;
13497+ struct inode *h_dir;
1facf9fc 13498+ struct au_branch *br;
13499+
1facf9fc 13500+ err = -ENOSPC;
13501+ if (unlikely(*max_len <= Fh_tail)) {
13502+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
13503+ goto out;
13504+ }
13505+
13506+ err = FILEID_ROOT;
0c3ec466
AM
13507+ if (inode->i_ino == AUFS_ROOT_INO) {
13508+ AuDebugOn(inode->i_ino != AUFS_ROOT_INO);
1facf9fc 13509+ goto out;
13510+ }
13511+
1facf9fc 13512+ h_parent = NULL;
0c3ec466
AM
13513+ sb = inode->i_sb;
13514+ err = si_read_lock(sb, AuLock_FLUSH);
027c5e7a
AM
13515+ if (unlikely(err))
13516+ goto out;
13517+
1facf9fc 13518+#ifdef CONFIG_AUFS_DEBUG
13519+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
13520+ AuWarn1("NFS-exporting requires xino\n");
13521+#endif
027c5e7a 13522+ err = -EIO;
0c3ec466
AM
13523+ parent = NULL;
13524+ ii_read_lock_child(inode);
5afbbe0d 13525+ bindex = au_ibtop(inode);
0c3ec466 13526+ if (!dir) {
c1595e42 13527+ dentry = d_find_any_alias(inode);
0c3ec466
AM
13528+ if (unlikely(!dentry))
13529+ goto out_unlock;
13530+ AuDebugOn(au_test_anon(dentry));
13531+ parent = dget_parent(dentry);
13532+ dput(dentry);
13533+ if (unlikely(!parent))
13534+ goto out_unlock;
5527c038
JR
13535+ if (d_really_is_positive(parent))
13536+ dir = d_inode(parent);
1facf9fc 13537+ }
0c3ec466
AM
13538+
13539+ ii_read_lock_parent(dir);
13540+ h_dir = au_h_iptr(dir, bindex);
13541+ ii_read_unlock(dir);
13542+ if (unlikely(!h_dir))
13543+ goto out_parent;
c1595e42 13544+ h_parent = d_find_any_alias(h_dir);
1facf9fc 13545+ if (unlikely(!h_parent))
0c3ec466 13546+ goto out_hparent;
1facf9fc 13547+
13548+ err = -EPERM;
13549+ br = au_sbr(sb, bindex);
86dc4139 13550+ h_sb = au_br_sb(br);
1facf9fc 13551+ if (unlikely(!h_sb->s_export_op)) {
13552+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
0c3ec466 13553+ goto out_hparent;
1facf9fc 13554+ }
13555+
13556+ fh[Fh_br_id] = br->br_id;
13557+ fh[Fh_sigen] = au_sigen(sb);
13558+ encode_ino(fh + Fh_ino, inode->i_ino);
0c3ec466 13559+ encode_ino(fh + Fh_dir_ino, dir->i_ino);
1facf9fc 13560+ fh[Fh_igen] = inode->i_generation;
13561+
13562+ *max_len -= Fh_tail;
13563+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
13564+ max_len,
13565+ /*connectable or subtreecheck*/0);
13566+ err = fh[Fh_h_type];
13567+ *max_len += Fh_tail;
13568+ /* todo: macros? */
1716fcea 13569+ if (err != FILEID_INVALID)
1facf9fc 13570+ err = 99;
13571+ else
13572+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
13573+
0c3ec466 13574+out_hparent:
1facf9fc 13575+ dput(h_parent);
0c3ec466 13576+out_parent:
1facf9fc 13577+ dput(parent);
0c3ec466
AM
13578+out_unlock:
13579+ ii_read_unlock(inode);
13580+ si_read_unlock(sb);
4f0767ce 13581+out:
1facf9fc 13582+ if (unlikely(err < 0))
1716fcea 13583+ err = FILEID_INVALID;
1facf9fc 13584+ return err;
13585+}
13586+
13587+/* ---------------------------------------------------------------------- */
13588+
4a4d8108
AM
13589+static int aufs_commit_metadata(struct inode *inode)
13590+{
13591+ int err;
13592+ aufs_bindex_t bindex;
13593+ struct super_block *sb;
13594+ struct inode *h_inode;
13595+ int (*f)(struct inode *inode);
13596+
13597+ sb = inode->i_sb;
e49829fe 13598+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 13599+ ii_write_lock_child(inode);
5afbbe0d 13600+ bindex = au_ibtop(inode);
4a4d8108
AM
13601+ AuDebugOn(bindex < 0);
13602+ h_inode = au_h_iptr(inode, bindex);
13603+
13604+ f = h_inode->i_sb->s_export_op->commit_metadata;
13605+ if (f)
13606+ err = f(h_inode);
13607+ else {
13608+ struct writeback_control wbc = {
13609+ .sync_mode = WB_SYNC_ALL,
13610+ .nr_to_write = 0 /* metadata only */
13611+ };
13612+
13613+ err = sync_inode(h_inode, &wbc);
13614+ }
13615+
13616+ au_cpup_attr_timesizes(inode);
13617+ ii_write_unlock(inode);
13618+ si_read_unlock(sb);
13619+ return err;
13620+}
13621+
13622+/* ---------------------------------------------------------------------- */
13623+
1facf9fc 13624+static struct export_operations aufs_export_op = {
4a4d8108 13625+ .fh_to_dentry = aufs_fh_to_dentry,
1facf9fc 13626+ /* .fh_to_parent = aufs_fh_to_parent, */
4a4d8108
AM
13627+ .encode_fh = aufs_encode_fh,
13628+ .commit_metadata = aufs_commit_metadata
1facf9fc 13629+};
13630+
13631+void au_export_init(struct super_block *sb)
13632+{
13633+ struct au_sbinfo *sbinfo;
13634+ __u32 u;
13635+
5afbbe0d
AM
13636+ BUILD_BUG_ON_MSG(IS_BUILTIN(CONFIG_AUFS_FS)
13637+ && IS_MODULE(CONFIG_EXPORTFS),
13638+ AUFS_NAME ": unsupported configuration "
13639+ "CONFIG_EXPORTFS=m and CONFIG_AUFS_FS=y");
13640+
1facf9fc 13641+ sb->s_export_op = &aufs_export_op;
13642+ sbinfo = au_sbi(sb);
13643+ sbinfo->si_xigen = NULL;
13644+ get_random_bytes(&u, sizeof(u));
13645+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
13646+ atomic_set(&sbinfo->si_xigen_next, u);
13647+}
076b876e 13648diff -urN /usr/share/empty/fs/aufs/fhsm.c linux/fs/aufs/fhsm.c
eca34b5c 13649--- /usr/share/empty/fs/aufs/fhsm.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 13650+++ linux/fs/aufs/fhsm.c 2021-05-02 20:15:14.673337458 +0200
062440b3 13651@@ -0,0 +1,427 @@
cd7a4cd9 13652+// SPDX-License-Identifier: GPL-2.0
076b876e 13653+/*
d58c55f2 13654+ * Copyright (C) 2011-2020 Junjiro R. Okajima
076b876e
AM
13655+ *
13656+ * This program, aufs is free software; you can redistribute it and/or modify
13657+ * it under the terms of the GNU General Public License as published by
13658+ * the Free Software Foundation; either version 2 of the License, or
13659+ * (at your option) any later version.
13660+ *
13661+ * This program is distributed in the hope that it will be useful,
13662+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13663+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13664+ * GNU General Public License for more details.
13665+ *
13666+ * You should have received a copy of the GNU General Public License
13667+ * along with this program; if not, write to the Free Software
13668+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13669+ */
13670+
13671+/*
13672+ * File-based Hierarchy Storage Management
13673+ */
13674+
13675+#include <linux/anon_inodes.h>
13676+#include <linux/poll.h>
13677+#include <linux/seq_file.h>
13678+#include <linux/statfs.h>
13679+#include "aufs.h"
13680+
c1595e42
JR
13681+static aufs_bindex_t au_fhsm_bottom(struct super_block *sb)
13682+{
13683+ struct au_sbinfo *sbinfo;
13684+ struct au_fhsm *fhsm;
13685+
13686+ SiMustAnyLock(sb);
13687+
13688+ sbinfo = au_sbi(sb);
13689+ fhsm = &sbinfo->si_fhsm;
13690+ AuDebugOn(!fhsm);
13691+ return fhsm->fhsm_bottom;
13692+}
13693+
13694+void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex)
13695+{
13696+ struct au_sbinfo *sbinfo;
13697+ struct au_fhsm *fhsm;
13698+
13699+ SiMustWriteLock(sb);
13700+
13701+ sbinfo = au_sbi(sb);
13702+ fhsm = &sbinfo->si_fhsm;
13703+ AuDebugOn(!fhsm);
13704+ fhsm->fhsm_bottom = bindex;
13705+}
13706+
13707+/* ---------------------------------------------------------------------- */
13708+
076b876e
AM
13709+static int au_fhsm_test_jiffy(struct au_sbinfo *sbinfo, struct au_branch *br)
13710+{
13711+ struct au_br_fhsm *bf;
13712+
13713+ bf = br->br_fhsm;
13714+ MtxMustLock(&bf->bf_lock);
13715+
13716+ return !bf->bf_readable
13717+ || time_after(jiffies,
13718+ bf->bf_jiffy + sbinfo->si_fhsm.fhsm_expire);
13719+}
13720+
13721+/* ---------------------------------------------------------------------- */
13722+
13723+static void au_fhsm_notify(struct super_block *sb, int val)
13724+{
13725+ struct au_sbinfo *sbinfo;
13726+ struct au_fhsm *fhsm;
13727+
13728+ SiMustAnyLock(sb);
13729+
13730+ sbinfo = au_sbi(sb);
13731+ fhsm = &sbinfo->si_fhsm;
13732+ if (au_fhsm_pid(fhsm)
13733+ && atomic_read(&fhsm->fhsm_readable) != -1) {
13734+ atomic_set(&fhsm->fhsm_readable, val);
13735+ if (val)
13736+ wake_up(&fhsm->fhsm_wqh);
13737+ }
13738+}
13739+
13740+static int au_fhsm_stfs(struct super_block *sb, aufs_bindex_t bindex,
13741+ struct aufs_stfs *rstfs, int do_lock, int do_notify)
13742+{
13743+ int err;
13744+ struct au_branch *br;
13745+ struct au_br_fhsm *bf;
13746+
13747+ br = au_sbr(sb, bindex);
13748+ AuDebugOn(au_br_rdonly(br));
13749+ bf = br->br_fhsm;
13750+ AuDebugOn(!bf);
13751+
13752+ if (do_lock)
13753+ mutex_lock(&bf->bf_lock);
13754+ else
13755+ MtxMustLock(&bf->bf_lock);
13756+
13757+ /* sb->s_root for NFS is unreliable */
13758+ err = au_br_stfs(br, &bf->bf_stfs);
13759+ if (unlikely(err)) {
13760+ AuErr1("FHSM failed (%d), b%d, ignored.\n", bindex, err);
13761+ goto out;
13762+ }
13763+
13764+ bf->bf_jiffy = jiffies;
13765+ bf->bf_readable = 1;
13766+ if (do_notify)
13767+ au_fhsm_notify(sb, /*val*/1);
13768+ if (rstfs)
13769+ *rstfs = bf->bf_stfs;
13770+
13771+out:
13772+ if (do_lock)
13773+ mutex_unlock(&bf->bf_lock);
13774+ au_fhsm_notify(sb, /*val*/1);
13775+
13776+ return err;
13777+}
13778+
13779+void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force)
13780+{
13781+ int err;
076b876e
AM
13782+ struct au_sbinfo *sbinfo;
13783+ struct au_fhsm *fhsm;
13784+ struct au_branch *br;
13785+ struct au_br_fhsm *bf;
13786+
13787+ AuDbg("b%d, force %d\n", bindex, force);
13788+ SiMustAnyLock(sb);
13789+
13790+ sbinfo = au_sbi(sb);
13791+ fhsm = &sbinfo->si_fhsm;
c1595e42
JR
13792+ if (!au_ftest_si(sbinfo, FHSM)
13793+ || fhsm->fhsm_bottom == bindex)
076b876e
AM
13794+ return;
13795+
13796+ br = au_sbr(sb, bindex);
13797+ bf = br->br_fhsm;
13798+ AuDebugOn(!bf);
13799+ mutex_lock(&bf->bf_lock);
13800+ if (force
13801+ || au_fhsm_pid(fhsm)
13802+ || au_fhsm_test_jiffy(sbinfo, br))
13803+ err = au_fhsm_stfs(sb, bindex, /*rstfs*/NULL, /*do_lock*/0,
13804+ /*do_notify*/1);
13805+ mutex_unlock(&bf->bf_lock);
13806+}
13807+
13808+void au_fhsm_wrote_all(struct super_block *sb, int force)
13809+{
5afbbe0d 13810+ aufs_bindex_t bindex, bbot;
076b876e
AM
13811+ struct au_branch *br;
13812+
13813+ /* exclude the bottom */
5afbbe0d
AM
13814+ bbot = au_fhsm_bottom(sb);
13815+ for (bindex = 0; bindex < bbot; bindex++) {
076b876e
AM
13816+ br = au_sbr(sb, bindex);
13817+ if (au_br_fhsm(br->br_perm))
13818+ au_fhsm_wrote(sb, bindex, force);
13819+ }
13820+}
13821+
13822+/* ---------------------------------------------------------------------- */
13823+
be118d29 13824+static __poll_t au_fhsm_poll(struct file *file, struct poll_table_struct *wait)
076b876e 13825+{
be118d29 13826+ __poll_t mask;
076b876e
AM
13827+ struct au_sbinfo *sbinfo;
13828+ struct au_fhsm *fhsm;
13829+
13830+ mask = 0;
13831+ sbinfo = file->private_data;
13832+ fhsm = &sbinfo->si_fhsm;
13833+ poll_wait(file, &fhsm->fhsm_wqh, wait);
13834+ if (atomic_read(&fhsm->fhsm_readable))
be118d29 13835+ mask = EPOLLIN /* | EPOLLRDNORM */;
076b876e 13836+
b00004a5
AM
13837+ if (!mask)
13838+ AuDbg("mask 0x%x\n", mask);
076b876e
AM
13839+ return mask;
13840+}
13841+
13842+static int au_fhsm_do_read_one(struct aufs_stbr __user *stbr,
13843+ struct aufs_stfs *stfs, __s16 brid)
13844+{
13845+ int err;
13846+
13847+ err = copy_to_user(&stbr->stfs, stfs, sizeof(*stfs));
13848+ if (!err)
13849+ err = __put_user(brid, &stbr->brid);
13850+ if (unlikely(err))
13851+ err = -EFAULT;
13852+
13853+ return err;
13854+}
13855+
13856+static ssize_t au_fhsm_do_read(struct super_block *sb,
13857+ struct aufs_stbr __user *stbr, size_t count)
13858+{
13859+ ssize_t err;
13860+ int nstbr;
5afbbe0d 13861+ aufs_bindex_t bindex, bbot;
076b876e
AM
13862+ struct au_branch *br;
13863+ struct au_br_fhsm *bf;
13864+
13865+ /* except the bottom branch */
13866+ err = 0;
13867+ nstbr = 0;
5afbbe0d
AM
13868+ bbot = au_fhsm_bottom(sb);
13869+ for (bindex = 0; !err && bindex < bbot; bindex++) {
076b876e
AM
13870+ br = au_sbr(sb, bindex);
13871+ if (!au_br_fhsm(br->br_perm))
13872+ continue;
13873+
13874+ bf = br->br_fhsm;
13875+ mutex_lock(&bf->bf_lock);
13876+ if (bf->bf_readable) {
13877+ err = -EFAULT;
13878+ if (count >= sizeof(*stbr))
13879+ err = au_fhsm_do_read_one(stbr++, &bf->bf_stfs,
13880+ br->br_id);
13881+ if (!err) {
13882+ bf->bf_readable = 0;
13883+ count -= sizeof(*stbr);
13884+ nstbr++;
13885+ }
13886+ }
13887+ mutex_unlock(&bf->bf_lock);
13888+ }
13889+ if (!err)
13890+ err = sizeof(*stbr) * nstbr;
13891+
13892+ return err;
13893+}
13894+
13895+static ssize_t au_fhsm_read(struct file *file, char __user *buf, size_t count,
13896+ loff_t *pos)
13897+{
13898+ ssize_t err;
13899+ int readable;
5afbbe0d 13900+ aufs_bindex_t nfhsm, bindex, bbot;
076b876e
AM
13901+ struct au_sbinfo *sbinfo;
13902+ struct au_fhsm *fhsm;
13903+ struct au_branch *br;
13904+ struct super_block *sb;
13905+
13906+ err = 0;
13907+ sbinfo = file->private_data;
13908+ fhsm = &sbinfo->si_fhsm;
13909+need_data:
13910+ spin_lock_irq(&fhsm->fhsm_wqh.lock);
13911+ if (!atomic_read(&fhsm->fhsm_readable)) {
13912+ if (vfsub_file_flags(file) & O_NONBLOCK)
13913+ err = -EAGAIN;
13914+ else
13915+ err = wait_event_interruptible_locked_irq
13916+ (fhsm->fhsm_wqh,
13917+ atomic_read(&fhsm->fhsm_readable));
13918+ }
13919+ spin_unlock_irq(&fhsm->fhsm_wqh.lock);
13920+ if (unlikely(err))
13921+ goto out;
13922+
13923+ /* sb may already be dead */
13924+ au_rw_read_lock(&sbinfo->si_rwsem);
13925+ readable = atomic_read(&fhsm->fhsm_readable);
13926+ if (readable > 0) {
13927+ sb = sbinfo->si_sb;
13928+ AuDebugOn(!sb);
13929+ /* exclude the bottom branch */
13930+ nfhsm = 0;
5afbbe0d
AM
13931+ bbot = au_fhsm_bottom(sb);
13932+ for (bindex = 0; bindex < bbot; bindex++) {
076b876e
AM
13933+ br = au_sbr(sb, bindex);
13934+ if (au_br_fhsm(br->br_perm))
13935+ nfhsm++;
13936+ }
13937+ err = -EMSGSIZE;
13938+ if (nfhsm * sizeof(struct aufs_stbr) <= count) {
13939+ atomic_set(&fhsm->fhsm_readable, 0);
13940+ err = au_fhsm_do_read(sbinfo->si_sb, (void __user *)buf,
13941+ count);
13942+ }
13943+ }
13944+ au_rw_read_unlock(&sbinfo->si_rwsem);
13945+ if (!readable)
13946+ goto need_data;
13947+
13948+out:
13949+ return err;
13950+}
13951+
13952+static int au_fhsm_release(struct inode *inode, struct file *file)
13953+{
13954+ struct au_sbinfo *sbinfo;
13955+ struct au_fhsm *fhsm;
13956+
13957+ /* sb may already be dead */
13958+ sbinfo = file->private_data;
13959+ fhsm = &sbinfo->si_fhsm;
13960+ spin_lock(&fhsm->fhsm_spin);
13961+ fhsm->fhsm_pid = 0;
13962+ spin_unlock(&fhsm->fhsm_spin);
13963+ kobject_put(&sbinfo->si_kobj);
13964+
13965+ return 0;
13966+}
13967+
13968+static const struct file_operations au_fhsm_fops = {
13969+ .owner = THIS_MODULE,
13970+ .llseek = noop_llseek,
13971+ .read = au_fhsm_read,
13972+ .poll = au_fhsm_poll,
13973+ .release = au_fhsm_release
13974+};
13975+
13976+int au_fhsm_fd(struct super_block *sb, int oflags)
13977+{
13978+ int err, fd;
13979+ struct au_sbinfo *sbinfo;
13980+ struct au_fhsm *fhsm;
13981+
13982+ err = -EPERM;
13983+ if (unlikely(!capable(CAP_SYS_ADMIN)))
13984+ goto out;
13985+
13986+ err = -EINVAL;
13987+ if (unlikely(oflags & ~(O_CLOEXEC | O_NONBLOCK)))
13988+ goto out;
13989+
13990+ err = 0;
13991+ sbinfo = au_sbi(sb);
13992+ fhsm = &sbinfo->si_fhsm;
13993+ spin_lock(&fhsm->fhsm_spin);
13994+ if (!fhsm->fhsm_pid)
13995+ fhsm->fhsm_pid = current->pid;
13996+ else
13997+ err = -EBUSY;
13998+ spin_unlock(&fhsm->fhsm_spin);
13999+ if (unlikely(err))
14000+ goto out;
14001+
14002+ oflags |= O_RDONLY;
14003+ /* oflags |= FMODE_NONOTIFY; */
14004+ fd = anon_inode_getfd("[aufs_fhsm]", &au_fhsm_fops, sbinfo, oflags);
14005+ err = fd;
14006+ if (unlikely(fd < 0))
14007+ goto out_pid;
14008+
acd2b654 14009+ /* succeed regardless 'fhsm' status */
076b876e
AM
14010+ kobject_get(&sbinfo->si_kobj);
14011+ si_noflush_read_lock(sb);
14012+ if (au_ftest_si(sbinfo, FHSM))
14013+ au_fhsm_wrote_all(sb, /*force*/0);
14014+ si_read_unlock(sb);
14015+ goto out; /* success */
14016+
14017+out_pid:
14018+ spin_lock(&fhsm->fhsm_spin);
14019+ fhsm->fhsm_pid = 0;
14020+ spin_unlock(&fhsm->fhsm_spin);
14021+out:
14022+ AuTraceErr(err);
14023+ return err;
14024+}
14025+
14026+/* ---------------------------------------------------------------------- */
14027+
14028+int au_fhsm_br_alloc(struct au_branch *br)
14029+{
14030+ int err;
14031+
14032+ err = 0;
14033+ br->br_fhsm = kmalloc(sizeof(*br->br_fhsm), GFP_NOFS);
14034+ if (br->br_fhsm)
14035+ au_br_fhsm_init(br->br_fhsm);
14036+ else
14037+ err = -ENOMEM;
14038+
14039+ return err;
14040+}
14041+
14042+/* ---------------------------------------------------------------------- */
14043+
14044+void au_fhsm_fin(struct super_block *sb)
14045+{
14046+ au_fhsm_notify(sb, /*val*/-1);
14047+}
14048+
14049+void au_fhsm_init(struct au_sbinfo *sbinfo)
14050+{
14051+ struct au_fhsm *fhsm;
14052+
14053+ fhsm = &sbinfo->si_fhsm;
14054+ spin_lock_init(&fhsm->fhsm_spin);
14055+ init_waitqueue_head(&fhsm->fhsm_wqh);
14056+ atomic_set(&fhsm->fhsm_readable, 0);
14057+ fhsm->fhsm_expire
14058+ = msecs_to_jiffies(AUFS_FHSM_CACHE_DEF_SEC * MSEC_PER_SEC);
c1595e42 14059+ fhsm->fhsm_bottom = -1;
076b876e
AM
14060+}
14061+
14062+void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec)
14063+{
14064+ sbinfo->si_fhsm.fhsm_expire
14065+ = msecs_to_jiffies(sec * MSEC_PER_SEC);
14066+}
14067+
14068+void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo)
14069+{
14070+ unsigned int u;
14071+
14072+ if (!au_ftest_si(sbinfo, FHSM))
14073+ return;
14074+
14075+ u = jiffies_to_msecs(sbinfo->si_fhsm.fhsm_expire) / MSEC_PER_SEC;
14076+ if (u != AUFS_FHSM_CACHE_DEF_SEC)
14077+ seq_printf(seq, ",fhsm_sec=%u", u);
14078+}
7f207e10 14079diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
eca34b5c 14080--- /usr/share/empty/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 14081+++ linux/fs/aufs/file.c 2021-05-02 20:15:14.673337458 +0200
42a736d3 14082@@ -0,0 +1,863 @@
cd7a4cd9 14083+// SPDX-License-Identifier: GPL-2.0
1facf9fc 14084+/*
d58c55f2 14085+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 14086+ *
14087+ * This program, aufs is free software; you can redistribute it and/or modify
14088+ * it under the terms of the GNU General Public License as published by
14089+ * the Free Software Foundation; either version 2 of the License, or
14090+ * (at your option) any later version.
dece6358
AM
14091+ *
14092+ * This program is distributed in the hope that it will be useful,
14093+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14094+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14095+ * GNU General Public License for more details.
14096+ *
14097+ * You should have received a copy of the GNU General Public License
523b37e3 14098+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 14099+ */
14100+
14101+/*
4a4d8108 14102+ * handling file/dir, and address_space operation
1facf9fc 14103+ */
14104+
7eafdf33
AM
14105+#ifdef CONFIG_AUFS_DEBUG
14106+#include <linux/migrate.h>
14107+#endif
4a4d8108 14108+#include <linux/pagemap.h>
1facf9fc 14109+#include "aufs.h"
14110+
4a4d8108
AM
14111+/* drop flags for writing */
14112+unsigned int au_file_roflags(unsigned int flags)
14113+{
14114+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
14115+ flags |= O_RDONLY | O_NOATIME;
14116+ return flags;
14117+}
14118+
14119+/* common functions to regular file and dir */
14120+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
392086de 14121+ struct file *file, int force_wr)
1facf9fc 14122+{
1308ab2a 14123+ struct file *h_file;
4a4d8108
AM
14124+ struct dentry *h_dentry;
14125+ struct inode *h_inode;
14126+ struct super_block *sb;
14127+ struct au_branch *br;
14128+ struct path h_path;
b912730e 14129+ int err;
1facf9fc 14130+
4a4d8108
AM
14131+ /* a race condition can happen between open and unlink/rmdir */
14132+ h_file = ERR_PTR(-ENOENT);
14133+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 14134+ if (au_test_nfsd() && (!h_dentry || d_is_negative(h_dentry)))
4a4d8108 14135+ goto out;
5527c038 14136+ h_inode = d_inode(h_dentry);
027c5e7a
AM
14137+ spin_lock(&h_dentry->d_lock);
14138+ err = (!d_unhashed(dentry) && d_unlinked(h_dentry))
5527c038 14139+ /* || !d_inode(dentry)->i_nlink */
027c5e7a
AM
14140+ ;
14141+ spin_unlock(&h_dentry->d_lock);
14142+ if (unlikely(err))
4a4d8108 14143+ goto out;
1facf9fc 14144+
4a4d8108
AM
14145+ sb = dentry->d_sb;
14146+ br = au_sbr(sb, bindex);
b912730e
AM
14147+ err = au_br_test_oflag(flags, br);
14148+ h_file = ERR_PTR(err);
14149+ if (unlikely(err))
027c5e7a 14150+ goto out;
1facf9fc 14151+
4a4d8108 14152+ /* drop flags for writing */
5527c038 14153+ if (au_test_ro(sb, bindex, d_inode(dentry))) {
392086de
AM
14154+ if (force_wr && !(flags & O_WRONLY))
14155+ force_wr = 0;
4a4d8108 14156+ flags = au_file_roflags(flags);
392086de
AM
14157+ if (force_wr) {
14158+ h_file = ERR_PTR(-EROFS);
14159+ flags = au_file_roflags(flags);
14160+ if (unlikely(vfsub_native_ro(h_inode)
14161+ || IS_APPEND(h_inode)))
14162+ goto out;
14163+ flags &= ~O_ACCMODE;
14164+ flags |= O_WRONLY;
14165+ }
14166+ }
4a4d8108 14167+ flags &= ~O_CREAT;
acd2b654 14168+ au_lcnt_inc(&br->br_nfiles);
4a4d8108 14169+ h_path.dentry = h_dentry;
86dc4139 14170+ h_path.mnt = au_br_mnt(br);
38d290e6 14171+ h_file = vfsub_dentry_open(&h_path, flags);
4a4d8108
AM
14172+ if (IS_ERR(h_file))
14173+ goto out_br;
dece6358 14174+
b912730e 14175+ if (flags & __FMODE_EXEC) {
4a4d8108
AM
14176+ err = deny_write_access(h_file);
14177+ if (unlikely(err)) {
14178+ fput(h_file);
14179+ h_file = ERR_PTR(err);
14180+ goto out_br;
14181+ }
14182+ }
953406b4 14183+ fsnotify_open(h_file);
4a4d8108 14184+ goto out; /* success */
1facf9fc 14185+
4f0767ce 14186+out_br:
acd2b654 14187+ au_lcnt_dec(&br->br_nfiles);
4f0767ce 14188+out:
4a4d8108
AM
14189+ return h_file;
14190+}
1308ab2a 14191+
076b876e
AM
14192+static int au_cmoo(struct dentry *dentry)
14193+{
8b6a4947 14194+ int err, cmoo, matched;
076b876e
AM
14195+ unsigned int udba;
14196+ struct path h_path;
14197+ struct au_pin pin;
14198+ struct au_cp_generic cpg = {
14199+ .dentry = dentry,
14200+ .bdst = -1,
14201+ .bsrc = -1,
14202+ .len = -1,
14203+ .pin = &pin,
14204+ .flags = AuCpup_DTIME | AuCpup_HOPEN
14205+ };
7e9cd9fe 14206+ struct inode *delegated;
076b876e
AM
14207+ struct super_block *sb;
14208+ struct au_sbinfo *sbinfo;
14209+ struct au_fhsm *fhsm;
14210+ pid_t pid;
14211+ struct au_branch *br;
14212+ struct dentry *parent;
14213+ struct au_hinode *hdir;
14214+
14215+ DiMustWriteLock(dentry);
5527c038 14216+ IiMustWriteLock(d_inode(dentry));
076b876e
AM
14217+
14218+ err = 0;
14219+ if (IS_ROOT(dentry))
14220+ goto out;
5afbbe0d 14221+ cpg.bsrc = au_dbtop(dentry);
076b876e
AM
14222+ if (!cpg.bsrc)
14223+ goto out;
14224+
14225+ sb = dentry->d_sb;
14226+ sbinfo = au_sbi(sb);
14227+ fhsm = &sbinfo->si_fhsm;
14228+ pid = au_fhsm_pid(fhsm);
8b6a4947
AM
14229+ rcu_read_lock();
14230+ matched = (pid
14231+ && (current->pid == pid
14232+ || rcu_dereference(current->real_parent)->pid == pid));
14233+ rcu_read_unlock();
14234+ if (matched)
076b876e
AM
14235+ goto out;
14236+
14237+ br = au_sbr(sb, cpg.bsrc);
14238+ cmoo = au_br_cmoo(br->br_perm);
14239+ if (!cmoo)
14240+ goto out;
7e9cd9fe 14241+ if (!d_is_reg(dentry))
076b876e
AM
14242+ cmoo &= AuBrAttr_COO_ALL;
14243+ if (!cmoo)
14244+ goto out;
14245+
14246+ parent = dget_parent(dentry);
14247+ di_write_lock_parent(parent);
14248+ err = au_wbr_do_copyup_bu(dentry, cpg.bsrc - 1);
14249+ cpg.bdst = err;
14250+ if (unlikely(err < 0)) {
14251+ err = 0; /* there is no upper writable branch */
14252+ goto out_dgrade;
14253+ }
14254+ AuDbg("bsrc %d, bdst %d\n", cpg.bsrc, cpg.bdst);
14255+
14256+ /* do not respect the coo attrib for the target branch */
14257+ err = au_cpup_dirs(dentry, cpg.bdst);
14258+ if (unlikely(err))
14259+ goto out_dgrade;
14260+
14261+ di_downgrade_lock(parent, AuLock_IR);
14262+ udba = au_opt_udba(sb);
14263+ err = au_pin(&pin, dentry, cpg.bdst, udba,
14264+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14265+ if (unlikely(err))
14266+ goto out_parent;
14267+
14268+ err = au_sio_cpup_simple(&cpg);
14269+ au_unpin(&pin);
14270+ if (unlikely(err))
14271+ goto out_parent;
14272+ if (!(cmoo & AuBrWAttr_MOO))
14273+ goto out_parent; /* success */
14274+
14275+ err = au_pin(&pin, dentry, cpg.bsrc, udba,
14276+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14277+ if (unlikely(err))
14278+ goto out_parent;
14279+
14280+ h_path.mnt = au_br_mnt(br);
14281+ h_path.dentry = au_h_dptr(dentry, cpg.bsrc);
5527c038 14282+ hdir = au_hi(d_inode(parent), cpg.bsrc);
076b876e
AM
14283+ delegated = NULL;
14284+ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated, /*force*/1);
14285+ au_unpin(&pin);
14286+ /* todo: keep h_dentry or not? */
14287+ if (unlikely(err == -EWOULDBLOCK)) {
14288+ pr_warn("cannot retry for NFSv4 delegation"
14289+ " for an internal unlink\n");
14290+ iput(delegated);
14291+ }
14292+ if (unlikely(err)) {
14293+ pr_err("unlink %pd after coo failed (%d), ignored\n",
14294+ dentry, err);
14295+ err = 0;
14296+ }
14297+ goto out_parent; /* success */
14298+
14299+out_dgrade:
14300+ di_downgrade_lock(parent, AuLock_IR);
14301+out_parent:
14302+ di_read_unlock(parent, AuLock_IR);
14303+ dput(parent);
14304+out:
14305+ AuTraceErr(err);
14306+ return err;
14307+}
14308+
b912730e 14309+int au_do_open(struct file *file, struct au_do_open_args *args)
1facf9fc 14310+{
8b6a4947 14311+ int err, aopen = args->aopen;
1facf9fc 14312+ struct dentry *dentry;
076b876e 14313+ struct au_finfo *finfo;
1308ab2a 14314+
8b6a4947 14315+ if (!aopen)
b912730e
AM
14316+ err = au_finfo_init(file, args->fidir);
14317+ else {
14318+ lockdep_off();
14319+ err = au_finfo_init(file, args->fidir);
14320+ lockdep_on();
14321+ }
4a4d8108
AM
14322+ if (unlikely(err))
14323+ goto out;
1facf9fc 14324+
2000de60 14325+ dentry = file->f_path.dentry;
b912730e 14326+ AuDebugOn(IS_ERR_OR_NULL(dentry));
8b6a4947
AM
14327+ di_write_lock_child(dentry);
14328+ err = au_cmoo(dentry);
14329+ di_downgrade_lock(dentry, AuLock_IR);
14330+ if (!err) {
14331+ if (!aopen)
b912730e 14332+ err = args->open(file, vfsub_file_flags(file), NULL);
8b6a4947
AM
14333+ else {
14334+ lockdep_off();
acd2b654
AM
14335+ err = args->open(file, vfsub_file_flags(file),
14336+ args->h_file);
8b6a4947
AM
14337+ lockdep_on();
14338+ }
b912730e 14339+ }
8b6a4947 14340+ di_read_unlock(dentry, AuLock_IR);
1facf9fc 14341+
076b876e
AM
14342+ finfo = au_fi(file);
14343+ if (!err) {
14344+ finfo->fi_file = file;
8b6a4947
AM
14345+ au_hbl_add(&finfo->fi_hlist,
14346+ &au_sbi(file->f_path.dentry->d_sb)->si_files);
076b876e 14347+ }
8b6a4947 14348+ if (!aopen)
b912730e
AM
14349+ fi_write_unlock(file);
14350+ else {
14351+ lockdep_off();
14352+ fi_write_unlock(file);
14353+ lockdep_on();
14354+ }
4a4d8108 14355+ if (unlikely(err)) {
076b876e 14356+ finfo->fi_hdir = NULL;
1c60b727 14357+ au_finfo_fin(file);
1308ab2a 14358+ }
4a4d8108 14359+
4f0767ce 14360+out:
8b6a4947 14361+ AuTraceErr(err);
1308ab2a 14362+ return err;
14363+}
dece6358 14364+
4a4d8108 14365+int au_reopen_nondir(struct file *file)
1308ab2a 14366+{
4a4d8108 14367+ int err;
5afbbe0d 14368+ aufs_bindex_t btop;
4a4d8108 14369+ struct dentry *dentry;
acd2b654 14370+ struct au_branch *br;
4a4d8108 14371+ struct file *h_file, *h_file_tmp;
1308ab2a 14372+
2000de60 14373+ dentry = file->f_path.dentry;
5afbbe0d 14374+ btop = au_dbtop(dentry);
acd2b654 14375+ br = au_sbr(dentry->d_sb, btop);
4a4d8108 14376+ h_file_tmp = NULL;
5afbbe0d 14377+ if (au_fbtop(file) == btop) {
4a4d8108
AM
14378+ h_file = au_hf_top(file);
14379+ if (file->f_mode == h_file->f_mode)
14380+ return 0; /* success */
14381+ h_file_tmp = h_file;
14382+ get_file(h_file_tmp);
acd2b654 14383+ au_lcnt_inc(&br->br_nfiles);
5afbbe0d 14384+ au_set_h_fptr(file, btop, NULL);
4a4d8108
AM
14385+ }
14386+ AuDebugOn(au_fi(file)->fi_hdir);
86dc4139
AM
14387+ /*
14388+ * it can happen
14389+ * file exists on both of rw and ro
5afbbe0d 14390+ * open --> dbtop and fbtop are both 0
86dc4139
AM
14391+ * prepend a branch as rw, "rw" become ro
14392+ * remove rw/file
14393+ * delete the top branch, "rw" becomes rw again
5afbbe0d
AM
14394+ * --> dbtop is 1, fbtop is still 0
14395+ * write --> fbtop is 0 but dbtop is 1
86dc4139 14396+ */
5afbbe0d 14397+ /* AuDebugOn(au_fbtop(file) < btop); */
1308ab2a 14398+
5afbbe0d 14399+ h_file = au_h_open(dentry, btop, vfsub_file_flags(file) & ~O_TRUNC,
392086de 14400+ file, /*force_wr*/0);
4a4d8108 14401+ err = PTR_ERR(h_file);
86dc4139
AM
14402+ if (IS_ERR(h_file)) {
14403+ if (h_file_tmp) {
acd2b654 14404+ /* revert */
5afbbe0d 14405+ au_set_h_fptr(file, btop, h_file_tmp);
86dc4139
AM
14406+ h_file_tmp = NULL;
14407+ }
4a4d8108 14408+ goto out; /* todo: close all? */
86dc4139 14409+ }
4a4d8108
AM
14410+
14411+ err = 0;
5afbbe0d
AM
14412+ au_set_fbtop(file, btop);
14413+ au_set_h_fptr(file, btop, h_file);
4a4d8108
AM
14414+ au_update_figen(file);
14415+ /* todo: necessary? */
14416+ /* file->f_ra = h_file->f_ra; */
14417+
4f0767ce 14418+out:
acd2b654 14419+ if (h_file_tmp) {
4a4d8108 14420+ fput(h_file_tmp);
acd2b654
AM
14421+ au_lcnt_dec(&br->br_nfiles);
14422+ }
4a4d8108 14423+ return err;
1facf9fc 14424+}
14425+
1308ab2a 14426+/* ---------------------------------------------------------------------- */
14427+
4a4d8108
AM
14428+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
14429+ struct dentry *hi_wh)
1facf9fc 14430+{
4a4d8108 14431+ int err;
5afbbe0d 14432+ aufs_bindex_t btop;
4a4d8108
AM
14433+ struct au_dinfo *dinfo;
14434+ struct dentry *h_dentry;
14435+ struct au_hdentry *hdp;
1facf9fc 14436+
2000de60 14437+ dinfo = au_di(file->f_path.dentry);
4a4d8108 14438+ AuRwMustWriteLock(&dinfo->di_rwsem);
dece6358 14439+
5afbbe0d
AM
14440+ btop = dinfo->di_btop;
14441+ dinfo->di_btop = btgt;
14442+ hdp = au_hdentry(dinfo, btgt);
14443+ h_dentry = hdp->hd_dentry;
14444+ hdp->hd_dentry = hi_wh;
4a4d8108 14445+ err = au_reopen_nondir(file);
5afbbe0d
AM
14446+ hdp->hd_dentry = h_dentry;
14447+ dinfo->di_btop = btop;
1facf9fc 14448+
1facf9fc 14449+ return err;
14450+}
14451+
4a4d8108 14452+static int au_ready_to_write_wh(struct file *file, loff_t len,
86dc4139 14453+ aufs_bindex_t bcpup, struct au_pin *pin)
1facf9fc 14454+{
4a4d8108 14455+ int err;
027c5e7a 14456+ struct inode *inode, *h_inode;
c2b27bf2
AM
14457+ struct dentry *h_dentry, *hi_wh;
14458+ struct au_cp_generic cpg = {
2000de60 14459+ .dentry = file->f_path.dentry,
c2b27bf2
AM
14460+ .bdst = bcpup,
14461+ .bsrc = -1,
14462+ .len = len,
14463+ .pin = pin
14464+ };
1facf9fc 14465+
5afbbe0d 14466+ au_update_dbtop(cpg.dentry);
5527c038 14467+ inode = d_inode(cpg.dentry);
027c5e7a 14468+ h_inode = NULL;
5afbbe0d
AM
14469+ if (au_dbtop(cpg.dentry) <= bcpup
14470+ && au_dbbot(cpg.dentry) >= bcpup) {
c2b27bf2 14471+ h_dentry = au_h_dptr(cpg.dentry, bcpup);
5527c038
JR
14472+ if (h_dentry && d_is_positive(h_dentry))
14473+ h_inode = d_inode(h_dentry);
027c5e7a 14474+ }
4a4d8108 14475+ hi_wh = au_hi_wh(inode, bcpup);
027c5e7a 14476+ if (!hi_wh && !h_inode)
c2b27bf2 14477+ err = au_sio_cpup_wh(&cpg, file);
4a4d8108
AM
14478+ else
14479+ /* already copied-up after unlink */
14480+ err = au_reopen_wh(file, bcpup, hi_wh);
1facf9fc 14481+
4a4d8108 14482+ if (!err
38d290e6
JR
14483+ && (inode->i_nlink > 1
14484+ || (inode->i_state & I_LINKABLE))
c2b27bf2
AM
14485+ && au_opt_test(au_mntflags(cpg.dentry->d_sb), PLINK))
14486+ au_plink_append(inode, bcpup, au_h_dptr(cpg.dentry, bcpup));
1308ab2a 14487+
dece6358 14488+ return err;
1facf9fc 14489+}
14490+
4a4d8108
AM
14491+/*
14492+ * prepare the @file for writing.
14493+ */
14494+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
1facf9fc 14495+{
4a4d8108 14496+ int err;
5afbbe0d 14497+ aufs_bindex_t dbtop;
c1595e42 14498+ struct dentry *parent;
86dc4139 14499+ struct inode *inode;
1facf9fc 14500+ struct super_block *sb;
4a4d8108 14501+ struct file *h_file;
c2b27bf2 14502+ struct au_cp_generic cpg = {
2000de60 14503+ .dentry = file->f_path.dentry,
c2b27bf2
AM
14504+ .bdst = -1,
14505+ .bsrc = -1,
14506+ .len = len,
14507+ .pin = pin,
14508+ .flags = AuCpup_DTIME
14509+ };
1facf9fc 14510+
c2b27bf2 14511+ sb = cpg.dentry->d_sb;
5527c038 14512+ inode = d_inode(cpg.dentry);
5afbbe0d 14513+ cpg.bsrc = au_fbtop(file);
c2b27bf2 14514+ err = au_test_ro(sb, cpg.bsrc, inode);
4a4d8108 14515+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
c2b27bf2
AM
14516+ err = au_pin(pin, cpg.dentry, cpg.bsrc, AuOpt_UDBA_NONE,
14517+ /*flags*/0);
1facf9fc 14518+ goto out;
4a4d8108 14519+ }
1facf9fc 14520+
027c5e7a 14521+ /* need to cpup or reopen */
c2b27bf2 14522+ parent = dget_parent(cpg.dentry);
4a4d8108 14523+ di_write_lock_parent(parent);
c2b27bf2
AM
14524+ err = AuWbrCopyup(au_sbi(sb), cpg.dentry);
14525+ cpg.bdst = err;
4a4d8108
AM
14526+ if (unlikely(err < 0))
14527+ goto out_dgrade;
14528+ err = 0;
14529+
c2b27bf2
AM
14530+ if (!d_unhashed(cpg.dentry) && !au_h_dptr(parent, cpg.bdst)) {
14531+ err = au_cpup_dirs(cpg.dentry, cpg.bdst);
1facf9fc 14532+ if (unlikely(err))
4a4d8108
AM
14533+ goto out_dgrade;
14534+ }
14535+
c2b27bf2 14536+ err = au_pin(pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE,
4a4d8108
AM
14537+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14538+ if (unlikely(err))
14539+ goto out_dgrade;
14540+
5afbbe0d
AM
14541+ dbtop = au_dbtop(cpg.dentry);
14542+ if (dbtop <= cpg.bdst)
c2b27bf2 14543+ cpg.bsrc = cpg.bdst;
027c5e7a 14544+
5afbbe0d 14545+ if (dbtop <= cpg.bdst /* just reopen */
c2b27bf2 14546+ || !d_unhashed(cpg.dentry) /* copyup and reopen */
027c5e7a 14547+ ) {
392086de 14548+ h_file = au_h_open_pre(cpg.dentry, cpg.bsrc, /*force_wr*/0);
86dc4139 14549+ if (IS_ERR(h_file))
027c5e7a 14550+ err = PTR_ERR(h_file);
86dc4139 14551+ else {
027c5e7a 14552+ di_downgrade_lock(parent, AuLock_IR);
5afbbe0d 14553+ if (dbtop > cpg.bdst)
c2b27bf2 14554+ err = au_sio_cpup_simple(&cpg);
027c5e7a
AM
14555+ if (!err)
14556+ err = au_reopen_nondir(file);
c2b27bf2 14557+ au_h_open_post(cpg.dentry, cpg.bsrc, h_file);
027c5e7a 14558+ }
027c5e7a
AM
14559+ } else { /* copyup as wh and reopen */
14560+ /*
14561+ * since writable hfsplus branch is not supported,
14562+ * h_open_pre/post() are unnecessary.
14563+ */
c2b27bf2 14564+ err = au_ready_to_write_wh(file, len, cpg.bdst, pin);
4a4d8108 14565+ di_downgrade_lock(parent, AuLock_IR);
4a4d8108 14566+ }
4a4d8108
AM
14567+
14568+ if (!err) {
14569+ au_pin_set_parent_lflag(pin, /*lflag*/0);
14570+ goto out_dput; /* success */
14571+ }
14572+ au_unpin(pin);
14573+ goto out_unlock;
1facf9fc 14574+
4f0767ce 14575+out_dgrade:
4a4d8108 14576+ di_downgrade_lock(parent, AuLock_IR);
4f0767ce 14577+out_unlock:
4a4d8108 14578+ di_read_unlock(parent, AuLock_IR);
4f0767ce 14579+out_dput:
4a4d8108 14580+ dput(parent);
4f0767ce 14581+out:
1facf9fc 14582+ return err;
14583+}
14584+
4a4d8108
AM
14585+/* ---------------------------------------------------------------------- */
14586+
14587+int au_do_flush(struct file *file, fl_owner_t id,
14588+ int (*flush)(struct file *file, fl_owner_t id))
1facf9fc 14589+{
4a4d8108 14590+ int err;
1facf9fc 14591+ struct super_block *sb;
4a4d8108 14592+ struct inode *inode;
1facf9fc 14593+
c06a8ce3
AM
14594+ inode = file_inode(file);
14595+ sb = inode->i_sb;
4a4d8108
AM
14596+ si_noflush_read_lock(sb);
14597+ fi_read_lock(file);
b752ccd1 14598+ ii_read_lock_child(inode);
1facf9fc 14599+
4a4d8108
AM
14600+ err = flush(file, id);
14601+ au_cpup_attr_timesizes(inode);
1facf9fc 14602+
b752ccd1 14603+ ii_read_unlock(inode);
4a4d8108 14604+ fi_read_unlock(file);
1308ab2a 14605+ si_read_unlock(sb);
dece6358 14606+ return err;
1facf9fc 14607+}
14608+
4a4d8108
AM
14609+/* ---------------------------------------------------------------------- */
14610+
14611+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
1facf9fc 14612+{
4a4d8108 14613+ int err;
4a4d8108
AM
14614+ struct au_pin pin;
14615+ struct au_finfo *finfo;
c2b27bf2 14616+ struct dentry *parent, *hi_wh;
4a4d8108 14617+ struct inode *inode;
1facf9fc 14618+ struct super_block *sb;
c2b27bf2 14619+ struct au_cp_generic cpg = {
2000de60 14620+ .dentry = file->f_path.dentry,
c2b27bf2
AM
14621+ .bdst = -1,
14622+ .bsrc = -1,
14623+ .len = -1,
14624+ .pin = &pin,
14625+ .flags = AuCpup_DTIME
14626+ };
1facf9fc 14627+
4a4d8108
AM
14628+ FiMustWriteLock(file);
14629+
14630+ err = 0;
14631+ finfo = au_fi(file);
c2b27bf2 14632+ sb = cpg.dentry->d_sb;
5527c038 14633+ inode = d_inode(cpg.dentry);
5afbbe0d 14634+ cpg.bdst = au_ibtop(inode);
c2b27bf2 14635+ if (cpg.bdst == finfo->fi_btop || IS_ROOT(cpg.dentry))
1308ab2a 14636+ goto out;
dece6358 14637+
c2b27bf2
AM
14638+ parent = dget_parent(cpg.dentry);
14639+ if (au_test_ro(sb, cpg.bdst, inode)) {
4a4d8108 14640+ di_read_lock_parent(parent, !AuLock_IR);
c2b27bf2
AM
14641+ err = AuWbrCopyup(au_sbi(sb), cpg.dentry);
14642+ cpg.bdst = err;
4a4d8108
AM
14643+ di_read_unlock(parent, !AuLock_IR);
14644+ if (unlikely(err < 0))
14645+ goto out_parent;
14646+ err = 0;
1facf9fc 14647+ }
1facf9fc 14648+
4a4d8108 14649+ di_read_lock_parent(parent, AuLock_IR);
c2b27bf2 14650+ hi_wh = au_hi_wh(inode, cpg.bdst);
7f207e10
AM
14651+ if (!S_ISDIR(inode->i_mode)
14652+ && au_opt_test(au_mntflags(sb), PLINK)
4a4d8108 14653+ && au_plink_test(inode)
c2b27bf2 14654+ && !d_unhashed(cpg.dentry)
5afbbe0d 14655+ && cpg.bdst < au_dbtop(cpg.dentry)) {
c2b27bf2 14656+ err = au_test_and_cpup_dirs(cpg.dentry, cpg.bdst);
4a4d8108
AM
14657+ if (unlikely(err))
14658+ goto out_unlock;
14659+
14660+ /* always superio. */
c2b27bf2 14661+ err = au_pin(&pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE,
4a4d8108 14662+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
367653fa 14663+ if (!err) {
c2b27bf2 14664+ err = au_sio_cpup_simple(&cpg);
367653fa
AM
14665+ au_unpin(&pin);
14666+ }
4a4d8108
AM
14667+ } else if (hi_wh) {
14668+ /* already copied-up after unlink */
c2b27bf2 14669+ err = au_reopen_wh(file, cpg.bdst, hi_wh);
4a4d8108
AM
14670+ *need_reopen = 0;
14671+ }
1facf9fc 14672+
4f0767ce 14673+out_unlock:
4a4d8108 14674+ di_read_unlock(parent, AuLock_IR);
4f0767ce 14675+out_parent:
4a4d8108 14676+ dput(parent);
4f0767ce 14677+out:
1308ab2a 14678+ return err;
dece6358 14679+}
1facf9fc 14680+
4a4d8108 14681+static void au_do_refresh_dir(struct file *file)
dece6358 14682+{
5afbbe0d 14683+ aufs_bindex_t bindex, bbot, new_bindex, brid;
4a4d8108
AM
14684+ struct au_hfile *p, tmp, *q;
14685+ struct au_finfo *finfo;
1308ab2a 14686+ struct super_block *sb;
4a4d8108 14687+ struct au_fidir *fidir;
1facf9fc 14688+
4a4d8108 14689+ FiMustWriteLock(file);
1facf9fc 14690+
2000de60 14691+ sb = file->f_path.dentry->d_sb;
4a4d8108
AM
14692+ finfo = au_fi(file);
14693+ fidir = finfo->fi_hdir;
14694+ AuDebugOn(!fidir);
14695+ p = fidir->fd_hfile + finfo->fi_btop;
14696+ brid = p->hf_br->br_id;
5afbbe0d
AM
14697+ bbot = fidir->fd_bbot;
14698+ for (bindex = finfo->fi_btop; bindex <= bbot; bindex++, p++) {
4a4d8108
AM
14699+ if (!p->hf_file)
14700+ continue;
1308ab2a 14701+
4a4d8108
AM
14702+ new_bindex = au_br_index(sb, p->hf_br->br_id);
14703+ if (new_bindex == bindex)
14704+ continue;
14705+ if (new_bindex < 0) {
14706+ au_set_h_fptr(file, bindex, NULL);
14707+ continue;
14708+ }
1308ab2a 14709+
4a4d8108
AM
14710+ /* swap two lower inode, and loop again */
14711+ q = fidir->fd_hfile + new_bindex;
14712+ tmp = *q;
14713+ *q = *p;
14714+ *p = tmp;
14715+ if (tmp.hf_file) {
14716+ bindex--;
14717+ p--;
14718+ }
14719+ }
1308ab2a 14720+
4a4d8108 14721+ p = fidir->fd_hfile;
2000de60 14722+ if (!au_test_mmapped(file) && !d_unlinked(file->f_path.dentry)) {
5afbbe0d
AM
14723+ bbot = au_sbbot(sb);
14724+ for (finfo->fi_btop = 0; finfo->fi_btop <= bbot;
4a4d8108
AM
14725+ finfo->fi_btop++, p++)
14726+ if (p->hf_file) {
c06a8ce3 14727+ if (file_inode(p->hf_file))
4a4d8108 14728+ break;
1c60b727 14729+ au_hfput(p, /*execed*/0);
4a4d8108
AM
14730+ }
14731+ } else {
5afbbe0d
AM
14732+ bbot = au_br_index(sb, brid);
14733+ for (finfo->fi_btop = 0; finfo->fi_btop < bbot;
4a4d8108
AM
14734+ finfo->fi_btop++, p++)
14735+ if (p->hf_file)
1c60b727 14736+ au_hfput(p, /*execed*/0);
5afbbe0d 14737+ bbot = au_sbbot(sb);
4a4d8108 14738+ }
1308ab2a 14739+
5afbbe0d
AM
14740+ p = fidir->fd_hfile + bbot;
14741+ for (fidir->fd_bbot = bbot; fidir->fd_bbot >= finfo->fi_btop;
4a4d8108
AM
14742+ fidir->fd_bbot--, p--)
14743+ if (p->hf_file) {
c06a8ce3 14744+ if (file_inode(p->hf_file))
4a4d8108 14745+ break;
1c60b727 14746+ au_hfput(p, /*execed*/0);
4a4d8108
AM
14747+ }
14748+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
1308ab2a 14749+}
14750+
4a4d8108
AM
14751+/*
14752+ * after branch manipulating, refresh the file.
14753+ */
14754+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
1facf9fc 14755+{
e2f27e51 14756+ int err, need_reopen, nbr;
5afbbe0d 14757+ aufs_bindex_t bbot, bindex;
4a4d8108 14758+ struct dentry *dentry;
e2f27e51 14759+ struct super_block *sb;
1308ab2a 14760+ struct au_finfo *finfo;
4a4d8108 14761+ struct au_hfile *hfile;
1facf9fc 14762+
2000de60 14763+ dentry = file->f_path.dentry;
e2f27e51
AM
14764+ sb = dentry->d_sb;
14765+ nbr = au_sbbot(sb) + 1;
1308ab2a 14766+ finfo = au_fi(file);
4a4d8108
AM
14767+ if (!finfo->fi_hdir) {
14768+ hfile = &finfo->fi_htop;
14769+ AuDebugOn(!hfile->hf_file);
e2f27e51 14770+ bindex = au_br_index(sb, hfile->hf_br->br_id);
4a4d8108
AM
14771+ AuDebugOn(bindex < 0);
14772+ if (bindex != finfo->fi_btop)
5afbbe0d 14773+ au_set_fbtop(file, bindex);
4a4d8108 14774+ } else {
e2f27e51 14775+ err = au_fidir_realloc(finfo, nbr, /*may_shrink*/0);
4a4d8108
AM
14776+ if (unlikely(err))
14777+ goto out;
14778+ au_do_refresh_dir(file);
14779+ }
1facf9fc 14780+
4a4d8108
AM
14781+ err = 0;
14782+ need_reopen = 1;
14783+ if (!au_test_mmapped(file))
14784+ err = au_file_refresh_by_inode(file, &need_reopen);
e2f27e51
AM
14785+ if (finfo->fi_hdir)
14786+ /* harmless if err */
14787+ au_fidir_realloc(finfo, nbr, /*may_shrink*/1);
027c5e7a 14788+ if (!err && need_reopen && !d_unlinked(dentry))
4a4d8108
AM
14789+ err = reopen(file);
14790+ if (!err) {
14791+ au_update_figen(file);
14792+ goto out; /* success */
14793+ }
14794+
14795+ /* error, close all lower files */
14796+ if (finfo->fi_hdir) {
5afbbe0d
AM
14797+ bbot = au_fbbot_dir(file);
14798+ for (bindex = au_fbtop(file); bindex <= bbot; bindex++)
4a4d8108
AM
14799+ au_set_h_fptr(file, bindex, NULL);
14800+ }
1facf9fc 14801+
4f0767ce 14802+out:
1facf9fc 14803+ return err;
14804+}
14805+
4a4d8108
AM
14806+/* common function to regular file and dir */
14807+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
521ced18 14808+ int wlock, unsigned int fi_lsc)
dece6358 14809+{
1308ab2a 14810+ int err;
4a4d8108 14811+ unsigned int sigen, figen;
5afbbe0d 14812+ aufs_bindex_t btop;
4a4d8108
AM
14813+ unsigned char pseudo_link;
14814+ struct dentry *dentry;
14815+ struct inode *inode;
1facf9fc 14816+
4a4d8108 14817+ err = 0;
2000de60 14818+ dentry = file->f_path.dentry;
5527c038 14819+ inode = d_inode(dentry);
4a4d8108 14820+ sigen = au_sigen(dentry->d_sb);
521ced18 14821+ fi_write_lock_nested(file, fi_lsc);
4a4d8108 14822+ figen = au_figen(file);
521ced18
JR
14823+ if (!fi_lsc)
14824+ di_write_lock_child(dentry);
14825+ else
14826+ di_write_lock_child2(dentry);
5afbbe0d
AM
14827+ btop = au_dbtop(dentry);
14828+ pseudo_link = (btop != au_ibtop(inode));
14829+ if (sigen == figen && !pseudo_link && au_fbtop(file) == btop) {
4a4d8108
AM
14830+ if (!wlock) {
14831+ di_downgrade_lock(dentry, AuLock_IR);
14832+ fi_downgrade_lock(file);
14833+ }
14834+ goto out; /* success */
14835+ }
dece6358 14836+
4a4d8108 14837+ AuDbg("sigen %d, figen %d\n", sigen, figen);
027c5e7a 14838+ if (au_digen_test(dentry, sigen)) {
4a4d8108 14839+ err = au_reval_dpath(dentry, sigen);
027c5e7a 14840+ AuDebugOn(!err && au_digen_test(dentry, sigen));
4a4d8108 14841+ }
dece6358 14842+
027c5e7a
AM
14843+ if (!err)
14844+ err = refresh_file(file, reopen);
4a4d8108
AM
14845+ if (!err) {
14846+ if (!wlock) {
14847+ di_downgrade_lock(dentry, AuLock_IR);
14848+ fi_downgrade_lock(file);
14849+ }
14850+ } else {
14851+ di_write_unlock(dentry);
14852+ fi_write_unlock(file);
14853+ }
1facf9fc 14854+
4f0767ce 14855+out:
1308ab2a 14856+ return err;
14857+}
1facf9fc 14858+
4a4d8108
AM
14859+/* ---------------------------------------------------------------------- */
14860+
14861+/* cf. aufs_nopage() */
14862+/* for madvise(2) */
14863+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
1308ab2a 14864+{
4a4d8108
AM
14865+ unlock_page(page);
14866+ return 0;
14867+}
1facf9fc 14868+
4a4d8108 14869+/* it will never be called, but necessary to support O_DIRECT */
5afbbe0d 14870+static ssize_t aufs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
4a4d8108 14871+{ BUG(); return 0; }
1facf9fc 14872+
4a4d8108
AM
14873+/* they will never be called. */
14874+#ifdef CONFIG_AUFS_DEBUG
14875+static int aufs_write_begin(struct file *file, struct address_space *mapping,
14876+ loff_t pos, unsigned len, unsigned flags,
14877+ struct page **pagep, void **fsdata)
14878+{ AuUnsupport(); return 0; }
14879+static int aufs_write_end(struct file *file, struct address_space *mapping,
14880+ loff_t pos, unsigned len, unsigned copied,
14881+ struct page *page, void *fsdata)
14882+{ AuUnsupport(); return 0; }
14883+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
14884+{ AuUnsupport(); return 0; }
1308ab2a 14885+
4a4d8108
AM
14886+static int aufs_set_page_dirty(struct page *page)
14887+{ AuUnsupport(); return 0; }
392086de
AM
14888+static void aufs_invalidatepage(struct page *page, unsigned int offset,
14889+ unsigned int length)
4a4d8108
AM
14890+{ AuUnsupport(); }
14891+static int aufs_releasepage(struct page *page, gfp_t gfp)
14892+{ AuUnsupport(); return 0; }
79b8bda9 14893+#if 0 /* called by memory compaction regardless file */
4a4d8108 14894+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
7eafdf33 14895+ struct page *page, enum migrate_mode mode)
4a4d8108 14896+{ AuUnsupport(); return 0; }
79b8bda9 14897+#endif
e2f27e51
AM
14898+static bool aufs_isolate_page(struct page *page, isolate_mode_t mode)
14899+{ AuUnsupport(); return true; }
14900+static void aufs_putback_page(struct page *page)
14901+{ AuUnsupport(); }
4a4d8108
AM
14902+static int aufs_launder_page(struct page *page)
14903+{ AuUnsupport(); return 0; }
14904+static int aufs_is_partially_uptodate(struct page *page,
38d290e6
JR
14905+ unsigned long from,
14906+ unsigned long count)
4a4d8108 14907+{ AuUnsupport(); return 0; }
392086de
AM
14908+static void aufs_is_dirty_writeback(struct page *page, bool *dirty,
14909+ bool *writeback)
14910+{ AuUnsupport(); }
4a4d8108
AM
14911+static int aufs_error_remove_page(struct address_space *mapping,
14912+ struct page *page)
14913+{ AuUnsupport(); return 0; }
b4510431
AM
14914+static int aufs_swap_activate(struct swap_info_struct *sis, struct file *file,
14915+ sector_t *span)
14916+{ AuUnsupport(); return 0; }
14917+static void aufs_swap_deactivate(struct file *file)
14918+{ AuUnsupport(); }
4a4d8108
AM
14919+#endif /* CONFIG_AUFS_DEBUG */
14920+
14921+const struct address_space_operations aufs_aop = {
14922+ .readpage = aufs_readpage,
14923+ .direct_IO = aufs_direct_IO,
4a4d8108
AM
14924+#ifdef CONFIG_AUFS_DEBUG
14925+ .writepage = aufs_writepage,
4a4d8108
AM
14926+ /* no writepages, because of writepage */
14927+ .set_page_dirty = aufs_set_page_dirty,
14928+ /* no readpages, because of readpage */
14929+ .write_begin = aufs_write_begin,
14930+ .write_end = aufs_write_end,
14931+ /* no bmap, no block device */
14932+ .invalidatepage = aufs_invalidatepage,
14933+ .releasepage = aufs_releasepage,
79b8bda9
AM
14934+ /* is fallback_migrate_page ok? */
14935+ /* .migratepage = aufs_migratepage, */
e2f27e51
AM
14936+ .isolate_page = aufs_isolate_page,
14937+ .putback_page = aufs_putback_page,
4a4d8108
AM
14938+ .launder_page = aufs_launder_page,
14939+ .is_partially_uptodate = aufs_is_partially_uptodate,
392086de 14940+ .is_dirty_writeback = aufs_is_dirty_writeback,
b4510431
AM
14941+ .error_remove_page = aufs_error_remove_page,
14942+ .swap_activate = aufs_swap_activate,
14943+ .swap_deactivate = aufs_swap_deactivate
4a4d8108 14944+#endif /* CONFIG_AUFS_DEBUG */
dece6358 14945+};
7f207e10 14946diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
eca34b5c 14947--- /usr/share/empty/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 14948+++ linux/fs/aufs/file.h 2021-05-02 20:15:14.673337458 +0200
9f237c51 14949@@ -0,0 +1,342 @@
062440b3 14950+/* SPDX-License-Identifier: GPL-2.0 */
4a4d8108 14951+/*
d58c55f2 14952+ * Copyright (C) 2005-2020 Junjiro R. Okajima
4a4d8108
AM
14953+ *
14954+ * This program, aufs is free software; you can redistribute it and/or modify
14955+ * it under the terms of the GNU General Public License as published by
14956+ * the Free Software Foundation; either version 2 of the License, or
14957+ * (at your option) any later version.
14958+ *
14959+ * This program is distributed in the hope that it will be useful,
14960+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14961+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14962+ * GNU General Public License for more details.
14963+ *
14964+ * You should have received a copy of the GNU General Public License
523b37e3 14965+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 14966+ */
1facf9fc 14967+
4a4d8108
AM
14968+/*
14969+ * file operations
14970+ */
1facf9fc 14971+
4a4d8108
AM
14972+#ifndef __AUFS_FILE_H__
14973+#define __AUFS_FILE_H__
1facf9fc 14974+
4a4d8108 14975+#ifdef __KERNEL__
1facf9fc 14976+
2cbb1c4b 14977+#include <linux/file.h>
4a4d8108 14978+#include <linux/fs.h>
3c1bdaff 14979+#include <linux/mm_types.h>
4a4d8108 14980+#include <linux/poll.h>
4a4d8108 14981+#include "rwsem.h"
1facf9fc 14982+
4a4d8108
AM
14983+struct au_branch;
14984+struct au_hfile {
14985+ struct file *hf_file;
14986+ struct au_branch *hf_br;
14987+};
1facf9fc 14988+
4a4d8108
AM
14989+struct au_vdir;
14990+struct au_fidir {
14991+ aufs_bindex_t fd_bbot;
14992+ aufs_bindex_t fd_nent;
14993+ struct au_vdir *fd_vdir_cache;
14994+ struct au_hfile fd_hfile[];
14995+};
1facf9fc 14996+
4a4d8108 14997+static inline int au_fidir_sz(int nent)
dece6358 14998+{
4f0767ce
JR
14999+ AuDebugOn(nent < 0);
15000+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
4a4d8108 15001+}
1facf9fc 15002+
4a4d8108
AM
15003+struct au_finfo {
15004+ atomic_t fi_generation;
dece6358 15005+
4a4d8108
AM
15006+ struct au_rwsem fi_rwsem;
15007+ aufs_bindex_t fi_btop;
15008+
15009+ /* do not union them */
15010+ struct { /* for non-dir */
15011+ struct au_hfile fi_htop;
2cbb1c4b 15012+ atomic_t fi_mmapped;
4a4d8108
AM
15013+ };
15014+ struct au_fidir *fi_hdir; /* for dir only */
523b37e3 15015+
8b6a4947 15016+ struct hlist_bl_node fi_hlist;
1c60b727 15017+ struct file *fi_file; /* very ugly */
9f237c51 15018+ struct rcu_head rcu;
4a4d8108 15019+} ____cacheline_aligned_in_smp;
1facf9fc 15020+
4a4d8108 15021+/* ---------------------------------------------------------------------- */
1facf9fc 15022+
4a4d8108
AM
15023+/* file.c */
15024+extern const struct address_space_operations aufs_aop;
15025+unsigned int au_file_roflags(unsigned int flags);
15026+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
392086de 15027+ struct file *file, int force_wr);
b912730e 15028+struct au_do_open_args {
8b6a4947 15029+ int aopen;
b912730e
AM
15030+ int (*open)(struct file *file, int flags,
15031+ struct file *h_file);
15032+ struct au_fidir *fidir;
15033+ struct file *h_file;
15034+};
15035+int au_do_open(struct file *file, struct au_do_open_args *args);
4a4d8108
AM
15036+int au_reopen_nondir(struct file *file);
15037+struct au_pin;
15038+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
15039+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
521ced18 15040+ int wlock, unsigned int fi_lsc);
4a4d8108
AM
15041+int au_do_flush(struct file *file, fl_owner_t id,
15042+ int (*flush)(struct file *file, fl_owner_t id));
1facf9fc 15043+
4a4d8108
AM
15044+/* poll.c */
15045+#ifdef CONFIG_AUFS_POLL
cd7a4cd9 15046+__poll_t aufs_poll(struct file *file, struct poll_table_struct *pt);
4a4d8108 15047+#endif
1facf9fc 15048+
4a4d8108
AM
15049+#ifdef CONFIG_AUFS_BR_HFSPLUS
15050+/* hfsplus.c */
392086de
AM
15051+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex,
15052+ int force_wr);
4a4d8108
AM
15053+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
15054+ struct file *h_file);
15055+#else
c1595e42
JR
15056+AuStub(struct file *, au_h_open_pre, return NULL, struct dentry *dentry,
15057+ aufs_bindex_t bindex, int force_wr)
4a4d8108
AM
15058+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
15059+ struct file *h_file);
15060+#endif
1facf9fc 15061+
4a4d8108
AM
15062+/* f_op.c */
15063+extern const struct file_operations aufs_file_fop;
b912730e 15064+int au_do_open_nondir(struct file *file, int flags, struct file *h_file);
4a4d8108 15065+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
521ced18 15066+struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc);
4a4d8108 15067+
4a4d8108 15068+/* finfo.c */
f0c0a007 15069+void au_hfput(struct au_hfile *hf, int execed);
4a4d8108
AM
15070+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
15071+ struct file *h_file);
1facf9fc 15072+
4a4d8108 15073+void au_update_figen(struct file *file);
4a4d8108 15074+struct au_fidir *au_fidir_alloc(struct super_block *sb);
e2f27e51 15075+int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink);
1facf9fc 15076+
4a4d8108 15077+void au_fi_init_once(void *_fi);
1c60b727 15078+void au_finfo_fin(struct file *file);
4a4d8108 15079+int au_finfo_init(struct file *file, struct au_fidir *fidir);
1facf9fc 15080+
4a4d8108
AM
15081+/* ioctl.c */
15082+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
15083+#ifdef CONFIG_COMPAT
15084+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
15085+ unsigned long arg);
c2b27bf2
AM
15086+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
15087+ unsigned long arg);
b752ccd1 15088+#endif
1facf9fc 15089+
4a4d8108 15090+/* ---------------------------------------------------------------------- */
1facf9fc 15091+
4a4d8108
AM
15092+static inline struct au_finfo *au_fi(struct file *file)
15093+{
38d290e6 15094+ return file->private_data;
4a4d8108 15095+}
1facf9fc 15096+
4a4d8108 15097+/* ---------------------------------------------------------------------- */
1facf9fc 15098+
8b6a4947
AM
15099+#define fi_read_lock(f) au_rw_read_lock(&au_fi(f)->fi_rwsem)
15100+#define fi_write_lock(f) au_rw_write_lock(&au_fi(f)->fi_rwsem)
15101+#define fi_read_trylock(f) au_rw_read_trylock(&au_fi(f)->fi_rwsem)
15102+#define fi_write_trylock(f) au_rw_write_trylock(&au_fi(f)->fi_rwsem)
4a4d8108 15103+/*
8b6a4947
AM
15104+#define fi_read_trylock_nested(f) \
15105+ au_rw_read_trylock_nested(&au_fi(f)->fi_rwsem)
15106+#define fi_write_trylock_nested(f) \
15107+ au_rw_write_trylock_nested(&au_fi(f)->fi_rwsem)
15108+*/
15109+
15110+#define fi_read_unlock(f) au_rw_read_unlock(&au_fi(f)->fi_rwsem)
15111+#define fi_write_unlock(f) au_rw_write_unlock(&au_fi(f)->fi_rwsem)
15112+#define fi_downgrade_lock(f) au_rw_dgrade_lock(&au_fi(f)->fi_rwsem)
1308ab2a 15113+
521ced18
JR
15114+/* lock subclass for finfo */
15115+enum {
15116+ AuLsc_FI_1,
15117+ AuLsc_FI_2
15118+};
15119+
15120+static inline void fi_read_lock_nested(struct file *f, unsigned int lsc)
15121+{
15122+ au_rw_read_lock_nested(&au_fi(f)->fi_rwsem, lsc);
15123+}
15124+
15125+static inline void fi_write_lock_nested(struct file *f, unsigned int lsc)
15126+{
15127+ au_rw_write_lock_nested(&au_fi(f)->fi_rwsem, lsc);
15128+}
15129+
15130+/*
15131+ * fi_read_lock_1, fi_write_lock_1,
15132+ * fi_read_lock_2, fi_write_lock_2
15133+ */
15134+#define AuReadLockFunc(name) \
15135+static inline void fi_read_lock_##name(struct file *f) \
15136+{ fi_read_lock_nested(f, AuLsc_FI_##name); }
15137+
15138+#define AuWriteLockFunc(name) \
15139+static inline void fi_write_lock_##name(struct file *f) \
15140+{ fi_write_lock_nested(f, AuLsc_FI_##name); }
15141+
15142+#define AuRWLockFuncs(name) \
15143+ AuReadLockFunc(name) \
15144+ AuWriteLockFunc(name)
15145+
15146+AuRWLockFuncs(1);
15147+AuRWLockFuncs(2);
15148+
15149+#undef AuReadLockFunc
15150+#undef AuWriteLockFunc
15151+#undef AuRWLockFuncs
15152+
4a4d8108
AM
15153+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
15154+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
15155+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 15156+
1308ab2a 15157+/* ---------------------------------------------------------------------- */
15158+
4a4d8108 15159+/* todo: hard/soft set? */
5afbbe0d 15160+static inline aufs_bindex_t au_fbtop(struct file *file)
dece6358 15161+{
4a4d8108
AM
15162+ FiMustAnyLock(file);
15163+ return au_fi(file)->fi_btop;
15164+}
dece6358 15165+
5afbbe0d 15166+static inline aufs_bindex_t au_fbbot_dir(struct file *file)
4a4d8108
AM
15167+{
15168+ FiMustAnyLock(file);
15169+ AuDebugOn(!au_fi(file)->fi_hdir);
15170+ return au_fi(file)->fi_hdir->fd_bbot;
15171+}
1facf9fc 15172+
4a4d8108
AM
15173+static inline struct au_vdir *au_fvdir_cache(struct file *file)
15174+{
15175+ FiMustAnyLock(file);
15176+ AuDebugOn(!au_fi(file)->fi_hdir);
15177+ return au_fi(file)->fi_hdir->fd_vdir_cache;
15178+}
1facf9fc 15179+
5afbbe0d 15180+static inline void au_set_fbtop(struct file *file, aufs_bindex_t bindex)
4a4d8108
AM
15181+{
15182+ FiMustWriteLock(file);
15183+ au_fi(file)->fi_btop = bindex;
15184+}
1facf9fc 15185+
5afbbe0d 15186+static inline void au_set_fbbot_dir(struct file *file, aufs_bindex_t bindex)
4a4d8108
AM
15187+{
15188+ FiMustWriteLock(file);
15189+ AuDebugOn(!au_fi(file)->fi_hdir);
15190+ au_fi(file)->fi_hdir->fd_bbot = bindex;
15191+}
1308ab2a 15192+
4a4d8108
AM
15193+static inline void au_set_fvdir_cache(struct file *file,
15194+ struct au_vdir *vdir_cache)
15195+{
15196+ FiMustWriteLock(file);
15197+ AuDebugOn(!au_fi(file)->fi_hdir);
15198+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
15199+}
dece6358 15200+
4a4d8108
AM
15201+static inline struct file *au_hf_top(struct file *file)
15202+{
15203+ FiMustAnyLock(file);
15204+ AuDebugOn(au_fi(file)->fi_hdir);
15205+ return au_fi(file)->fi_htop.hf_file;
15206+}
1facf9fc 15207+
4a4d8108
AM
15208+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
15209+{
15210+ FiMustAnyLock(file);
15211+ AuDebugOn(!au_fi(file)->fi_hdir);
15212+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
dece6358
AM
15213+}
15214+
4a4d8108
AM
15215+/* todo: memory barrier? */
15216+static inline unsigned int au_figen(struct file *f)
dece6358 15217+{
4a4d8108
AM
15218+ return atomic_read(&au_fi(f)->fi_generation);
15219+}
dece6358 15220+
2cbb1c4b
JR
15221+static inline void au_set_mmapped(struct file *f)
15222+{
15223+ if (atomic_inc_return(&au_fi(f)->fi_mmapped))
15224+ return;
0c3ec466 15225+ pr_warn("fi_mmapped wrapped around\n");
2cbb1c4b
JR
15226+ while (!atomic_inc_return(&au_fi(f)->fi_mmapped))
15227+ ;
15228+}
15229+
15230+static inline void au_unset_mmapped(struct file *f)
15231+{
15232+ atomic_dec(&au_fi(f)->fi_mmapped);
15233+}
15234+
4a4d8108
AM
15235+static inline int au_test_mmapped(struct file *f)
15236+{
2cbb1c4b
JR
15237+ return atomic_read(&au_fi(f)->fi_mmapped);
15238+}
15239+
15240+/* customize vma->vm_file */
15241+
15242+static inline void au_do_vm_file_reset(struct vm_area_struct *vma,
15243+ struct file *file)
15244+{
53392da6
AM
15245+ struct file *f;
15246+
15247+ f = vma->vm_file;
2cbb1c4b
JR
15248+ get_file(file);
15249+ vma->vm_file = file;
53392da6 15250+ fput(f);
2cbb1c4b
JR
15251+}
15252+
15253+#ifdef CONFIG_MMU
15254+#define AuDbgVmRegion(file, vma) do {} while (0)
15255+
15256+static inline void au_vm_file_reset(struct vm_area_struct *vma,
15257+ struct file *file)
15258+{
15259+ au_do_vm_file_reset(vma, file);
15260+}
15261+#else
15262+#define AuDbgVmRegion(file, vma) \
15263+ AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file))
15264+
15265+static inline void au_vm_file_reset(struct vm_area_struct *vma,
15266+ struct file *file)
15267+{
53392da6
AM
15268+ struct file *f;
15269+
2cbb1c4b 15270+ au_do_vm_file_reset(vma, file);
53392da6 15271+ f = vma->vm_region->vm_file;
2cbb1c4b
JR
15272+ get_file(file);
15273+ vma->vm_region->vm_file = file;
53392da6 15274+ fput(f);
2cbb1c4b
JR
15275+}
15276+#endif /* CONFIG_MMU */
15277+
15278+/* handle vma->vm_prfile */
fb47a38f 15279+static inline void au_vm_prfile_set(struct vm_area_struct *vma,
2cbb1c4b
JR
15280+ struct file *file)
15281+{
2cbb1c4b
JR
15282+ get_file(file);
15283+ vma->vm_prfile = file;
15284+#ifndef CONFIG_MMU
15285+ get_file(file);
15286+ vma->vm_region->vm_prfile = file;
15287+#endif
fb47a38f 15288+}
1308ab2a 15289+
4a4d8108
AM
15290+#endif /* __KERNEL__ */
15291+#endif /* __AUFS_FILE_H__ */
7f207e10 15292diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
eca34b5c 15293--- /usr/share/empty/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 15294+++ linux/fs/aufs/finfo.c 2021-05-02 20:15:14.673337458 +0200
062440b3 15295@@ -0,0 +1,149 @@
cd7a4cd9 15296+// SPDX-License-Identifier: GPL-2.0
4a4d8108 15297+/*
d58c55f2 15298+ * Copyright (C) 2005-2020 Junjiro R. Okajima
4a4d8108
AM
15299+ *
15300+ * This program, aufs is free software; you can redistribute it and/or modify
15301+ * it under the terms of the GNU General Public License as published by
15302+ * the Free Software Foundation; either version 2 of the License, or
15303+ * (at your option) any later version.
15304+ *
15305+ * This program is distributed in the hope that it will be useful,
15306+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15307+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15308+ * GNU General Public License for more details.
15309+ *
15310+ * You should have received a copy of the GNU General Public License
523b37e3 15311+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 15312+ */
1308ab2a 15313+
4a4d8108
AM
15314+/*
15315+ * file private data
15316+ */
1facf9fc 15317+
4a4d8108 15318+#include "aufs.h"
1facf9fc 15319+
f0c0a007 15320+void au_hfput(struct au_hfile *hf, int execed)
4a4d8108 15321+{
f0c0a007 15322+ if (execed)
4a4d8108
AM
15323+ allow_write_access(hf->hf_file);
15324+ fput(hf->hf_file);
15325+ hf->hf_file = NULL;
acd2b654 15326+ au_lcnt_dec(&hf->hf_br->br_nfiles);
4a4d8108
AM
15327+ hf->hf_br = NULL;
15328+}
1facf9fc 15329+
4a4d8108
AM
15330+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
15331+{
15332+ struct au_finfo *finfo = au_fi(file);
15333+ struct au_hfile *hf;
15334+ struct au_fidir *fidir;
15335+
15336+ fidir = finfo->fi_hdir;
15337+ if (!fidir) {
15338+ AuDebugOn(finfo->fi_btop != bindex);
15339+ hf = &finfo->fi_htop;
15340+ } else
15341+ hf = fidir->fd_hfile + bindex;
15342+
15343+ if (hf && hf->hf_file)
f0c0a007 15344+ au_hfput(hf, vfsub_file_execed(file));
4a4d8108
AM
15345+ if (val) {
15346+ FiMustWriteLock(file);
b912730e 15347+ AuDebugOn(IS_ERR_OR_NULL(file->f_path.dentry));
4a4d8108 15348+ hf->hf_file = val;
2000de60 15349+ hf->hf_br = au_sbr(file->f_path.dentry->d_sb, bindex);
1308ab2a 15350+ }
4a4d8108 15351+}
1facf9fc 15352+
4a4d8108
AM
15353+void au_update_figen(struct file *file)
15354+{
2000de60 15355+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_path.dentry));
4a4d8108 15356+ /* smp_mb(); */ /* atomic_set */
1facf9fc 15357+}
15358+
4a4d8108
AM
15359+/* ---------------------------------------------------------------------- */
15360+
4a4d8108
AM
15361+struct au_fidir *au_fidir_alloc(struct super_block *sb)
15362+{
15363+ struct au_fidir *fidir;
15364+ int nbr;
15365+
5afbbe0d 15366+ nbr = au_sbbot(sb) + 1;
4a4d8108
AM
15367+ if (nbr < 2)
15368+ nbr = 2; /* initial allocate for 2 branches */
15369+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
15370+ if (fidir) {
15371+ fidir->fd_bbot = -1;
15372+ fidir->fd_nent = nbr;
4a4d8108
AM
15373+ }
15374+
15375+ return fidir;
15376+}
15377+
e2f27e51 15378+int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink)
4a4d8108
AM
15379+{
15380+ int err;
15381+ struct au_fidir *fidir, *p;
15382+
15383+ AuRwMustWriteLock(&finfo->fi_rwsem);
15384+ fidir = finfo->fi_hdir;
15385+ AuDebugOn(!fidir);
15386+
15387+ err = -ENOMEM;
15388+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
e2f27e51 15389+ GFP_NOFS, may_shrink);
4a4d8108
AM
15390+ if (p) {
15391+ p->fd_nent = nbr;
15392+ finfo->fi_hdir = p;
15393+ err = 0;
15394+ }
1facf9fc 15395+
dece6358 15396+ return err;
1facf9fc 15397+}
1308ab2a 15398+
15399+/* ---------------------------------------------------------------------- */
15400+
1c60b727 15401+void au_finfo_fin(struct file *file)
1308ab2a 15402+{
4a4d8108
AM
15403+ struct au_finfo *finfo;
15404+
acd2b654 15405+ au_lcnt_dec(&au_sbi(file->f_path.dentry->d_sb)->si_nfiles);
7f207e10 15406+
4a4d8108
AM
15407+ finfo = au_fi(file);
15408+ AuDebugOn(finfo->fi_hdir);
15409+ AuRwDestroy(&finfo->fi_rwsem);
1c60b727 15410+ au_cache_free_finfo(finfo);
1308ab2a 15411+}
1308ab2a 15412+
e49829fe 15413+void au_fi_init_once(void *_finfo)
4a4d8108 15414+{
e49829fe 15415+ struct au_finfo *finfo = _finfo;
1308ab2a 15416+
e49829fe 15417+ au_rw_init(&finfo->fi_rwsem);
4a4d8108 15418+}
1308ab2a 15419+
4a4d8108
AM
15420+int au_finfo_init(struct file *file, struct au_fidir *fidir)
15421+{
1716fcea 15422+ int err;
4a4d8108
AM
15423+ struct au_finfo *finfo;
15424+ struct dentry *dentry;
15425+
15426+ err = -ENOMEM;
2000de60 15427+ dentry = file->f_path.dentry;
4a4d8108
AM
15428+ finfo = au_cache_alloc_finfo();
15429+ if (unlikely(!finfo))
15430+ goto out;
15431+
15432+ err = 0;
acd2b654 15433+ au_lcnt_inc(&au_sbi(dentry->d_sb)->si_nfiles);
4a4d8108
AM
15434+ au_rw_write_lock(&finfo->fi_rwsem);
15435+ finfo->fi_btop = -1;
15436+ finfo->fi_hdir = fidir;
15437+ atomic_set(&finfo->fi_generation, au_digen(dentry));
15438+ /* smp_mb(); */ /* atomic_set */
15439+
15440+ file->private_data = finfo;
15441+
15442+out:
15443+ return err;
15444+}
7f207e10 15445diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
eca34b5c 15446--- /usr/share/empty/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6
JR
15447+++ linux/fs/aufs/f_op.c 2021-05-02 20:15:14.673337458 +0200
15448@@ -0,0 +1,771 @@
cd7a4cd9 15449+// SPDX-License-Identifier: GPL-2.0
dece6358 15450+/*
d58c55f2 15451+ * Copyright (C) 2005-2020 Junjiro R. Okajima
dece6358
AM
15452+ *
15453+ * This program, aufs is free software; you can redistribute it and/or modify
15454+ * it under the terms of the GNU General Public License as published by
15455+ * the Free Software Foundation; either version 2 of the License, or
15456+ * (at your option) any later version.
15457+ *
15458+ * This program is distributed in the hope that it will be useful,
15459+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15460+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15461+ * GNU General Public License for more details.
15462+ *
15463+ * You should have received a copy of the GNU General Public License
523b37e3 15464+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
dece6358 15465+ */
1facf9fc 15466+
15467+/*
4a4d8108 15468+ * file and vm operations
1facf9fc 15469+ */
dece6358 15470+
86dc4139 15471+#include <linux/aio.h>
4a4d8108
AM
15472+#include <linux/fs_stack.h>
15473+#include <linux/mman.h>
4a4d8108 15474+#include <linux/security.h>
dece6358
AM
15475+#include "aufs.h"
15476+
b912730e 15477+int au_do_open_nondir(struct file *file, int flags, struct file *h_file)
1facf9fc 15478+{
4a4d8108
AM
15479+ int err;
15480+ aufs_bindex_t bindex;
8cdd5066 15481+ struct dentry *dentry, *h_dentry;
4a4d8108 15482+ struct au_finfo *finfo;
38d290e6 15483+ struct inode *h_inode;
4a4d8108
AM
15484+
15485+ FiMustWriteLock(file);
15486+
523b37e3 15487+ err = 0;
2000de60 15488+ dentry = file->f_path.dentry;
b912730e 15489+ AuDebugOn(IS_ERR_OR_NULL(dentry));
4a4d8108
AM
15490+ finfo = au_fi(file);
15491+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
2cbb1c4b 15492+ atomic_set(&finfo->fi_mmapped, 0);
5afbbe0d 15493+ bindex = au_dbtop(dentry);
8cdd5066
JR
15494+ if (!h_file) {
15495+ h_dentry = au_h_dptr(dentry, bindex);
15496+ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb);
15497+ if (unlikely(err))
15498+ goto out;
b912730e 15499+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0);
acd2b654
AM
15500+ if (IS_ERR(h_file)) {
15501+ err = PTR_ERR(h_file);
15502+ goto out;
15503+ }
8cdd5066
JR
15504+ } else {
15505+ h_dentry = h_file->f_path.dentry;
15506+ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb);
15507+ if (unlikely(err))
15508+ goto out;
acd2b654 15509+ /* br ref is already inc-ed */
8cdd5066 15510+ }
acd2b654
AM
15511+
15512+ if ((flags & __O_TMPFILE)
15513+ && !(flags & O_EXCL)) {
15514+ h_inode = file_inode(h_file);
15515+ spin_lock(&h_inode->i_lock);
15516+ h_inode->i_state |= I_LINKABLE;
15517+ spin_unlock(&h_inode->i_lock);
4a4d8108 15518+ }
acd2b654
AM
15519+ au_set_fbtop(file, bindex);
15520+ au_set_h_fptr(file, bindex, h_file);
15521+ au_update_figen(file);
15522+ /* todo: necessary? */
15523+ /* file->f_ra = h_file->f_ra; */
027c5e7a 15524+
8cdd5066 15525+out:
4a4d8108 15526+ return err;
1facf9fc 15527+}
15528+
4a4d8108
AM
15529+static int aufs_open_nondir(struct inode *inode __maybe_unused,
15530+ struct file *file)
1facf9fc 15531+{
4a4d8108 15532+ int err;
1308ab2a 15533+ struct super_block *sb;
b912730e
AM
15534+ struct au_do_open_args args = {
15535+ .open = au_do_open_nondir
15536+ };
1facf9fc 15537+
523b37e3
AM
15538+ AuDbg("%pD, f_flags 0x%x, f_mode 0x%x\n",
15539+ file, vfsub_file_flags(file), file->f_mode);
1facf9fc 15540+
2000de60 15541+ sb = file->f_path.dentry->d_sb;
4a4d8108 15542+ si_read_lock(sb, AuLock_FLUSH);
b912730e 15543+ err = au_do_open(file, &args);
4a4d8108
AM
15544+ si_read_unlock(sb);
15545+ return err;
15546+}
1facf9fc 15547+
4a4d8108
AM
15548+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
15549+{
15550+ struct au_finfo *finfo;
15551+ aufs_bindex_t bindex;
1facf9fc 15552+
4a4d8108 15553+ finfo = au_fi(file);
8b6a4947
AM
15554+ au_hbl_del(&finfo->fi_hlist,
15555+ &au_sbi(file->f_path.dentry->d_sb)->si_files);
4a4d8108 15556+ bindex = finfo->fi_btop;
b4510431 15557+ if (bindex >= 0)
4a4d8108 15558+ au_set_h_fptr(file, bindex, NULL);
7f207e10 15559+
1c60b727 15560+ au_finfo_fin(file);
4a4d8108 15561+ return 0;
1facf9fc 15562+}
15563+
4a4d8108
AM
15564+/* ---------------------------------------------------------------------- */
15565+
15566+static int au_do_flush_nondir(struct file *file, fl_owner_t id)
dece6358 15567+{
1308ab2a 15568+ int err;
4a4d8108
AM
15569+ struct file *h_file;
15570+
15571+ err = 0;
15572+ h_file = au_hf_top(file);
15573+ if (h_file)
15574+ err = vfsub_flush(h_file, id);
15575+ return err;
15576+}
15577+
15578+static int aufs_flush_nondir(struct file *file, fl_owner_t id)
15579+{
15580+ return au_do_flush(file, id, au_do_flush_nondir);
15581+}
15582+
15583+/* ---------------------------------------------------------------------- */
9dbd164d
AM
15584+/*
15585+ * read and write functions acquire [fdi]_rwsem once, but release before
15586+ * mmap_sem. This is because to stop a race condition between mmap(2).
acd2b654 15587+ * Releasing these aufs-rwsem should be safe, no branch-management (by keeping
9dbd164d
AM
15588+ * si_rwsem), no harmful copy-up should happen. Actually copy-up may happen in
15589+ * read functions after [fdi]_rwsem are released, but it should be harmless.
15590+ */
4a4d8108 15591+
b912730e 15592+/* Callers should call au_read_post() or fput() in the end */
521ced18 15593+struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc)
4a4d8108 15594+{
4a4d8108 15595+ struct file *h_file;
b912730e 15596+ int err;
1facf9fc 15597+
521ced18 15598+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0, lsc);
b912730e
AM
15599+ if (!err) {
15600+ di_read_unlock(file->f_path.dentry, AuLock_IR);
15601+ h_file = au_hf_top(file);
15602+ get_file(h_file);
15603+ if (!keep_fi)
15604+ fi_read_unlock(file);
15605+ } else
15606+ h_file = ERR_PTR(err);
15607+
15608+ return h_file;
15609+}
15610+
15611+static void au_read_post(struct inode *inode, struct file *h_file)
15612+{
15613+ /* update without lock, I don't think it a problem */
15614+ fsstack_copy_attr_atime(inode, file_inode(h_file));
15615+ fput(h_file);
15616+}
15617+
15618+struct au_write_pre {
521ced18
JR
15619+ /* input */
15620+ unsigned int lsc;
15621+
15622+ /* output */
b912730e 15623+ blkcnt_t blks;
5afbbe0d 15624+ aufs_bindex_t btop;
b912730e
AM
15625+};
15626+
15627+/*
15628+ * return with iinfo is write-locked
15629+ * callers should call au_write_post() or iinfo_write_unlock() + fput() in the
15630+ * end
15631+ */
15632+static struct file *au_write_pre(struct file *file, int do_ready,
15633+ struct au_write_pre *wpre)
15634+{
15635+ struct file *h_file;
15636+ struct dentry *dentry;
15637+ int err;
521ced18 15638+ unsigned int lsc;
b912730e
AM
15639+ struct au_pin pin;
15640+
521ced18
JR
15641+ lsc = 0;
15642+ if (wpre)
15643+ lsc = wpre->lsc;
15644+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, lsc);
b912730e 15645+ h_file = ERR_PTR(err);
dece6358
AM
15646+ if (unlikely(err))
15647+ goto out;
1facf9fc 15648+
b912730e
AM
15649+ dentry = file->f_path.dentry;
15650+ if (do_ready) {
15651+ err = au_ready_to_write(file, -1, &pin);
15652+ if (unlikely(err)) {
15653+ h_file = ERR_PTR(err);
15654+ di_write_unlock(dentry);
15655+ goto out_fi;
15656+ }
15657+ }
15658+
15659+ di_downgrade_lock(dentry, /*flags*/0);
15660+ if (wpre)
5afbbe0d 15661+ wpre->btop = au_fbtop(file);
4a4d8108 15662+ h_file = au_hf_top(file);
9dbd164d 15663+ get_file(h_file);
b912730e
AM
15664+ if (wpre)
15665+ wpre->blks = file_inode(h_file)->i_blocks;
15666+ if (do_ready)
15667+ au_unpin(&pin);
15668+ di_read_unlock(dentry, /*flags*/0);
15669+
15670+out_fi:
15671+ fi_write_unlock(file);
15672+out:
15673+ return h_file;
15674+}
15675+
15676+static void au_write_post(struct inode *inode, struct file *h_file,
15677+ struct au_write_pre *wpre, ssize_t written)
15678+{
15679+ struct inode *h_inode;
15680+
15681+ au_cpup_attr_timesizes(inode);
5afbbe0d 15682+ AuDebugOn(au_ibtop(inode) != wpre->btop);
b912730e
AM
15683+ h_inode = file_inode(h_file);
15684+ inode->i_mode = h_inode->i_mode;
15685+ ii_write_unlock(inode);
b912730e
AM
15686+ /* AuDbg("blks %llu, %llu\n", (u64)blks, (u64)h_inode->i_blocks); */
15687+ if (written > 0)
5afbbe0d 15688+ au_fhsm_wrote(inode->i_sb, wpre->btop,
b912730e 15689+ /*force*/h_inode->i_blocks > wpre->blks);
1c60b727 15690+ fput(h_file);
b912730e
AM
15691+}
15692+
e49829fe
JR
15693+/*
15694+ * todo: very ugly
15695+ * it locks both of i_mutex and si_rwsem for read in safe.
15696+ * if the plink maintenance mode continues forever (that is the problem),
15697+ * may loop forever.
15698+ */
15699+static void au_mtx_and_read_lock(struct inode *inode)
15700+{
15701+ int err;
15702+ struct super_block *sb = inode->i_sb;
15703+
15704+ while (1) {
febd17d6 15705+ inode_lock(inode);
e49829fe
JR
15706+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
15707+ if (!err)
15708+ break;
febd17d6 15709+ inode_unlock(inode);
e49829fe
JR
15710+ si_read_lock(sb, AuLock_NOPLMW);
15711+ si_read_unlock(sb);
15712+ }
15713+}
15714+
076b876e
AM
15715+static ssize_t au_do_iter(struct file *h_file, int rw, struct kiocb *kio,
15716+ struct iov_iter *iov_iter)
dece6358 15717+{
4a4d8108
AM
15718+ ssize_t err;
15719+ struct file *file;
076b876e 15720+ ssize_t (*iter)(struct kiocb *, struct iov_iter *);
1facf9fc 15721+
4a4d8108
AM
15722+ err = security_file_permission(h_file, rw);
15723+ if (unlikely(err))
15724+ goto out;
1facf9fc 15725+
43982f53 15726+ err = -ENOSYS; /* the branch doesn't have its ->(read|write)_iter() */
076b876e 15727+ iter = NULL;
5527c038 15728+ if (rw == MAY_READ)
076b876e 15729+ iter = h_file->f_op->read_iter;
5527c038 15730+ else if (rw == MAY_WRITE)
076b876e 15731+ iter = h_file->f_op->write_iter;
076b876e
AM
15732+
15733+ file = kio->ki_filp;
15734+ kio->ki_filp = h_file;
15735+ if (iter) {
2cbb1c4b 15736+ lockdep_off();
076b876e
AM
15737+ err = iter(kio, iov_iter);
15738+ lockdep_on();
4a4d8108
AM
15739+ } else
15740+ /* currently there is no such fs */
15741+ WARN_ON_ONCE(1);
076b876e 15742+ kio->ki_filp = file;
1facf9fc 15743+
4f0767ce 15744+out:
dece6358
AM
15745+ return err;
15746+}
1facf9fc 15747+
076b876e 15748+static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter)
1facf9fc 15749+{
4a4d8108
AM
15750+ ssize_t err;
15751+ struct file *file, *h_file;
b912730e 15752+ struct inode *inode;
dece6358 15753+ struct super_block *sb;
1facf9fc 15754+
4a4d8108 15755+ file = kio->ki_filp;
b912730e
AM
15756+ inode = file_inode(file);
15757+ sb = inode->i_sb;
e49829fe 15758+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 15759+
521ced18 15760+ h_file = au_read_pre(file, /*keep_fi*/1, /*lsc*/0);
b912730e
AM
15761+ err = PTR_ERR(h_file);
15762+ if (IS_ERR(h_file))
15763+ goto out;
9dbd164d 15764+
5afbbe0d
AM
15765+ if (au_test_loopback_kthread()) {
15766+ au_warn_loopback(h_file->f_path.dentry->d_sb);
15767+ if (file->f_mapping != h_file->f_mapping) {
15768+ file->f_mapping = h_file->f_mapping;
15769+ smp_mb(); /* unnecessary? */
15770+ }
15771+ }
15772+ fi_read_unlock(file);
15773+
076b876e 15774+ err = au_do_iter(h_file, MAY_READ, kio, iov_iter);
4a4d8108
AM
15775+ /* todo: necessary? */
15776+ /* file->f_ra = h_file->f_ra; */
b912730e 15777+ au_read_post(inode, h_file);
1facf9fc 15778+
4f0767ce 15779+out:
4a4d8108 15780+ si_read_unlock(sb);
1308ab2a 15781+ return err;
15782+}
1facf9fc 15783+
076b876e 15784+static ssize_t aufs_write_iter(struct kiocb *kio, struct iov_iter *iov_iter)
1308ab2a 15785+{
4a4d8108 15786+ ssize_t err;
b912730e
AM
15787+ struct au_write_pre wpre;
15788+ struct inode *inode;
4a4d8108 15789+ struct file *file, *h_file;
1308ab2a 15790+
4a4d8108 15791+ file = kio->ki_filp;
b912730e 15792+ inode = file_inode(file);
e49829fe
JR
15793+ au_mtx_and_read_lock(inode);
15794+
521ced18 15795+ wpre.lsc = 0;
b912730e
AM
15796+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
15797+ err = PTR_ERR(h_file);
15798+ if (IS_ERR(h_file))
9dbd164d 15799+ goto out;
9dbd164d 15800+
076b876e 15801+ err = au_do_iter(h_file, MAY_WRITE, kio, iov_iter);
b912730e 15802+ au_write_post(inode, h_file, &wpre, err);
1facf9fc 15803+
4f0767ce 15804+out:
b912730e 15805+ si_read_unlock(inode->i_sb);
febd17d6 15806+ inode_unlock(inode);
dece6358 15807+ return err;
1facf9fc 15808+}
15809+
0b2a12c6
JR
15810+/*
15811+ * We may be able to remove aufs_splice_{read,write}() since almost all FSes
15812+ * don't have their own .splice_{read,write} implimentations, and they use
15813+ * generic_file_splice_read() and iter_file_splice_write() who can act like the
15814+ * simple converters to f_op->iter_read() and ->iter_write().
15815+ * But we keep our own implementations because some non-mainlined FSes may have
15816+ * their own .splice_{read,write} implimentations and aufs doesn't want to take
15817+ * away an opportunity to co-work with aufs from them.
15818+ */
4a4d8108
AM
15819+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
15820+ struct pipe_inode_info *pipe, size_t len,
15821+ unsigned int flags)
1facf9fc 15822+{
4a4d8108
AM
15823+ ssize_t err;
15824+ struct file *h_file;
b912730e 15825+ struct inode *inode;
dece6358 15826+ struct super_block *sb;
1facf9fc 15827+
b912730e
AM
15828+ inode = file_inode(file);
15829+ sb = inode->i_sb;
e49829fe 15830+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
b912730e 15831+
521ced18 15832+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
b912730e
AM
15833+ err = PTR_ERR(h_file);
15834+ if (IS_ERR(h_file))
dece6358 15835+ goto out;
1facf9fc 15836+
4a4d8108 15837+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
acd2b654 15838+ /* todo: necessary? */
4a4d8108 15839+ /* file->f_ra = h_file->f_ra; */
b912730e 15840+ au_read_post(inode, h_file);
1facf9fc 15841+
4f0767ce 15842+out:
4a4d8108 15843+ si_read_unlock(sb);
dece6358 15844+ return err;
1facf9fc 15845+}
15846+
4a4d8108
AM
15847+static ssize_t
15848+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
15849+ size_t len, unsigned int flags)
1facf9fc 15850+{
4a4d8108 15851+ ssize_t err;
b912730e
AM
15852+ struct au_write_pre wpre;
15853+ struct inode *inode;
076b876e 15854+ struct file *h_file;
1facf9fc 15855+
b912730e 15856+ inode = file_inode(file);
e49829fe 15857+ au_mtx_and_read_lock(inode);
9dbd164d 15858+
521ced18 15859+ wpre.lsc = 0;
b912730e
AM
15860+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
15861+ err = PTR_ERR(h_file);
15862+ if (IS_ERR(h_file))
9dbd164d 15863+ goto out;
9dbd164d 15864+
4a4d8108 15865+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
b912730e 15866+ au_write_post(inode, h_file, &wpre, err);
1facf9fc 15867+
4f0767ce 15868+out:
b912730e 15869+ si_read_unlock(inode->i_sb);
febd17d6 15870+ inode_unlock(inode);
4a4d8108
AM
15871+ return err;
15872+}
1facf9fc 15873+
38d290e6
JR
15874+static long aufs_fallocate(struct file *file, int mode, loff_t offset,
15875+ loff_t len)
15876+{
15877+ long err;
b912730e 15878+ struct au_write_pre wpre;
38d290e6
JR
15879+ struct inode *inode;
15880+ struct file *h_file;
15881+
b912730e 15882+ inode = file_inode(file);
38d290e6
JR
15883+ au_mtx_and_read_lock(inode);
15884+
521ced18 15885+ wpre.lsc = 0;
b912730e
AM
15886+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
15887+ err = PTR_ERR(h_file);
15888+ if (IS_ERR(h_file))
38d290e6 15889+ goto out;
38d290e6
JR
15890+
15891+ lockdep_off();
03673fb0 15892+ err = vfs_fallocate(h_file, mode, offset, len);
38d290e6 15893+ lockdep_on();
b912730e 15894+ au_write_post(inode, h_file, &wpre, /*written*/1);
38d290e6
JR
15895+
15896+out:
b912730e 15897+ si_read_unlock(inode->i_sb);
febd17d6 15898+ inode_unlock(inode);
38d290e6
JR
15899+ return err;
15900+}
15901+
521ced18
JR
15902+static ssize_t aufs_copy_file_range(struct file *src, loff_t src_pos,
15903+ struct file *dst, loff_t dst_pos,
15904+ size_t len, unsigned int flags)
15905+{
15906+ ssize_t err;
15907+ struct au_write_pre wpre;
15908+ enum { SRC, DST };
15909+ struct {
15910+ struct inode *inode;
15911+ struct file *h_file;
15912+ struct super_block *h_sb;
15913+ } a[2];
15914+#define a_src a[SRC]
15915+#define a_dst a[DST]
15916+
15917+ err = -EINVAL;
15918+ a_src.inode = file_inode(src);
15919+ if (unlikely(!S_ISREG(a_src.inode->i_mode)))
15920+ goto out;
15921+ a_dst.inode = file_inode(dst);
15922+ if (unlikely(!S_ISREG(a_dst.inode->i_mode)))
15923+ goto out;
15924+
15925+ au_mtx_and_read_lock(a_dst.inode);
15926+ /*
15927+ * in order to match the order in di_write_lock2_{child,parent}(),
acd2b654 15928+ * use f_path.dentry for this comparison.
521ced18
JR
15929+ */
15930+ if (src->f_path.dentry < dst->f_path.dentry) {
15931+ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_1);
15932+ err = PTR_ERR(a_src.h_file);
15933+ if (IS_ERR(a_src.h_file))
15934+ goto out_si;
15935+
15936+ wpre.lsc = AuLsc_FI_2;
15937+ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre);
15938+ err = PTR_ERR(a_dst.h_file);
15939+ if (IS_ERR(a_dst.h_file)) {
15940+ au_read_post(a_src.inode, a_src.h_file);
15941+ goto out_si;
15942+ }
15943+ } else {
15944+ wpre.lsc = AuLsc_FI_1;
15945+ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre);
15946+ err = PTR_ERR(a_dst.h_file);
15947+ if (IS_ERR(a_dst.h_file))
15948+ goto out_si;
15949+
15950+ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_2);
15951+ err = PTR_ERR(a_src.h_file);
15952+ if (IS_ERR(a_src.h_file)) {
15953+ au_write_post(a_dst.inode, a_dst.h_file, &wpre,
15954+ /*written*/0);
15955+ goto out_si;
15956+ }
15957+ }
15958+
15959+ err = -EXDEV;
15960+ a_src.h_sb = file_inode(a_src.h_file)->i_sb;
15961+ a_dst.h_sb = file_inode(a_dst.h_file)->i_sb;
15962+ if (unlikely(a_src.h_sb != a_dst.h_sb)) {
15963+ AuDbgFile(src);
15964+ AuDbgFile(dst);
15965+ goto out_file;
15966+ }
15967+
15968+ err = vfsub_copy_file_range(a_src.h_file, src_pos, a_dst.h_file,
15969+ dst_pos, len, flags);
15970+
15971+out_file:
15972+ au_write_post(a_dst.inode, a_dst.h_file, &wpre, err);
15973+ fi_read_unlock(src);
15974+ au_read_post(a_src.inode, a_src.h_file);
15975+out_si:
15976+ si_read_unlock(a_dst.inode->i_sb);
15977+ inode_unlock(a_dst.inode);
15978+out:
15979+ return err;
15980+#undef a_src
15981+#undef a_dst
15982+}
15983+
4a4d8108
AM
15984+/* ---------------------------------------------------------------------- */
15985+
9dbd164d
AM
15986+/*
15987+ * The locking order around current->mmap_sem.
15988+ * - in most and regular cases
15989+ * file I/O syscall -- aufs_read() or something
15990+ * -- si_rwsem for read -- mmap_sem
15991+ * (Note that [fdi]i_rwsem are released before mmap_sem).
15992+ * - in mmap case
15993+ * mmap(2) -- mmap_sem -- aufs_mmap() -- si_rwsem for read -- [fdi]i_rwsem
acd2b654
AM
15994+ * This AB-BA order is definitely bad, but is not a problem since "si_rwsem for
15995+ * read" allows multiple processes to acquire it and [fdi]i_rwsem are not held
15996+ * in file I/O. Aufs needs to stop lockdep in aufs_mmap() though.
9dbd164d
AM
15997+ * It means that when aufs acquires si_rwsem for write, the process should never
15998+ * acquire mmap_sem.
15999+ *
392086de 16000+ * Actually aufs_iterate() holds [fdi]i_rwsem before mmap_sem, but this is not a
9dbd164d
AM
16001+ * problem either since any directory is not able to be mmap-ed.
16002+ * The similar scenario is applied to aufs_readlink() too.
16003+ */
16004+
38d290e6 16005+#if 0 /* stop calling security_file_mmap() */
2dfbb274
AM
16006+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
16007+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b)
16008+
16009+static unsigned long au_arch_prot_conv(unsigned long flags)
16010+{
16011+ /* currently ppc64 only */
16012+#ifdef CONFIG_PPC64
16013+ /* cf. linux/arch/powerpc/include/asm/mman.h */
16014+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
16015+ return AuConv_VM_PROT(flags, SAO);
16016+#else
16017+ AuDebugOn(arch_calc_vm_prot_bits(-1));
16018+ return 0;
16019+#endif
16020+}
16021+
16022+static unsigned long au_prot_conv(unsigned long flags)
16023+{
16024+ return AuConv_VM_PROT(flags, READ)
16025+ | AuConv_VM_PROT(flags, WRITE)
16026+ | AuConv_VM_PROT(flags, EXEC)
16027+ | au_arch_prot_conv(flags);
16028+}
16029+
16030+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
16031+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b)
16032+
16033+static unsigned long au_flag_conv(unsigned long flags)
16034+{
16035+ return AuConv_VM_MAP(flags, GROWSDOWN)
16036+ | AuConv_VM_MAP(flags, DENYWRITE)
2dfbb274
AM
16037+ | AuConv_VM_MAP(flags, LOCKED);
16038+}
38d290e6 16039+#endif
2dfbb274 16040+
9dbd164d 16041+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
dece6358 16042+{
4a4d8108 16043+ int err;
4a4d8108 16044+ const unsigned char wlock
9dbd164d 16045+ = (file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
4a4d8108 16046+ struct super_block *sb;
9dbd164d 16047+ struct file *h_file;
b912730e 16048+ struct inode *inode;
9dbd164d
AM
16049+
16050+ AuDbgVmRegion(file, vma);
1308ab2a 16051+
b912730e
AM
16052+ inode = file_inode(file);
16053+ sb = inode->i_sb;
9dbd164d 16054+ lockdep_off();
e49829fe 16055+ si_read_lock(sb, AuLock_NOPLMW);
4a4d8108 16056+
b912730e 16057+ h_file = au_write_pre(file, wlock, /*wpre*/NULL);
9dbd164d 16058+ lockdep_on();
b912730e
AM
16059+ err = PTR_ERR(h_file);
16060+ if (IS_ERR(h_file))
16061+ goto out;
1308ab2a 16062+
b912730e
AM
16063+ err = 0;
16064+ au_set_mmapped(file);
9dbd164d 16065+ au_vm_file_reset(vma, h_file);
38d290e6
JR
16066+ /*
16067+ * we cannot call security_mmap_file() here since it may acquire
16068+ * mmap_sem or i_mutex.
16069+ *
16070+ * err = security_mmap_file(h_file, au_prot_conv(vma->vm_flags),
16071+ * au_flag_conv(vma->vm_flags));
16072+ */
9dbd164d 16073+ if (!err)
521ced18 16074+ err = call_mmap(h_file, vma);
b912730e
AM
16075+ if (!err) {
16076+ au_vm_prfile_set(vma, file);
16077+ fsstack_copy_attr_atime(inode, file_inode(h_file));
16078+ goto out_fput; /* success */
16079+ }
2cbb1c4b
JR
16080+ au_unset_mmapped(file);
16081+ au_vm_file_reset(vma, file);
b912730e 16082+
2cbb1c4b 16083+out_fput:
9dbd164d 16084+ lockdep_off();
b912730e
AM
16085+ ii_write_unlock(inode);
16086+ lockdep_on();
16087+ fput(h_file);
4f0767ce 16088+out:
b912730e 16089+ lockdep_off();
9dbd164d
AM
16090+ si_read_unlock(sb);
16091+ lockdep_on();
16092+ AuTraceErr(err);
4a4d8108
AM
16093+ return err;
16094+}
16095+
16096+/* ---------------------------------------------------------------------- */
16097+
1e00d052
AM
16098+static int aufs_fsync_nondir(struct file *file, loff_t start, loff_t end,
16099+ int datasync)
4a4d8108
AM
16100+{
16101+ int err;
b912730e 16102+ struct au_write_pre wpre;
4a4d8108
AM
16103+ struct inode *inode;
16104+ struct file *h_file;
4a4d8108
AM
16105+
16106+ err = 0; /* -EBADF; */ /* posix? */
16107+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
b912730e 16108+ goto out;
4a4d8108 16109+
b912730e
AM
16110+ inode = file_inode(file);
16111+ au_mtx_and_read_lock(inode);
16112+
521ced18 16113+ wpre.lsc = 0;
b912730e
AM
16114+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
16115+ err = PTR_ERR(h_file);
16116+ if (IS_ERR(h_file))
4a4d8108 16117+ goto out_unlock;
4a4d8108 16118+
53392da6 16119+ err = vfsub_fsync(h_file, &h_file->f_path, datasync);
b912730e 16120+ au_write_post(inode, h_file, &wpre, /*written*/0);
4a4d8108 16121+
4f0767ce 16122+out_unlock:
b912730e 16123+ si_read_unlock(inode->i_sb);
febd17d6 16124+ inode_unlock(inode);
b912730e 16125+out:
4a4d8108 16126+ return err;
dece6358
AM
16127+}
16128+
4a4d8108 16129+static int aufs_fasync(int fd, struct file *file, int flag)
dece6358 16130+{
4a4d8108
AM
16131+ int err;
16132+ struct file *h_file;
4a4d8108 16133+ struct super_block *sb;
1308ab2a 16134+
b912730e 16135+ sb = file->f_path.dentry->d_sb;
e49829fe 16136+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
b912730e 16137+
521ced18 16138+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
b912730e
AM
16139+ err = PTR_ERR(h_file);
16140+ if (IS_ERR(h_file))
4a4d8108
AM
16141+ goto out;
16142+
523b37e3 16143+ if (h_file->f_op->fasync)
4a4d8108 16144+ err = h_file->f_op->fasync(fd, h_file, flag);
b912730e 16145+ fput(h_file); /* instead of au_read_post() */
1308ab2a 16146+
4f0767ce 16147+out:
4a4d8108 16148+ si_read_unlock(sb);
1308ab2a 16149+ return err;
dece6358 16150+}
4a4d8108 16151+
febd17d6
JR
16152+static int aufs_setfl(struct file *file, unsigned long arg)
16153+{
16154+ int err;
16155+ struct file *h_file;
16156+ struct super_block *sb;
16157+
16158+ sb = file->f_path.dentry->d_sb;
16159+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
16160+
521ced18 16161+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
febd17d6
JR
16162+ err = PTR_ERR(h_file);
16163+ if (IS_ERR(h_file))
16164+ goto out;
16165+
1c60b727
AM
16166+ /* stop calling h_file->fasync */
16167+ arg |= vfsub_file_flags(file) & FASYNC;
febd17d6
JR
16168+ err = setfl(/*unused fd*/-1, h_file, arg);
16169+ fput(h_file); /* instead of au_read_post() */
16170+
16171+out:
16172+ si_read_unlock(sb);
16173+ return err;
16174+}
16175+
4a4d8108
AM
16176+/* ---------------------------------------------------------------------- */
16177+
16178+/* no one supports this operation, currently */
43982f53 16179+#if 0 /* reserved for future use */
4a4d8108 16180+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
2000de60 16181+ size_t len, loff_t *pos, int more)
4a4d8108
AM
16182+{
16183+}
16184+#endif
16185+
16186+/* ---------------------------------------------------------------------- */
16187+
16188+const struct file_operations aufs_file_fop = {
16189+ .owner = THIS_MODULE,
2cbb1c4b 16190+
027c5e7a 16191+ .llseek = default_llseek,
4a4d8108 16192+
076b876e
AM
16193+ .read_iter = aufs_read_iter,
16194+ .write_iter = aufs_write_iter,
16195+
4a4d8108
AM
16196+#ifdef CONFIG_AUFS_POLL
16197+ .poll = aufs_poll,
16198+#endif
16199+ .unlocked_ioctl = aufs_ioctl_nondir,
b752ccd1 16200+#ifdef CONFIG_COMPAT
c2b27bf2 16201+ .compat_ioctl = aufs_compat_ioctl_nondir,
b752ccd1 16202+#endif
4a4d8108
AM
16203+ .mmap = aufs_mmap,
16204+ .open = aufs_open_nondir,
16205+ .flush = aufs_flush_nondir,
16206+ .release = aufs_release_nondir,
16207+ .fsync = aufs_fsync_nondir,
4a4d8108
AM
16208+ .fasync = aufs_fasync,
16209+ /* .sendpage = aufs_sendpage, */
febd17d6 16210+ .setfl = aufs_setfl,
4a4d8108
AM
16211+ .splice_write = aufs_splice_write,
16212+ .splice_read = aufs_splice_read,
43982f53 16213+#if 0 /* reserved for future use */
4a4d8108 16214+ .aio_splice_write = aufs_aio_splice_write,
38d290e6 16215+ .aio_splice_read = aufs_aio_splice_read,
4a4d8108 16216+#endif
521ced18
JR
16217+ .fallocate = aufs_fallocate,
16218+ .copy_file_range = aufs_copy_file_range
4a4d8108 16219+};
7f207e10 16220diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
eca34b5c 16221--- /usr/share/empty/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 16222+++ linux/fs/aufs/fstype.h 2021-05-02 20:15:14.673337458 +0200
062440b3
AM
16223@@ -0,0 +1,401 @@
16224+/* SPDX-License-Identifier: GPL-2.0 */
4a4d8108 16225+/*
d58c55f2 16226+ * Copyright (C) 2005-2020 Junjiro R. Okajima
4a4d8108
AM
16227+ *
16228+ * This program, aufs is free software; you can redistribute it and/or modify
16229+ * it under the terms of the GNU General Public License as published by
16230+ * the Free Software Foundation; either version 2 of the License, or
16231+ * (at your option) any later version.
16232+ *
16233+ * This program is distributed in the hope that it will be useful,
16234+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16235+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16236+ * GNU General Public License for more details.
16237+ *
16238+ * You should have received a copy of the GNU General Public License
523b37e3 16239+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
16240+ */
16241+
16242+/*
16243+ * judging filesystem type
16244+ */
16245+
16246+#ifndef __AUFS_FSTYPE_H__
16247+#define __AUFS_FSTYPE_H__
16248+
16249+#ifdef __KERNEL__
16250+
16251+#include <linux/fs.h>
16252+#include <linux/magic.h>
b912730e 16253+#include <linux/nfs_fs.h>
b95c5147 16254+#include <linux/romfs_fs.h>
4a4d8108
AM
16255+
16256+static inline int au_test_aufs(struct super_block *sb)
16257+{
16258+ return sb->s_magic == AUFS_SUPER_MAGIC;
16259+}
16260+
16261+static inline const char *au_sbtype(struct super_block *sb)
16262+{
16263+ return sb->s_type->name;
16264+}
1308ab2a 16265+
16266+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
16267+{
f0c0a007 16268+#if IS_ENABLED(CONFIG_ISO9660_FS)
2000de60 16269+ return sb->s_magic == ISOFS_SUPER_MAGIC;
dece6358
AM
16270+#else
16271+ return 0;
16272+#endif
16273+}
16274+
1308ab2a 16275+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
dece6358 16276+{
f0c0a007 16277+#if IS_ENABLED(CONFIG_ROMFS_FS)
2000de60 16278+ return sb->s_magic == ROMFS_MAGIC;
dece6358
AM
16279+#else
16280+ return 0;
16281+#endif
16282+}
16283+
1308ab2a 16284+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
dece6358 16285+{
f0c0a007 16286+#if IS_ENABLED(CONFIG_CRAMFS)
1308ab2a 16287+ return sb->s_magic == CRAMFS_MAGIC;
16288+#endif
16289+ return 0;
16290+}
16291+
16292+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
16293+{
f0c0a007 16294+#if IS_ENABLED(CONFIG_NFS_FS)
1308ab2a 16295+ return sb->s_magic == NFS_SUPER_MAGIC;
dece6358
AM
16296+#else
16297+ return 0;
16298+#endif
16299+}
16300+
1308ab2a 16301+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
dece6358 16302+{
f0c0a007 16303+#if IS_ENABLED(CONFIG_FUSE_FS)
1308ab2a 16304+ return sb->s_magic == FUSE_SUPER_MAGIC;
dece6358
AM
16305+#else
16306+ return 0;
16307+#endif
16308+}
16309+
1308ab2a 16310+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
dece6358 16311+{
f0c0a007 16312+#if IS_ENABLED(CONFIG_XFS_FS)
1308ab2a 16313+ return sb->s_magic == XFS_SB_MAGIC;
dece6358
AM
16314+#else
16315+ return 0;
16316+#endif
16317+}
16318+
1308ab2a 16319+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
dece6358 16320+{
1308ab2a 16321+#ifdef CONFIG_TMPFS
16322+ return sb->s_magic == TMPFS_MAGIC;
16323+#else
16324+ return 0;
dece6358 16325+#endif
dece6358
AM
16326+}
16327+
1308ab2a 16328+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
1facf9fc 16329+{
f0c0a007 16330+#if IS_ENABLED(CONFIG_ECRYPT_FS)
1308ab2a 16331+ return !strcmp(au_sbtype(sb), "ecryptfs");
16332+#else
16333+ return 0;
16334+#endif
1facf9fc 16335+}
16336+
1308ab2a 16337+static inline int au_test_ramfs(struct super_block *sb)
16338+{
16339+ return sb->s_magic == RAMFS_MAGIC;
16340+}
16341+
16342+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
16343+{
f0c0a007 16344+#if IS_ENABLED(CONFIG_UBIFS_FS)
1308ab2a 16345+ return sb->s_magic == UBIFS_SUPER_MAGIC;
16346+#else
16347+ return 0;
16348+#endif
16349+}
16350+
16351+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
16352+{
16353+#ifdef CONFIG_PROC_FS
16354+ return sb->s_magic == PROC_SUPER_MAGIC;
16355+#else
16356+ return 0;
16357+#endif
16358+}
16359+
16360+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
16361+{
16362+#ifdef CONFIG_SYSFS
16363+ return sb->s_magic == SYSFS_MAGIC;
16364+#else
16365+ return 0;
16366+#endif
16367+}
16368+
16369+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
16370+{
f0c0a007 16371+#if IS_ENABLED(CONFIG_CONFIGFS_FS)
1308ab2a 16372+ return sb->s_magic == CONFIGFS_MAGIC;
16373+#else
16374+ return 0;
16375+#endif
16376+}
16377+
16378+static inline int au_test_minix(struct super_block *sb __maybe_unused)
16379+{
f0c0a007 16380+#if IS_ENABLED(CONFIG_MINIX_FS)
1308ab2a 16381+ return sb->s_magic == MINIX3_SUPER_MAGIC
16382+ || sb->s_magic == MINIX2_SUPER_MAGIC
16383+ || sb->s_magic == MINIX2_SUPER_MAGIC2
16384+ || sb->s_magic == MINIX_SUPER_MAGIC
16385+ || sb->s_magic == MINIX_SUPER_MAGIC2;
16386+#else
16387+ return 0;
16388+#endif
16389+}
16390+
1308ab2a 16391+static inline int au_test_fat(struct super_block *sb __maybe_unused)
16392+{
f0c0a007 16393+#if IS_ENABLED(CONFIG_FAT_FS)
1308ab2a 16394+ return sb->s_magic == MSDOS_SUPER_MAGIC;
16395+#else
16396+ return 0;
16397+#endif
16398+}
16399+
16400+static inline int au_test_msdos(struct super_block *sb)
16401+{
16402+ return au_test_fat(sb);
16403+}
16404+
16405+static inline int au_test_vfat(struct super_block *sb)
16406+{
16407+ return au_test_fat(sb);
16408+}
16409+
16410+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
16411+{
16412+#ifdef CONFIG_SECURITYFS
16413+ return sb->s_magic == SECURITYFS_MAGIC;
16414+#else
16415+ return 0;
16416+#endif
16417+}
16418+
16419+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
16420+{
f0c0a007 16421+#if IS_ENABLED(CONFIG_SQUASHFS)
1308ab2a 16422+ return sb->s_magic == SQUASHFS_MAGIC;
16423+#else
16424+ return 0;
16425+#endif
16426+}
16427+
16428+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
16429+{
f0c0a007 16430+#if IS_ENABLED(CONFIG_BTRFS_FS)
1308ab2a 16431+ return sb->s_magic == BTRFS_SUPER_MAGIC;
16432+#else
16433+ return 0;
16434+#endif
16435+}
16436+
16437+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
16438+{
f0c0a007 16439+#if IS_ENABLED(CONFIG_XENFS)
1308ab2a 16440+ return sb->s_magic == XENFS_SUPER_MAGIC;
16441+#else
16442+ return 0;
16443+#endif
16444+}
16445+
16446+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
16447+{
16448+#ifdef CONFIG_DEBUG_FS
16449+ return sb->s_magic == DEBUGFS_MAGIC;
16450+#else
16451+ return 0;
16452+#endif
16453+}
16454+
16455+static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
16456+{
f0c0a007 16457+#if IS_ENABLED(CONFIG_NILFS)
1308ab2a 16458+ return sb->s_magic == NILFS_SUPER_MAGIC;
16459+#else
16460+ return 0;
16461+#endif
16462+}
16463+
4a4d8108
AM
16464+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
16465+{
f0c0a007 16466+#if IS_ENABLED(CONFIG_HFSPLUS_FS)
4a4d8108
AM
16467+ return sb->s_magic == HFSPLUS_SUPER_MAGIC;
16468+#else
16469+ return 0;
16470+#endif
16471+}
16472+
1308ab2a 16473+/* ---------------------------------------------------------------------- */
16474+/*
16475+ * they can't be an aufs branch.
16476+ */
16477+static inline int au_test_fs_unsuppoted(struct super_block *sb)
16478+{
16479+ return
16480+#ifndef CONFIG_AUFS_BR_RAMFS
16481+ au_test_ramfs(sb) ||
16482+#endif
16483+ au_test_procfs(sb)
16484+ || au_test_sysfs(sb)
16485+ || au_test_configfs(sb)
16486+ || au_test_debugfs(sb)
16487+ || au_test_securityfs(sb)
16488+ || au_test_xenfs(sb)
16489+ || au_test_ecryptfs(sb)
16490+ /* || !strcmp(au_sbtype(sb), "unionfs") */
16491+ || au_test_aufs(sb); /* will be supported in next version */
16492+}
16493+
1308ab2a 16494+static inline int au_test_fs_remote(struct super_block *sb)
16495+{
16496+ return !au_test_tmpfs(sb)
16497+#ifdef CONFIG_AUFS_BR_RAMFS
16498+ && !au_test_ramfs(sb)
16499+#endif
16500+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
16501+}
16502+
16503+/* ---------------------------------------------------------------------- */
16504+
16505+/*
16506+ * Note: these functions (below) are created after reading ->getattr() in all
16507+ * filesystems under linux/fs. it means we have to do so in every update...
16508+ */
16509+
16510+/*
16511+ * some filesystems require getattr to refresh the inode attributes before
16512+ * referencing.
16513+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
16514+ * and leave the work for d_revalidate()
16515+ */
16516+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
16517+{
16518+ return au_test_nfs(sb)
16519+ || au_test_fuse(sb)
1308ab2a 16520+ /* || au_test_btrfs(sb) */ /* untested */
1308ab2a 16521+ ;
16522+}
16523+
16524+/*
16525+ * filesystems which don't maintain i_size or i_blocks.
16526+ */
16527+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
16528+{
16529+ return au_test_xfs(sb)
4a4d8108
AM
16530+ || au_test_btrfs(sb)
16531+ || au_test_ubifs(sb)
16532+ || au_test_hfsplus(sb) /* maintained, but incorrect */
1308ab2a 16533+ /* || au_test_minix(sb) */ /* untested */
16534+ ;
16535+}
16536+
16537+/*
16538+ * filesystems which don't store the correct value in some of their inode
16539+ * attributes.
16540+ */
16541+static inline int au_test_fs_bad_iattr(struct super_block *sb)
16542+{
16543+ return au_test_fs_bad_iattr_size(sb)
1308ab2a 16544+ || au_test_fat(sb)
16545+ || au_test_msdos(sb)
16546+ || au_test_vfat(sb);
1facf9fc 16547+}
16548+
16549+/* they don't check i_nlink in link(2) */
16550+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
16551+{
16552+ return au_test_tmpfs(sb)
16553+#ifdef CONFIG_AUFS_BR_RAMFS
16554+ || au_test_ramfs(sb)
16555+#endif
4a4d8108 16556+ || au_test_ubifs(sb)
4a4d8108 16557+ || au_test_hfsplus(sb);
1facf9fc 16558+}
16559+
16560+/*
16561+ * filesystems which sets S_NOATIME and S_NOCMTIME.
16562+ */
16563+static inline int au_test_fs_notime(struct super_block *sb)
16564+{
16565+ return au_test_nfs(sb)
16566+ || au_test_fuse(sb)
dece6358 16567+ || au_test_ubifs(sb)
1facf9fc 16568+ ;
16569+}
16570+
1facf9fc 16571+/* temporary support for i#1 in cramfs */
16572+static inline int au_test_fs_unique_ino(struct inode *inode)
16573+{
16574+ if (au_test_cramfs(inode->i_sb))
16575+ return inode->i_ino != 1;
16576+ return 1;
16577+}
16578+
16579+/* ---------------------------------------------------------------------- */
16580+
16581+/*
16582+ * the filesystem where the xino files placed must support i/o after unlink and
16583+ * maintain i_size and i_blocks.
16584+ */
16585+static inline int au_test_fs_bad_xino(struct super_block *sb)
16586+{
16587+ return au_test_fs_remote(sb)
16588+ || au_test_fs_bad_iattr_size(sb)
1facf9fc 16589+ /* don't want unnecessary work for xino */
16590+ || au_test_aufs(sb)
1308ab2a 16591+ || au_test_ecryptfs(sb)
16592+ || au_test_nilfs(sb);
1facf9fc 16593+}
16594+
16595+static inline int au_test_fs_trunc_xino(struct super_block *sb)
16596+{
16597+ return au_test_tmpfs(sb)
16598+ || au_test_ramfs(sb);
16599+}
16600+
16601+/*
16602+ * test if the @sb is real-readonly.
16603+ */
16604+static inline int au_test_fs_rr(struct super_block *sb)
16605+{
16606+ return au_test_squashfs(sb)
16607+ || au_test_iso9660(sb)
16608+ || au_test_cramfs(sb)
16609+ || au_test_romfs(sb);
16610+}
16611+
b912730e
AM
16612+/*
16613+ * test if the @inode is nfs with 'noacl' option
2121bcd9 16614+ * NFS always sets SB_POSIXACL regardless its mount option 'noacl.'
b912730e
AM
16615+ */
16616+static inline int au_test_nfs_noacl(struct inode *inode)
16617+{
16618+ return au_test_nfs(inode->i_sb)
16619+ /* && IS_POSIXACL(inode) */
16620+ && !nfs_server_capable(inode, NFS_CAP_ACLS);
16621+}
16622+
1facf9fc 16623+#endif /* __KERNEL__ */
16624+#endif /* __AUFS_FSTYPE_H__ */
8b6a4947 16625diff -urN /usr/share/empty/fs/aufs/hbl.h linux/fs/aufs/hbl.h
eca34b5c 16626--- /usr/share/empty/fs/aufs/hbl.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 16627+++ linux/fs/aufs/hbl.h 2021-05-02 20:15:14.673337458 +0200
062440b3
AM
16628@@ -0,0 +1,65 @@
16629+/* SPDX-License-Identifier: GPL-2.0 */
8b6a4947 16630+/*
d58c55f2 16631+ * Copyright (C) 2017-2020 Junjiro R. Okajima
8b6a4947
AM
16632+ *
16633+ * This program, aufs is free software; you can redistribute it and/or modify
16634+ * it under the terms of the GNU General Public License as published by
16635+ * the Free Software Foundation; either version 2 of the License, or
16636+ * (at your option) any later version.
16637+ *
16638+ * This program is distributed in the hope that it will be useful,
16639+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16640+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16641+ * GNU General Public License for more details.
16642+ *
16643+ * You should have received a copy of the GNU General Public License
16644+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
16645+ */
16646+
16647+/*
16648+ * helpers for hlist_bl.h
16649+ */
16650+
16651+#ifndef __AUFS_HBL_H__
16652+#define __AUFS_HBL_H__
16653+
16654+#ifdef __KERNEL__
16655+
16656+#include <linux/list_bl.h>
16657+
16658+static inline void au_hbl_add(struct hlist_bl_node *node,
16659+ struct hlist_bl_head *hbl)
16660+{
16661+ hlist_bl_lock(hbl);
16662+ hlist_bl_add_head(node, hbl);
16663+ hlist_bl_unlock(hbl);
16664+}
16665+
16666+static inline void au_hbl_del(struct hlist_bl_node *node,
16667+ struct hlist_bl_head *hbl)
16668+{
16669+ hlist_bl_lock(hbl);
16670+ hlist_bl_del(node);
16671+ hlist_bl_unlock(hbl);
16672+}
16673+
16674+#define au_hbl_for_each(pos, head) \
16675+ for (pos = hlist_bl_first(head); \
16676+ pos; \
16677+ pos = pos->next)
16678+
16679+static inline unsigned long au_hbl_count(struct hlist_bl_head *hbl)
16680+{
16681+ unsigned long cnt;
16682+ struct hlist_bl_node *pos;
16683+
16684+ cnt = 0;
16685+ hlist_bl_lock(hbl);
16686+ au_hbl_for_each(pos, hbl)
16687+ cnt++;
16688+ hlist_bl_unlock(hbl);
16689+ return cnt;
16690+}
16691+
16692+#endif /* __KERNEL__ */
16693+#endif /* __AUFS_HBL_H__ */
7f207e10 16694diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
eca34b5c 16695--- /usr/share/empty/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 16696+++ linux/fs/aufs/hfsnotify.c 2021-05-02 20:15:14.673337458 +0200
fbc438ed 16697@@ -0,0 +1,288 @@
cd7a4cd9 16698+// SPDX-License-Identifier: GPL-2.0
1facf9fc 16699+/*
d58c55f2 16700+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 16701+ *
16702+ * This program, aufs is free software; you can redistribute it and/or modify
16703+ * it under the terms of the GNU General Public License as published by
16704+ * the Free Software Foundation; either version 2 of the License, or
16705+ * (at your option) any later version.
dece6358
AM
16706+ *
16707+ * This program is distributed in the hope that it will be useful,
16708+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16709+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16710+ * GNU General Public License for more details.
16711+ *
16712+ * You should have received a copy of the GNU General Public License
523b37e3 16713+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 16714+ */
16715+
16716+/*
4a4d8108 16717+ * fsnotify for the lower directories
1facf9fc 16718+ */
16719+
16720+#include "aufs.h"
16721+
4a4d8108
AM
16722+/* FS_IN_IGNORED is unnecessary */
16723+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
16724+ | FS_CREATE | FS_EVENT_ON_CHILD);
7f207e10 16725+static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq);
7eafdf33 16726+static __cacheline_aligned_in_smp atomic64_t au_hfsn_ifree = ATOMIC64_INIT(0);
1facf9fc 16727+
0c5527e5 16728+static void au_hfsn_free_mark(struct fsnotify_mark *mark)
1facf9fc 16729+{
0c5527e5
AM
16730+ struct au_hnotify *hn = container_of(mark, struct au_hnotify,
16731+ hn_mark);
5afbbe0d 16732+ /* AuDbg("here\n"); */
1c60b727 16733+ au_cache_free_hnotify(hn);
8b6a4947 16734+ smp_mb__before_atomic(); /* for atomic64_dec */
1716fcea
AM
16735+ if (atomic64_dec_and_test(&au_hfsn_ifree))
16736+ wake_up(&au_hfsn_wq);
4a4d8108 16737+}
1facf9fc 16738+
027c5e7a 16739+static int au_hfsn_alloc(struct au_hinode *hinode)
4a4d8108 16740+{
1716fcea 16741+ int err;
027c5e7a
AM
16742+ struct au_hnotify *hn;
16743+ struct super_block *sb;
16744+ struct au_branch *br;
0c5527e5 16745+ struct fsnotify_mark *mark;
027c5e7a 16746+ aufs_bindex_t bindex;
1facf9fc 16747+
027c5e7a
AM
16748+ hn = hinode->hi_notify;
16749+ sb = hn->hn_aufs_inode->i_sb;
16750+ bindex = au_br_index(sb, hinode->hi_id);
16751+ br = au_sbr(sb, bindex);
1716fcea
AM
16752+ AuDebugOn(!br->br_hfsn);
16753+
0c5527e5 16754+ mark = &hn->hn_mark;
ffa93bbd 16755+ fsnotify_init_mark(mark, br->br_hfsn->hfsn_group);
0c5527e5 16756+ mark->mask = AuHfsnMask;
7f207e10
AM
16757+ /*
16758+ * by udba rename or rmdir, aufs assign a new inode to the known
16759+ * h_inode, so specify 1 to allow dups.
16760+ */
c1595e42 16761+ lockdep_off();
acd2b654 16762+ err = fsnotify_add_inode_mark(mark, hinode->hi_inode, /*allow_dups*/1);
c1595e42 16763+ lockdep_on();
1716fcea
AM
16764+
16765+ return err;
1facf9fc 16766+}
16767+
7eafdf33 16768+static int au_hfsn_free(struct au_hinode *hinode, struct au_hnotify *hn)
1facf9fc 16769+{
0c5527e5 16770+ struct fsnotify_mark *mark;
7eafdf33 16771+ unsigned long long ull;
1716fcea 16772+ struct fsnotify_group *group;
7eafdf33
AM
16773+
16774+ ull = atomic64_inc_return(&au_hfsn_ifree);
16775+ BUG_ON(!ull);
953406b4 16776+
0c5527e5 16777+ mark = &hn->hn_mark;
1716fcea
AM
16778+ spin_lock(&mark->lock);
16779+ group = mark->group;
16780+ fsnotify_get_group(group);
16781+ spin_unlock(&mark->lock);
c1595e42 16782+ lockdep_off();
1716fcea 16783+ fsnotify_destroy_mark(mark, group);
5afbbe0d 16784+ fsnotify_put_mark(mark);
1716fcea 16785+ fsnotify_put_group(group);
c1595e42 16786+ lockdep_on();
7f207e10 16787+
7eafdf33
AM
16788+ /* free hn by myself */
16789+ return 0;
1facf9fc 16790+}
16791+
16792+/* ---------------------------------------------------------------------- */
16793+
4a4d8108 16794+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 16795+{
0c5527e5 16796+ struct fsnotify_mark *mark;
1facf9fc 16797+
0c5527e5
AM
16798+ mark = &hinode->hi_notify->hn_mark;
16799+ spin_lock(&mark->lock);
1facf9fc 16800+ if (do_set) {
0c5527e5
AM
16801+ AuDebugOn(mark->mask & AuHfsnMask);
16802+ mark->mask |= AuHfsnMask;
1facf9fc 16803+ } else {
0c5527e5
AM
16804+ AuDebugOn(!(mark->mask & AuHfsnMask));
16805+ mark->mask &= ~AuHfsnMask;
1facf9fc 16806+ }
0c5527e5 16807+ spin_unlock(&mark->lock);
4a4d8108 16808+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
1facf9fc 16809+}
16810+
4a4d8108 16811+/* ---------------------------------------------------------------------- */
1facf9fc 16812+
4a4d8108
AM
16813+/* #define AuDbgHnotify */
16814+#ifdef AuDbgHnotify
16815+static char *au_hfsn_name(u32 mask)
16816+{
16817+#ifdef CONFIG_AUFS_DEBUG
c06a8ce3
AM
16818+#define test_ret(flag) \
16819+ do { \
16820+ if (mask & flag) \
16821+ return #flag; \
16822+ } while (0)
4a4d8108
AM
16823+ test_ret(FS_ACCESS);
16824+ test_ret(FS_MODIFY);
16825+ test_ret(FS_ATTRIB);
16826+ test_ret(FS_CLOSE_WRITE);
16827+ test_ret(FS_CLOSE_NOWRITE);
16828+ test_ret(FS_OPEN);
16829+ test_ret(FS_MOVED_FROM);
16830+ test_ret(FS_MOVED_TO);
16831+ test_ret(FS_CREATE);
16832+ test_ret(FS_DELETE);
16833+ test_ret(FS_DELETE_SELF);
16834+ test_ret(FS_MOVE_SELF);
16835+ test_ret(FS_UNMOUNT);
16836+ test_ret(FS_Q_OVERFLOW);
16837+ test_ret(FS_IN_IGNORED);
b912730e 16838+ test_ret(FS_ISDIR);
4a4d8108
AM
16839+ test_ret(FS_IN_ONESHOT);
16840+ test_ret(FS_EVENT_ON_CHILD);
16841+ return "";
16842+#undef test_ret
16843+#else
16844+ return "??";
16845+#endif
1facf9fc 16846+}
4a4d8108 16847+#endif
1facf9fc 16848+
16849+/* ---------------------------------------------------------------------- */
16850+
1716fcea
AM
16851+static void au_hfsn_free_group(struct fsnotify_group *group)
16852+{
16853+ struct au_br_hfsnotify *hfsn = group->private;
16854+
5afbbe0d 16855+ /* AuDbg("here\n"); */
9f237c51 16856+ au_kfree_try_rcu(hfsn);
1716fcea
AM
16857+}
16858+
4a4d8108 16859+static int au_hfsn_handle_event(struct fsnotify_group *group,
a2654f78 16860+ u32 mask, const void *data, int data_type,
e37dd06a 16861+ struct inode *dir,
83b672a5 16862+ const struct qstr *file_name, u32 cookie,
ffa93bbd 16863+ struct fsnotify_iter_info *iter_info)
1facf9fc 16864+{
16865+ int err;
4a4d8108
AM
16866+ struct au_hnotify *hnotify;
16867+ struct inode *h_dir, *h_inode;
cd7a4cd9 16868+ struct fsnotify_mark *inode_mark;
4a4d8108 16869+
fb47a38f 16870+ AuDebugOn(data_type != FSNOTIFY_EVENT_INODE);
1facf9fc 16871+
16872+ err = 0;
0c5527e5 16873+ /* if FS_UNMOUNT happens, there must be another bug */
4a4d8108 16874+ AuDebugOn(mask & FS_UNMOUNT);
0c5527e5 16875+ if (mask & (FS_IN_IGNORED | FS_UNMOUNT))
1facf9fc 16876+ goto out;
1facf9fc 16877+
e37dd06a 16878+ h_dir = dir;
fb47a38f 16879+ h_inode = NULL;
4a4d8108 16880+#ifdef AuDbgHnotify
392086de 16881+ au_debug_on();
fbc438ed
JR
16882+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
16883+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
4a4d8108
AM
16884+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
16885+ h_dir->i_ino, mask, au_hfsn_name(mask),
fbc438ed 16886+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
4a4d8108 16887+ /* WARN_ON(1); */
1facf9fc 16888+ }
392086de 16889+ au_debug_off();
1facf9fc 16890+#endif
4a4d8108 16891+
cd7a4cd9 16892+ inode_mark = fsnotify_iter_inode_mark(iter_info);
0c5527e5
AM
16893+ AuDebugOn(!inode_mark);
16894+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
b62f1e65 16895+ err = au_hnotify(h_dir, hnotify, mask, file_name, h_inode);
1facf9fc 16896+
4a4d8108
AM
16897+out:
16898+ return err;
16899+}
1facf9fc 16900+
4a4d8108 16901+static struct fsnotify_ops au_hfsn_ops = {
1716fcea 16902+ .handle_event = au_hfsn_handle_event,
ffa93bbd
AM
16903+ .free_group_priv = au_hfsn_free_group,
16904+ .free_mark = au_hfsn_free_mark
4a4d8108
AM
16905+};
16906+
16907+/* ---------------------------------------------------------------------- */
16908+
027c5e7a
AM
16909+static void au_hfsn_fin_br(struct au_branch *br)
16910+{
1716fcea 16911+ struct au_br_hfsnotify *hfsn;
027c5e7a 16912+
1716fcea 16913+ hfsn = br->br_hfsn;
c1595e42
JR
16914+ if (hfsn) {
16915+ lockdep_off();
1716fcea 16916+ fsnotify_put_group(hfsn->hfsn_group);
c1595e42
JR
16917+ lockdep_on();
16918+ }
027c5e7a
AM
16919+}
16920+
1716fcea 16921+static int au_hfsn_init_br(struct au_branch *br, int perm)
4a4d8108
AM
16922+{
16923+ int err;
1716fcea
AM
16924+ struct fsnotify_group *group;
16925+ struct au_br_hfsnotify *hfsn;
1facf9fc 16926+
4a4d8108 16927+ err = 0;
1716fcea
AM
16928+ br->br_hfsn = NULL;
16929+ if (!au_br_hnotifyable(perm))
027c5e7a 16930+ goto out;
027c5e7a 16931+
1716fcea
AM
16932+ err = -ENOMEM;
16933+ hfsn = kmalloc(sizeof(*hfsn), GFP_NOFS);
16934+ if (unlikely(!hfsn))
027c5e7a
AM
16935+ goto out;
16936+
1716fcea
AM
16937+ err = 0;
16938+ group = fsnotify_alloc_group(&au_hfsn_ops);
16939+ if (IS_ERR(group)) {
16940+ err = PTR_ERR(group);
0c5527e5 16941+ pr_err("fsnotify_alloc_group() failed, %d\n", err);
1716fcea 16942+ goto out_hfsn;
4a4d8108 16943+ }
1facf9fc 16944+
1716fcea
AM
16945+ group->private = hfsn;
16946+ hfsn->hfsn_group = group;
16947+ br->br_hfsn = hfsn;
16948+ goto out; /* success */
16949+
16950+out_hfsn:
9f237c51 16951+ au_kfree_try_rcu(hfsn);
027c5e7a 16952+out:
1716fcea
AM
16953+ return err;
16954+}
16955+
16956+static int au_hfsn_reset_br(unsigned int udba, struct au_branch *br, int perm)
16957+{
16958+ int err;
16959+
16960+ err = 0;
16961+ if (!br->br_hfsn)
16962+ err = au_hfsn_init_br(br, perm);
16963+
1facf9fc 16964+ return err;
16965+}
16966+
7eafdf33
AM
16967+/* ---------------------------------------------------------------------- */
16968+
16969+static void au_hfsn_fin(void)
16970+{
16971+ AuDbg("au_hfsn_ifree %lld\n", (long long)atomic64_read(&au_hfsn_ifree));
16972+ wait_event(au_hfsn_wq, !atomic64_read(&au_hfsn_ifree));
16973+}
16974+
4a4d8108
AM
16975+const struct au_hnotify_op au_hnotify_op = {
16976+ .ctl = au_hfsn_ctl,
16977+ .alloc = au_hfsn_alloc,
16978+ .free = au_hfsn_free,
1facf9fc 16979+
7eafdf33
AM
16980+ .fin = au_hfsn_fin,
16981+
027c5e7a
AM
16982+ .reset_br = au_hfsn_reset_br,
16983+ .fin_br = au_hfsn_fin_br,
16984+ .init_br = au_hfsn_init_br
4a4d8108 16985+};
7f207e10 16986diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
eca34b5c 16987--- /usr/share/empty/fs/aufs/hfsplus.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 16988+++ linux/fs/aufs/hfsplus.c 2021-05-02 20:15:14.673337458 +0200
acd2b654 16989@@ -0,0 +1,60 @@
cd7a4cd9 16990+// SPDX-License-Identifier: GPL-2.0
4a4d8108 16991+/*
d58c55f2 16992+ * Copyright (C) 2010-2020 Junjiro R. Okajima
4a4d8108
AM
16993+ *
16994+ * This program, aufs is free software; you can redistribute it and/or modify
16995+ * it under the terms of the GNU General Public License as published by
16996+ * the Free Software Foundation; either version 2 of the License, or
16997+ * (at your option) any later version.
16998+ *
16999+ * This program is distributed in the hope that it will be useful,
17000+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17001+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17002+ * GNU General Public License for more details.
17003+ *
17004+ * You should have received a copy of the GNU General Public License
523b37e3 17005+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 17006+ */
1facf9fc 17007+
4a4d8108 17008+/*
acd2b654 17009+ * special support for filesystems which acquires an inode mutex
4a4d8108
AM
17010+ * at final closing a file, eg, hfsplus.
17011+ *
17012+ * This trick is very simple and stupid, just to open the file before really
acd2b654 17013+ * necessary open to tell hfsplus that this is not the final closing.
4a4d8108
AM
17014+ * The caller should call au_h_open_pre() after acquiring the inode mutex,
17015+ * and au_h_open_post() after releasing it.
17016+ */
1facf9fc 17017+
4a4d8108 17018+#include "aufs.h"
1facf9fc 17019+
392086de
AM
17020+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex,
17021+ int force_wr)
4a4d8108
AM
17022+{
17023+ struct file *h_file;
17024+ struct dentry *h_dentry;
1facf9fc 17025+
4a4d8108
AM
17026+ h_dentry = au_h_dptr(dentry, bindex);
17027+ AuDebugOn(!h_dentry);
5527c038 17028+ AuDebugOn(d_is_negative(h_dentry));
4a4d8108
AM
17029+
17030+ h_file = NULL;
17031+ if (au_test_hfsplus(h_dentry->d_sb)
7e9cd9fe 17032+ && d_is_reg(h_dentry))
4a4d8108
AM
17033+ h_file = au_h_open(dentry, bindex,
17034+ O_RDONLY | O_NOATIME | O_LARGEFILE,
392086de 17035+ /*file*/NULL, force_wr);
4a4d8108 17036+ return h_file;
1facf9fc 17037+}
17038+
4a4d8108
AM
17039+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
17040+ struct file *h_file)
17041+{
acd2b654
AM
17042+ struct au_branch *br;
17043+
4a4d8108
AM
17044+ if (h_file) {
17045+ fput(h_file);
acd2b654
AM
17046+ br = au_sbr(dentry->d_sb, bindex);
17047+ au_lcnt_dec(&br->br_nfiles);
4a4d8108
AM
17048+ }
17049+}
7f207e10 17050diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
eca34b5c 17051--- /usr/share/empty/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 17052+++ linux/fs/aufs/hnotify.c 2021-05-02 20:15:14.673337458 +0200
43982f53 17053@@ -0,0 +1,715 @@
cd7a4cd9 17054+// SPDX-License-Identifier: GPL-2.0
e49829fe 17055+/*
d58c55f2 17056+ * Copyright (C) 2005-2020 Junjiro R. Okajima
e49829fe
JR
17057+ *
17058+ * This program, aufs is free software; you can redistribute it and/or modify
17059+ * it under the terms of the GNU General Public License as published by
17060+ * the Free Software Foundation; either version 2 of the License, or
17061+ * (at your option) any later version.
17062+ *
17063+ * This program is distributed in the hope that it will be useful,
17064+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17065+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17066+ * GNU General Public License for more details.
17067+ *
17068+ * You should have received a copy of the GNU General Public License
523b37e3 17069+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
e49829fe
JR
17070+ */
17071+
17072+/*
7f207e10 17073+ * abstraction to notify the direct changes on lower directories
e49829fe
JR
17074+ */
17075+
eca801bf 17076+/* #include <linux/iversion.h> */
e49829fe
JR
17077+#include "aufs.h"
17078+
027c5e7a 17079+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode)
e49829fe
JR
17080+{
17081+ int err;
7f207e10 17082+ struct au_hnotify *hn;
1facf9fc 17083+
4a4d8108
AM
17084+ err = -ENOMEM;
17085+ hn = au_cache_alloc_hnotify();
17086+ if (hn) {
17087+ hn->hn_aufs_inode = inode;
027c5e7a
AM
17088+ hinode->hi_notify = hn;
17089+ err = au_hnotify_op.alloc(hinode);
17090+ AuTraceErr(err);
17091+ if (unlikely(err)) {
17092+ hinode->hi_notify = NULL;
1c60b727 17093+ au_cache_free_hnotify(hn);
4a4d8108
AM
17094+ /*
17095+ * The upper dir was removed by udba, but the same named
acd2b654 17096+ * dir left. In this case, aufs assigns a new inode
4a4d8108 17097+ * number and set the monitor again.
acd2b654 17098+ * For the lower dir, the old monitor is still left.
4a4d8108
AM
17099+ */
17100+ if (err == -EEXIST)
17101+ err = 0;
17102+ }
1308ab2a 17103+ }
1308ab2a 17104+
027c5e7a 17105+ AuTraceErr(err);
1308ab2a 17106+ return err;
dece6358 17107+}
1facf9fc 17108+
4a4d8108 17109+void au_hn_free(struct au_hinode *hinode)
dece6358 17110+{
4a4d8108 17111+ struct au_hnotify *hn;
1facf9fc 17112+
4a4d8108
AM
17113+ hn = hinode->hi_notify;
17114+ if (hn) {
4a4d8108 17115+ hinode->hi_notify = NULL;
7eafdf33 17116+ if (au_hnotify_op.free(hinode, hn))
1c60b727 17117+ au_cache_free_hnotify(hn);
4a4d8108
AM
17118+ }
17119+}
dece6358 17120+
4a4d8108 17121+/* ---------------------------------------------------------------------- */
dece6358 17122+
4a4d8108
AM
17123+void au_hn_ctl(struct au_hinode *hinode, int do_set)
17124+{
17125+ if (hinode->hi_notify)
17126+ au_hnotify_op.ctl(hinode, do_set);
17127+}
17128+
17129+void au_hn_reset(struct inode *inode, unsigned int flags)
17130+{
5afbbe0d 17131+ aufs_bindex_t bindex, bbot;
4a4d8108
AM
17132+ struct inode *hi;
17133+ struct dentry *iwhdentry;
1facf9fc 17134+
5afbbe0d
AM
17135+ bbot = au_ibbot(inode);
17136+ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) {
4a4d8108
AM
17137+ hi = au_h_iptr(inode, bindex);
17138+ if (!hi)
17139+ continue;
1308ab2a 17140+
febd17d6 17141+ /* inode_lock_nested(hi, AuLsc_I_CHILD); */
4a4d8108
AM
17142+ iwhdentry = au_hi_wh(inode, bindex);
17143+ if (iwhdentry)
17144+ dget(iwhdentry);
17145+ au_igrab(hi);
17146+ au_set_h_iptr(inode, bindex, NULL, 0);
17147+ au_set_h_iptr(inode, bindex, au_igrab(hi),
17148+ flags & ~AuHi_XINO);
17149+ iput(hi);
17150+ dput(iwhdentry);
febd17d6 17151+ /* inode_unlock(hi); */
1facf9fc 17152+ }
1facf9fc 17153+}
17154+
1308ab2a 17155+/* ---------------------------------------------------------------------- */
1facf9fc 17156+
4a4d8108 17157+static int hn_xino(struct inode *inode, struct inode *h_inode)
1facf9fc 17158+{
4a4d8108 17159+ int err;
5afbbe0d 17160+ aufs_bindex_t bindex, bbot, bfound, btop;
4a4d8108 17161+ struct inode *h_i;
1facf9fc 17162+
4a4d8108
AM
17163+ err = 0;
17164+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 17165+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
17166+ goto out;
17167+ }
1facf9fc 17168+
4a4d8108 17169+ bfound = -1;
5afbbe0d
AM
17170+ bbot = au_ibbot(inode);
17171+ btop = au_ibtop(inode);
4a4d8108 17172+#if 0 /* reserved for future use */
5afbbe0d 17173+ if (bindex == bbot) {
4a4d8108
AM
17174+ /* keep this ino in rename case */
17175+ goto out;
17176+ }
17177+#endif
5afbbe0d 17178+ for (bindex = btop; bindex <= bbot; bindex++)
4a4d8108
AM
17179+ if (au_h_iptr(inode, bindex) == h_inode) {
17180+ bfound = bindex;
17181+ break;
17182+ }
17183+ if (bfound < 0)
1308ab2a 17184+ goto out;
1facf9fc 17185+
5afbbe0d 17186+ for (bindex = btop; bindex <= bbot; bindex++) {
4a4d8108
AM
17187+ h_i = au_h_iptr(inode, bindex);
17188+ if (!h_i)
17189+ continue;
1facf9fc 17190+
4a4d8108
AM
17191+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
17192+ /* ignore this error */
17193+ /* bad action? */
1facf9fc 17194+ }
1facf9fc 17195+
4a4d8108 17196+ /* children inode number will be broken */
1facf9fc 17197+
4f0767ce 17198+out:
4a4d8108
AM
17199+ AuTraceErr(err);
17200+ return err;
1facf9fc 17201+}
17202+
4a4d8108 17203+static int hn_gen_tree(struct dentry *dentry)
1facf9fc 17204+{
4a4d8108
AM
17205+ int err, i, j, ndentry;
17206+ struct au_dcsub_pages dpages;
17207+ struct au_dpage *dpage;
17208+ struct dentry **dentries;
1facf9fc 17209+
4a4d8108
AM
17210+ err = au_dpages_init(&dpages, GFP_NOFS);
17211+ if (unlikely(err))
17212+ goto out;
17213+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
17214+ if (unlikely(err))
17215+ goto out_dpages;
1facf9fc 17216+
4a4d8108
AM
17217+ for (i = 0; i < dpages.ndpage; i++) {
17218+ dpage = dpages.dpages + i;
17219+ dentries = dpage->dentries;
17220+ ndentry = dpage->ndentry;
17221+ for (j = 0; j < ndentry; j++) {
17222+ struct dentry *d;
17223+
17224+ d = dentries[j];
17225+ if (IS_ROOT(d))
17226+ continue;
17227+
4a4d8108 17228+ au_digen_dec(d);
5527c038 17229+ if (d_really_is_positive(d))
4a4d8108
AM
17230+ /* todo: reset children xino?
17231+ cached children only? */
5527c038 17232+ au_iigen_dec(d_inode(d));
1308ab2a 17233+ }
dece6358 17234+ }
1facf9fc 17235+
4f0767ce 17236+out_dpages:
4a4d8108 17237+ au_dpages_free(&dpages);
4f0767ce 17238+out:
dece6358
AM
17239+ return err;
17240+}
17241+
1308ab2a 17242+/*
4a4d8108 17243+ * return 0 if processed.
1308ab2a 17244+ */
4a4d8108
AM
17245+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
17246+ const unsigned int isdir)
dece6358 17247+{
1308ab2a 17248+ int err;
4a4d8108
AM
17249+ struct dentry *d;
17250+ struct qstr *dname;
1facf9fc 17251+
4a4d8108
AM
17252+ err = 1;
17253+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 17254+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
17255+ err = 0;
17256+ goto out;
17257+ }
dece6358 17258+
4a4d8108
AM
17259+ if (!isdir) {
17260+ AuDebugOn(!name);
17261+ au_iigen_dec(inode);
027c5e7a 17262+ spin_lock(&inode->i_lock);
c1595e42 17263+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) {
027c5e7a 17264+ spin_lock(&d->d_lock);
4a4d8108
AM
17265+ dname = &d->d_name;
17266+ if (dname->len != nlen
027c5e7a
AM
17267+ && memcmp(dname->name, name, nlen)) {
17268+ spin_unlock(&d->d_lock);
4a4d8108 17269+ continue;
027c5e7a 17270+ }
4a4d8108 17271+ err = 0;
4a4d8108
AM
17272+ au_digen_dec(d);
17273+ spin_unlock(&d->d_lock);
17274+ break;
1facf9fc 17275+ }
027c5e7a 17276+ spin_unlock(&inode->i_lock);
1308ab2a 17277+ } else {
027c5e7a 17278+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIR);
c1595e42 17279+ d = d_find_any_alias(inode);
4a4d8108
AM
17280+ if (!d) {
17281+ au_iigen_dec(inode);
17282+ goto out;
17283+ }
1facf9fc 17284+
027c5e7a 17285+ spin_lock(&d->d_lock);
4a4d8108 17286+ dname = &d->d_name;
027c5e7a
AM
17287+ if (dname->len == nlen && !memcmp(dname->name, name, nlen)) {
17288+ spin_unlock(&d->d_lock);
4a4d8108 17289+ err = hn_gen_tree(d);
027c5e7a
AM
17290+ spin_lock(&d->d_lock);
17291+ }
17292+ spin_unlock(&d->d_lock);
4a4d8108
AM
17293+ dput(d);
17294+ }
1facf9fc 17295+
4f0767ce 17296+out:
4a4d8108 17297+ AuTraceErr(err);
1308ab2a 17298+ return err;
17299+}
dece6358 17300+
4a4d8108 17301+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
1facf9fc 17302+{
4a4d8108 17303+ int err;
1facf9fc 17304+
5527c038 17305+ if (IS_ROOT(dentry)) {
0c3ec466 17306+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
17307+ return 0;
17308+ }
1308ab2a 17309+
4a4d8108
AM
17310+ err = 0;
17311+ if (!isdir) {
4a4d8108 17312+ au_digen_dec(dentry);
5527c038
JR
17313+ if (d_really_is_positive(dentry))
17314+ au_iigen_dec(d_inode(dentry));
4a4d8108 17315+ } else {
027c5e7a 17316+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR);
5527c038 17317+ if (d_really_is_positive(dentry))
4a4d8108
AM
17318+ err = hn_gen_tree(dentry);
17319+ }
17320+
17321+ AuTraceErr(err);
17322+ return err;
1facf9fc 17323+}
17324+
4a4d8108 17325+/* ---------------------------------------------------------------------- */
1facf9fc 17326+
4a4d8108
AM
17327+/* hnotify job flags */
17328+#define AuHnJob_XINO0 1
17329+#define AuHnJob_GEN (1 << 1)
17330+#define AuHnJob_DIRENT (1 << 2)
17331+#define AuHnJob_ISDIR (1 << 3)
17332+#define AuHnJob_TRYXINO0 (1 << 4)
17333+#define AuHnJob_MNTPNT (1 << 5)
17334+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name)
7f207e10
AM
17335+#define au_fset_hnjob(flags, name) \
17336+ do { (flags) |= AuHnJob_##name; } while (0)
17337+#define au_fclr_hnjob(flags, name) \
17338+ do { (flags) &= ~AuHnJob_##name; } while (0)
1facf9fc 17339+
4a4d8108
AM
17340+enum {
17341+ AuHn_CHILD,
17342+ AuHn_PARENT,
17343+ AuHnLast
17344+};
1facf9fc 17345+
4a4d8108
AM
17346+struct au_hnotify_args {
17347+ struct inode *h_dir, *dir, *h_child_inode;
17348+ u32 mask;
17349+ unsigned int flags[AuHnLast];
17350+ unsigned int h_child_nlen;
17351+ char h_child_name[];
17352+};
1facf9fc 17353+
4a4d8108
AM
17354+struct hn_job_args {
17355+ unsigned int flags;
17356+ struct inode *inode, *h_inode, *dir, *h_dir;
17357+ struct dentry *dentry;
17358+ char *h_name;
17359+ int h_nlen;
17360+};
1308ab2a 17361+
4a4d8108
AM
17362+static int hn_job(struct hn_job_args *a)
17363+{
17364+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
076b876e 17365+ int e;
1308ab2a 17366+
4a4d8108
AM
17367+ /* reset xino */
17368+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
17369+ hn_xino(a->inode, a->h_inode); /* ignore this error */
1308ab2a 17370+
4a4d8108
AM
17371+ if (au_ftest_hnjob(a->flags, TRYXINO0)
17372+ && a->inode
17373+ && a->h_inode) {
be118d29 17374+ inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD);
38d290e6
JR
17375+ if (!a->h_inode->i_nlink
17376+ && !(a->h_inode->i_state & I_LINKABLE))
4a4d8108 17377+ hn_xino(a->inode, a->h_inode); /* ignore this error */
3c1bdaff 17378+ inode_unlock_shared(a->h_inode);
1308ab2a 17379+ }
1facf9fc 17380+
4a4d8108
AM
17381+ /* make the generation obsolete */
17382+ if (au_ftest_hnjob(a->flags, GEN)) {
076b876e 17383+ e = -1;
4a4d8108 17384+ if (a->inode)
076b876e 17385+ e = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
4a4d8108 17386+ isdir);
076b876e 17387+ if (e && a->dentry)
4a4d8108
AM
17388+ hn_gen_by_name(a->dentry, isdir);
17389+ /* ignore this error */
1facf9fc 17390+ }
1facf9fc 17391+
4a4d8108
AM
17392+ /* make dir entries obsolete */
17393+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
17394+ struct au_vdir *vdir;
1facf9fc 17395+
4a4d8108
AM
17396+ vdir = au_ivdir(a->inode);
17397+ if (vdir)
17398+ vdir->vd_jiffy = 0;
17399+ /* IMustLock(a->inode); */
be118d29 17400+ /* inode_inc_iversion(a->inode); */
4a4d8108 17401+ }
1facf9fc 17402+
4a4d8108
AM
17403+ /* can do nothing but warn */
17404+ if (au_ftest_hnjob(a->flags, MNTPNT)
17405+ && a->dentry
17406+ && d_mountpoint(a->dentry))
523b37e3 17407+ pr_warn("mount-point %pd is removed or renamed\n", a->dentry);
1facf9fc 17408+
4a4d8108 17409+ return 0;
1308ab2a 17410+}
1facf9fc 17411+
1308ab2a 17412+/* ---------------------------------------------------------------------- */
1facf9fc 17413+
4a4d8108
AM
17414+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
17415+ struct inode *dir)
1308ab2a 17416+{
4a4d8108
AM
17417+ struct dentry *dentry, *d, *parent;
17418+ struct qstr *dname;
1308ab2a 17419+
c1595e42 17420+ parent = d_find_any_alias(dir);
4a4d8108
AM
17421+ if (!parent)
17422+ return NULL;
1308ab2a 17423+
4a4d8108 17424+ dentry = NULL;
027c5e7a 17425+ spin_lock(&parent->d_lock);
c1595e42 17426+ list_for_each_entry(d, &parent->d_subdirs, d_child) {
523b37e3 17427+ /* AuDbg("%pd\n", d); */
027c5e7a 17428+ spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
4a4d8108
AM
17429+ dname = &d->d_name;
17430+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
027c5e7a
AM
17431+ goto cont_unlock;
17432+ if (au_di(d))
17433+ au_digen_dec(d);
17434+ else
17435+ goto cont_unlock;
c1595e42 17436+ if (au_dcount(d) > 0) {
027c5e7a 17437+ dentry = dget_dlock(d);
4a4d8108 17438+ spin_unlock(&d->d_lock);
027c5e7a 17439+ break;
dece6358 17440+ }
1facf9fc 17441+
f6b6e03d 17442+cont_unlock:
027c5e7a 17443+ spin_unlock(&d->d_lock);
1308ab2a 17444+ }
027c5e7a 17445+ spin_unlock(&parent->d_lock);
4a4d8108 17446+ dput(parent);
1facf9fc 17447+
4a4d8108
AM
17448+ if (dentry)
17449+ di_write_lock_child(dentry);
1308ab2a 17450+
4a4d8108
AM
17451+ return dentry;
17452+}
dece6358 17453+
4a4d8108
AM
17454+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
17455+ aufs_bindex_t bindex, ino_t h_ino)
17456+{
17457+ struct inode *inode;
17458+ ino_t ino;
17459+ int err;
17460+
17461+ inode = NULL;
17462+ err = au_xino_read(sb, bindex, h_ino, &ino);
17463+ if (!err && ino)
17464+ inode = ilookup(sb, ino);
17465+ if (!inode)
17466+ goto out;
17467+
17468+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 17469+ pr_warn("wrong root branch\n");
4a4d8108
AM
17470+ iput(inode);
17471+ inode = NULL;
17472+ goto out;
1308ab2a 17473+ }
17474+
4a4d8108 17475+ ii_write_lock_child(inode);
1308ab2a 17476+
4f0767ce 17477+out:
4a4d8108 17478+ return inode;
dece6358
AM
17479+}
17480+
4a4d8108 17481+static void au_hn_bh(void *_args)
1facf9fc 17482+{
4a4d8108
AM
17483+ struct au_hnotify_args *a = _args;
17484+ struct super_block *sb;
5afbbe0d 17485+ aufs_bindex_t bindex, bbot, bfound;
4a4d8108 17486+ unsigned char xino, try_iput;
1facf9fc 17487+ int err;
1308ab2a 17488+ struct inode *inode;
4a4d8108
AM
17489+ ino_t h_ino;
17490+ struct hn_job_args args;
17491+ struct dentry *dentry;
17492+ struct au_sbinfo *sbinfo;
1facf9fc 17493+
4a4d8108
AM
17494+ AuDebugOn(!_args);
17495+ AuDebugOn(!a->h_dir);
17496+ AuDebugOn(!a->dir);
17497+ AuDebugOn(!a->mask);
17498+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
17499+ a->mask, a->dir->i_ino, a->h_dir->i_ino,
17500+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
1facf9fc 17501+
4a4d8108
AM
17502+ inode = NULL;
17503+ dentry = NULL;
17504+ /*
17505+ * do not lock a->dir->i_mutex here
17506+ * because of d_revalidate() may cause a deadlock.
17507+ */
17508+ sb = a->dir->i_sb;
17509+ AuDebugOn(!sb);
17510+ sbinfo = au_sbi(sb);
17511+ AuDebugOn(!sbinfo);
7f207e10 17512+ si_write_lock(sb, AuLock_NOPLMW);
1facf9fc 17513+
8b6a4947
AM
17514+ if (au_opt_test(sbinfo->si_mntflags, DIRREN))
17515+ switch (a->mask & FS_EVENTS_POSS_ON_CHILD) {
17516+ case FS_MOVED_FROM:
17517+ case FS_MOVED_TO:
17518+ AuWarn1("DIRREN with UDBA may not work correctly "
17519+ "for the direct rename(2)\n");
17520+ }
17521+
4a4d8108
AM
17522+ ii_read_lock_parent(a->dir);
17523+ bfound = -1;
5afbbe0d
AM
17524+ bbot = au_ibbot(a->dir);
17525+ for (bindex = au_ibtop(a->dir); bindex <= bbot; bindex++)
4a4d8108
AM
17526+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
17527+ bfound = bindex;
17528+ break;
17529+ }
17530+ ii_read_unlock(a->dir);
17531+ if (unlikely(bfound < 0))
17532+ goto out;
1facf9fc 17533+
4a4d8108
AM
17534+ xino = !!au_opt_test(au_mntflags(sb), XINO);
17535+ h_ino = 0;
17536+ if (a->h_child_inode)
17537+ h_ino = a->h_child_inode->i_ino;
1facf9fc 17538+
4a4d8108
AM
17539+ if (a->h_child_nlen
17540+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
17541+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
17542+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
17543+ a->dir);
17544+ try_iput = 0;
5527c038
JR
17545+ if (dentry && d_really_is_positive(dentry))
17546+ inode = d_inode(dentry);
4a4d8108
AM
17547+ if (xino && !inode && h_ino
17548+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
17549+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
17550+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
17551+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
17552+ try_iput = 1;
f0c0a007 17553+ }
1facf9fc 17554+
4a4d8108
AM
17555+ args.flags = a->flags[AuHn_CHILD];
17556+ args.dentry = dentry;
17557+ args.inode = inode;
17558+ args.h_inode = a->h_child_inode;
17559+ args.dir = a->dir;
17560+ args.h_dir = a->h_dir;
17561+ args.h_name = a->h_child_name;
17562+ args.h_nlen = a->h_child_nlen;
17563+ err = hn_job(&args);
17564+ if (dentry) {
027c5e7a 17565+ if (au_di(dentry))
4a4d8108
AM
17566+ di_write_unlock(dentry);
17567+ dput(dentry);
17568+ }
17569+ if (inode && try_iput) {
17570+ ii_write_unlock(inode);
17571+ iput(inode);
17572+ }
1facf9fc 17573+
4a4d8108
AM
17574+ ii_write_lock_parent(a->dir);
17575+ args.flags = a->flags[AuHn_PARENT];
17576+ args.dentry = NULL;
17577+ args.inode = a->dir;
17578+ args.h_inode = a->h_dir;
17579+ args.dir = NULL;
17580+ args.h_dir = NULL;
17581+ args.h_name = NULL;
17582+ args.h_nlen = 0;
17583+ err = hn_job(&args);
17584+ ii_write_unlock(a->dir);
1facf9fc 17585+
4f0767ce 17586+out:
4a4d8108
AM
17587+ iput(a->h_child_inode);
17588+ iput(a->h_dir);
17589+ iput(a->dir);
027c5e7a
AM
17590+ si_write_unlock(sb);
17591+ au_nwt_done(&sbinfo->si_nowait);
9f237c51 17592+ au_kfree_rcu(a);
dece6358 17593+}
1facf9fc 17594+
4a4d8108
AM
17595+/* ---------------------------------------------------------------------- */
17596+
17597+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
b62f1e65 17598+ const struct qstr *h_child_qstr, struct inode *h_child_inode)
dece6358 17599+{
4a4d8108 17600+ int err, len;
53392da6 17601+ unsigned int flags[AuHnLast], f;
4a4d8108
AM
17602+ unsigned char isdir, isroot, wh;
17603+ struct inode *dir;
17604+ struct au_hnotify_args *args;
17605+ char *p, *h_child_name;
dece6358 17606+
1308ab2a 17607+ err = 0;
4a4d8108
AM
17608+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
17609+ dir = igrab(hnotify->hn_aufs_inode);
17610+ if (!dir)
17611+ goto out;
1facf9fc 17612+
4a4d8108
AM
17613+ isroot = (dir->i_ino == AUFS_ROOT_INO);
17614+ wh = 0;
17615+ h_child_name = (void *)h_child_qstr->name;
17616+ len = h_child_qstr->len;
17617+ if (h_child_name) {
17618+ if (len > AUFS_WH_PFX_LEN
17619+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
17620+ h_child_name += AUFS_WH_PFX_LEN;
17621+ len -= AUFS_WH_PFX_LEN;
17622+ wh = 1;
17623+ }
1facf9fc 17624+ }
dece6358 17625+
4a4d8108
AM
17626+ isdir = 0;
17627+ if (h_child_inode)
17628+ isdir = !!S_ISDIR(h_child_inode->i_mode);
17629+ flags[AuHn_PARENT] = AuHnJob_ISDIR;
17630+ flags[AuHn_CHILD] = 0;
17631+ if (isdir)
17632+ flags[AuHn_CHILD] = AuHnJob_ISDIR;
17633+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
17634+ au_fset_hnjob(flags[AuHn_CHILD], GEN);
fbc438ed 17635+ switch (mask & ALL_FSNOTIFY_DIRENT_EVENTS) {
4a4d8108
AM
17636+ case FS_MOVED_FROM:
17637+ case FS_MOVED_TO:
17638+ au_fset_hnjob(flags[AuHn_CHILD], XINO0);
17639+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
42a736d3 17640+ fallthrough;
4a4d8108 17641+ case FS_CREATE:
fb47a38f 17642+ AuDebugOn(!h_child_name);
4a4d8108 17643+ break;
1facf9fc 17644+
4a4d8108
AM
17645+ case FS_DELETE:
17646+ /*
17647+ * aufs never be able to get this child inode.
17648+ * revalidation should be in d_revalidate()
17649+ * by checking i_nlink, i_generation or d_unhashed().
17650+ */
17651+ AuDebugOn(!h_child_name);
17652+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
17653+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
17654+ break;
dece6358 17655+
4a4d8108
AM
17656+ default:
17657+ AuDebugOn(1);
17658+ }
1308ab2a 17659+
4a4d8108
AM
17660+ if (wh)
17661+ h_child_inode = NULL;
1308ab2a 17662+
4a4d8108
AM
17663+ err = -ENOMEM;
17664+ /* iput() and kfree() will be called in au_hnotify() */
4a4d8108 17665+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
4a4d8108
AM
17666+ if (unlikely(!args)) {
17667+ AuErr1("no memory\n");
17668+ iput(dir);
17669+ goto out;
17670+ }
17671+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
17672+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
17673+ args->mask = mask;
17674+ args->dir = dir;
17675+ args->h_dir = igrab(h_dir);
17676+ if (h_child_inode)
17677+ h_child_inode = igrab(h_child_inode); /* can be NULL */
17678+ args->h_child_inode = h_child_inode;
17679+ args->h_child_nlen = len;
17680+ if (len) {
17681+ p = (void *)args;
17682+ p += sizeof(*args);
17683+ memcpy(p, h_child_name, len);
17684+ p[len] = 0;
1308ab2a 17685+ }
1308ab2a 17686+
38d290e6 17687+ /* NFS fires the event for silly-renamed one from kworker */
53392da6 17688+ f = 0;
38d290e6
JR
17689+ if (!dir->i_nlink
17690+ || (au_test_nfs(h_dir->i_sb) && (mask & FS_DELETE)))
53392da6
AM
17691+ f = AuWkq_NEST;
17692+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb, f);
4a4d8108
AM
17693+ if (unlikely(err)) {
17694+ pr_err("wkq %d\n", err);
17695+ iput(args->h_child_inode);
17696+ iput(args->h_dir);
17697+ iput(args->dir);
9f237c51 17698+ au_kfree_rcu(args);
1facf9fc 17699+ }
1facf9fc 17700+
4a4d8108 17701+out:
1facf9fc 17702+ return err;
17703+}
17704+
027c5e7a
AM
17705+/* ---------------------------------------------------------------------- */
17706+
17707+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm)
17708+{
17709+ int err;
17710+
17711+ AuDebugOn(!(udba & AuOptMask_UDBA));
17712+
17713+ err = 0;
17714+ if (au_hnotify_op.reset_br)
17715+ err = au_hnotify_op.reset_br(udba, br, perm);
17716+
17717+ return err;
17718+}
17719+
17720+int au_hnotify_init_br(struct au_branch *br, int perm)
17721+{
17722+ int err;
17723+
17724+ err = 0;
17725+ if (au_hnotify_op.init_br)
17726+ err = au_hnotify_op.init_br(br, perm);
17727+
17728+ return err;
17729+}
17730+
17731+void au_hnotify_fin_br(struct au_branch *br)
17732+{
17733+ if (au_hnotify_op.fin_br)
17734+ au_hnotify_op.fin_br(br);
17735+}
17736+
4a4d8108
AM
17737+static void au_hn_destroy_cache(void)
17738+{
1c60b727
AM
17739+ kmem_cache_destroy(au_cache[AuCache_HNOTIFY]);
17740+ au_cache[AuCache_HNOTIFY] = NULL;
4a4d8108 17741+}
1308ab2a 17742+
4a4d8108 17743+int __init au_hnotify_init(void)
1facf9fc 17744+{
1308ab2a 17745+ int err;
1308ab2a 17746+
4a4d8108 17747+ err = -ENOMEM;
1c60b727
AM
17748+ au_cache[AuCache_HNOTIFY] = AuCache(au_hnotify);
17749+ if (au_cache[AuCache_HNOTIFY]) {
027c5e7a
AM
17750+ err = 0;
17751+ if (au_hnotify_op.init)
17752+ err = au_hnotify_op.init();
4a4d8108
AM
17753+ if (unlikely(err))
17754+ au_hn_destroy_cache();
1308ab2a 17755+ }
1308ab2a 17756+ AuTraceErr(err);
4a4d8108 17757+ return err;
1308ab2a 17758+}
17759+
4a4d8108 17760+void au_hnotify_fin(void)
1308ab2a 17761+{
027c5e7a
AM
17762+ if (au_hnotify_op.fin)
17763+ au_hnotify_op.fin();
f0c0a007 17764+
4a4d8108 17765+ /* cf. au_cache_fin() */
1c60b727 17766+ if (au_cache[AuCache_HNOTIFY])
4a4d8108 17767+ au_hn_destroy_cache();
dece6358 17768+}
7f207e10 17769diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
eca34b5c 17770--- /usr/share/empty/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 17771+++ linux/fs/aufs/iinfo.c 2021-05-02 20:15:14.673337458 +0200
062440b3 17772@@ -0,0 +1,286 @@
cd7a4cd9 17773+// SPDX-License-Identifier: GPL-2.0
dece6358 17774+/*
d58c55f2 17775+ * Copyright (C) 2005-2020 Junjiro R. Okajima
dece6358
AM
17776+ *
17777+ * This program, aufs is free software; you can redistribute it and/or modify
17778+ * it under the terms of the GNU General Public License as published by
17779+ * the Free Software Foundation; either version 2 of the License, or
17780+ * (at your option) any later version.
17781+ *
17782+ * This program is distributed in the hope that it will be useful,
17783+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17784+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17785+ * GNU General Public License for more details.
17786+ *
17787+ * You should have received a copy of the GNU General Public License
523b37e3 17788+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
dece6358 17789+ */
1facf9fc 17790+
dece6358 17791+/*
4a4d8108 17792+ * inode private data
dece6358 17793+ */
1facf9fc 17794+
1308ab2a 17795+#include "aufs.h"
1facf9fc 17796+
4a4d8108 17797+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 17798+{
4a4d8108 17799+ struct inode *h_inode;
5afbbe0d 17800+ struct au_hinode *hinode;
1facf9fc 17801+
4a4d8108 17802+ IiMustAnyLock(inode);
1facf9fc 17803+
5afbbe0d
AM
17804+ hinode = au_hinode(au_ii(inode), bindex);
17805+ h_inode = hinode->hi_inode;
4a4d8108
AM
17806+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
17807+ return h_inode;
17808+}
1facf9fc 17809+
4a4d8108
AM
17810+/* todo: hard/soft set? */
17811+void au_hiput(struct au_hinode *hinode)
17812+{
17813+ au_hn_free(hinode);
17814+ dput(hinode->hi_whdentry);
17815+ iput(hinode->hi_inode);
17816+}
1facf9fc 17817+
4a4d8108
AM
17818+unsigned int au_hi_flags(struct inode *inode, int isdir)
17819+{
17820+ unsigned int flags;
17821+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
1facf9fc 17822+
4a4d8108
AM
17823+ flags = 0;
17824+ if (au_opt_test(mnt_flags, XINO))
17825+ au_fset_hi(flags, XINO);
17826+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
17827+ au_fset_hi(flags, HNOTIFY);
17828+ return flags;
1facf9fc 17829+}
17830+
4a4d8108
AM
17831+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
17832+ struct inode *h_inode, unsigned int flags)
1308ab2a 17833+{
4a4d8108
AM
17834+ struct au_hinode *hinode;
17835+ struct inode *hi;
17836+ struct au_iinfo *iinfo = au_ii(inode);
1facf9fc 17837+
4a4d8108 17838+ IiMustWriteLock(inode);
dece6358 17839+
5afbbe0d 17840+ hinode = au_hinode(iinfo, bindex);
4a4d8108
AM
17841+ hi = hinode->hi_inode;
17842+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
17843+
17844+ if (hi)
17845+ au_hiput(hinode);
17846+ hinode->hi_inode = h_inode;
17847+ if (h_inode) {
17848+ int err;
17849+ struct super_block *sb = inode->i_sb;
17850+ struct au_branch *br;
17851+
027c5e7a
AM
17852+ AuDebugOn(inode->i_mode
17853+ && (h_inode->i_mode & S_IFMT)
17854+ != (inode->i_mode & S_IFMT));
5afbbe0d 17855+ if (bindex == iinfo->ii_btop)
4a4d8108
AM
17856+ au_cpup_igen(inode, h_inode);
17857+ br = au_sbr(sb, bindex);
17858+ hinode->hi_id = br->br_id;
17859+ if (au_ftest_hi(flags, XINO)) {
17860+ err = au_xino_write(sb, bindex, h_inode->i_ino,
17861+ inode->i_ino);
17862+ if (unlikely(err))
17863+ AuIOErr1("failed au_xino_write() %d\n", err);
17864+ }
17865+
17866+ if (au_ftest_hi(flags, HNOTIFY)
17867+ && au_br_hnotifyable(br->br_perm)) {
027c5e7a 17868+ err = au_hn_alloc(hinode, inode);
4a4d8108
AM
17869+ if (unlikely(err))
17870+ AuIOErr1("au_hn_alloc() %d\n", err);
1308ab2a 17871+ }
17872+ }
4a4d8108 17873+}
dece6358 17874+
4a4d8108
AM
17875+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
17876+ struct dentry *h_wh)
17877+{
17878+ struct au_hinode *hinode;
dece6358 17879+
4a4d8108
AM
17880+ IiMustWriteLock(inode);
17881+
5afbbe0d 17882+ hinode = au_hinode(au_ii(inode), bindex);
4a4d8108
AM
17883+ AuDebugOn(hinode->hi_whdentry);
17884+ hinode->hi_whdentry = h_wh;
1facf9fc 17885+}
17886+
537831f9 17887+void au_update_iigen(struct inode *inode, int half)
1308ab2a 17888+{
537831f9
AM
17889+ struct au_iinfo *iinfo;
17890+ struct au_iigen *iigen;
17891+ unsigned int sigen;
17892+
17893+ sigen = au_sigen(inode->i_sb);
17894+ iinfo = au_ii(inode);
17895+ iigen = &iinfo->ii_generation;
be52b249 17896+ spin_lock(&iigen->ig_spin);
537831f9
AM
17897+ iigen->ig_generation = sigen;
17898+ if (half)
17899+ au_ig_fset(iigen->ig_flags, HALF_REFRESHED);
17900+ else
17901+ au_ig_fclr(iigen->ig_flags, HALF_REFRESHED);
be52b249 17902+ spin_unlock(&iigen->ig_spin);
4a4d8108 17903+}
1facf9fc 17904+
4a4d8108
AM
17905+/* it may be called at remount time, too */
17906+void au_update_ibrange(struct inode *inode, int do_put_zero)
17907+{
17908+ struct au_iinfo *iinfo;
5afbbe0d 17909+ aufs_bindex_t bindex, bbot;
1facf9fc 17910+
5afbbe0d 17911+ AuDebugOn(au_is_bad_inode(inode));
4a4d8108 17912+ IiMustWriteLock(inode);
1facf9fc 17913+
5afbbe0d
AM
17914+ iinfo = au_ii(inode);
17915+ if (do_put_zero && iinfo->ii_btop >= 0) {
17916+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot;
4a4d8108
AM
17917+ bindex++) {
17918+ struct inode *h_i;
1facf9fc 17919+
5afbbe0d 17920+ h_i = au_hinode(iinfo, bindex)->hi_inode;
38d290e6
JR
17921+ if (h_i
17922+ && !h_i->i_nlink
17923+ && !(h_i->i_state & I_LINKABLE))
027c5e7a
AM
17924+ au_set_h_iptr(inode, bindex, NULL, 0);
17925+ }
4a4d8108
AM
17926+ }
17927+
5afbbe0d
AM
17928+ iinfo->ii_btop = -1;
17929+ iinfo->ii_bbot = -1;
17930+ bbot = au_sbbot(inode->i_sb);
17931+ for (bindex = 0; bindex <= bbot; bindex++)
17932+ if (au_hinode(iinfo, bindex)->hi_inode) {
17933+ iinfo->ii_btop = bindex;
4a4d8108 17934+ break;
027c5e7a 17935+ }
5afbbe0d
AM
17936+ if (iinfo->ii_btop >= 0)
17937+ for (bindex = bbot; bindex >= iinfo->ii_btop; bindex--)
17938+ if (au_hinode(iinfo, bindex)->hi_inode) {
17939+ iinfo->ii_bbot = bindex;
027c5e7a
AM
17940+ break;
17941+ }
5afbbe0d 17942+ AuDebugOn(iinfo->ii_btop > iinfo->ii_bbot);
1308ab2a 17943+}
1facf9fc 17944+
dece6358 17945+/* ---------------------------------------------------------------------- */
1facf9fc 17946+
4a4d8108 17947+void au_icntnr_init_once(void *_c)
dece6358 17948+{
4a4d8108
AM
17949+ struct au_icntnr *c = _c;
17950+ struct au_iinfo *iinfo = &c->iinfo;
1facf9fc 17951+
be52b249 17952+ spin_lock_init(&iinfo->ii_generation.ig_spin);
4a4d8108
AM
17953+ au_rw_init(&iinfo->ii_rwsem);
17954+ inode_init_once(&c->vfs_inode);
17955+}
1facf9fc 17956+
5afbbe0d
AM
17957+void au_hinode_init(struct au_hinode *hinode)
17958+{
17959+ hinode->hi_inode = NULL;
17960+ hinode->hi_id = -1;
17961+ au_hn_init(hinode);
17962+ hinode->hi_whdentry = NULL;
17963+}
17964+
4a4d8108
AM
17965+int au_iinfo_init(struct inode *inode)
17966+{
17967+ struct au_iinfo *iinfo;
17968+ struct super_block *sb;
5afbbe0d 17969+ struct au_hinode *hi;
4a4d8108 17970+ int nbr, i;
1facf9fc 17971+
4a4d8108
AM
17972+ sb = inode->i_sb;
17973+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
5afbbe0d 17974+ nbr = au_sbbot(sb) + 1;
4a4d8108
AM
17975+ if (unlikely(nbr <= 0))
17976+ nbr = 1;
5afbbe0d
AM
17977+ hi = kmalloc_array(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
17978+ if (hi) {
acd2b654 17979+ au_lcnt_inc(&au_sbi(sb)->si_ninodes);
5afbbe0d
AM
17980+
17981+ iinfo->ii_hinode = hi;
17982+ for (i = 0; i < nbr; i++, hi++)
17983+ au_hinode_init(hi);
1facf9fc 17984+
537831f9 17985+ iinfo->ii_generation.ig_generation = au_sigen(sb);
5afbbe0d
AM
17986+ iinfo->ii_btop = -1;
17987+ iinfo->ii_bbot = -1;
4a4d8108
AM
17988+ iinfo->ii_vdir = NULL;
17989+ return 0;
1308ab2a 17990+ }
4a4d8108
AM
17991+ return -ENOMEM;
17992+}
1facf9fc 17993+
e2f27e51 17994+int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink)
4a4d8108 17995+{
5afbbe0d 17996+ int err, i;
4a4d8108 17997+ struct au_hinode *hip;
1facf9fc 17998+
4a4d8108
AM
17999+ AuRwMustWriteLock(&iinfo->ii_rwsem);
18000+
18001+ err = -ENOMEM;
e2f27e51
AM
18002+ hip = au_krealloc(iinfo->ii_hinode, sizeof(*hip) * nbr, GFP_NOFS,
18003+ may_shrink);
4a4d8108
AM
18004+ if (hip) {
18005+ iinfo->ii_hinode = hip;
5afbbe0d
AM
18006+ i = iinfo->ii_bbot + 1;
18007+ hip += i;
18008+ for (; i < nbr; i++, hip++)
18009+ au_hinode_init(hip);
4a4d8108 18010+ err = 0;
1308ab2a 18011+ }
4a4d8108 18012+
1308ab2a 18013+ return err;
1facf9fc 18014+}
18015+
4a4d8108 18016+void au_iinfo_fin(struct inode *inode)
1facf9fc 18017+{
4a4d8108
AM
18018+ struct au_iinfo *iinfo;
18019+ struct au_hinode *hi;
18020+ struct super_block *sb;
5afbbe0d 18021+ aufs_bindex_t bindex, bbot;
b752ccd1 18022+ const unsigned char unlinked = !inode->i_nlink;
1308ab2a 18023+
5afbbe0d 18024+ AuDebugOn(au_is_bad_inode(inode));
1308ab2a 18025+
b752ccd1 18026+ sb = inode->i_sb;
acd2b654 18027+ au_lcnt_dec(&au_sbi(sb)->si_ninodes);
b752ccd1
AM
18028+ if (si_pid_test(sb))
18029+ au_xino_delete_inode(inode, unlinked);
18030+ else {
18031+ /*
18032+ * it is safe to hide the dependency between sbinfo and
18033+ * sb->s_umount.
18034+ */
18035+ lockdep_off();
18036+ si_noflush_read_lock(sb);
18037+ au_xino_delete_inode(inode, unlinked);
18038+ si_read_unlock(sb);
18039+ lockdep_on();
18040+ }
18041+
5afbbe0d 18042+ iinfo = au_ii(inode);
4a4d8108 18043+ if (iinfo->ii_vdir)
1c60b727 18044+ au_vdir_free(iinfo->ii_vdir);
1308ab2a 18045+
5afbbe0d 18046+ bindex = iinfo->ii_btop;
b752ccd1 18047+ if (bindex >= 0) {
5afbbe0d
AM
18048+ hi = au_hinode(iinfo, bindex);
18049+ bbot = iinfo->ii_bbot;
18050+ while (bindex++ <= bbot) {
b752ccd1 18051+ if (hi->hi_inode)
4a4d8108 18052+ au_hiput(hi);
4a4d8108
AM
18053+ hi++;
18054+ }
18055+ }
9f237c51 18056+ au_kfree_rcu(iinfo->ii_hinode);
4a4d8108 18057+ AuRwDestroy(&iinfo->ii_rwsem);
dece6358 18058+}
7f207e10 18059diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
eca34b5c 18060--- /usr/share/empty/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6
JR
18061+++ linux/fs/aufs/inode.c 2021-05-02 20:15:14.673337458 +0200
18062@@ -0,0 +1,531 @@
cd7a4cd9 18063+// SPDX-License-Identifier: GPL-2.0
4a4d8108 18064+/*
d58c55f2 18065+ * Copyright (C) 2005-2020 Junjiro R. Okajima
4a4d8108
AM
18066+ *
18067+ * This program, aufs is free software; you can redistribute it and/or modify
18068+ * it under the terms of the GNU General Public License as published by
18069+ * the Free Software Foundation; either version 2 of the License, or
18070+ * (at your option) any later version.
18071+ *
18072+ * This program is distributed in the hope that it will be useful,
18073+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18074+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18075+ * GNU General Public License for more details.
18076+ *
18077+ * You should have received a copy of the GNU General Public License
523b37e3 18078+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 18079+ */
1facf9fc 18080+
4a4d8108
AM
18081+/*
18082+ * inode functions
18083+ */
1facf9fc 18084+
eca801bf 18085+#include <linux/iversion.h>
4a4d8108 18086+#include "aufs.h"
1308ab2a 18087+
4a4d8108
AM
18088+struct inode *au_igrab(struct inode *inode)
18089+{
18090+ if (inode) {
18091+ AuDebugOn(!atomic_read(&inode->i_count));
027c5e7a 18092+ ihold(inode);
1facf9fc 18093+ }
4a4d8108
AM
18094+ return inode;
18095+}
1facf9fc 18096+
4a4d8108
AM
18097+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
18098+{
18099+ au_cpup_attr_all(inode, /*force*/0);
537831f9 18100+ au_update_iigen(inode, /*half*/1);
4a4d8108 18101+ if (do_version)
be118d29 18102+ inode_inc_iversion(inode);
dece6358 18103+}
1facf9fc 18104+
027c5e7a 18105+static int au_ii_refresh(struct inode *inode, int *update)
dece6358 18106+{
e2f27e51 18107+ int err, e, nbr;
027c5e7a 18108+ umode_t type;
4a4d8108 18109+ aufs_bindex_t bindex, new_bindex;
1308ab2a 18110+ struct super_block *sb;
4a4d8108 18111+ struct au_iinfo *iinfo;
027c5e7a 18112+ struct au_hinode *p, *q, tmp;
1facf9fc 18113+
5afbbe0d 18114+ AuDebugOn(au_is_bad_inode(inode));
4a4d8108 18115+ IiMustWriteLock(inode);
1facf9fc 18116+
027c5e7a 18117+ *update = 0;
4a4d8108 18118+ sb = inode->i_sb;
e2f27e51 18119+ nbr = au_sbbot(sb) + 1;
027c5e7a 18120+ type = inode->i_mode & S_IFMT;
4a4d8108 18121+ iinfo = au_ii(inode);
e2f27e51 18122+ err = au_hinode_realloc(iinfo, nbr, /*may_shrink*/0);
4a4d8108 18123+ if (unlikely(err))
1308ab2a 18124+ goto out;
1facf9fc 18125+
5afbbe0d
AM
18126+ AuDebugOn(iinfo->ii_btop < 0);
18127+ p = au_hinode(iinfo, iinfo->ii_btop);
18128+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot;
4a4d8108
AM
18129+ bindex++, p++) {
18130+ if (!p->hi_inode)
18131+ continue;
1facf9fc 18132+
027c5e7a 18133+ AuDebugOn(type != (p->hi_inode->i_mode & S_IFMT));
4a4d8108
AM
18134+ new_bindex = au_br_index(sb, p->hi_id);
18135+ if (new_bindex == bindex)
18136+ continue;
1facf9fc 18137+
4a4d8108 18138+ if (new_bindex < 0) {
027c5e7a 18139+ *update = 1;
4a4d8108
AM
18140+ au_hiput(p);
18141+ p->hi_inode = NULL;
18142+ continue;
1308ab2a 18143+ }
4a4d8108 18144+
5afbbe0d
AM
18145+ if (new_bindex < iinfo->ii_btop)
18146+ iinfo->ii_btop = new_bindex;
18147+ if (iinfo->ii_bbot < new_bindex)
18148+ iinfo->ii_bbot = new_bindex;
4a4d8108 18149+ /* swap two lower inode, and loop again */
5afbbe0d 18150+ q = au_hinode(iinfo, new_bindex);
4a4d8108
AM
18151+ tmp = *q;
18152+ *q = *p;
18153+ *p = tmp;
18154+ if (tmp.hi_inode) {
18155+ bindex--;
18156+ p--;
1308ab2a 18157+ }
18158+ }
4a4d8108 18159+ au_update_ibrange(inode, /*do_put_zero*/0);
e2f27e51 18160+ au_hinode_realloc(iinfo, nbr, /*may_shrink*/1); /* harmless if err */
4a4d8108
AM
18161+ e = au_dy_irefresh(inode);
18162+ if (unlikely(e && !err))
18163+ err = e;
1facf9fc 18164+
4f0767ce 18165+out:
027c5e7a
AM
18166+ AuTraceErr(err);
18167+ return err;
18168+}
18169+
b95c5147
AM
18170+void au_refresh_iop(struct inode *inode, int force_getattr)
18171+{
18172+ int type;
18173+ struct au_sbinfo *sbi = au_sbi(inode->i_sb);
18174+ const struct inode_operations *iop
18175+ = force_getattr ? aufs_iop : sbi->si_iop_array;
18176+
18177+ if (inode->i_op == iop)
18178+ return;
18179+
18180+ switch (inode->i_mode & S_IFMT) {
18181+ case S_IFDIR:
18182+ type = AuIop_DIR;
18183+ break;
18184+ case S_IFLNK:
18185+ type = AuIop_SYMLINK;
18186+ break;
18187+ default:
18188+ type = AuIop_OTHER;
18189+ break;
18190+ }
18191+
18192+ inode->i_op = iop + type;
18193+ /* unnecessary smp_wmb() */
18194+}
18195+
027c5e7a
AM
18196+int au_refresh_hinode_self(struct inode *inode)
18197+{
18198+ int err, update;
18199+
18200+ err = au_ii_refresh(inode, &update);
18201+ if (!err)
18202+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
18203+
18204+ AuTraceErr(err);
4a4d8108
AM
18205+ return err;
18206+}
1facf9fc 18207+
4a4d8108
AM
18208+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
18209+{
027c5e7a 18210+ int err, e, update;
4a4d8108 18211+ unsigned int flags;
027c5e7a 18212+ umode_t mode;
5afbbe0d 18213+ aufs_bindex_t bindex, bbot;
027c5e7a 18214+ unsigned char isdir;
4a4d8108
AM
18215+ struct au_hinode *p;
18216+ struct au_iinfo *iinfo;
1facf9fc 18217+
027c5e7a 18218+ err = au_ii_refresh(inode, &update);
4a4d8108
AM
18219+ if (unlikely(err))
18220+ goto out;
18221+
18222+ update = 0;
18223+ iinfo = au_ii(inode);
5afbbe0d 18224+ p = au_hinode(iinfo, iinfo->ii_btop);
027c5e7a
AM
18225+ mode = (inode->i_mode & S_IFMT);
18226+ isdir = S_ISDIR(mode);
4a4d8108 18227+ flags = au_hi_flags(inode, isdir);
5afbbe0d
AM
18228+ bbot = au_dbbot(dentry);
18229+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) {
5527c038 18230+ struct inode *h_i, *h_inode;
4a4d8108
AM
18231+ struct dentry *h_d;
18232+
18233+ h_d = au_h_dptr(dentry, bindex);
5527c038 18234+ if (!h_d || d_is_negative(h_d))
4a4d8108
AM
18235+ continue;
18236+
5527c038
JR
18237+ h_inode = d_inode(h_d);
18238+ AuDebugOn(mode != (h_inode->i_mode & S_IFMT));
5afbbe0d 18239+ if (iinfo->ii_btop <= bindex && bindex <= iinfo->ii_bbot) {
4a4d8108
AM
18240+ h_i = au_h_iptr(inode, bindex);
18241+ if (h_i) {
5527c038 18242+ if (h_i == h_inode)
4a4d8108
AM
18243+ continue;
18244+ err = -EIO;
18245+ break;
18246+ }
18247+ }
5afbbe0d
AM
18248+ if (bindex < iinfo->ii_btop)
18249+ iinfo->ii_btop = bindex;
18250+ if (iinfo->ii_bbot < bindex)
18251+ iinfo->ii_bbot = bindex;
5527c038 18252+ au_set_h_iptr(inode, bindex, au_igrab(h_inode), flags);
4a4d8108 18253+ update = 1;
1308ab2a 18254+ }
4a4d8108
AM
18255+ au_update_ibrange(inode, /*do_put_zero*/0);
18256+ e = au_dy_irefresh(inode);
18257+ if (unlikely(e && !err))
18258+ err = e;
027c5e7a
AM
18259+ if (!err)
18260+ au_refresh_hinode_attr(inode, update && isdir);
4a4d8108 18261+
4f0767ce 18262+out:
4a4d8108 18263+ AuTraceErr(err);
1308ab2a 18264+ return err;
dece6358
AM
18265+}
18266+
4a4d8108 18267+static int set_inode(struct inode *inode, struct dentry *dentry)
dece6358 18268+{
4a4d8108
AM
18269+ int err;
18270+ unsigned int flags;
18271+ umode_t mode;
5afbbe0d 18272+ aufs_bindex_t bindex, btop, btail;
4a4d8108
AM
18273+ unsigned char isdir;
18274+ struct dentry *h_dentry;
18275+ struct inode *h_inode;
18276+ struct au_iinfo *iinfo;
43982f53 18277+ const struct inode_operations *iop;
dece6358 18278+
4a4d8108 18279+ IiMustWriteLock(inode);
dece6358 18280+
4a4d8108
AM
18281+ err = 0;
18282+ isdir = 0;
b95c5147 18283+ iop = au_sbi(inode->i_sb)->si_iop_array;
5afbbe0d
AM
18284+ btop = au_dbtop(dentry);
18285+ h_dentry = au_h_dptr(dentry, btop);
5527c038 18286+ h_inode = d_inode(h_dentry);
4a4d8108
AM
18287+ mode = h_inode->i_mode;
18288+ switch (mode & S_IFMT) {
18289+ case S_IFREG:
18290+ btail = au_dbtail(dentry);
b95c5147 18291+ inode->i_op = iop + AuIop_OTHER;
4a4d8108 18292+ inode->i_fop = &aufs_file_fop;
5afbbe0d 18293+ err = au_dy_iaop(inode, btop, h_inode);
4a4d8108
AM
18294+ if (unlikely(err))
18295+ goto out;
18296+ break;
18297+ case S_IFDIR:
18298+ isdir = 1;
18299+ btail = au_dbtaildir(dentry);
b95c5147 18300+ inode->i_op = iop + AuIop_DIR;
4a4d8108
AM
18301+ inode->i_fop = &aufs_dir_fop;
18302+ break;
18303+ case S_IFLNK:
18304+ btail = au_dbtail(dentry);
b95c5147 18305+ inode->i_op = iop + AuIop_SYMLINK;
4a4d8108
AM
18306+ break;
18307+ case S_IFBLK:
18308+ case S_IFCHR:
18309+ case S_IFIFO:
18310+ case S_IFSOCK:
18311+ btail = au_dbtail(dentry);
b95c5147 18312+ inode->i_op = iop + AuIop_OTHER;
38d290e6 18313+ init_special_inode(inode, mode, h_inode->i_rdev);
4a4d8108
AM
18314+ break;
18315+ default:
18316+ AuIOErr("Unknown file type 0%o\n", mode);
18317+ err = -EIO;
1308ab2a 18318+ goto out;
4a4d8108 18319+ }
dece6358 18320+
4a4d8108
AM
18321+ /* do not set hnotify for whiteouted dirs (SHWH mode) */
18322+ flags = au_hi_flags(inode, isdir);
18323+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
18324+ && au_ftest_hi(flags, HNOTIFY)
18325+ && dentry->d_name.len > AUFS_WH_PFX_LEN
18326+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
18327+ au_fclr_hi(flags, HNOTIFY);
18328+ iinfo = au_ii(inode);
5afbbe0d
AM
18329+ iinfo->ii_btop = btop;
18330+ iinfo->ii_bbot = btail;
18331+ for (bindex = btop; bindex <= btail; bindex++) {
4a4d8108
AM
18332+ h_dentry = au_h_dptr(dentry, bindex);
18333+ if (h_dentry)
18334+ au_set_h_iptr(inode, bindex,
5527c038 18335+ au_igrab(d_inode(h_dentry)), flags);
4a4d8108
AM
18336+ }
18337+ au_cpup_attr_all(inode, /*force*/1);
c1595e42
JR
18338+ /*
18339+ * to force calling aufs_get_acl() every time,
18340+ * do not call cache_no_acl() for aufs inode.
18341+ */
dece6358 18342+
4f0767ce 18343+out:
4a4d8108
AM
18344+ return err;
18345+}
dece6358 18346+
027c5e7a
AM
18347+/*
18348+ * successful returns with iinfo write_locked
18349+ * minus: errno
18350+ * zero: success, matched
18351+ * plus: no error, but unmatched
18352+ */
18353+static int reval_inode(struct inode *inode, struct dentry *dentry)
4a4d8108
AM
18354+{
18355+ int err;
cfc41e69 18356+ unsigned int gen, igflags;
5afbbe0d 18357+ aufs_bindex_t bindex, bbot;
4a4d8108 18358+ struct inode *h_inode, *h_dinode;
5527c038 18359+ struct dentry *h_dentry;
dece6358 18360+
4a4d8108
AM
18361+ /*
18362+ * before this function, if aufs got any iinfo lock, it must be only
18363+ * one, the parent dir.
18364+ * it can happen by UDBA and the obsoleted inode number.
18365+ */
18366+ err = -EIO;
18367+ if (unlikely(inode->i_ino == parent_ino(dentry)))
18368+ goto out;
18369+
027c5e7a 18370+ err = 1;
4a4d8108 18371+ ii_write_lock_new_child(inode);
5afbbe0d 18372+ h_dentry = au_h_dptr(dentry, au_dbtop(dentry));
5527c038 18373+ h_dinode = d_inode(h_dentry);
5afbbe0d
AM
18374+ bbot = au_ibbot(inode);
18375+ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) {
4a4d8108 18376+ h_inode = au_h_iptr(inode, bindex);
537831f9
AM
18377+ if (!h_inode || h_inode != h_dinode)
18378+ continue;
18379+
18380+ err = 0;
cfc41e69 18381+ gen = au_iigen(inode, &igflags);
537831f9 18382+ if (gen == au_digen(dentry)
cfc41e69 18383+ && !au_ig_ftest(igflags, HALF_REFRESHED))
4a4d8108 18384+ break;
537831f9
AM
18385+
18386+ /* fully refresh inode using dentry */
18387+ err = au_refresh_hinode(inode, dentry);
18388+ if (!err)
18389+ au_update_iigen(inode, /*half*/0);
18390+ break;
1facf9fc 18391+ }
dece6358 18392+
4a4d8108
AM
18393+ if (unlikely(err))
18394+ ii_write_unlock(inode);
4f0767ce 18395+out:
1facf9fc 18396+ return err;
18397+}
1facf9fc 18398+
4a4d8108
AM
18399+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
18400+ unsigned int d_type, ino_t *ino)
1facf9fc 18401+{
521ced18
JR
18402+ int err, idx;
18403+ const int isnondir = d_type != DT_DIR;
1facf9fc 18404+
b752ccd1 18405+ /* prevent hardlinked inode number from race condition */
521ced18
JR
18406+ if (isnondir) {
18407+ err = au_xinondir_enter(sb, bindex, h_ino, &idx);
18408+ if (unlikely(err))
18409+ goto out;
4a4d8108 18410+ }
521ced18 18411+
4a4d8108
AM
18412+ err = au_xino_read(sb, bindex, h_ino, ino);
18413+ if (unlikely(err))
521ced18 18414+ goto out_xinondir;
1308ab2a 18415+
4a4d8108
AM
18416+ if (!*ino) {
18417+ err = -EIO;
18418+ *ino = au_xino_new_ino(sb);
18419+ if (unlikely(!*ino))
521ced18 18420+ goto out_xinondir;
4a4d8108
AM
18421+ err = au_xino_write(sb, bindex, h_ino, *ino);
18422+ if (unlikely(err))
521ced18 18423+ goto out_xinondir;
1308ab2a 18424+ }
1facf9fc 18425+
521ced18
JR
18426+out_xinondir:
18427+ if (isnondir && idx >= 0)
18428+ au_xinondir_leave(sb, bindex, h_ino, idx);
4f0767ce 18429+out:
1facf9fc 18430+ return err;
18431+}
18432+
4a4d8108
AM
18433+/* successful returns with iinfo write_locked */
18434+/* todo: return with unlocked? */
18435+struct inode *au_new_inode(struct dentry *dentry, int must_new)
1facf9fc 18436+{
5527c038 18437+ struct inode *inode, *h_inode;
4a4d8108
AM
18438+ struct dentry *h_dentry;
18439+ struct super_block *sb;
18440+ ino_t h_ino, ino;
521ced18 18441+ int err, idx, hlinked;
5afbbe0d 18442+ aufs_bindex_t btop;
1facf9fc 18443+
4a4d8108 18444+ sb = dentry->d_sb;
5afbbe0d
AM
18445+ btop = au_dbtop(dentry);
18446+ h_dentry = au_h_dptr(dentry, btop);
5527c038
JR
18447+ h_inode = d_inode(h_dentry);
18448+ h_ino = h_inode->i_ino;
521ced18 18449+ hlinked = !d_is_dir(h_dentry) && h_inode->i_nlink > 1;
b752ccd1 18450+
521ced18 18451+new_ino:
b752ccd1
AM
18452+ /*
18453+ * stop 'race'-ing between hardlinks under different
18454+ * parents.
18455+ */
521ced18
JR
18456+ if (hlinked) {
18457+ err = au_xinondir_enter(sb, btop, h_ino, &idx);
18458+ inode = ERR_PTR(err);
18459+ if (unlikely(err))
18460+ goto out;
18461+ }
b752ccd1 18462+
5afbbe0d 18463+ err = au_xino_read(sb, btop, h_ino, &ino);
4a4d8108
AM
18464+ inode = ERR_PTR(err);
18465+ if (unlikely(err))
521ced18 18466+ goto out_xinondir;
b752ccd1 18467+
4a4d8108
AM
18468+ if (!ino) {
18469+ ino = au_xino_new_ino(sb);
18470+ if (unlikely(!ino)) {
18471+ inode = ERR_PTR(-EIO);
521ced18 18472+ goto out_xinondir;
dece6358
AM
18473+ }
18474+ }
1facf9fc 18475+
4a4d8108
AM
18476+ AuDbg("i%lu\n", (unsigned long)ino);
18477+ inode = au_iget_locked(sb, ino);
18478+ err = PTR_ERR(inode);
18479+ if (IS_ERR(inode))
521ced18 18480+ goto out_xinondir;
1facf9fc 18481+
4a4d8108
AM
18482+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
18483+ if (inode->i_state & I_NEW) {
18484+ ii_write_lock_new_child(inode);
18485+ err = set_inode(inode, dentry);
18486+ if (!err) {
18487+ unlock_new_inode(inode);
521ced18 18488+ goto out_xinondir; /* success */
4a4d8108 18489+ }
1308ab2a 18490+
027c5e7a
AM
18491+ /*
18492+ * iget_failed() calls iput(), but we need to call
18493+ * ii_write_unlock() after iget_failed(). so dirty hack for
18494+ * i_count.
18495+ */
18496+ atomic_inc(&inode->i_count);
4a4d8108 18497+ iget_failed(inode);
027c5e7a 18498+ ii_write_unlock(inode);
5afbbe0d 18499+ au_xino_write(sb, btop, h_ino, /*ino*/0);
027c5e7a
AM
18500+ /* ignore this error */
18501+ goto out_iput;
18502+ } else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) {
b752ccd1
AM
18503+ /*
18504+ * horrible race condition between lookup, readdir and copyup
18505+ * (or something).
18506+ */
521ced18
JR
18507+ if (hlinked && idx >= 0)
18508+ au_xinondir_leave(sb, btop, h_ino, idx);
027c5e7a
AM
18509+ err = reval_inode(inode, dentry);
18510+ if (unlikely(err < 0)) {
521ced18 18511+ hlinked = 0;
027c5e7a
AM
18512+ goto out_iput;
18513+ }
521ced18 18514+ if (!err)
4a4d8108 18515+ goto out; /* success */
521ced18
JR
18516+ else if (hlinked && idx >= 0) {
18517+ err = au_xinondir_enter(sb, btop, h_ino, &idx);
18518+ if (unlikely(err)) {
18519+ iput(inode);
18520+ inode = ERR_PTR(err);
18521+ goto out;
18522+ }
18523+ }
4a4d8108
AM
18524+ }
18525+
5527c038 18526+ if (unlikely(au_test_fs_unique_ino(h_inode)))
4a4d8108 18527+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
523b37e3 18528+ " b%d, %s, %pd, hi%lu, i%lu.\n",
5afbbe0d 18529+ btop, au_sbtype(h_dentry->d_sb), dentry,
4a4d8108
AM
18530+ (unsigned long)h_ino, (unsigned long)ino);
18531+ ino = 0;
5afbbe0d 18532+ err = au_xino_write(sb, btop, h_ino, /*ino*/0);
4a4d8108
AM
18533+ if (!err) {
18534+ iput(inode);
521ced18
JR
18535+ if (hlinked && idx >= 0)
18536+ au_xinondir_leave(sb, btop, h_ino, idx);
4a4d8108
AM
18537+ goto new_ino;
18538+ }
1308ab2a 18539+
4f0767ce 18540+out_iput:
4a4d8108 18541+ iput(inode);
4a4d8108 18542+ inode = ERR_PTR(err);
521ced18
JR
18543+out_xinondir:
18544+ if (hlinked && idx >= 0)
18545+ au_xinondir_leave(sb, btop, h_ino, idx);
4f0767ce 18546+out:
4a4d8108 18547+ return inode;
1facf9fc 18548+}
18549+
4a4d8108 18550+/* ---------------------------------------------------------------------- */
1facf9fc 18551+
4a4d8108
AM
18552+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
18553+ struct inode *inode)
18554+{
18555+ int err;
076b876e 18556+ struct inode *hi;
1facf9fc 18557+
4a4d8108 18558+ err = au_br_rdonly(au_sbr(sb, bindex));
1facf9fc 18559+
4a4d8108
AM
18560+ /* pseudo-link after flushed may happen out of bounds */
18561+ if (!err
18562+ && inode
5afbbe0d
AM
18563+ && au_ibtop(inode) <= bindex
18564+ && bindex <= au_ibbot(inode)) {
4a4d8108
AM
18565+ /*
18566+ * permission check is unnecessary since vfsub routine
18567+ * will be called later
18568+ */
076b876e 18569+ hi = au_h_iptr(inode, bindex);
4a4d8108
AM
18570+ if (hi)
18571+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
1facf9fc 18572+ }
18573+
4a4d8108
AM
18574+ return err;
18575+}
dece6358 18576+
0b2a12c6
JR
18577+int au_test_h_perm(struct user_namespace *h_userns, struct inode *h_inode,
18578+ int mask)
4a4d8108 18579+{
2dfbb274 18580+ if (uid_eq(current_fsuid(), GLOBAL_ROOT_UID))
4a4d8108 18581+ return 0;
0b2a12c6 18582+ return inode_permission(h_userns, h_inode, mask);
4a4d8108 18583+}
1facf9fc 18584+
0b2a12c6
JR
18585+int au_test_h_perm_sio(struct user_namespace *h_userns, struct inode *h_inode,
18586+ int mask)
4a4d8108
AM
18587+{
18588+ if (au_test_nfs(h_inode->i_sb)
18589+ && (mask & MAY_WRITE)
18590+ && S_ISDIR(h_inode->i_mode))
18591+ mask |= MAY_READ; /* force permission check */
0b2a12c6 18592+ return au_test_h_perm(h_userns, h_inode, mask);
1facf9fc 18593+}
7f207e10 18594diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
eca34b5c 18595--- /usr/share/empty/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6
JR
18596+++ linux/fs/aufs/inode.h 2021-05-02 20:15:14.673337458 +0200
18597@@ -0,0 +1,705 @@
062440b3 18598+/* SPDX-License-Identifier: GPL-2.0 */
4a4d8108 18599+/*
d58c55f2 18600+ * Copyright (C) 2005-2020 Junjiro R. Okajima
4a4d8108
AM
18601+ *
18602+ * This program, aufs is free software; you can redistribute it and/or modify
18603+ * it under the terms of the GNU General Public License as published by
18604+ * the Free Software Foundation; either version 2 of the License, or
18605+ * (at your option) any later version.
18606+ *
18607+ * This program is distributed in the hope that it will be useful,
18608+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18609+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18610+ * GNU General Public License for more details.
18611+ *
18612+ * You should have received a copy of the GNU General Public License
523b37e3 18613+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 18614+ */
1facf9fc 18615+
1308ab2a 18616+/*
4a4d8108 18617+ * inode operations
1308ab2a 18618+ */
dece6358 18619+
4a4d8108
AM
18620+#ifndef __AUFS_INODE_H__
18621+#define __AUFS_INODE_H__
dece6358 18622+
4a4d8108 18623+#ifdef __KERNEL__
1308ab2a 18624+
4a4d8108 18625+#include <linux/fsnotify.h>
4a4d8108 18626+#include "rwsem.h"
1308ab2a 18627+
4a4d8108 18628+struct vfsmount;
1facf9fc 18629+
4a4d8108
AM
18630+struct au_hnotify {
18631+#ifdef CONFIG_AUFS_HNOTIFY
18632+#ifdef CONFIG_AUFS_HFSNOTIFY
7f207e10 18633+ /* never use fsnotify_add_vfsmount_mark() */
0c5527e5 18634+ struct fsnotify_mark hn_mark;
4a4d8108 18635+#endif
1c60b727 18636+ struct inode *hn_aufs_inode; /* no get/put */
9f237c51 18637+ struct rcu_head rcu;
4a4d8108
AM
18638+#endif
18639+} ____cacheline_aligned_in_smp;
1facf9fc 18640+
4a4d8108
AM
18641+struct au_hinode {
18642+ struct inode *hi_inode;
18643+ aufs_bindex_t hi_id;
18644+#ifdef CONFIG_AUFS_HNOTIFY
18645+ struct au_hnotify *hi_notify;
18646+#endif
dece6358 18647+
4a4d8108
AM
18648+ /* reference to the copied-up whiteout with get/put */
18649+ struct dentry *hi_whdentry;
18650+};
dece6358 18651+
537831f9
AM
18652+/* ig_flags */
18653+#define AuIG_HALF_REFRESHED 1
18654+#define au_ig_ftest(flags, name) ((flags) & AuIG_##name)
18655+#define au_ig_fset(flags, name) \
18656+ do { (flags) |= AuIG_##name; } while (0)
18657+#define au_ig_fclr(flags, name) \
18658+ do { (flags) &= ~AuIG_##name; } while (0)
18659+
18660+struct au_iigen {
be52b249 18661+ spinlock_t ig_spin;
537831f9
AM
18662+ __u32 ig_generation, ig_flags;
18663+};
18664+
4a4d8108
AM
18665+struct au_vdir;
18666+struct au_iinfo {
7a9e40b8 18667+ struct au_iigen ii_generation;
4a4d8108 18668+ struct super_block *ii_hsb1; /* no get/put */
1facf9fc 18669+
4a4d8108 18670+ struct au_rwsem ii_rwsem;
5afbbe0d 18671+ aufs_bindex_t ii_btop, ii_bbot;
4a4d8108
AM
18672+ __u32 ii_higen;
18673+ struct au_hinode *ii_hinode;
18674+ struct au_vdir *ii_vdir;
18675+};
1facf9fc 18676+
4a4d8108 18677+struct au_icntnr {
9f237c51
AM
18678+ struct au_iinfo iinfo;
18679+ struct inode vfs_inode;
18680+ struct hlist_bl_node plink;
18681+ struct rcu_head rcu;
4a4d8108 18682+} ____cacheline_aligned_in_smp;
1308ab2a 18683+
4a4d8108
AM
18684+/* au_pin flags */
18685+#define AuPin_DI_LOCKED 1
18686+#define AuPin_MNT_WRITE (1 << 1)
18687+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
7f207e10
AM
18688+#define au_fset_pin(flags, name) \
18689+ do { (flags) |= AuPin_##name; } while (0)
18690+#define au_fclr_pin(flags, name) \
18691+ do { (flags) &= ~AuPin_##name; } while (0)
4a4d8108
AM
18692+
18693+struct au_pin {
18694+ /* input */
18695+ struct dentry *dentry;
18696+ unsigned int udba;
18697+ unsigned char lsc_di, lsc_hi, flags;
18698+ aufs_bindex_t bindex;
18699+
18700+ /* output */
18701+ struct dentry *parent;
18702+ struct au_hinode *hdir;
18703+ struct vfsmount *h_mnt;
86dc4139
AM
18704+
18705+ /* temporary unlock/relock for copyup */
18706+ struct dentry *h_dentry, *h_parent;
18707+ struct au_branch *br;
18708+ struct task_struct *task;
4a4d8108 18709+};
1facf9fc 18710+
86dc4139 18711+void au_pin_hdir_unlock(struct au_pin *p);
c1595e42 18712+int au_pin_hdir_lock(struct au_pin *p);
86dc4139 18713+int au_pin_hdir_relock(struct au_pin *p);
86dc4139
AM
18714+void au_pin_hdir_acquire_nest(struct au_pin *p);
18715+void au_pin_hdir_release(struct au_pin *p);
18716+
1308ab2a 18717+/* ---------------------------------------------------------------------- */
18718+
4a4d8108 18719+static inline struct au_iinfo *au_ii(struct inode *inode)
1facf9fc 18720+{
5afbbe0d
AM
18721+ BUG_ON(is_bad_inode(inode));
18722+ return &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
4a4d8108 18723+}
1facf9fc 18724+
4a4d8108 18725+/* ---------------------------------------------------------------------- */
1facf9fc 18726+
4a4d8108
AM
18727+/* inode.c */
18728+struct inode *au_igrab(struct inode *inode);
b95c5147 18729+void au_refresh_iop(struct inode *inode, int force_getattr);
027c5e7a 18730+int au_refresh_hinode_self(struct inode *inode);
4a4d8108
AM
18731+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
18732+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
18733+ unsigned int d_type, ino_t *ino);
18734+struct inode *au_new_inode(struct dentry *dentry, int must_new);
18735+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
18736+ struct inode *inode);
0b2a12c6
JR
18737+int au_test_h_perm(struct user_namespace *h_userns, struct inode *h_inode,
18738+ int mask);
18739+int au_test_h_perm_sio(struct user_namespace *h_userns, struct inode *h_inode,
18740+ int mask);
1facf9fc 18741+
4a4d8108
AM
18742+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
18743+ ino_t h_ino, unsigned int d_type, ino_t *ino)
18744+{
18745+#ifdef CONFIG_AUFS_SHWH
18746+ return au_ino(sb, bindex, h_ino, d_type, ino);
18747+#else
18748+ return 0;
18749+#endif
18750+}
1facf9fc 18751+
4a4d8108 18752+/* i_op.c */
b95c5147
AM
18753+enum {
18754+ AuIop_SYMLINK,
18755+ AuIop_DIR,
18756+ AuIop_OTHER,
18757+ AuIop_Last
18758+};
43982f53 18759+extern struct inode_operations aufs_iop[AuIop_Last], /* not const */
b95c5147 18760+ aufs_iop_nogetattr[AuIop_Last];
1308ab2a 18761+
4a4d8108
AM
18762+/* au_wr_dir flags */
18763+#define AuWrDir_ADD_ENTRY 1
7e9cd9fe
AM
18764+#define AuWrDir_ISDIR (1 << 1)
18765+#define AuWrDir_TMPFILE (1 << 2)
4a4d8108 18766+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
7f207e10
AM
18767+#define au_fset_wrdir(flags, name) \
18768+ do { (flags) |= AuWrDir_##name; } while (0)
18769+#define au_fclr_wrdir(flags, name) \
18770+ do { (flags) &= ~AuWrDir_##name; } while (0)
1facf9fc 18771+
4a4d8108
AM
18772+struct au_wr_dir_args {
18773+ aufs_bindex_t force_btgt;
18774+ unsigned char flags;
18775+};
18776+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
18777+ struct au_wr_dir_args *args);
dece6358 18778+
4a4d8108
AM
18779+struct dentry *au_pinned_h_parent(struct au_pin *pin);
18780+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
18781+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
18782+ unsigned int udba, unsigned char flags);
18783+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
18784+ unsigned int udba, unsigned char flags) __must_check;
18785+int au_do_pin(struct au_pin *pin) __must_check;
18786+void au_unpin(struct au_pin *pin);
c1595e42
JR
18787+int au_reval_for_attr(struct dentry *dentry, unsigned int sigen);
18788+
18789+#define AuIcpup_DID_CPUP 1
18790+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
18791+#define au_fset_icpup(flags, name) \
18792+ do { (flags) |= AuIcpup_##name; } while (0)
18793+#define au_fclr_icpup(flags, name) \
18794+ do { (flags) &= ~AuIcpup_##name; } while (0)
18795+
18796+struct au_icpup_args {
18797+ unsigned char flags;
18798+ unsigned char pin_flags;
18799+ aufs_bindex_t btgt;
18800+ unsigned int udba;
18801+ struct au_pin pin;
18802+ struct path h_path;
18803+ struct inode *h_inode;
18804+};
18805+
18806+int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
18807+ struct au_icpup_args *a);
18808+
42b5c33a
AM
18809+int au_h_path_getattr(struct dentry *dentry, struct inode *inode, int force,
18810+ struct path *h_path, int locked);
1facf9fc 18811+
4a4d8108
AM
18812+/* i_op_add.c */
18813+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
18814+ struct dentry *h_parent, int isdir);
0b2a12c6
JR
18815+int aufs_mknod(struct user_namespace *userns, struct inode *dir,
18816+ struct dentry *dentry, umode_t mode, dev_t dev);
18817+int aufs_symlink(struct user_namespace *userns, struct inode *dir,
18818+ struct dentry *dentry, const char *symname);
18819+int aufs_create(struct user_namespace *userns, struct inode *dir,
18820+ struct dentry *dentry, umode_t mode, bool want_excl);
b912730e
AM
18821+struct vfsub_aopen_args;
18822+int au_aopen_or_create(struct inode *dir, struct dentry *dentry,
18823+ struct vfsub_aopen_args *args);
0b2a12c6
JR
18824+int aufs_tmpfile(struct user_namespace *userns, struct inode *dir,
18825+ struct dentry *dentry, umode_t mode);
4a4d8108
AM
18826+int aufs_link(struct dentry *src_dentry, struct inode *dir,
18827+ struct dentry *dentry);
0b2a12c6
JR
18828+int aufs_mkdir(struct user_namespace *userns, struct inode *dir,
18829+ struct dentry *dentry, umode_t mode);
1facf9fc 18830+
4a4d8108
AM
18831+/* i_op_del.c */
18832+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
18833+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
18834+ struct dentry *h_parent, int isdir);
18835+int aufs_unlink(struct inode *dir, struct dentry *dentry);
18836+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1308ab2a 18837+
4a4d8108
AM
18838+/* i_op_ren.c */
18839+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
0b2a12c6
JR
18840+int aufs_rename(struct user_namespace *userns,
18841+ struct inode *_src_dir, struct dentry *_src_dentry,
18842+ struct inode *_dst_dir, struct dentry *_dst_dentry,
18843+ unsigned int _flags);
1facf9fc 18844+
4a4d8108
AM
18845+/* iinfo.c */
18846+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
18847+void au_hiput(struct au_hinode *hinode);
18848+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
18849+ struct dentry *h_wh);
18850+unsigned int au_hi_flags(struct inode *inode, int isdir);
1308ab2a 18851+
4a4d8108
AM
18852+/* hinode flags */
18853+#define AuHi_XINO 1
18854+#define AuHi_HNOTIFY (1 << 1)
18855+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
7f207e10
AM
18856+#define au_fset_hi(flags, name) \
18857+ do { (flags) |= AuHi_##name; } while (0)
18858+#define au_fclr_hi(flags, name) \
18859+ do { (flags) &= ~AuHi_##name; } while (0)
1facf9fc 18860+
4a4d8108
AM
18861+#ifndef CONFIG_AUFS_HNOTIFY
18862+#undef AuHi_HNOTIFY
18863+#define AuHi_HNOTIFY 0
18864+#endif
1facf9fc 18865+
4a4d8108
AM
18866+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
18867+ struct inode *h_inode, unsigned int flags);
1facf9fc 18868+
537831f9 18869+void au_update_iigen(struct inode *inode, int half);
4a4d8108 18870+void au_update_ibrange(struct inode *inode, int do_put_zero);
1facf9fc 18871+
4a4d8108 18872+void au_icntnr_init_once(void *_c);
5afbbe0d 18873+void au_hinode_init(struct au_hinode *hinode);
4a4d8108
AM
18874+int au_iinfo_init(struct inode *inode);
18875+void au_iinfo_fin(struct inode *inode);
e2f27e51 18876+int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink);
1308ab2a 18877+
e49829fe 18878+#ifdef CONFIG_PROC_FS
4a4d8108 18879+/* plink.c */
e49829fe 18880+int au_plink_maint(struct super_block *sb, int flags);
7e9cd9fe 18881+struct au_sbinfo;
e49829fe
JR
18882+void au_plink_maint_leave(struct au_sbinfo *sbinfo);
18883+int au_plink_maint_enter(struct super_block *sb);
4a4d8108
AM
18884+#ifdef CONFIG_AUFS_DEBUG
18885+void au_plink_list(struct super_block *sb);
18886+#else
18887+AuStubVoid(au_plink_list, struct super_block *sb)
18888+#endif
18889+int au_plink_test(struct inode *inode);
18890+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
18891+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
18892+ struct dentry *h_dentry);
e49829fe
JR
18893+void au_plink_put(struct super_block *sb, int verbose);
18894+void au_plink_clean(struct super_block *sb, int verbose);
4a4d8108 18895+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
e49829fe
JR
18896+#else
18897+AuStubInt0(au_plink_maint, struct super_block *sb, int flags);
18898+AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo);
18899+AuStubInt0(au_plink_maint_enter, struct super_block *sb);
18900+AuStubVoid(au_plink_list, struct super_block *sb);
18901+AuStubInt0(au_plink_test, struct inode *inode);
18902+AuStub(struct dentry *, au_plink_lkup, return NULL,
18903+ struct inode *inode, aufs_bindex_t bindex);
18904+AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex,
18905+ struct dentry *h_dentry);
18906+AuStubVoid(au_plink_put, struct super_block *sb, int verbose);
18907+AuStubVoid(au_plink_clean, struct super_block *sb, int verbose);
18908+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id);
18909+#endif /* CONFIG_PROC_FS */
1facf9fc 18910+
c1595e42
JR
18911+#ifdef CONFIG_AUFS_XATTR
18912+/* xattr.c */
0b2a12c6 18913+int au_cpup_xattr(struct path *h_dst, struct path *h_src, int ignore_flags,
7e9cd9fe 18914+ unsigned int verbose);
c1595e42 18915+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size);
f2c43d5f 18916+void au_xattr_init(struct super_block *sb);
c1595e42 18917+#else
0b2a12c6 18918+AuStubInt0(au_cpup_xattr, struct path *h_dst, struct path *h_src,
7e9cd9fe 18919+ int ignore_flags, unsigned int verbose);
f2c43d5f 18920+AuStubVoid(au_xattr_init, struct super_block *sb);
c1595e42
JR
18921+#endif
18922+
18923+#ifdef CONFIG_FS_POSIX_ACL
18924+struct posix_acl *aufs_get_acl(struct inode *inode, int type);
0b2a12c6
JR
18925+int aufs_set_acl(struct user_namespace *userns, struct inode *inode,
18926+ struct posix_acl *acl, int type);
c1595e42
JR
18927+#endif
18928+
18929+#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL)
18930+enum {
18931+ AU_XATTR_SET,
c1595e42
JR
18932+ AU_ACL_SET
18933+};
18934+
f2c43d5f 18935+struct au_sxattr {
c1595e42
JR
18936+ int type;
18937+ union {
18938+ struct {
18939+ const char *name;
18940+ const void *value;
18941+ size_t size;
18942+ int flags;
18943+ } set;
18944+ struct {
c1595e42
JR
18945+ struct posix_acl *acl;
18946+ int type;
18947+ } acl_set;
18948+ } u;
18949+};
f2c43d5f
AM
18950+ssize_t au_sxattr(struct dentry *dentry, struct inode *inode,
18951+ struct au_sxattr *arg);
c1595e42
JR
18952+#endif
18953+
4a4d8108 18954+/* ---------------------------------------------------------------------- */
1308ab2a 18955+
4a4d8108
AM
18956+/* lock subclass for iinfo */
18957+enum {
18958+ AuLsc_II_CHILD, /* child first */
18959+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */
18960+ AuLsc_II_CHILD3, /* copyup dirs */
18961+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
18962+ AuLsc_II_PARENT2,
18963+ AuLsc_II_PARENT3, /* copyup dirs */
18964+ AuLsc_II_NEW_CHILD
18965+};
1308ab2a 18966+
1facf9fc 18967+/*
4a4d8108
AM
18968+ * ii_read_lock_child, ii_write_lock_child,
18969+ * ii_read_lock_child2, ii_write_lock_child2,
18970+ * ii_read_lock_child3, ii_write_lock_child3,
18971+ * ii_read_lock_parent, ii_write_lock_parent,
18972+ * ii_read_lock_parent2, ii_write_lock_parent2,
18973+ * ii_read_lock_parent3, ii_write_lock_parent3,
18974+ * ii_read_lock_new_child, ii_write_lock_new_child,
1facf9fc 18975+ */
4a4d8108
AM
18976+#define AuReadLockFunc(name, lsc) \
18977+static inline void ii_read_lock_##name(struct inode *i) \
18978+{ \
18979+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
18980+}
18981+
18982+#define AuWriteLockFunc(name, lsc) \
18983+static inline void ii_write_lock_##name(struct inode *i) \
18984+{ \
18985+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
18986+}
18987+
18988+#define AuRWLockFuncs(name, lsc) \
18989+ AuReadLockFunc(name, lsc) \
18990+ AuWriteLockFunc(name, lsc)
18991+
18992+AuRWLockFuncs(child, CHILD);
18993+AuRWLockFuncs(child2, CHILD2);
18994+AuRWLockFuncs(child3, CHILD3);
18995+AuRWLockFuncs(parent, PARENT);
18996+AuRWLockFuncs(parent2, PARENT2);
18997+AuRWLockFuncs(parent3, PARENT3);
18998+AuRWLockFuncs(new_child, NEW_CHILD);
18999+
19000+#undef AuReadLockFunc
19001+#undef AuWriteLockFunc
19002+#undef AuRWLockFuncs
1facf9fc 19003+
8b6a4947
AM
19004+#define ii_read_unlock(i) au_rw_read_unlock(&au_ii(i)->ii_rwsem)
19005+#define ii_write_unlock(i) au_rw_write_unlock(&au_ii(i)->ii_rwsem)
19006+#define ii_downgrade_lock(i) au_rw_dgrade_lock(&au_ii(i)->ii_rwsem)
1facf9fc 19007+
4a4d8108
AM
19008+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
19009+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
19010+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
1facf9fc 19011+
4a4d8108 19012+/* ---------------------------------------------------------------------- */
1308ab2a 19013+
027c5e7a
AM
19014+static inline void au_icntnr_init(struct au_icntnr *c)
19015+{
19016+#ifdef CONFIG_AUFS_DEBUG
19017+ c->vfs_inode.i_mode = 0;
19018+#endif
19019+}
19020+
cfc41e69 19021+static inline unsigned int au_iigen(struct inode *inode, unsigned int *igflags)
4a4d8108 19022+{
537831f9
AM
19023+ unsigned int gen;
19024+ struct au_iinfo *iinfo;
be52b249 19025+ struct au_iigen *iigen;
537831f9
AM
19026+
19027+ iinfo = au_ii(inode);
be52b249
AM
19028+ iigen = &iinfo->ii_generation;
19029+ spin_lock(&iigen->ig_spin);
cfc41e69
AM
19030+ if (igflags)
19031+ *igflags = iigen->ig_flags;
be52b249
AM
19032+ gen = iigen->ig_generation;
19033+ spin_unlock(&iigen->ig_spin);
537831f9
AM
19034+
19035+ return gen;
4a4d8108 19036+}
1308ab2a 19037+
4a4d8108
AM
19038+/* tiny test for inode number */
19039+/* tmpfs generation is too rough */
19040+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
19041+{
19042+ struct au_iinfo *iinfo;
1308ab2a 19043+
4a4d8108
AM
19044+ iinfo = au_ii(inode);
19045+ AuRwMustAnyLock(&iinfo->ii_rwsem);
19046+ return !(iinfo->ii_hsb1 == h_inode->i_sb
19047+ && iinfo->ii_higen == h_inode->i_generation);
19048+}
1308ab2a 19049+
4a4d8108
AM
19050+static inline void au_iigen_dec(struct inode *inode)
19051+{
537831f9 19052+ struct au_iinfo *iinfo;
be52b249 19053+ struct au_iigen *iigen;
537831f9
AM
19054+
19055+ iinfo = au_ii(inode);
be52b249
AM
19056+ iigen = &iinfo->ii_generation;
19057+ spin_lock(&iigen->ig_spin);
19058+ iigen->ig_generation--;
19059+ spin_unlock(&iigen->ig_spin);
027c5e7a
AM
19060+}
19061+
19062+static inline int au_iigen_test(struct inode *inode, unsigned int sigen)
19063+{
19064+ int err;
19065+
19066+ err = 0;
537831f9 19067+ if (unlikely(inode && au_iigen(inode, NULL) != sigen))
027c5e7a
AM
19068+ err = -EIO;
19069+
19070+ return err;
4a4d8108 19071+}
1308ab2a 19072+
4a4d8108 19073+/* ---------------------------------------------------------------------- */
1308ab2a 19074+
5afbbe0d
AM
19075+static inline struct au_hinode *au_hinode(struct au_iinfo *iinfo,
19076+ aufs_bindex_t bindex)
19077+{
19078+ return iinfo->ii_hinode + bindex;
19079+}
19080+
19081+static inline int au_is_bad_inode(struct inode *inode)
19082+{
19083+ return !!(is_bad_inode(inode) || !au_hinode(au_ii(inode), 0));
19084+}
19085+
4a4d8108
AM
19086+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
19087+ aufs_bindex_t bindex)
19088+{
19089+ IiMustAnyLock(inode);
5afbbe0d 19090+ return au_hinode(au_ii(inode), bindex)->hi_id;
4a4d8108 19091+}
1308ab2a 19092+
5afbbe0d 19093+static inline aufs_bindex_t au_ibtop(struct inode *inode)
4a4d8108
AM
19094+{
19095+ IiMustAnyLock(inode);
5afbbe0d 19096+ return au_ii(inode)->ii_btop;
4a4d8108 19097+}
1308ab2a 19098+
5afbbe0d 19099+static inline aufs_bindex_t au_ibbot(struct inode *inode)
4a4d8108
AM
19100+{
19101+ IiMustAnyLock(inode);
5afbbe0d 19102+ return au_ii(inode)->ii_bbot;
4a4d8108 19103+}
1308ab2a 19104+
4a4d8108
AM
19105+static inline struct au_vdir *au_ivdir(struct inode *inode)
19106+{
19107+ IiMustAnyLock(inode);
19108+ return au_ii(inode)->ii_vdir;
19109+}
1308ab2a 19110+
4a4d8108
AM
19111+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
19112+{
19113+ IiMustAnyLock(inode);
5afbbe0d 19114+ return au_hinode(au_ii(inode), bindex)->hi_whdentry;
4a4d8108 19115+}
1308ab2a 19116+
5afbbe0d 19117+static inline void au_set_ibtop(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 19118+{
4a4d8108 19119+ IiMustWriteLock(inode);
5afbbe0d 19120+ au_ii(inode)->ii_btop = bindex;
4a4d8108 19121+}
1308ab2a 19122+
5afbbe0d 19123+static inline void au_set_ibbot(struct inode *inode, aufs_bindex_t bindex)
4a4d8108
AM
19124+{
19125+ IiMustWriteLock(inode);
5afbbe0d 19126+ au_ii(inode)->ii_bbot = bindex;
1308ab2a 19127+}
19128+
4a4d8108
AM
19129+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
19130+{
19131+ IiMustWriteLock(inode);
19132+ au_ii(inode)->ii_vdir = vdir;
19133+}
1facf9fc 19134+
4a4d8108 19135+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 19136+{
4a4d8108 19137+ IiMustAnyLock(inode);
5afbbe0d 19138+ return au_hinode(au_ii(inode), bindex);
4a4d8108 19139+}
dece6358 19140+
4a4d8108 19141+/* ---------------------------------------------------------------------- */
1facf9fc 19142+
4a4d8108
AM
19143+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
19144+{
19145+ if (pin)
19146+ return pin->parent;
19147+ return NULL;
1facf9fc 19148+}
19149+
4a4d8108 19150+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
1facf9fc 19151+{
4a4d8108
AM
19152+ if (pin && pin->hdir)
19153+ return pin->hdir->hi_inode;
19154+ return NULL;
1308ab2a 19155+}
1facf9fc 19156+
4a4d8108
AM
19157+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
19158+{
19159+ if (pin)
19160+ return pin->hdir;
19161+ return NULL;
19162+}
1facf9fc 19163+
4a4d8108 19164+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
1308ab2a 19165+{
4a4d8108
AM
19166+ if (pin)
19167+ pin->dentry = dentry;
19168+}
1308ab2a 19169+
4a4d8108
AM
19170+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
19171+ unsigned char lflag)
19172+{
19173+ if (pin) {
7f207e10 19174+ if (lflag)
4a4d8108 19175+ au_fset_pin(pin->flags, DI_LOCKED);
7f207e10 19176+ else
4a4d8108 19177+ au_fclr_pin(pin->flags, DI_LOCKED);
1308ab2a 19178+ }
4a4d8108
AM
19179+}
19180+
7e9cd9fe 19181+#if 0 /* reserved */
4a4d8108
AM
19182+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
19183+{
19184+ if (pin) {
19185+ dput(pin->parent);
19186+ pin->parent = dget(parent);
1facf9fc 19187+ }
4a4d8108 19188+}
7e9cd9fe 19189+#endif
1facf9fc 19190+
4a4d8108
AM
19191+/* ---------------------------------------------------------------------- */
19192+
027c5e7a 19193+struct au_branch;
4a4d8108
AM
19194+#ifdef CONFIG_AUFS_HNOTIFY
19195+struct au_hnotify_op {
19196+ void (*ctl)(struct au_hinode *hinode, int do_set);
027c5e7a 19197+ int (*alloc)(struct au_hinode *hinode);
7eafdf33
AM
19198+
19199+ /*
42a736d3 19200+ * if it returns true, the caller should free hinode->hi_notify,
7eafdf33
AM
19201+ * otherwise ->free() frees it.
19202+ */
19203+ int (*free)(struct au_hinode *hinode,
19204+ struct au_hnotify *hn) __must_check;
4a4d8108
AM
19205+
19206+ void (*fin)(void);
19207+ int (*init)(void);
027c5e7a
AM
19208+
19209+ int (*reset_br)(unsigned int udba, struct au_branch *br, int perm);
19210+ void (*fin_br)(struct au_branch *br);
19211+ int (*init_br)(struct au_branch *br, int perm);
4a4d8108
AM
19212+};
19213+
19214+/* hnotify.c */
027c5e7a 19215+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode);
4a4d8108
AM
19216+void au_hn_free(struct au_hinode *hinode);
19217+void au_hn_ctl(struct au_hinode *hinode, int do_set);
19218+void au_hn_reset(struct inode *inode, unsigned int flags);
19219+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
fbc438ed 19220+ const struct qstr *h_child_qstr, struct inode *h_child_inode);
027c5e7a
AM
19221+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm);
19222+int au_hnotify_init_br(struct au_branch *br, int perm);
19223+void au_hnotify_fin_br(struct au_branch *br);
4a4d8108
AM
19224+int __init au_hnotify_init(void);
19225+void au_hnotify_fin(void);
19226+
7f207e10 19227+/* hfsnotify.c */
4a4d8108
AM
19228+extern const struct au_hnotify_op au_hnotify_op;
19229+
19230+static inline
19231+void au_hn_init(struct au_hinode *hinode)
19232+{
19233+ hinode->hi_notify = NULL;
1308ab2a 19234+}
19235+
53392da6
AM
19236+static inline struct au_hnotify *au_hn(struct au_hinode *hinode)
19237+{
19238+ return hinode->hi_notify;
19239+}
19240+
4a4d8108 19241+#else
c1595e42
JR
19242+AuStub(int, au_hn_alloc, return -EOPNOTSUPP,
19243+ struct au_hinode *hinode __maybe_unused,
19244+ struct inode *inode __maybe_unused)
19245+AuStub(struct au_hnotify *, au_hn, return NULL, struct au_hinode *hinode)
4a4d8108
AM
19246+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
19247+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
19248+ int do_set __maybe_unused)
19249+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
19250+ unsigned int flags __maybe_unused)
027c5e7a
AM
19251+AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused,
19252+ struct au_branch *br __maybe_unused,
19253+ int perm __maybe_unused)
19254+AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused,
19255+ int perm __maybe_unused)
19256+AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused)
4a4d8108
AM
19257+AuStubInt0(__init au_hnotify_init, void)
19258+AuStubVoid(au_hnotify_fin, void)
19259+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
19260+#endif /* CONFIG_AUFS_HNOTIFY */
19261+
19262+static inline void au_hn_suspend(struct au_hinode *hdir)
19263+{
19264+ au_hn_ctl(hdir, /*do_set*/0);
1308ab2a 19265+}
19266+
4a4d8108 19267+static inline void au_hn_resume(struct au_hinode *hdir)
1308ab2a 19268+{
4a4d8108
AM
19269+ au_hn_ctl(hdir, /*do_set*/1);
19270+}
1308ab2a 19271+
5afbbe0d 19272+static inline void au_hn_inode_lock(struct au_hinode *hdir)
4a4d8108 19273+{
febd17d6 19274+ inode_lock(hdir->hi_inode);
4a4d8108
AM
19275+ au_hn_suspend(hdir);
19276+}
dece6358 19277+
5afbbe0d 19278+static inline void au_hn_inode_lock_nested(struct au_hinode *hdir,
4a4d8108
AM
19279+ unsigned int sc __maybe_unused)
19280+{
febd17d6 19281+ inode_lock_nested(hdir->hi_inode, sc);
4a4d8108 19282+ au_hn_suspend(hdir);
1facf9fc 19283+}
1facf9fc 19284+
8b6a4947
AM
19285+#if 0 /* unused */
19286+#include "vfsub.h"
3c1bdaff
AM
19287+static inline void au_hn_inode_lock_shared_nested(struct au_hinode *hdir,
19288+ unsigned int sc)
19289+{
be118d29 19290+ inode_lock_shared_nested(hdir->hi_inode, sc);
3c1bdaff
AM
19291+ au_hn_suspend(hdir);
19292+}
8b6a4947 19293+#endif
3c1bdaff 19294+
5afbbe0d 19295+static inline void au_hn_inode_unlock(struct au_hinode *hdir)
4a4d8108
AM
19296+{
19297+ au_hn_resume(hdir);
febd17d6 19298+ inode_unlock(hdir->hi_inode);
4a4d8108
AM
19299+}
19300+
19301+#endif /* __KERNEL__ */
19302+#endif /* __AUFS_INODE_H__ */
7f207e10 19303diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
eca34b5c 19304--- /usr/share/empty/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 19305+++ linux/fs/aufs/ioctl.c 2021-05-02 20:15:14.673337458 +0200
062440b3 19306@@ -0,0 +1,220 @@
cd7a4cd9 19307+// SPDX-License-Identifier: GPL-2.0
4a4d8108 19308+/*
d58c55f2 19309+ * Copyright (C) 2005-2020 Junjiro R. Okajima
4a4d8108
AM
19310+ *
19311+ * This program, aufs is free software; you can redistribute it and/or modify
19312+ * it under the terms of the GNU General Public License as published by
19313+ * the Free Software Foundation; either version 2 of the License, or
19314+ * (at your option) any later version.
19315+ *
19316+ * This program is distributed in the hope that it will be useful,
19317+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19318+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19319+ * GNU General Public License for more details.
19320+ *
19321+ * You should have received a copy of the GNU General Public License
523b37e3 19322+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
19323+ */
19324+
19325+/*
19326+ * ioctl
19327+ * plink-management and readdir in userspace.
19328+ * assist the pathconf(3) wrapper library.
c2b27bf2 19329+ * move-down
076b876e 19330+ * File-based Hierarchical Storage Management.
4a4d8108
AM
19331+ */
19332+
c2b27bf2
AM
19333+#include <linux/compat.h>
19334+#include <linux/file.h>
4a4d8108
AM
19335+#include "aufs.h"
19336+
1e00d052 19337+static int au_wbr_fd(struct path *path, struct aufs_wbr_fd __user *arg)
4a4d8108
AM
19338+{
19339+ int err, fd;
5afbbe0d 19340+ aufs_bindex_t wbi, bindex, bbot;
4a4d8108
AM
19341+ struct file *h_file;
19342+ struct super_block *sb;
19343+ struct dentry *root;
1e00d052
AM
19344+ struct au_branch *br;
19345+ struct aufs_wbr_fd wbrfd = {
19346+ .oflags = au_dir_roflags,
19347+ .brid = -1
19348+ };
19349+ const int valid = O_RDONLY | O_NONBLOCK | O_LARGEFILE | O_DIRECTORY
19350+ | O_NOATIME | O_CLOEXEC;
4a4d8108 19351+
1e00d052
AM
19352+ AuDebugOn(wbrfd.oflags & ~valid);
19353+
19354+ if (arg) {
19355+ err = copy_from_user(&wbrfd, arg, sizeof(wbrfd));
19356+ if (unlikely(err)) {
19357+ err = -EFAULT;
19358+ goto out;
19359+ }
19360+
19361+ err = -EINVAL;
19362+ AuDbg("wbrfd{0%o, %d}\n", wbrfd.oflags, wbrfd.brid);
19363+ wbrfd.oflags |= au_dir_roflags;
19364+ AuDbg("0%o\n", wbrfd.oflags);
19365+ if (unlikely(wbrfd.oflags & ~valid))
19366+ goto out;
19367+ }
19368+
2000de60 19369+ fd = get_unused_fd_flags(0);
1e00d052
AM
19370+ err = fd;
19371+ if (unlikely(fd < 0))
4a4d8108 19372+ goto out;
4a4d8108 19373+
1e00d052 19374+ h_file = ERR_PTR(-EINVAL);
4a4d8108 19375+ wbi = 0;
1e00d052 19376+ br = NULL;
4a4d8108
AM
19377+ sb = path->dentry->d_sb;
19378+ root = sb->s_root;
19379+ aufs_read_lock(root, AuLock_IR);
5afbbe0d 19380+ bbot = au_sbbot(sb);
1e00d052
AM
19381+ if (wbrfd.brid >= 0) {
19382+ wbi = au_br_index(sb, wbrfd.brid);
5afbbe0d 19383+ if (unlikely(wbi < 0 || wbi > bbot))
1e00d052
AM
19384+ goto out_unlock;
19385+ }
19386+
19387+ h_file = ERR_PTR(-ENOENT);
19388+ br = au_sbr(sb, wbi);
19389+ if (!au_br_writable(br->br_perm)) {
19390+ if (arg)
19391+ goto out_unlock;
19392+
19393+ bindex = wbi + 1;
19394+ wbi = -1;
5afbbe0d 19395+ for (; bindex <= bbot; bindex++) {
1e00d052
AM
19396+ br = au_sbr(sb, bindex);
19397+ if (au_br_writable(br->br_perm)) {
4a4d8108 19398+ wbi = bindex;
1e00d052 19399+ br = au_sbr(sb, wbi);
4a4d8108
AM
19400+ break;
19401+ }
19402+ }
4a4d8108
AM
19403+ }
19404+ AuDbg("wbi %d\n", wbi);
1e00d052 19405+ if (wbi >= 0)
392086de
AM
19406+ h_file = au_h_open(root, wbi, wbrfd.oflags, NULL,
19407+ /*force_wr*/0);
1e00d052
AM
19408+
19409+out_unlock:
4a4d8108
AM
19410+ aufs_read_unlock(root, AuLock_IR);
19411+ err = PTR_ERR(h_file);
19412+ if (IS_ERR(h_file))
19413+ goto out_fd;
19414+
acd2b654 19415+ au_lcnt_dec(&br->br_nfiles); /* cf. au_h_open() */
4a4d8108
AM
19416+ fd_install(fd, h_file);
19417+ err = fd;
19418+ goto out; /* success */
19419+
4f0767ce 19420+out_fd:
4a4d8108 19421+ put_unused_fd(fd);
4f0767ce 19422+out:
1e00d052 19423+ AuTraceErr(err);
4a4d8108
AM
19424+ return err;
19425+}
19426+
19427+/* ---------------------------------------------------------------------- */
19428+
19429+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
19430+{
19431+ long err;
c1595e42 19432+ struct dentry *dentry;
4a4d8108
AM
19433+
19434+ switch (cmd) {
4a4d8108
AM
19435+ case AUFS_CTL_RDU:
19436+ case AUFS_CTL_RDU_INO:
19437+ err = au_rdu_ioctl(file, cmd, arg);
19438+ break;
19439+
19440+ case AUFS_CTL_WBR_FD:
1e00d052 19441+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
4a4d8108
AM
19442+ break;
19443+
027c5e7a
AM
19444+ case AUFS_CTL_IBUSY:
19445+ err = au_ibusy_ioctl(file, arg);
19446+ break;
19447+
076b876e
AM
19448+ case AUFS_CTL_BRINFO:
19449+ err = au_brinfo_ioctl(file, arg);
19450+ break;
19451+
19452+ case AUFS_CTL_FHSM_FD:
2000de60 19453+ dentry = file->f_path.dentry;
c1595e42
JR
19454+ if (IS_ROOT(dentry))
19455+ err = au_fhsm_fd(dentry->d_sb, arg);
19456+ else
19457+ err = -ENOTTY;
076b876e
AM
19458+ break;
19459+
4a4d8108
AM
19460+ default:
19461+ /* do not call the lower */
19462+ AuDbg("0x%x\n", cmd);
19463+ err = -ENOTTY;
19464+ }
19465+
19466+ AuTraceErr(err);
19467+ return err;
19468+}
19469+
19470+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
19471+{
19472+ long err;
19473+
19474+ switch (cmd) {
c2b27bf2 19475+ case AUFS_CTL_MVDOWN:
2000de60 19476+ err = au_mvdown(file->f_path.dentry, (void __user *)arg);
c2b27bf2
AM
19477+ break;
19478+
4a4d8108 19479+ case AUFS_CTL_WBR_FD:
1e00d052 19480+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
4a4d8108
AM
19481+ break;
19482+
19483+ default:
19484+ /* do not call the lower */
19485+ AuDbg("0x%x\n", cmd);
19486+ err = -ENOTTY;
19487+ }
19488+
19489+ AuTraceErr(err);
19490+ return err;
19491+}
b752ccd1
AM
19492+
19493+#ifdef CONFIG_COMPAT
19494+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
19495+ unsigned long arg)
19496+{
19497+ long err;
19498+
19499+ switch (cmd) {
19500+ case AUFS_CTL_RDU:
19501+ case AUFS_CTL_RDU_INO:
19502+ err = au_rdu_compat_ioctl(file, cmd, arg);
19503+ break;
19504+
027c5e7a
AM
19505+ case AUFS_CTL_IBUSY:
19506+ err = au_ibusy_compat_ioctl(file, arg);
19507+ break;
19508+
076b876e
AM
19509+ case AUFS_CTL_BRINFO:
19510+ err = au_brinfo_compat_ioctl(file, arg);
19511+ break;
19512+
b752ccd1
AM
19513+ default:
19514+ err = aufs_ioctl_dir(file, cmd, arg);
19515+ }
19516+
19517+ AuTraceErr(err);
19518+ return err;
19519+}
19520+
b752ccd1
AM
19521+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
19522+ unsigned long arg)
19523+{
19524+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
19525+}
19526+#endif
7f207e10 19527diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
eca34b5c 19528--- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6
JR
19529+++ linux/fs/aufs/i_op_add.c 2021-05-02 20:15:14.673337458 +0200
19530@@ -0,0 +1,941 @@
cd7a4cd9 19531+// SPDX-License-Identifier: GPL-2.0
4a4d8108 19532+/*
d58c55f2 19533+ * Copyright (C) 2005-2020 Junjiro R. Okajima
4a4d8108
AM
19534+ *
19535+ * This program, aufs is free software; you can redistribute it and/or modify
19536+ * it under the terms of the GNU General Public License as published by
19537+ * the Free Software Foundation; either version 2 of the License, or
19538+ * (at your option) any later version.
19539+ *
19540+ * This program is distributed in the hope that it will be useful,
19541+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19542+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19543+ * GNU General Public License for more details.
19544+ *
19545+ * You should have received a copy of the GNU General Public License
523b37e3 19546+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
19547+ */
19548+
19549+/*
19550+ * inode operations (add entry)
19551+ */
19552+
eca801bf 19553+#include <linux/iversion.h>
4a4d8108
AM
19554+#include "aufs.h"
19555+
19556+/*
19557+ * final procedure of adding a new entry, except link(2).
19558+ * remove whiteout, instantiate, copyup the parent dir's times and size
19559+ * and update version.
19560+ * if it failed, re-create the removed whiteout.
19561+ */
19562+static int epilog(struct inode *dir, aufs_bindex_t bindex,
19563+ struct dentry *wh_dentry, struct dentry *dentry)
19564+{
19565+ int err, rerr;
19566+ aufs_bindex_t bwh;
19567+ struct path h_path;
076b876e 19568+ struct super_block *sb;
4a4d8108
AM
19569+ struct inode *inode, *h_dir;
19570+ struct dentry *wh;
19571+
19572+ bwh = -1;
076b876e 19573+ sb = dir->i_sb;
4a4d8108 19574+ if (wh_dentry) {
5527c038 19575+ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */
4a4d8108
AM
19576+ IMustLock(h_dir);
19577+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
19578+ bwh = au_dbwh(dentry);
19579+ h_path.dentry = wh_dentry;
076b876e 19580+ h_path.mnt = au_sbr_mnt(sb, bindex);
4a4d8108
AM
19581+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
19582+ dentry);
19583+ if (unlikely(err))
19584+ goto out;
19585+ }
19586+
19587+ inode = au_new_inode(dentry, /*must_new*/1);
19588+ if (!IS_ERR(inode)) {
19589+ d_instantiate(dentry, inode);
5527c038 19590+ dir = d_inode(dentry->d_parent); /* dir inode is locked */
4a4d8108 19591+ IMustLock(dir);
b912730e 19592+ au_dir_ts(dir, bindex);
be118d29 19593+ inode_inc_iversion(dir);
076b876e 19594+ au_fhsm_wrote(sb, bindex, /*force*/0);
4a4d8108
AM
19595+ return 0; /* success */
19596+ }
19597+
19598+ err = PTR_ERR(inode);
19599+ if (!wh_dentry)
19600+ goto out;
19601+
19602+ /* revert */
19603+ /* dir inode is locked */
19604+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
19605+ rerr = PTR_ERR(wh);
19606+ if (IS_ERR(wh)) {
523b37e3
AM
19607+ AuIOErr("%pd reverting whiteout failed(%d, %d)\n",
19608+ dentry, err, rerr);
4a4d8108
AM
19609+ err = -EIO;
19610+ } else
19611+ dput(wh);
19612+
4f0767ce 19613+out:
4a4d8108
AM
19614+ return err;
19615+}
19616+
027c5e7a
AM
19617+static int au_d_may_add(struct dentry *dentry)
19618+{
19619+ int err;
19620+
19621+ err = 0;
19622+ if (unlikely(d_unhashed(dentry)))
19623+ err = -ENOENT;
5527c038 19624+ if (unlikely(d_really_is_positive(dentry)))
027c5e7a
AM
19625+ err = -EEXIST;
19626+ return err;
19627+}
19628+
4a4d8108
AM
19629+/*
19630+ * simple tests for the adding inode operations.
19631+ * following the checks in vfs, plus the parent-child relationship.
19632+ */
19633+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
19634+ struct dentry *h_parent, int isdir)
19635+{
19636+ int err;
19637+ umode_t h_mode;
19638+ struct dentry *h_dentry;
19639+ struct inode *h_inode;
19640+
19641+ err = -ENAMETOOLONG;
19642+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
19643+ goto out;
19644+
19645+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 19646+ if (d_really_is_negative(dentry)) {
4a4d8108 19647+ err = -EEXIST;
5527c038 19648+ if (unlikely(d_is_positive(h_dentry)))
4a4d8108
AM
19649+ goto out;
19650+ } else {
19651+ /* rename(2) case */
19652+ err = -EIO;
5527c038
JR
19653+ if (unlikely(d_is_negative(h_dentry)))
19654+ goto out;
19655+ h_inode = d_inode(h_dentry);
19656+ if (unlikely(!h_inode->i_nlink))
4a4d8108
AM
19657+ goto out;
19658+
19659+ h_mode = h_inode->i_mode;
19660+ if (!isdir) {
19661+ err = -EISDIR;
19662+ if (unlikely(S_ISDIR(h_mode)))
19663+ goto out;
19664+ } else if (unlikely(!S_ISDIR(h_mode))) {
19665+ err = -ENOTDIR;
19666+ goto out;
19667+ }
19668+ }
19669+
19670+ err = 0;
19671+ /* expected parent dir is locked */
19672+ if (unlikely(h_parent != h_dentry->d_parent))
19673+ err = -EIO;
19674+
4f0767ce 19675+out:
4a4d8108
AM
19676+ AuTraceErr(err);
19677+ return err;
19678+}
19679+
19680+/*
19681+ * initial procedure of adding a new entry.
19682+ * prepare writable branch and the parent dir, lock it,
19683+ * and lookup whiteout for the new entry.
19684+ */
19685+static struct dentry*
19686+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
19687+ struct dentry *src_dentry, struct au_pin *pin,
19688+ struct au_wr_dir_args *wr_dir_args)
19689+{
19690+ struct dentry *wh_dentry, *h_parent;
19691+ struct super_block *sb;
19692+ struct au_branch *br;
19693+ int err;
19694+ unsigned int udba;
19695+ aufs_bindex_t bcpup;
19696+
523b37e3 19697+ AuDbg("%pd\n", dentry);
4a4d8108
AM
19698+
19699+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
19700+ bcpup = err;
19701+ wh_dentry = ERR_PTR(err);
19702+ if (unlikely(err < 0))
19703+ goto out;
19704+
19705+ sb = dentry->d_sb;
19706+ udba = au_opt_udba(sb);
19707+ err = au_pin(pin, dentry, bcpup, udba,
19708+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
19709+ wh_dentry = ERR_PTR(err);
19710+ if (unlikely(err))
19711+ goto out;
19712+
19713+ h_parent = au_pinned_h_parent(pin);
19714+ if (udba != AuOpt_UDBA_NONE
5afbbe0d 19715+ && au_dbtop(dentry) == bcpup)
4a4d8108
AM
19716+ err = au_may_add(dentry, bcpup, h_parent,
19717+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
19718+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
19719+ err = -ENAMETOOLONG;
19720+ wh_dentry = ERR_PTR(err);
19721+ if (unlikely(err))
19722+ goto out_unpin;
19723+
19724+ br = au_sbr(sb, bcpup);
19725+ if (dt) {
19726+ struct path tmp = {
19727+ .dentry = h_parent,
86dc4139 19728+ .mnt = au_br_mnt(br)
4a4d8108
AM
19729+ };
19730+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
19731+ }
19732+
19733+ wh_dentry = NULL;
19734+ if (bcpup != au_dbwh(dentry))
19735+ goto out; /* success */
19736+
2000de60
JR
19737+ /*
19738+ * ENAMETOOLONG here means that if we allowed create such name, then it
19739+ * would not be able to removed in the future. So we don't allow such
19740+ * name here and we don't handle ENAMETOOLONG differently here.
19741+ */
4a4d8108
AM
19742+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
19743+
4f0767ce 19744+out_unpin:
4a4d8108
AM
19745+ if (IS_ERR(wh_dentry))
19746+ au_unpin(pin);
4f0767ce 19747+out:
4a4d8108
AM
19748+ return wh_dentry;
19749+}
19750+
19751+/* ---------------------------------------------------------------------- */
19752+
19753+enum { Mknod, Symlink, Creat };
19754+struct simple_arg {
19755+ int type;
19756+ union {
19757+ struct {
b912730e
AM
19758+ umode_t mode;
19759+ bool want_excl;
19760+ bool try_aopen;
19761+ struct vfsub_aopen_args *aopen;
4a4d8108
AM
19762+ } c;
19763+ struct {
19764+ const char *symname;
19765+ } s;
19766+ struct {
7eafdf33 19767+ umode_t mode;
4a4d8108
AM
19768+ dev_t dev;
19769+ } m;
19770+ } u;
19771+};
19772+
19773+static int add_simple(struct inode *dir, struct dentry *dentry,
19774+ struct simple_arg *arg)
19775+{
076b876e 19776+ int err, rerr;
5afbbe0d 19777+ aufs_bindex_t btop;
4a4d8108 19778+ unsigned char created;
b912730e
AM
19779+ const unsigned char try_aopen
19780+ = (arg->type == Creat && arg->u.c.try_aopen);
acd2b654 19781+ struct vfsub_aopen_args *aopen = arg->u.c.aopen;
4a4d8108
AM
19782+ struct dentry *wh_dentry, *parent;
19783+ struct inode *h_dir;
b912730e
AM
19784+ struct super_block *sb;
19785+ struct au_branch *br;
acd2b654 19786+ /* to reduce stack size */
c2b27bf2
AM
19787+ struct {
19788+ struct au_dtime dt;
19789+ struct au_pin pin;
19790+ struct path h_path;
19791+ struct au_wr_dir_args wr_dir_args;
19792+ } *a;
4a4d8108 19793+
523b37e3 19794+ AuDbg("%pd\n", dentry);
4a4d8108
AM
19795+ IMustLock(dir);
19796+
c2b27bf2
AM
19797+ err = -ENOMEM;
19798+ a = kmalloc(sizeof(*a), GFP_NOFS);
19799+ if (unlikely(!a))
19800+ goto out;
19801+ a->wr_dir_args.force_btgt = -1;
19802+ a->wr_dir_args.flags = AuWrDir_ADD_ENTRY;
19803+
4a4d8108 19804+ parent = dentry->d_parent; /* dir inode is locked */
b912730e
AM
19805+ if (!try_aopen) {
19806+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
19807+ if (unlikely(err))
19808+ goto out_free;
19809+ }
027c5e7a
AM
19810+ err = au_d_may_add(dentry);
19811+ if (unlikely(err))
19812+ goto out_unlock;
b912730e
AM
19813+ if (!try_aopen)
19814+ di_write_lock_parent(parent);
c2b27bf2
AM
19815+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
19816+ &a->pin, &a->wr_dir_args);
4a4d8108
AM
19817+ err = PTR_ERR(wh_dentry);
19818+ if (IS_ERR(wh_dentry))
027c5e7a 19819+ goto out_parent;
4a4d8108 19820+
5afbbe0d 19821+ btop = au_dbtop(dentry);
b912730e 19822+ sb = dentry->d_sb;
5afbbe0d
AM
19823+ br = au_sbr(sb, btop);
19824+ a->h_path.dentry = au_h_dptr(dentry, btop);
b912730e 19825+ a->h_path.mnt = au_br_mnt(br);
c2b27bf2 19826+ h_dir = au_pinned_h_dir(&a->pin);
4a4d8108
AM
19827+ switch (arg->type) {
19828+ case Creat:
acd2b654 19829+ if (!try_aopen || !h_dir->i_op->atomic_open) {
b912730e
AM
19830+ err = vfsub_create(h_dir, &a->h_path, arg->u.c.mode,
19831+ arg->u.c.want_excl);
acd2b654
AM
19832+ created = !err;
19833+ if (!err && try_aopen)
19834+ aopen->file->f_mode |= FMODE_CREATED;
19835+ } else {
19836+ aopen->br = br;
19837+ err = vfsub_atomic_open(h_dir, a->h_path.dentry, aopen);
19838+ AuDbg("err %d\n", err);
19839+ AuDbgFile(aopen->file);
19840+ created = err >= 0
19841+ && !!(aopen->file->f_mode & FMODE_CREATED);
19842+ }
4a4d8108
AM
19843+ break;
19844+ case Symlink:
c2b27bf2 19845+ err = vfsub_symlink(h_dir, &a->h_path, arg->u.s.symname);
acd2b654 19846+ created = !err;
4a4d8108
AM
19847+ break;
19848+ case Mknod:
c2b27bf2
AM
19849+ err = vfsub_mknod(h_dir, &a->h_path, arg->u.m.mode,
19850+ arg->u.m.dev);
acd2b654 19851+ created = !err;
4a4d8108
AM
19852+ break;
19853+ default:
19854+ BUG();
19855+ }
acd2b654
AM
19856+ if (unlikely(err < 0))
19857+ goto out_unpin;
19858+
19859+ err = epilog(dir, btop, wh_dentry, dentry);
4a4d8108 19860+ if (!err)
acd2b654 19861+ goto out_unpin; /* success */
4a4d8108
AM
19862+
19863+ /* revert */
acd2b654 19864+ if (created /* && d_is_positive(a->h_path.dentry) */) {
523b37e3
AM
19865+ /* no delegation since it is just created */
19866+ rerr = vfsub_unlink(h_dir, &a->h_path, /*delegated*/NULL,
19867+ /*force*/0);
4a4d8108 19868+ if (rerr) {
523b37e3
AM
19869+ AuIOErr("%pd revert failure(%d, %d)\n",
19870+ dentry, err, rerr);
4a4d8108
AM
19871+ err = -EIO;
19872+ }
c2b27bf2 19873+ au_dtime_revert(&a->dt);
4a4d8108 19874+ }
acd2b654
AM
19875+ if (try_aopen && h_dir->i_op->atomic_open
19876+ && (aopen->file->f_mode & FMODE_OPENED))
19877+ /* aopen->file is still opened */
19878+ au_lcnt_dec(&aopen->br->br_nfiles);
4a4d8108 19879+
acd2b654 19880+out_unpin:
c2b27bf2 19881+ au_unpin(&a->pin);
4a4d8108 19882+ dput(wh_dentry);
027c5e7a 19883+out_parent:
b912730e
AM
19884+ if (!try_aopen)
19885+ di_write_unlock(parent);
027c5e7a 19886+out_unlock:
4a4d8108 19887+ if (unlikely(err)) {
5afbbe0d 19888+ au_update_dbtop(dentry);
4a4d8108
AM
19889+ d_drop(dentry);
19890+ }
b912730e
AM
19891+ if (!try_aopen)
19892+ aufs_read_unlock(dentry, AuLock_DW);
c2b27bf2 19893+out_free:
9f237c51 19894+ au_kfree_rcu(a);
027c5e7a 19895+out:
4a4d8108
AM
19896+ return err;
19897+}
19898+
0b2a12c6
JR
19899+int aufs_mknod(struct user_namespace *userns, struct inode *dir,
19900+ struct dentry *dentry, umode_t mode, dev_t dev)
4a4d8108
AM
19901+{
19902+ struct simple_arg arg = {
19903+ .type = Mknod,
19904+ .u.m = {
19905+ .mode = mode,
19906+ .dev = dev
19907+ }
19908+ };
19909+ return add_simple(dir, dentry, &arg);
19910+}
19911+
0b2a12c6
JR
19912+int aufs_symlink(struct user_namespace *userns, struct inode *dir,
19913+ struct dentry *dentry, const char *symname)
4a4d8108
AM
19914+{
19915+ struct simple_arg arg = {
19916+ .type = Symlink,
19917+ .u.s.symname = symname
19918+ };
19919+ return add_simple(dir, dentry, &arg);
19920+}
19921+
0b2a12c6
JR
19922+int aufs_create(struct user_namespace *userns, struct inode *dir,
19923+ struct dentry *dentry, umode_t mode, bool want_excl)
4a4d8108
AM
19924+{
19925+ struct simple_arg arg = {
19926+ .type = Creat,
19927+ .u.c = {
b4510431
AM
19928+ .mode = mode,
19929+ .want_excl = want_excl
4a4d8108
AM
19930+ }
19931+ };
19932+ return add_simple(dir, dentry, &arg);
19933+}
19934+
b912730e
AM
19935+int au_aopen_or_create(struct inode *dir, struct dentry *dentry,
19936+ struct vfsub_aopen_args *aopen_args)
19937+{
19938+ struct simple_arg arg = {
19939+ .type = Creat,
19940+ .u.c = {
19941+ .mode = aopen_args->create_mode,
19942+ .want_excl = aopen_args->open_flag & O_EXCL,
19943+ .try_aopen = true,
19944+ .aopen = aopen_args
19945+ }
19946+ };
19947+ return add_simple(dir, dentry, &arg);
19948+}
19949+
0b2a12c6
JR
19950+int aufs_tmpfile(struct user_namespace *userns, struct inode *dir,
19951+ struct dentry *dentry, umode_t mode)
38d290e6
JR
19952+{
19953+ int err;
19954+ aufs_bindex_t bindex;
19955+ struct super_block *sb;
19956+ struct dentry *parent, *h_parent, *h_dentry;
19957+ struct inode *h_dir, *inode;
19958+ struct vfsmount *h_mnt;
0b2a12c6 19959+ struct user_namespace *h_userns;
38d290e6
JR
19960+ struct au_wr_dir_args wr_dir_args = {
19961+ .force_btgt = -1,
19962+ .flags = AuWrDir_TMPFILE
19963+ };
19964+
19965+ /* copy-up may happen */
febd17d6 19966+ inode_lock(dir);
38d290e6
JR
19967+
19968+ sb = dir->i_sb;
19969+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
19970+ if (unlikely(err))
19971+ goto out;
19972+
19973+ err = au_di_init(dentry);
19974+ if (unlikely(err))
19975+ goto out_si;
19976+
19977+ err = -EBUSY;
19978+ parent = d_find_any_alias(dir);
19979+ AuDebugOn(!parent);
19980+ di_write_lock_parent(parent);
5527c038 19981+ if (unlikely(d_inode(parent) != dir))
38d290e6
JR
19982+ goto out_parent;
19983+
19984+ err = au_digen_test(parent, au_sigen(sb));
19985+ if (unlikely(err))
19986+ goto out_parent;
19987+
5afbbe0d
AM
19988+ bindex = au_dbtop(parent);
19989+ au_set_dbtop(dentry, bindex);
19990+ au_set_dbbot(dentry, bindex);
38d290e6
JR
19991+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
19992+ bindex = err;
19993+ if (unlikely(err < 0))
19994+ goto out_parent;
19995+
19996+ err = -EOPNOTSUPP;
19997+ h_dir = au_h_iptr(dir, bindex);
19998+ if (unlikely(!h_dir->i_op->tmpfile))
19999+ goto out_parent;
20000+
20001+ h_mnt = au_sbr_mnt(sb, bindex);
20002+ err = vfsub_mnt_want_write(h_mnt);
20003+ if (unlikely(err))
20004+ goto out_parent;
20005+
0b2a12c6 20006+ h_userns = mnt_user_ns(h_mnt);
38d290e6 20007+ h_parent = au_h_dptr(parent, bindex);
0b2a12c6 20008+ h_dentry = vfs_tmpfile(h_userns, h_parent, mode, /*open_flag*/0);
521ced18
JR
20009+ if (IS_ERR(h_dentry)) {
20010+ err = PTR_ERR(h_dentry);
38d290e6 20011+ goto out_mnt;
521ced18 20012+ }
38d290e6 20013+
5afbbe0d
AM
20014+ au_set_dbtop(dentry, bindex);
20015+ au_set_dbbot(dentry, bindex);
38d290e6
JR
20016+ au_set_h_dptr(dentry, bindex, dget(h_dentry));
20017+ inode = au_new_inode(dentry, /*must_new*/1);
20018+ if (IS_ERR(inode)) {
20019+ err = PTR_ERR(inode);
20020+ au_set_h_dptr(dentry, bindex, NULL);
5afbbe0d
AM
20021+ au_set_dbtop(dentry, -1);
20022+ au_set_dbbot(dentry, -1);
38d290e6
JR
20023+ } else {
20024+ if (!inode->i_nlink)
20025+ set_nlink(inode, 1);
20026+ d_tmpfile(dentry, inode);
20027+ au_di(dentry)->di_tmpfile = 1;
20028+
20029+ /* update without i_mutex */
5afbbe0d 20030+ if (au_ibtop(dir) == au_dbtop(dentry))
38d290e6
JR
20031+ au_cpup_attr_timesizes(dir);
20032+ }
38d290e6 20033+ dput(h_dentry);
521ced18 20034+
38d290e6
JR
20035+out_mnt:
20036+ vfsub_mnt_drop_write(h_mnt);
20037+out_parent:
20038+ di_write_unlock(parent);
20039+ dput(parent);
20040+ di_write_unlock(dentry);
5afbbe0d 20041+ if (unlikely(err)) {
38d290e6
JR
20042+ au_di_fin(dentry);
20043+ dentry->d_fsdata = NULL;
20044+ }
20045+out_si:
20046+ si_read_unlock(sb);
20047+out:
febd17d6 20048+ inode_unlock(dir);
38d290e6
JR
20049+ return err;
20050+}
20051+
4a4d8108
AM
20052+/* ---------------------------------------------------------------------- */
20053+
20054+struct au_link_args {
20055+ aufs_bindex_t bdst, bsrc;
20056+ struct au_pin pin;
20057+ struct path h_path;
20058+ struct dentry *src_parent, *parent;
20059+};
20060+
20061+static int au_cpup_before_link(struct dentry *src_dentry,
20062+ struct au_link_args *a)
20063+{
20064+ int err;
20065+ struct dentry *h_src_dentry;
c2b27bf2
AM
20066+ struct au_cp_generic cpg = {
20067+ .dentry = src_dentry,
20068+ .bdst = a->bdst,
20069+ .bsrc = a->bsrc,
20070+ .len = -1,
20071+ .pin = &a->pin,
20072+ .flags = AuCpup_DTIME | AuCpup_HOPEN /* | AuCpup_KEEPLINO */
20073+ };
4a4d8108
AM
20074+
20075+ di_read_lock_parent(a->src_parent, AuLock_IR);
20076+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
20077+ if (unlikely(err))
20078+ goto out;
20079+
20080+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
4a4d8108
AM
20081+ err = au_pin(&a->pin, src_dentry, a->bdst,
20082+ au_opt_udba(src_dentry->d_sb),
20083+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
20084+ if (unlikely(err))
20085+ goto out;
367653fa 20086+
c2b27bf2 20087+ err = au_sio_cpup_simple(&cpg);
4a4d8108
AM
20088+ au_unpin(&a->pin);
20089+
4f0767ce 20090+out:
4a4d8108
AM
20091+ di_read_unlock(a->src_parent, AuLock_IR);
20092+ return err;
20093+}
20094+
86dc4139
AM
20095+static int au_cpup_or_link(struct dentry *src_dentry, struct dentry *dentry,
20096+ struct au_link_args *a)
4a4d8108
AM
20097+{
20098+ int err;
20099+ unsigned char plink;
5afbbe0d 20100+ aufs_bindex_t bbot;
4a4d8108 20101+ struct dentry *h_src_dentry;
523b37e3 20102+ struct inode *h_inode, *inode, *delegated;
4a4d8108
AM
20103+ struct super_block *sb;
20104+ struct file *h_file;
20105+
20106+ plink = 0;
20107+ h_inode = NULL;
20108+ sb = src_dentry->d_sb;
5527c038 20109+ inode = d_inode(src_dentry);
5afbbe0d 20110+ if (au_ibtop(inode) <= a->bdst)
4a4d8108
AM
20111+ h_inode = au_h_iptr(inode, a->bdst);
20112+ if (!h_inode || !h_inode->i_nlink) {
20113+ /* copyup src_dentry as the name of dentry. */
5afbbe0d
AM
20114+ bbot = au_dbbot(dentry);
20115+ if (bbot < a->bsrc)
20116+ au_set_dbbot(dentry, a->bsrc);
86dc4139
AM
20117+ au_set_h_dptr(dentry, a->bsrc,
20118+ dget(au_h_dptr(src_dentry, a->bsrc)));
20119+ dget(a->h_path.dentry);
20120+ au_set_h_dptr(dentry, a->bdst, NULL);
c1595e42
JR
20121+ AuDbg("temporary d_inode...\n");
20122+ spin_lock(&dentry->d_lock);
5527c038 20123+ dentry->d_inode = d_inode(src_dentry); /* tmp */
c1595e42 20124+ spin_unlock(&dentry->d_lock);
392086de 20125+ h_file = au_h_open_pre(dentry, a->bsrc, /*force_wr*/0);
86dc4139 20126+ if (IS_ERR(h_file))
4a4d8108 20127+ err = PTR_ERR(h_file);
86dc4139 20128+ else {
c2b27bf2
AM
20129+ struct au_cp_generic cpg = {
20130+ .dentry = dentry,
20131+ .bdst = a->bdst,
20132+ .bsrc = -1,
20133+ .len = -1,
20134+ .pin = &a->pin,
20135+ .flags = AuCpup_KEEPLINO
20136+ };
20137+ err = au_sio_cpup_simple(&cpg);
86dc4139
AM
20138+ au_h_open_post(dentry, a->bsrc, h_file);
20139+ if (!err) {
20140+ dput(a->h_path.dentry);
20141+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
20142+ } else
20143+ au_set_h_dptr(dentry, a->bdst,
20144+ a->h_path.dentry);
20145+ }
c1595e42 20146+ spin_lock(&dentry->d_lock);
86dc4139 20147+ dentry->d_inode = NULL; /* restore */
c1595e42
JR
20148+ spin_unlock(&dentry->d_lock);
20149+ AuDbg("temporary d_inode...done\n");
86dc4139 20150+ au_set_h_dptr(dentry, a->bsrc, NULL);
5afbbe0d 20151+ au_set_dbbot(dentry, bbot);
4a4d8108
AM
20152+ } else {
20153+ /* the inode of src_dentry already exists on a.bdst branch */
20154+ h_src_dentry = d_find_alias(h_inode);
20155+ if (!h_src_dentry && au_plink_test(inode)) {
20156+ plink = 1;
20157+ h_src_dentry = au_plink_lkup(inode, a->bdst);
20158+ err = PTR_ERR(h_src_dentry);
20159+ if (IS_ERR(h_src_dentry))
20160+ goto out;
20161+
5527c038 20162+ if (unlikely(d_is_negative(h_src_dentry))) {
4a4d8108
AM
20163+ dput(h_src_dentry);
20164+ h_src_dentry = NULL;
20165+ }
20166+
20167+ }
20168+ if (h_src_dentry) {
523b37e3 20169+ delegated = NULL;
4a4d8108 20170+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
523b37e3
AM
20171+ &a->h_path, &delegated);
20172+ if (unlikely(err == -EWOULDBLOCK)) {
20173+ pr_warn("cannot retry for NFSv4 delegation"
20174+ " for an internal link\n");
20175+ iput(delegated);
20176+ }
4a4d8108
AM
20177+ dput(h_src_dentry);
20178+ } else {
20179+ AuIOErr("no dentry found for hi%lu on b%d\n",
20180+ h_inode->i_ino, a->bdst);
20181+ err = -EIO;
20182+ }
20183+ }
20184+
20185+ if (!err && !plink)
20186+ au_plink_append(inode, a->bdst, a->h_path.dentry);
20187+
20188+out:
2cbb1c4b 20189+ AuTraceErr(err);
4a4d8108
AM
20190+ return err;
20191+}
20192+
20193+int aufs_link(struct dentry *src_dentry, struct inode *dir,
20194+ struct dentry *dentry)
20195+{
20196+ int err, rerr;
20197+ struct au_dtime dt;
20198+ struct au_link_args *a;
20199+ struct dentry *wh_dentry, *h_src_dentry;
523b37e3 20200+ struct inode *inode, *delegated;
4a4d8108
AM
20201+ struct super_block *sb;
20202+ struct au_wr_dir_args wr_dir_args = {
20203+ /* .force_btgt = -1, */
20204+ .flags = AuWrDir_ADD_ENTRY
20205+ };
20206+
20207+ IMustLock(dir);
5527c038 20208+ inode = d_inode(src_dentry);
4a4d8108
AM
20209+ IMustLock(inode);
20210+
4a4d8108
AM
20211+ err = -ENOMEM;
20212+ a = kzalloc(sizeof(*a), GFP_NOFS);
20213+ if (unlikely(!a))
20214+ goto out;
20215+
20216+ a->parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
20217+ err = aufs_read_and_write_lock2(dentry, src_dentry,
20218+ AuLock_NOPLM | AuLock_GEN);
e49829fe
JR
20219+ if (unlikely(err))
20220+ goto out_kfree;
38d290e6 20221+ err = au_d_linkable(src_dentry);
027c5e7a
AM
20222+ if (unlikely(err))
20223+ goto out_unlock;
20224+ err = au_d_may_add(dentry);
20225+ if (unlikely(err))
20226+ goto out_unlock;
e49829fe 20227+
4a4d8108 20228+ a->src_parent = dget_parent(src_dentry);
5afbbe0d 20229+ wr_dir_args.force_btgt = au_ibtop(inode);
4a4d8108
AM
20230+
20231+ di_write_lock_parent(a->parent);
20232+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
20233+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
20234+ &wr_dir_args);
20235+ err = PTR_ERR(wh_dentry);
20236+ if (IS_ERR(wh_dentry))
027c5e7a 20237+ goto out_parent;
4a4d8108
AM
20238+
20239+ err = 0;
20240+ sb = dentry->d_sb;
5afbbe0d 20241+ a->bdst = au_dbtop(dentry);
4a4d8108
AM
20242+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
20243+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
5afbbe0d 20244+ a->bsrc = au_ibtop(inode);
2cbb1c4b 20245+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
38d290e6
JR
20246+ if (!h_src_dentry && au_di(src_dentry)->di_tmpfile)
20247+ h_src_dentry = dget(au_hi_wh(inode, a->bsrc));
2cbb1c4b 20248+ if (!h_src_dentry) {
5afbbe0d 20249+ a->bsrc = au_dbtop(src_dentry);
2cbb1c4b
JR
20250+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
20251+ AuDebugOn(!h_src_dentry);
38d290e6
JR
20252+ } else if (IS_ERR(h_src_dentry)) {
20253+ err = PTR_ERR(h_src_dentry);
2cbb1c4b 20254+ goto out_parent;
38d290e6 20255+ }
2cbb1c4b 20256+
f2c43d5f
AM
20257+ /*
20258+ * aufs doesn't touch the credential so
acd2b654 20259+ * security_dentry_create_files_as() is unnecessary.
f2c43d5f 20260+ */
4a4d8108
AM
20261+ if (au_opt_test(au_mntflags(sb), PLINK)) {
20262+ if (a->bdst < a->bsrc
20263+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
86dc4139 20264+ err = au_cpup_or_link(src_dentry, dentry, a);
523b37e3
AM
20265+ else {
20266+ delegated = NULL;
4a4d8108 20267+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
523b37e3
AM
20268+ &a->h_path, &delegated);
20269+ if (unlikely(err == -EWOULDBLOCK)) {
20270+ pr_warn("cannot retry for NFSv4 delegation"
20271+ " for an internal link\n");
20272+ iput(delegated);
20273+ }
20274+ }
2cbb1c4b 20275+ dput(h_src_dentry);
4a4d8108
AM
20276+ } else {
20277+ /*
20278+ * copyup src_dentry to the branch we process,
20279+ * and then link(2) to it.
20280+ */
2cbb1c4b 20281+ dput(h_src_dentry);
4a4d8108
AM
20282+ if (a->bdst < a->bsrc
20283+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
20284+ au_unpin(&a->pin);
20285+ di_write_unlock(a->parent);
20286+ err = au_cpup_before_link(src_dentry, a);
20287+ di_write_lock_parent(a->parent);
20288+ if (!err)
20289+ err = au_pin(&a->pin, dentry, a->bdst,
20290+ au_opt_udba(sb),
20291+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
20292+ if (unlikely(err))
20293+ goto out_wh;
20294+ }
20295+ if (!err) {
20296+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
20297+ err = -ENOENT;
5527c038 20298+ if (h_src_dentry && d_is_positive(h_src_dentry)) {
523b37e3 20299+ delegated = NULL;
4a4d8108
AM
20300+ err = vfsub_link(h_src_dentry,
20301+ au_pinned_h_dir(&a->pin),
523b37e3
AM
20302+ &a->h_path, &delegated);
20303+ if (unlikely(err == -EWOULDBLOCK)) {
20304+ pr_warn("cannot retry"
20305+ " for NFSv4 delegation"
20306+ " for an internal link\n");
20307+ iput(delegated);
20308+ }
20309+ }
4a4d8108
AM
20310+ }
20311+ }
20312+ if (unlikely(err))
20313+ goto out_unpin;
20314+
20315+ if (wh_dentry) {
20316+ a->h_path.dentry = wh_dentry;
20317+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
20318+ dentry);
20319+ if (unlikely(err))
20320+ goto out_revert;
20321+ }
20322+
b912730e 20323+ au_dir_ts(dir, a->bdst);
be118d29 20324+ inode_inc_iversion(dir);
4a4d8108
AM
20325+ inc_nlink(inode);
20326+ inode->i_ctime = dir->i_ctime;
027c5e7a
AM
20327+ d_instantiate(dentry, au_igrab(inode));
20328+ if (d_unhashed(a->h_path.dentry))
4a4d8108
AM
20329+ /* some filesystem calls d_drop() */
20330+ d_drop(dentry);
076b876e
AM
20331+ /* some filesystems consume an inode even hardlink */
20332+ au_fhsm_wrote(sb, a->bdst, /*force*/0);
4a4d8108
AM
20333+ goto out_unpin; /* success */
20334+
4f0767ce 20335+out_revert:
523b37e3
AM
20336+ /* no delegation since it is just created */
20337+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path,
20338+ /*delegated*/NULL, /*force*/0);
027c5e7a 20339+ if (unlikely(rerr)) {
523b37e3 20340+ AuIOErr("%pd reverting failed(%d, %d)\n", dentry, err, rerr);
027c5e7a
AM
20341+ err = -EIO;
20342+ }
4a4d8108 20343+ au_dtime_revert(&dt);
4f0767ce 20344+out_unpin:
4a4d8108 20345+ au_unpin(&a->pin);
4f0767ce 20346+out_wh:
4a4d8108 20347+ dput(wh_dentry);
027c5e7a
AM
20348+out_parent:
20349+ di_write_unlock(a->parent);
20350+ dput(a->src_parent);
4f0767ce 20351+out_unlock:
4a4d8108 20352+ if (unlikely(err)) {
5afbbe0d 20353+ au_update_dbtop(dentry);
4a4d8108
AM
20354+ d_drop(dentry);
20355+ }
4a4d8108 20356+ aufs_read_and_write_unlock2(dentry, src_dentry);
e49829fe 20357+out_kfree:
9f237c51 20358+ au_kfree_rcu(a);
4f0767ce 20359+out:
86dc4139 20360+ AuTraceErr(err);
4a4d8108
AM
20361+ return err;
20362+}
20363+
0b2a12c6
JR
20364+int aufs_mkdir(struct user_namespace *userns, struct inode *dir,
20365+ struct dentry *dentry, umode_t mode)
4a4d8108
AM
20366+{
20367+ int err, rerr;
20368+ aufs_bindex_t bindex;
20369+ unsigned char diropq;
20370+ struct path h_path;
20371+ struct dentry *wh_dentry, *parent, *opq_dentry;
febd17d6 20372+ struct inode *h_inode;
4a4d8108
AM
20373+ struct super_block *sb;
20374+ struct {
20375+ struct au_pin pin;
20376+ struct au_dtime dt;
20377+ } *a; /* reduce the stack usage */
20378+ struct au_wr_dir_args wr_dir_args = {
20379+ .force_btgt = -1,
20380+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
20381+ };
20382+
20383+ IMustLock(dir);
20384+
20385+ err = -ENOMEM;
20386+ a = kmalloc(sizeof(*a), GFP_NOFS);
20387+ if (unlikely(!a))
20388+ goto out;
20389+
027c5e7a
AM
20390+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
20391+ if (unlikely(err))
20392+ goto out_free;
20393+ err = au_d_may_add(dentry);
20394+ if (unlikely(err))
20395+ goto out_unlock;
20396+
4a4d8108
AM
20397+ parent = dentry->d_parent; /* dir inode is locked */
20398+ di_write_lock_parent(parent);
20399+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
20400+ &a->pin, &wr_dir_args);
20401+ err = PTR_ERR(wh_dentry);
20402+ if (IS_ERR(wh_dentry))
027c5e7a 20403+ goto out_parent;
4a4d8108
AM
20404+
20405+ sb = dentry->d_sb;
5afbbe0d 20406+ bindex = au_dbtop(dentry);
4a4d8108
AM
20407+ h_path.dentry = au_h_dptr(dentry, bindex);
20408+ h_path.mnt = au_sbr_mnt(sb, bindex);
20409+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
20410+ if (unlikely(err))
027c5e7a 20411+ goto out_unpin;
4a4d8108
AM
20412+
20413+ /* make the dir opaque */
20414+ diropq = 0;
febd17d6 20415+ h_inode = d_inode(h_path.dentry);
4a4d8108
AM
20416+ if (wh_dentry
20417+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
febd17d6 20418+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 20419+ opq_dentry = au_diropq_create(dentry, bindex);
febd17d6 20420+ inode_unlock(h_inode);
4a4d8108
AM
20421+ err = PTR_ERR(opq_dentry);
20422+ if (IS_ERR(opq_dentry))
20423+ goto out_dir;
20424+ dput(opq_dentry);
20425+ diropq = 1;
20426+ }
20427+
20428+ err = epilog(dir, bindex, wh_dentry, dentry);
20429+ if (!err) {
20430+ inc_nlink(dir);
027c5e7a 20431+ goto out_unpin; /* success */
4a4d8108
AM
20432+ }
20433+
20434+ /* revert */
20435+ if (diropq) {
20436+ AuLabel(revert opq);
febd17d6 20437+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 20438+ rerr = au_diropq_remove(dentry, bindex);
febd17d6 20439+ inode_unlock(h_inode);
4a4d8108 20440+ if (rerr) {
523b37e3
AM
20441+ AuIOErr("%pd reverting diropq failed(%d, %d)\n",
20442+ dentry, err, rerr);
4a4d8108
AM
20443+ err = -EIO;
20444+ }
20445+ }
20446+
4f0767ce 20447+out_dir:
4a4d8108
AM
20448+ AuLabel(revert dir);
20449+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
20450+ if (rerr) {
523b37e3
AM
20451+ AuIOErr("%pd reverting dir failed(%d, %d)\n",
20452+ dentry, err, rerr);
4a4d8108
AM
20453+ err = -EIO;
20454+ }
4a4d8108 20455+ au_dtime_revert(&a->dt);
027c5e7a 20456+out_unpin:
4a4d8108
AM
20457+ au_unpin(&a->pin);
20458+ dput(wh_dentry);
027c5e7a
AM
20459+out_parent:
20460+ di_write_unlock(parent);
20461+out_unlock:
4a4d8108 20462+ if (unlikely(err)) {
5afbbe0d 20463+ au_update_dbtop(dentry);
4a4d8108
AM
20464+ d_drop(dentry);
20465+ }
4a4d8108 20466+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 20467+out_free:
9f237c51 20468+ au_kfree_rcu(a);
4f0767ce 20469+out:
4a4d8108
AM
20470+ return err;
20471+}
7f207e10 20472diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
eca34b5c 20473--- /usr/share/empty/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6
JR
20474+++ linux/fs/aufs/i_op.c 2021-05-02 20:15:14.673337458 +0200
20475@@ -0,0 +1,1513 @@
cd7a4cd9 20476+// SPDX-License-Identifier: GPL-2.0
4a4d8108 20477+/*
d58c55f2 20478+ * Copyright (C) 2005-2020 Junjiro R. Okajima
4a4d8108
AM
20479+ *
20480+ * This program, aufs is free software; you can redistribute it and/or modify
20481+ * it under the terms of the GNU General Public License as published by
20482+ * the Free Software Foundation; either version 2 of the License, or
20483+ * (at your option) any later version.
20484+ *
20485+ * This program is distributed in the hope that it will be useful,
20486+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20487+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20488+ * GNU General Public License for more details.
20489+ *
20490+ * You should have received a copy of the GNU General Public License
523b37e3 20491+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 20492+ */
1facf9fc 20493+
1308ab2a 20494+/*
4a4d8108 20495+ * inode operations (except add/del/rename)
1308ab2a 20496+ */
4a4d8108
AM
20497+
20498+#include <linux/device_cgroup.h>
20499+#include <linux/fs_stack.h>
eca801bf 20500+#include <linux/iversion.h>
4a4d8108
AM
20501+#include <linux/namei.h>
20502+#include <linux/security.h>
4a4d8108
AM
20503+#include "aufs.h"
20504+
1e00d052 20505+static int h_permission(struct inode *h_inode, int mask,
79b8bda9 20506+ struct path *h_path, int brperm)
1facf9fc 20507+{
1308ab2a 20508+ int err;
4a4d8108 20509+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
0b2a12c6 20510+ struct user_namespace *h_userns;
1facf9fc 20511+
e2f27e51
AM
20512+ err = -EPERM;
20513+ if (write_mask && IS_IMMUTABLE(h_inode))
20514+ goto out;
20515+
4a4d8108 20516+ err = -EACCES;
e2f27e51
AM
20517+ if (((mask & MAY_EXEC)
20518+ && S_ISREG(h_inode->i_mode)
20519+ && (path_noexec(h_path)
cd7a4cd9 20520+ || !(h_inode->i_mode & 0111))))
4a4d8108
AM
20521+ goto out;
20522+
20523+ /*
20524+ * - skip the lower fs test in the case of write to ro branch.
20525+ * - nfs dir permission write check is optimized, but a policy for
20526+ * link/rename requires a real check.
2121bcd9 20527+ * - nfs always sets SB_POSIXACL regardless its mount option 'noacl.'
b912730e 20528+ * in this case, generic_permission() returns -EOPNOTSUPP.
4a4d8108 20529+ */
0b2a12c6 20530+ h_userns = mnt_user_ns(h_path->mnt);
4a4d8108
AM
20531+ if ((write_mask && !au_br_writable(brperm))
20532+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
20533+ && write_mask && !(mask & MAY_READ))
20534+ || !h_inode->i_op->permission) {
20535+ /* AuLabel(generic_permission); */
062440b3 20536+ /* AuDbg("get_acl %ps\n", h_inode->i_op->get_acl); */
0b2a12c6 20537+ err = generic_permission(h_userns, h_inode, mask);
b912730e 20538+ if (err == -EOPNOTSUPP && au_test_nfs_noacl(h_inode))
0b2a12c6
JR
20539+ err = h_inode->i_op->permission(h_userns, h_inode,
20540+ mask);
b912730e 20541+ AuTraceErr(err);
1308ab2a 20542+ } else {
4a4d8108 20543+ /* AuLabel(h_inode->permission); */
0b2a12c6 20544+ err = h_inode->i_op->permission(h_userns, h_inode, mask);
4a4d8108
AM
20545+ AuTraceErr(err);
20546+ }
1facf9fc 20547+
4a4d8108
AM
20548+ if (!err)
20549+ err = devcgroup_inode_permission(h_inode, mask);
7f207e10 20550+ if (!err)
4a4d8108 20551+ err = security_inode_permission(h_inode, mask);
4a4d8108 20552+
4f0767ce 20553+out:
1308ab2a 20554+ return err;
20555+}
dece6358 20556+
0b2a12c6
JR
20557+static int aufs_permission(struct user_namespace *userns, struct inode *inode,
20558+ int mask)
1308ab2a 20559+{
20560+ int err;
5afbbe0d 20561+ aufs_bindex_t bindex, bbot;
4a4d8108
AM
20562+ const unsigned char isdir = !!S_ISDIR(inode->i_mode),
20563+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
20564+ struct inode *h_inode;
20565+ struct super_block *sb;
20566+ struct au_branch *br;
1facf9fc 20567+
027c5e7a 20568+ /* todo: support rcu-walk? */
1e00d052 20569+ if (mask & MAY_NOT_BLOCK)
027c5e7a
AM
20570+ return -ECHILD;
20571+
4a4d8108
AM
20572+ sb = inode->i_sb;
20573+ si_read_lock(sb, AuLock_FLUSH);
20574+ ii_read_lock_child(inode);
43982f53
AM
20575+#if 0 /* reserved for future use */
20576+ /*
20577+ * This test may be rather 'too much' since the test is essentially done
20578+ * in the aufs_lookup(). Theoretically it is possible that the inode
20579+ * generation doesn't match to the superblock's here. But it isn't a
20580+ * big deal I suppose.
20581+ */
027c5e7a
AM
20582+ err = au_iigen_test(inode, au_sigen(sb));
20583+ if (unlikely(err))
20584+ goto out;
20585+#endif
dece6358 20586+
076b876e
AM
20587+ if (!isdir
20588+ || write_mask
20589+ || au_opt_test(au_mntflags(sb), DIRPERM1)) {
4a4d8108 20590+ err = au_busy_or_stale();
5afbbe0d 20591+ h_inode = au_h_iptr(inode, au_ibtop(inode));
4a4d8108
AM
20592+ if (unlikely(!h_inode
20593+ || (h_inode->i_mode & S_IFMT)
20594+ != (inode->i_mode & S_IFMT)))
20595+ goto out;
1facf9fc 20596+
4a4d8108 20597+ err = 0;
5afbbe0d 20598+ bindex = au_ibtop(inode);
4a4d8108 20599+ br = au_sbr(sb, bindex);
79b8bda9 20600+ err = h_permission(h_inode, mask, &br->br_path, br->br_perm);
4a4d8108
AM
20601+ if (write_mask
20602+ && !err
20603+ && !special_file(h_inode->i_mode)) {
20604+ /* test whether the upper writable branch exists */
20605+ err = -EROFS;
20606+ for (; bindex >= 0; bindex--)
20607+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
20608+ err = 0;
20609+ break;
20610+ }
20611+ }
20612+ goto out;
20613+ }
dece6358 20614+
4a4d8108 20615+ /* non-write to dir */
1308ab2a 20616+ err = 0;
5afbbe0d
AM
20617+ bbot = au_ibbot(inode);
20618+ for (bindex = au_ibtop(inode); !err && bindex <= bbot; bindex++) {
4a4d8108
AM
20619+ h_inode = au_h_iptr(inode, bindex);
20620+ if (h_inode) {
20621+ err = au_busy_or_stale();
20622+ if (unlikely(!S_ISDIR(h_inode->i_mode)))
20623+ break;
20624+
20625+ br = au_sbr(sb, bindex);
79b8bda9 20626+ err = h_permission(h_inode, mask, &br->br_path,
4a4d8108
AM
20627+ br->br_perm);
20628+ }
20629+ }
1308ab2a 20630+
4f0767ce 20631+out:
4a4d8108
AM
20632+ ii_read_unlock(inode);
20633+ si_read_unlock(sb);
1308ab2a 20634+ return err;
20635+}
20636+
4a4d8108 20637+/* ---------------------------------------------------------------------- */
1facf9fc 20638+
4a4d8108 20639+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
b4510431 20640+ unsigned int flags)
4a4d8108
AM
20641+{
20642+ struct dentry *ret, *parent;
b752ccd1 20643+ struct inode *inode;
4a4d8108 20644+ struct super_block *sb;
1716fcea 20645+ int err, npositive;
dece6358 20646+
4a4d8108 20647+ IMustLock(dir);
1308ab2a 20648+
537831f9
AM
20649+ /* todo: support rcu-walk? */
20650+ ret = ERR_PTR(-ECHILD);
20651+ if (flags & LOOKUP_RCU)
20652+ goto out;
20653+
20654+ ret = ERR_PTR(-ENAMETOOLONG);
20655+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
20656+ goto out;
20657+
4a4d8108 20658+ sb = dir->i_sb;
7f207e10
AM
20659+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
20660+ ret = ERR_PTR(err);
20661+ if (unlikely(err))
20662+ goto out;
20663+
4a4d8108
AM
20664+ err = au_di_init(dentry);
20665+ ret = ERR_PTR(err);
20666+ if (unlikely(err))
7f207e10 20667+ goto out_si;
1308ab2a 20668+
9dbd164d 20669+ inode = NULL;
027c5e7a 20670+ npositive = 0; /* suppress a warning */
4a4d8108
AM
20671+ parent = dentry->d_parent; /* dir inode is locked */
20672+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
20673+ err = au_alive_dir(parent);
20674+ if (!err)
20675+ err = au_digen_test(parent, au_sigen(sb));
20676+ if (!err) {
5afbbe0d
AM
20677+ /* regardless LOOKUP_CREATE, always ALLOW_NEG */
20678+ npositive = au_lkup_dentry(dentry, au_dbtop(parent),
20679+ AuLkup_ALLOW_NEG);
027c5e7a
AM
20680+ err = npositive;
20681+ }
4a4d8108 20682+ di_read_unlock(parent, AuLock_IR);
4a4d8108
AM
20683+ ret = ERR_PTR(err);
20684+ if (unlikely(err < 0))
20685+ goto out_unlock;
1308ab2a 20686+
4a4d8108 20687+ if (npositive) {
b752ccd1 20688+ inode = au_new_inode(dentry, /*must_new*/0);
c1595e42
JR
20689+ if (IS_ERR(inode)) {
20690+ ret = (void *)inode;
20691+ inode = NULL;
20692+ goto out_unlock;
20693+ }
9dbd164d 20694+ }
4a4d8108 20695+
c1595e42
JR
20696+ if (inode)
20697+ atomic_inc(&inode->i_count);
4a4d8108 20698+ ret = d_splice_alias(inode, dentry);
43982f53 20699+#if 0 /* reserved for future use */
537831f9
AM
20700+ if (unlikely(d_need_lookup(dentry))) {
20701+ spin_lock(&dentry->d_lock);
20702+ dentry->d_flags &= ~DCACHE_NEED_LOOKUP;
20703+ spin_unlock(&dentry->d_lock);
20704+ } else
20705+#endif
c1595e42 20706+ if (inode) {
2000de60 20707+ if (!IS_ERR(ret)) {
c1595e42 20708+ iput(inode);
2000de60
JR
20709+ if (ret && ret != dentry)
20710+ ii_write_unlock(inode);
20711+ } else {
c1595e42
JR
20712+ ii_write_unlock(inode);
20713+ iput(inode);
20714+ inode = NULL;
20715+ }
7f207e10 20716+ }
1facf9fc 20717+
4f0767ce 20718+out_unlock:
4a4d8108 20719+ di_write_unlock(dentry);
7f207e10 20720+out_si:
4a4d8108 20721+ si_read_unlock(sb);
7f207e10 20722+out:
4a4d8108
AM
20723+ return ret;
20724+}
1facf9fc 20725+
4a4d8108 20726+/* ---------------------------------------------------------------------- */
1facf9fc 20727+
acd2b654
AM
20728+/*
20729+ * very dirty and complicated aufs ->atomic_open().
20730+ * aufs_atomic_open()
20731+ * + au_aopen_or_create()
20732+ * + add_simple()
20733+ * + vfsub_atomic_open()
20734+ * + branch fs ->atomic_open()
20735+ * may call the actual 'open' for h_file
20736+ * + inc br_nfiles only if opened
20737+ * + au_aopen_no_open() or au_aopen_do_open()
20738+ *
20739+ * au_aopen_do_open()
20740+ * + finish_open()
20741+ * + au_do_aopen()
20742+ * + au_do_open() the body of all 'open'
20743+ * + au_do_open_nondir()
20744+ * set the passed h_file
20745+ *
20746+ * au_aopen_no_open()
20747+ * + finish_no_open()
20748+ */
20749+
b912730e 20750+struct aopen_node {
8b6a4947 20751+ struct hlist_bl_node hblist;
b912730e
AM
20752+ struct file *file, *h_file;
20753+};
20754+
20755+static int au_do_aopen(struct inode *inode, struct file *file)
20756+{
8b6a4947
AM
20757+ struct hlist_bl_head *aopen;
20758+ struct hlist_bl_node *pos;
b912730e
AM
20759+ struct aopen_node *node;
20760+ struct au_do_open_args args = {
8b6a4947
AM
20761+ .aopen = 1,
20762+ .open = au_do_open_nondir
b912730e
AM
20763+ };
20764+
20765+ aopen = &au_sbi(inode->i_sb)->si_aopen;
8b6a4947
AM
20766+ hlist_bl_lock(aopen);
20767+ hlist_bl_for_each_entry(node, pos, aopen, hblist)
b912730e
AM
20768+ if (node->file == file) {
20769+ args.h_file = node->h_file;
20770+ break;
20771+ }
8b6a4947 20772+ hlist_bl_unlock(aopen);
b912730e
AM
20773+ /* AuDebugOn(!args.h_file); */
20774+
20775+ return au_do_open(file, &args);
20776+}
20777+
acd2b654
AM
20778+static int au_aopen_do_open(struct file *file, struct dentry *dentry,
20779+ struct aopen_node *aopen_node)
20780+{
20781+ int err;
20782+ struct hlist_bl_head *aopen;
20783+
20784+ AuLabel(here);
20785+ aopen = &au_sbi(dentry->d_sb)->si_aopen;
20786+ au_hbl_add(&aopen_node->hblist, aopen);
20787+ err = finish_open(file, dentry, au_do_aopen);
20788+ au_hbl_del(&aopen_node->hblist, aopen);
20789+ /* AuDbgFile(file); */
20790+ AuDbg("%pd%s%s\n", dentry,
20791+ (file->f_mode & FMODE_CREATED) ? " created" : "",
20792+ (file->f_mode & FMODE_OPENED) ? " opened" : "");
20793+
20794+ AuTraceErr(err);
20795+ return err;
20796+}
20797+
20798+static int au_aopen_no_open(struct file *file, struct dentry *dentry)
20799+{
20800+ int err;
20801+
20802+ AuLabel(here);
20803+ dget(dentry);
20804+ err = finish_no_open(file, dentry);
20805+
20806+ AuTraceErr(err);
20807+ return err;
20808+}
20809+
b912730e
AM
20810+static int aufs_atomic_open(struct inode *dir, struct dentry *dentry,
20811+ struct file *file, unsigned int open_flag,
acd2b654 20812+ umode_t create_mode)
b912730e 20813+{
acd2b654 20814+ int err, did_open;
5afbbe0d 20815+ unsigned int lkup_flags;
acd2b654
AM
20816+ aufs_bindex_t bindex;
20817+ struct super_block *sb;
f0c0a007 20818+ struct dentry *parent, *d;
b912730e
AM
20819+ struct vfsub_aopen_args args = {
20820+ .open_flag = open_flag,
acd2b654 20821+ .create_mode = create_mode
b912730e
AM
20822+ };
20823+ struct aopen_node aopen_node = {
20824+ .file = file
20825+ };
20826+
20827+ IMustLock(dir);
5afbbe0d 20828+ AuDbg("open_flag 0%o\n", open_flag);
b912730e
AM
20829+ AuDbgDentry(dentry);
20830+
20831+ err = 0;
20832+ if (!au_di(dentry)) {
5afbbe0d
AM
20833+ lkup_flags = LOOKUP_OPEN;
20834+ if (open_flag & O_CREAT)
20835+ lkup_flags |= LOOKUP_CREATE;
20836+ d = aufs_lookup(dir, dentry, lkup_flags);
b912730e
AM
20837+ if (IS_ERR(d)) {
20838+ err = PTR_ERR(d);
5afbbe0d 20839+ AuTraceErr(err);
b912730e
AM
20840+ goto out;
20841+ } else if (d) {
20842+ /*
20843+ * obsoleted dentry found.
20844+ * another error will be returned later.
20845+ */
20846+ d_drop(d);
b912730e 20847+ AuDbgDentry(d);
5afbbe0d 20848+ dput(d);
b912730e
AM
20849+ }
20850+ AuDbgDentry(dentry);
20851+ }
20852+
20853+ if (d_is_positive(dentry)
20854+ || d_unhashed(dentry)
20855+ || d_unlinked(dentry)
acd2b654
AM
20856+ || !(open_flag & O_CREAT)) {
20857+ err = au_aopen_no_open(file, dentry);
20858+ goto out; /* success */
20859+ }
b912730e
AM
20860+
20861+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
20862+ if (unlikely(err))
20863+ goto out;
20864+
acd2b654 20865+ sb = dentry->d_sb;
b912730e
AM
20866+ parent = dentry->d_parent; /* dir is locked */
20867+ di_write_lock_parent(parent);
5afbbe0d 20868+ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG);
acd2b654
AM
20869+ if (unlikely(err < 0))
20870+ goto out_parent;
b912730e
AM
20871+
20872+ AuDbgDentry(dentry);
acd2b654
AM
20873+ if (d_is_positive(dentry)) {
20874+ err = au_aopen_no_open(file, dentry);
20875+ goto out_parent; /* success */
20876+ }
b912730e 20877+
acd2b654 20878+ args.file = alloc_empty_file(file->f_flags, current_cred());
b912730e
AM
20879+ err = PTR_ERR(args.file);
20880+ if (IS_ERR(args.file))
acd2b654 20881+ goto out_parent;
b912730e 20882+
acd2b654 20883+ bindex = au_dbtop(dentry);
b912730e
AM
20884+ err = au_aopen_or_create(dir, dentry, &args);
20885+ AuTraceErr(err);
20886+ AuDbgFile(args.file);
acd2b654
AM
20887+ file->f_mode = args.file->f_mode & ~FMODE_OPENED;
20888+ did_open = !!(args.file->f_mode & FMODE_OPENED);
20889+ if (!did_open) {
20890+ fput(args.file);
20891+ args.file = NULL;
b912730e 20892+ }
8b6a4947
AM
20893+ di_write_unlock(parent);
20894+ di_write_unlock(dentry);
acd2b654
AM
20895+ if (unlikely(err < 0)) {
20896+ if (args.file)
20897+ fput(args.file);
20898+ goto out_sb;
b912730e 20899+ }
b912730e 20900+
acd2b654
AM
20901+ if (!did_open)
20902+ err = au_aopen_no_open(file, dentry);
8b6a4947 20903+ else {
acd2b654
AM
20904+ aopen_node.h_file = args.file;
20905+ err = au_aopen_do_open(file, dentry, &aopen_node);
8b6a4947 20906+ }
acd2b654
AM
20907+ if (unlikely(err < 0)) {
20908+ if (args.file)
20909+ fput(args.file);
20910+ if (did_open)
20911+ au_lcnt_dec(&args.br->br_nfiles);
b912730e 20912+ }
acd2b654
AM
20913+ goto out_sb; /* success */
20914+
20915+out_parent:
20916+ di_write_unlock(parent);
20917+ di_write_unlock(dentry);
20918+out_sb:
20919+ si_read_unlock(sb);
b912730e 20920+out:
b912730e 20921+ AuTraceErr(err);
acd2b654 20922+ AuDbgFile(file);
b912730e
AM
20923+ return err;
20924+}
20925+
20926+
20927+/* ---------------------------------------------------------------------- */
20928+
4a4d8108
AM
20929+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
20930+ const unsigned char add_entry, aufs_bindex_t bcpup,
5afbbe0d 20931+ aufs_bindex_t btop)
4a4d8108
AM
20932+{
20933+ int err;
20934+ struct dentry *h_parent;
20935+ struct inode *h_dir;
1facf9fc 20936+
027c5e7a 20937+ if (add_entry)
5527c038 20938+ IMustLock(d_inode(parent));
027c5e7a 20939+ else
4a4d8108
AM
20940+ di_write_lock_parent(parent);
20941+
20942+ err = 0;
20943+ if (!au_h_dptr(parent, bcpup)) {
5afbbe0d 20944+ if (btop > bcpup)
c2b27bf2 20945+ err = au_cpup_dirs(dentry, bcpup);
5afbbe0d 20946+ else if (btop < bcpup)
4a4d8108
AM
20947+ err = au_cpdown_dirs(dentry, bcpup);
20948+ else
c2b27bf2 20949+ BUG();
4a4d8108 20950+ }
38d290e6 20951+ if (!err && add_entry && !au_ftest_wrdir(add_entry, TMPFILE)) {
4a4d8108 20952+ h_parent = au_h_dptr(parent, bcpup);
5527c038 20953+ h_dir = d_inode(h_parent);
be118d29 20954+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
7e9cd9fe 20955+ err = au_lkup_neg(dentry, bcpup, /*wh*/0);
4a4d8108 20956+ /* todo: no unlock here */
3c1bdaff 20957+ inode_unlock_shared(h_dir);
027c5e7a
AM
20958+
20959+ AuDbg("bcpup %d\n", bcpup);
20960+ if (!err) {
5527c038 20961+ if (d_really_is_negative(dentry))
5afbbe0d 20962+ au_set_h_dptr(dentry, btop, NULL);
4a4d8108
AM
20963+ au_update_dbrange(dentry, /*do_put_zero*/0);
20964+ }
1308ab2a 20965+ }
1facf9fc 20966+
4a4d8108
AM
20967+ if (!add_entry)
20968+ di_write_unlock(parent);
20969+ if (!err)
20970+ err = bcpup; /* success */
1308ab2a 20971+
027c5e7a 20972+ AuTraceErr(err);
4a4d8108
AM
20973+ return err;
20974+}
1facf9fc 20975+
4a4d8108
AM
20976+/*
20977+ * decide the branch and the parent dir where we will create a new entry.
20978+ * returns new bindex or an error.
20979+ * copyup the parent dir if needed.
20980+ */
20981+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
20982+ struct au_wr_dir_args *args)
20983+{
20984+ int err;
392086de 20985+ unsigned int flags;
5afbbe0d 20986+ aufs_bindex_t bcpup, btop, src_btop;
86dc4139
AM
20987+ const unsigned char add_entry
20988+ = au_ftest_wrdir(args->flags, ADD_ENTRY)
38d290e6 20989+ | au_ftest_wrdir(args->flags, TMPFILE);
4a4d8108
AM
20990+ struct super_block *sb;
20991+ struct dentry *parent;
20992+ struct au_sbinfo *sbinfo;
1facf9fc 20993+
4a4d8108
AM
20994+ sb = dentry->d_sb;
20995+ sbinfo = au_sbi(sb);
20996+ parent = dget_parent(dentry);
5afbbe0d
AM
20997+ btop = au_dbtop(dentry);
20998+ bcpup = btop;
4a4d8108
AM
20999+ if (args->force_btgt < 0) {
21000+ if (src_dentry) {
5afbbe0d
AM
21001+ src_btop = au_dbtop(src_dentry);
21002+ if (src_btop < btop)
21003+ bcpup = src_btop;
4a4d8108 21004+ } else if (add_entry) {
392086de
AM
21005+ flags = 0;
21006+ if (au_ftest_wrdir(args->flags, ISDIR))
21007+ au_fset_wbr(flags, DIR);
21008+ err = AuWbrCreate(sbinfo, dentry, flags);
4a4d8108
AM
21009+ bcpup = err;
21010+ }
1facf9fc 21011+
5527c038 21012+ if (bcpup < 0 || au_test_ro(sb, bcpup, d_inode(dentry))) {
4a4d8108
AM
21013+ if (add_entry)
21014+ err = AuWbrCopyup(sbinfo, dentry);
21015+ else {
21016+ if (!IS_ROOT(dentry)) {
21017+ di_read_lock_parent(parent, !AuLock_IR);
21018+ err = AuWbrCopyup(sbinfo, dentry);
21019+ di_read_unlock(parent, !AuLock_IR);
21020+ } else
21021+ err = AuWbrCopyup(sbinfo, dentry);
21022+ }
21023+ bcpup = err;
21024+ if (unlikely(err < 0))
21025+ goto out;
21026+ }
21027+ } else {
21028+ bcpup = args->force_btgt;
5527c038 21029+ AuDebugOn(au_test_ro(sb, bcpup, d_inode(dentry)));
1308ab2a 21030+ }
027c5e7a 21031+
5afbbe0d 21032+ AuDbg("btop %d, bcpup %d\n", btop, bcpup);
4a4d8108 21033+ err = bcpup;
5afbbe0d 21034+ if (bcpup == btop)
4a4d8108 21035+ goto out; /* success */
4a4d8108
AM
21036+
21037+ /* copyup the new parent into the branch we process */
5afbbe0d 21038+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, btop);
027c5e7a 21039+ if (err >= 0) {
5527c038 21040+ if (d_really_is_negative(dentry)) {
5afbbe0d
AM
21041+ au_set_h_dptr(dentry, btop, NULL);
21042+ au_set_dbtop(dentry, bcpup);
21043+ au_set_dbbot(dentry, bcpup);
027c5e7a 21044+ }
38d290e6
JR
21045+ AuDebugOn(add_entry
21046+ && !au_ftest_wrdir(args->flags, TMPFILE)
21047+ && !au_h_dptr(dentry, bcpup));
027c5e7a 21048+ }
86dc4139
AM
21049+
21050+out:
21051+ dput(parent);
21052+ return err;
21053+}
21054+
21055+/* ---------------------------------------------------------------------- */
21056+
21057+void au_pin_hdir_unlock(struct au_pin *p)
21058+{
21059+ if (p->hdir)
5afbbe0d 21060+ au_hn_inode_unlock(p->hdir);
86dc4139
AM
21061+}
21062+
c1595e42 21063+int au_pin_hdir_lock(struct au_pin *p)
86dc4139
AM
21064+{
21065+ int err;
21066+
21067+ err = 0;
21068+ if (!p->hdir)
21069+ goto out;
21070+
21071+ /* even if an error happens later, keep this lock */
5afbbe0d 21072+ au_hn_inode_lock_nested(p->hdir, p->lsc_hi);
86dc4139
AM
21073+
21074+ err = -EBUSY;
5527c038 21075+ if (unlikely(p->hdir->hi_inode != d_inode(p->h_parent)))
86dc4139
AM
21076+ goto out;
21077+
21078+ err = 0;
21079+ if (p->h_dentry)
21080+ err = au_h_verify(p->h_dentry, p->udba, p->hdir->hi_inode,
21081+ p->h_parent, p->br);
21082+
21083+out:
21084+ return err;
21085+}
21086+
21087+int au_pin_hdir_relock(struct au_pin *p)
21088+{
21089+ int err, i;
21090+ struct inode *h_i;
21091+ struct dentry *h_d[] = {
21092+ p->h_dentry,
21093+ p->h_parent
21094+ };
21095+
21096+ err = au_pin_hdir_lock(p);
21097+ if (unlikely(err))
21098+ goto out;
21099+
21100+ for (i = 0; !err && i < sizeof(h_d)/sizeof(*h_d); i++) {
21101+ if (!h_d[i])
21102+ continue;
5527c038
JR
21103+ if (d_is_positive(h_d[i])) {
21104+ h_i = d_inode(h_d[i]);
86dc4139 21105+ err = !h_i->i_nlink;
5527c038 21106+ }
86dc4139
AM
21107+ }
21108+
21109+out:
21110+ return err;
21111+}
21112+
5afbbe0d 21113+static void au_pin_hdir_set_owner(struct au_pin *p, struct task_struct *task)
86dc4139 21114+{
eca34b5c 21115+ atomic_long_set(&p->hdir->hi_inode->i_rwsem.owner, (long)task);
86dc4139
AM
21116+}
21117+
21118+void au_pin_hdir_acquire_nest(struct au_pin *p)
21119+{
21120+ if (p->hdir) {
5afbbe0d 21121+ rwsem_acquire_nest(&p->hdir->hi_inode->i_rwsem.dep_map,
86dc4139
AM
21122+ p->lsc_hi, 0, NULL, _RET_IP_);
21123+ au_pin_hdir_set_owner(p, current);
21124+ }
dece6358 21125+}
1facf9fc 21126+
86dc4139
AM
21127+void au_pin_hdir_release(struct au_pin *p)
21128+{
21129+ if (p->hdir) {
21130+ au_pin_hdir_set_owner(p, p->task);
d58c55f2 21131+ rwsem_release(&p->hdir->hi_inode->i_rwsem.dep_map, _RET_IP_);
86dc4139
AM
21132+ }
21133+}
1308ab2a 21134+
4a4d8108 21135+struct dentry *au_pinned_h_parent(struct au_pin *pin)
1308ab2a 21136+{
4a4d8108
AM
21137+ if (pin && pin->parent)
21138+ return au_h_dptr(pin->parent, pin->bindex);
21139+ return NULL;
dece6358 21140+}
1facf9fc 21141+
4a4d8108 21142+void au_unpin(struct au_pin *p)
dece6358 21143+{
86dc4139
AM
21144+ if (p->hdir)
21145+ au_pin_hdir_unlock(p);
e49829fe 21146+ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE))
b4510431 21147+ vfsub_mnt_drop_write(p->h_mnt);
4a4d8108
AM
21148+ if (!p->hdir)
21149+ return;
1facf9fc 21150+
4a4d8108
AM
21151+ if (!au_ftest_pin(p->flags, DI_LOCKED))
21152+ di_read_unlock(p->parent, AuLock_IR);
21153+ iput(p->hdir->hi_inode);
21154+ dput(p->parent);
21155+ p->parent = NULL;
21156+ p->hdir = NULL;
21157+ p->h_mnt = NULL;
86dc4139 21158+ /* do not clear p->task */
4a4d8108 21159+}
1308ab2a 21160+
4a4d8108
AM
21161+int au_do_pin(struct au_pin *p)
21162+{
21163+ int err;
21164+ struct super_block *sb;
4a4d8108
AM
21165+ struct inode *h_dir;
21166+
21167+ err = 0;
21168+ sb = p->dentry->d_sb;
86dc4139 21169+ p->br = au_sbr(sb, p->bindex);
4a4d8108
AM
21170+ if (IS_ROOT(p->dentry)) {
21171+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
86dc4139 21172+ p->h_mnt = au_br_mnt(p->br);
b4510431 21173+ err = vfsub_mnt_want_write(p->h_mnt);
4a4d8108
AM
21174+ if (unlikely(err)) {
21175+ au_fclr_pin(p->flags, MNT_WRITE);
21176+ goto out_err;
21177+ }
21178+ }
dece6358 21179+ goto out;
1facf9fc 21180+ }
21181+
86dc4139 21182+ p->h_dentry = NULL;
5afbbe0d 21183+ if (p->bindex <= au_dbbot(p->dentry))
86dc4139 21184+ p->h_dentry = au_h_dptr(p->dentry, p->bindex);
dece6358 21185+
4a4d8108
AM
21186+ p->parent = dget_parent(p->dentry);
21187+ if (!au_ftest_pin(p->flags, DI_LOCKED))
21188+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
dece6358 21189+
4a4d8108 21190+ h_dir = NULL;
86dc4139 21191+ p->h_parent = au_h_dptr(p->parent, p->bindex);
5527c038 21192+ p->hdir = au_hi(d_inode(p->parent), p->bindex);
4a4d8108
AM
21193+ if (p->hdir)
21194+ h_dir = p->hdir->hi_inode;
dece6358 21195+
b752ccd1
AM
21196+ /*
21197+ * udba case, or
21198+ * if DI_LOCKED is not set, then p->parent may be different
21199+ * and h_parent can be NULL.
21200+ */
86dc4139 21201+ if (unlikely(!p->hdir || !h_dir || !p->h_parent)) {
e49829fe 21202+ err = -EBUSY;
4a4d8108
AM
21203+ if (!au_ftest_pin(p->flags, DI_LOCKED))
21204+ di_read_unlock(p->parent, AuLock_IR);
21205+ dput(p->parent);
21206+ p->parent = NULL;
21207+ goto out_err;
21208+ }
1308ab2a 21209+
4a4d8108 21210+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
86dc4139 21211+ p->h_mnt = au_br_mnt(p->br);
b4510431 21212+ err = vfsub_mnt_want_write(p->h_mnt);
dece6358 21213+ if (unlikely(err)) {
4a4d8108 21214+ au_fclr_pin(p->flags, MNT_WRITE);
86dc4139
AM
21215+ if (!au_ftest_pin(p->flags, DI_LOCKED))
21216+ di_read_unlock(p->parent, AuLock_IR);
21217+ dput(p->parent);
21218+ p->parent = NULL;
21219+ goto out_err;
dece6358
AM
21220+ }
21221+ }
4a4d8108 21222+
86dc4139
AM
21223+ au_igrab(h_dir);
21224+ err = au_pin_hdir_lock(p);
21225+ if (!err)
21226+ goto out; /* success */
21227+
076b876e
AM
21228+ au_unpin(p);
21229+
4f0767ce 21230+out_err:
4a4d8108
AM
21231+ pr_err("err %d\n", err);
21232+ err = au_busy_or_stale();
4f0767ce 21233+out:
1facf9fc 21234+ return err;
21235+}
21236+
4a4d8108
AM
21237+void au_pin_init(struct au_pin *p, struct dentry *dentry,
21238+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
21239+ unsigned int udba, unsigned char flags)
21240+{
21241+ p->dentry = dentry;
21242+ p->udba = udba;
21243+ p->lsc_di = lsc_di;
21244+ p->lsc_hi = lsc_hi;
21245+ p->flags = flags;
21246+ p->bindex = bindex;
21247+
21248+ p->parent = NULL;
21249+ p->hdir = NULL;
21250+ p->h_mnt = NULL;
86dc4139
AM
21251+
21252+ p->h_dentry = NULL;
21253+ p->h_parent = NULL;
21254+ p->br = NULL;
21255+ p->task = current;
4a4d8108
AM
21256+}
21257+
21258+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
21259+ unsigned int udba, unsigned char flags)
21260+{
21261+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
21262+ udba, flags);
21263+ return au_do_pin(pin);
21264+}
21265+
dece6358
AM
21266+/* ---------------------------------------------------------------------- */
21267+
1308ab2a 21268+/*
4a4d8108
AM
21269+ * ->setattr() and ->getattr() are called in various cases.
21270+ * chmod, stat: dentry is revalidated.
21271+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be
21272+ * unhashed.
21273+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
1308ab2a 21274+ */
027c5e7a 21275+/* todo: consolidate with do_refresh() and simple_reval_dpath() */
c1595e42 21276+int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
1facf9fc 21277+{
4a4d8108 21278+ int err;
4a4d8108 21279+ struct dentry *parent;
1facf9fc 21280+
1308ab2a 21281+ err = 0;
027c5e7a 21282+ if (au_digen_test(dentry, sigen)) {
4a4d8108
AM
21283+ parent = dget_parent(dentry);
21284+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 21285+ err = au_refresh_dentry(dentry, parent);
4a4d8108
AM
21286+ di_read_unlock(parent, AuLock_IR);
21287+ dput(parent);
dece6358 21288+ }
1facf9fc 21289+
4a4d8108 21290+ AuTraceErr(err);
1308ab2a 21291+ return err;
21292+}
dece6358 21293+
c1595e42
JR
21294+int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
21295+ struct au_icpup_args *a)
1308ab2a 21296+{
21297+ int err;
4a4d8108 21298+ loff_t sz;
5afbbe0d 21299+ aufs_bindex_t btop, ibtop;
4a4d8108
AM
21300+ struct dentry *hi_wh, *parent;
21301+ struct inode *inode;
4a4d8108
AM
21302+ struct au_wr_dir_args wr_dir_args = {
21303+ .force_btgt = -1,
21304+ .flags = 0
21305+ };
21306+
2000de60 21307+ if (d_is_dir(dentry))
4a4d8108
AM
21308+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
21309+ /* plink or hi_wh() case */
5afbbe0d 21310+ btop = au_dbtop(dentry);
5527c038 21311+ inode = d_inode(dentry);
5afbbe0d
AM
21312+ ibtop = au_ibtop(inode);
21313+ if (btop != ibtop && !au_test_ro(inode->i_sb, ibtop, inode))
21314+ wr_dir_args.force_btgt = ibtop;
4a4d8108
AM
21315+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
21316+ if (unlikely(err < 0))
21317+ goto out;
21318+ a->btgt = err;
5afbbe0d 21319+ if (err != btop)
4a4d8108
AM
21320+ au_fset_icpup(a->flags, DID_CPUP);
21321+
21322+ err = 0;
21323+ a->pin_flags = AuPin_MNT_WRITE;
21324+ parent = NULL;
21325+ if (!IS_ROOT(dentry)) {
21326+ au_fset_pin(a->pin_flags, DI_LOCKED);
21327+ parent = dget_parent(dentry);
21328+ di_write_lock_parent(parent);
21329+ }
21330+
21331+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
21332+ if (unlikely(err))
21333+ goto out_parent;
21334+
4a4d8108 21335+ sz = -1;
5afbbe0d 21336+ a->h_path.dentry = au_h_dptr(dentry, btop);
5527c038 21337+ a->h_inode = d_inode(a->h_path.dentry);
c1595e42 21338+ if (ia && (ia->ia_valid & ATTR_SIZE)) {
be118d29 21339+ inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD);
c1595e42
JR
21340+ if (ia->ia_size < i_size_read(a->h_inode))
21341+ sz = ia->ia_size;
3c1bdaff 21342+ inode_unlock_shared(a->h_inode);
c1595e42 21343+ }
4a4d8108 21344+
4a4d8108 21345+ hi_wh = NULL;
027c5e7a 21346+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) {
4a4d8108
AM
21347+ hi_wh = au_hi_wh(inode, a->btgt);
21348+ if (!hi_wh) {
c2b27bf2
AM
21349+ struct au_cp_generic cpg = {
21350+ .dentry = dentry,
21351+ .bdst = a->btgt,
21352+ .bsrc = -1,
21353+ .len = sz,
21354+ .pin = &a->pin
21355+ };
21356+ err = au_sio_cpup_wh(&cpg, /*file*/NULL);
4a4d8108
AM
21357+ if (unlikely(err))
21358+ goto out_unlock;
21359+ hi_wh = au_hi_wh(inode, a->btgt);
21360+ /* todo: revalidate hi_wh? */
21361+ }
21362+ }
21363+
21364+ if (parent) {
21365+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
21366+ di_downgrade_lock(parent, AuLock_IR);
21367+ dput(parent);
21368+ parent = NULL;
21369+ }
21370+ if (!au_ftest_icpup(a->flags, DID_CPUP))
21371+ goto out; /* success */
21372+
21373+ if (!d_unhashed(dentry)) {
c2b27bf2
AM
21374+ struct au_cp_generic cpg = {
21375+ .dentry = dentry,
21376+ .bdst = a->btgt,
5afbbe0d 21377+ .bsrc = btop,
c2b27bf2
AM
21378+ .len = sz,
21379+ .pin = &a->pin,
21380+ .flags = AuCpup_DTIME | AuCpup_HOPEN
21381+ };
21382+ err = au_sio_cpup_simple(&cpg);
4a4d8108
AM
21383+ if (!err)
21384+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
21385+ } else if (!hi_wh)
21386+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
21387+ else
21388+ a->h_path.dentry = hi_wh; /* do not dget here */
1308ab2a 21389+
4f0767ce 21390+out_unlock:
5527c038 21391+ a->h_inode = d_inode(a->h_path.dentry);
86dc4139 21392+ if (!err)
dece6358 21393+ goto out; /* success */
4a4d8108 21394+ au_unpin(&a->pin);
4f0767ce 21395+out_parent:
4a4d8108
AM
21396+ if (parent) {
21397+ di_write_unlock(parent);
21398+ dput(parent);
21399+ }
4f0767ce 21400+out:
86dc4139 21401+ if (!err)
febd17d6 21402+ inode_lock_nested(a->h_inode, AuLsc_I_CHILD);
1facf9fc 21403+ return err;
21404+}
21405+
0b2a12c6
JR
21406+static int aufs_setattr(struct user_namespace *userns, struct dentry *dentry,
21407+ struct iattr *ia)
1facf9fc 21408+{
4a4d8108 21409+ int err;
523b37e3 21410+ struct inode *inode, *delegated;
4a4d8108
AM
21411+ struct super_block *sb;
21412+ struct file *file;
21413+ struct au_icpup_args *a;
0b2a12c6 21414+ struct user_namespace *h_userns;
1facf9fc 21415+
5527c038 21416+ inode = d_inode(dentry);
4a4d8108 21417+ IMustLock(inode);
dece6358 21418+
0b2a12c6 21419+ err = setattr_prepare(userns, dentry, ia);
f2c43d5f
AM
21420+ if (unlikely(err))
21421+ goto out;
21422+
4a4d8108
AM
21423+ err = -ENOMEM;
21424+ a = kzalloc(sizeof(*a), GFP_NOFS);
21425+ if (unlikely(!a))
21426+ goto out;
1facf9fc 21427+
4a4d8108
AM
21428+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
21429+ ia->ia_valid &= ~ATTR_MODE;
dece6358 21430+
4a4d8108
AM
21431+ file = NULL;
21432+ sb = dentry->d_sb;
e49829fe
JR
21433+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21434+ if (unlikely(err))
21435+ goto out_kfree;
21436+
4a4d8108
AM
21437+ if (ia->ia_valid & ATTR_FILE) {
21438+ /* currently ftruncate(2) only */
7e9cd9fe 21439+ AuDebugOn(!d_is_reg(dentry));
4a4d8108 21440+ file = ia->ia_file;
521ced18
JR
21441+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1,
21442+ /*fi_lsc*/0);
4a4d8108
AM
21443+ if (unlikely(err))
21444+ goto out_si;
21445+ ia->ia_file = au_hf_top(file);
21446+ a->udba = AuOpt_UDBA_NONE;
21447+ } else {
21448+ /* fchmod() doesn't pass ia_file */
21449+ a->udba = au_opt_udba(sb);
027c5e7a
AM
21450+ di_write_lock_child(dentry);
21451+ /* no d_unlinked(), to set UDBA_NONE for root */
4a4d8108
AM
21452+ if (d_unhashed(dentry))
21453+ a->udba = AuOpt_UDBA_NONE;
4a4d8108
AM
21454+ if (a->udba != AuOpt_UDBA_NONE) {
21455+ AuDebugOn(IS_ROOT(dentry));
21456+ err = au_reval_for_attr(dentry, au_sigen(sb));
21457+ if (unlikely(err))
21458+ goto out_dentry;
21459+ }
dece6358 21460+ }
dece6358 21461+
4a4d8108
AM
21462+ err = au_pin_and_icpup(dentry, ia, a);
21463+ if (unlikely(err < 0))
21464+ goto out_dentry;
21465+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
21466+ ia->ia_file = NULL;
21467+ ia->ia_valid &= ~ATTR_FILE;
1308ab2a 21468+ }
dece6358 21469+
4a4d8108
AM
21470+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
21471+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
21472+ == (ATTR_MODE | ATTR_CTIME)) {
7eafdf33 21473+ err = security_path_chmod(&a->h_path, ia->ia_mode);
4a4d8108
AM
21474+ if (unlikely(err))
21475+ goto out_unlock;
21476+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
21477+ && (ia->ia_valid & ATTR_CTIME)) {
86dc4139 21478+ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid);
4a4d8108
AM
21479+ if (unlikely(err))
21480+ goto out_unlock;
21481+ }
dece6358 21482+
4a4d8108
AM
21483+ if (ia->ia_valid & ATTR_SIZE) {
21484+ struct file *f;
1308ab2a 21485+
953406b4 21486+ if (ia->ia_size < i_size_read(inode))
4a4d8108 21487+ /* unmap only */
953406b4 21488+ truncate_setsize(inode, ia->ia_size);
1308ab2a 21489+
4a4d8108
AM
21490+ f = NULL;
21491+ if (ia->ia_valid & ATTR_FILE)
21492+ f = ia->ia_file;
febd17d6 21493+ inode_unlock(a->h_inode);
4a4d8108 21494+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
febd17d6 21495+ inode_lock_nested(a->h_inode, AuLsc_I_CHILD);
523b37e3
AM
21496+ } else {
21497+ delegated = NULL;
21498+ while (1) {
21499+ err = vfsub_notify_change(&a->h_path, ia, &delegated);
21500+ if (delegated) {
21501+ err = break_deleg_wait(&delegated);
21502+ if (!err)
21503+ continue;
21504+ }
21505+ break;
21506+ }
21507+ }
8cdd5066
JR
21508+ /*
21509+ * regardless aufs 'acl' option setting.
21510+ * why don't all acl-aware fs call this func from their ->setattr()?
21511+ */
0b2a12c6
JR
21512+ if (!err && (ia->ia_valid & ATTR_MODE)) {
21513+ h_userns = mnt_user_ns(a->h_path.mnt);
21514+ err = vfsub_acl_chmod(h_userns, a->h_inode, ia->ia_mode);
21515+ }
4a4d8108
AM
21516+ if (!err)
21517+ au_cpup_attr_changeable(inode);
1308ab2a 21518+
4f0767ce 21519+out_unlock:
febd17d6 21520+ inode_unlock(a->h_inode);
4a4d8108 21521+ au_unpin(&a->pin);
027c5e7a 21522+ if (unlikely(err))
5afbbe0d 21523+ au_update_dbtop(dentry);
4f0767ce 21524+out_dentry:
4a4d8108
AM
21525+ di_write_unlock(dentry);
21526+ if (file) {
21527+ fi_write_unlock(file);
21528+ ia->ia_file = file;
21529+ ia->ia_valid |= ATTR_FILE;
21530+ }
4f0767ce 21531+out_si:
4a4d8108 21532+ si_read_unlock(sb);
e49829fe 21533+out_kfree:
9f237c51 21534+ au_kfree_rcu(a);
4f0767ce 21535+out:
4a4d8108
AM
21536+ AuTraceErr(err);
21537+ return err;
1facf9fc 21538+}
21539+
c1595e42
JR
21540+#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL)
21541+static int au_h_path_to_set_attr(struct dentry *dentry,
21542+ struct au_icpup_args *a, struct path *h_path)
21543+{
21544+ int err;
21545+ struct super_block *sb;
21546+
21547+ sb = dentry->d_sb;
21548+ a->udba = au_opt_udba(sb);
21549+ /* no d_unlinked(), to set UDBA_NONE for root */
21550+ if (d_unhashed(dentry))
21551+ a->udba = AuOpt_UDBA_NONE;
21552+ if (a->udba != AuOpt_UDBA_NONE) {
21553+ AuDebugOn(IS_ROOT(dentry));
21554+ err = au_reval_for_attr(dentry, au_sigen(sb));
21555+ if (unlikely(err))
21556+ goto out;
21557+ }
21558+ err = au_pin_and_icpup(dentry, /*ia*/NULL, a);
21559+ if (unlikely(err < 0))
21560+ goto out;
21561+
21562+ h_path->dentry = a->h_path.dentry;
21563+ h_path->mnt = au_sbr_mnt(sb, a->btgt);
21564+
21565+out:
21566+ return err;
21567+}
21568+
f2c43d5f
AM
21569+ssize_t au_sxattr(struct dentry *dentry, struct inode *inode,
21570+ struct au_sxattr *arg)
c1595e42
JR
21571+{
21572+ int err;
21573+ struct path h_path;
21574+ struct super_block *sb;
21575+ struct au_icpup_args *a;
5afbbe0d 21576+ struct inode *h_inode;
0b2a12c6 21577+ struct user_namespace *h_userns;
c1595e42 21578+
c1595e42
JR
21579+ IMustLock(inode);
21580+
21581+ err = -ENOMEM;
21582+ a = kzalloc(sizeof(*a), GFP_NOFS);
21583+ if (unlikely(!a))
21584+ goto out;
21585+
21586+ sb = dentry->d_sb;
21587+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21588+ if (unlikely(err))
21589+ goto out_kfree;
21590+
21591+ h_path.dentry = NULL; /* silence gcc */
21592+ di_write_lock_child(dentry);
21593+ err = au_h_path_to_set_attr(dentry, a, &h_path);
21594+ if (unlikely(err))
21595+ goto out_di;
0b2a12c6 21596+ h_userns = mnt_user_ns(h_path.mnt);
c1595e42 21597+
febd17d6 21598+ inode_unlock(a->h_inode);
c1595e42
JR
21599+ switch (arg->type) {
21600+ case AU_XATTR_SET:
5afbbe0d 21601+ AuDebugOn(d_is_negative(h_path.dentry));
0b2a12c6 21602+ err = vfsub_setxattr(h_userns, h_path.dentry,
c1595e42
JR
21603+ arg->u.set.name, arg->u.set.value,
21604+ arg->u.set.size, arg->u.set.flags);
21605+ break;
c1595e42
JR
21606+ case AU_ACL_SET:
21607+ err = -EOPNOTSUPP;
5527c038 21608+ h_inode = d_inode(h_path.dentry);
0b2a12c6 21609+ if (h_inode->i_op->set_acl) {
f2c43d5f 21610+ /* this will call posix_acl_update_mode */
0b2a12c6 21611+ err = h_inode->i_op->set_acl(h_userns, h_inode,
c1595e42
JR
21612+ arg->u.acl_set.acl,
21613+ arg->u.acl_set.type);
0b2a12c6 21614+ }
c1595e42
JR
21615+ break;
21616+ }
21617+ if (!err)
21618+ au_cpup_attr_timesizes(inode);
21619+
21620+ au_unpin(&a->pin);
21621+ if (unlikely(err))
5afbbe0d 21622+ au_update_dbtop(dentry);
c1595e42
JR
21623+
21624+out_di:
21625+ di_write_unlock(dentry);
21626+ si_read_unlock(sb);
21627+out_kfree:
9f237c51 21628+ au_kfree_rcu(a);
c1595e42
JR
21629+out:
21630+ AuTraceErr(err);
21631+ return err;
21632+}
21633+#endif
21634+
4a4d8108
AM
21635+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
21636+ unsigned int nlink)
1facf9fc 21637+{
9dbd164d
AM
21638+ unsigned int n;
21639+
4a4d8108 21640+ inode->i_mode = st->mode;
86dc4139
AM
21641+ /* don't i_[ug]id_write() here */
21642+ inode->i_uid = st->uid;
21643+ inode->i_gid = st->gid;
4a4d8108
AM
21644+ inode->i_atime = st->atime;
21645+ inode->i_mtime = st->mtime;
21646+ inode->i_ctime = st->ctime;
1facf9fc 21647+
4a4d8108
AM
21648+ au_cpup_attr_nlink(inode, /*force*/0);
21649+ if (S_ISDIR(inode->i_mode)) {
9dbd164d
AM
21650+ n = inode->i_nlink;
21651+ n -= nlink;
21652+ n += st->nlink;
f6b6e03d 21653+ smp_mb(); /* for i_nlink */
7eafdf33 21654+ /* 0 can happen */
92d182d2 21655+ set_nlink(inode, n);
4a4d8108 21656+ }
1facf9fc 21657+
4a4d8108
AM
21658+ spin_lock(&inode->i_lock);
21659+ inode->i_blocks = st->blocks;
21660+ i_size_write(inode, st->size);
21661+ spin_unlock(&inode->i_lock);
1facf9fc 21662+}
21663+
c1595e42 21664+/*
f2c43d5f 21665+ * common routine for aufs_getattr() and au_getxattr().
c1595e42
JR
21666+ * returns zero or negative (an error).
21667+ * @dentry will be read-locked in success.
21668+ */
42b5c33a
AM
21669+int au_h_path_getattr(struct dentry *dentry, struct inode *inode, int force,
21670+ struct path *h_path, int locked)
1facf9fc 21671+{
4a4d8108 21672+ int err;
076b876e 21673+ unsigned int mnt_flags, sigen;
c1595e42 21674+ unsigned char udba_none;
4a4d8108 21675+ aufs_bindex_t bindex;
4a4d8108 21676+ struct super_block *sb, *h_sb;
1facf9fc 21677+
c1595e42
JR
21678+ h_path->mnt = NULL;
21679+ h_path->dentry = NULL;
21680+
21681+ err = 0;
4a4d8108 21682+ sb = dentry->d_sb;
4a4d8108
AM
21683+ mnt_flags = au_mntflags(sb);
21684+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
1facf9fc 21685+
a2654f78
AM
21686+ if (unlikely(locked))
21687+ goto body; /* skip locking dinfo */
21688+
4a4d8108 21689+ /* support fstat(2) */
027c5e7a 21690+ if (!d_unlinked(dentry) && !udba_none) {
076b876e 21691+ sigen = au_sigen(sb);
027c5e7a
AM
21692+ err = au_digen_test(dentry, sigen);
21693+ if (!err) {
4a4d8108 21694+ di_read_lock_child(dentry, AuLock_IR);
027c5e7a 21695+ err = au_dbrange_test(dentry);
c1595e42
JR
21696+ if (unlikely(err)) {
21697+ di_read_unlock(dentry, AuLock_IR);
21698+ goto out;
21699+ }
027c5e7a 21700+ } else {
4a4d8108
AM
21701+ AuDebugOn(IS_ROOT(dentry));
21702+ di_write_lock_child(dentry);
027c5e7a
AM
21703+ err = au_dbrange_test(dentry);
21704+ if (!err)
21705+ err = au_reval_for_attr(dentry, sigen);
c1595e42
JR
21706+ if (!err)
21707+ di_downgrade_lock(dentry, AuLock_IR);
21708+ else {
21709+ di_write_unlock(dentry);
21710+ goto out;
21711+ }
4a4d8108
AM
21712+ }
21713+ } else
21714+ di_read_lock_child(dentry, AuLock_IR);
1facf9fc 21715+
a2654f78 21716+body:
42b5c33a
AM
21717+ if (!inode) {
21718+ inode = d_inode(dentry);
21719+ if (unlikely(!inode))
21720+ goto out;
21721+ }
5afbbe0d 21722+ bindex = au_ibtop(inode);
c1595e42
JR
21723+ h_path->mnt = au_sbr_mnt(sb, bindex);
21724+ h_sb = h_path->mnt->mnt_sb;
21725+ if (!force
21726+ && !au_test_fs_bad_iattr(h_sb)
21727+ && udba_none)
21728+ goto out; /* success */
1facf9fc 21729+
5afbbe0d 21730+ if (au_dbtop(dentry) == bindex)
c1595e42 21731+ h_path->dentry = au_h_dptr(dentry, bindex);
4a4d8108 21732+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
c1595e42
JR
21733+ h_path->dentry = au_plink_lkup(inode, bindex);
21734+ if (IS_ERR(h_path->dentry))
21735+ /* pretending success */
21736+ h_path->dentry = NULL;
21737+ else
21738+ dput(h_path->dentry);
4a4d8108 21739+ }
c1595e42
JR
21740+
21741+out:
21742+ return err;
21743+}
21744+
0b2a12c6
JR
21745+static int aufs_getattr(struct user_namespace *userns, const struct path *path,
21746+ struct kstat *st, u32 request, unsigned int query)
c1595e42
JR
21747+{
21748+ int err;
21749+ unsigned char positive;
21750+ struct path h_path;
521ced18 21751+ struct dentry *dentry;
c1595e42
JR
21752+ struct inode *inode;
21753+ struct super_block *sb;
21754+
521ced18 21755+ dentry = path->dentry;
5527c038 21756+ inode = d_inode(dentry);
c1595e42
JR
21757+ sb = dentry->d_sb;
21758+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21759+ if (unlikely(err))
21760+ goto out;
42b5c33a
AM
21761+ err = au_h_path_getattr(dentry, /*inode*/NULL, /*force*/0, &h_path,
21762+ /*locked*/0);
c1595e42
JR
21763+ if (unlikely(err))
21764+ goto out_si;
c06a8ce3 21765+ if (unlikely(!h_path.dentry))
c1595e42 21766+ /* illegally overlapped or something */
4a4d8108
AM
21767+ goto out_fill; /* pretending success */
21768+
5527c038 21769+ positive = d_is_positive(h_path.dentry);
4a4d8108 21770+ if (positive)
521ced18
JR
21771+ /* no vfsub version */
21772+ err = vfs_getattr(&h_path, st, request, query);
4a4d8108
AM
21773+ if (!err) {
21774+ if (positive)
c06a8ce3 21775+ au_refresh_iattr(inode, st,
5527c038 21776+ d_inode(h_path.dentry)->i_nlink);
4a4d8108 21777+ goto out_fill; /* success */
1facf9fc 21778+ }
7f207e10 21779+ AuTraceErr(err);
c1595e42 21780+ goto out_di;
4a4d8108 21781+
4f0767ce 21782+out_fill:
0b2a12c6 21783+ generic_fillattr(userns, inode, st);
c1595e42 21784+out_di:
4a4d8108 21785+ di_read_unlock(dentry, AuLock_IR);
c1595e42 21786+out_si:
4a4d8108 21787+ si_read_unlock(sb);
7f207e10
AM
21788+out:
21789+ AuTraceErr(err);
4a4d8108 21790+ return err;
1facf9fc 21791+}
21792+
21793+/* ---------------------------------------------------------------------- */
21794+
febd17d6
JR
21795+static const char *aufs_get_link(struct dentry *dentry, struct inode *inode,
21796+ struct delayed_call *done)
4a4d8108 21797+{
c2c0f25c 21798+ const char *ret;
c2c0f25c 21799+ struct dentry *h_dentry;
febd17d6 21800+ struct inode *h_inode;
4a4d8108 21801+ int err;
c2c0f25c 21802+ aufs_bindex_t bindex;
1facf9fc 21803+
79b8bda9 21804+ ret = NULL; /* suppress a warning */
febd17d6
JR
21805+ err = -ECHILD;
21806+ if (!dentry)
21807+ goto out;
21808+
027c5e7a
AM
21809+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
21810+ if (unlikely(err))
c2c0f25c 21811+ goto out;
027c5e7a
AM
21812+
21813+ err = au_d_hashed_positive(dentry);
c2c0f25c
AM
21814+ if (unlikely(err))
21815+ goto out_unlock;
21816+
21817+ err = -EINVAL;
21818+ inode = d_inode(dentry);
5afbbe0d 21819+ bindex = au_ibtop(inode);
c2c0f25c 21820+ h_inode = au_h_iptr(inode, bindex);
febd17d6 21821+ if (unlikely(!h_inode->i_op->get_link))
c2c0f25c
AM
21822+ goto out_unlock;
21823+
21824+ err = -EBUSY;
21825+ h_dentry = NULL;
5afbbe0d 21826+ if (au_dbtop(dentry) <= bindex) {
c2c0f25c
AM
21827+ h_dentry = au_h_dptr(dentry, bindex);
21828+ if (h_dentry)
21829+ dget(h_dentry);
027c5e7a 21830+ }
c2c0f25c
AM
21831+ if (!h_dentry) {
21832+ h_dentry = d_find_any_alias(h_inode);
21833+ if (IS_ERR(h_dentry)) {
21834+ err = PTR_ERR(h_dentry);
febd17d6 21835+ goto out_unlock;
c2c0f25c
AM
21836+ }
21837+ }
21838+ if (unlikely(!h_dentry))
febd17d6 21839+ goto out_unlock;
1facf9fc 21840+
c2c0f25c 21841+ err = 0;
062440b3 21842+ AuDbg("%ps\n", h_inode->i_op->get_link);
c2c0f25c 21843+ AuDbgDentry(h_dentry);
f2c43d5f 21844+ ret = vfs_get_link(h_dentry, done);
c2c0f25c 21845+ dput(h_dentry);
febd17d6
JR
21846+ if (IS_ERR(ret))
21847+ err = PTR_ERR(ret);
c2c0f25c 21848+
c2c0f25c
AM
21849+out_unlock:
21850+ aufs_read_unlock(dentry, AuLock_IR);
4f0767ce 21851+out:
c2c0f25c
AM
21852+ if (unlikely(err))
21853+ ret = ERR_PTR(err);
21854+ AuTraceErrPtr(ret);
21855+ return ret;
4a4d8108 21856+}
1facf9fc 21857+
4a4d8108 21858+/* ---------------------------------------------------------------------- */
1facf9fc 21859+
e2f27e51
AM
21860+static int au_is_special(struct inode *inode)
21861+{
21862+ return (inode->i_mode & (S_IFBLK | S_IFCHR | S_IFIFO | S_IFSOCK));
21863+}
21864+
acd2b654
AM
21865+static int aufs_update_time(struct inode *inode, struct timespec64 *ts,
21866+ int flags)
4a4d8108 21867+{
0c3ec466 21868+ int err;
e2f27e51 21869+ aufs_bindex_t bindex;
0c3ec466
AM
21870+ struct super_block *sb;
21871+ struct inode *h_inode;
e2f27e51 21872+ struct vfsmount *h_mnt;
0c3ec466
AM
21873+
21874+ sb = inode->i_sb;
e2f27e51
AM
21875+ WARN_ONCE((flags & S_ATIME) && !IS_NOATIME(inode),
21876+ "unexpected s_flags 0x%lx", sb->s_flags);
21877+
0c3ec466
AM
21878+ /* mmap_sem might be acquired already, cf. aufs_mmap() */
21879+ lockdep_off();
21880+ si_read_lock(sb, AuLock_FLUSH);
21881+ ii_write_lock_child(inode);
e2f27e51
AM
21882+
21883+ err = 0;
21884+ bindex = au_ibtop(inode);
21885+ h_inode = au_h_iptr(inode, bindex);
21886+ if (!au_test_ro(sb, bindex, inode)) {
21887+ h_mnt = au_sbr_mnt(sb, bindex);
21888+ err = vfsub_mnt_want_write(h_mnt);
21889+ if (!err) {
21890+ err = vfsub_update_time(h_inode, ts, flags);
21891+ vfsub_mnt_drop_write(h_mnt);
21892+ }
21893+ } else if (au_is_special(h_inode)) {
21894+ /*
21895+ * Never copy-up here.
21896+ * These special files may already be opened and used for
21897+ * communicating. If we copied it up, then the communication
21898+ * would be corrupted.
21899+ */
21900+ AuWarn1("timestamps for i%lu are ignored "
21901+ "since it is on readonly branch (hi%lu).\n",
21902+ inode->i_ino, h_inode->i_ino);
21903+ } else if (flags & ~S_ATIME) {
21904+ err = -EIO;
21905+ AuIOErr1("unexpected flags 0x%x\n", flags);
21906+ AuDebugOn(1);
21907+ }
21908+
38d290e6
JR
21909+ if (!err)
21910+ au_cpup_attr_timesizes(inode);
0c3ec466
AM
21911+ ii_write_unlock(inode);
21912+ si_read_unlock(sb);
21913+ lockdep_on();
38d290e6
JR
21914+
21915+ if (!err && (flags & S_VERSION))
21916+ inode_inc_iversion(inode);
21917+
0c3ec466 21918+ return err;
4a4d8108 21919+}
1facf9fc 21920+
4a4d8108 21921+/* ---------------------------------------------------------------------- */
1308ab2a 21922+
b95c5147
AM
21923+/* no getattr version will be set by module.c:aufs_init() */
21924+struct inode_operations aufs_iop_nogetattr[AuIop_Last],
21925+ aufs_iop[] = {
21926+ [AuIop_SYMLINK] = {
21927+ .permission = aufs_permission,
c1595e42 21928+#ifdef CONFIG_FS_POSIX_ACL
b95c5147
AM
21929+ .get_acl = aufs_get_acl,
21930+ .set_acl = aufs_set_acl, /* unsupport for symlink? */
c1595e42
JR
21931+#endif
21932+
b95c5147
AM
21933+ .setattr = aufs_setattr,
21934+ .getattr = aufs_getattr,
0c3ec466 21935+
c1595e42 21936+#ifdef CONFIG_AUFS_XATTR
b95c5147 21937+ .listxattr = aufs_listxattr,
c1595e42
JR
21938+#endif
21939+
febd17d6 21940+ .get_link = aufs_get_link,
0c3ec466 21941+
b95c5147
AM
21942+ /* .update_time = aufs_update_time */
21943+ },
21944+ [AuIop_DIR] = {
21945+ .create = aufs_create,
21946+ .lookup = aufs_lookup,
21947+ .link = aufs_link,
21948+ .unlink = aufs_unlink,
21949+ .symlink = aufs_symlink,
21950+ .mkdir = aufs_mkdir,
21951+ .rmdir = aufs_rmdir,
21952+ .mknod = aufs_mknod,
21953+ .rename = aufs_rename,
21954+
21955+ .permission = aufs_permission,
c1595e42 21956+#ifdef CONFIG_FS_POSIX_ACL
b95c5147
AM
21957+ .get_acl = aufs_get_acl,
21958+ .set_acl = aufs_set_acl,
c1595e42
JR
21959+#endif
21960+
b95c5147
AM
21961+ .setattr = aufs_setattr,
21962+ .getattr = aufs_getattr,
0c3ec466 21963+
c1595e42 21964+#ifdef CONFIG_AUFS_XATTR
b95c5147 21965+ .listxattr = aufs_listxattr,
c1595e42
JR
21966+#endif
21967+
b95c5147
AM
21968+ .update_time = aufs_update_time,
21969+ .atomic_open = aufs_atomic_open,
21970+ .tmpfile = aufs_tmpfile
21971+ },
21972+ [AuIop_OTHER] = {
21973+ .permission = aufs_permission,
c1595e42 21974+#ifdef CONFIG_FS_POSIX_ACL
b95c5147
AM
21975+ .get_acl = aufs_get_acl,
21976+ .set_acl = aufs_set_acl,
c1595e42
JR
21977+#endif
21978+
b95c5147
AM
21979+ .setattr = aufs_setattr,
21980+ .getattr = aufs_getattr,
0c3ec466 21981+
c1595e42 21982+#ifdef CONFIG_AUFS_XATTR
b95c5147 21983+ .listxattr = aufs_listxattr,
c1595e42
JR
21984+#endif
21985+
b95c5147
AM
21986+ .update_time = aufs_update_time
21987+ }
4a4d8108 21988+};
7f207e10 21989diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
eca34b5c 21990--- /usr/share/empty/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6
JR
21991+++ linux/fs/aufs/i_op_del.c 2021-05-02 20:15:14.673337458 +0200
21992@@ -0,0 +1,515 @@
cd7a4cd9 21993+// SPDX-License-Identifier: GPL-2.0
1facf9fc 21994+/*
d58c55f2 21995+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 21996+ *
21997+ * This program, aufs is free software; you can redistribute it and/or modify
21998+ * it under the terms of the GNU General Public License as published by
21999+ * the Free Software Foundation; either version 2 of the License, or
22000+ * (at your option) any later version.
dece6358
AM
22001+ *
22002+ * This program is distributed in the hope that it will be useful,
22003+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22004+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22005+ * GNU General Public License for more details.
22006+ *
22007+ * You should have received a copy of the GNU General Public License
523b37e3 22008+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 22009+ */
22010+
22011+/*
4a4d8108 22012+ * inode operations (del entry)
1308ab2a 22013+ */
dece6358 22014+
eca801bf 22015+#include <linux/iversion.h>
1308ab2a 22016+#include "aufs.h"
dece6358 22017+
4a4d8108
AM
22018+/*
22019+ * decide if a new whiteout for @dentry is necessary or not.
22020+ * when it is necessary, prepare the parent dir for the upper branch whose
22021+ * branch index is @bcpup for creation. the actual creation of the whiteout will
22022+ * be done by caller.
22023+ * return value:
22024+ * 0: wh is unnecessary
22025+ * plus: wh is necessary
22026+ * minus: error
22027+ */
22028+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1308ab2a 22029+{
4a4d8108 22030+ int need_wh, err;
5afbbe0d 22031+ aufs_bindex_t btop;
4a4d8108 22032+ struct super_block *sb;
dece6358 22033+
4a4d8108 22034+ sb = dentry->d_sb;
5afbbe0d 22035+ btop = au_dbtop(dentry);
4a4d8108 22036+ if (*bcpup < 0) {
5afbbe0d
AM
22037+ *bcpup = btop;
22038+ if (au_test_ro(sb, btop, d_inode(dentry))) {
4a4d8108
AM
22039+ err = AuWbrCopyup(au_sbi(sb), dentry);
22040+ *bcpup = err;
22041+ if (unlikely(err < 0))
22042+ goto out;
22043+ }
22044+ } else
5afbbe0d 22045+ AuDebugOn(btop < *bcpup
5527c038 22046+ || au_test_ro(sb, *bcpup, d_inode(dentry)));
5afbbe0d 22047+ AuDbg("bcpup %d, btop %d\n", *bcpup, btop);
1308ab2a 22048+
5afbbe0d 22049+ if (*bcpup != btop) {
4a4d8108
AM
22050+ err = au_cpup_dirs(dentry, *bcpup);
22051+ if (unlikely(err))
22052+ goto out;
22053+ need_wh = 1;
22054+ } else {
027c5e7a 22055+ struct au_dinfo *dinfo, *tmp;
4a4d8108 22056+
027c5e7a
AM
22057+ need_wh = -ENOMEM;
22058+ dinfo = au_di(dentry);
22059+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
22060+ if (tmp) {
22061+ au_di_cp(tmp, dinfo);
22062+ au_di_swap(tmp, dinfo);
22063+ /* returns the number of positive dentries */
5afbbe0d
AM
22064+ need_wh = au_lkup_dentry(dentry, btop + 1,
22065+ /* AuLkup_IGNORE_PERM */ 0);
027c5e7a
AM
22066+ au_di_swap(tmp, dinfo);
22067+ au_rw_write_unlock(&tmp->di_rwsem);
22068+ au_di_free(tmp);
4a4d8108
AM
22069+ }
22070+ }
22071+ AuDbg("need_wh %d\n", need_wh);
22072+ err = need_wh;
22073+
4f0767ce 22074+out:
4a4d8108 22075+ return err;
1facf9fc 22076+}
22077+
4a4d8108
AM
22078+/*
22079+ * simple tests for the del-entry operations.
22080+ * following the checks in vfs, plus the parent-child relationship.
22081+ */
22082+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
22083+ struct dentry *h_parent, int isdir)
1facf9fc 22084+{
4a4d8108
AM
22085+ int err;
22086+ umode_t h_mode;
22087+ struct dentry *h_dentry, *h_latest;
1308ab2a 22088+ struct inode *h_inode;
0b2a12c6 22089+ struct user_namespace *h_userns;
1facf9fc 22090+
4a4d8108 22091+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 22092+ if (d_really_is_positive(dentry)) {
4a4d8108 22093+ err = -ENOENT;
5527c038
JR
22094+ if (unlikely(d_is_negative(h_dentry)))
22095+ goto out;
22096+ h_inode = d_inode(h_dentry);
22097+ if (unlikely(!h_inode->i_nlink))
4a4d8108 22098+ goto out;
1facf9fc 22099+
4a4d8108
AM
22100+ h_mode = h_inode->i_mode;
22101+ if (!isdir) {
22102+ err = -EISDIR;
22103+ if (unlikely(S_ISDIR(h_mode)))
22104+ goto out;
22105+ } else if (unlikely(!S_ISDIR(h_mode))) {
22106+ err = -ENOTDIR;
22107+ goto out;
22108+ }
22109+ } else {
22110+ /* rename(2) case */
22111+ err = -EIO;
5527c038 22112+ if (unlikely(d_is_positive(h_dentry)))
4a4d8108
AM
22113+ goto out;
22114+ }
1facf9fc 22115+
4a4d8108
AM
22116+ err = -ENOENT;
22117+ /* expected parent dir is locked */
22118+ if (unlikely(h_parent != h_dentry->d_parent))
22119+ goto out;
22120+ err = 0;
22121+
22122+ /*
22123+ * rmdir a dir may break the consistency on some filesystem.
22124+ * let's try heavy test.
22125+ */
22126+ err = -EACCES;
0b2a12c6 22127+ h_userns = au_sbr_userns(dentry->d_sb, bindex);
076b876e 22128+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1)
0b2a12c6 22129+ && au_test_h_perm(h_userns, d_inode(h_parent),
076b876e 22130+ MAY_EXEC | MAY_WRITE)))
4a4d8108
AM
22131+ goto out;
22132+
0b2a12c6 22133+ h_latest = au_sio_lkup_one(h_userns, &dentry->d_name, h_parent);
4a4d8108
AM
22134+ err = -EIO;
22135+ if (IS_ERR(h_latest))
22136+ goto out;
22137+ if (h_latest == h_dentry)
22138+ err = 0;
22139+ dput(h_latest);
22140+
4f0767ce 22141+out:
4a4d8108 22142+ return err;
1308ab2a 22143+}
1facf9fc 22144+
4a4d8108
AM
22145+/*
22146+ * decide the branch where we operate for @dentry. the branch index will be set
acd2b654 22147+ * @rbcpup. after deciding it, 'pin' it and store the timestamps of the parent
4a4d8108
AM
22148+ * dir for reverting.
22149+ * when a new whiteout is necessary, create it.
22150+ */
22151+static struct dentry*
22152+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
22153+ struct au_dtime *dt, struct au_pin *pin)
1308ab2a 22154+{
4a4d8108
AM
22155+ struct dentry *wh_dentry;
22156+ struct super_block *sb;
22157+ struct path h_path;
22158+ int err, need_wh;
22159+ unsigned int udba;
22160+ aufs_bindex_t bcpup;
dece6358 22161+
4a4d8108
AM
22162+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
22163+ wh_dentry = ERR_PTR(need_wh);
22164+ if (unlikely(need_wh < 0))
22165+ goto out;
22166+
22167+ sb = dentry->d_sb;
22168+ udba = au_opt_udba(sb);
22169+ bcpup = *rbcpup;
22170+ err = au_pin(pin, dentry, bcpup, udba,
22171+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
22172+ wh_dentry = ERR_PTR(err);
22173+ if (unlikely(err))
22174+ goto out;
22175+
22176+ h_path.dentry = au_pinned_h_parent(pin);
22177+ if (udba != AuOpt_UDBA_NONE
5afbbe0d 22178+ && au_dbtop(dentry) == bcpup) {
4a4d8108
AM
22179+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
22180+ wh_dentry = ERR_PTR(err);
22181+ if (unlikely(err))
22182+ goto out_unpin;
22183+ }
22184+
22185+ h_path.mnt = au_sbr_mnt(sb, bcpup);
22186+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
22187+ wh_dentry = NULL;
22188+ if (!need_wh)
22189+ goto out; /* success, no need to create whiteout */
22190+
22191+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
22192+ if (IS_ERR(wh_dentry))
22193+ goto out_unpin;
22194+
22195+ /* returns with the parent is locked and wh_dentry is dget-ed */
22196+ goto out; /* success */
22197+
4f0767ce 22198+out_unpin:
4a4d8108 22199+ au_unpin(pin);
4f0767ce 22200+out:
4a4d8108 22201+ return wh_dentry;
1facf9fc 22202+}
22203+
4a4d8108
AM
22204+/*
22205+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
22206+ * in order to be revertible and save time for removing many child whiteouts
22207+ * under the dir.
22208+ * returns 1 when there are too many child whiteout and caller should remove
22209+ * them asynchronously. returns 0 when the number of children is enough small to
22210+ * remove now or the branch fs is a remote fs.
22211+ * otherwise return an error.
22212+ */
22213+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
22214+ struct au_nhash *whlist, struct inode *dir)
1facf9fc 22215+{
4a4d8108
AM
22216+ int rmdir_later, err, dirwh;
22217+ struct dentry *h_dentry;
22218+ struct super_block *sb;
5527c038 22219+ struct inode *inode;
4a4d8108
AM
22220+
22221+ sb = dentry->d_sb;
22222+ SiMustAnyLock(sb);
22223+ h_dentry = au_h_dptr(dentry, bindex);
22224+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
22225+ if (unlikely(err))
22226+ goto out;
22227+
22228+ /* stop monitoring */
5527c038
JR
22229+ inode = d_inode(dentry);
22230+ au_hn_free(au_hi(inode, bindex));
4a4d8108
AM
22231+
22232+ if (!au_test_fs_remote(h_dentry->d_sb)) {
22233+ dirwh = au_sbi(sb)->si_dirwh;
22234+ rmdir_later = (dirwh <= 1);
22235+ if (!rmdir_later)
22236+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
22237+ dirwh);
22238+ if (rmdir_later)
22239+ return rmdir_later;
22240+ }
1facf9fc 22241+
4a4d8108
AM
22242+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
22243+ if (unlikely(err)) {
523b37e3
AM
22244+ AuIOErr("rmdir %pd, b%d failed, %d. ignored\n",
22245+ h_dentry, bindex, err);
4a4d8108
AM
22246+ err = 0;
22247+ }
dece6358 22248+
4f0767ce 22249+out:
4a4d8108
AM
22250+ AuTraceErr(err);
22251+ return err;
22252+}
1308ab2a 22253+
4a4d8108
AM
22254+/*
22255+ * final procedure for deleting a entry.
22256+ * maintain dentry and iattr.
22257+ */
22258+static void epilog(struct inode *dir, struct dentry *dentry,
22259+ aufs_bindex_t bindex)
22260+{
22261+ struct inode *inode;
1308ab2a 22262+
5527c038 22263+ inode = d_inode(dentry);
4a4d8108
AM
22264+ d_drop(dentry);
22265+ inode->i_ctime = dir->i_ctime;
1308ab2a 22266+
b912730e 22267+ au_dir_ts(dir, bindex);
be118d29 22268+ inode_inc_iversion(dir);
1facf9fc 22269+}
22270+
4a4d8108
AM
22271+/*
22272+ * when an error happened, remove the created whiteout and revert everything.
22273+ */
7f207e10
AM
22274+static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex,
22275+ aufs_bindex_t bwh, struct dentry *wh_dentry,
22276+ struct dentry *dentry, struct au_dtime *dt)
1facf9fc 22277+{
4a4d8108
AM
22278+ int rerr;
22279+ struct path h_path = {
22280+ .dentry = wh_dentry,
7f207e10 22281+ .mnt = au_sbr_mnt(dir->i_sb, bindex)
4a4d8108 22282+ };
dece6358 22283+
7f207e10 22284+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry);
4a4d8108
AM
22285+ if (!rerr) {
22286+ au_set_dbwh(dentry, bwh);
22287+ au_dtime_revert(dt);
22288+ return 0;
22289+ }
dece6358 22290+
523b37e3 22291+ AuIOErr("%pd reverting whiteout failed(%d, %d)\n", dentry, err, rerr);
4a4d8108 22292+ return -EIO;
1facf9fc 22293+}
22294+
4a4d8108 22295+/* ---------------------------------------------------------------------- */
1facf9fc 22296+
4a4d8108 22297+int aufs_unlink(struct inode *dir, struct dentry *dentry)
1308ab2a 22298+{
4a4d8108 22299+ int err;
5afbbe0d 22300+ aufs_bindex_t bwh, bindex, btop;
523b37e3 22301+ struct inode *inode, *h_dir, *delegated;
4a4d8108 22302+ struct dentry *parent, *wh_dentry;
acd2b654 22303+ /* to reduce stack size */
c2b27bf2
AM
22304+ struct {
22305+ struct au_dtime dt;
22306+ struct au_pin pin;
22307+ struct path h_path;
22308+ } *a;
1facf9fc 22309+
4a4d8108 22310+ IMustLock(dir);
027c5e7a 22311+
c2b27bf2
AM
22312+ err = -ENOMEM;
22313+ a = kmalloc(sizeof(*a), GFP_NOFS);
22314+ if (unlikely(!a))
22315+ goto out;
22316+
027c5e7a
AM
22317+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
22318+ if (unlikely(err))
c2b27bf2 22319+ goto out_free;
027c5e7a
AM
22320+ err = au_d_hashed_positive(dentry);
22321+ if (unlikely(err))
22322+ goto out_unlock;
5527c038 22323+ inode = d_inode(dentry);
4a4d8108 22324+ IMustLock(inode);
027c5e7a 22325+ err = -EISDIR;
2000de60 22326+ if (unlikely(d_is_dir(dentry)))
027c5e7a 22327+ goto out_unlock; /* possible? */
1facf9fc 22328+
5afbbe0d 22329+ btop = au_dbtop(dentry);
4a4d8108
AM
22330+ bwh = au_dbwh(dentry);
22331+ bindex = -1;
027c5e7a
AM
22332+ parent = dentry->d_parent; /* dir inode is locked */
22333+ di_write_lock_parent(parent);
c2b27bf2
AM
22334+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &a->dt,
22335+ &a->pin);
4a4d8108
AM
22336+ err = PTR_ERR(wh_dentry);
22337+ if (IS_ERR(wh_dentry))
027c5e7a 22338+ goto out_parent;
1facf9fc 22339+
5afbbe0d
AM
22340+ a->h_path.mnt = au_sbr_mnt(dentry->d_sb, btop);
22341+ a->h_path.dentry = au_h_dptr(dentry, btop);
c2b27bf2 22342+ dget(a->h_path.dentry);
5afbbe0d 22343+ if (bindex == btop) {
c2b27bf2 22344+ h_dir = au_pinned_h_dir(&a->pin);
523b37e3
AM
22345+ delegated = NULL;
22346+ err = vfsub_unlink(h_dir, &a->h_path, &delegated, /*force*/0);
22347+ if (unlikely(err == -EWOULDBLOCK)) {
22348+ pr_warn("cannot retry for NFSv4 delegation"
22349+ " for an internal unlink\n");
22350+ iput(delegated);
22351+ }
4a4d8108
AM
22352+ } else {
22353+ /* dir inode is locked */
5527c038 22354+ h_dir = d_inode(wh_dentry->d_parent);
4a4d8108
AM
22355+ IMustLock(h_dir);
22356+ err = 0;
22357+ }
dece6358 22358+
4a4d8108 22359+ if (!err) {
7f207e10 22360+ vfsub_drop_nlink(inode);
4a4d8108
AM
22361+ epilog(dir, dentry, bindex);
22362+
22363+ /* update target timestamps */
5afbbe0d 22364+ if (bindex == btop) {
c2b27bf2
AM
22365+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL);
22366+ /*ignore*/
5527c038 22367+ inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
4a4d8108
AM
22368+ } else
22369+ /* todo: this timestamp may be reverted later */
22370+ inode->i_ctime = h_dir->i_ctime;
027c5e7a 22371+ goto out_unpin; /* success */
1facf9fc 22372+ }
22373+
4a4d8108
AM
22374+ /* revert */
22375+ if (wh_dentry) {
22376+ int rerr;
22377+
c2b27bf2
AM
22378+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry,
22379+ &a->dt);
4a4d8108
AM
22380+ if (rerr)
22381+ err = rerr;
dece6358 22382+ }
1facf9fc 22383+
027c5e7a 22384+out_unpin:
c2b27bf2 22385+ au_unpin(&a->pin);
4a4d8108 22386+ dput(wh_dentry);
c2b27bf2 22387+ dput(a->h_path.dentry);
027c5e7a 22388+out_parent:
4a4d8108 22389+ di_write_unlock(parent);
027c5e7a 22390+out_unlock:
4a4d8108 22391+ aufs_read_unlock(dentry, AuLock_DW);
c2b27bf2 22392+out_free:
9f237c51 22393+ au_kfree_rcu(a);
027c5e7a 22394+out:
4a4d8108 22395+ return err;
dece6358
AM
22396+}
22397+
4a4d8108 22398+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
1308ab2a 22399+{
4a4d8108 22400+ int err, rmdir_later;
5afbbe0d 22401+ aufs_bindex_t bwh, bindex, btop;
4a4d8108
AM
22402+ struct inode *inode;
22403+ struct dentry *parent, *wh_dentry, *h_dentry;
22404+ struct au_whtmp_rmdir *args;
acd2b654 22405+ /* to reduce stack size */
c2b27bf2
AM
22406+ struct {
22407+ struct au_dtime dt;
22408+ struct au_pin pin;
22409+ } *a;
1facf9fc 22410+
4a4d8108 22411+ IMustLock(dir);
027c5e7a 22412+
c2b27bf2
AM
22413+ err = -ENOMEM;
22414+ a = kmalloc(sizeof(*a), GFP_NOFS);
22415+ if (unlikely(!a))
22416+ goto out;
22417+
027c5e7a
AM
22418+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
22419+ if (unlikely(err))
c2b27bf2 22420+ goto out_free;
53392da6
AM
22421+ err = au_alive_dir(dentry);
22422+ if (unlikely(err))
027c5e7a 22423+ goto out_unlock;
5527c038 22424+ inode = d_inode(dentry);
4a4d8108 22425+ IMustLock(inode);
027c5e7a 22426+ err = -ENOTDIR;
2000de60 22427+ if (unlikely(!d_is_dir(dentry)))
027c5e7a 22428+ goto out_unlock; /* possible? */
dece6358 22429+
4a4d8108
AM
22430+ err = -ENOMEM;
22431+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
22432+ if (unlikely(!args))
22433+ goto out_unlock;
dece6358 22434+
4a4d8108
AM
22435+ parent = dentry->d_parent; /* dir inode is locked */
22436+ di_write_lock_parent(parent);
22437+ err = au_test_empty(dentry, &args->whlist);
22438+ if (unlikely(err))
027c5e7a 22439+ goto out_parent;
1facf9fc 22440+
5afbbe0d 22441+ btop = au_dbtop(dentry);
4a4d8108
AM
22442+ bwh = au_dbwh(dentry);
22443+ bindex = -1;
c2b27bf2
AM
22444+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &a->dt,
22445+ &a->pin);
4a4d8108
AM
22446+ err = PTR_ERR(wh_dentry);
22447+ if (IS_ERR(wh_dentry))
027c5e7a 22448+ goto out_parent;
1facf9fc 22449+
5afbbe0d 22450+ h_dentry = au_h_dptr(dentry, btop);
4a4d8108
AM
22451+ dget(h_dentry);
22452+ rmdir_later = 0;
5afbbe0d
AM
22453+ if (bindex == btop) {
22454+ err = renwh_and_rmdir(dentry, btop, &args->whlist, dir);
4a4d8108
AM
22455+ if (err > 0) {
22456+ rmdir_later = err;
22457+ err = 0;
22458+ }
22459+ } else {
22460+ /* stop monitoring */
5afbbe0d 22461+ au_hn_free(au_hi(inode, btop));
4a4d8108
AM
22462+
22463+ /* dir inode is locked */
5527c038 22464+ IMustLock(d_inode(wh_dentry->d_parent));
1facf9fc 22465+ err = 0;
22466+ }
22467+
4a4d8108 22468+ if (!err) {
027c5e7a 22469+ vfsub_dead_dir(inode);
4a4d8108
AM
22470+ au_set_dbdiropq(dentry, -1);
22471+ epilog(dir, dentry, bindex);
1308ab2a 22472+
4a4d8108 22473+ if (rmdir_later) {
5afbbe0d 22474+ au_whtmp_kick_rmdir(dir, btop, h_dentry, args);
4a4d8108
AM
22475+ args = NULL;
22476+ }
1308ab2a 22477+
4a4d8108 22478+ goto out_unpin; /* success */
1facf9fc 22479+ }
22480+
4a4d8108
AM
22481+ /* revert */
22482+ AuLabel(revert);
22483+ if (wh_dentry) {
22484+ int rerr;
1308ab2a 22485+
c2b27bf2
AM
22486+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry,
22487+ &a->dt);
4a4d8108
AM
22488+ if (rerr)
22489+ err = rerr;
1facf9fc 22490+ }
22491+
4f0767ce 22492+out_unpin:
c2b27bf2 22493+ au_unpin(&a->pin);
4a4d8108
AM
22494+ dput(wh_dentry);
22495+ dput(h_dentry);
027c5e7a 22496+out_parent:
4a4d8108
AM
22497+ di_write_unlock(parent);
22498+ if (args)
22499+ au_whtmp_rmdir_free(args);
4f0767ce 22500+out_unlock:
4a4d8108 22501+ aufs_read_unlock(dentry, AuLock_DW);
c2b27bf2 22502+out_free:
9f237c51 22503+ au_kfree_rcu(a);
4f0767ce 22504+out:
4a4d8108
AM
22505+ AuTraceErr(err);
22506+ return err;
dece6358 22507+}
7f207e10 22508diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
eca34b5c 22509--- /usr/share/empty/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6
JR
22510+++ linux/fs/aufs/i_op_ren.c 2021-05-02 20:15:14.673337458 +0200
22511@@ -0,0 +1,1251 @@
cd7a4cd9 22512+// SPDX-License-Identifier: GPL-2.0
1facf9fc 22513+/*
d58c55f2 22514+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 22515+ *
22516+ * This program, aufs is free software; you can redistribute it and/or modify
22517+ * it under the terms of the GNU General Public License as published by
22518+ * the Free Software Foundation; either version 2 of the License, or
22519+ * (at your option) any later version.
dece6358
AM
22520+ *
22521+ * This program is distributed in the hope that it will be useful,
22522+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22523+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22524+ * GNU General Public License for more details.
22525+ *
22526+ * You should have received a copy of the GNU General Public License
523b37e3 22527+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 22528+ */
22529+
22530+/*
4a4d8108
AM
22531+ * inode operation (rename entry)
22532+ * todo: this is crazy monster
1facf9fc 22533+ */
22534+
eca801bf 22535+#include <linux/iversion.h>
1facf9fc 22536+#include "aufs.h"
22537+
4a4d8108
AM
22538+enum { AuSRC, AuDST, AuSrcDst };
22539+enum { AuPARENT, AuCHILD, AuParentChild };
1facf9fc 22540+
f2c43d5f
AM
22541+#define AuRen_ISDIR_SRC 1
22542+#define AuRen_ISDIR_DST (1 << 1)
22543+#define AuRen_ISSAMEDIR (1 << 2)
22544+#define AuRen_WHSRC (1 << 3)
22545+#define AuRen_WHDST (1 << 4)
22546+#define AuRen_MNT_WRITE (1 << 5)
22547+#define AuRen_DT_DSTDIR (1 << 6)
22548+#define AuRen_DIROPQ_SRC (1 << 7)
22549+#define AuRen_DIROPQ_DST (1 << 8)
8b6a4947
AM
22550+#define AuRen_DIRREN (1 << 9)
22551+#define AuRen_DROPPED_SRC (1 << 10)
22552+#define AuRen_DROPPED_DST (1 << 11)
4a4d8108 22553+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
7f207e10
AM
22554+#define au_fset_ren(flags, name) \
22555+ do { (flags) |= AuRen_##name; } while (0)
22556+#define au_fclr_ren(flags, name) \
22557+ do { (flags) &= ~AuRen_##name; } while (0)
1facf9fc 22558+
8b6a4947
AM
22559+#ifndef CONFIG_AUFS_DIRREN
22560+#undef AuRen_DIRREN
22561+#define AuRen_DIRREN 0
22562+#endif
22563+
4a4d8108
AM
22564+struct au_ren_args {
22565+ struct {
22566+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
22567+ *wh_dentry;
22568+ struct inode *dir, *inode;
f2c43d5f 22569+ struct au_hinode *hdir, *hinode;
4a4d8108 22570+ struct au_dtime dt[AuParentChild];
f2c43d5f 22571+ aufs_bindex_t btop, bdiropq;
4a4d8108 22572+ } sd[AuSrcDst];
1facf9fc 22573+
4a4d8108
AM
22574+#define src_dentry sd[AuSRC].dentry
22575+#define src_dir sd[AuSRC].dir
22576+#define src_inode sd[AuSRC].inode
22577+#define src_h_dentry sd[AuSRC].h_dentry
22578+#define src_parent sd[AuSRC].parent
22579+#define src_h_parent sd[AuSRC].h_parent
22580+#define src_wh_dentry sd[AuSRC].wh_dentry
22581+#define src_hdir sd[AuSRC].hdir
f2c43d5f 22582+#define src_hinode sd[AuSRC].hinode
4a4d8108
AM
22583+#define src_h_dir sd[AuSRC].hdir->hi_inode
22584+#define src_dt sd[AuSRC].dt
5afbbe0d 22585+#define src_btop sd[AuSRC].btop
f2c43d5f 22586+#define src_bdiropq sd[AuSRC].bdiropq
1facf9fc 22587+
4a4d8108
AM
22588+#define dst_dentry sd[AuDST].dentry
22589+#define dst_dir sd[AuDST].dir
22590+#define dst_inode sd[AuDST].inode
22591+#define dst_h_dentry sd[AuDST].h_dentry
22592+#define dst_parent sd[AuDST].parent
22593+#define dst_h_parent sd[AuDST].h_parent
22594+#define dst_wh_dentry sd[AuDST].wh_dentry
22595+#define dst_hdir sd[AuDST].hdir
f2c43d5f 22596+#define dst_hinode sd[AuDST].hinode
4a4d8108
AM
22597+#define dst_h_dir sd[AuDST].hdir->hi_inode
22598+#define dst_dt sd[AuDST].dt
5afbbe0d 22599+#define dst_btop sd[AuDST].btop
f2c43d5f 22600+#define dst_bdiropq sd[AuDST].bdiropq
4a4d8108
AM
22601+
22602+ struct dentry *h_trap;
22603+ struct au_branch *br;
4a4d8108
AM
22604+ struct path h_path;
22605+ struct au_nhash whlist;
f2c43d5f 22606+ aufs_bindex_t btgt, src_bwh;
1facf9fc 22607+
f2c43d5f
AM
22608+ struct {
22609+ unsigned short auren_flags;
22610+ unsigned char flags; /* syscall parameter */
22611+ unsigned char exchange;
22612+ } __packed;
1facf9fc 22613+
4a4d8108
AM
22614+ struct au_whtmp_rmdir *thargs;
22615+ struct dentry *h_dst;
8b6a4947 22616+ struct au_hinode *h_root;
4a4d8108 22617+};
1308ab2a 22618+
4a4d8108 22619+/* ---------------------------------------------------------------------- */
1308ab2a 22620+
4a4d8108
AM
22621+/*
22622+ * functions for reverting.
22623+ * when an error happened in a single rename systemcall, we should revert
79b8bda9 22624+ * everything as if nothing happened.
4a4d8108
AM
22625+ * we don't need to revert the copied-up/down the parent dir since they are
22626+ * harmless.
22627+ */
1facf9fc 22628+
4a4d8108
AM
22629+#define RevertFailure(fmt, ...) do { \
22630+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
22631+ ##__VA_ARGS__, err, rerr); \
22632+ err = -EIO; \
22633+} while (0)
1facf9fc 22634+
f2c43d5f 22635+static void au_ren_do_rev_diropq(int err, struct au_ren_args *a, int idx)
1facf9fc 22636+{
4a4d8108 22637+ int rerr;
f2c43d5f
AM
22638+ struct dentry *d;
22639+#define src_or_dst(member) a->sd[idx].member
1facf9fc 22640+
f2c43d5f
AM
22641+ d = src_or_dst(dentry); /* {src,dst}_dentry */
22642+ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD);
22643+ rerr = au_diropq_remove(d, a->btgt);
22644+ au_hn_inode_unlock(src_or_dst(hinode));
22645+ au_set_dbdiropq(d, src_or_dst(bdiropq));
4a4d8108 22646+ if (rerr)
f2c43d5f
AM
22647+ RevertFailure("remove diropq %pd", d);
22648+
22649+#undef src_or_dst_
22650+}
22651+
22652+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
22653+{
22654+ if (au_ftest_ren(a->auren_flags, DIROPQ_SRC))
22655+ au_ren_do_rev_diropq(err, a, AuSRC);
22656+ if (au_ftest_ren(a->auren_flags, DIROPQ_DST))
22657+ au_ren_do_rev_diropq(err, a, AuDST);
4a4d8108 22658+}
1facf9fc 22659+
4a4d8108
AM
22660+static void au_ren_rev_rename(int err, struct au_ren_args *a)
22661+{
22662+ int rerr;
523b37e3 22663+ struct inode *delegated;
1facf9fc 22664+
b4510431
AM
22665+ a->h_path.dentry = vfsub_lkup_one(&a->src_dentry->d_name,
22666+ a->src_h_parent);
4a4d8108
AM
22667+ rerr = PTR_ERR(a->h_path.dentry);
22668+ if (IS_ERR(a->h_path.dentry)) {
523b37e3 22669+ RevertFailure("lkup one %pd", a->src_dentry);
4a4d8108 22670+ return;
1facf9fc 22671+ }
22672+
523b37e3 22673+ delegated = NULL;
4a4d8108
AM
22674+ rerr = vfsub_rename(a->dst_h_dir,
22675+ au_h_dptr(a->src_dentry, a->btgt),
f2c43d5f 22676+ a->src_h_dir, &a->h_path, &delegated, a->flags);
523b37e3
AM
22677+ if (unlikely(rerr == -EWOULDBLOCK)) {
22678+ pr_warn("cannot retry for NFSv4 delegation"
22679+ " for an internal rename\n");
22680+ iput(delegated);
22681+ }
4a4d8108
AM
22682+ d_drop(a->h_path.dentry);
22683+ dput(a->h_path.dentry);
22684+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
22685+ if (rerr)
523b37e3 22686+ RevertFailure("rename %pd", a->src_dentry);
1facf9fc 22687+}
22688+
4a4d8108 22689+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
1facf9fc 22690+{
4a4d8108 22691+ int rerr;
523b37e3 22692+ struct inode *delegated;
dece6358 22693+
b4510431
AM
22694+ a->h_path.dentry = vfsub_lkup_one(&a->dst_dentry->d_name,
22695+ a->dst_h_parent);
4a4d8108
AM
22696+ rerr = PTR_ERR(a->h_path.dentry);
22697+ if (IS_ERR(a->h_path.dentry)) {
523b37e3 22698+ RevertFailure("lkup one %pd", a->dst_dentry);
4a4d8108
AM
22699+ return;
22700+ }
5527c038 22701+ if (d_is_positive(a->h_path.dentry)) {
4a4d8108
AM
22702+ d_drop(a->h_path.dentry);
22703+ dput(a->h_path.dentry);
22704+ return;
dece6358
AM
22705+ }
22706+
523b37e3
AM
22707+ delegated = NULL;
22708+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path,
f2c43d5f 22709+ &delegated, a->flags);
523b37e3
AM
22710+ if (unlikely(rerr == -EWOULDBLOCK)) {
22711+ pr_warn("cannot retry for NFSv4 delegation"
22712+ " for an internal rename\n");
22713+ iput(delegated);
22714+ }
4a4d8108
AM
22715+ d_drop(a->h_path.dentry);
22716+ dput(a->h_path.dentry);
22717+ if (!rerr)
22718+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
22719+ else
523b37e3 22720+ RevertFailure("rename %pd", a->h_dst);
4a4d8108 22721+}
1308ab2a 22722+
4a4d8108
AM
22723+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
22724+{
22725+ int rerr;
1308ab2a 22726+
4a4d8108
AM
22727+ a->h_path.dentry = a->src_wh_dentry;
22728+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
027c5e7a 22729+ au_set_dbwh(a->src_dentry, a->src_bwh);
4a4d8108 22730+ if (rerr)
523b37e3 22731+ RevertFailure("unlink %pd", a->src_wh_dentry);
4a4d8108 22732+}
4a4d8108 22733+#undef RevertFailure
1facf9fc 22734+
1308ab2a 22735+/* ---------------------------------------------------------------------- */
22736+
4a4d8108
AM
22737+/*
22738+ * when we have to copyup the renaming entry, do it with the rename-target name
22739+ * in order to minimize the cost (the later actual rename is unnecessary).
22740+ * otherwise rename it on the target branch.
22741+ */
22742+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 22743+{
dece6358 22744+ int err;
4a4d8108 22745+ struct dentry *d;
523b37e3 22746+ struct inode *delegated;
1facf9fc 22747+
4a4d8108 22748+ d = a->src_dentry;
5afbbe0d 22749+ if (au_dbtop(d) == a->btgt) {
4a4d8108 22750+ a->h_path.dentry = a->dst_h_dentry;
5afbbe0d 22751+ AuDebugOn(au_dbtop(d) != a->btgt);
523b37e3 22752+ delegated = NULL;
4a4d8108 22753+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
f2c43d5f
AM
22754+ a->dst_h_dir, &a->h_path, &delegated,
22755+ a->flags);
523b37e3
AM
22756+ if (unlikely(err == -EWOULDBLOCK)) {
22757+ pr_warn("cannot retry for NFSv4 delegation"
22758+ " for an internal rename\n");
22759+ iput(delegated);
22760+ }
c2b27bf2 22761+ } else
86dc4139 22762+ BUG();
1308ab2a 22763+
027c5e7a
AM
22764+ if (!err && a->h_dst)
22765+ /* it will be set to dinfo later */
22766+ dget(a->h_dst);
1facf9fc 22767+
dece6358
AM
22768+ return err;
22769+}
1facf9fc 22770+
4a4d8108
AM
22771+/* cf. aufs_rmdir() */
22772+static int au_ren_del_whtmp(struct au_ren_args *a)
dece6358 22773+{
4a4d8108
AM
22774+ int err;
22775+ struct inode *dir;
1facf9fc 22776+
4a4d8108
AM
22777+ dir = a->dst_dir;
22778+ SiMustAnyLock(dir->i_sb);
22779+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
22780+ au_sbi(dir->i_sb)->si_dirwh)
22781+ || au_test_fs_remote(a->h_dst->d_sb)) {
22782+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
22783+ if (unlikely(err))
523b37e3
AM
22784+ pr_warn("failed removing whtmp dir %pd (%d), "
22785+ "ignored.\n", a->h_dst, err);
4a4d8108
AM
22786+ } else {
22787+ au_nhash_wh_free(&a->thargs->whlist);
22788+ a->thargs->whlist = a->whlist;
22789+ a->whlist.nh_num = 0;
22790+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
22791+ dput(a->h_dst);
22792+ a->thargs = NULL;
22793+ }
22794+
22795+ return 0;
1308ab2a 22796+}
1facf9fc 22797+
4a4d8108 22798+/* make it 'opaque' dir. */
f2c43d5f 22799+static int au_ren_do_diropq(struct au_ren_args *a, int idx)
4a4d8108
AM
22800+{
22801+ int err;
f2c43d5f
AM
22802+ struct dentry *d, *diropq;
22803+#define src_or_dst(member) a->sd[idx].member
1facf9fc 22804+
4a4d8108 22805+ err = 0;
f2c43d5f
AM
22806+ d = src_or_dst(dentry); /* {src,dst}_dentry */
22807+ src_or_dst(bdiropq) = au_dbdiropq(d);
22808+ src_or_dst(hinode) = au_hi(src_or_dst(inode), a->btgt);
22809+ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD);
22810+ diropq = au_diropq_create(d, a->btgt);
22811+ au_hn_inode_unlock(src_or_dst(hinode));
4a4d8108
AM
22812+ if (IS_ERR(diropq))
22813+ err = PTR_ERR(diropq);
076b876e
AM
22814+ else
22815+ dput(diropq);
1facf9fc 22816+
f2c43d5f 22817+#undef src_or_dst_
4a4d8108
AM
22818+ return err;
22819+}
1facf9fc 22820+
f2c43d5f 22821+static int au_ren_diropq(struct au_ren_args *a)
4a4d8108
AM
22822+{
22823+ int err;
f2c43d5f
AM
22824+ unsigned char always;
22825+ struct dentry *d;
1facf9fc 22826+
f2c43d5f
AM
22827+ err = 0;
22828+ d = a->dst_dentry; /* already renamed on the branch */
22829+ always = !!au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ);
22830+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)
8b6a4947 22831+ && !au_ftest_ren(a->auren_flags, DIRREN)
f2c43d5f
AM
22832+ && a->btgt != au_dbdiropq(a->src_dentry)
22833+ && (a->dst_wh_dentry
22834+ || a->btgt <= au_dbdiropq(d)
22835+ /* hide the lower to keep xino */
22836+ /* the lowers may not be a dir, but we hide them anyway */
22837+ || a->btgt < au_dbbot(d)
22838+ || always)) {
22839+ AuDbg("here\n");
22840+ err = au_ren_do_diropq(a, AuSRC);
22841+ if (unlikely(err))
4a4d8108 22842+ goto out;
f2c43d5f 22843+ au_fset_ren(a->auren_flags, DIROPQ_SRC);
4a4d8108 22844+ }
f2c43d5f
AM
22845+ if (!a->exchange)
22846+ goto out; /* success */
1facf9fc 22847+
f2c43d5f
AM
22848+ d = a->src_dentry; /* already renamed on the branch */
22849+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)
22850+ && a->btgt != au_dbdiropq(a->dst_dentry)
22851+ && (a->btgt < au_dbdiropq(d)
22852+ || a->btgt < au_dbbot(d)
22853+ || always)) {
22854+ AuDbgDentry(a->src_dentry);
22855+ AuDbgDentry(a->dst_dentry);
22856+ err = au_ren_do_diropq(a, AuDST);
4a4d8108 22857+ if (unlikely(err))
f2c43d5f
AM
22858+ goto out_rev_src;
22859+ au_fset_ren(a->auren_flags, DIROPQ_DST);
22860+ }
22861+ goto out; /* success */
dece6358 22862+
f2c43d5f
AM
22863+out_rev_src:
22864+ AuDbg("err %d, reverting src\n", err);
22865+ au_ren_rev_diropq(err, a);
22866+out:
22867+ return err;
22868+}
22869+
22870+static int do_rename(struct au_ren_args *a)
22871+{
22872+ int err;
22873+ struct dentry *d, *h_d;
22874+
22875+ if (!a->exchange) {
22876+ /* prepare workqueue args for asynchronous rmdir */
22877+ h_d = a->dst_h_dentry;
22878+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)
8b6a4947 22879+ /* && !au_ftest_ren(a->auren_flags, DIRREN) */
f2c43d5f
AM
22880+ && d_is_positive(h_d)) {
22881+ err = -ENOMEM;
22882+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb,
22883+ GFP_NOFS);
22884+ if (unlikely(!a->thargs))
22885+ goto out;
22886+ a->h_dst = dget(h_d);
22887+ }
22888+
22889+ /* create whiteout for src_dentry */
22890+ if (au_ftest_ren(a->auren_flags, WHSRC)) {
22891+ a->src_bwh = au_dbwh(a->src_dentry);
22892+ AuDebugOn(a->src_bwh >= 0);
22893+ a->src_wh_dentry = au_wh_create(a->src_dentry, a->btgt,
22894+ a->src_h_parent);
22895+ err = PTR_ERR(a->src_wh_dentry);
22896+ if (IS_ERR(a->src_wh_dentry))
22897+ goto out_thargs;
22898+ }
22899+
22900+ /* lookup whiteout for dentry */
22901+ if (au_ftest_ren(a->auren_flags, WHDST)) {
22902+ h_d = au_wh_lkup(a->dst_h_parent,
22903+ &a->dst_dentry->d_name, a->br);
22904+ err = PTR_ERR(h_d);
22905+ if (IS_ERR(h_d))
22906+ goto out_whsrc;
22907+ if (d_is_negative(h_d))
22908+ dput(h_d);
22909+ else
22910+ a->dst_wh_dentry = h_d;
22911+ }
22912+
22913+ /* rename dentry to tmpwh */
22914+ if (a->thargs) {
22915+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
22916+ if (unlikely(err))
22917+ goto out_whdst;
22918+
22919+ d = a->dst_dentry;
22920+ au_set_h_dptr(d, a->btgt, NULL);
22921+ err = au_lkup_neg(d, a->btgt, /*wh*/0);
22922+ if (unlikely(err))
22923+ goto out_whtmp;
22924+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
22925+ }
4a4d8108 22926+ }
1facf9fc 22927+
5afbbe0d 22928+ BUG_ON(d_is_positive(a->dst_h_dentry) && a->src_btop != a->btgt);
43982f53 22929+#if 0 /* debugging */
8b6a4947
AM
22930+ BUG_ON(!au_ftest_ren(a->auren_flags, DIRREN)
22931+ && d_is_positive(a->dst_h_dentry)
22932+ && a->src_btop != a->btgt);
22933+#endif
1facf9fc 22934+
4a4d8108 22935+ /* rename by vfs_rename or cpup */
4a4d8108
AM
22936+ err = au_ren_or_cpup(a);
22937+ if (unlikely(err))
22938+ /* leave the copied-up one */
22939+ goto out_whtmp;
1308ab2a 22940+
4a4d8108 22941+ /* make dir opaque */
f2c43d5f
AM
22942+ err = au_ren_diropq(a);
22943+ if (unlikely(err))
22944+ goto out_rename;
1308ab2a 22945+
4a4d8108 22946+ /* update target timestamps */
f2c43d5f
AM
22947+ if (a->exchange) {
22948+ AuDebugOn(au_dbtop(a->dst_dentry) != a->btgt);
22949+ a->h_path.dentry = au_h_dptr(a->dst_dentry, a->btgt);
22950+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
22951+ a->dst_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
22952+ }
5afbbe0d 22953+ AuDebugOn(au_dbtop(a->src_dentry) != a->btgt);
4a4d8108
AM
22954+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
22955+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
5527c038 22956+ a->src_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
1facf9fc 22957+
f2c43d5f
AM
22958+ if (!a->exchange) {
22959+ /* remove whiteout for dentry */
22960+ if (a->dst_wh_dentry) {
22961+ a->h_path.dentry = a->dst_wh_dentry;
22962+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
22963+ a->dst_dentry);
22964+ if (unlikely(err))
22965+ goto out_diropq;
22966+ }
1facf9fc 22967+
f2c43d5f
AM
22968+ /* remove whtmp */
22969+ if (a->thargs)
22970+ au_ren_del_whtmp(a); /* ignore this error */
1308ab2a 22971+
f2c43d5f
AM
22972+ au_fhsm_wrote(a->src_dentry->d_sb, a->btgt, /*force*/0);
22973+ }
4a4d8108
AM
22974+ err = 0;
22975+ goto out_success;
22976+
4f0767ce 22977+out_diropq:
f2c43d5f 22978+ au_ren_rev_diropq(err, a);
4f0767ce 22979+out_rename:
7e9cd9fe 22980+ au_ren_rev_rename(err, a);
027c5e7a 22981+ dput(a->h_dst);
4f0767ce 22982+out_whtmp:
4a4d8108
AM
22983+ if (a->thargs)
22984+ au_ren_rev_whtmp(err, a);
4f0767ce 22985+out_whdst:
4a4d8108
AM
22986+ dput(a->dst_wh_dentry);
22987+ a->dst_wh_dentry = NULL;
4f0767ce 22988+out_whsrc:
4a4d8108
AM
22989+ if (a->src_wh_dentry)
22990+ au_ren_rev_whsrc(err, a);
4f0767ce 22991+out_success:
4a4d8108
AM
22992+ dput(a->src_wh_dentry);
22993+ dput(a->dst_wh_dentry);
4f0767ce 22994+out_thargs:
4a4d8108
AM
22995+ if (a->thargs) {
22996+ dput(a->h_dst);
22997+ au_whtmp_rmdir_free(a->thargs);
22998+ a->thargs = NULL;
22999+ }
4f0767ce 23000+out:
4a4d8108 23001+ return err;
dece6358 23002+}
1facf9fc 23003+
1308ab2a 23004+/* ---------------------------------------------------------------------- */
1facf9fc 23005+
4a4d8108
AM
23006+/*
23007+ * test if @dentry dir can be rename destination or not.
23008+ * success means, it is a logically empty dir.
23009+ */
23010+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
1308ab2a 23011+{
4a4d8108 23012+ return au_test_empty(dentry, whlist);
1308ab2a 23013+}
1facf9fc 23014+
4a4d8108 23015+/*
8b6a4947
AM
23016+ * test if @a->src_dentry dir can be rename source or not.
23017+ * if it can, return 0.
4a4d8108
AM
23018+ * success means,
23019+ * - it is a logically empty dir.
23020+ * - or, it exists on writable branch and has no children including whiteouts
8b6a4947 23021+ * on the lower branch unless DIRREN is on.
4a4d8108 23022+ */
8b6a4947 23023+static int may_rename_srcdir(struct au_ren_args *a)
4a4d8108
AM
23024+{
23025+ int err;
23026+ unsigned int rdhash;
8b6a4947
AM
23027+ aufs_bindex_t btop, btgt;
23028+ struct dentry *dentry;
23029+ struct super_block *sb;
23030+ struct au_sbinfo *sbinfo;
1facf9fc 23031+
8b6a4947
AM
23032+ dentry = a->src_dentry;
23033+ sb = dentry->d_sb;
23034+ sbinfo = au_sbi(sb);
23035+ if (au_opt_test(sbinfo->si_mntflags, DIRREN))
23036+ au_fset_ren(a->auren_flags, DIRREN);
23037+
23038+ btgt = a->btgt;
5afbbe0d
AM
23039+ btop = au_dbtop(dentry);
23040+ if (btop != btgt) {
4a4d8108 23041+ struct au_nhash whlist;
dece6358 23042+
8b6a4947
AM
23043+ SiMustAnyLock(sb);
23044+ rdhash = sbinfo->si_rdhash;
4a4d8108
AM
23045+ if (!rdhash)
23046+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
23047+ dentry));
23048+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
23049+ if (unlikely(err))
23050+ goto out;
23051+ err = au_test_empty(dentry, &whlist);
23052+ au_nhash_wh_free(&whlist);
23053+ goto out;
23054+ }
dece6358 23055+
5afbbe0d 23056+ if (btop == au_dbtaildir(dentry))
4a4d8108 23057+ return 0; /* success */
dece6358 23058+
4a4d8108 23059+ err = au_test_empty_lower(dentry);
1facf9fc 23060+
4f0767ce 23061+out:
4a4d8108 23062+ if (err == -ENOTEMPTY) {
8b6a4947
AM
23063+ if (au_ftest_ren(a->auren_flags, DIRREN)) {
23064+ err = 0;
23065+ } else {
23066+ AuWarn1("renaming dir who has child(ren) on multiple "
23067+ "branches, is not supported\n");
23068+ err = -EXDEV;
23069+ }
4a4d8108
AM
23070+ }
23071+ return err;
23072+}
1308ab2a 23073+
4a4d8108
AM
23074+/* side effect: sets whlist and h_dentry */
23075+static int au_ren_may_dir(struct au_ren_args *a)
1308ab2a 23076+{
4a4d8108
AM
23077+ int err;
23078+ unsigned int rdhash;
23079+ struct dentry *d;
1facf9fc 23080+
4a4d8108
AM
23081+ d = a->dst_dentry;
23082+ SiMustAnyLock(d->d_sb);
1facf9fc 23083+
4a4d8108 23084+ err = 0;
f2c43d5f 23085+ if (au_ftest_ren(a->auren_flags, ISDIR_DST) && a->dst_inode) {
4a4d8108
AM
23086+ rdhash = au_sbi(d->d_sb)->si_rdhash;
23087+ if (!rdhash)
23088+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
23089+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
23090+ if (unlikely(err))
23091+ goto out;
1308ab2a 23092+
f2c43d5f
AM
23093+ if (!a->exchange) {
23094+ au_set_dbtop(d, a->dst_btop);
23095+ err = may_rename_dstdir(d, &a->whlist);
23096+ au_set_dbtop(d, a->btgt);
23097+ } else
8b6a4947 23098+ err = may_rename_srcdir(a);
4a4d8108 23099+ }
5afbbe0d 23100+ a->dst_h_dentry = au_h_dptr(d, au_dbtop(d));
4a4d8108
AM
23101+ if (unlikely(err))
23102+ goto out;
23103+
23104+ d = a->src_dentry;
5afbbe0d 23105+ a->src_h_dentry = au_h_dptr(d, au_dbtop(d));
f2c43d5f 23106+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) {
8b6a4947 23107+ err = may_rename_srcdir(a);
4a4d8108
AM
23108+ if (unlikely(err)) {
23109+ au_nhash_wh_free(&a->whlist);
23110+ a->whlist.nh_num = 0;
23111+ }
23112+ }
4f0767ce 23113+out:
4a4d8108 23114+ return err;
1facf9fc 23115+}
23116+
4a4d8108 23117+/* ---------------------------------------------------------------------- */
1facf9fc 23118+
4a4d8108
AM
23119+/*
23120+ * simple tests for rename.
23121+ * following the checks in vfs, plus the parent-child relationship.
23122+ */
23123+static int au_may_ren(struct au_ren_args *a)
23124+{
23125+ int err, isdir;
23126+ struct inode *h_inode;
1facf9fc 23127+
5afbbe0d 23128+ if (a->src_btop == a->btgt) {
4a4d8108 23129+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
f2c43d5f 23130+ au_ftest_ren(a->auren_flags, ISDIR_SRC));
4a4d8108
AM
23131+ if (unlikely(err))
23132+ goto out;
23133+ err = -EINVAL;
23134+ if (unlikely(a->src_h_dentry == a->h_trap))
23135+ goto out;
23136+ }
1facf9fc 23137+
4a4d8108 23138+ err = 0;
5afbbe0d 23139+ if (a->dst_btop != a->btgt)
4a4d8108 23140+ goto out;
1facf9fc 23141+
027c5e7a
AM
23142+ err = -ENOTEMPTY;
23143+ if (unlikely(a->dst_h_dentry == a->h_trap))
23144+ goto out;
23145+
4a4d8108 23146+ err = -EIO;
f2c43d5f 23147+ isdir = !!au_ftest_ren(a->auren_flags, ISDIR_DST);
5527c038
JR
23148+ if (d_really_is_negative(a->dst_dentry)) {
23149+ if (d_is_negative(a->dst_h_dentry))
23150+ err = au_may_add(a->dst_dentry, a->btgt,
23151+ a->dst_h_parent, isdir);
4a4d8108 23152+ } else {
5527c038 23153+ if (unlikely(d_is_negative(a->dst_h_dentry)))
4a4d8108 23154+ goto out;
5527c038
JR
23155+ h_inode = d_inode(a->dst_h_dentry);
23156+ if (h_inode->i_nlink)
23157+ err = au_may_del(a->dst_dentry, a->btgt,
23158+ a->dst_h_parent, isdir);
4a4d8108 23159+ }
1facf9fc 23160+
4f0767ce 23161+out:
4a4d8108
AM
23162+ if (unlikely(err == -ENOENT || err == -EEXIST))
23163+ err = -EIO;
23164+ AuTraceErr(err);
23165+ return err;
23166+}
1facf9fc 23167+
1308ab2a 23168+/* ---------------------------------------------------------------------- */
1facf9fc 23169+
4a4d8108
AM
23170+/*
23171+ * locking order
23172+ * (VFS)
23173+ * - src_dir and dir by lock_rename()
acd2b654 23174+ * - inode if exists
4a4d8108
AM
23175+ * (aufs)
23176+ * - lock all
23177+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
23178+ * + si_read_lock
23179+ * + di_write_lock2_child()
23180+ * + di_write_lock_child()
23181+ * + ii_write_lock_child()
23182+ * + di_write_lock_child2()
23183+ * + ii_write_lock_child2()
23184+ * + src_parent and parent
23185+ * + di_write_lock_parent()
23186+ * + ii_write_lock_parent()
23187+ * + di_write_lock_parent2()
23188+ * + ii_write_lock_parent2()
23189+ * + lower src_dir and dir by vfsub_lock_rename()
23190+ * + verify the every relationships between child and parent. if any
23191+ * of them failed, unlock all and return -EBUSY.
23192+ */
23193+static void au_ren_unlock(struct au_ren_args *a)
1308ab2a 23194+{
4a4d8108
AM
23195+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
23196+ a->dst_h_parent, a->dst_hdir);
8b6a4947
AM
23197+ if (au_ftest_ren(a->auren_flags, DIRREN)
23198+ && a->h_root)
23199+ au_hn_inode_unlock(a->h_root);
f2c43d5f 23200+ if (au_ftest_ren(a->auren_flags, MNT_WRITE))
86dc4139 23201+ vfsub_mnt_drop_write(au_br_mnt(a->br));
1308ab2a 23202+}
23203+
4a4d8108 23204+static int au_ren_lock(struct au_ren_args *a)
1308ab2a 23205+{
4a4d8108
AM
23206+ int err;
23207+ unsigned int udba;
1308ab2a 23208+
4a4d8108
AM
23209+ err = 0;
23210+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
23211+ a->src_hdir = au_hi(a->src_dir, a->btgt);
23212+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
23213+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
86dc4139
AM
23214+
23215+ err = vfsub_mnt_want_write(au_br_mnt(a->br));
23216+ if (unlikely(err))
23217+ goto out;
f2c43d5f 23218+ au_fset_ren(a->auren_flags, MNT_WRITE);
8b6a4947
AM
23219+ if (au_ftest_ren(a->auren_flags, DIRREN)) {
23220+ struct dentry *root;
23221+ struct inode *dir;
23222+
23223+ /*
23224+ * sbinfo is already locked, so this ii_read_lock is
23225+ * unnecessary. but our debugging feature checks it.
23226+ */
23227+ root = a->src_inode->i_sb->s_root;
23228+ if (root != a->src_parent && root != a->dst_parent) {
23229+ dir = d_inode(root);
23230+ ii_read_lock_parent3(dir);
23231+ a->h_root = au_hi(dir, a->btgt);
23232+ ii_read_unlock(dir);
23233+ au_hn_inode_lock_nested(a->h_root, AuLsc_I_PARENT3);
23234+ }
23235+ }
4a4d8108
AM
23236+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
23237+ a->dst_h_parent, a->dst_hdir);
23238+ udba = au_opt_udba(a->src_dentry->d_sb);
5527c038
JR
23239+ if (unlikely(a->src_hdir->hi_inode != d_inode(a->src_h_parent)
23240+ || a->dst_hdir->hi_inode != d_inode(a->dst_h_parent)))
4a4d8108 23241+ err = au_busy_or_stale();
5afbbe0d 23242+ if (!err && au_dbtop(a->src_dentry) == a->btgt)
4a4d8108 23243+ err = au_h_verify(a->src_h_dentry, udba,
5527c038 23244+ d_inode(a->src_h_parent), a->src_h_parent,
4a4d8108 23245+ a->br);
5afbbe0d 23246+ if (!err && au_dbtop(a->dst_dentry) == a->btgt)
4a4d8108 23247+ err = au_h_verify(a->dst_h_dentry, udba,
5527c038 23248+ d_inode(a->dst_h_parent), a->dst_h_parent,
4a4d8108 23249+ a->br);
86dc4139 23250+ if (!err)
4a4d8108 23251+ goto out; /* success */
4a4d8108
AM
23252+
23253+ err = au_busy_or_stale();
4a4d8108 23254+ au_ren_unlock(a);
86dc4139 23255+
4f0767ce 23256+out:
4a4d8108 23257+ return err;
1facf9fc 23258+}
23259+
23260+/* ---------------------------------------------------------------------- */
23261+
4a4d8108 23262+static void au_ren_refresh_dir(struct au_ren_args *a)
1facf9fc 23263+{
4a4d8108 23264+ struct inode *dir;
dece6358 23265+
4a4d8108 23266+ dir = a->dst_dir;
be118d29 23267+ inode_inc_iversion(dir);
f2c43d5f 23268+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) {
4a4d8108
AM
23269+ /* is this updating defined in POSIX? */
23270+ au_cpup_attr_timesizes(a->src_inode);
23271+ au_cpup_attr_nlink(dir, /*force*/1);
4a4d8108 23272+ }
b912730e 23273+ au_dir_ts(dir, a->btgt);
dece6358 23274+
f2c43d5f
AM
23275+ if (a->exchange) {
23276+ dir = a->src_dir;
be118d29 23277+ inode_inc_iversion(dir);
f2c43d5f
AM
23278+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)) {
23279+ /* is this updating defined in POSIX? */
23280+ au_cpup_attr_timesizes(a->dst_inode);
23281+ au_cpup_attr_nlink(dir, /*force*/1);
23282+ }
23283+ au_dir_ts(dir, a->btgt);
23284+ }
23285+
23286+ if (au_ftest_ren(a->auren_flags, ISSAMEDIR))
4a4d8108 23287+ return;
dece6358 23288+
4a4d8108 23289+ dir = a->src_dir;
be118d29 23290+ inode_inc_iversion(dir);
f2c43d5f 23291+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC))
4a4d8108 23292+ au_cpup_attr_nlink(dir, /*force*/1);
b912730e 23293+ au_dir_ts(dir, a->btgt);
1facf9fc 23294+}
23295+
4a4d8108 23296+static void au_ren_refresh(struct au_ren_args *a)
1facf9fc 23297+{
5afbbe0d 23298+ aufs_bindex_t bbot, bindex;
4a4d8108
AM
23299+ struct dentry *d, *h_d;
23300+ struct inode *i, *h_i;
23301+ struct super_block *sb;
dece6358 23302+
027c5e7a
AM
23303+ d = a->dst_dentry;
23304+ d_drop(d);
23305+ if (a->h_dst)
23306+ /* already dget-ed by au_ren_or_cpup() */
23307+ au_set_h_dptr(d, a->btgt, a->h_dst);
23308+
23309+ i = a->dst_inode;
23310+ if (i) {
f2c43d5f
AM
23311+ if (!a->exchange) {
23312+ if (!au_ftest_ren(a->auren_flags, ISDIR_DST))
23313+ vfsub_drop_nlink(i);
23314+ else {
23315+ vfsub_dead_dir(i);
23316+ au_cpup_attr_timesizes(i);
23317+ }
23318+ au_update_dbrange(d, /*do_put_zero*/1);
23319+ } else
23320+ au_cpup_attr_nlink(i, /*force*/1);
027c5e7a 23321+ } else {
5afbbe0d
AM
23322+ bbot = a->btgt;
23323+ for (bindex = au_dbtop(d); bindex < bbot; bindex++)
027c5e7a 23324+ au_set_h_dptr(d, bindex, NULL);
5afbbe0d
AM
23325+ bbot = au_dbbot(d);
23326+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++)
027c5e7a
AM
23327+ au_set_h_dptr(d, bindex, NULL);
23328+ au_update_dbrange(d, /*do_put_zero*/0);
23329+ }
23330+
8b6a4947
AM
23331+ if (a->exchange
23332+ || au_ftest_ren(a->auren_flags, DIRREN)) {
23333+ d_drop(a->src_dentry);
23334+ if (au_ftest_ren(a->auren_flags, DIRREN))
23335+ au_set_dbwh(a->src_dentry, -1);
23336+ return;
23337+ }
23338+
4a4d8108 23339+ d = a->src_dentry;
8b6a4947
AM
23340+ au_set_dbwh(d, -1);
23341+ bbot = au_dbbot(d);
23342+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) {
23343+ h_d = au_h_dptr(d, bindex);
23344+ if (h_d)
23345+ au_set_h_dptr(d, bindex, NULL);
23346+ }
23347+ au_set_dbbot(d, a->btgt);
4a4d8108 23348+
8b6a4947
AM
23349+ sb = d->d_sb;
23350+ i = a->src_inode;
23351+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
23352+ return; /* success */
4a4d8108 23353+
8b6a4947
AM
23354+ bbot = au_ibbot(i);
23355+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) {
23356+ h_i = au_h_iptr(i, bindex);
23357+ if (h_i) {
23358+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
23359+ /* ignore this error */
23360+ au_set_h_iptr(i, bindex, NULL, 0);
4a4d8108
AM
23361+ }
23362+ }
8b6a4947 23363+ au_set_ibbot(i, a->btgt);
1308ab2a 23364+}
dece6358 23365+
4a4d8108
AM
23366+/* ---------------------------------------------------------------------- */
23367+
23368+/* mainly for link(2) and rename(2) */
23369+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
1308ab2a 23370+{
4a4d8108
AM
23371+ aufs_bindex_t bdiropq, bwh;
23372+ struct dentry *parent;
23373+ struct au_branch *br;
23374+
23375+ parent = dentry->d_parent;
5527c038 23376+ IMustLock(d_inode(parent)); /* dir is locked */
4a4d8108
AM
23377+
23378+ bdiropq = au_dbdiropq(parent);
23379+ bwh = au_dbwh(dentry);
23380+ br = au_sbr(dentry->d_sb, btgt);
23381+ if (au_br_rdonly(br)
23382+ || (0 <= bdiropq && bdiropq < btgt)
23383+ || (0 <= bwh && bwh < btgt))
23384+ btgt = -1;
23385+
23386+ AuDbg("btgt %d\n", btgt);
23387+ return btgt;
1facf9fc 23388+}
23389+
5afbbe0d 23390+/* sets src_btop, dst_btop and btgt */
4a4d8108 23391+static int au_ren_wbr(struct au_ren_args *a)
1facf9fc 23392+{
4a4d8108
AM
23393+ int err;
23394+ struct au_wr_dir_args wr_dir_args = {
23395+ /* .force_btgt = -1, */
23396+ .flags = AuWrDir_ADD_ENTRY
23397+ };
dece6358 23398+
5afbbe0d
AM
23399+ a->src_btop = au_dbtop(a->src_dentry);
23400+ a->dst_btop = au_dbtop(a->dst_dentry);
f2c43d5f
AM
23401+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)
23402+ || au_ftest_ren(a->auren_flags, ISDIR_DST))
4a4d8108 23403+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
5afbbe0d
AM
23404+ wr_dir_args.force_btgt = a->src_btop;
23405+ if (a->dst_inode && a->dst_btop < a->src_btop)
23406+ wr_dir_args.force_btgt = a->dst_btop;
4a4d8108
AM
23407+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
23408+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
23409+ a->btgt = err;
f2c43d5f
AM
23410+ if (a->exchange)
23411+ au_update_dbtop(a->dst_dentry);
dece6358 23412+
4a4d8108 23413+ return err;
1facf9fc 23414+}
23415+
4a4d8108 23416+static void au_ren_dt(struct au_ren_args *a)
1facf9fc 23417+{
4a4d8108
AM
23418+ a->h_path.dentry = a->src_h_parent;
23419+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
f2c43d5f 23420+ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR)) {
4a4d8108
AM
23421+ a->h_path.dentry = a->dst_h_parent;
23422+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
23423+ }
1facf9fc 23424+
f2c43d5f
AM
23425+ au_fclr_ren(a->auren_flags, DT_DSTDIR);
23426+ if (!au_ftest_ren(a->auren_flags, ISDIR_SRC)
23427+ && !a->exchange)
4a4d8108 23428+ return;
dece6358 23429+
4a4d8108
AM
23430+ a->h_path.dentry = a->src_h_dentry;
23431+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
5527c038 23432+ if (d_is_positive(a->dst_h_dentry)) {
f2c43d5f 23433+ au_fset_ren(a->auren_flags, DT_DSTDIR);
4a4d8108
AM
23434+ a->h_path.dentry = a->dst_h_dentry;
23435+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
23436+ }
1308ab2a 23437+}
dece6358 23438+
4a4d8108 23439+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1308ab2a 23440+{
4a4d8108 23441+ struct dentry *h_d;
febd17d6 23442+ struct inode *h_inode;
4a4d8108
AM
23443+
23444+ au_dtime_revert(a->src_dt + AuPARENT);
f2c43d5f 23445+ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR))
4a4d8108
AM
23446+ au_dtime_revert(a->dst_dt + AuPARENT);
23447+
f2c43d5f 23448+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) && err != -EIO) {
4a4d8108 23449+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
febd17d6
JR
23450+ h_inode = d_inode(h_d);
23451+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 23452+ au_dtime_revert(a->src_dt + AuCHILD);
febd17d6 23453+ inode_unlock(h_inode);
4a4d8108 23454+
f2c43d5f 23455+ if (au_ftest_ren(a->auren_flags, DT_DSTDIR)) {
4a4d8108 23456+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
febd17d6
JR
23457+ h_inode = d_inode(h_d);
23458+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 23459+ au_dtime_revert(a->dst_dt + AuCHILD);
febd17d6 23460+ inode_unlock(h_inode);
1facf9fc 23461+ }
23462+ }
23463+}
23464+
4a4d8108
AM
23465+/* ---------------------------------------------------------------------- */
23466+
0b2a12c6
JR
23467+int aufs_rename(struct user_namespace *userns,
23468+ struct inode *_src_dir, struct dentry *_src_dentry,
f2c43d5f
AM
23469+ struct inode *_dst_dir, struct dentry *_dst_dentry,
23470+ unsigned int _flags)
1facf9fc 23471+{
f2c43d5f 23472+ int err, lock_flags;
8b6a4947 23473+ void *rev;
4a4d8108
AM
23474+ /* reduce stack space */
23475+ struct au_ren_args *a;
f2c43d5f 23476+ struct au_pin pin;
4a4d8108 23477+
f2c43d5f 23478+ AuDbg("%pd, %pd, 0x%x\n", _src_dentry, _dst_dentry, _flags);
4a4d8108
AM
23479+ IMustLock(_src_dir);
23480+ IMustLock(_dst_dir);
23481+
f2c43d5f
AM
23482+ err = -EINVAL;
23483+ if (unlikely(_flags & RENAME_WHITEOUT))
23484+ goto out;
23485+
4a4d8108
AM
23486+ err = -ENOMEM;
23487+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
23488+ a = kzalloc(sizeof(*a), GFP_NOFS);
23489+ if (unlikely(!a))
23490+ goto out;
23491+
f2c43d5f 23492+ a->flags = _flags;
acd2b654
AM
23493+ BUILD_BUG_ON(sizeof(a->exchange) == sizeof(u8)
23494+ && RENAME_EXCHANGE > U8_MAX);
f2c43d5f 23495+ a->exchange = _flags & RENAME_EXCHANGE;
4a4d8108
AM
23496+ a->src_dir = _src_dir;
23497+ a->src_dentry = _src_dentry;
5527c038
JR
23498+ a->src_inode = NULL;
23499+ if (d_really_is_positive(a->src_dentry))
23500+ a->src_inode = d_inode(a->src_dentry);
4a4d8108
AM
23501+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
23502+ a->dst_dir = _dst_dir;
23503+ a->dst_dentry = _dst_dentry;
5527c038
JR
23504+ a->dst_inode = NULL;
23505+ if (d_really_is_positive(a->dst_dentry))
23506+ a->dst_inode = d_inode(a->dst_dentry);
4a4d8108
AM
23507+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
23508+ if (a->dst_inode) {
f2c43d5f
AM
23509+ /*
23510+ * if EXCHANGE && src is non-dir && dst is dir,
23511+ * dst is not locked.
23512+ */
23513+ /* IMustLock(a->dst_inode); */
4a4d8108 23514+ au_igrab(a->dst_inode);
1facf9fc 23515+ }
1facf9fc 23516+
4a4d8108 23517+ err = -ENOTDIR;
f2c43d5f 23518+ lock_flags = AuLock_FLUSH | AuLock_NOPLM | AuLock_GEN;
2000de60 23519+ if (d_is_dir(a->src_dentry)) {
f2c43d5f
AM
23520+ au_fset_ren(a->auren_flags, ISDIR_SRC);
23521+ if (unlikely(!a->exchange
23522+ && d_really_is_positive(a->dst_dentry)
2000de60 23523+ && !d_is_dir(a->dst_dentry)))
4a4d8108 23524+ goto out_free;
f2c43d5f
AM
23525+ lock_flags |= AuLock_DIRS;
23526+ }
23527+ if (a->dst_inode && d_is_dir(a->dst_dentry)) {
23528+ au_fset_ren(a->auren_flags, ISDIR_DST);
23529+ if (unlikely(!a->exchange
23530+ && d_really_is_positive(a->src_dentry)
23531+ && !d_is_dir(a->src_dentry)))
23532+ goto out_free;
23533+ lock_flags |= AuLock_DIRS;
b95c5147 23534+ }
8b6a4947
AM
23535+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
23536+ lock_flags);
e49829fe
JR
23537+ if (unlikely(err))
23538+ goto out_free;
1facf9fc 23539+
027c5e7a
AM
23540+ err = au_d_hashed_positive(a->src_dentry);
23541+ if (unlikely(err))
23542+ goto out_unlock;
23543+ err = -ENOENT;
23544+ if (a->dst_inode) {
23545+ /*
f2c43d5f 23546+ * If it is a dir, VFS unhash it before this
027c5e7a
AM
23547+ * function. It means we cannot rely upon d_unhashed().
23548+ */
23549+ if (unlikely(!a->dst_inode->i_nlink))
23550+ goto out_unlock;
f2c43d5f 23551+ if (!au_ftest_ren(a->auren_flags, ISDIR_DST)) {
027c5e7a 23552+ err = au_d_hashed_positive(a->dst_dentry);
f2c43d5f 23553+ if (unlikely(err && !a->exchange))
027c5e7a
AM
23554+ goto out_unlock;
23555+ } else if (unlikely(IS_DEADDIR(a->dst_inode)))
23556+ goto out_unlock;
23557+ } else if (unlikely(d_unhashed(a->dst_dentry)))
23558+ goto out_unlock;
23559+
7eafdf33
AM
23560+ /*
23561+ * is it possible?
79b8bda9 23562+ * yes, it happened (in linux-3.3-rcN) but I don't know why.
7eafdf33
AM
23563+ * there may exist a problem somewhere else.
23564+ */
23565+ err = -EINVAL;
5527c038 23566+ if (unlikely(d_inode(a->dst_parent) == d_inode(a->src_dentry)))
7eafdf33
AM
23567+ goto out_unlock;
23568+
f2c43d5f 23569+ au_fset_ren(a->auren_flags, ISSAMEDIR); /* temporary */
4a4d8108 23570+ di_write_lock_parent(a->dst_parent);
1facf9fc 23571+
4a4d8108
AM
23572+ /* which branch we process */
23573+ err = au_ren_wbr(a);
23574+ if (unlikely(err < 0))
027c5e7a 23575+ goto out_parent;
4a4d8108 23576+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
86dc4139 23577+ a->h_path.mnt = au_br_mnt(a->br);
1facf9fc 23578+
4a4d8108
AM
23579+ /* are they available to be renamed */
23580+ err = au_ren_may_dir(a);
23581+ if (unlikely(err))
23582+ goto out_children;
1facf9fc 23583+
4a4d8108 23584+ /* prepare the writable parent dir on the same branch */
5afbbe0d 23585+ if (a->dst_btop == a->btgt) {
f2c43d5f 23586+ au_fset_ren(a->auren_flags, WHDST);
4a4d8108
AM
23587+ } else {
23588+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
23589+ if (unlikely(err))
23590+ goto out_children;
23591+ }
1facf9fc 23592+
f2c43d5f
AM
23593+ err = 0;
23594+ if (!a->exchange) {
23595+ if (a->src_dir != a->dst_dir) {
23596+ /*
23597+ * this temporary unlock is safe,
23598+ * because both dir->i_mutex are locked.
23599+ */
23600+ di_write_unlock(a->dst_parent);
23601+ di_write_lock_parent(a->src_parent);
23602+ err = au_wr_dir_need_wh(a->src_dentry,
23603+ au_ftest_ren(a->auren_flags,
23604+ ISDIR_SRC),
23605+ &a->btgt);
23606+ di_write_unlock(a->src_parent);
23607+ di_write_lock2_parent(a->src_parent, a->dst_parent,
23608+ /*isdir*/1);
23609+ au_fclr_ren(a->auren_flags, ISSAMEDIR);
23610+ } else
23611+ err = au_wr_dir_need_wh(a->src_dentry,
23612+ au_ftest_ren(a->auren_flags,
23613+ ISDIR_SRC),
23614+ &a->btgt);
23615+ }
4a4d8108
AM
23616+ if (unlikely(err < 0))
23617+ goto out_children;
23618+ if (err)
f2c43d5f 23619+ au_fset_ren(a->auren_flags, WHSRC);
1facf9fc 23620+
86dc4139 23621+ /* cpup src */
5afbbe0d 23622+ if (a->src_btop != a->btgt) {
86dc4139
AM
23623+ err = au_pin(&pin, a->src_dentry, a->btgt,
23624+ au_opt_udba(a->src_dentry->d_sb),
23625+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
367653fa 23626+ if (!err) {
c2b27bf2
AM
23627+ struct au_cp_generic cpg = {
23628+ .dentry = a->src_dentry,
23629+ .bdst = a->btgt,
5afbbe0d 23630+ .bsrc = a->src_btop,
c2b27bf2
AM
23631+ .len = -1,
23632+ .pin = &pin,
23633+ .flags = AuCpup_DTIME | AuCpup_HOPEN
23634+ };
5afbbe0d 23635+ AuDebugOn(au_dbtop(a->src_dentry) != a->src_btop);
c2b27bf2 23636+ err = au_sio_cpup_simple(&cpg);
367653fa 23637+ au_unpin(&pin);
86dc4139 23638+ }
86dc4139
AM
23639+ if (unlikely(err))
23640+ goto out_children;
5afbbe0d 23641+ a->src_btop = a->btgt;
86dc4139 23642+ a->src_h_dentry = au_h_dptr(a->src_dentry, a->btgt);
f2c43d5f
AM
23643+ if (!a->exchange)
23644+ au_fset_ren(a->auren_flags, WHSRC);
23645+ }
23646+
23647+ /* cpup dst */
23648+ if (a->exchange && a->dst_inode
23649+ && a->dst_btop != a->btgt) {
23650+ err = au_pin(&pin, a->dst_dentry, a->btgt,
23651+ au_opt_udba(a->dst_dentry->d_sb),
23652+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
23653+ if (!err) {
23654+ struct au_cp_generic cpg = {
23655+ .dentry = a->dst_dentry,
23656+ .bdst = a->btgt,
23657+ .bsrc = a->dst_btop,
23658+ .len = -1,
23659+ .pin = &pin,
23660+ .flags = AuCpup_DTIME | AuCpup_HOPEN
23661+ };
23662+ err = au_sio_cpup_simple(&cpg);
23663+ au_unpin(&pin);
23664+ }
23665+ if (unlikely(err))
23666+ goto out_children;
23667+ a->dst_btop = a->btgt;
23668+ a->dst_h_dentry = au_h_dptr(a->dst_dentry, a->btgt);
86dc4139
AM
23669+ }
23670+
4a4d8108
AM
23671+ /* lock them all */
23672+ err = au_ren_lock(a);
23673+ if (unlikely(err))
86dc4139 23674+ /* leave the copied-up one */
4a4d8108 23675+ goto out_children;
1facf9fc 23676+
f2c43d5f
AM
23677+ if (!a->exchange) {
23678+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
23679+ err = au_may_ren(a);
23680+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
23681+ err = -ENAMETOOLONG;
23682+ if (unlikely(err))
23683+ goto out_hdir;
23684+ }
1facf9fc 23685+
4a4d8108
AM
23686+ /* store timestamps to be revertible */
23687+ au_ren_dt(a);
1facf9fc 23688+
8b6a4947
AM
23689+ /* store dirren info */
23690+ if (au_ftest_ren(a->auren_flags, DIRREN)) {
23691+ err = au_dr_rename(a->src_dentry, a->btgt,
23692+ &a->dst_dentry->d_name, &rev);
23693+ AuTraceErr(err);
23694+ if (unlikely(err))
23695+ goto out_dt;
23696+ }
23697+
4a4d8108
AM
23698+ /* here we go */
23699+ err = do_rename(a);
23700+ if (unlikely(err))
8b6a4947
AM
23701+ goto out_dirren;
23702+
23703+ if (au_ftest_ren(a->auren_flags, DIRREN))
23704+ au_dr_rename_fin(a->src_dentry, a->btgt, rev);
4a4d8108
AM
23705+
23706+ /* update dir attributes */
23707+ au_ren_refresh_dir(a);
23708+
23709+ /* dput/iput all lower dentries */
23710+ au_ren_refresh(a);
23711+
23712+ goto out_hdir; /* success */
23713+
8b6a4947
AM
23714+out_dirren:
23715+ if (au_ftest_ren(a->auren_flags, DIRREN))
23716+ au_dr_rename_rev(a->src_dentry, a->btgt, rev);
4f0767ce 23717+out_dt:
4a4d8108 23718+ au_ren_rev_dt(err, a);
4f0767ce 23719+out_hdir:
4a4d8108 23720+ au_ren_unlock(a);
4f0767ce 23721+out_children:
4a4d8108 23722+ au_nhash_wh_free(&a->whlist);
5afbbe0d
AM
23723+ if (err && a->dst_inode && a->dst_btop != a->btgt) {
23724+ AuDbg("btop %d, btgt %d\n", a->dst_btop, a->btgt);
027c5e7a 23725+ au_set_h_dptr(a->dst_dentry, a->btgt, NULL);
5afbbe0d 23726+ au_set_dbtop(a->dst_dentry, a->dst_btop);
4a4d8108 23727+ }
027c5e7a 23728+out_parent:
f2c43d5f 23729+ if (!err) {
8b6a4947
AM
23730+ if (d_unhashed(a->src_dentry))
23731+ au_fset_ren(a->auren_flags, DROPPED_SRC);
23732+ if (d_unhashed(a->dst_dentry))
23733+ au_fset_ren(a->auren_flags, DROPPED_DST);
f2c43d5f
AM
23734+ if (!a->exchange)
23735+ d_move(a->src_dentry, a->dst_dentry);
8b6a4947 23736+ else {
f2c43d5f 23737+ d_exchange(a->src_dentry, a->dst_dentry);
8b6a4947
AM
23738+ if (au_ftest_ren(a->auren_flags, DROPPED_DST))
23739+ d_drop(a->dst_dentry);
23740+ }
23741+ if (au_ftest_ren(a->auren_flags, DROPPED_SRC))
23742+ d_drop(a->src_dentry);
f2c43d5f 23743+ } else {
5afbbe0d 23744+ au_update_dbtop(a->dst_dentry);
027c5e7a
AM
23745+ if (!a->dst_inode)
23746+ d_drop(a->dst_dentry);
23747+ }
f2c43d5f 23748+ if (au_ftest_ren(a->auren_flags, ISSAMEDIR))
4a4d8108
AM
23749+ di_write_unlock(a->dst_parent);
23750+ else
23751+ di_write_unlock2(a->src_parent, a->dst_parent);
027c5e7a 23752+out_unlock:
4a4d8108 23753+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
4f0767ce 23754+out_free:
4a4d8108
AM
23755+ iput(a->dst_inode);
23756+ if (a->thargs)
23757+ au_whtmp_rmdir_free(a->thargs);
9f237c51 23758+ au_kfree_rcu(a);
4f0767ce 23759+out:
4a4d8108
AM
23760+ AuTraceErr(err);
23761+ return err;
1308ab2a 23762+}
7f207e10 23763diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
eca34b5c 23764--- /usr/share/empty/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 23765+++ linux/fs/aufs/Kconfig 2021-05-02 20:15:14.670004120 +0200
2121bcd9
AM
23766@@ -0,0 +1,199 @@
23767+# SPDX-License-Identifier: GPL-2.0
4a4d8108
AM
23768+config AUFS_FS
23769+ tristate "Aufs (Advanced multi layered unification filesystem) support"
4a4d8108
AM
23770+ help
23771+ Aufs is a stackable unification filesystem such as Unionfs,
23772+ which unifies several directories and provides a merged single
23773+ directory.
23774+ In the early days, aufs was entirely re-designed and
23775+ re-implemented Unionfs Version 1.x series. Introducing many
23776+ original ideas, approaches and improvements, it becomes totally
23777+ different from Unionfs while keeping the basic features.
1facf9fc 23778+
4a4d8108
AM
23779+if AUFS_FS
23780+choice
23781+ prompt "Maximum number of branches"
23782+ default AUFS_BRANCH_MAX_127
23783+ help
23784+ Specifies the maximum number of branches (or member directories)
23785+ in a single aufs. The larger value consumes more system
23786+ resources and has a minor impact to performance.
23787+config AUFS_BRANCH_MAX_127
23788+ bool "127"
23789+ help
23790+ Specifies the maximum number of branches (or member directories)
23791+ in a single aufs. The larger value consumes more system
23792+ resources and has a minor impact to performance.
23793+config AUFS_BRANCH_MAX_511
23794+ bool "511"
23795+ help
23796+ Specifies the maximum number of branches (or member directories)
23797+ in a single aufs. The larger value consumes more system
23798+ resources and has a minor impact to performance.
23799+config AUFS_BRANCH_MAX_1023
23800+ bool "1023"
23801+ help
23802+ Specifies the maximum number of branches (or member directories)
23803+ in a single aufs. The larger value consumes more system
23804+ resources and has a minor impact to performance.
23805+config AUFS_BRANCH_MAX_32767
23806+ bool "32767"
23807+ help
23808+ Specifies the maximum number of branches (or member directories)
23809+ in a single aufs. The larger value consumes more system
23810+ resources and has a minor impact to performance.
23811+endchoice
1facf9fc 23812+
e49829fe
JR
23813+config AUFS_SBILIST
23814+ bool
23815+ depends on AUFS_MAGIC_SYSRQ || PROC_FS
23816+ default y
23817+ help
23818+ Automatic configuration for internal use.
23819+ When aufs supports Magic SysRq or /proc, enabled automatically.
23820+
4a4d8108
AM
23821+config AUFS_HNOTIFY
23822+ bool "Detect direct branch access (bypassing aufs)"
23823+ help
23824+ If you want to modify files on branches directly, eg. bypassing aufs,
23825+ and want aufs to detect the changes of them fully, then enable this
23826+ option and use 'udba=notify' mount option.
7f207e10 23827+ Currently there is only one available configuration, "fsnotify".
4a4d8108
AM
23828+ It will have a negative impact to the performance.
23829+ See detail in aufs.5.
dece6358 23830+
4a4d8108
AM
23831+choice
23832+ prompt "method" if AUFS_HNOTIFY
23833+ default AUFS_HFSNOTIFY
23834+config AUFS_HFSNOTIFY
23835+ bool "fsnotify"
23836+ select FSNOTIFY
4a4d8108 23837+endchoice
1facf9fc 23838+
4a4d8108
AM
23839+config AUFS_EXPORT
23840+ bool "NFS-exportable aufs"
2cbb1c4b 23841+ depends on EXPORTFS
4a4d8108
AM
23842+ help
23843+ If you want to export your mounted aufs via NFS, then enable this
23844+ option. There are several requirements for this configuration.
23845+ See detail in aufs.5.
1facf9fc 23846+
4a4d8108
AM
23847+config AUFS_INO_T_64
23848+ bool
23849+ depends on AUFS_EXPORT
23850+ depends on 64BIT && !(ALPHA || S390)
23851+ default y
23852+ help
23853+ Automatic configuration for internal use.
23854+ /* typedef unsigned long/int __kernel_ino_t */
23855+ /* alpha and s390x are int */
1facf9fc 23856+
c1595e42
JR
23857+config AUFS_XATTR
23858+ bool "support for XATTR/EA (including Security Labels)"
23859+ help
23860+ If your branch fs supports XATTR/EA and you want to make them
23861+ available in aufs too, then enable this opsion and specify the
23862+ branch attributes for EA.
23863+ See detail in aufs.5.
23864+
076b876e
AM
23865+config AUFS_FHSM
23866+ bool "File-based Hierarchical Storage Management"
23867+ help
23868+ Hierarchical Storage Management (or HSM) is a well-known feature
23869+ in the storage world. Aufs provides this feature as file-based.
23870+ with multiple branches.
23871+ These multiple branches are prioritized, ie. the topmost one
23872+ should be the fastest drive and be used heavily.
23873+
4a4d8108
AM
23874+config AUFS_RDU
23875+ bool "Readdir in userspace"
23876+ help
23877+ Aufs has two methods to provide a merged view for a directory,
23878+ by a user-space library and by kernel-space natively. The latter
23879+ is always enabled but sometimes large and slow.
23880+ If you enable this option, install the library in aufs2-util
23881+ package, and set some environment variables for your readdir(3),
23882+ then the work will be handled in user-space which generally
23883+ shows better performance in most cases.
23884+ See detail in aufs.5.
1facf9fc 23885+
8b6a4947
AM
23886+config AUFS_DIRREN
23887+ bool "Workaround for rename(2)-ing a directory"
23888+ help
23889+ By default, aufs returns EXDEV error in renameing a dir who has
23890+ his child on the lower branch, since it is a bad idea to issue
23891+ rename(2) internally for every lower branch. But user may not
23892+ accept this behaviour. So here is a workaround to allow such
23893+ rename(2) and store some extra infromation on the writable
23894+ branch. Obviously this costs high (and I don't like it).
23895+ To use this feature, you need to enable this configuration AND
23896+ to specify the mount option `dirren.'
23897+ See details in aufs.5 and the design documents.
23898+
4a4d8108
AM
23899+config AUFS_SHWH
23900+ bool "Show whiteouts"
23901+ help
23902+ If you want to make the whiteouts in aufs visible, then enable
23903+ this option and specify 'shwh' mount option. Although it may
23904+ sounds like philosophy or something, but in technically it
23905+ simply shows the name of whiteout with keeping its behaviour.
1facf9fc 23906+
4a4d8108
AM
23907+config AUFS_BR_RAMFS
23908+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
23909+ help
23910+ If you want to use ramfs as an aufs branch fs, then enable this
23911+ option. Generally tmpfs is recommended.
23912+ Aufs prohibited them to be a branch fs by default, because
23913+ initramfs becomes unusable after switch_root or something
23914+ generally. If you sets initramfs as an aufs branch and boot your
23915+ system by switch_root, you will meet a problem easily since the
23916+ files in initramfs may be inaccessible.
23917+ Unless you are going to use ramfs as an aufs branch fs without
23918+ switch_root or something, leave it N.
1facf9fc 23919+
4a4d8108
AM
23920+config AUFS_BR_FUSE
23921+ bool "Fuse fs as an aufs branch"
23922+ depends on FUSE_FS
23923+ select AUFS_POLL
23924+ help
23925+ If you want to use fuse-based userspace filesystem as an aufs
23926+ branch fs, then enable this option.
23927+ It implements the internal poll(2) operation which is
23928+ implemented by fuse only (curretnly).
1facf9fc 23929+
4a4d8108
AM
23930+config AUFS_POLL
23931+ bool
23932+ help
23933+ Automatic configuration for internal use.
1facf9fc 23934+
4a4d8108
AM
23935+config AUFS_BR_HFSPLUS
23936+ bool "Hfsplus as an aufs branch"
23937+ depends on HFSPLUS_FS
23938+ default y
23939+ help
23940+ If you want to use hfsplus fs as an aufs branch fs, then enable
23941+ this option. This option introduces a small overhead at
23942+ copying-up a file on hfsplus.
1facf9fc 23943+
4a4d8108
AM
23944+config AUFS_BDEV_LOOP
23945+ bool
23946+ depends on BLK_DEV_LOOP
23947+ default y
23948+ help
23949+ Automatic configuration for internal use.
23950+ Convert =[ym] into =y.
1308ab2a 23951+
4a4d8108
AM
23952+config AUFS_DEBUG
23953+ bool "Debug aufs"
23954+ help
23955+ Enable this to compile aufs internal debug code.
23956+ It will have a negative impact to the performance.
23957+
23958+config AUFS_MAGIC_SYSRQ
23959+ bool
23960+ depends on AUFS_DEBUG && MAGIC_SYSRQ
23961+ default y
23962+ help
23963+ Automatic configuration for internal use.
23964+ When aufs supports Magic SysRq, enabled automatically.
23965+endif
acd2b654 23966diff -urN /usr/share/empty/fs/aufs/lcnt.h linux/fs/aufs/lcnt.h
eca34b5c 23967--- /usr/share/empty/fs/aufs/lcnt.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 23968+++ linux/fs/aufs/lcnt.h 2021-05-02 20:15:14.673337458 +0200
acd2b654
AM
23969@@ -0,0 +1,186 @@
23970+/* SPDX-License-Identifier: GPL-2.0 */
23971+/*
d58c55f2 23972+ * Copyright (C) 2018-2020 Junjiro R. Okajima
acd2b654
AM
23973+ *
23974+ * This program, aufs is free software; you can redistribute it and/or modify
23975+ * it under the terms of the GNU General Public License as published by
23976+ * the Free Software Foundation; either version 2 of the License, or
23977+ * (at your option) any later version.
23978+ *
23979+ * This program is distributed in the hope that it will be useful,
23980+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23981+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23982+ * GNU General Public License for more details.
23983+ *
23984+ * You should have received a copy of the GNU General Public License
23985+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
23986+ */
23987+
23988+/*
23989+ * simple long counter wrapper
23990+ */
23991+
23992+#ifndef __AUFS_LCNT_H__
23993+#define __AUFS_LCNT_H__
23994+
23995+#ifdef __KERNEL__
23996+
23997+#include "debug.h"
23998+
23999+#define AuLCntATOMIC 1
24000+#define AuLCntPCPUCNT 2
24001+/*
24002+ * why does percpu_refcount require extra synchronize_rcu()s in
24003+ * au_br_do_free()
24004+ */
24005+#define AuLCntPCPUREF 3
24006+
24007+/* #define AuLCntChosen AuLCntATOMIC */
24008+#define AuLCntChosen AuLCntPCPUCNT
24009+/* #define AuLCntChosen AuLCntPCPUREF */
24010+
24011+#if AuLCntChosen == AuLCntATOMIC
24012+#include <linux/atomic.h>
24013+
24014+typedef atomic_long_t au_lcnt_t;
24015+
24016+static inline int au_lcnt_init(au_lcnt_t *cnt, void *release __maybe_unused)
24017+{
24018+ atomic_long_set(cnt, 0);
24019+ return 0;
24020+}
24021+
24022+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused)
24023+{
24024+ /* empty */
24025+}
24026+
24027+static inline void au_lcnt_fin(au_lcnt_t *cnt __maybe_unused,
24028+ int do_sync __maybe_unused)
24029+{
24030+ /* empty */
24031+}
24032+
24033+static inline void au_lcnt_inc(au_lcnt_t *cnt)
24034+{
24035+ atomic_long_inc(cnt);
24036+}
24037+
24038+static inline void au_lcnt_dec(au_lcnt_t *cnt)
24039+{
24040+ atomic_long_dec(cnt);
24041+}
24042+
24043+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev __maybe_unused)
24044+{
24045+ return atomic_long_read(cnt);
24046+}
24047+#endif
24048+
24049+#if AuLCntChosen == AuLCntPCPUCNT
24050+#include <linux/percpu_counter.h>
24051+
24052+typedef struct percpu_counter au_lcnt_t;
24053+
24054+static inline int au_lcnt_init(au_lcnt_t *cnt, void *release __maybe_unused)
24055+{
24056+ return percpu_counter_init(cnt, 0, GFP_NOFS);
24057+}
24058+
24059+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused)
24060+{
24061+ /* empty */
24062+}
24063+
24064+static inline void au_lcnt_fin(au_lcnt_t *cnt, int do_sync __maybe_unused)
24065+{
24066+ percpu_counter_destroy(cnt);
24067+}
24068+
24069+static inline void au_lcnt_inc(au_lcnt_t *cnt)
24070+{
24071+ percpu_counter_inc(cnt);
24072+}
24073+
24074+static inline void au_lcnt_dec(au_lcnt_t *cnt)
24075+{
24076+ percpu_counter_dec(cnt);
24077+}
24078+
24079+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev __maybe_unused)
24080+{
24081+ s64 n;
24082+
24083+ n = percpu_counter_sum(cnt);
24084+ BUG_ON(n < 0);
24085+ if (LONG_MAX != LLONG_MAX
24086+ && n > LONG_MAX)
24087+ AuWarn1("%s\n", "wrap-around");
24088+
24089+ return n;
24090+}
24091+#endif
24092+
24093+#if AuLCntChosen == AuLCntPCPUREF
24094+#include <linux/percpu-refcount.h>
24095+
24096+typedef struct percpu_ref au_lcnt_t;
24097+
24098+static inline int au_lcnt_init(au_lcnt_t *cnt, percpu_ref_func_t *release)
24099+{
24100+ if (!release)
24101+ release = percpu_ref_exit;
24102+ return percpu_ref_init(cnt, release, /*percpu mode*/0, GFP_NOFS);
24103+}
24104+
24105+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused)
24106+{
24107+ synchronize_rcu();
24108+}
24109+
24110+static inline void au_lcnt_fin(au_lcnt_t *cnt, int do_sync)
24111+{
24112+ percpu_ref_kill(cnt);
24113+ if (do_sync)
24114+ au_lcnt_wait_for_fin(cnt);
24115+}
24116+
24117+static inline void au_lcnt_inc(au_lcnt_t *cnt)
24118+{
24119+ percpu_ref_get(cnt);
24120+}
24121+
24122+static inline void au_lcnt_dec(au_lcnt_t *cnt)
24123+{
24124+ percpu_ref_put(cnt);
24125+}
24126+
24127+/*
24128+ * avoid calling this func as possible.
24129+ */
24130+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev)
24131+{
24132+ long l;
24133+
24134+ percpu_ref_switch_to_atomic_sync(cnt);
24135+ l = atomic_long_read(&cnt->count);
24136+ if (do_rev)
24137+ percpu_ref_switch_to_percpu(cnt);
24138+
24139+ /* percpu_ref is initialized by 1 instead of 0 */
24140+ return l - 1;
24141+}
24142+#endif
24143+
24144+#ifdef CONFIG_AUFS_DEBUG
24145+#define AuLCntZero(val) do { \
24146+ long l = val; \
24147+ if (l) \
24148+ AuDbg("%s = %ld\n", #val, l); \
24149+} while (0)
24150+#else
24151+#define AuLCntZero(val) do {} while (0)
24152+#endif
24153+
24154+#endif /* __KERNEL__ */
24155+#endif /* __AUFS_LCNT_H__ */
7f207e10 24156diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
eca34b5c 24157--- /usr/share/empty/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 24158+++ linux/fs/aufs/loop.c 2021-05-02 20:15:14.673337458 +0200
062440b3 24159@@ -0,0 +1,148 @@
cd7a4cd9 24160+// SPDX-License-Identifier: GPL-2.0
1facf9fc 24161+/*
d58c55f2 24162+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 24163+ *
24164+ * This program, aufs is free software; you can redistribute it and/or modify
24165+ * it under the terms of the GNU General Public License as published by
24166+ * the Free Software Foundation; either version 2 of the License, or
24167+ * (at your option) any later version.
dece6358
AM
24168+ *
24169+ * This program is distributed in the hope that it will be useful,
24170+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24171+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24172+ * GNU General Public License for more details.
24173+ *
24174+ * You should have received a copy of the GNU General Public License
523b37e3 24175+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24176+ */
24177+
24178+/*
24179+ * support for loopback block device as a branch
24180+ */
24181+
1facf9fc 24182+#include "aufs.h"
24183+
392086de
AM
24184+/* added into drivers/block/loop.c */
24185+static struct file *(*backing_file_func)(struct super_block *sb);
24186+
1facf9fc 24187+/*
24188+ * test if two lower dentries have overlapping branches.
24189+ */
b752ccd1 24190+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
1facf9fc 24191+{
b752ccd1 24192+ struct super_block *h_sb;
392086de
AM
24193+ struct file *backing_file;
24194+
24195+ if (unlikely(!backing_file_func)) {
24196+ /* don't load "loop" module here */
24197+ backing_file_func = symbol_get(loop_backing_file);
24198+ if (unlikely(!backing_file_func))
24199+ /* "loop" module is not loaded */
24200+ return 0;
24201+ }
1facf9fc 24202+
b752ccd1 24203+ h_sb = h_adding->d_sb;
392086de
AM
24204+ backing_file = backing_file_func(h_sb);
24205+ if (!backing_file)
1facf9fc 24206+ return 0;
24207+
2000de60 24208+ h_adding = backing_file->f_path.dentry;
b752ccd1
AM
24209+ /*
24210+ * h_adding can be local NFS.
24211+ * in this case aufs cannot detect the loop.
24212+ */
24213+ if (unlikely(h_adding->d_sb == sb))
1facf9fc 24214+ return 1;
b752ccd1 24215+ return !!au_test_subdir(h_adding, sb->s_root);
1facf9fc 24216+}
24217+
24218+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
24219+int au_test_loopback_kthread(void)
24220+{
b752ccd1
AM
24221+ int ret;
24222+ struct task_struct *tsk = current;
a2a7ad62 24223+ char c, comm[sizeof(tsk->comm)];
b752ccd1
AM
24224+
24225+ ret = 0;
24226+ if (tsk->flags & PF_KTHREAD) {
a2a7ad62
AM
24227+ get_task_comm(comm, tsk);
24228+ c = comm[4];
b752ccd1 24229+ ret = ('0' <= c && c <= '9'
a2a7ad62 24230+ && !strncmp(comm, "loop", 4));
b752ccd1 24231+ }
1facf9fc 24232+
b752ccd1 24233+ return ret;
1facf9fc 24234+}
87a755f4
AM
24235+
24236+/* ---------------------------------------------------------------------- */
24237+
24238+#define au_warn_loopback_step 16
24239+static int au_warn_loopback_nelem = au_warn_loopback_step;
24240+static unsigned long *au_warn_loopback_array;
24241+
24242+void au_warn_loopback(struct super_block *h_sb)
24243+{
24244+ int i, new_nelem;
24245+ unsigned long *a, magic;
24246+ static DEFINE_SPINLOCK(spin);
24247+
24248+ magic = h_sb->s_magic;
24249+ spin_lock(&spin);
24250+ a = au_warn_loopback_array;
24251+ for (i = 0; i < au_warn_loopback_nelem && *a; i++)
24252+ if (a[i] == magic) {
24253+ spin_unlock(&spin);
24254+ return;
24255+ }
24256+
24257+ /* h_sb is new to us, print it */
24258+ if (i < au_warn_loopback_nelem) {
24259+ a[i] = magic;
24260+ goto pr;
24261+ }
24262+
24263+ /* expand the array */
24264+ new_nelem = au_warn_loopback_nelem + au_warn_loopback_step;
24265+ a = au_kzrealloc(au_warn_loopback_array,
24266+ au_warn_loopback_nelem * sizeof(unsigned long),
e2f27e51
AM
24267+ new_nelem * sizeof(unsigned long), GFP_ATOMIC,
24268+ /*may_shrink*/0);
87a755f4
AM
24269+ if (a) {
24270+ au_warn_loopback_nelem = new_nelem;
24271+ au_warn_loopback_array = a;
24272+ a[i] = magic;
24273+ goto pr;
24274+ }
24275+
24276+ spin_unlock(&spin);
24277+ AuWarn1("realloc failed, ignored\n");
24278+ return;
24279+
24280+pr:
24281+ spin_unlock(&spin);
0c3ec466
AM
24282+ pr_warn("you may want to try another patch for loopback file "
24283+ "on %s(0x%lx) branch\n", au_sbtype(h_sb), magic);
87a755f4
AM
24284+}
24285+
24286+int au_loopback_init(void)
24287+{
24288+ int err;
24289+ struct super_block *sb __maybe_unused;
24290+
fbc438ed 24291+ BUILD_BUG_ON(sizeof(sb->s_magic) != sizeof(*au_warn_loopback_array));
87a755f4
AM
24292+
24293+ err = 0;
24294+ au_warn_loopback_array = kcalloc(au_warn_loopback_step,
24295+ sizeof(unsigned long), GFP_NOFS);
24296+ if (unlikely(!au_warn_loopback_array))
24297+ err = -ENOMEM;
24298+
24299+ return err;
24300+}
24301+
24302+void au_loopback_fin(void)
24303+{
79b8bda9
AM
24304+ if (backing_file_func)
24305+ symbol_put(loop_backing_file);
9f237c51 24306+ au_kfree_try_rcu(au_warn_loopback_array);
87a755f4 24307+}
7f207e10 24308diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
eca34b5c 24309--- /usr/share/empty/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 24310+++ linux/fs/aufs/loop.h 2021-05-02 20:15:14.673337458 +0200
eca801bf 24311@@ -0,0 +1,55 @@
062440b3 24312+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 24313+/*
d58c55f2 24314+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 24315+ *
24316+ * This program, aufs is free software; you can redistribute it and/or modify
24317+ * it under the terms of the GNU General Public License as published by
24318+ * the Free Software Foundation; either version 2 of the License, or
24319+ * (at your option) any later version.
dece6358
AM
24320+ *
24321+ * This program is distributed in the hope that it will be useful,
24322+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24323+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24324+ * GNU General Public License for more details.
24325+ *
24326+ * You should have received a copy of the GNU General Public License
523b37e3 24327+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24328+ */
24329+
24330+/*
24331+ * support for loopback mount as a branch
24332+ */
24333+
24334+#ifndef __AUFS_LOOP_H__
24335+#define __AUFS_LOOP_H__
24336+
24337+#ifdef __KERNEL__
24338+
dece6358
AM
24339+struct dentry;
24340+struct super_block;
1facf9fc 24341+
24342+#ifdef CONFIG_AUFS_BDEV_LOOP
392086de
AM
24343+/* drivers/block/loop.c */
24344+struct file *loop_backing_file(struct super_block *sb);
24345+
1facf9fc 24346+/* loop.c */
b752ccd1 24347+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
1facf9fc 24348+int au_test_loopback_kthread(void);
87a755f4
AM
24349+void au_warn_loopback(struct super_block *h_sb);
24350+
24351+int au_loopback_init(void);
24352+void au_loopback_fin(void);
1facf9fc 24353+#else
83b672a5 24354+AuStub(struct file *, loop_backing_file, return NULL, struct super_block *sb)
eca801bf 24355+
4a4d8108 24356+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
b752ccd1 24357+ struct dentry *h_adding)
4a4d8108 24358+AuStubInt0(au_test_loopback_kthread, void)
87a755f4
AM
24359+AuStubVoid(au_warn_loopback, struct super_block *h_sb)
24360+
24361+AuStubInt0(au_loopback_init, void)
24362+AuStubVoid(au_loopback_fin, void)
1facf9fc 24363+#endif /* BLK_DEV_LOOP */
24364+
24365+#endif /* __KERNEL__ */
24366+#endif /* __AUFS_LOOP_H__ */
7f207e10 24367diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
eca34b5c 24368--- /usr/share/empty/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 24369+++ linux/fs/aufs/magic.mk 2021-05-02 20:15:14.673337458 +0200
2121bcd9
AM
24370@@ -0,0 +1,31 @@
24371+# SPDX-License-Identifier: GPL-2.0
1facf9fc 24372+
24373+# defined in ${srctree}/fs/fuse/inode.c
24374+# tristate
24375+ifdef CONFIG_FUSE_FS
24376+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
24377+endif
24378+
1facf9fc 24379+# defined in ${srctree}/fs/xfs/xfs_sb.h
24380+# tristate
24381+ifdef CONFIG_XFS_FS
24382+ccflags-y += -DXFS_SB_MAGIC=0x58465342
24383+endif
24384+
24385+# defined in ${srctree}/fs/configfs/mount.c
24386+# tristate
24387+ifdef CONFIG_CONFIGFS_FS
24388+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
24389+endif
24390+
1facf9fc 24391+# defined in ${srctree}/fs/ubifs/ubifs.h
24392+# tristate
24393+ifdef CONFIG_UBIFS_FS
24394+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
24395+endif
4a4d8108
AM
24396+
24397+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
24398+# tristate
24399+ifdef CONFIG_HFSPLUS_FS
24400+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
24401+endif
7f207e10 24402diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
eca34b5c 24403--- /usr/share/empty/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 24404+++ linux/fs/aufs/Makefile 2021-05-02 20:15:14.670004120 +0200
2121bcd9
AM
24405@@ -0,0 +1,46 @@
24406+# SPDX-License-Identifier: GPL-2.0
4a4d8108
AM
24407+
24408+include ${src}/magic.mk
24409+ifeq (${CONFIG_AUFS_FS},m)
24410+include ${src}/conf.mk
24411+endif
24412+-include ${src}/priv_def.mk
24413+
24414+# cf. include/linux/kernel.h
24415+# enable pr_debug
24416+ccflags-y += -DDEBUG
f6c5ef8b
AM
24417+# sparse requires the full pathname
24418+ifdef M
523b37e3 24419+ccflags-y += -include ${M}/../../include/uapi/linux/aufs_type.h
f6c5ef8b 24420+else
523b37e3 24421+ccflags-y += -include ${srctree}/include/uapi/linux/aufs_type.h
f6c5ef8b 24422+endif
4a4d8108
AM
24423+
24424+obj-$(CONFIG_AUFS_FS) += aufs.o
24425+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
24426+ wkq.o vfsub.o dcsub.o \
e49829fe 24427+ cpup.o whout.o wbr_policy.o \
4a4d8108
AM
24428+ dinfo.o dentry.o \
24429+ dynop.o \
24430+ finfo.o file.o f_op.o \
24431+ dir.o vdir.o \
24432+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
c2b27bf2 24433+ mvdown.o ioctl.o
4a4d8108
AM
24434+
24435+# all are boolean
e49829fe 24436+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o
4a4d8108
AM
24437+aufs-$(CONFIG_SYSFS) += sysfs.o
24438+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
24439+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
24440+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
24441+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
4a4d8108 24442+aufs-$(CONFIG_AUFS_EXPORT) += export.o
c1595e42
JR
24443+aufs-$(CONFIG_AUFS_XATTR) += xattr.o
24444+aufs-$(CONFIG_FS_POSIX_ACL) += posix_acl.o
8b6a4947 24445+aufs-$(CONFIG_AUFS_DIRREN) += dirren.o
076b876e 24446+aufs-$(CONFIG_AUFS_FHSM) += fhsm.o
4a4d8108
AM
24447+aufs-$(CONFIG_AUFS_POLL) += poll.o
24448+aufs-$(CONFIG_AUFS_RDU) += rdu.o
4a4d8108
AM
24449+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
24450+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
24451+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
7f207e10 24452diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
eca34b5c 24453--- /usr/share/empty/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 24454+++ linux/fs/aufs/module.c 2021-05-02 20:15:14.673337458 +0200
062440b3 24455@@ -0,0 +1,273 @@
cd7a4cd9 24456+// SPDX-License-Identifier: GPL-2.0
1facf9fc 24457+/*
d58c55f2 24458+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 24459+ *
24460+ * This program, aufs is free software; you can redistribute it and/or modify
24461+ * it under the terms of the GNU General Public License as published by
24462+ * the Free Software Foundation; either version 2 of the License, or
24463+ * (at your option) any later version.
dece6358
AM
24464+ *
24465+ * This program is distributed in the hope that it will be useful,
24466+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24467+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24468+ * GNU General Public License for more details.
24469+ *
24470+ * You should have received a copy of the GNU General Public License
523b37e3 24471+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24472+ */
24473+
24474+/*
24475+ * module global variables and operations
24476+ */
24477+
24478+#include <linux/module.h>
24479+#include <linux/seq_file.h>
24480+#include "aufs.h"
24481+
e2f27e51
AM
24482+/* shrinkable realloc */
24483+void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink)
1facf9fc 24484+{
e2f27e51
AM
24485+ size_t sz;
24486+ int diff;
1facf9fc 24487+
e2f27e51
AM
24488+ sz = 0;
24489+ diff = -1;
24490+ if (p) {
24491+#if 0 /* unused */
24492+ if (!new_sz) {
9f237c51 24493+ au_kfree_rcu(p);
e2f27e51
AM
24494+ p = NULL;
24495+ goto out;
24496+ }
24497+#else
24498+ AuDebugOn(!new_sz);
24499+#endif
24500+ sz = ksize(p);
24501+ diff = au_kmidx_sub(sz, new_sz);
24502+ }
24503+ if (sz && !diff)
24504+ goto out;
24505+
24506+ if (sz < new_sz)
24507+ /* expand or SLOB */
24508+ p = krealloc(p, new_sz, gfp);
24509+ else if (new_sz < sz && may_shrink) {
24510+ /* shrink */
24511+ void *q;
24512+
24513+ q = kmalloc(new_sz, gfp);
24514+ if (q) {
24515+ if (p) {
24516+ memcpy(q, p, new_sz);
9f237c51 24517+ au_kfree_try_rcu(p);
e2f27e51
AM
24518+ }
24519+ p = q;
24520+ } else
24521+ p = NULL;
24522+ }
24523+
24524+out:
24525+ return p;
24526+}
24527+
24528+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp,
24529+ int may_shrink)
24530+{
24531+ p = au_krealloc(p, new_sz, gfp, may_shrink);
24532+ if (p && new_sz > nused)
1facf9fc 24533+ memset(p + nused, 0, new_sz - nused);
24534+ return p;
24535+}
24536+
24537+/* ---------------------------------------------------------------------- */
1facf9fc 24538+/*
24539+ * aufs caches
24540+ */
1c60b727 24541+struct kmem_cache *au_cache[AuCache_Last];
5afbbe0d
AM
24542+
24543+static void au_cache_fin(void)
24544+{
24545+ int i;
24546+
24547+ /*
24548+ * Make sure all delayed rcu free inodes are flushed before we
24549+ * destroy cache.
24550+ */
24551+ rcu_barrier();
24552+
24553+ /* excluding AuCache_HNOTIFY */
24554+ BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last);
24555+ for (i = 0; i < AuCache_HNOTIFY; i++) {
1c60b727
AM
24556+ kmem_cache_destroy(au_cache[i]);
24557+ au_cache[i] = NULL;
5afbbe0d
AM
24558+ }
24559+}
24560+
1facf9fc 24561+static int __init au_cache_init(void)
24562+{
1c60b727
AM
24563+ au_cache[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
24564+ if (au_cache[AuCache_DINFO])
027c5e7a 24565+ /* SLAB_DESTROY_BY_RCU */
1c60b727 24566+ au_cache[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
f0c0a007 24567+ au_icntnr_init_once);
1c60b727
AM
24568+ if (au_cache[AuCache_ICNTNR])
24569+ au_cache[AuCache_FINFO] = AuCacheCtor(au_finfo,
f0c0a007 24570+ au_fi_init_once);
1c60b727
AM
24571+ if (au_cache[AuCache_FINFO])
24572+ au_cache[AuCache_VDIR] = AuCache(au_vdir);
24573+ if (au_cache[AuCache_VDIR])
24574+ au_cache[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
24575+ if (au_cache[AuCache_DEHSTR])
1facf9fc 24576+ return 0;
24577+
5afbbe0d 24578+ au_cache_fin();
1facf9fc 24579+ return -ENOMEM;
24580+}
24581+
1facf9fc 24582+/* ---------------------------------------------------------------------- */
24583+
24584+int au_dir_roflags;
24585+
e49829fe 24586+#ifdef CONFIG_AUFS_SBILIST
1e00d052
AM
24587+/*
24588+ * iterate_supers_type() doesn't protect us from
24589+ * remounting (branch management)
24590+ */
8b6a4947 24591+struct hlist_bl_head au_sbilist;
e49829fe
JR
24592+#endif
24593+
1facf9fc 24594+/*
24595+ * functions for module interface.
24596+ */
24597+MODULE_LICENSE("GPL");
24598+/* MODULE_LICENSE("GPL v2"); */
dece6358 24599+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 24600+MODULE_DESCRIPTION(AUFS_NAME
24601+ " -- Advanced multi layered unification filesystem");
24602+MODULE_VERSION(AUFS_VERSION);
c06a8ce3 24603+MODULE_ALIAS_FS(AUFS_NAME);
1facf9fc 24604+
1facf9fc 24605+/* this module parameter has no meaning when SYSFS is disabled */
24606+int sysaufs_brs = 1;
24607+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
cd7a4cd9 24608+module_param_named(brs, sysaufs_brs, int, 0444);
1facf9fc 24609+
076b876e 24610+/* this module parameter has no meaning when USER_NS is disabled */
8cdd5066 24611+bool au_userns;
076b876e 24612+MODULE_PARM_DESC(allow_userns, "allow unprivileged to mount under userns");
cd7a4cd9 24613+module_param_named(allow_userns, au_userns, bool, 0444);
076b876e 24614+
1facf9fc 24615+/* ---------------------------------------------------------------------- */
24616+
24617+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
24618+
24619+int au_seq_path(struct seq_file *seq, struct path *path)
24620+{
79b8bda9
AM
24621+ int err;
24622+
24623+ err = seq_path(seq, path, au_esc_chars);
1c60b727 24624+ if (err >= 0)
79b8bda9 24625+ err = 0;
1c60b727 24626+ else
79b8bda9
AM
24627+ err = -ENOMEM;
24628+
24629+ return err;
1facf9fc 24630+}
24631+
24632+/* ---------------------------------------------------------------------- */
24633+
24634+static int __init aufs_init(void)
24635+{
24636+ int err, i;
24637+ char *p;
24638+
24639+ p = au_esc_chars;
24640+ for (i = 1; i <= ' '; i++)
24641+ *p++ = i;
24642+ *p++ = '\\';
24643+ *p++ = '\x7f';
24644+ *p = 0;
24645+
24646+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
24647+
b95c5147
AM
24648+ memcpy(aufs_iop_nogetattr, aufs_iop, sizeof(aufs_iop));
24649+ for (i = 0; i < AuIop_Last; i++)
24650+ aufs_iop_nogetattr[i].getattr = NULL;
24651+
1c60b727 24652+ memset(au_cache, 0, sizeof(au_cache)); /* including hnotify */
f0c0a007 24653+
e49829fe 24654+ au_sbilist_init();
1facf9fc 24655+ sysaufs_brs_init();
24656+ au_debug_init();
4a4d8108 24657+ au_dy_init();
1facf9fc 24658+ err = sysaufs_init();
24659+ if (unlikely(err))
24660+ goto out;
062440b3 24661+ err = dbgaufs_init();
4f0767ce 24662+ if (unlikely(err))
953406b4 24663+ goto out_sysaufs;
062440b3
AM
24664+ err = au_procfs_init();
24665+ if (unlikely(err))
24666+ goto out_dbgaufs;
e49829fe
JR
24667+ err = au_wkq_init();
24668+ if (unlikely(err))
24669+ goto out_procfs;
87a755f4 24670+ err = au_loopback_init();
1facf9fc 24671+ if (unlikely(err))
24672+ goto out_wkq;
87a755f4
AM
24673+ err = au_hnotify_init();
24674+ if (unlikely(err))
24675+ goto out_loopback;
1facf9fc 24676+ err = au_sysrq_init();
24677+ if (unlikely(err))
24678+ goto out_hin;
24679+ err = au_cache_init();
24680+ if (unlikely(err))
24681+ goto out_sysrq;
076b876e
AM
24682+
24683+ aufs_fs_type.fs_flags |= au_userns ? FS_USERNS_MOUNT : 0;
1facf9fc 24684+ err = register_filesystem(&aufs_fs_type);
24685+ if (unlikely(err))
24686+ goto out_cache;
076b876e 24687+
4a4d8108
AM
24688+ /* since we define pr_fmt, call printk directly */
24689+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
1facf9fc 24690+ goto out; /* success */
24691+
4f0767ce 24692+out_cache:
1facf9fc 24693+ au_cache_fin();
4f0767ce 24694+out_sysrq:
1facf9fc 24695+ au_sysrq_fin();
4f0767ce 24696+out_hin:
4a4d8108 24697+ au_hnotify_fin();
87a755f4
AM
24698+out_loopback:
24699+ au_loopback_fin();
4f0767ce 24700+out_wkq:
1facf9fc 24701+ au_wkq_fin();
e49829fe
JR
24702+out_procfs:
24703+ au_procfs_fin();
062440b3
AM
24704+out_dbgaufs:
24705+ dbgaufs_fin();
4f0767ce 24706+out_sysaufs:
1facf9fc 24707+ sysaufs_fin();
4a4d8108 24708+ au_dy_fin();
4f0767ce 24709+out:
1facf9fc 24710+ return err;
24711+}
24712+
24713+static void __exit aufs_exit(void)
24714+{
24715+ unregister_filesystem(&aufs_fs_type);
24716+ au_cache_fin();
24717+ au_sysrq_fin();
4a4d8108 24718+ au_hnotify_fin();
87a755f4 24719+ au_loopback_fin();
1facf9fc 24720+ au_wkq_fin();
e49829fe 24721+ au_procfs_fin();
062440b3 24722+ dbgaufs_fin();
1facf9fc 24723+ sysaufs_fin();
4a4d8108 24724+ au_dy_fin();
1facf9fc 24725+}
24726+
24727+module_init(aufs_init);
24728+module_exit(aufs_exit);
7f207e10 24729diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
eca34b5c 24730--- /usr/share/empty/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 24731+++ linux/fs/aufs/module.h 2021-05-02 20:15:14.673337458 +0200
9f237c51 24732@@ -0,0 +1,166 @@
062440b3 24733+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 24734+/*
d58c55f2 24735+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 24736+ *
24737+ * This program, aufs is free software; you can redistribute it and/or modify
24738+ * it under the terms of the GNU General Public License as published by
24739+ * the Free Software Foundation; either version 2 of the License, or
24740+ * (at your option) any later version.
dece6358
AM
24741+ *
24742+ * This program is distributed in the hope that it will be useful,
24743+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24744+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24745+ * GNU General Public License for more details.
24746+ *
24747+ * You should have received a copy of the GNU General Public License
523b37e3 24748+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24749+ */
24750+
24751+/*
24752+ * module initialization and module-global
24753+ */
24754+
24755+#ifndef __AUFS_MODULE_H__
24756+#define __AUFS_MODULE_H__
24757+
24758+#ifdef __KERNEL__
24759+
24760+#include <linux/slab.h>
9f237c51
AM
24761+#include "debug.h"
24762+#include "dentry.h"
24763+#include "dir.h"
24764+#include "file.h"
24765+#include "inode.h"
1facf9fc 24766+
dece6358
AM
24767+struct path;
24768+struct seq_file;
24769+
1facf9fc 24770+/* module parameters */
1facf9fc 24771+extern int sysaufs_brs;
8cdd5066 24772+extern bool au_userns;
1facf9fc 24773+
24774+/* ---------------------------------------------------------------------- */
24775+
24776+extern int au_dir_roflags;
24777+
e2f27e51
AM
24778+void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink);
24779+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp,
24780+ int may_shrink);
24781+
9f237c51
AM
24782+/*
24783+ * Comparing the size of the object with sizeof(struct rcu_head)
24784+ * case 1: object is always larger
24785+ * --> au_kfree_rcu() or au_kfree_do_rcu()
24786+ * case 2: object is always smaller
24787+ * --> au_kfree_small()
24788+ * case 3: object can be any size
24789+ * --> au_kfree_try_rcu()
24790+ */
24791+
24792+static inline void au_kfree_do_rcu(const void *p)
24793+{
24794+ struct {
24795+ struct rcu_head rcu;
24796+ } *a = (void *)p;
24797+
24798+ kfree_rcu(a, rcu);
24799+}
24800+
24801+#define au_kfree_rcu(_p) do { \
24802+ typeof(_p) p = (_p); \
24803+ BUILD_BUG_ON(sizeof(*p) < sizeof(struct rcu_head)); \
24804+ if (p) \
24805+ au_kfree_do_rcu(p); \
24806+ } while (0)
24807+
24808+#define au_kfree_do_sz_test(sz) (sz >= sizeof(struct rcu_head))
24809+#define au_kfree_sz_test(p) (p && au_kfree_do_sz_test(ksize(p)))
24810+
24811+static inline void au_kfree_try_rcu(const void *p)
24812+{
24813+ if (!p)
24814+ return;
24815+ if (au_kfree_sz_test(p))
24816+ au_kfree_do_rcu(p);
24817+ else
24818+ kfree(p);
24819+}
24820+
24821+static inline void au_kfree_small(const void *p)
24822+{
24823+ if (!p)
24824+ return;
24825+ AuDebugOn(au_kfree_sz_test(p));
24826+ kfree(p);
24827+}
24828+
e2f27e51
AM
24829+static inline int au_kmidx_sub(size_t sz, size_t new_sz)
24830+{
24831+#ifndef CONFIG_SLOB
24832+ return kmalloc_index(sz) - kmalloc_index(new_sz);
24833+#else
24834+ return -1; /* SLOB is untested */
24835+#endif
24836+}
24837+
1facf9fc 24838+int au_seq_path(struct seq_file *seq, struct path *path);
24839+
e49829fe
JR
24840+#ifdef CONFIG_PROC_FS
24841+/* procfs.c */
24842+int __init au_procfs_init(void);
24843+void au_procfs_fin(void);
24844+#else
24845+AuStubInt0(au_procfs_init, void);
24846+AuStubVoid(au_procfs_fin, void);
24847+#endif
24848+
4f0767ce
JR
24849+/* ---------------------------------------------------------------------- */
24850+
1c60b727 24851+/* kmem cache */
1facf9fc 24852+enum {
24853+ AuCache_DINFO,
24854+ AuCache_ICNTNR,
24855+ AuCache_FINFO,
24856+ AuCache_VDIR,
24857+ AuCache_DEHSTR,
7eafdf33 24858+ AuCache_HNOTIFY, /* must be last */
1facf9fc 24859+ AuCache_Last
24860+};
24861+
1c60b727 24862+extern struct kmem_cache *au_cache[AuCache_Last];
f0c0a007 24863+
4a4d8108
AM
24864+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
24865+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
24866+#define AuCacheCtor(type, ctor) \
24867+ kmem_cache_create(#type, sizeof(struct type), \
24868+ __alignof__(struct type), AuCacheFlags, ctor)
1facf9fc 24869+
9f237c51
AM
24870+#define AuCacheFuncs(name, index) \
24871+ static inline struct au_##name *au_cache_alloc_##name(void) \
24872+ { return kmem_cache_alloc(au_cache[AuCache_##index], GFP_NOFS); } \
24873+ static inline void au_cache_free_##name##_norcu(struct au_##name *p) \
24874+ { kmem_cache_free(au_cache[AuCache_##index], p); } \
24875+ \
24876+ static inline void au_cache_free_##name##_rcu_cb(struct rcu_head *rcu) \
24877+ { void *p = rcu; \
24878+ p -= offsetof(struct au_##name, rcu); \
24879+ kmem_cache_free(au_cache[AuCache_##index], p); } \
24880+ static inline void au_cache_free_##name##_rcu(struct au_##name *p) \
24881+ { BUILD_BUG_ON(sizeof(struct au_##name) < sizeof(struct rcu_head)); \
24882+ call_rcu(&p->rcu, au_cache_free_##name##_rcu_cb); } \
24883+ \
24884+ static inline void au_cache_free_##name(struct au_##name *p) \
24885+ { /* au_cache_free_##name##_norcu(p); */ \
24886+ au_cache_free_##name##_rcu(p); }
1facf9fc 24887+
24888+AuCacheFuncs(dinfo, DINFO);
24889+AuCacheFuncs(icntnr, ICNTNR);
24890+AuCacheFuncs(finfo, FINFO);
24891+AuCacheFuncs(vdir, VDIR);
4a4d8108
AM
24892+AuCacheFuncs(vdir_dehstr, DEHSTR);
24893+#ifdef CONFIG_AUFS_HNOTIFY
24894+AuCacheFuncs(hnotify, HNOTIFY);
24895+#endif
1facf9fc 24896+
4a4d8108
AM
24897+#endif /* __KERNEL__ */
24898+#endif /* __AUFS_MODULE_H__ */
c2b27bf2 24899diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
eca34b5c 24900--- /usr/share/empty/fs/aufs/mvdown.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 24901+++ linux/fs/aufs/mvdown.c 2021-05-02 20:15:14.673337458 +0200
ba1aed25 24902@@ -0,0 +1,706 @@
cd7a4cd9 24903+// SPDX-License-Identifier: GPL-2.0
c2b27bf2 24904+/*
d58c55f2 24905+ * Copyright (C) 2011-2020 Junjiro R. Okajima
c2b27bf2
AM
24906+ *
24907+ * This program, aufs is free software; you can redistribute it and/or modify
24908+ * it under the terms of the GNU General Public License as published by
24909+ * the Free Software Foundation; either version 2 of the License, or
24910+ * (at your option) any later version.
24911+ *
24912+ * This program is distributed in the hope that it will be useful,
24913+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24914+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24915+ * GNU General Public License for more details.
24916+ *
24917+ * You should have received a copy of the GNU General Public License
523b37e3
AM
24918+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
24919+ */
24920+
24921+/*
24922+ * move-down, opposite of copy-up
c2b27bf2
AM
24923+ */
24924+
24925+#include "aufs.h"
24926+
c2b27bf2
AM
24927+struct au_mvd_args {
24928+ struct {
c2b27bf2
AM
24929+ struct super_block *h_sb;
24930+ struct dentry *h_parent;
24931+ struct au_hinode *hdir;
392086de 24932+ struct inode *h_dir, *h_inode;
c1595e42 24933+ struct au_pin pin;
c2b27bf2
AM
24934+ } info[AUFS_MVDOWN_NARRAY];
24935+
24936+ struct aufs_mvdown mvdown;
24937+ struct dentry *dentry, *parent;
24938+ struct inode *inode, *dir;
24939+ struct super_block *sb;
24940+ aufs_bindex_t bopq, bwh, bfound;
24941+ unsigned char rename_lock;
c2b27bf2
AM
24942+};
24943+
392086de 24944+#define mvd_errno mvdown.au_errno
076b876e
AM
24945+#define mvd_bsrc mvdown.stbr[AUFS_MVDOWN_UPPER].bindex
24946+#define mvd_src_brid mvdown.stbr[AUFS_MVDOWN_UPPER].brid
24947+#define mvd_bdst mvdown.stbr[AUFS_MVDOWN_LOWER].bindex
24948+#define mvd_dst_brid mvdown.stbr[AUFS_MVDOWN_LOWER].brid
c2b27bf2 24949+
392086de
AM
24950+#define mvd_h_src_sb info[AUFS_MVDOWN_UPPER].h_sb
24951+#define mvd_h_src_parent info[AUFS_MVDOWN_UPPER].h_parent
24952+#define mvd_hdir_src info[AUFS_MVDOWN_UPPER].hdir
24953+#define mvd_h_src_dir info[AUFS_MVDOWN_UPPER].h_dir
24954+#define mvd_h_src_inode info[AUFS_MVDOWN_UPPER].h_inode
c1595e42 24955+#define mvd_pin_src info[AUFS_MVDOWN_UPPER].pin
392086de
AM
24956+
24957+#define mvd_h_dst_sb info[AUFS_MVDOWN_LOWER].h_sb
24958+#define mvd_h_dst_parent info[AUFS_MVDOWN_LOWER].h_parent
24959+#define mvd_hdir_dst info[AUFS_MVDOWN_LOWER].hdir
24960+#define mvd_h_dst_dir info[AUFS_MVDOWN_LOWER].h_dir
24961+#define mvd_h_dst_inode info[AUFS_MVDOWN_LOWER].h_inode
c1595e42 24962+#define mvd_pin_dst info[AUFS_MVDOWN_LOWER].pin
c2b27bf2
AM
24963+
24964+#define AU_MVD_PR(flag, ...) do { \
24965+ if (flag) \
24966+ pr_err(__VA_ARGS__); \
24967+ } while (0)
24968+
076b876e
AM
24969+static int find_lower_writable(struct au_mvd_args *a)
24970+{
24971+ struct super_block *sb;
5afbbe0d 24972+ aufs_bindex_t bindex, bbot;
076b876e
AM
24973+ struct au_branch *br;
24974+
24975+ sb = a->sb;
24976+ bindex = a->mvd_bsrc;
5afbbe0d 24977+ bbot = au_sbbot(sb);
076b876e 24978+ if (a->mvdown.flags & AUFS_MVDOWN_FHSM_LOWER)
5afbbe0d 24979+ for (bindex++; bindex <= bbot; bindex++) {
076b876e
AM
24980+ br = au_sbr(sb, bindex);
24981+ if (au_br_fhsm(br->br_perm)
8b6a4947 24982+ && !sb_rdonly(au_br_sb(br)))
076b876e
AM
24983+ return bindex;
24984+ }
24985+ else if (!(a->mvdown.flags & AUFS_MVDOWN_ROLOWER))
5afbbe0d 24986+ for (bindex++; bindex <= bbot; bindex++) {
076b876e
AM
24987+ br = au_sbr(sb, bindex);
24988+ if (!au_br_rdonly(br))
24989+ return bindex;
24990+ }
24991+ else
5afbbe0d 24992+ for (bindex++; bindex <= bbot; bindex++) {
076b876e 24993+ br = au_sbr(sb, bindex);
8b6a4947 24994+ if (!sb_rdonly(au_br_sb(br))) {
076b876e
AM
24995+ if (au_br_rdonly(br))
24996+ a->mvdown.flags
24997+ |= AUFS_MVDOWN_ROLOWER_R;
24998+ return bindex;
24999+ }
25000+ }
25001+
25002+ return -1;
25003+}
25004+
c2b27bf2 25005+/* make the parent dir on bdst */
392086de 25006+static int au_do_mkdir(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25007+{
25008+ int err;
25009+
25010+ err = 0;
25011+ a->mvd_hdir_src = au_hi(a->dir, a->mvd_bsrc);
25012+ a->mvd_hdir_dst = au_hi(a->dir, a->mvd_bdst);
25013+ a->mvd_h_src_parent = au_h_dptr(a->parent, a->mvd_bsrc);
25014+ a->mvd_h_dst_parent = NULL;
5afbbe0d 25015+ if (au_dbbot(a->parent) >= a->mvd_bdst)
c2b27bf2
AM
25016+ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst);
25017+ if (!a->mvd_h_dst_parent) {
25018+ err = au_cpdown_dirs(a->dentry, a->mvd_bdst);
25019+ if (unlikely(err)) {
392086de 25020+ AU_MVD_PR(dmsg, "cpdown_dirs failed\n");
c2b27bf2
AM
25021+ goto out;
25022+ }
25023+ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst);
25024+ }
25025+
25026+out:
25027+ AuTraceErr(err);
25028+ return err;
25029+}
25030+
25031+/* lock them all */
392086de 25032+static int au_do_lock(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25033+{
25034+ int err;
25035+ struct dentry *h_trap;
25036+
25037+ a->mvd_h_src_sb = au_sbr_sb(a->sb, a->mvd_bsrc);
25038+ a->mvd_h_dst_sb = au_sbr_sb(a->sb, a->mvd_bdst);
c1595e42
JR
25039+ err = au_pin(&a->mvd_pin_dst, a->dentry, a->mvd_bdst,
25040+ au_opt_udba(a->sb),
25041+ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
25042+ AuTraceErr(err);
25043+ if (unlikely(err)) {
25044+ AU_MVD_PR(dmsg, "pin_dst failed\n");
25045+ goto out;
25046+ }
25047+
c2b27bf2
AM
25048+ if (a->mvd_h_src_sb != a->mvd_h_dst_sb) {
25049+ a->rename_lock = 0;
c1595e42
JR
25050+ au_pin_init(&a->mvd_pin_src, a->dentry, a->mvd_bsrc,
25051+ AuLsc_DI_PARENT, AuLsc_I_PARENT3,
25052+ au_opt_udba(a->sb),
25053+ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
25054+ err = au_do_pin(&a->mvd_pin_src);
25055+ AuTraceErr(err);
5527c038 25056+ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent);
c1595e42
JR
25057+ if (unlikely(err)) {
25058+ AU_MVD_PR(dmsg, "pin_src failed\n");
25059+ goto out_dst;
25060+ }
25061+ goto out; /* success */
c2b27bf2
AM
25062+ }
25063+
c2b27bf2 25064+ a->rename_lock = 1;
c1595e42
JR
25065+ au_pin_hdir_unlock(&a->mvd_pin_dst);
25066+ err = au_pin(&a->mvd_pin_src, a->dentry, a->mvd_bsrc,
25067+ au_opt_udba(a->sb),
25068+ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
25069+ AuTraceErr(err);
5527c038 25070+ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent);
c1595e42
JR
25071+ if (unlikely(err)) {
25072+ AU_MVD_PR(dmsg, "pin_src failed\n");
25073+ au_pin_hdir_lock(&a->mvd_pin_dst);
25074+ goto out_dst;
25075+ }
25076+ au_pin_hdir_unlock(&a->mvd_pin_src);
c2b27bf2
AM
25077+ h_trap = vfsub_lock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
25078+ a->mvd_h_dst_parent, a->mvd_hdir_dst);
25079+ if (h_trap) {
25080+ err = (h_trap != a->mvd_h_src_parent);
25081+ if (err)
25082+ err = (h_trap != a->mvd_h_dst_parent);
25083+ }
25084+ BUG_ON(err); /* it should never happen */
c1595e42
JR
25085+ if (unlikely(a->mvd_h_src_dir != au_pinned_h_dir(&a->mvd_pin_src))) {
25086+ err = -EBUSY;
25087+ AuTraceErr(err);
25088+ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
25089+ a->mvd_h_dst_parent, a->mvd_hdir_dst);
25090+ au_pin_hdir_lock(&a->mvd_pin_src);
25091+ au_unpin(&a->mvd_pin_src);
25092+ au_pin_hdir_lock(&a->mvd_pin_dst);
25093+ goto out_dst;
25094+ }
25095+ goto out; /* success */
c2b27bf2 25096+
c1595e42
JR
25097+out_dst:
25098+ au_unpin(&a->mvd_pin_dst);
c2b27bf2
AM
25099+out:
25100+ AuTraceErr(err);
25101+ return err;
25102+}
25103+
392086de 25104+static void au_do_unlock(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2 25105+{
c1595e42
JR
25106+ if (!a->rename_lock)
25107+ au_unpin(&a->mvd_pin_src);
25108+ else {
c2b27bf2
AM
25109+ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
25110+ a->mvd_h_dst_parent, a->mvd_hdir_dst);
c1595e42
JR
25111+ au_pin_hdir_lock(&a->mvd_pin_src);
25112+ au_unpin(&a->mvd_pin_src);
25113+ au_pin_hdir_lock(&a->mvd_pin_dst);
25114+ }
25115+ au_unpin(&a->mvd_pin_dst);
c2b27bf2
AM
25116+}
25117+
25118+/* copy-down the file */
392086de 25119+static int au_do_cpdown(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25120+{
25121+ int err;
25122+ struct au_cp_generic cpg = {
25123+ .dentry = a->dentry,
25124+ .bdst = a->mvd_bdst,
25125+ .bsrc = a->mvd_bsrc,
25126+ .len = -1,
c1595e42 25127+ .pin = &a->mvd_pin_dst,
c2b27bf2
AM
25128+ .flags = AuCpup_DTIME | AuCpup_HOPEN
25129+ };
25130+
25131+ AuDbg("b%d, b%d\n", cpg.bsrc, cpg.bdst);
392086de
AM
25132+ if (a->mvdown.flags & AUFS_MVDOWN_OWLOWER)
25133+ au_fset_cpup(cpg.flags, OVERWRITE);
25134+ if (a->mvdown.flags & AUFS_MVDOWN_ROLOWER)
25135+ au_fset_cpup(cpg.flags, RWDST);
c2b27bf2
AM
25136+ err = au_sio_cpdown_simple(&cpg);
25137+ if (unlikely(err))
392086de 25138+ AU_MVD_PR(dmsg, "cpdown failed\n");
c2b27bf2
AM
25139+
25140+ AuTraceErr(err);
25141+ return err;
25142+}
25143+
25144+/*
25145+ * unlink the whiteout on bdst if exist which may be created by UDBA while we
25146+ * were sleeping
25147+ */
392086de 25148+static int au_do_unlink_wh(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25149+{
25150+ int err;
25151+ struct path h_path;
25152+ struct au_branch *br;
523b37e3 25153+ struct inode *delegated;
c2b27bf2
AM
25154+
25155+ br = au_sbr(a->sb, a->mvd_bdst);
25156+ h_path.dentry = au_wh_lkup(a->mvd_h_dst_parent, &a->dentry->d_name, br);
25157+ err = PTR_ERR(h_path.dentry);
25158+ if (IS_ERR(h_path.dentry)) {
392086de 25159+ AU_MVD_PR(dmsg, "wh_lkup failed\n");
c2b27bf2
AM
25160+ goto out;
25161+ }
25162+
25163+ err = 0;
5527c038 25164+ if (d_is_positive(h_path.dentry)) {
c2b27bf2 25165+ h_path.mnt = au_br_mnt(br);
523b37e3 25166+ delegated = NULL;
5527c038 25167+ err = vfsub_unlink(d_inode(a->mvd_h_dst_parent), &h_path,
523b37e3
AM
25168+ &delegated, /*force*/0);
25169+ if (unlikely(err == -EWOULDBLOCK)) {
25170+ pr_warn("cannot retry for NFSv4 delegation"
25171+ " for an internal unlink\n");
25172+ iput(delegated);
25173+ }
c2b27bf2 25174+ if (unlikely(err))
392086de 25175+ AU_MVD_PR(dmsg, "wh_unlink failed\n");
c2b27bf2
AM
25176+ }
25177+ dput(h_path.dentry);
25178+
25179+out:
25180+ AuTraceErr(err);
25181+ return err;
25182+}
25183+
25184+/*
25185+ * unlink the topmost h_dentry
c2b27bf2 25186+ */
392086de 25187+static int au_do_unlink(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25188+{
25189+ int err;
25190+ struct path h_path;
523b37e3 25191+ struct inode *delegated;
c2b27bf2
AM
25192+
25193+ h_path.mnt = au_sbr_mnt(a->sb, a->mvd_bsrc);
25194+ h_path.dentry = au_h_dptr(a->dentry, a->mvd_bsrc);
523b37e3
AM
25195+ delegated = NULL;
25196+ err = vfsub_unlink(a->mvd_h_src_dir, &h_path, &delegated, /*force*/0);
25197+ if (unlikely(err == -EWOULDBLOCK)) {
25198+ pr_warn("cannot retry for NFSv4 delegation"
25199+ " for an internal unlink\n");
25200+ iput(delegated);
25201+ }
c2b27bf2 25202+ if (unlikely(err))
392086de 25203+ AU_MVD_PR(dmsg, "unlink failed\n");
c2b27bf2
AM
25204+
25205+ AuTraceErr(err);
25206+ return err;
25207+}
25208+
076b876e
AM
25209+/* Since mvdown succeeded, we ignore an error of this function */
25210+static void au_do_stfs(const unsigned char dmsg, struct au_mvd_args *a)
25211+{
25212+ int err;
25213+ struct au_branch *br;
25214+
25215+ a->mvdown.flags |= AUFS_MVDOWN_STFS_FAILED;
25216+ br = au_sbr(a->sb, a->mvd_bsrc);
25217+ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_UPPER].stfs);
25218+ if (!err) {
25219+ br = au_sbr(a->sb, a->mvd_bdst);
25220+ a->mvdown.stbr[AUFS_MVDOWN_LOWER].brid = br->br_id;
25221+ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_LOWER].stfs);
25222+ }
25223+ if (!err)
25224+ a->mvdown.flags &= ~AUFS_MVDOWN_STFS_FAILED;
25225+ else
25226+ AU_MVD_PR(dmsg, "statfs failed (%d), ignored\n", err);
25227+}
25228+
c2b27bf2
AM
25229+/*
25230+ * copy-down the file and unlink the bsrc file.
25231+ * - unlink the bdst whout if exist
25232+ * - copy-down the file (with whtmp name and rename)
25233+ * - unlink the bsrc file
25234+ */
392086de 25235+static int au_do_mvdown(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25236+{
25237+ int err;
25238+
392086de 25239+ err = au_do_mkdir(dmsg, a);
c2b27bf2 25240+ if (!err)
392086de 25241+ err = au_do_lock(dmsg, a);
c2b27bf2
AM
25242+ if (unlikely(err))
25243+ goto out;
25244+
25245+ /*
25246+ * do not revert the activities we made on bdst since they should be
25247+ * harmless in aufs.
25248+ */
25249+
392086de 25250+ err = au_do_cpdown(dmsg, a);
c2b27bf2 25251+ if (!err)
392086de
AM
25252+ err = au_do_unlink_wh(dmsg, a);
25253+ if (!err && !(a->mvdown.flags & AUFS_MVDOWN_KUPPER))
25254+ err = au_do_unlink(dmsg, a);
c2b27bf2
AM
25255+ if (unlikely(err))
25256+ goto out_unlock;
25257+
c1595e42
JR
25258+ AuDbg("%pd2, 0x%x, %d --> %d\n",
25259+ a->dentry, a->mvdown.flags, a->mvd_bsrc, a->mvd_bdst);
076b876e
AM
25260+ if (find_lower_writable(a) < 0)
25261+ a->mvdown.flags |= AUFS_MVDOWN_BOTTOM;
25262+
25263+ if (a->mvdown.flags & AUFS_MVDOWN_STFS)
25264+ au_do_stfs(dmsg, a);
25265+
c2b27bf2 25266+ /* maintain internal array */
392086de
AM
25267+ if (!(a->mvdown.flags & AUFS_MVDOWN_KUPPER)) {
25268+ au_set_h_dptr(a->dentry, a->mvd_bsrc, NULL);
5afbbe0d 25269+ au_set_dbtop(a->dentry, a->mvd_bdst);
392086de 25270+ au_set_h_iptr(a->inode, a->mvd_bsrc, NULL, /*flags*/0);
5afbbe0d 25271+ au_set_ibtop(a->inode, a->mvd_bdst);
79b8bda9
AM
25272+ } else {
25273+ /* hide the lower */
25274+ au_set_h_dptr(a->dentry, a->mvd_bdst, NULL);
5afbbe0d 25275+ au_set_dbbot(a->dentry, a->mvd_bsrc);
79b8bda9 25276+ au_set_h_iptr(a->inode, a->mvd_bdst, NULL, /*flags*/0);
5afbbe0d 25277+ au_set_ibbot(a->inode, a->mvd_bsrc);
392086de 25278+ }
5afbbe0d
AM
25279+ if (au_dbbot(a->dentry) < a->mvd_bdst)
25280+ au_set_dbbot(a->dentry, a->mvd_bdst);
25281+ if (au_ibbot(a->inode) < a->mvd_bdst)
25282+ au_set_ibbot(a->inode, a->mvd_bdst);
c2b27bf2
AM
25283+
25284+out_unlock:
392086de 25285+ au_do_unlock(dmsg, a);
c2b27bf2
AM
25286+out:
25287+ AuTraceErr(err);
25288+ return err;
25289+}
25290+
25291+/* ---------------------------------------------------------------------- */
25292+
c2b27bf2 25293+/* make sure the file is idle */
392086de 25294+static int au_mvd_args_busy(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25295+{
25296+ int err, plinked;
c2b27bf2
AM
25297+
25298+ err = 0;
c2b27bf2 25299+ plinked = !!au_opt_test(au_mntflags(a->sb), PLINK);
5afbbe0d 25300+ if (au_dbtop(a->dentry) == a->mvd_bsrc
c1595e42 25301+ && au_dcount(a->dentry) == 1
c2b27bf2 25302+ && atomic_read(&a->inode->i_count) == 1
392086de 25303+ /* && a->mvd_h_src_inode->i_nlink == 1 */
c2b27bf2
AM
25304+ && (!plinked || !au_plink_test(a->inode))
25305+ && a->inode->i_nlink == 1)
25306+ goto out;
25307+
25308+ err = -EBUSY;
392086de 25309+ AU_MVD_PR(dmsg,
c1595e42 25310+ "b%d, d{b%d, c%d?}, i{c%d?, l%u}, hi{l%u}, p{%d, %d}\n",
5afbbe0d 25311+ a->mvd_bsrc, au_dbtop(a->dentry), au_dcount(a->dentry),
c2b27bf2 25312+ atomic_read(&a->inode->i_count), a->inode->i_nlink,
392086de 25313+ a->mvd_h_src_inode->i_nlink,
c2b27bf2
AM
25314+ plinked, plinked ? au_plink_test(a->inode) : 0);
25315+
25316+out:
25317+ AuTraceErr(err);
25318+ return err;
25319+}
25320+
25321+/* make sure the parent dir is fine */
392086de 25322+static int au_mvd_args_parent(const unsigned char dmsg,
c2b27bf2
AM
25323+ struct au_mvd_args *a)
25324+{
25325+ int err;
25326+ aufs_bindex_t bindex;
25327+
25328+ err = 0;
25329+ if (unlikely(au_alive_dir(a->parent))) {
25330+ err = -ENOENT;
392086de 25331+ AU_MVD_PR(dmsg, "parent dir is dead\n");
c2b27bf2
AM
25332+ goto out;
25333+ }
25334+
25335+ a->bopq = au_dbdiropq(a->parent);
25336+ bindex = au_wbr_nonopq(a->dentry, a->mvd_bdst);
25337+ AuDbg("b%d\n", bindex);
25338+ if (unlikely((bindex >= 0 && bindex < a->mvd_bdst)
25339+ || (a->bopq != -1 && a->bopq < a->mvd_bdst))) {
25340+ err = -EINVAL;
392086de
AM
25341+ a->mvd_errno = EAU_MVDOWN_OPAQUE;
25342+ AU_MVD_PR(dmsg, "ancestor is opaque b%d, b%d\n",
c2b27bf2
AM
25343+ a->bopq, a->mvd_bdst);
25344+ }
25345+
25346+out:
25347+ AuTraceErr(err);
25348+ return err;
25349+}
25350+
392086de 25351+static int au_mvd_args_intermediate(const unsigned char dmsg,
c2b27bf2
AM
25352+ struct au_mvd_args *a)
25353+{
25354+ int err;
25355+ struct au_dinfo *dinfo, *tmp;
25356+
25357+ /* lookup the next lower positive entry */
25358+ err = -ENOMEM;
25359+ tmp = au_di_alloc(a->sb, AuLsc_DI_TMP);
25360+ if (unlikely(!tmp))
25361+ goto out;
25362+
25363+ a->bfound = -1;
25364+ a->bwh = -1;
25365+ dinfo = au_di(a->dentry);
25366+ au_di_cp(tmp, dinfo);
25367+ au_di_swap(tmp, dinfo);
25368+
25369+ /* returns the number of positive dentries */
5afbbe0d
AM
25370+ err = au_lkup_dentry(a->dentry, a->mvd_bsrc + 1,
25371+ /* AuLkup_IGNORE_PERM */ 0);
c2b27bf2
AM
25372+ if (!err)
25373+ a->bwh = au_dbwh(a->dentry);
25374+ else if (err > 0)
5afbbe0d 25375+ a->bfound = au_dbtop(a->dentry);
c2b27bf2
AM
25376+
25377+ au_di_swap(tmp, dinfo);
25378+ au_rw_write_unlock(&tmp->di_rwsem);
25379+ au_di_free(tmp);
25380+ if (unlikely(err < 0))
392086de 25381+ AU_MVD_PR(dmsg, "failed look-up lower\n");
c2b27bf2
AM
25382+
25383+ /*
25384+ * here, we have these cases.
25385+ * bfound == -1
25386+ * no positive dentry under bsrc. there are more sub-cases.
25387+ * bwh < 0
25388+ * there no whiteout, we can safely move-down.
25389+ * bwh <= bsrc
25390+ * impossible
25391+ * bsrc < bwh && bwh < bdst
25392+ * there is a whiteout on RO branch. cannot proceed.
25393+ * bwh == bdst
25394+ * there is a whiteout on the RW target branch. it should
25395+ * be removed.
25396+ * bdst < bwh
25397+ * there is a whiteout somewhere unrelated branch.
25398+ * -1 < bfound && bfound <= bsrc
25399+ * impossible.
25400+ * bfound < bdst
25401+ * found, but it is on RO branch between bsrc and bdst. cannot
25402+ * proceed.
25403+ * bfound == bdst
25404+ * found, replace it if AUFS_MVDOWN_FORCE is set. otherwise return
25405+ * error.
25406+ * bdst < bfound
25407+ * found, after we create the file on bdst, it will be hidden.
25408+ */
25409+
25410+ AuDebugOn(a->bfound == -1
25411+ && a->bwh != -1
25412+ && a->bwh <= a->mvd_bsrc);
25413+ AuDebugOn(-1 < a->bfound
25414+ && a->bfound <= a->mvd_bsrc);
25415+
25416+ err = -EINVAL;
25417+ if (a->bfound == -1
25418+ && a->mvd_bsrc < a->bwh
25419+ && a->bwh != -1
25420+ && a->bwh < a->mvd_bdst) {
392086de
AM
25421+ a->mvd_errno = EAU_MVDOWN_WHITEOUT;
25422+ AU_MVD_PR(dmsg, "bsrc %d, bdst %d, bfound %d, bwh %d\n",
c2b27bf2
AM
25423+ a->mvd_bsrc, a->mvd_bdst, a->bfound, a->bwh);
25424+ goto out;
25425+ } else if (a->bfound != -1 && a->bfound < a->mvd_bdst) {
392086de
AM
25426+ a->mvd_errno = EAU_MVDOWN_UPPER;
25427+ AU_MVD_PR(dmsg, "bdst %d, bfound %d\n",
c2b27bf2
AM
25428+ a->mvd_bdst, a->bfound);
25429+ goto out;
25430+ }
25431+
25432+ err = 0; /* success */
25433+
25434+out:
25435+ AuTraceErr(err);
25436+ return err;
25437+}
25438+
392086de 25439+static int au_mvd_args_exist(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25440+{
25441+ int err;
25442+
392086de
AM
25443+ err = 0;
25444+ if (!(a->mvdown.flags & AUFS_MVDOWN_OWLOWER)
25445+ && a->bfound == a->mvd_bdst)
25446+ err = -EEXIST;
c2b27bf2
AM
25447+ AuTraceErr(err);
25448+ return err;
25449+}
25450+
392086de 25451+static int au_mvd_args(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25452+{
25453+ int err;
25454+ struct au_branch *br;
25455+
25456+ err = -EISDIR;
25457+ if (unlikely(S_ISDIR(a->inode->i_mode)))
25458+ goto out;
25459+
25460+ err = -EINVAL;
392086de 25461+ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_UPPER))
5afbbe0d 25462+ a->mvd_bsrc = au_ibtop(a->inode);
392086de
AM
25463+ else {
25464+ a->mvd_bsrc = au_br_index(a->sb, a->mvd_src_brid);
25465+ if (unlikely(a->mvd_bsrc < 0
5afbbe0d
AM
25466+ || (a->mvd_bsrc < au_dbtop(a->dentry)
25467+ || au_dbbot(a->dentry) < a->mvd_bsrc
392086de 25468+ || !au_h_dptr(a->dentry, a->mvd_bsrc))
5afbbe0d
AM
25469+ || (a->mvd_bsrc < au_ibtop(a->inode)
25470+ || au_ibbot(a->inode) < a->mvd_bsrc
392086de
AM
25471+ || !au_h_iptr(a->inode, a->mvd_bsrc)))) {
25472+ a->mvd_errno = EAU_MVDOWN_NOUPPER;
25473+ AU_MVD_PR(dmsg, "no upper\n");
25474+ goto out;
25475+ }
25476+ }
5afbbe0d 25477+ if (unlikely(a->mvd_bsrc == au_sbbot(a->sb))) {
392086de
AM
25478+ a->mvd_errno = EAU_MVDOWN_BOTTOM;
25479+ AU_MVD_PR(dmsg, "on the bottom\n");
c2b27bf2
AM
25480+ goto out;
25481+ }
392086de 25482+ a->mvd_h_src_inode = au_h_iptr(a->inode, a->mvd_bsrc);
c2b27bf2
AM
25483+ br = au_sbr(a->sb, a->mvd_bsrc);
25484+ err = au_br_rdonly(br);
392086de
AM
25485+ if (!(a->mvdown.flags & AUFS_MVDOWN_ROUPPER)) {
25486+ if (unlikely(err))
25487+ goto out;
25488+ } else if (!(vfsub_native_ro(a->mvd_h_src_inode)
25489+ || IS_APPEND(a->mvd_h_src_inode))) {
25490+ if (err)
25491+ a->mvdown.flags |= AUFS_MVDOWN_ROUPPER_R;
25492+ /* go on */
25493+ } else
c2b27bf2
AM
25494+ goto out;
25495+
25496+ err = -EINVAL;
392086de
AM
25497+ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_LOWER)) {
25498+ a->mvd_bdst = find_lower_writable(a);
25499+ if (unlikely(a->mvd_bdst < 0)) {
25500+ a->mvd_errno = EAU_MVDOWN_BOTTOM;
25501+ AU_MVD_PR(dmsg, "no writable lower branch\n");
25502+ goto out;
25503+ }
25504+ } else {
25505+ a->mvd_bdst = au_br_index(a->sb, a->mvd_dst_brid);
25506+ if (unlikely(a->mvd_bdst < 0
5afbbe0d 25507+ || au_sbbot(a->sb) < a->mvd_bdst)) {
392086de
AM
25508+ a->mvd_errno = EAU_MVDOWN_NOLOWERBR;
25509+ AU_MVD_PR(dmsg, "no lower brid\n");
25510+ goto out;
25511+ }
c2b27bf2
AM
25512+ }
25513+
392086de 25514+ err = au_mvd_args_busy(dmsg, a);
c2b27bf2 25515+ if (!err)
392086de 25516+ err = au_mvd_args_parent(dmsg, a);
c2b27bf2 25517+ if (!err)
392086de 25518+ err = au_mvd_args_intermediate(dmsg, a);
c2b27bf2 25519+ if (!err)
392086de 25520+ err = au_mvd_args_exist(dmsg, a);
c2b27bf2
AM
25521+ if (!err)
25522+ AuDbg("b%d, b%d\n", a->mvd_bsrc, a->mvd_bdst);
25523+
25524+out:
25525+ AuTraceErr(err);
25526+ return err;
25527+}
25528+
25529+int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *uarg)
25530+{
392086de
AM
25531+ int err, e;
25532+ unsigned char dmsg;
25533+ struct au_mvd_args *args;
79b8bda9 25534+ struct inode *inode;
c2b27bf2 25535+
79b8bda9 25536+ inode = d_inode(dentry);
c2b27bf2
AM
25537+ err = -EPERM;
25538+ if (unlikely(!capable(CAP_SYS_ADMIN)))
25539+ goto out;
25540+
392086de
AM
25541+ err = -ENOMEM;
25542+ args = kmalloc(sizeof(*args), GFP_NOFS);
25543+ if (unlikely(!args))
25544+ goto out;
25545+
25546+ err = copy_from_user(&args->mvdown, uarg, sizeof(args->mvdown));
25547+ if (!err)
ba1aed25
AM
25548+ /* VERIFY_WRITE */
25549+ err = !access_ok(uarg, sizeof(*uarg));
c2b27bf2
AM
25550+ if (unlikely(err)) {
25551+ err = -EFAULT;
392086de
AM
25552+ AuTraceErr(err);
25553+ goto out_free;
c2b27bf2 25554+ }
392086de
AM
25555+ AuDbg("flags 0x%x\n", args->mvdown.flags);
25556+ args->mvdown.flags &= ~(AUFS_MVDOWN_ROLOWER_R | AUFS_MVDOWN_ROUPPER_R);
25557+ args->mvdown.au_errno = 0;
25558+ args->dentry = dentry;
79b8bda9 25559+ args->inode = inode;
392086de 25560+ args->sb = dentry->d_sb;
c2b27bf2 25561+
392086de
AM
25562+ err = -ENOENT;
25563+ dmsg = !!(args->mvdown.flags & AUFS_MVDOWN_DMSG);
25564+ args->parent = dget_parent(dentry);
5527c038 25565+ args->dir = d_inode(args->parent);
febd17d6 25566+ inode_lock_nested(args->dir, I_MUTEX_PARENT);
392086de
AM
25567+ dput(args->parent);
25568+ if (unlikely(args->parent != dentry->d_parent)) {
25569+ AU_MVD_PR(dmsg, "parent dir is moved\n");
c2b27bf2
AM
25570+ goto out_dir;
25571+ }
25572+
febd17d6 25573+ inode_lock_nested(inode, I_MUTEX_CHILD);
b95c5147 25574+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_NOPLMW);
c2b27bf2
AM
25575+ if (unlikely(err))
25576+ goto out_inode;
25577+
392086de
AM
25578+ di_write_lock_parent(args->parent);
25579+ err = au_mvd_args(dmsg, args);
c2b27bf2
AM
25580+ if (unlikely(err))
25581+ goto out_parent;
25582+
392086de 25583+ err = au_do_mvdown(dmsg, args);
c2b27bf2
AM
25584+ if (unlikely(err))
25585+ goto out_parent;
c2b27bf2 25586+
392086de 25587+ au_cpup_attr_timesizes(args->dir);
79b8bda9
AM
25588+ au_cpup_attr_timesizes(inode);
25589+ if (!(args->mvdown.flags & AUFS_MVDOWN_KUPPER))
25590+ au_cpup_igen(inode, au_h_iptr(inode, args->mvd_bdst));
c2b27bf2
AM
25591+ /* au_digen_dec(dentry); */
25592+
25593+out_parent:
392086de 25594+ di_write_unlock(args->parent);
c2b27bf2
AM
25595+ aufs_read_unlock(dentry, AuLock_DW);
25596+out_inode:
febd17d6 25597+ inode_unlock(inode);
c2b27bf2 25598+out_dir:
febd17d6 25599+ inode_unlock(args->dir);
392086de
AM
25600+out_free:
25601+ e = copy_to_user(uarg, &args->mvdown, sizeof(args->mvdown));
25602+ if (unlikely(e))
25603+ err = -EFAULT;
9f237c51 25604+ au_kfree_rcu(args);
c2b27bf2
AM
25605+out:
25606+ AuTraceErr(err);
25607+ return err;
25608+}
25609diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
eca34b5c 25610--- /usr/share/empty/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 25611+++ linux/fs/aufs/opts.c 2021-05-02 20:15:14.676670793 +0200
eca34b5c 25612@@ -0,0 +1,1880 @@
cd7a4cd9 25613+// SPDX-License-Identifier: GPL-2.0
1facf9fc 25614+/*
d58c55f2 25615+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 25616+ *
25617+ * This program, aufs is free software; you can redistribute it and/or modify
25618+ * it under the terms of the GNU General Public License as published by
25619+ * the Free Software Foundation; either version 2 of the License, or
25620+ * (at your option) any later version.
dece6358
AM
25621+ *
25622+ * This program is distributed in the hope that it will be useful,
25623+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25624+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25625+ * GNU General Public License for more details.
25626+ *
25627+ * You should have received a copy of the GNU General Public License
523b37e3 25628+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 25629+ */
25630+
25631+/*
25632+ * mount options/flags
25633+ */
25634+
dece6358 25635+#include <linux/namei.h>
1facf9fc 25636+#include <linux/types.h> /* a distribution requires */
25637+#include <linux/parser.h>
25638+#include "aufs.h"
25639+
25640+/* ---------------------------------------------------------------------- */
25641+
25642+enum {
25643+ Opt_br,
7e9cd9fe
AM
25644+ Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend,
25645+ Opt_idel, Opt_imod,
25646+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash,
dece6358 25647+ Opt_rdblk_def, Opt_rdhash_def,
7e9cd9fe 25648+ Opt_xino, Opt_noxino,
1facf9fc 25649+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
25650+ Opt_trunc_xino_path, Opt_itrunc_xino,
25651+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 25652+ Opt_shwh, Opt_noshwh,
1facf9fc 25653+ Opt_plink, Opt_noplink, Opt_list_plink,
25654+ Opt_udba,
4a4d8108 25655+ Opt_dio, Opt_nodio,
1facf9fc 25656+ Opt_diropq_a, Opt_diropq_w,
25657+ Opt_warn_perm, Opt_nowarn_perm,
25658+ Opt_wbr_copyup, Opt_wbr_create,
076b876e 25659+ Opt_fhsm_sec,
1facf9fc 25660+ Opt_verbose, Opt_noverbose,
25661+ Opt_sum, Opt_nosum, Opt_wsum,
076b876e 25662+ Opt_dirperm1, Opt_nodirperm1,
8b6a4947 25663+ Opt_dirren, Opt_nodirren,
c1595e42 25664+ Opt_acl, Opt_noacl,
1facf9fc 25665+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
25666+};
25667+
25668+static match_table_t options = {
25669+ {Opt_br, "br=%s"},
25670+ {Opt_br, "br:%s"},
25671+
25672+ {Opt_add, "add=%d:%s"},
25673+ {Opt_add, "add:%d:%s"},
25674+ {Opt_add, "ins=%d:%s"},
25675+ {Opt_add, "ins:%d:%s"},
25676+ {Opt_append, "append=%s"},
25677+ {Opt_append, "append:%s"},
25678+ {Opt_prepend, "prepend=%s"},
25679+ {Opt_prepend, "prepend:%s"},
25680+
25681+ {Opt_del, "del=%s"},
25682+ {Opt_del, "del:%s"},
25683+ /* {Opt_idel, "idel:%d"}, */
25684+ {Opt_mod, "mod=%s"},
25685+ {Opt_mod, "mod:%s"},
25686+ /* {Opt_imod, "imod:%d:%s"}, */
25687+
25688+ {Opt_dirwh, "dirwh=%d"},
25689+
25690+ {Opt_xino, "xino=%s"},
25691+ {Opt_noxino, "noxino"},
25692+ {Opt_trunc_xino, "trunc_xino"},
25693+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
25694+ {Opt_notrunc_xino, "notrunc_xino"},
25695+ {Opt_trunc_xino_path, "trunc_xino=%s"},
25696+ {Opt_itrunc_xino, "itrunc_xino=%d"},
25697+ /* {Opt_zxino, "zxino=%s"}, */
25698+ {Opt_trunc_xib, "trunc_xib"},
25699+ {Opt_notrunc_xib, "notrunc_xib"},
25700+
e49829fe 25701+#ifdef CONFIG_PROC_FS
1facf9fc 25702+ {Opt_plink, "plink"},
e49829fe
JR
25703+#else
25704+ {Opt_ignore_silent, "plink"},
25705+#endif
25706+
1facf9fc 25707+ {Opt_noplink, "noplink"},
e49829fe 25708+
1facf9fc 25709+#ifdef CONFIG_AUFS_DEBUG
25710+ {Opt_list_plink, "list_plink"},
25711+#endif
25712+
25713+ {Opt_udba, "udba=%s"},
25714+
4a4d8108
AM
25715+ {Opt_dio, "dio"},
25716+ {Opt_nodio, "nodio"},
25717+
8b6a4947
AM
25718+#ifdef CONFIG_AUFS_DIRREN
25719+ {Opt_dirren, "dirren"},
25720+ {Opt_nodirren, "nodirren"},
25721+#else
25722+ {Opt_ignore, "dirren"},
25723+ {Opt_ignore_silent, "nodirren"},
25724+#endif
25725+
076b876e
AM
25726+#ifdef CONFIG_AUFS_FHSM
25727+ {Opt_fhsm_sec, "fhsm_sec=%d"},
25728+#else
8b6a4947 25729+ {Opt_ignore, "fhsm_sec=%d"},
076b876e
AM
25730+#endif
25731+
1facf9fc 25732+ {Opt_diropq_a, "diropq=always"},
25733+ {Opt_diropq_a, "diropq=a"},
25734+ {Opt_diropq_w, "diropq=whiteouted"},
25735+ {Opt_diropq_w, "diropq=w"},
25736+
25737+ {Opt_warn_perm, "warn_perm"},
25738+ {Opt_nowarn_perm, "nowarn_perm"},
25739+
25740+ /* keep them temporary */
1facf9fc 25741+ {Opt_ignore_silent, "nodlgt"},
8b6a4947 25742+ {Opt_ignore, "clean_plink"},
1facf9fc 25743+
dece6358
AM
25744+#ifdef CONFIG_AUFS_SHWH
25745+ {Opt_shwh, "shwh"},
25746+#endif
25747+ {Opt_noshwh, "noshwh"},
25748+
076b876e
AM
25749+ {Opt_dirperm1, "dirperm1"},
25750+ {Opt_nodirperm1, "nodirperm1"},
25751+
1facf9fc 25752+ {Opt_verbose, "verbose"},
25753+ {Opt_verbose, "v"},
25754+ {Opt_noverbose, "noverbose"},
25755+ {Opt_noverbose, "quiet"},
25756+ {Opt_noverbose, "q"},
25757+ {Opt_noverbose, "silent"},
25758+
25759+ {Opt_sum, "sum"},
25760+ {Opt_nosum, "nosum"},
25761+ {Opt_wsum, "wsum"},
25762+
25763+ {Opt_rdcache, "rdcache=%d"},
25764+ {Opt_rdblk, "rdblk=%d"},
dece6358 25765+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 25766+ {Opt_rdhash, "rdhash=%d"},
dece6358 25767+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 25768+
25769+ {Opt_wbr_create, "create=%s"},
25770+ {Opt_wbr_create, "create_policy=%s"},
25771+ {Opt_wbr_copyup, "cpup=%s"},
25772+ {Opt_wbr_copyup, "copyup=%s"},
25773+ {Opt_wbr_copyup, "copyup_policy=%s"},
25774+
c1595e42
JR
25775+ /* generic VFS flag */
25776+#ifdef CONFIG_FS_POSIX_ACL
25777+ {Opt_acl, "acl"},
25778+ {Opt_noacl, "noacl"},
25779+#else
8b6a4947 25780+ {Opt_ignore, "acl"},
c1595e42
JR
25781+ {Opt_ignore_silent, "noacl"},
25782+#endif
25783+
1facf9fc 25784+ /* internal use for the scripts */
25785+ {Opt_ignore_silent, "si=%s"},
25786+
25787+ {Opt_br, "dirs=%s"},
25788+ {Opt_ignore, "debug=%d"},
25789+ {Opt_ignore, "delete=whiteout"},
25790+ {Opt_ignore, "delete=all"},
25791+ {Opt_ignore, "imap=%s"},
25792+
1308ab2a 25793+ /* temporary workaround, due to old mount(8)? */
25794+ {Opt_ignore_silent, "relatime"},
25795+
1facf9fc 25796+ {Opt_err, NULL}
25797+};
25798+
25799+/* ---------------------------------------------------------------------- */
25800+
076b876e 25801+static const char *au_parser_pattern(int val, match_table_t tbl)
1facf9fc 25802+{
076b876e
AM
25803+ struct match_token *p;
25804+
25805+ p = tbl;
25806+ while (p->pattern) {
25807+ if (p->token == val)
25808+ return p->pattern;
25809+ p++;
1facf9fc 25810+ }
25811+ BUG();
25812+ return "??";
25813+}
25814+
076b876e
AM
25815+static const char *au_optstr(int *val, match_table_t tbl)
25816+{
25817+ struct match_token *p;
25818+ int v;
25819+
25820+ v = *val;
2000de60
JR
25821+ if (!v)
25822+ goto out;
076b876e 25823+ p = tbl;
2000de60
JR
25824+ while (p->pattern) {
25825+ if (p->token
25826+ && (v & p->token) == p->token) {
076b876e
AM
25827+ *val &= ~p->token;
25828+ return p->pattern;
25829+ }
25830+ p++;
25831+ }
2000de60
JR
25832+
25833+out:
076b876e
AM
25834+ return NULL;
25835+}
25836+
1facf9fc 25837+/* ---------------------------------------------------------------------- */
25838+
1e00d052 25839+static match_table_t brperm = {
1facf9fc 25840+ {AuBrPerm_RO, AUFS_BRPERM_RO},
25841+ {AuBrPerm_RR, AUFS_BRPERM_RR},
25842+ {AuBrPerm_RW, AUFS_BRPERM_RW},
1e00d052
AM
25843+ {0, NULL}
25844+};
1facf9fc 25845+
86dc4139 25846+static match_table_t brattr = {
076b876e
AM
25847+ /* general */
25848+ {AuBrAttr_COO_REG, AUFS_BRATTR_COO_REG},
25849+ {AuBrAttr_COO_ALL, AUFS_BRATTR_COO_ALL},
c1595e42 25850+ /* 'unpin' attrib is meaningless since linux-3.18-rc1 */
86dc4139 25851+ {AuBrAttr_UNPIN, AUFS_BRATTR_UNPIN},
2000de60 25852+#ifdef CONFIG_AUFS_FHSM
076b876e 25853+ {AuBrAttr_FHSM, AUFS_BRATTR_FHSM},
2000de60
JR
25854+#endif
25855+#ifdef CONFIG_AUFS_XATTR
c1595e42
JR
25856+ {AuBrAttr_ICEX, AUFS_BRATTR_ICEX},
25857+ {AuBrAttr_ICEX_SEC, AUFS_BRATTR_ICEX_SEC},
25858+ {AuBrAttr_ICEX_SYS, AUFS_BRATTR_ICEX_SYS},
25859+ {AuBrAttr_ICEX_TR, AUFS_BRATTR_ICEX_TR},
25860+ {AuBrAttr_ICEX_USR, AUFS_BRATTR_ICEX_USR},
25861+ {AuBrAttr_ICEX_OTH, AUFS_BRATTR_ICEX_OTH},
2000de60 25862+#endif
076b876e
AM
25863+
25864+ /* ro/rr branch */
1e00d052 25865+ {AuBrRAttr_WH, AUFS_BRRATTR_WH},
076b876e
AM
25866+
25867+ /* rw branch */
25868+ {AuBrWAttr_MOO, AUFS_BRWATTR_MOO},
1e00d052 25869+ {AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH},
076b876e 25870+
1e00d052 25871+ {0, NULL}
1facf9fc 25872+};
25873+
1e00d052
AM
25874+static int br_attr_val(char *str, match_table_t table, substring_t args[])
25875+{
25876+ int attr, v;
25877+ char *p;
25878+
25879+ attr = 0;
25880+ do {
25881+ p = strchr(str, '+');
25882+ if (p)
25883+ *p = 0;
25884+ v = match_token(str, table, args);
076b876e
AM
25885+ if (v) {
25886+ if (v & AuBrAttr_CMOO_Mask)
25887+ attr &= ~AuBrAttr_CMOO_Mask;
1e00d052 25888+ attr |= v;
076b876e 25889+ } else {
1e00d052
AM
25890+ if (p)
25891+ *p = '+';
0c3ec466 25892+ pr_warn("ignored branch attribute %s\n", str);
1e00d052
AM
25893+ break;
25894+ }
25895+ if (p)
25896+ str = p + 1;
25897+ } while (p);
25898+
25899+ return attr;
25900+}
25901+
076b876e
AM
25902+static int au_do_optstr_br_attr(au_br_perm_str_t *str, int perm)
25903+{
25904+ int sz;
25905+ const char *p;
25906+ char *q;
25907+
076b876e
AM
25908+ q = str->a;
25909+ *q = 0;
25910+ p = au_optstr(&perm, brattr);
25911+ if (p) {
25912+ sz = strlen(p);
25913+ memcpy(q, p, sz + 1);
25914+ q += sz;
25915+ } else
25916+ goto out;
25917+
25918+ do {
25919+ p = au_optstr(&perm, brattr);
25920+ if (p) {
25921+ *q++ = '+';
25922+ sz = strlen(p);
25923+ memcpy(q, p, sz + 1);
25924+ q += sz;
25925+ }
25926+ } while (p);
25927+
25928+out:
c1595e42 25929+ return q - str->a;
076b876e
AM
25930+}
25931+
4a4d8108 25932+static int noinline_for_stack br_perm_val(char *perm)
1facf9fc 25933+{
076b876e
AM
25934+ int val, bad, sz;
25935+ char *p;
1facf9fc 25936+ substring_t args[MAX_OPT_ARGS];
076b876e 25937+ au_br_perm_str_t attr;
1facf9fc 25938+
1e00d052
AM
25939+ p = strchr(perm, '+');
25940+ if (p)
25941+ *p = 0;
25942+ val = match_token(perm, brperm, args);
25943+ if (!val) {
25944+ if (p)
25945+ *p = '+';
0c3ec466 25946+ pr_warn("ignored branch permission %s\n", perm);
1e00d052
AM
25947+ val = AuBrPerm_RO;
25948+ goto out;
25949+ }
25950+ if (!p)
25951+ goto out;
25952+
076b876e
AM
25953+ val |= br_attr_val(p + 1, brattr, args);
25954+
25955+ bad = 0;
86dc4139 25956+ switch (val & AuBrPerm_Mask) {
1e00d052
AM
25957+ case AuBrPerm_RO:
25958+ case AuBrPerm_RR:
076b876e
AM
25959+ bad = val & AuBrWAttr_Mask;
25960+ val &= ~AuBrWAttr_Mask;
1e00d052
AM
25961+ break;
25962+ case AuBrPerm_RW:
076b876e
AM
25963+ bad = val & AuBrRAttr_Mask;
25964+ val &= ~AuBrRAttr_Mask;
1e00d052
AM
25965+ break;
25966+ }
c1595e42
JR
25967+
25968+ /*
25969+ * 'unpin' attrib becomes meaningless since linux-3.18-rc1, but aufs
25970+ * does not treat it as an error, just warning.
25971+ * this is a tiny guard for the user operation.
25972+ */
25973+ if (val & AuBrAttr_UNPIN) {
25974+ bad |= AuBrAttr_UNPIN;
25975+ val &= ~AuBrAttr_UNPIN;
25976+ }
25977+
076b876e
AM
25978+ if (unlikely(bad)) {
25979+ sz = au_do_optstr_br_attr(&attr, bad);
25980+ AuDebugOn(!sz);
25981+ pr_warn("ignored branch attribute %s\n", attr.a);
25982+ }
1e00d052
AM
25983+
25984+out:
1facf9fc 25985+ return val;
25986+}
25987+
076b876e 25988+void au_optstr_br_perm(au_br_perm_str_t *str, int perm)
1facf9fc 25989+{
076b876e
AM
25990+ au_br_perm_str_t attr;
25991+ const char *p;
25992+ char *q;
1e00d052
AM
25993+ int sz;
25994+
076b876e
AM
25995+ q = str->a;
25996+ p = au_optstr(&perm, brperm);
25997+ AuDebugOn(!p || !*p);
25998+ sz = strlen(p);
25999+ memcpy(q, p, sz + 1);
26000+ q += sz;
1e00d052 26001+
076b876e
AM
26002+ sz = au_do_optstr_br_attr(&attr, perm);
26003+ if (sz) {
26004+ *q++ = '+';
26005+ memcpy(q, attr.a, sz + 1);
1e00d052
AM
26006+ }
26007+
076b876e 26008+ AuDebugOn(strlen(str->a) >= sizeof(str->a));
1facf9fc 26009+}
26010+
26011+/* ---------------------------------------------------------------------- */
26012+
26013+static match_table_t udbalevel = {
26014+ {AuOpt_UDBA_REVAL, "reval"},
26015+ {AuOpt_UDBA_NONE, "none"},
4a4d8108
AM
26016+#ifdef CONFIG_AUFS_HNOTIFY
26017+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
26018+#ifdef CONFIG_AUFS_HFSNOTIFY
26019+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
4a4d8108 26020+#endif
1facf9fc 26021+#endif
26022+ {-1, NULL}
26023+};
26024+
4a4d8108 26025+static int noinline_for_stack udba_val(char *str)
1facf9fc 26026+{
26027+ substring_t args[MAX_OPT_ARGS];
26028+
7f207e10 26029+ return match_token(str, udbalevel, args);
1facf9fc 26030+}
26031+
26032+const char *au_optstr_udba(int udba)
26033+{
076b876e 26034+ return au_parser_pattern(udba, udbalevel);
1facf9fc 26035+}
26036+
26037+/* ---------------------------------------------------------------------- */
26038+
26039+static match_table_t au_wbr_create_policy = {
26040+ {AuWbrCreate_TDP, "tdp"},
26041+ {AuWbrCreate_TDP, "top-down-parent"},
26042+ {AuWbrCreate_RR, "rr"},
26043+ {AuWbrCreate_RR, "round-robin"},
26044+ {AuWbrCreate_MFS, "mfs"},
26045+ {AuWbrCreate_MFS, "most-free-space"},
26046+ {AuWbrCreate_MFSV, "mfs:%d"},
26047+ {AuWbrCreate_MFSV, "most-free-space:%d"},
26048+
f2c43d5f
AM
26049+ /* top-down regardless the parent, and then mfs */
26050+ {AuWbrCreate_TDMFS, "tdmfs:%d"},
26051+ {AuWbrCreate_TDMFSV, "tdmfs:%d:%d"},
26052+
1facf9fc 26053+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
26054+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
26055+ {AuWbrCreate_PMFS, "pmfs"},
26056+ {AuWbrCreate_PMFSV, "pmfs:%d"},
392086de
AM
26057+ {AuWbrCreate_PMFSRR, "pmfsrr:%d"},
26058+ {AuWbrCreate_PMFSRRV, "pmfsrr:%d:%d"},
1facf9fc 26059+
26060+ {-1, NULL}
26061+};
26062+
1facf9fc 26063+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
26064+ struct au_opt_wbr_create *create)
26065+{
26066+ int err;
26067+ unsigned long long ull;
26068+
26069+ err = 0;
a2654f78 26070+ if (!match_u64(arg, &ull))
1facf9fc 26071+ create->mfsrr_watermark = ull;
26072+ else {
4a4d8108 26073+ pr_err("bad integer in %s\n", str);
1facf9fc 26074+ err = -EINVAL;
26075+ }
26076+
26077+ return err;
26078+}
26079+
26080+static int au_wbr_mfs_sec(substring_t *arg, char *str,
26081+ struct au_opt_wbr_create *create)
26082+{
26083+ int n, err;
26084+
26085+ err = 0;
027c5e7a 26086+ if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC)
1facf9fc 26087+ create->mfs_second = n;
26088+ else {
4a4d8108 26089+ pr_err("bad integer in %s\n", str);
1facf9fc 26090+ err = -EINVAL;
26091+ }
26092+
26093+ return err;
26094+}
26095+
4a4d8108
AM
26096+static int noinline_for_stack
26097+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
1facf9fc 26098+{
26099+ int err, e;
26100+ substring_t args[MAX_OPT_ARGS];
26101+
26102+ err = match_token(str, au_wbr_create_policy, args);
26103+ create->wbr_create = err;
26104+ switch (err) {
26105+ case AuWbrCreate_MFSRRV:
f2c43d5f 26106+ case AuWbrCreate_TDMFSV:
392086de 26107+ case AuWbrCreate_PMFSRRV:
1facf9fc 26108+ e = au_wbr_mfs_wmark(&args[0], str, create);
26109+ if (!e)
26110+ e = au_wbr_mfs_sec(&args[1], str, create);
26111+ if (unlikely(e))
26112+ err = e;
26113+ break;
26114+ case AuWbrCreate_MFSRR:
f2c43d5f 26115+ case AuWbrCreate_TDMFS:
392086de 26116+ case AuWbrCreate_PMFSRR:
1facf9fc 26117+ e = au_wbr_mfs_wmark(&args[0], str, create);
26118+ if (unlikely(e)) {
26119+ err = e;
26120+ break;
26121+ }
42a736d3 26122+ fallthrough;
1facf9fc 26123+ case AuWbrCreate_MFS:
26124+ case AuWbrCreate_PMFS:
027c5e7a 26125+ create->mfs_second = AUFS_MFS_DEF_SEC;
1facf9fc 26126+ break;
26127+ case AuWbrCreate_MFSV:
26128+ case AuWbrCreate_PMFSV:
26129+ e = au_wbr_mfs_sec(&args[0], str, create);
26130+ if (unlikely(e))
26131+ err = e;
26132+ break;
26133+ }
26134+
26135+ return err;
26136+}
26137+
26138+const char *au_optstr_wbr_create(int wbr_create)
26139+{
076b876e 26140+ return au_parser_pattern(wbr_create, au_wbr_create_policy);
1facf9fc 26141+}
26142+
26143+static match_table_t au_wbr_copyup_policy = {
26144+ {AuWbrCopyup_TDP, "tdp"},
26145+ {AuWbrCopyup_TDP, "top-down-parent"},
26146+ {AuWbrCopyup_BUP, "bup"},
26147+ {AuWbrCopyup_BUP, "bottom-up-parent"},
26148+ {AuWbrCopyup_BU, "bu"},
26149+ {AuWbrCopyup_BU, "bottom-up"},
26150+ {-1, NULL}
26151+};
26152+
4a4d8108 26153+static int noinline_for_stack au_wbr_copyup_val(char *str)
1facf9fc 26154+{
26155+ substring_t args[MAX_OPT_ARGS];
26156+
26157+ return match_token(str, au_wbr_copyup_policy, args);
26158+}
26159+
26160+const char *au_optstr_wbr_copyup(int wbr_copyup)
26161+{
076b876e 26162+ return au_parser_pattern(wbr_copyup, au_wbr_copyup_policy);
1facf9fc 26163+}
26164+
26165+/* ---------------------------------------------------------------------- */
26166+
26167+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
26168+
26169+static void dump_opts(struct au_opts *opts)
26170+{
26171+#ifdef CONFIG_AUFS_DEBUG
26172+ /* reduce stack space */
26173+ union {
26174+ struct au_opt_add *add;
26175+ struct au_opt_del *del;
26176+ struct au_opt_mod *mod;
26177+ struct au_opt_xino *xino;
26178+ struct au_opt_xino_itrunc *xino_itrunc;
26179+ struct au_opt_wbr_create *create;
26180+ } u;
26181+ struct au_opt *opt;
26182+
26183+ opt = opts->opt;
26184+ while (opt->type != Opt_tail) {
26185+ switch (opt->type) {
26186+ case Opt_add:
26187+ u.add = &opt->add;
26188+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
26189+ u.add->bindex, u.add->pathname, u.add->perm,
26190+ u.add->path.dentry);
26191+ break;
26192+ case Opt_del:
26193+ case Opt_idel:
26194+ u.del = &opt->del;
26195+ AuDbg("del {%s, %p}\n",
26196+ u.del->pathname, u.del->h_path.dentry);
26197+ break;
26198+ case Opt_mod:
26199+ case Opt_imod:
26200+ u.mod = &opt->mod;
26201+ AuDbg("mod {%s, 0x%x, %p}\n",
26202+ u.mod->path, u.mod->perm, u.mod->h_root);
26203+ break;
26204+ case Opt_append:
26205+ u.add = &opt->add;
26206+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
26207+ u.add->bindex, u.add->pathname, u.add->perm,
26208+ u.add->path.dentry);
26209+ break;
26210+ case Opt_prepend:
26211+ u.add = &opt->add;
26212+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
26213+ u.add->bindex, u.add->pathname, u.add->perm,
26214+ u.add->path.dentry);
26215+ break;
26216+ case Opt_dirwh:
26217+ AuDbg("dirwh %d\n", opt->dirwh);
26218+ break;
26219+ case Opt_rdcache:
26220+ AuDbg("rdcache %d\n", opt->rdcache);
26221+ break;
26222+ case Opt_rdblk:
26223+ AuDbg("rdblk %u\n", opt->rdblk);
26224+ break;
dece6358
AM
26225+ case Opt_rdblk_def:
26226+ AuDbg("rdblk_def\n");
26227+ break;
1facf9fc 26228+ case Opt_rdhash:
26229+ AuDbg("rdhash %u\n", opt->rdhash);
26230+ break;
dece6358
AM
26231+ case Opt_rdhash_def:
26232+ AuDbg("rdhash_def\n");
26233+ break;
1facf9fc 26234+ case Opt_xino:
26235+ u.xino = &opt->xino;
523b37e3 26236+ AuDbg("xino {%s %pD}\n", u.xino->path, u.xino->file);
1facf9fc 26237+ break;
26238+ case Opt_trunc_xino:
26239+ AuLabel(trunc_xino);
26240+ break;
26241+ case Opt_notrunc_xino:
26242+ AuLabel(notrunc_xino);
26243+ break;
26244+ case Opt_trunc_xino_path:
26245+ case Opt_itrunc_xino:
26246+ u.xino_itrunc = &opt->xino_itrunc;
26247+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
26248+ break;
1facf9fc 26249+ case Opt_noxino:
26250+ AuLabel(noxino);
26251+ break;
26252+ case Opt_trunc_xib:
26253+ AuLabel(trunc_xib);
26254+ break;
26255+ case Opt_notrunc_xib:
26256+ AuLabel(notrunc_xib);
26257+ break;
dece6358
AM
26258+ case Opt_shwh:
26259+ AuLabel(shwh);
26260+ break;
26261+ case Opt_noshwh:
26262+ AuLabel(noshwh);
26263+ break;
076b876e
AM
26264+ case Opt_dirperm1:
26265+ AuLabel(dirperm1);
26266+ break;
26267+ case Opt_nodirperm1:
26268+ AuLabel(nodirperm1);
26269+ break;
1facf9fc 26270+ case Opt_plink:
26271+ AuLabel(plink);
26272+ break;
26273+ case Opt_noplink:
26274+ AuLabel(noplink);
26275+ break;
26276+ case Opt_list_plink:
26277+ AuLabel(list_plink);
26278+ break;
26279+ case Opt_udba:
26280+ AuDbg("udba %d, %s\n",
26281+ opt->udba, au_optstr_udba(opt->udba));
26282+ break;
4a4d8108
AM
26283+ case Opt_dio:
26284+ AuLabel(dio);
26285+ break;
26286+ case Opt_nodio:
26287+ AuLabel(nodio);
26288+ break;
1facf9fc 26289+ case Opt_diropq_a:
26290+ AuLabel(diropq_a);
26291+ break;
26292+ case Opt_diropq_w:
26293+ AuLabel(diropq_w);
26294+ break;
26295+ case Opt_warn_perm:
26296+ AuLabel(warn_perm);
26297+ break;
26298+ case Opt_nowarn_perm:
26299+ AuLabel(nowarn_perm);
26300+ break;
1facf9fc 26301+ case Opt_verbose:
26302+ AuLabel(verbose);
26303+ break;
26304+ case Opt_noverbose:
26305+ AuLabel(noverbose);
26306+ break;
26307+ case Opt_sum:
26308+ AuLabel(sum);
26309+ break;
26310+ case Opt_nosum:
26311+ AuLabel(nosum);
26312+ break;
26313+ case Opt_wsum:
26314+ AuLabel(wsum);
26315+ break;
26316+ case Opt_wbr_create:
26317+ u.create = &opt->wbr_create;
26318+ AuDbg("create %d, %s\n", u.create->wbr_create,
26319+ au_optstr_wbr_create(u.create->wbr_create));
26320+ switch (u.create->wbr_create) {
26321+ case AuWbrCreate_MFSV:
26322+ case AuWbrCreate_PMFSV:
26323+ AuDbg("%d sec\n", u.create->mfs_second);
26324+ break;
26325+ case AuWbrCreate_MFSRR:
f2c43d5f 26326+ case AuWbrCreate_TDMFS:
1facf9fc 26327+ AuDbg("%llu watermark\n",
26328+ u.create->mfsrr_watermark);
26329+ break;
26330+ case AuWbrCreate_MFSRRV:
f2c43d5f 26331+ case AuWbrCreate_TDMFSV:
392086de 26332+ case AuWbrCreate_PMFSRRV:
1facf9fc 26333+ AuDbg("%llu watermark, %d sec\n",
26334+ u.create->mfsrr_watermark,
26335+ u.create->mfs_second);
26336+ break;
26337+ }
26338+ break;
26339+ case Opt_wbr_copyup:
26340+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
26341+ au_optstr_wbr_copyup(opt->wbr_copyup));
26342+ break;
076b876e
AM
26343+ case Opt_fhsm_sec:
26344+ AuDbg("fhsm_sec %u\n", opt->fhsm_second);
26345+ break;
8b6a4947
AM
26346+ case Opt_dirren:
26347+ AuLabel(dirren);
26348+ break;
26349+ case Opt_nodirren:
26350+ AuLabel(nodirren);
26351+ break;
c1595e42
JR
26352+ case Opt_acl:
26353+ AuLabel(acl);
26354+ break;
26355+ case Opt_noacl:
26356+ AuLabel(noacl);
26357+ break;
1facf9fc 26358+ default:
26359+ BUG();
26360+ }
26361+ opt++;
26362+ }
26363+#endif
26364+}
26365+
26366+void au_opts_free(struct au_opts *opts)
26367+{
26368+ struct au_opt *opt;
26369+
26370+ opt = opts->opt;
26371+ while (opt->type != Opt_tail) {
26372+ switch (opt->type) {
26373+ case Opt_add:
26374+ case Opt_append:
26375+ case Opt_prepend:
26376+ path_put(&opt->add.path);
26377+ break;
26378+ case Opt_del:
26379+ case Opt_idel:
26380+ path_put(&opt->del.h_path);
26381+ break;
26382+ case Opt_mod:
26383+ case Opt_imod:
26384+ dput(opt->mod.h_root);
26385+ break;
26386+ case Opt_xino:
26387+ fput(opt->xino.file);
26388+ break;
26389+ }
26390+ opt++;
26391+ }
26392+}
26393+
26394+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
26395+ aufs_bindex_t bindex)
26396+{
26397+ int err;
26398+ struct au_opt_add *add = &opt->add;
26399+ char *p;
26400+
26401+ add->bindex = bindex;
1e00d052 26402+ add->perm = AuBrPerm_RO;
1facf9fc 26403+ add->pathname = opt_str;
26404+ p = strchr(opt_str, '=');
26405+ if (p) {
26406+ *p++ = 0;
26407+ if (*p)
26408+ add->perm = br_perm_val(p);
26409+ }
26410+
26411+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
26412+ if (!err) {
26413+ if (!p) {
26414+ add->perm = AuBrPerm_RO;
26415+ if (au_test_fs_rr(add->path.dentry->d_sb))
26416+ add->perm = AuBrPerm_RR;
2121bcd9 26417+ else if (!bindex && !(sb_flags & SB_RDONLY))
1facf9fc 26418+ add->perm = AuBrPerm_RW;
26419+ }
26420+ opt->type = Opt_add;
26421+ goto out;
26422+ }
4a4d8108 26423+ pr_err("lookup failed %s (%d)\n", add->pathname, err);
1facf9fc 26424+ err = -EINVAL;
26425+
4f0767ce 26426+out:
1facf9fc 26427+ return err;
26428+}
26429+
26430+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
26431+{
26432+ int err;
26433+
26434+ del->pathname = args[0].from;
26435+ AuDbg("del path %s\n", del->pathname);
26436+
26437+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
26438+ if (unlikely(err))
4a4d8108 26439+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
1facf9fc 26440+
26441+ return err;
26442+}
26443+
26444+#if 0 /* reserved for future use */
26445+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
26446+ struct au_opt_del *del, substring_t args[])
26447+{
26448+ int err;
26449+ struct dentry *root;
26450+
26451+ err = -EINVAL;
26452+ root = sb->s_root;
26453+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d 26454+ if (bindex < 0 || au_sbbot(sb) < bindex) {
4a4d8108 26455+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 26456+ goto out;
26457+ }
26458+
26459+ err = 0;
26460+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
26461+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
26462+
4f0767ce 26463+out:
1facf9fc 26464+ aufs_read_unlock(root, !AuLock_IR);
26465+ return err;
26466+}
26467+#endif
26468+
4a4d8108
AM
26469+static int noinline_for_stack
26470+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
1facf9fc 26471+{
26472+ int err;
26473+ struct path path;
26474+ char *p;
26475+
26476+ err = -EINVAL;
26477+ mod->path = args[0].from;
26478+ p = strchr(mod->path, '=');
26479+ if (unlikely(!p)) {
acd2b654 26480+ pr_err("no permission %s\n", args[0].from);
1facf9fc 26481+ goto out;
26482+ }
26483+
26484+ *p++ = 0;
26485+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
26486+ if (unlikely(err)) {
4a4d8108 26487+ pr_err("lookup failed %s (%d)\n", mod->path, err);
1facf9fc 26488+ goto out;
26489+ }
26490+
26491+ mod->perm = br_perm_val(p);
26492+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
26493+ mod->h_root = dget(path.dentry);
26494+ path_put(&path);
26495+
4f0767ce 26496+out:
1facf9fc 26497+ return err;
26498+}
26499+
26500+#if 0 /* reserved for future use */
26501+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
26502+ struct au_opt_mod *mod, substring_t args[])
26503+{
26504+ int err;
26505+ struct dentry *root;
26506+
26507+ err = -EINVAL;
26508+ root = sb->s_root;
26509+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d 26510+ if (bindex < 0 || au_sbbot(sb) < bindex) {
4a4d8108 26511+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 26512+ goto out;
26513+ }
26514+
26515+ err = 0;
26516+ mod->perm = br_perm_val(args[1].from);
26517+ AuDbg("mod path %s, perm 0x%x, %s\n",
26518+ mod->path, mod->perm, args[1].from);
26519+ mod->h_root = dget(au_h_dptr(root, bindex));
26520+
4f0767ce 26521+out:
1facf9fc 26522+ aufs_read_unlock(root, !AuLock_IR);
26523+ return err;
26524+}
26525+#endif
26526+
26527+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
26528+ substring_t args[])
26529+{
26530+ int err;
26531+ struct file *file;
26532+
83b672a5 26533+ file = au_xino_create(sb, args[0].from, /*silent*/0, /*wbrtop*/0);
1facf9fc 26534+ err = PTR_ERR(file);
26535+ if (IS_ERR(file))
26536+ goto out;
26537+
26538+ err = -EINVAL;
2000de60 26539+ if (unlikely(file->f_path.dentry->d_sb == sb)) {
1facf9fc 26540+ fput(file);
4a4d8108 26541+ pr_err("%s must be outside\n", args[0].from);
1facf9fc 26542+ goto out;
26543+ }
26544+
26545+ err = 0;
26546+ xino->file = file;
26547+ xino->path = args[0].from;
26548+
4f0767ce 26549+out:
1facf9fc 26550+ return err;
26551+}
26552+
4a4d8108
AM
26553+static int noinline_for_stack
26554+au_opts_parse_xino_itrunc_path(struct super_block *sb,
26555+ struct au_opt_xino_itrunc *xino_itrunc,
26556+ substring_t args[])
1facf9fc 26557+{
26558+ int err;
5afbbe0d 26559+ aufs_bindex_t bbot, bindex;
1facf9fc 26560+ struct path path;
26561+ struct dentry *root;
26562+
26563+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
26564+ if (unlikely(err)) {
4a4d8108 26565+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
1facf9fc 26566+ goto out;
26567+ }
26568+
26569+ xino_itrunc->bindex = -1;
26570+ root = sb->s_root;
26571+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d
AM
26572+ bbot = au_sbbot(sb);
26573+ for (bindex = 0; bindex <= bbot; bindex++) {
1facf9fc 26574+ if (au_h_dptr(root, bindex) == path.dentry) {
26575+ xino_itrunc->bindex = bindex;
26576+ break;
26577+ }
26578+ }
26579+ aufs_read_unlock(root, !AuLock_IR);
26580+ path_put(&path);
26581+
26582+ if (unlikely(xino_itrunc->bindex < 0)) {
4a4d8108 26583+ pr_err("no such branch %s\n", args[0].from);
1facf9fc 26584+ err = -EINVAL;
26585+ }
26586+
4f0767ce 26587+out:
1facf9fc 26588+ return err;
26589+}
26590+
26591+/* called without aufs lock */
26592+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
26593+{
26594+ int err, n, token;
26595+ aufs_bindex_t bindex;
26596+ unsigned char skipped;
26597+ struct dentry *root;
26598+ struct au_opt *opt, *opt_tail;
26599+ char *opt_str;
26600+ /* reduce the stack space */
26601+ union {
26602+ struct au_opt_xino_itrunc *xino_itrunc;
26603+ struct au_opt_wbr_create *create;
26604+ } u;
26605+ struct {
26606+ substring_t args[MAX_OPT_ARGS];
26607+ } *a;
26608+
26609+ err = -ENOMEM;
26610+ a = kmalloc(sizeof(*a), GFP_NOFS);
26611+ if (unlikely(!a))
26612+ goto out;
26613+
26614+ root = sb->s_root;
26615+ err = 0;
26616+ bindex = 0;
26617+ opt = opts->opt;
26618+ opt_tail = opt + opts->max_opt - 1;
26619+ opt->type = Opt_tail;
26620+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
26621+ err = -EINVAL;
26622+ skipped = 0;
26623+ token = match_token(opt_str, options, a->args);
26624+ switch (token) {
26625+ case Opt_br:
26626+ err = 0;
26627+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
26628+ && *opt_str) {
26629+ err = opt_add(opt, opt_str, opts->sb_flags,
26630+ bindex++);
26631+ if (unlikely(!err && ++opt > opt_tail)) {
26632+ err = -E2BIG;
26633+ break;
26634+ }
26635+ opt->type = Opt_tail;
26636+ skipped = 1;
26637+ }
26638+ break;
26639+ case Opt_add:
26640+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 26641+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26642+ break;
26643+ }
26644+ bindex = n;
26645+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
26646+ bindex);
26647+ if (!err)
26648+ opt->type = token;
26649+ break;
26650+ case Opt_append:
26651+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
26652+ /*dummy bindex*/1);
26653+ if (!err)
26654+ opt->type = token;
26655+ break;
26656+ case Opt_prepend:
26657+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
26658+ /*bindex*/0);
26659+ if (!err)
26660+ opt->type = token;
26661+ break;
26662+ case Opt_del:
26663+ err = au_opts_parse_del(&opt->del, a->args);
26664+ if (!err)
26665+ opt->type = token;
26666+ break;
26667+#if 0 /* reserved for future use */
26668+ case Opt_idel:
26669+ del->pathname = "(indexed)";
26670+ if (unlikely(match_int(&args[0], &n))) {
4a4d8108 26671+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26672+ break;
26673+ }
26674+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
26675+ if (!err)
26676+ opt->type = token;
26677+ break;
26678+#endif
26679+ case Opt_mod:
26680+ err = au_opts_parse_mod(&opt->mod, a->args);
26681+ if (!err)
26682+ opt->type = token;
26683+ break;
26684+#ifdef IMOD /* reserved for future use */
26685+ case Opt_imod:
26686+ u.mod->path = "(indexed)";
26687+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 26688+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26689+ break;
26690+ }
26691+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
26692+ if (!err)
26693+ opt->type = token;
26694+ break;
26695+#endif
26696+ case Opt_xino:
26697+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
26698+ if (!err)
26699+ opt->type = token;
26700+ break;
26701+
26702+ case Opt_trunc_xino_path:
26703+ err = au_opts_parse_xino_itrunc_path
26704+ (sb, &opt->xino_itrunc, a->args);
26705+ if (!err)
26706+ opt->type = token;
26707+ break;
26708+
26709+ case Opt_itrunc_xino:
26710+ u.xino_itrunc = &opt->xino_itrunc;
26711+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 26712+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26713+ break;
26714+ }
26715+ u.xino_itrunc->bindex = n;
26716+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d 26717+ if (n < 0 || au_sbbot(sb) < n) {
4a4d8108 26718+ pr_err("out of bounds, %d\n", n);
1facf9fc 26719+ aufs_read_unlock(root, !AuLock_IR);
26720+ break;
26721+ }
26722+ aufs_read_unlock(root, !AuLock_IR);
26723+ err = 0;
26724+ opt->type = token;
26725+ break;
26726+
26727+ case Opt_dirwh:
26728+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
26729+ break;
26730+ err = 0;
26731+ opt->type = token;
26732+ break;
26733+
26734+ case Opt_rdcache:
027c5e7a
AM
26735+ if (unlikely(match_int(&a->args[0], &n))) {
26736+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26737+ break;
027c5e7a
AM
26738+ }
26739+ if (unlikely(n > AUFS_RDCACHE_MAX)) {
26740+ pr_err("rdcache must be smaller than %d\n",
26741+ AUFS_RDCACHE_MAX);
26742+ break;
26743+ }
26744+ opt->rdcache = n;
1facf9fc 26745+ err = 0;
26746+ opt->type = token;
26747+ break;
26748+ case Opt_rdblk:
26749+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 26750+ || n < 0
1facf9fc 26751+ || n > KMALLOC_MAX_SIZE)) {
4a4d8108 26752+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26753+ break;
26754+ }
1308ab2a 26755+ if (unlikely(n && n < NAME_MAX)) {
4a4d8108
AM
26756+ pr_err("rdblk must be larger than %d\n",
26757+ NAME_MAX);
1facf9fc 26758+ break;
26759+ }
26760+ opt->rdblk = n;
26761+ err = 0;
26762+ opt->type = token;
26763+ break;
26764+ case Opt_rdhash:
26765+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 26766+ || n < 0
1facf9fc 26767+ || n * sizeof(struct hlist_head)
26768+ > KMALLOC_MAX_SIZE)) {
4a4d8108 26769+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26770+ break;
26771+ }
26772+ opt->rdhash = n;
26773+ err = 0;
26774+ opt->type = token;
26775+ break;
26776+
26777+ case Opt_trunc_xino:
26778+ case Opt_notrunc_xino:
26779+ case Opt_noxino:
26780+ case Opt_trunc_xib:
26781+ case Opt_notrunc_xib:
dece6358
AM
26782+ case Opt_shwh:
26783+ case Opt_noshwh:
076b876e
AM
26784+ case Opt_dirperm1:
26785+ case Opt_nodirperm1:
1facf9fc 26786+ case Opt_plink:
26787+ case Opt_noplink:
26788+ case Opt_list_plink:
4a4d8108
AM
26789+ case Opt_dio:
26790+ case Opt_nodio:
1facf9fc 26791+ case Opt_diropq_a:
26792+ case Opt_diropq_w:
26793+ case Opt_warn_perm:
26794+ case Opt_nowarn_perm:
1facf9fc 26795+ case Opt_verbose:
26796+ case Opt_noverbose:
26797+ case Opt_sum:
26798+ case Opt_nosum:
26799+ case Opt_wsum:
dece6358
AM
26800+ case Opt_rdblk_def:
26801+ case Opt_rdhash_def:
8b6a4947
AM
26802+ case Opt_dirren:
26803+ case Opt_nodirren:
c1595e42
JR
26804+ case Opt_acl:
26805+ case Opt_noacl:
1facf9fc 26806+ err = 0;
26807+ opt->type = token;
26808+ break;
26809+
26810+ case Opt_udba:
26811+ opt->udba = udba_val(a->args[0].from);
26812+ if (opt->udba >= 0) {
26813+ err = 0;
26814+ opt->type = token;
26815+ } else
4a4d8108 26816+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 26817+ break;
26818+
26819+ case Opt_wbr_create:
26820+ u.create = &opt->wbr_create;
26821+ u.create->wbr_create
26822+ = au_wbr_create_val(a->args[0].from, u.create);
26823+ if (u.create->wbr_create >= 0) {
26824+ err = 0;
26825+ opt->type = token;
26826+ } else
4a4d8108 26827+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 26828+ break;
26829+ case Opt_wbr_copyup:
26830+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
26831+ if (opt->wbr_copyup >= 0) {
26832+ err = 0;
26833+ opt->type = token;
26834+ } else
4a4d8108 26835+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 26836+ break;
26837+
076b876e
AM
26838+ case Opt_fhsm_sec:
26839+ if (unlikely(match_int(&a->args[0], &n)
26840+ || n < 0)) {
26841+ pr_err("bad integer in %s\n", opt_str);
26842+ break;
26843+ }
26844+ if (sysaufs_brs) {
26845+ opt->fhsm_second = n;
26846+ opt->type = token;
26847+ } else
26848+ pr_warn("ignored %s\n", opt_str);
26849+ err = 0;
26850+ break;
26851+
1facf9fc 26852+ case Opt_ignore:
0c3ec466 26853+ pr_warn("ignored %s\n", opt_str);
42a736d3 26854+ fallthrough;
1facf9fc 26855+ case Opt_ignore_silent:
26856+ skipped = 1;
26857+ err = 0;
26858+ break;
26859+ case Opt_err:
4a4d8108 26860+ pr_err("unknown option %s\n", opt_str);
1facf9fc 26861+ break;
26862+ }
26863+
26864+ if (!err && !skipped) {
26865+ if (unlikely(++opt > opt_tail)) {
26866+ err = -E2BIG;
26867+ opt--;
26868+ opt->type = Opt_tail;
26869+ break;
26870+ }
26871+ opt->type = Opt_tail;
26872+ }
26873+ }
26874+
9f237c51 26875+ au_kfree_rcu(a);
1facf9fc 26876+ dump_opts(opts);
26877+ if (unlikely(err))
26878+ au_opts_free(opts);
26879+
4f0767ce 26880+out:
1facf9fc 26881+ return err;
26882+}
26883+
26884+static int au_opt_wbr_create(struct super_block *sb,
26885+ struct au_opt_wbr_create *create)
26886+{
26887+ int err;
26888+ struct au_sbinfo *sbinfo;
26889+
dece6358
AM
26890+ SiMustWriteLock(sb);
26891+
1facf9fc 26892+ err = 1; /* handled */
26893+ sbinfo = au_sbi(sb);
26894+ if (sbinfo->si_wbr_create_ops->fin) {
26895+ err = sbinfo->si_wbr_create_ops->fin(sb);
26896+ if (!err)
26897+ err = 1;
26898+ }
26899+
26900+ sbinfo->si_wbr_create = create->wbr_create;
26901+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
26902+ switch (create->wbr_create) {
26903+ case AuWbrCreate_MFSRRV:
26904+ case AuWbrCreate_MFSRR:
f2c43d5f
AM
26905+ case AuWbrCreate_TDMFS:
26906+ case AuWbrCreate_TDMFSV:
392086de
AM
26907+ case AuWbrCreate_PMFSRR:
26908+ case AuWbrCreate_PMFSRRV:
1facf9fc 26909+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
42a736d3 26910+ fallthrough;
1facf9fc 26911+ case AuWbrCreate_MFS:
26912+ case AuWbrCreate_MFSV:
26913+ case AuWbrCreate_PMFS:
26914+ case AuWbrCreate_PMFSV:
e49829fe
JR
26915+ sbinfo->si_wbr_mfs.mfs_expire
26916+ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC);
1facf9fc 26917+ break;
26918+ }
26919+
26920+ if (sbinfo->si_wbr_create_ops->init)
26921+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
26922+
26923+ return err;
26924+}
26925+
26926+/*
26927+ * returns,
26928+ * plus: processed without an error
26929+ * zero: unprocessed
26930+ */
26931+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
26932+ struct au_opts *opts)
26933+{
26934+ int err;
26935+ struct au_sbinfo *sbinfo;
26936+
dece6358
AM
26937+ SiMustWriteLock(sb);
26938+
1facf9fc 26939+ err = 1; /* handled */
26940+ sbinfo = au_sbi(sb);
26941+ switch (opt->type) {
26942+ case Opt_udba:
26943+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
26944+ sbinfo->si_mntflags |= opt->udba;
26945+ opts->given_udba |= opt->udba;
26946+ break;
26947+
26948+ case Opt_plink:
26949+ au_opt_set(sbinfo->si_mntflags, PLINK);
26950+ break;
26951+ case Opt_noplink:
26952+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
e49829fe 26953+ au_plink_put(sb, /*verbose*/1);
1facf9fc 26954+ au_opt_clr(sbinfo->si_mntflags, PLINK);
26955+ break;
26956+ case Opt_list_plink:
26957+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
26958+ au_plink_list(sb);
26959+ break;
26960+
4a4d8108
AM
26961+ case Opt_dio:
26962+ au_opt_set(sbinfo->si_mntflags, DIO);
26963+ au_fset_opts(opts->flags, REFRESH_DYAOP);
26964+ break;
26965+ case Opt_nodio:
26966+ au_opt_clr(sbinfo->si_mntflags, DIO);
26967+ au_fset_opts(opts->flags, REFRESH_DYAOP);
26968+ break;
26969+
076b876e
AM
26970+ case Opt_fhsm_sec:
26971+ au_fhsm_set(sbinfo, opt->fhsm_second);
26972+ break;
26973+
1facf9fc 26974+ case Opt_diropq_a:
26975+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
26976+ break;
26977+ case Opt_diropq_w:
26978+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
26979+ break;
26980+
26981+ case Opt_warn_perm:
26982+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
26983+ break;
26984+ case Opt_nowarn_perm:
26985+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
26986+ break;
26987+
1facf9fc 26988+ case Opt_verbose:
26989+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
26990+ break;
26991+ case Opt_noverbose:
26992+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
26993+ break;
26994+
26995+ case Opt_sum:
26996+ au_opt_set(sbinfo->si_mntflags, SUM);
26997+ break;
26998+ case Opt_wsum:
26999+ au_opt_clr(sbinfo->si_mntflags, SUM);
27000+ au_opt_set(sbinfo->si_mntflags, SUM_W);
eca34b5c 27001+ break;
1facf9fc 27002+ case Opt_nosum:
27003+ au_opt_clr(sbinfo->si_mntflags, SUM);
27004+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
27005+ break;
27006+
27007+ case Opt_wbr_create:
27008+ err = au_opt_wbr_create(sb, &opt->wbr_create);
27009+ break;
27010+ case Opt_wbr_copyup:
27011+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
27012+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
27013+ break;
27014+
27015+ case Opt_dirwh:
27016+ sbinfo->si_dirwh = opt->dirwh;
27017+ break;
27018+
27019+ case Opt_rdcache:
e49829fe
JR
27020+ sbinfo->si_rdcache
27021+ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
1facf9fc 27022+ break;
27023+ case Opt_rdblk:
27024+ sbinfo->si_rdblk = opt->rdblk;
27025+ break;
dece6358
AM
27026+ case Opt_rdblk_def:
27027+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
27028+ break;
1facf9fc 27029+ case Opt_rdhash:
27030+ sbinfo->si_rdhash = opt->rdhash;
27031+ break;
dece6358
AM
27032+ case Opt_rdhash_def:
27033+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
27034+ break;
27035+
27036+ case Opt_shwh:
27037+ au_opt_set(sbinfo->si_mntflags, SHWH);
27038+ break;
27039+ case Opt_noshwh:
27040+ au_opt_clr(sbinfo->si_mntflags, SHWH);
27041+ break;
1facf9fc 27042+
076b876e
AM
27043+ case Opt_dirperm1:
27044+ au_opt_set(sbinfo->si_mntflags, DIRPERM1);
27045+ break;
27046+ case Opt_nodirperm1:
27047+ au_opt_clr(sbinfo->si_mntflags, DIRPERM1);
27048+ break;
27049+
1facf9fc 27050+ case Opt_trunc_xino:
27051+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
27052+ break;
27053+ case Opt_notrunc_xino:
27054+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
27055+ break;
27056+
27057+ case Opt_trunc_xino_path:
27058+ case Opt_itrunc_xino:
acd2b654
AM
27059+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex,
27060+ /*idx_begin*/0);
1facf9fc 27061+ if (!err)
27062+ err = 1;
27063+ break;
27064+
27065+ case Opt_trunc_xib:
27066+ au_fset_opts(opts->flags, TRUNC_XIB);
27067+ break;
27068+ case Opt_notrunc_xib:
27069+ au_fclr_opts(opts->flags, TRUNC_XIB);
27070+ break;
27071+
8b6a4947
AM
27072+ case Opt_dirren:
27073+ err = 1;
27074+ if (!au_opt_test(sbinfo->si_mntflags, DIRREN)) {
27075+ err = au_dr_opt_set(sb);
27076+ if (!err)
27077+ err = 1;
27078+ }
27079+ if (err == 1)
27080+ au_opt_set(sbinfo->si_mntflags, DIRREN);
27081+ break;
27082+ case Opt_nodirren:
27083+ err = 1;
27084+ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) {
27085+ err = au_dr_opt_clr(sb, au_ftest_opts(opts->flags,
27086+ DR_FLUSHED));
27087+ if (!err)
27088+ err = 1;
27089+ }
27090+ if (err == 1)
27091+ au_opt_clr(sbinfo->si_mntflags, DIRREN);
27092+ break;
27093+
c1595e42 27094+ case Opt_acl:
2121bcd9 27095+ sb->s_flags |= SB_POSIXACL;
c1595e42
JR
27096+ break;
27097+ case Opt_noacl:
2121bcd9 27098+ sb->s_flags &= ~SB_POSIXACL;
c1595e42
JR
27099+ break;
27100+
1facf9fc 27101+ default:
27102+ err = 0;
27103+ break;
27104+ }
27105+
27106+ return err;
27107+}
27108+
27109+/*
27110+ * returns tri-state.
27111+ * plus: processed without an error
27112+ * zero: unprocessed
27113+ * minus: error
27114+ */
27115+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
27116+ struct au_opts *opts)
27117+{
27118+ int err, do_refresh;
27119+
27120+ err = 0;
27121+ switch (opt->type) {
27122+ case Opt_append:
5afbbe0d 27123+ opt->add.bindex = au_sbbot(sb) + 1;
1facf9fc 27124+ if (opt->add.bindex < 0)
27125+ opt->add.bindex = 0;
27126+ goto add;
eca34b5c 27127+ /* Always goto add, not fallthrough */
1facf9fc 27128+ case Opt_prepend:
27129+ opt->add.bindex = 0;
42a736d3 27130+ fallthrough;
f6b6e03d 27131+ add: /* indented label */
1facf9fc 27132+ case Opt_add:
27133+ err = au_br_add(sb, &opt->add,
27134+ au_ftest_opts(opts->flags, REMOUNT));
27135+ if (!err) {
27136+ err = 1;
027c5e7a 27137+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 27138+ }
27139+ break;
27140+
27141+ case Opt_del:
27142+ case Opt_idel:
27143+ err = au_br_del(sb, &opt->del,
27144+ au_ftest_opts(opts->flags, REMOUNT));
27145+ if (!err) {
27146+ err = 1;
27147+ au_fset_opts(opts->flags, TRUNC_XIB);
027c5e7a 27148+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 27149+ }
27150+ break;
27151+
27152+ case Opt_mod:
27153+ case Opt_imod:
27154+ err = au_br_mod(sb, &opt->mod,
27155+ au_ftest_opts(opts->flags, REMOUNT),
27156+ &do_refresh);
27157+ if (!err) {
27158+ err = 1;
027c5e7a
AM
27159+ if (do_refresh)
27160+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 27161+ }
27162+ break;
27163+ }
1facf9fc 27164+ return err;
27165+}
27166+
27167+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
27168+ struct au_opt_xino **opt_xino,
27169+ struct au_opts *opts)
27170+{
27171+ int err;
1facf9fc 27172+
27173+ err = 0;
27174+ switch (opt->type) {
27175+ case Opt_xino:
062440b3
AM
27176+ err = au_xino_set(sb, &opt->xino,
27177+ !!au_ftest_opts(opts->flags, REMOUNT));
27178+ if (unlikely(err))
27179+ break;
27180+
27181+ *opt_xino = &opt->xino;
1facf9fc 27182+ break;
27183+
27184+ case Opt_noxino:
27185+ au_xino_clr(sb);
1facf9fc 27186+ *opt_xino = (void *)-1;
27187+ break;
27188+ }
27189+
27190+ return err;
27191+}
27192+
27193+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
27194+ unsigned int pending)
27195+{
076b876e 27196+ int err, fhsm;
5afbbe0d 27197+ aufs_bindex_t bindex, bbot;
79b8bda9 27198+ unsigned char do_plink, skip, do_free, can_no_dreval;
1facf9fc 27199+ struct au_branch *br;
27200+ struct au_wbr *wbr;
79b8bda9 27201+ struct dentry *root, *dentry;
1facf9fc 27202+ struct inode *dir, *h_dir;
27203+ struct au_sbinfo *sbinfo;
27204+ struct au_hinode *hdir;
27205+
dece6358
AM
27206+ SiMustAnyLock(sb);
27207+
1facf9fc 27208+ sbinfo = au_sbi(sb);
27209+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
27210+
2121bcd9 27211+ if (!(sb_flags & SB_RDONLY)) {
dece6358 27212+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
0c3ec466 27213+ pr_warn("first branch should be rw\n");
dece6358 27214+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
febd17d6 27215+ pr_warn_once("shwh should be used with ro\n");
dece6358 27216+ }
1facf9fc 27217+
4a4d8108 27218+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1facf9fc 27219+ && !au_opt_test(sbinfo->si_mntflags, XINO))
febd17d6 27220+ pr_warn_once("udba=*notify requires xino\n");
1facf9fc 27221+
076b876e 27222+ if (au_opt_test(sbinfo->si_mntflags, DIRPERM1))
febd17d6
JR
27223+ pr_warn_once("dirperm1 breaks the protection"
27224+ " by the permission bits on the lower branch\n");
076b876e 27225+
1facf9fc 27226+ err = 0;
076b876e 27227+ fhsm = 0;
1facf9fc 27228+ root = sb->s_root;
5527c038 27229+ dir = d_inode(root);
1facf9fc 27230+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
79b8bda9
AM
27231+ can_no_dreval = !!au_opt_test((sbinfo->si_mntflags | pending),
27232+ UDBA_NONE);
5afbbe0d
AM
27233+ bbot = au_sbbot(sb);
27234+ for (bindex = 0; !err && bindex <= bbot; bindex++) {
1facf9fc 27235+ skip = 0;
27236+ h_dir = au_h_iptr(dir, bindex);
27237+ br = au_sbr(sb, bindex);
1facf9fc 27238+
c1595e42
JR
27239+ if ((br->br_perm & AuBrAttr_ICEX)
27240+ && !h_dir->i_op->listxattr)
27241+ br->br_perm &= ~AuBrAttr_ICEX;
43982f53 27242+#if 0 /* untested */
c1595e42 27243+ if ((br->br_perm & AuBrAttr_ICEX_SEC)
2121bcd9 27244+ && (au_br_sb(br)->s_flags & SB_NOSEC))
c1595e42
JR
27245+ br->br_perm &= ~AuBrAttr_ICEX_SEC;
27246+#endif
27247+
27248+ do_free = 0;
1facf9fc 27249+ wbr = br->br_wbr;
27250+ if (wbr)
27251+ wbr_wh_read_lock(wbr);
27252+
1e00d052 27253+ if (!au_br_writable(br->br_perm)) {
1facf9fc 27254+ do_free = !!wbr;
27255+ skip = (!wbr
27256+ || (!wbr->wbr_whbase
27257+ && !wbr->wbr_plink
27258+ && !wbr->wbr_orph));
1e00d052 27259+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 27260+ /* skip = (!br->br_whbase && !br->br_orph); */
27261+ skip = (!wbr || !wbr->wbr_whbase);
27262+ if (skip && wbr) {
27263+ if (do_plink)
27264+ skip = !!wbr->wbr_plink;
27265+ else
27266+ skip = !wbr->wbr_plink;
27267+ }
1e00d052 27268+ } else {
1facf9fc 27269+ /* skip = (br->br_whbase && br->br_ohph); */
27270+ skip = (wbr && wbr->wbr_whbase);
27271+ if (skip) {
27272+ if (do_plink)
27273+ skip = !!wbr->wbr_plink;
27274+ else
27275+ skip = !wbr->wbr_plink;
27276+ }
1facf9fc 27277+ }
27278+ if (wbr)
27279+ wbr_wh_read_unlock(wbr);
27280+
79b8bda9
AM
27281+ if (can_no_dreval) {
27282+ dentry = br->br_path.dentry;
27283+ spin_lock(&dentry->d_lock);
27284+ if (dentry->d_flags &
27285+ (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE))
27286+ can_no_dreval = 0;
27287+ spin_unlock(&dentry->d_lock);
27288+ }
27289+
076b876e
AM
27290+ if (au_br_fhsm(br->br_perm)) {
27291+ fhsm++;
27292+ AuDebugOn(!br->br_fhsm);
27293+ }
27294+
1facf9fc 27295+ if (skip)
27296+ continue;
27297+
27298+ hdir = au_hi(dir, bindex);
5afbbe0d 27299+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 27300+ if (wbr)
27301+ wbr_wh_write_lock(wbr);
86dc4139 27302+ err = au_wh_init(br, sb);
1facf9fc 27303+ if (wbr)
27304+ wbr_wh_write_unlock(wbr);
5afbbe0d 27305+ au_hn_inode_unlock(hdir);
1facf9fc 27306+
27307+ if (!err && do_free) {
9f237c51 27308+ au_kfree_rcu(wbr);
1facf9fc 27309+ br->br_wbr = NULL;
27310+ }
27311+ }
27312+
79b8bda9
AM
27313+ if (can_no_dreval)
27314+ au_fset_si(sbinfo, NO_DREVAL);
27315+ else
27316+ au_fclr_si(sbinfo, NO_DREVAL);
27317+
c1595e42 27318+ if (fhsm >= 2) {
076b876e 27319+ au_fset_si(sbinfo, FHSM);
5afbbe0d 27320+ for (bindex = bbot; bindex >= 0; bindex--) {
c1595e42
JR
27321+ br = au_sbr(sb, bindex);
27322+ if (au_br_fhsm(br->br_perm)) {
27323+ au_fhsm_set_bottom(sb, bindex);
27324+ break;
27325+ }
27326+ }
27327+ } else {
076b876e 27328+ au_fclr_si(sbinfo, FHSM);
c1595e42
JR
27329+ au_fhsm_set_bottom(sb, -1);
27330+ }
076b876e 27331+
1facf9fc 27332+ return err;
27333+}
27334+
27335+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
27336+{
27337+ int err;
27338+ unsigned int tmp;
5afbbe0d 27339+ aufs_bindex_t bindex, bbot;
1facf9fc 27340+ struct au_opt *opt;
27341+ struct au_opt_xino *opt_xino, xino;
27342+ struct au_sbinfo *sbinfo;
027c5e7a 27343+ struct au_branch *br;
076b876e 27344+ struct inode *dir;
1facf9fc 27345+
dece6358
AM
27346+ SiMustWriteLock(sb);
27347+
1facf9fc 27348+ err = 0;
27349+ opt_xino = NULL;
27350+ opt = opts->opt;
27351+ while (err >= 0 && opt->type != Opt_tail)
27352+ err = au_opt_simple(sb, opt++, opts);
27353+ if (err > 0)
27354+ err = 0;
27355+ else if (unlikely(err < 0))
27356+ goto out;
27357+
27358+ /* disable xino and udba temporary */
27359+ sbinfo = au_sbi(sb);
27360+ tmp = sbinfo->si_mntflags;
27361+ au_opt_clr(sbinfo->si_mntflags, XINO);
27362+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
27363+
27364+ opt = opts->opt;
27365+ while (err >= 0 && opt->type != Opt_tail)
27366+ err = au_opt_br(sb, opt++, opts);
27367+ if (err > 0)
27368+ err = 0;
27369+ else if (unlikely(err < 0))
27370+ goto out;
27371+
5afbbe0d
AM
27372+ bbot = au_sbbot(sb);
27373+ if (unlikely(bbot < 0)) {
1facf9fc 27374+ err = -EINVAL;
4a4d8108 27375+ pr_err("no branches\n");
1facf9fc 27376+ goto out;
27377+ }
27378+
27379+ if (au_opt_test(tmp, XINO))
27380+ au_opt_set(sbinfo->si_mntflags, XINO);
27381+ opt = opts->opt;
27382+ while (!err && opt->type != Opt_tail)
27383+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
27384+ if (unlikely(err))
27385+ goto out;
27386+
27387+ err = au_opts_verify(sb, sb->s_flags, tmp);
27388+ if (unlikely(err))
27389+ goto out;
27390+
27391+ /* restore xino */
27392+ if (au_opt_test(tmp, XINO) && !opt_xino) {
27393+ xino.file = au_xino_def(sb);
27394+ err = PTR_ERR(xino.file);
27395+ if (IS_ERR(xino.file))
27396+ goto out;
27397+
27398+ err = au_xino_set(sb, &xino, /*remount*/0);
27399+ fput(xino.file);
27400+ if (unlikely(err))
27401+ goto out;
27402+ }
27403+
27404+ /* restore udba */
027c5e7a 27405+ tmp &= AuOptMask_UDBA;
1facf9fc 27406+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
027c5e7a 27407+ sbinfo->si_mntflags |= tmp;
5afbbe0d
AM
27408+ bbot = au_sbbot(sb);
27409+ for (bindex = 0; bindex <= bbot; bindex++) {
027c5e7a
AM
27410+ br = au_sbr(sb, bindex);
27411+ err = au_hnotify_reset_br(tmp, br, br->br_perm);
27412+ if (unlikely(err))
27413+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
27414+ bindex, err);
27415+ /* go on even if err */
27416+ }
4a4d8108 27417+ if (au_opt_test(tmp, UDBA_HNOTIFY)) {
5527c038 27418+ dir = d_inode(sb->s_root);
4a4d8108 27419+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1facf9fc 27420+ }
27421+
4f0767ce 27422+out:
1facf9fc 27423+ return err;
27424+}
27425+
27426+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
27427+{
27428+ int err, rerr;
79b8bda9 27429+ unsigned char no_dreval;
1facf9fc 27430+ struct inode *dir;
27431+ struct au_opt_xino *opt_xino;
27432+ struct au_opt *opt;
27433+ struct au_sbinfo *sbinfo;
27434+
dece6358
AM
27435+ SiMustWriteLock(sb);
27436+
8b6a4947
AM
27437+ err = au_dr_opt_flush(sb);
27438+ if (unlikely(err))
27439+ goto out;
27440+ au_fset_opts(opts->flags, DR_FLUSHED);
27441+
5527c038 27442+ dir = d_inode(sb->s_root);
1facf9fc 27443+ sbinfo = au_sbi(sb);
1facf9fc 27444+ opt_xino = NULL;
27445+ opt = opts->opt;
27446+ while (err >= 0 && opt->type != Opt_tail) {
27447+ err = au_opt_simple(sb, opt, opts);
27448+ if (!err)
27449+ err = au_opt_br(sb, opt, opts);
27450+ if (!err)
27451+ err = au_opt_xino(sb, opt, &opt_xino, opts);
27452+ opt++;
27453+ }
27454+ if (err > 0)
27455+ err = 0;
27456+ AuTraceErr(err);
27457+ /* go on even err */
27458+
79b8bda9 27459+ no_dreval = !!au_ftest_si(sbinfo, NO_DREVAL);
1facf9fc 27460+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
27461+ if (unlikely(rerr && !err))
27462+ err = rerr;
27463+
79b8bda9 27464+ if (no_dreval != !!au_ftest_si(sbinfo, NO_DREVAL))
b95c5147 27465+ au_fset_opts(opts->flags, REFRESH_IDOP);
79b8bda9 27466+
1facf9fc 27467+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
27468+ rerr = au_xib_trunc(sb);
27469+ if (unlikely(rerr && !err))
27470+ err = rerr;
27471+ }
27472+
27473+ /* will be handled by the caller */
027c5e7a 27474+ if (!au_ftest_opts(opts->flags, REFRESH)
79b8bda9
AM
27475+ && (opts->given_udba
27476+ || au_opt_test(sbinfo->si_mntflags, XINO)
b95c5147 27477+ || au_ftest_opts(opts->flags, REFRESH_IDOP)
79b8bda9 27478+ ))
027c5e7a 27479+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 27480+
27481+ AuDbg("status 0x%x\n", opts->flags);
8b6a4947
AM
27482+
27483+out:
1facf9fc 27484+ return err;
27485+}
27486+
27487+/* ---------------------------------------------------------------------- */
27488+
27489+unsigned int au_opt_udba(struct super_block *sb)
27490+{
27491+ return au_mntflags(sb) & AuOptMask_UDBA;
27492+}
7f207e10 27493diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
eca34b5c 27494--- /usr/share/empty/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 27495+++ linux/fs/aufs/opts.h 2021-05-02 20:15:14.676670793 +0200
062440b3
AM
27496@@ -0,0 +1,225 @@
27497+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 27498+/*
d58c55f2 27499+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 27500+ *
27501+ * This program, aufs is free software; you can redistribute it and/or modify
27502+ * it under the terms of the GNU General Public License as published by
27503+ * the Free Software Foundation; either version 2 of the License, or
27504+ * (at your option) any later version.
dece6358
AM
27505+ *
27506+ * This program is distributed in the hope that it will be useful,
27507+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27508+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27509+ * GNU General Public License for more details.
27510+ *
27511+ * You should have received a copy of the GNU General Public License
523b37e3 27512+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 27513+ */
27514+
27515+/*
27516+ * mount options/flags
27517+ */
27518+
27519+#ifndef __AUFS_OPTS_H__
27520+#define __AUFS_OPTS_H__
27521+
27522+#ifdef __KERNEL__
27523+
dece6358 27524+#include <linux/path.h>
1facf9fc 27525+
dece6358 27526+struct file;
dece6358 27527+
1facf9fc 27528+/* ---------------------------------------------------------------------- */
27529+
27530+/* mount flags */
27531+#define AuOpt_XINO 1 /* external inode number bitmap
27532+ and translation table */
27533+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
27534+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
27535+#define AuOpt_UDBA_REVAL (1 << 3)
4a4d8108 27536+#define AuOpt_UDBA_HNOTIFY (1 << 4)
dece6358
AM
27537+#define AuOpt_SHWH (1 << 5) /* show whiteout */
27538+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
076b876e
AM
27539+#define AuOpt_DIRPERM1 (1 << 7) /* ignore the lower dir's perm
27540+ bits */
dece6358
AM
27541+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
27542+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
27543+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
27544+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
eca801bf 27545+#define AuOpt_VERBOSE (1 << 13) /* print the cause of error */
4a4d8108 27546+#define AuOpt_DIO (1 << 14) /* direct io */
8b6a4947 27547+#define AuOpt_DIRREN (1 << 15) /* directory rename */
1facf9fc 27548+
4a4d8108
AM
27549+#ifndef CONFIG_AUFS_HNOTIFY
27550+#undef AuOpt_UDBA_HNOTIFY
27551+#define AuOpt_UDBA_HNOTIFY 0
1facf9fc 27552+#endif
8b6a4947
AM
27553+#ifndef CONFIG_AUFS_DIRREN
27554+#undef AuOpt_DIRREN
27555+#define AuOpt_DIRREN 0
27556+#endif
dece6358
AM
27557+#ifndef CONFIG_AUFS_SHWH
27558+#undef AuOpt_SHWH
27559+#define AuOpt_SHWH 0
27560+#endif
1facf9fc 27561+
27562+#define AuOpt_Def (AuOpt_XINO \
27563+ | AuOpt_UDBA_REVAL \
27564+ | AuOpt_PLINK \
27565+ /* | AuOpt_DIRPERM1 */ \
27566+ | AuOpt_WARN_PERM)
27567+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
27568+ | AuOpt_UDBA_REVAL \
4a4d8108 27569+ | AuOpt_UDBA_HNOTIFY)
1facf9fc 27570+
27571+#define au_opt_test(flags, name) (flags & AuOpt_##name)
27572+#define au_opt_set(flags, name) do { \
27573+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
27574+ ((flags) |= AuOpt_##name); \
27575+} while (0)
27576+#define au_opt_set_udba(flags, name) do { \
27577+ (flags) &= ~AuOptMask_UDBA; \
27578+ ((flags) |= AuOpt_##name); \
27579+} while (0)
7f207e10
AM
27580+#define au_opt_clr(flags, name) do { \
27581+ ((flags) &= ~AuOpt_##name); \
27582+} while (0)
1facf9fc 27583+
e49829fe
JR
27584+static inline unsigned int au_opts_plink(unsigned int mntflags)
27585+{
27586+#ifdef CONFIG_PROC_FS
27587+ return mntflags;
27588+#else
27589+ return mntflags & ~AuOpt_PLINK;
27590+#endif
27591+}
27592+
1facf9fc 27593+/* ---------------------------------------------------------------------- */
27594+
27595+/* policies to select one among multiple writable branches */
27596+enum {
27597+ AuWbrCreate_TDP, /* top down parent */
27598+ AuWbrCreate_RR, /* round robin */
27599+ AuWbrCreate_MFS, /* most free space */
27600+ AuWbrCreate_MFSV, /* mfs with seconds */
27601+ AuWbrCreate_MFSRR, /* mfs then rr */
27602+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
f2c43d5f
AM
27603+ AuWbrCreate_TDMFS, /* top down regardless parent and mfs */
27604+ AuWbrCreate_TDMFSV, /* top down regardless parent and mfs */
1facf9fc 27605+ AuWbrCreate_PMFS, /* parent and mfs */
27606+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
392086de
AM
27607+ AuWbrCreate_PMFSRR, /* parent, mfs and round-robin */
27608+ AuWbrCreate_PMFSRRV, /* plus seconds */
1facf9fc 27609+
27610+ AuWbrCreate_Def = AuWbrCreate_TDP
27611+};
27612+
27613+enum {
27614+ AuWbrCopyup_TDP, /* top down parent */
27615+ AuWbrCopyup_BUP, /* bottom up parent */
27616+ AuWbrCopyup_BU, /* bottom up */
27617+
27618+ AuWbrCopyup_Def = AuWbrCopyup_TDP
27619+};
27620+
27621+/* ---------------------------------------------------------------------- */
27622+
27623+struct au_opt_add {
27624+ aufs_bindex_t bindex;
27625+ char *pathname;
27626+ int perm;
27627+ struct path path;
27628+};
27629+
27630+struct au_opt_del {
27631+ char *pathname;
27632+ struct path h_path;
27633+};
27634+
27635+struct au_opt_mod {
27636+ char *path;
27637+ int perm;
27638+ struct dentry *h_root;
27639+};
27640+
27641+struct au_opt_xino {
27642+ char *path;
27643+ struct file *file;
27644+};
27645+
27646+struct au_opt_xino_itrunc {
27647+ aufs_bindex_t bindex;
27648+};
27649+
27650+struct au_opt_wbr_create {
27651+ int wbr_create;
27652+ int mfs_second;
27653+ unsigned long long mfsrr_watermark;
27654+};
27655+
27656+struct au_opt {
27657+ int type;
27658+ union {
27659+ struct au_opt_xino xino;
27660+ struct au_opt_xino_itrunc xino_itrunc;
27661+ struct au_opt_add add;
27662+ struct au_opt_del del;
27663+ struct au_opt_mod mod;
27664+ int dirwh;
27665+ int rdcache;
27666+ unsigned int rdblk;
27667+ unsigned int rdhash;
27668+ int udba;
27669+ struct au_opt_wbr_create wbr_create;
27670+ int wbr_copyup;
076b876e 27671+ unsigned int fhsm_second;
1facf9fc 27672+ };
27673+};
27674+
27675+/* opts flags */
27676+#define AuOpts_REMOUNT 1
027c5e7a
AM
27677+#define AuOpts_REFRESH (1 << 1)
27678+#define AuOpts_TRUNC_XIB (1 << 2)
27679+#define AuOpts_REFRESH_DYAOP (1 << 3)
b95c5147 27680+#define AuOpts_REFRESH_IDOP (1 << 4)
8b6a4947 27681+#define AuOpts_DR_FLUSHED (1 << 5)
1facf9fc 27682+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
7f207e10
AM
27683+#define au_fset_opts(flags, name) \
27684+ do { (flags) |= AuOpts_##name; } while (0)
27685+#define au_fclr_opts(flags, name) \
27686+ do { (flags) &= ~AuOpts_##name; } while (0)
1facf9fc 27687+
8b6a4947
AM
27688+#ifndef CONFIG_AUFS_DIRREN
27689+#undef AuOpts_DR_FLUSHED
27690+#define AuOpts_DR_FLUSHED 0
27691+#endif
27692+
1facf9fc 27693+struct au_opts {
27694+ struct au_opt *opt;
27695+ int max_opt;
27696+
27697+ unsigned int given_udba;
27698+ unsigned int flags;
27699+ unsigned long sb_flags;
27700+};
27701+
27702+/* ---------------------------------------------------------------------- */
27703+
7e9cd9fe 27704+/* opts.c */
076b876e 27705+void au_optstr_br_perm(au_br_perm_str_t *str, int perm);
1facf9fc 27706+const char *au_optstr_udba(int udba);
27707+const char *au_optstr_wbr_copyup(int wbr_copyup);
27708+const char *au_optstr_wbr_create(int wbr_create);
27709+
27710+void au_opts_free(struct au_opts *opts);
3c1bdaff 27711+struct super_block;
1facf9fc 27712+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
27713+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
27714+ unsigned int pending);
27715+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
27716+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
27717+
27718+unsigned int au_opt_udba(struct super_block *sb);
27719+
1facf9fc 27720+#endif /* __KERNEL__ */
27721+#endif /* __AUFS_OPTS_H__ */
7f207e10 27722diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
eca34b5c 27723--- /usr/share/empty/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 27724+++ linux/fs/aufs/plink.c 2021-05-02 20:15:14.676670793 +0200
062440b3 27725@@ -0,0 +1,516 @@
cd7a4cd9 27726+// SPDX-License-Identifier: GPL-2.0
1facf9fc 27727+/*
d58c55f2 27728+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 27729+ *
27730+ * This program, aufs is free software; you can redistribute it and/or modify
27731+ * it under the terms of the GNU General Public License as published by
27732+ * the Free Software Foundation; either version 2 of the License, or
27733+ * (at your option) any later version.
dece6358
AM
27734+ *
27735+ * This program is distributed in the hope that it will be useful,
27736+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27737+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27738+ * GNU General Public License for more details.
27739+ *
27740+ * You should have received a copy of the GNU General Public License
523b37e3 27741+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 27742+ */
27743+
27744+/*
27745+ * pseudo-link
27746+ */
27747+
27748+#include "aufs.h"
27749+
27750+/*
e49829fe 27751+ * the pseudo-link maintenance mode.
1facf9fc 27752+ * during a user process maintains the pseudo-links,
27753+ * prohibit adding a new plink and branch manipulation.
e49829fe
JR
27754+ *
27755+ * Flags
27756+ * NOPLM:
27757+ * For entry functions which will handle plink, and i_mutex is already held
27758+ * in VFS.
27759+ * They cannot wait and should return an error at once.
27760+ * Callers has to check the error.
27761+ * NOPLMW:
27762+ * For entry functions which will handle plink, but i_mutex is not held
27763+ * in VFS.
27764+ * They can wait the plink maintenance mode to finish.
27765+ *
27766+ * They behave like F_SETLK and F_SETLKW.
27767+ * If the caller never handle plink, then both flags are unnecessary.
1facf9fc 27768+ */
e49829fe
JR
27769+
27770+int au_plink_maint(struct super_block *sb, int flags)
1facf9fc 27771+{
e49829fe
JR
27772+ int err;
27773+ pid_t pid, ppid;
f0c0a007 27774+ struct task_struct *parent, *prev;
e49829fe 27775+ struct au_sbinfo *sbi;
dece6358
AM
27776+
27777+ SiMustAnyLock(sb);
27778+
e49829fe
JR
27779+ err = 0;
27780+ if (!au_opt_test(au_mntflags(sb), PLINK))
27781+ goto out;
27782+
27783+ sbi = au_sbi(sb);
27784+ pid = sbi->si_plink_maint_pid;
27785+ if (!pid || pid == current->pid)
27786+ goto out;
27787+
27788+ /* todo: it highly depends upon /sbin/mount.aufs */
f0c0a007
AM
27789+ prev = NULL;
27790+ parent = current;
27791+ ppid = 0;
e49829fe 27792+ rcu_read_lock();
f0c0a007
AM
27793+ while (1) {
27794+ parent = rcu_dereference(parent->real_parent);
27795+ if (parent == prev)
27796+ break;
27797+ ppid = task_pid_vnr(parent);
27798+ if (pid == ppid) {
27799+ rcu_read_unlock();
27800+ goto out;
27801+ }
27802+ prev = parent;
27803+ }
e49829fe 27804+ rcu_read_unlock();
e49829fe
JR
27805+
27806+ if (au_ftest_lock(flags, NOPLMW)) {
027c5e7a
AM
27807+ /* if there is no i_mutex lock in VFS, we don't need to wait */
27808+ /* AuDebugOn(!lockdep_depth(current)); */
e49829fe
JR
27809+ while (sbi->si_plink_maint_pid) {
27810+ si_read_unlock(sb);
27811+ /* gave up wake_up_bit() */
27812+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid);
27813+
27814+ if (au_ftest_lock(flags, FLUSH))
27815+ au_nwt_flush(&sbi->si_nowait);
27816+ si_noflush_read_lock(sb);
27817+ }
27818+ } else if (au_ftest_lock(flags, NOPLM)) {
27819+ AuDbg("ppid %d, pid %d\n", ppid, pid);
27820+ err = -EAGAIN;
27821+ }
27822+
27823+out:
27824+ return err;
4a4d8108
AM
27825+}
27826+
e49829fe 27827+void au_plink_maint_leave(struct au_sbinfo *sbinfo)
4a4d8108 27828+{
4a4d8108 27829+ spin_lock(&sbinfo->si_plink_maint_lock);
027c5e7a 27830+ sbinfo->si_plink_maint_pid = 0;
4a4d8108 27831+ spin_unlock(&sbinfo->si_plink_maint_lock);
027c5e7a 27832+ wake_up_all(&sbinfo->si_plink_wq);
4a4d8108
AM
27833+}
27834+
e49829fe 27835+int au_plink_maint_enter(struct super_block *sb)
4a4d8108
AM
27836+{
27837+ int err;
4a4d8108
AM
27838+ struct au_sbinfo *sbinfo;
27839+
27840+ err = 0;
4a4d8108
AM
27841+ sbinfo = au_sbi(sb);
27842+ /* make sure i am the only one in this fs */
e49829fe
JR
27843+ si_write_lock(sb, AuLock_FLUSH);
27844+ if (au_opt_test(au_mntflags(sb), PLINK)) {
27845+ spin_lock(&sbinfo->si_plink_maint_lock);
27846+ if (!sbinfo->si_plink_maint_pid)
27847+ sbinfo->si_plink_maint_pid = current->pid;
27848+ else
27849+ err = -EBUSY;
27850+ spin_unlock(&sbinfo->si_plink_maint_lock);
27851+ }
4a4d8108
AM
27852+ si_write_unlock(sb);
27853+
27854+ return err;
1facf9fc 27855+}
27856+
27857+/* ---------------------------------------------------------------------- */
27858+
1facf9fc 27859+#ifdef CONFIG_AUFS_DEBUG
27860+void au_plink_list(struct super_block *sb)
27861+{
86dc4139 27862+ int i;
1facf9fc 27863+ struct au_sbinfo *sbinfo;
8b6a4947
AM
27864+ struct hlist_bl_head *hbl;
27865+ struct hlist_bl_node *pos;
5afbbe0d 27866+ struct au_icntnr *icntnr;
1facf9fc 27867+
dece6358
AM
27868+ SiMustAnyLock(sb);
27869+
1facf9fc 27870+ sbinfo = au_sbi(sb);
27871+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 27872+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 27873+
86dc4139 27874+ for (i = 0; i < AuPlink_NHASH; i++) {
8b6a4947
AM
27875+ hbl = sbinfo->si_plink + i;
27876+ hlist_bl_lock(hbl);
27877+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink)
5afbbe0d 27878+ AuDbg("%lu\n", icntnr->vfs_inode.i_ino);
8b6a4947 27879+ hlist_bl_unlock(hbl);
86dc4139 27880+ }
1facf9fc 27881+}
27882+#endif
27883+
27884+/* is the inode pseudo-linked? */
27885+int au_plink_test(struct inode *inode)
27886+{
86dc4139 27887+ int found, i;
1facf9fc 27888+ struct au_sbinfo *sbinfo;
8b6a4947
AM
27889+ struct hlist_bl_head *hbl;
27890+ struct hlist_bl_node *pos;
5afbbe0d 27891+ struct au_icntnr *icntnr;
1facf9fc 27892+
27893+ sbinfo = au_sbi(inode->i_sb);
dece6358 27894+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 27895+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
e49829fe 27896+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
1facf9fc 27897+
27898+ found = 0;
86dc4139 27899+ i = au_plink_hash(inode->i_ino);
8b6a4947
AM
27900+ hbl = sbinfo->si_plink + i;
27901+ hlist_bl_lock(hbl);
27902+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink)
5afbbe0d 27903+ if (&icntnr->vfs_inode == inode) {
1facf9fc 27904+ found = 1;
27905+ break;
27906+ }
8b6a4947 27907+ hlist_bl_unlock(hbl);
1facf9fc 27908+ return found;
27909+}
27910+
27911+/* ---------------------------------------------------------------------- */
27912+
27913+/*
27914+ * generate a name for plink.
27915+ * the file will be stored under AUFS_WH_PLINKDIR.
27916+ */
27917+/* 20 is max digits length of ulong 64 */
27918+#define PLINK_NAME_LEN ((20 + 1) * 2)
27919+
27920+static int plink_name(char *name, int len, struct inode *inode,
27921+ aufs_bindex_t bindex)
27922+{
27923+ int rlen;
27924+ struct inode *h_inode;
27925+
27926+ h_inode = au_h_iptr(inode, bindex);
27927+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
27928+ return rlen;
27929+}
27930+
7f207e10
AM
27931+struct au_do_plink_lkup_args {
27932+ struct dentry **errp;
27933+ struct qstr *tgtname;
27934+ struct dentry *h_parent;
27935+ struct au_branch *br;
27936+};
27937+
27938+static struct dentry *au_do_plink_lkup(struct qstr *tgtname,
27939+ struct dentry *h_parent,
27940+ struct au_branch *br)
27941+{
27942+ struct dentry *h_dentry;
febd17d6 27943+ struct inode *h_inode;
7f207e10 27944+
febd17d6 27945+ h_inode = d_inode(h_parent);
be118d29 27946+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD2);
b4510431 27947+ h_dentry = vfsub_lkup_one(tgtname, h_parent);
3c1bdaff 27948+ inode_unlock_shared(h_inode);
7f207e10
AM
27949+ return h_dentry;
27950+}
27951+
27952+static void au_call_do_plink_lkup(void *args)
27953+{
27954+ struct au_do_plink_lkup_args *a = args;
27955+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br);
27956+}
27957+
1facf9fc 27958+/* lookup the plink-ed @inode under the branch at @bindex */
27959+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
27960+{
27961+ struct dentry *h_dentry, *h_parent;
27962+ struct au_branch *br;
7f207e10 27963+ int wkq_err;
1facf9fc 27964+ char a[PLINK_NAME_LEN];
0c3ec466 27965+ struct qstr tgtname = QSTR_INIT(a, 0);
1facf9fc 27966+
e49829fe
JR
27967+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
27968+
1facf9fc 27969+ br = au_sbr(inode->i_sb, bindex);
27970+ h_parent = br->br_wbr->wbr_plink;
1facf9fc 27971+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
27972+
2dfbb274 27973+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) {
7f207e10
AM
27974+ struct au_do_plink_lkup_args args = {
27975+ .errp = &h_dentry,
27976+ .tgtname = &tgtname,
27977+ .h_parent = h_parent,
27978+ .br = br
27979+ };
27980+
27981+ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args);
27982+ if (unlikely(wkq_err))
27983+ h_dentry = ERR_PTR(wkq_err);
27984+ } else
27985+ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br);
27986+
1facf9fc 27987+ return h_dentry;
27988+}
27989+
27990+/* create a pseudo-link */
27991+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
27992+ struct dentry *h_dentry, struct au_branch *br)
27993+{
27994+ int err;
27995+ struct path h_path = {
86dc4139 27996+ .mnt = au_br_mnt(br)
1facf9fc 27997+ };
523b37e3 27998+ struct inode *h_dir, *delegated;
1facf9fc 27999+
5527c038 28000+ h_dir = d_inode(h_parent);
febd17d6 28001+ inode_lock_nested(h_dir, AuLsc_I_CHILD2);
4f0767ce 28002+again:
b4510431 28003+ h_path.dentry = vfsub_lkup_one(tgt, h_parent);
1facf9fc 28004+ err = PTR_ERR(h_path.dentry);
28005+ if (IS_ERR(h_path.dentry))
28006+ goto out;
28007+
28008+ err = 0;
28009+ /* wh.plink dir is not monitored */
7f207e10 28010+ /* todo: is it really safe? */
5527c038
JR
28011+ if (d_is_positive(h_path.dentry)
28012+ && d_inode(h_path.dentry) != d_inode(h_dentry)) {
523b37e3
AM
28013+ delegated = NULL;
28014+ err = vfsub_unlink(h_dir, &h_path, &delegated, /*force*/0);
28015+ if (unlikely(err == -EWOULDBLOCK)) {
28016+ pr_warn("cannot retry for NFSv4 delegation"
28017+ " for an internal unlink\n");
28018+ iput(delegated);
28019+ }
1facf9fc 28020+ dput(h_path.dentry);
28021+ h_path.dentry = NULL;
28022+ if (!err)
28023+ goto again;
28024+ }
5527c038 28025+ if (!err && d_is_negative(h_path.dentry)) {
523b37e3
AM
28026+ delegated = NULL;
28027+ err = vfsub_link(h_dentry, h_dir, &h_path, &delegated);
28028+ if (unlikely(err == -EWOULDBLOCK)) {
28029+ pr_warn("cannot retry for NFSv4 delegation"
28030+ " for an internal link\n");
28031+ iput(delegated);
28032+ }
28033+ }
1facf9fc 28034+ dput(h_path.dentry);
28035+
4f0767ce 28036+out:
febd17d6 28037+ inode_unlock(h_dir);
1facf9fc 28038+ return err;
28039+}
28040+
28041+struct do_whplink_args {
28042+ int *errp;
28043+ struct qstr *tgt;
28044+ struct dentry *h_parent;
28045+ struct dentry *h_dentry;
28046+ struct au_branch *br;
28047+};
28048+
28049+static void call_do_whplink(void *args)
28050+{
28051+ struct do_whplink_args *a = args;
28052+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
28053+}
28054+
28055+static int whplink(struct dentry *h_dentry, struct inode *inode,
28056+ aufs_bindex_t bindex, struct au_branch *br)
28057+{
28058+ int err, wkq_err;
28059+ struct au_wbr *wbr;
28060+ struct dentry *h_parent;
1facf9fc 28061+ char a[PLINK_NAME_LEN];
0c3ec466 28062+ struct qstr tgtname = QSTR_INIT(a, 0);
1facf9fc 28063+
28064+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
28065+ h_parent = wbr->wbr_plink;
1facf9fc 28066+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
28067+
28068+ /* always superio. */
2dfbb274 28069+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) {
1facf9fc 28070+ struct do_whplink_args args = {
28071+ .errp = &err,
28072+ .tgt = &tgtname,
28073+ .h_parent = h_parent,
28074+ .h_dentry = h_dentry,
28075+ .br = br
28076+ };
28077+ wkq_err = au_wkq_wait(call_do_whplink, &args);
28078+ if (unlikely(wkq_err))
28079+ err = wkq_err;
28080+ } else
28081+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
1facf9fc 28082+
28083+ return err;
28084+}
28085+
1facf9fc 28086+/*
28087+ * create a new pseudo-link for @h_dentry on @bindex.
28088+ * the linked inode is held in aufs @inode.
28089+ */
28090+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
28091+ struct dentry *h_dentry)
28092+{
28093+ struct super_block *sb;
28094+ struct au_sbinfo *sbinfo;
8b6a4947
AM
28095+ struct hlist_bl_head *hbl;
28096+ struct hlist_bl_node *pos;
5afbbe0d 28097+ struct au_icntnr *icntnr;
86dc4139 28098+ int found, err, cnt, i;
1facf9fc 28099+
28100+ sb = inode->i_sb;
28101+ sbinfo = au_sbi(sb);
28102+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 28103+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 28104+
86dc4139 28105+ found = au_plink_test(inode);
4a4d8108 28106+ if (found)
1facf9fc 28107+ return;
4a4d8108 28108+
86dc4139 28109+ i = au_plink_hash(inode->i_ino);
8b6a4947 28110+ hbl = sbinfo->si_plink + i;
5afbbe0d 28111+ au_igrab(inode);
1facf9fc 28112+
8b6a4947
AM
28113+ hlist_bl_lock(hbl);
28114+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) {
5afbbe0d 28115+ if (&icntnr->vfs_inode == inode) {
4a4d8108
AM
28116+ found = 1;
28117+ break;
28118+ }
1facf9fc 28119+ }
5afbbe0d
AM
28120+ if (!found) {
28121+ icntnr = container_of(inode, struct au_icntnr, vfs_inode);
8b6a4947 28122+ hlist_bl_add_head(&icntnr->plink, hbl);
5afbbe0d 28123+ }
8b6a4947 28124+ hlist_bl_unlock(hbl);
4a4d8108 28125+ if (!found) {
8b6a4947 28126+ cnt = au_hbl_count(hbl);
acd2b654 28127+#define msg "unexpectedly unbalanced or too many pseudo-links"
86dc4139
AM
28128+ if (cnt > AUFS_PLINK_WARN)
28129+ AuWarn1(msg ", %d\n", cnt);
28130+#undef msg
1facf9fc 28131+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
5afbbe0d
AM
28132+ if (unlikely(err)) {
28133+ pr_warn("err %d, damaged pseudo link.\n", err);
8b6a4947 28134+ au_hbl_del(&icntnr->plink, hbl);
5afbbe0d 28135+ iput(&icntnr->vfs_inode);
4a4d8108 28136+ }
5afbbe0d
AM
28137+ } else
28138+ iput(&icntnr->vfs_inode);
1facf9fc 28139+}
28140+
28141+/* free all plinks */
e49829fe 28142+void au_plink_put(struct super_block *sb, int verbose)
1facf9fc 28143+{
86dc4139 28144+ int i, warned;
1facf9fc 28145+ struct au_sbinfo *sbinfo;
8b6a4947
AM
28146+ struct hlist_bl_head *hbl;
28147+ struct hlist_bl_node *pos, *tmp;
5afbbe0d 28148+ struct au_icntnr *icntnr;
1facf9fc 28149+
dece6358
AM
28150+ SiMustWriteLock(sb);
28151+
1facf9fc 28152+ sbinfo = au_sbi(sb);
28153+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 28154+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 28155+
1facf9fc 28156+ /* no spin_lock since sbinfo is write-locked */
86dc4139
AM
28157+ warned = 0;
28158+ for (i = 0; i < AuPlink_NHASH; i++) {
8b6a4947
AM
28159+ hbl = sbinfo->si_plink + i;
28160+ if (!warned && verbose && !hlist_bl_empty(hbl)) {
86dc4139
AM
28161+ pr_warn("pseudo-link is not flushed");
28162+ warned = 1;
28163+ }
8b6a4947 28164+ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink)
5afbbe0d 28165+ iput(&icntnr->vfs_inode);
8b6a4947 28166+ INIT_HLIST_BL_HEAD(hbl);
86dc4139 28167+ }
1facf9fc 28168+}
28169+
e49829fe
JR
28170+void au_plink_clean(struct super_block *sb, int verbose)
28171+{
28172+ struct dentry *root;
28173+
28174+ root = sb->s_root;
28175+ aufs_write_lock(root);
28176+ if (au_opt_test(au_mntflags(sb), PLINK))
28177+ au_plink_put(sb, verbose);
28178+ aufs_write_unlock(root);
28179+}
28180+
86dc4139
AM
28181+static int au_plink_do_half_refresh(struct inode *inode, aufs_bindex_t br_id)
28182+{
28183+ int do_put;
5afbbe0d 28184+ aufs_bindex_t btop, bbot, bindex;
86dc4139
AM
28185+
28186+ do_put = 0;
5afbbe0d
AM
28187+ btop = au_ibtop(inode);
28188+ bbot = au_ibbot(inode);
28189+ if (btop >= 0) {
28190+ for (bindex = btop; bindex <= bbot; bindex++) {
86dc4139
AM
28191+ if (!au_h_iptr(inode, bindex)
28192+ || au_ii_br_id(inode, bindex) != br_id)
28193+ continue;
28194+ au_set_h_iptr(inode, bindex, NULL, 0);
28195+ do_put = 1;
28196+ break;
28197+ }
28198+ if (do_put)
5afbbe0d 28199+ for (bindex = btop; bindex <= bbot; bindex++)
86dc4139
AM
28200+ if (au_h_iptr(inode, bindex)) {
28201+ do_put = 0;
28202+ break;
28203+ }
28204+ } else
28205+ do_put = 1;
28206+
28207+ return do_put;
28208+}
28209+
1facf9fc 28210+/* free the plinks on a branch specified by @br_id */
28211+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
28212+{
28213+ struct au_sbinfo *sbinfo;
8b6a4947
AM
28214+ struct hlist_bl_head *hbl;
28215+ struct hlist_bl_node *pos, *tmp;
5afbbe0d 28216+ struct au_icntnr *icntnr;
1facf9fc 28217+ struct inode *inode;
86dc4139 28218+ int i, do_put;
1facf9fc 28219+
dece6358
AM
28220+ SiMustWriteLock(sb);
28221+
1facf9fc 28222+ sbinfo = au_sbi(sb);
28223+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 28224+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 28225+
8b6a4947 28226+ /* no bit_lock since sbinfo is write-locked */
86dc4139 28227+ for (i = 0; i < AuPlink_NHASH; i++) {
8b6a4947
AM
28228+ hbl = sbinfo->si_plink + i;
28229+ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink) {
5afbbe0d 28230+ inode = au_igrab(&icntnr->vfs_inode);
86dc4139
AM
28231+ ii_write_lock_child(inode);
28232+ do_put = au_plink_do_half_refresh(inode, br_id);
5afbbe0d 28233+ if (do_put) {
8b6a4947 28234+ hlist_bl_del(&icntnr->plink);
5afbbe0d
AM
28235+ iput(inode);
28236+ }
86dc4139
AM
28237+ ii_write_unlock(inode);
28238+ iput(inode);
dece6358 28239+ }
dece6358
AM
28240+ }
28241+}
7f207e10 28242diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
eca34b5c 28243--- /usr/share/empty/fs/aufs/poll.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 28244+++ linux/fs/aufs/poll.c 2021-05-02 20:15:14.676670793 +0200
cd7a4cd9
AM
28245@@ -0,0 +1,51 @@
28246+// SPDX-License-Identifier: GPL-2.0
dece6358 28247+/*
d58c55f2 28248+ * Copyright (C) 2005-2020 Junjiro R. Okajima
dece6358
AM
28249+ *
28250+ * This program, aufs is free software; you can redistribute it and/or modify
28251+ * it under the terms of the GNU General Public License as published by
28252+ * the Free Software Foundation; either version 2 of the License, or
28253+ * (at your option) any later version.
28254+ *
28255+ * This program is distributed in the hope that it will be useful,
28256+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28257+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28258+ * GNU General Public License for more details.
28259+ *
28260+ * You should have received a copy of the GNU General Public License
523b37e3 28261+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
dece6358
AM
28262+ */
28263+
1308ab2a 28264+/*
28265+ * poll operation
28266+ * There is only one filesystem which implements ->poll operation, currently.
28267+ */
28268+
28269+#include "aufs.h"
28270+
cd7a4cd9 28271+__poll_t aufs_poll(struct file *file, struct poll_table_struct *pt)
1308ab2a 28272+{
be118d29 28273+ __poll_t mask;
1308ab2a 28274+ struct file *h_file;
1308ab2a 28275+ struct super_block *sb;
28276+
28277+ /* We should pretend an error happened. */
be118d29 28278+ mask = EPOLLERR /* | EPOLLIN | EPOLLOUT */;
b912730e 28279+ sb = file->f_path.dentry->d_sb;
e49829fe 28280+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
b912730e 28281+
521ced18 28282+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
062440b3
AM
28283+ if (IS_ERR(h_file)) {
28284+ AuDbg("h_file %ld\n", PTR_ERR(h_file));
1308ab2a 28285+ goto out;
062440b3 28286+ }
1308ab2a 28287+
cd7a4cd9 28288+ mask = vfs_poll(h_file, pt);
b912730e 28289+ fput(h_file); /* instead of au_read_post() */
1308ab2a 28290+
4f0767ce 28291+out:
1308ab2a 28292+ si_read_unlock(sb);
062440b3 28293+ if (mask & EPOLLERR)
b00004a5 28294+ AuDbg("mask 0x%x\n", mask);
1308ab2a 28295+ return mask;
28296+}
c1595e42 28297diff -urN /usr/share/empty/fs/aufs/posix_acl.c linux/fs/aufs/posix_acl.c
eca34b5c 28298--- /usr/share/empty/fs/aufs/posix_acl.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6
JR
28299+++ linux/fs/aufs/posix_acl.c 2021-05-02 20:15:14.676670793 +0200
28300@@ -0,0 +1,106 @@
cd7a4cd9 28301+// SPDX-License-Identifier: GPL-2.0
c1595e42 28302+/*
d58c55f2 28303+ * Copyright (C) 2014-2020 Junjiro R. Okajima
c1595e42
JR
28304+ *
28305+ * This program, aufs is free software; you can redistribute it and/or modify
28306+ * it under the terms of the GNU General Public License as published by
28307+ * the Free Software Foundation; either version 2 of the License, or
28308+ * (at your option) any later version.
28309+ *
28310+ * This program is distributed in the hope that it will be useful,
28311+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28312+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28313+ * GNU General Public License for more details.
28314+ *
28315+ * You should have received a copy of the GNU General Public License
28316+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
28317+ */
28318+
28319+/*
28320+ * posix acl operations
28321+ */
28322+
28323+#include <linux/fs.h>
c1595e42
JR
28324+#include "aufs.h"
28325+
28326+struct posix_acl *aufs_get_acl(struct inode *inode, int type)
28327+{
28328+ struct posix_acl *acl;
28329+ int err;
28330+ aufs_bindex_t bindex;
28331+ struct inode *h_inode;
28332+ struct super_block *sb;
28333+
28334+ acl = NULL;
28335+ sb = inode->i_sb;
28336+ si_read_lock(sb, AuLock_FLUSH);
28337+ ii_read_lock_child(inode);
2121bcd9 28338+ if (!(sb->s_flags & SB_POSIXACL))
c1595e42
JR
28339+ goto out;
28340+
5afbbe0d 28341+ bindex = au_ibtop(inode);
c1595e42
JR
28342+ h_inode = au_h_iptr(inode, bindex);
28343+ if (unlikely(!h_inode
28344+ || ((h_inode->i_mode & S_IFMT)
28345+ != (inode->i_mode & S_IFMT)))) {
28346+ err = au_busy_or_stale();
28347+ acl = ERR_PTR(err);
28348+ goto out;
28349+ }
28350+
28351+ /* always topmost only */
28352+ acl = get_acl(h_inode, type);
9f00928d
AM
28353+ if (IS_ERR(acl))
28354+ forget_cached_acl(inode, type);
28355+ else
a2654f78 28356+ set_cached_acl(inode, type, acl);
c1595e42
JR
28357+
28358+out:
28359+ ii_read_unlock(inode);
28360+ si_read_unlock(sb);
28361+
28362+ AuTraceErrPtr(acl);
28363+ return acl;
28364+}
28365+
0b2a12c6
JR
28366+int aufs_set_acl(struct user_namespace *userns, struct inode *inode,
28367+ struct posix_acl *acl, int type)
c1595e42
JR
28368+{
28369+ int err;
28370+ ssize_t ssz;
28371+ struct dentry *dentry;
f2c43d5f 28372+ struct au_sxattr arg = {
c1595e42
JR
28373+ .type = AU_ACL_SET,
28374+ .u.acl_set = {
28375+ .acl = acl,
28376+ .type = type
28377+ },
28378+ };
28379+
5afbbe0d
AM
28380+ IMustLock(inode);
28381+
c1595e42
JR
28382+ if (inode->i_ino == AUFS_ROOT_INO)
28383+ dentry = dget(inode->i_sb->s_root);
28384+ else {
28385+ dentry = d_find_alias(inode);
28386+ if (!dentry)
28387+ dentry = d_find_any_alias(inode);
28388+ if (!dentry) {
28389+ pr_warn("cannot handle this inode, "
28390+ "please report to aufs-users ML\n");
28391+ err = -ENOENT;
28392+ goto out;
28393+ }
28394+ }
28395+
f2c43d5f 28396+ ssz = au_sxattr(dentry, inode, &arg);
9f00928d
AM
28397+ /* forget even it if succeeds since the branch might set differently */
28398+ forget_cached_acl(inode, type);
c1595e42
JR
28399+ dput(dentry);
28400+ err = ssz;
9f00928d 28401+ if (ssz >= 0)
c1595e42
JR
28402+ err = 0;
28403+
28404+out:
c1595e42
JR
28405+ return err;
28406+}
7f207e10 28407diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c
eca34b5c 28408--- /usr/share/empty/fs/aufs/procfs.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 28409+++ linux/fs/aufs/procfs.c 2021-05-02 20:15:14.676670793 +0200
394e211a 28410@@ -0,0 +1,170 @@
cd7a4cd9 28411+// SPDX-License-Identifier: GPL-2.0
e49829fe 28412+/*
d58c55f2 28413+ * Copyright (C) 2010-2020 Junjiro R. Okajima
e49829fe
JR
28414+ *
28415+ * This program, aufs is free software; you can redistribute it and/or modify
28416+ * it under the terms of the GNU General Public License as published by
28417+ * the Free Software Foundation; either version 2 of the License, or
28418+ * (at your option) any later version.
28419+ *
28420+ * This program is distributed in the hope that it will be useful,
28421+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28422+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28423+ * GNU General Public License for more details.
28424+ *
28425+ * You should have received a copy of the GNU General Public License
523b37e3 28426+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
e49829fe
JR
28427+ */
28428+
28429+/*
28430+ * procfs interfaces
28431+ */
28432+
28433+#include <linux/proc_fs.h>
28434+#include "aufs.h"
28435+
28436+static int au_procfs_plm_release(struct inode *inode, struct file *file)
28437+{
28438+ struct au_sbinfo *sbinfo;
28439+
28440+ sbinfo = file->private_data;
28441+ if (sbinfo) {
28442+ au_plink_maint_leave(sbinfo);
28443+ kobject_put(&sbinfo->si_kobj);
28444+ }
28445+
28446+ return 0;
28447+}
28448+
28449+static void au_procfs_plm_write_clean(struct file *file)
28450+{
28451+ struct au_sbinfo *sbinfo;
28452+
28453+ sbinfo = file->private_data;
28454+ if (sbinfo)
28455+ au_plink_clean(sbinfo->si_sb, /*verbose*/0);
28456+}
28457+
28458+static int au_procfs_plm_write_si(struct file *file, unsigned long id)
28459+{
28460+ int err;
28461+ struct super_block *sb;
28462+ struct au_sbinfo *sbinfo;
8b6a4947 28463+ struct hlist_bl_node *pos;
e49829fe
JR
28464+
28465+ err = -EBUSY;
28466+ if (unlikely(file->private_data))
28467+ goto out;
28468+
28469+ sb = NULL;
53392da6 28470+ /* don't use au_sbilist_lock() here */
8b6a4947
AM
28471+ hlist_bl_lock(&au_sbilist);
28472+ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list)
e49829fe 28473+ if (id == sysaufs_si_id(sbinfo)) {
83b672a5
AM
28474+ if (kobject_get_unless_zero(&sbinfo->si_kobj))
28475+ sb = sbinfo->si_sb;
e49829fe
JR
28476+ break;
28477+ }
8b6a4947 28478+ hlist_bl_unlock(&au_sbilist);
e49829fe
JR
28479+
28480+ err = -EINVAL;
28481+ if (unlikely(!sb))
28482+ goto out;
28483+
28484+ err = au_plink_maint_enter(sb);
28485+ if (!err)
28486+ /* keep kobject_get() */
28487+ file->private_data = sbinfo;
28488+ else
28489+ kobject_put(&sbinfo->si_kobj);
28490+out:
28491+ return err;
28492+}
28493+
28494+/*
28495+ * Accept a valid "si=xxxx" only.
28496+ * Once it is accepted successfully, accept "clean" too.
28497+ */
28498+static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf,
28499+ size_t count, loff_t *ppos)
28500+{
28501+ ssize_t err;
28502+ unsigned long id;
28503+ /* last newline is allowed */
28504+ char buf[3 + sizeof(unsigned long) * 2 + 1];
28505+
28506+ err = -EACCES;
28507+ if (unlikely(!capable(CAP_SYS_ADMIN)))
28508+ goto out;
28509+
28510+ err = -EINVAL;
28511+ if (unlikely(count > sizeof(buf)))
28512+ goto out;
28513+
28514+ err = copy_from_user(buf, ubuf, count);
28515+ if (unlikely(err)) {
28516+ err = -EFAULT;
28517+ goto out;
28518+ }
28519+ buf[count] = 0;
28520+
28521+ err = -EINVAL;
28522+ if (!strcmp("clean", buf)) {
28523+ au_procfs_plm_write_clean(file);
28524+ goto out_success;
28525+ } else if (unlikely(strncmp("si=", buf, 3)))
28526+ goto out;
28527+
9dbd164d 28528+ err = kstrtoul(buf + 3, 16, &id);
e49829fe
JR
28529+ if (unlikely(err))
28530+ goto out;
28531+
28532+ err = au_procfs_plm_write_si(file, id);
28533+ if (unlikely(err))
28534+ goto out;
28535+
28536+out_success:
28537+ err = count; /* success */
28538+out:
28539+ return err;
28540+}
28541+
394e211a
AM
28542+static const struct proc_ops au_procfs_plm_op = {
28543+ .proc_write = au_procfs_plm_write,
28544+ .proc_release = au_procfs_plm_release
e49829fe
JR
28545+};
28546+
28547+/* ---------------------------------------------------------------------- */
28548+
28549+static struct proc_dir_entry *au_procfs_dir;
28550+
28551+void au_procfs_fin(void)
28552+{
28553+ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir);
28554+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
28555+}
28556+
28557+int __init au_procfs_init(void)
28558+{
28559+ int err;
28560+ struct proc_dir_entry *entry;
28561+
28562+ err = -ENOMEM;
28563+ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL);
28564+ if (unlikely(!au_procfs_dir))
28565+ goto out;
28566+
cd7a4cd9 28567+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | 0200,
394e211a 28568+ au_procfs_dir, &au_procfs_plm_op);
e49829fe
JR
28569+ if (unlikely(!entry))
28570+ goto out_dir;
28571+
28572+ err = 0;
28573+ goto out; /* success */
28574+
28575+
28576+out_dir:
28577+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
28578+out:
28579+ return err;
28580+}
7f207e10 28581diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
eca34b5c 28582--- /usr/share/empty/fs/aufs/rdu.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 28583+++ linux/fs/aufs/rdu.c 2021-05-02 20:15:14.676670793 +0200
ba1aed25 28584@@ -0,0 +1,384 @@
cd7a4cd9 28585+// SPDX-License-Identifier: GPL-2.0
1308ab2a 28586+/*
d58c55f2 28587+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1308ab2a 28588+ *
28589+ * This program, aufs is free software; you can redistribute it and/or modify
28590+ * it under the terms of the GNU General Public License as published by
28591+ * the Free Software Foundation; either version 2 of the License, or
28592+ * (at your option) any later version.
28593+ *
28594+ * This program is distributed in the hope that it will be useful,
28595+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28596+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28597+ * GNU General Public License for more details.
28598+ *
28599+ * You should have received a copy of the GNU General Public License
523b37e3 28600+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1308ab2a 28601+ */
28602+
28603+/*
28604+ * readdir in userspace.
28605+ */
28606+
b752ccd1 28607+#include <linux/compat.h>
4a4d8108 28608+#include <linux/fs_stack.h>
1308ab2a 28609+#include <linux/security.h>
1308ab2a 28610+#include "aufs.h"
28611+
28612+/* bits for struct aufs_rdu.flags */
28613+#define AuRdu_CALLED 1
28614+#define AuRdu_CONT (1 << 1)
28615+#define AuRdu_FULL (1 << 2)
28616+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
7f207e10
AM
28617+#define au_fset_rdu(flags, name) \
28618+ do { (flags) |= AuRdu_##name; } while (0)
28619+#define au_fclr_rdu(flags, name) \
28620+ do { (flags) &= ~AuRdu_##name; } while (0)
1308ab2a 28621+
28622+struct au_rdu_arg {
392086de 28623+ struct dir_context ctx;
1308ab2a 28624+ struct aufs_rdu *rdu;
28625+ union au_rdu_ent_ul ent;
28626+ unsigned long end;
28627+
28628+ struct super_block *sb;
28629+ int err;
28630+};
28631+
392086de 28632+static int au_rdu_fill(struct dir_context *ctx, const char *name, int nlen,
1308ab2a 28633+ loff_t offset, u64 h_ino, unsigned int d_type)
28634+{
28635+ int err, len;
392086de 28636+ struct au_rdu_arg *arg = container_of(ctx, struct au_rdu_arg, ctx);
1308ab2a 28637+ struct aufs_rdu *rdu = arg->rdu;
28638+ struct au_rdu_ent ent;
28639+
28640+ err = 0;
28641+ arg->err = 0;
28642+ au_fset_rdu(rdu->cookie.flags, CALLED);
28643+ len = au_rdu_len(nlen);
28644+ if (arg->ent.ul + len < arg->end) {
28645+ ent.ino = h_ino;
28646+ ent.bindex = rdu->cookie.bindex;
28647+ ent.type = d_type;
28648+ ent.nlen = nlen;
4a4d8108
AM
28649+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
28650+ ent.type = DT_UNKNOWN;
1308ab2a 28651+
9dbd164d 28652+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 28653+ err = -EFAULT;
28654+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
28655+ goto out;
28656+ if (copy_to_user(arg->ent.e->name, name, nlen))
28657+ goto out;
28658+ /* the terminating NULL */
28659+ if (__put_user(0, arg->ent.e->name + nlen))
28660+ goto out;
28661+ err = 0;
28662+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
28663+ arg->ent.ul += len;
28664+ rdu->rent++;
28665+ } else {
28666+ err = -EFAULT;
28667+ au_fset_rdu(rdu->cookie.flags, FULL);
28668+ rdu->full = 1;
28669+ rdu->tail = arg->ent;
28670+ }
28671+
4f0767ce 28672+out:
1308ab2a 28673+ /* AuTraceErr(err); */
28674+ return err;
28675+}
28676+
28677+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
28678+{
28679+ int err;
28680+ loff_t offset;
28681+ struct au_rdu_cookie *cookie = &arg->rdu->cookie;
28682+
92d182d2 28683+ /* we don't have to care (FMODE_32BITHASH | FMODE_64BITHASH) for ext4 */
1308ab2a 28684+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
28685+ err = offset;
28686+ if (unlikely(offset != cookie->h_pos))
28687+ goto out;
28688+
28689+ err = 0;
28690+ do {
28691+ arg->err = 0;
28692+ au_fclr_rdu(cookie->flags, CALLED);
28693+ /* smp_mb(); */
392086de 28694+ err = vfsub_iterate_dir(h_file, &arg->ctx);
1308ab2a 28695+ if (err >= 0)
28696+ err = arg->err;
28697+ } while (!err
28698+ && au_ftest_rdu(cookie->flags, CALLED)
28699+ && !au_ftest_rdu(cookie->flags, FULL));
28700+ cookie->h_pos = h_file->f_pos;
28701+
4f0767ce 28702+out:
1308ab2a 28703+ AuTraceErr(err);
28704+ return err;
28705+}
28706+
28707+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
28708+{
28709+ int err;
5afbbe0d 28710+ aufs_bindex_t bbot;
392086de
AM
28711+ struct au_rdu_arg arg = {
28712+ .ctx = {
2000de60 28713+ .actor = au_rdu_fill
392086de
AM
28714+ }
28715+ };
1308ab2a 28716+ struct dentry *dentry;
28717+ struct inode *inode;
28718+ struct file *h_file;
28719+ struct au_rdu_cookie *cookie = &rdu->cookie;
28720+
ba1aed25
AM
28721+ /* VERIFY_WRITE */
28722+ err = !access_ok(rdu->ent.e, rdu->sz);
1308ab2a 28723+ if (unlikely(err)) {
28724+ err = -EFAULT;
28725+ AuTraceErr(err);
28726+ goto out;
28727+ }
28728+ rdu->rent = 0;
28729+ rdu->tail = rdu->ent;
28730+ rdu->full = 0;
28731+ arg.rdu = rdu;
28732+ arg.ent = rdu->ent;
28733+ arg.end = arg.ent.ul;
28734+ arg.end += rdu->sz;
28735+
28736+ err = -ENOTDIR;
5afbbe0d 28737+ if (unlikely(!file->f_op->iterate && !file->f_op->iterate_shared))
1308ab2a 28738+ goto out;
28739+
28740+ err = security_file_permission(file, MAY_READ);
28741+ AuTraceErr(err);
28742+ if (unlikely(err))
28743+ goto out;
28744+
2000de60 28745+ dentry = file->f_path.dentry;
5527c038 28746+ inode = d_inode(dentry);
5afbbe0d 28747+ inode_lock_shared(inode);
1308ab2a 28748+
28749+ arg.sb = inode->i_sb;
e49829fe
JR
28750+ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM);
28751+ if (unlikely(err))
28752+ goto out_mtx;
027c5e7a
AM
28753+ err = au_alive_dir(dentry);
28754+ if (unlikely(err))
28755+ goto out_si;
e49829fe 28756+ /* todo: reval? */
1308ab2a 28757+ fi_read_lock(file);
28758+
28759+ err = -EAGAIN;
28760+ if (unlikely(au_ftest_rdu(cookie->flags, CONT)
28761+ && cookie->generation != au_figen(file)))
28762+ goto out_unlock;
28763+
28764+ err = 0;
28765+ if (!rdu->blk) {
28766+ rdu->blk = au_sbi(arg.sb)->si_rdblk;
28767+ if (!rdu->blk)
28768+ rdu->blk = au_dir_size(file, /*dentry*/NULL);
28769+ }
5afbbe0d
AM
28770+ bbot = au_fbtop(file);
28771+ if (cookie->bindex < bbot)
28772+ cookie->bindex = bbot;
28773+ bbot = au_fbbot_dir(file);
28774+ /* AuDbg("b%d, b%d\n", cookie->bindex, bbot); */
28775+ for (; !err && cookie->bindex <= bbot;
1308ab2a 28776+ cookie->bindex++, cookie->h_pos = 0) {
4a4d8108 28777+ h_file = au_hf_dir(file, cookie->bindex);
1308ab2a 28778+ if (!h_file)
28779+ continue;
28780+
28781+ au_fclr_rdu(cookie->flags, FULL);
28782+ err = au_rdu_do(h_file, &arg);
28783+ AuTraceErr(err);
28784+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
28785+ break;
28786+ }
28787+ AuDbg("rent %llu\n", rdu->rent);
28788+
28789+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
28790+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
28791+ au_fset_rdu(cookie->flags, CONT);
28792+ cookie->generation = au_figen(file);
28793+ }
28794+
28795+ ii_read_lock_child(inode);
5afbbe0d 28796+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibtop(inode)));
1308ab2a 28797+ ii_read_unlock(inode);
28798+
4f0767ce 28799+out_unlock:
1308ab2a 28800+ fi_read_unlock(file);
027c5e7a 28801+out_si:
1308ab2a 28802+ si_read_unlock(arg.sb);
4f0767ce 28803+out_mtx:
5afbbe0d 28804+ inode_unlock_shared(inode);
4f0767ce 28805+out:
1308ab2a 28806+ AuTraceErr(err);
28807+ return err;
28808+}
28809+
28810+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
28811+{
28812+ int err;
28813+ ino_t ino;
28814+ unsigned long long nent;
28815+ union au_rdu_ent_ul *u;
28816+ struct au_rdu_ent ent;
28817+ struct super_block *sb;
28818+
28819+ err = 0;
28820+ nent = rdu->nent;
28821+ u = &rdu->ent;
2000de60 28822+ sb = file->f_path.dentry->d_sb;
1308ab2a 28823+ si_read_lock(sb, AuLock_FLUSH);
28824+ while (nent-- > 0) {
9dbd164d 28825+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 28826+ err = copy_from_user(&ent, u->e, sizeof(ent));
4a4d8108 28827+ if (!err)
ba1aed25
AM
28828+ /* VERIFY_WRITE */
28829+ err = !access_ok(&u->e->ino, sizeof(ino));
1308ab2a 28830+ if (unlikely(err)) {
28831+ err = -EFAULT;
28832+ AuTraceErr(err);
28833+ break;
28834+ }
28835+
28836+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
28837+ if (!ent.wh)
28838+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
28839+ else
28840+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
28841+ &ino);
28842+ if (unlikely(err)) {
28843+ AuTraceErr(err);
28844+ break;
28845+ }
28846+
28847+ err = __put_user(ino, &u->e->ino);
28848+ if (unlikely(err)) {
28849+ err = -EFAULT;
28850+ AuTraceErr(err);
28851+ break;
28852+ }
28853+ u->ul += au_rdu_len(ent.nlen);
28854+ }
28855+ si_read_unlock(sb);
28856+
28857+ return err;
28858+}
28859+
28860+/* ---------------------------------------------------------------------- */
28861+
28862+static int au_rdu_verify(struct aufs_rdu *rdu)
28863+{
b752ccd1 28864+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
1308ab2a 28865+ "%llu, b%d, 0x%x, g%u}\n",
b752ccd1 28866+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
1308ab2a 28867+ rdu->blk,
28868+ rdu->rent, rdu->shwh, rdu->full,
28869+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
28870+ rdu->cookie.generation);
dece6358 28871+
b752ccd1 28872+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
1308ab2a 28873+ return 0;
dece6358 28874+
b752ccd1
AM
28875+ AuDbg("%u:%u\n",
28876+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
1308ab2a 28877+ return -EINVAL;
28878+}
28879+
28880+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dece6358 28881+{
1308ab2a 28882+ long err, e;
28883+ struct aufs_rdu rdu;
28884+ void __user *p = (void __user *)arg;
dece6358 28885+
1308ab2a 28886+ err = copy_from_user(&rdu, p, sizeof(rdu));
28887+ if (unlikely(err)) {
28888+ err = -EFAULT;
28889+ AuTraceErr(err);
28890+ goto out;
28891+ }
28892+ err = au_rdu_verify(&rdu);
dece6358
AM
28893+ if (unlikely(err))
28894+ goto out;
28895+
1308ab2a 28896+ switch (cmd) {
28897+ case AUFS_CTL_RDU:
28898+ err = au_rdu(file, &rdu);
28899+ if (unlikely(err))
28900+ break;
dece6358 28901+
1308ab2a 28902+ e = copy_to_user(p, &rdu, sizeof(rdu));
28903+ if (unlikely(e)) {
28904+ err = -EFAULT;
28905+ AuTraceErr(err);
28906+ }
28907+ break;
28908+ case AUFS_CTL_RDU_INO:
28909+ err = au_rdu_ino(file, &rdu);
28910+ break;
28911+
28912+ default:
4a4d8108 28913+ /* err = -ENOTTY; */
1308ab2a 28914+ err = -EINVAL;
28915+ }
dece6358 28916+
4f0767ce 28917+out:
1308ab2a 28918+ AuTraceErr(err);
28919+ return err;
1facf9fc 28920+}
b752ccd1
AM
28921+
28922+#ifdef CONFIG_COMPAT
28923+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
28924+{
28925+ long err, e;
28926+ struct aufs_rdu rdu;
28927+ void __user *p = compat_ptr(arg);
28928+
28929+ /* todo: get_user()? */
28930+ err = copy_from_user(&rdu, p, sizeof(rdu));
28931+ if (unlikely(err)) {
28932+ err = -EFAULT;
28933+ AuTraceErr(err);
28934+ goto out;
28935+ }
28936+ rdu.ent.e = compat_ptr(rdu.ent.ul);
28937+ err = au_rdu_verify(&rdu);
28938+ if (unlikely(err))
28939+ goto out;
28940+
28941+ switch (cmd) {
28942+ case AUFS_CTL_RDU:
28943+ err = au_rdu(file, &rdu);
28944+ if (unlikely(err))
28945+ break;
28946+
28947+ rdu.ent.ul = ptr_to_compat(rdu.ent.e);
28948+ rdu.tail.ul = ptr_to_compat(rdu.tail.e);
28949+ e = copy_to_user(p, &rdu, sizeof(rdu));
28950+ if (unlikely(e)) {
28951+ err = -EFAULT;
28952+ AuTraceErr(err);
28953+ }
28954+ break;
28955+ case AUFS_CTL_RDU_INO:
28956+ err = au_rdu_ino(file, &rdu);
28957+ break;
28958+
28959+ default:
28960+ /* err = -ENOTTY; */
28961+ err = -EINVAL;
28962+ }
28963+
4f0767ce 28964+out:
b752ccd1
AM
28965+ AuTraceErr(err);
28966+ return err;
28967+}
28968+#endif
7f207e10 28969diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
eca34b5c 28970--- /usr/share/empty/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 28971+++ linux/fs/aufs/rwsem.h 2021-05-02 20:15:14.676670793 +0200
42a736d3 28972@@ -0,0 +1,85 @@
062440b3 28973+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 28974+/*
d58c55f2 28975+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 28976+ *
28977+ * This program, aufs is free software; you can redistribute it and/or modify
28978+ * it under the terms of the GNU General Public License as published by
28979+ * the Free Software Foundation; either version 2 of the License, or
28980+ * (at your option) any later version.
dece6358
AM
28981+ *
28982+ * This program is distributed in the hope that it will be useful,
28983+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28984+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28985+ * GNU General Public License for more details.
28986+ *
28987+ * You should have received a copy of the GNU General Public License
523b37e3 28988+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 28989+ */
28990+
28991+/*
28992+ * simple read-write semaphore wrappers
28993+ */
28994+
28995+#ifndef __AUFS_RWSEM_H__
28996+#define __AUFS_RWSEM_H__
28997+
28998+#ifdef __KERNEL__
28999+
4a4d8108 29000+#include "debug.h"
dece6358 29001+
acd2b654 29002+/* in the future, the name 'au_rwsem' will be totally gone */
8b6a4947 29003+#define au_rwsem rw_semaphore
dece6358
AM
29004+
29005+/* to debug easier, do not make them inlined functions */
8b6a4947 29006+#define AuRwMustNoWaiters(rw) AuDebugOn(rwsem_is_contended(rw))
42a736d3
AM
29007+
29008+#ifdef CONFIG_LOCKDEP
dece6358 29009+/* rwsem_is_locked() is unusable */
42a736d3
AM
29010+#define AuRwMustReadLock(rw) AuDebugOn(IS_ENABLED(CONFIG_LOCKDEP) \
29011+ && !lockdep_recursing(current) \
29012+ && debug_locks \
8b6a4947 29013+ && !lockdep_is_held_type(rw, 1))
42a736d3
AM
29014+#define AuRwMustWriteLock(rw) AuDebugOn(IS_ENABLED(CONFIG_LOCKDEP) \
29015+ && !lockdep_recursing(current) \
29016+ && debug_locks \
8b6a4947 29017+ && !lockdep_is_held_type(rw, 0))
42a736d3
AM
29018+#define AuRwMustAnyLock(rw) AuDebugOn(IS_ENABLED(CONFIG_LOCKDEP) \
29019+ && !lockdep_recursing(current) \
29020+ && debug_locks \
8b6a4947 29021+ && !lockdep_is_held(rw))
42a736d3
AM
29022+#define AuRwDestroy(rw) AuDebugOn(IS_ENABLED(CONFIG_LOCKDEP) \
29023+ && !lockdep_recursing(current) \
29024+ && debug_locks \
8b6a4947 29025+ && lockdep_is_held(rw))
42a736d3
AM
29026+#else
29027+#define AuRwMustReadLock(rw) do {} while (0)
29028+#define AuRwMustWriteLock(rw) do {} while (0)
29029+#define AuRwMustAnyLock(rw) do {} while (0)
29030+#define AuRwDestroy(rw) do {} while (0)
29031+#endif
8b6a4947
AM
29032+
29033+#define au_rw_init(rw) init_rwsem(rw)
dece6358 29034+
5afbbe0d
AM
29035+#define au_rw_init_wlock(rw) do { \
29036+ au_rw_init(rw); \
8b6a4947 29037+ down_write(rw); \
5afbbe0d 29038+ } while (0)
dece6358 29039+
8b6a4947
AM
29040+#define au_rw_init_wlock_nested(rw, lsc) do { \
29041+ au_rw_init(rw); \
29042+ down_write_nested(rw, lsc); \
5afbbe0d 29043+ } while (0)
dece6358 29044+
8b6a4947
AM
29045+#define au_rw_read_lock(rw) down_read(rw)
29046+#define au_rw_read_lock_nested(rw, lsc) down_read_nested(rw, lsc)
29047+#define au_rw_read_unlock(rw) up_read(rw)
29048+#define au_rw_dgrade_lock(rw) downgrade_write(rw)
29049+#define au_rw_write_lock(rw) down_write(rw)
29050+#define au_rw_write_lock_nested(rw, lsc) down_write_nested(rw, lsc)
29051+#define au_rw_write_unlock(rw) up_write(rw)
29052+/* why is not _nested version defined? */
29053+#define au_rw_read_trylock(rw) down_read_trylock(rw)
29054+#define au_rw_write_trylock(rw) down_write_trylock(rw)
1facf9fc 29055+
29056+#endif /* __KERNEL__ */
29057+#endif /* __AUFS_RWSEM_H__ */
7f207e10 29058diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
eca34b5c 29059--- /usr/share/empty/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 29060+++ linux/fs/aufs/sbinfo.c 2021-05-02 20:15:14.676670793 +0200
eca801bf 29061@@ -0,0 +1,314 @@
cd7a4cd9 29062+// SPDX-License-Identifier: GPL-2.0
1facf9fc 29063+/*
d58c55f2 29064+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 29065+ *
29066+ * This program, aufs is free software; you can redistribute it and/or modify
29067+ * it under the terms of the GNU General Public License as published by
29068+ * the Free Software Foundation; either version 2 of the License, or
29069+ * (at your option) any later version.
dece6358
AM
29070+ *
29071+ * This program is distributed in the hope that it will be useful,
29072+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29073+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29074+ * GNU General Public License for more details.
29075+ *
29076+ * You should have received a copy of the GNU General Public License
523b37e3 29077+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 29078+ */
29079+
29080+/*
29081+ * superblock private data
29082+ */
29083+
eca801bf 29084+#include <linux/iversion.h>
1facf9fc 29085+#include "aufs.h"
29086+
29087+/*
29088+ * they are necessary regardless sysfs is disabled.
29089+ */
29090+void au_si_free(struct kobject *kobj)
29091+{
86dc4139 29092+ int i;
1facf9fc 29093+ struct au_sbinfo *sbinfo;
b752ccd1 29094+ char *locked __maybe_unused; /* debug only */
1facf9fc 29095+
29096+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
86dc4139 29097+ for (i = 0; i < AuPlink_NHASH; i++)
8b6a4947 29098+ AuDebugOn(!hlist_bl_empty(sbinfo->si_plink + i));
f0c0a007 29099+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
5afbbe0d 29100+
acd2b654
AM
29101+ AuLCntZero(au_lcnt_read(&sbinfo->si_ninodes, /*do_rev*/0));
29102+ au_lcnt_fin(&sbinfo->si_ninodes, /*do_sync*/0);
29103+ AuLCntZero(au_lcnt_read(&sbinfo->si_nfiles, /*do_rev*/0));
29104+ au_lcnt_fin(&sbinfo->si_nfiles, /*do_sync*/0);
1facf9fc 29105+
062440b3 29106+ dbgaufs_si_fin(sbinfo);
e49829fe 29107+ au_rw_write_lock(&sbinfo->si_rwsem);
1facf9fc 29108+ au_br_free(sbinfo);
e49829fe 29109+ au_rw_write_unlock(&sbinfo->si_rwsem);
b752ccd1 29110+
9f237c51 29111+ au_kfree_try_rcu(sbinfo->si_branch);
1facf9fc 29112+ mutex_destroy(&sbinfo->si_xib_mtx);
dece6358 29113+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 29114+
acd2b654
AM
29115+ au_lcnt_wait_for_fin(&sbinfo->si_ninodes);
29116+ /* si_nfiles is waited too */
9f237c51 29117+ au_kfree_rcu(sbinfo);
1facf9fc 29118+}
29119+
29120+int au_si_alloc(struct super_block *sb)
29121+{
86dc4139 29122+ int err, i;
1facf9fc 29123+ struct au_sbinfo *sbinfo;
29124+
29125+ err = -ENOMEM;
4a4d8108 29126+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
1facf9fc 29127+ if (unlikely(!sbinfo))
29128+ goto out;
29129+
29130+ /* will be reallocated separately */
29131+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
29132+ if (unlikely(!sbinfo->si_branch))
febd17d6 29133+ goto out_sbinfo;
1facf9fc 29134+
1facf9fc 29135+ err = sysaufs_si_init(sbinfo);
062440b3
AM
29136+ if (!err) {
29137+ dbgaufs_si_null(sbinfo);
29138+ err = dbgaufs_si_init(sbinfo);
29139+ if (unlikely(err))
29140+ kobject_put(&sbinfo->si_kobj);
29141+ }
1facf9fc 29142+ if (unlikely(err))
29143+ goto out_br;
29144+
29145+ au_nwt_init(&sbinfo->si_nowait);
dece6358 29146+ au_rw_init_wlock(&sbinfo->si_rwsem);
b752ccd1 29147+
acd2b654
AM
29148+ au_lcnt_init(&sbinfo->si_ninodes, /*release*/NULL);
29149+ au_lcnt_init(&sbinfo->si_nfiles, /*release*/NULL);
7f207e10 29150+
5afbbe0d 29151+ sbinfo->si_bbot = -1;
392086de 29152+ sbinfo->si_last_br_id = AUFS_BRANCH_MAX / 2;
1facf9fc 29153+
29154+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
29155+ sbinfo->si_wbr_create = AuWbrCreate_Def;
4a4d8108
AM
29156+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
29157+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
1facf9fc 29158+
076b876e
AM
29159+ au_fhsm_init(sbinfo);
29160+
e49829fe 29161+ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def);
1facf9fc 29162+
392086de
AM
29163+ sbinfo->si_xino_jiffy = jiffies;
29164+ sbinfo->si_xino_expire
29165+ = msecs_to_jiffies(AUFS_XINO_DEF_SEC * MSEC_PER_SEC);
1facf9fc 29166+ mutex_init(&sbinfo->si_xib_mtx);
1facf9fc 29167+ /* leave si_xib_last_pindex and si_xib_next_bit */
29168+
8b6a4947 29169+ INIT_HLIST_BL_HEAD(&sbinfo->si_aopen);
b912730e 29170+
e49829fe 29171+ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC);
1facf9fc 29172+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
29173+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
29174+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
29175+
86dc4139 29176+ for (i = 0; i < AuPlink_NHASH; i++)
8b6a4947 29177+ INIT_HLIST_BL_HEAD(sbinfo->si_plink + i);
1facf9fc 29178+ init_waitqueue_head(&sbinfo->si_plink_wq);
4a4d8108 29179+ spin_lock_init(&sbinfo->si_plink_maint_lock);
1facf9fc 29180+
8b6a4947 29181+ INIT_HLIST_BL_HEAD(&sbinfo->si_files);
523b37e3 29182+
b95c5147
AM
29183+ /* with getattr by default */
29184+ sbinfo->si_iop_array = aufs_iop;
29185+
1facf9fc 29186+ /* leave other members for sysaufs and si_mnt. */
29187+ sbinfo->si_sb = sb;
29188+ sb->s_fs_info = sbinfo;
b752ccd1 29189+ si_pid_set(sb);
1facf9fc 29190+ return 0; /* success */
29191+
4f0767ce 29192+out_br:
9f237c51 29193+ au_kfree_try_rcu(sbinfo->si_branch);
4f0767ce 29194+out_sbinfo:
9f237c51 29195+ au_kfree_rcu(sbinfo);
4f0767ce 29196+out:
1facf9fc 29197+ return err;
29198+}
29199+
e2f27e51 29200+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink)
1facf9fc 29201+{
29202+ int err, sz;
29203+ struct au_branch **brp;
29204+
dece6358
AM
29205+ AuRwMustWriteLock(&sbinfo->si_rwsem);
29206+
1facf9fc 29207+ err = -ENOMEM;
5afbbe0d 29208+ sz = sizeof(*brp) * (sbinfo->si_bbot + 1);
1facf9fc 29209+ if (unlikely(!sz))
29210+ sz = sizeof(*brp);
e2f27e51
AM
29211+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS,
29212+ may_shrink);
1facf9fc 29213+ if (brp) {
29214+ sbinfo->si_branch = brp;
29215+ err = 0;
29216+ }
29217+
29218+ return err;
29219+}
29220+
29221+/* ---------------------------------------------------------------------- */
29222+
29223+unsigned int au_sigen_inc(struct super_block *sb)
29224+{
29225+ unsigned int gen;
5527c038 29226+ struct inode *inode;
1facf9fc 29227+
dece6358
AM
29228+ SiMustWriteLock(sb);
29229+
1facf9fc 29230+ gen = ++au_sbi(sb)->si_generation;
29231+ au_update_digen(sb->s_root);
5527c038
JR
29232+ inode = d_inode(sb->s_root);
29233+ au_update_iigen(inode, /*half*/0);
be118d29 29234+ inode_inc_iversion(inode);
1facf9fc 29235+ return gen;
29236+}
29237+
29238+aufs_bindex_t au_new_br_id(struct super_block *sb)
29239+{
29240+ aufs_bindex_t br_id;
29241+ int i;
29242+ struct au_sbinfo *sbinfo;
29243+
dece6358
AM
29244+ SiMustWriteLock(sb);
29245+
1facf9fc 29246+ sbinfo = au_sbi(sb);
29247+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
29248+ br_id = ++sbinfo->si_last_br_id;
7f207e10 29249+ AuDebugOn(br_id < 0);
1facf9fc 29250+ if (br_id && au_br_index(sb, br_id) < 0)
29251+ return br_id;
29252+ }
29253+
29254+ return -1;
29255+}
29256+
29257+/* ---------------------------------------------------------------------- */
29258+
e49829fe
JR
29259+/* it is ok that new 'nwt' tasks are appended while we are sleeping */
29260+int si_read_lock(struct super_block *sb, int flags)
29261+{
29262+ int err;
29263+
29264+ err = 0;
29265+ if (au_ftest_lock(flags, FLUSH))
29266+ au_nwt_flush(&au_sbi(sb)->si_nowait);
29267+
29268+ si_noflush_read_lock(sb);
29269+ err = au_plink_maint(sb, flags);
29270+ if (unlikely(err))
29271+ si_read_unlock(sb);
29272+
29273+ return err;
29274+}
29275+
29276+int si_write_lock(struct super_block *sb, int flags)
29277+{
29278+ int err;
29279+
29280+ if (au_ftest_lock(flags, FLUSH))
29281+ au_nwt_flush(&au_sbi(sb)->si_nowait);
29282+
29283+ si_noflush_write_lock(sb);
29284+ err = au_plink_maint(sb, flags);
29285+ if (unlikely(err))
29286+ si_write_unlock(sb);
29287+
29288+ return err;
29289+}
29290+
1facf9fc 29291+/* dentry and super_block lock. call at entry point */
e49829fe 29292+int aufs_read_lock(struct dentry *dentry, int flags)
1facf9fc 29293+{
e49829fe 29294+ int err;
027c5e7a 29295+ struct super_block *sb;
e49829fe 29296+
027c5e7a
AM
29297+ sb = dentry->d_sb;
29298+ err = si_read_lock(sb, flags);
29299+ if (unlikely(err))
29300+ goto out;
29301+
29302+ if (au_ftest_lock(flags, DW))
29303+ di_write_lock_child(dentry);
29304+ else
29305+ di_read_lock_child(dentry, flags);
29306+
29307+ if (au_ftest_lock(flags, GEN)) {
29308+ err = au_digen_test(dentry, au_sigen(sb));
79b8bda9
AM
29309+ if (!au_opt_test(au_mntflags(sb), UDBA_NONE))
29310+ AuDebugOn(!err && au_dbrange_test(dentry));
29311+ else if (!err)
29312+ err = au_dbrange_test(dentry);
027c5e7a
AM
29313+ if (unlikely(err))
29314+ aufs_read_unlock(dentry, flags);
e49829fe
JR
29315+ }
29316+
027c5e7a 29317+out:
e49829fe 29318+ return err;
1facf9fc 29319+}
29320+
29321+void aufs_read_unlock(struct dentry *dentry, int flags)
29322+{
29323+ if (au_ftest_lock(flags, DW))
29324+ di_write_unlock(dentry);
29325+ else
29326+ di_read_unlock(dentry, flags);
29327+ si_read_unlock(dentry->d_sb);
29328+}
29329+
29330+void aufs_write_lock(struct dentry *dentry)
29331+{
e49829fe 29332+ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW);
1facf9fc 29333+ di_write_lock_child(dentry);
29334+}
29335+
29336+void aufs_write_unlock(struct dentry *dentry)
29337+{
29338+ di_write_unlock(dentry);
29339+ si_write_unlock(dentry->d_sb);
29340+}
29341+
e49829fe 29342+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
1facf9fc 29343+{
e49829fe 29344+ int err;
027c5e7a
AM
29345+ unsigned int sigen;
29346+ struct super_block *sb;
e49829fe 29347+
027c5e7a
AM
29348+ sb = d1->d_sb;
29349+ err = si_read_lock(sb, flags);
29350+ if (unlikely(err))
29351+ goto out;
29352+
b95c5147 29353+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIRS));
027c5e7a
AM
29354+
29355+ if (au_ftest_lock(flags, GEN)) {
29356+ sigen = au_sigen(sb);
29357+ err = au_digen_test(d1, sigen);
29358+ AuDebugOn(!err && au_dbrange_test(d1));
29359+ if (!err) {
29360+ err = au_digen_test(d2, sigen);
29361+ AuDebugOn(!err && au_dbrange_test(d2));
29362+ }
29363+ if (unlikely(err))
29364+ aufs_read_and_write_unlock2(d1, d2);
29365+ }
29366+
29367+out:
e49829fe 29368+ return err;
1facf9fc 29369+}
29370+
29371+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
29372+{
29373+ di_write_unlock2(d1, d2);
29374+ si_read_unlock(d1->d_sb);
29375+}
7f207e10 29376diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
eca34b5c 29377--- /usr/share/empty/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6
JR
29378+++ linux/fs/aufs/super.c 2021-05-02 20:15:14.676670793 +0200
29379@@ -0,0 +1,1050 @@
cd7a4cd9 29380+// SPDX-License-Identifier: GPL-2.0
1facf9fc 29381+/*
d58c55f2 29382+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 29383+ *
29384+ * This program, aufs is free software; you can redistribute it and/or modify
29385+ * it under the terms of the GNU General Public License as published by
29386+ * the Free Software Foundation; either version 2 of the License, or
29387+ * (at your option) any later version.
dece6358
AM
29388+ *
29389+ * This program is distributed in the hope that it will be useful,
29390+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29391+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29392+ * GNU General Public License for more details.
29393+ *
29394+ * You should have received a copy of the GNU General Public License
523b37e3 29395+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 29396+ */
29397+
29398+/*
29399+ * mount and super_block operations
29400+ */
29401+
eca801bf 29402+#include <linux/iversion.h>
f6c5ef8b 29403+#include <linux/mm.h>
1facf9fc 29404+#include <linux/seq_file.h>
29405+#include <linux/statfs.h>
7f207e10 29406+#include <linux/vmalloc.h>
1facf9fc 29407+#include "aufs.h"
29408+
29409+/*
29410+ * super_operations
29411+ */
29412+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
29413+{
29414+ struct au_icntnr *c;
29415+
29416+ c = au_cache_alloc_icntnr();
29417+ if (c) {
027c5e7a 29418+ au_icntnr_init(c);
be118d29 29419+ inode_set_iversion(&c->vfs_inode, 1); /* sigen(sb); */
1facf9fc 29420+ c->iinfo.ii_hinode = NULL;
29421+ return &c->vfs_inode;
29422+ }
29423+ return NULL;
29424+}
29425+
29426+static void aufs_destroy_inode(struct inode *inode)
29427+{
5afbbe0d
AM
29428+ if (!au_is_bad_inode(inode))
29429+ au_iinfo_fin(inode);
fbc438ed
JR
29430+}
29431+
29432+static void aufs_free_inode(struct inode *inode)
29433+{
29434+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
1facf9fc 29435+}
29436+
29437+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
29438+{
29439+ struct inode *inode;
29440+ int err;
29441+
29442+ inode = iget_locked(sb, ino);
29443+ if (unlikely(!inode)) {
29444+ inode = ERR_PTR(-ENOMEM);
29445+ goto out;
29446+ }
29447+ if (!(inode->i_state & I_NEW))
29448+ goto out;
29449+
29450+ err = au_xigen_new(inode);
29451+ if (!err)
29452+ err = au_iinfo_init(inode);
29453+ if (!err)
be118d29 29454+ inode_inc_iversion(inode);
1facf9fc 29455+ else {
29456+ iget_failed(inode);
29457+ inode = ERR_PTR(err);
29458+ }
29459+
4f0767ce 29460+out:
1facf9fc 29461+ /* never return NULL */
29462+ AuDebugOn(!inode);
29463+ AuTraceErrPtr(inode);
29464+ return inode;
29465+}
29466+
29467+/* lock free root dinfo */
29468+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
29469+{
29470+ int err;
5afbbe0d 29471+ aufs_bindex_t bindex, bbot;
1facf9fc 29472+ struct path path;
4a4d8108 29473+ struct au_hdentry *hdp;
1facf9fc 29474+ struct au_branch *br;
076b876e 29475+ au_br_perm_str_t perm;
1facf9fc 29476+
29477+ err = 0;
5afbbe0d
AM
29478+ bbot = au_sbbot(sb);
29479+ bindex = 0;
29480+ hdp = au_hdentry(au_di(sb->s_root), bindex);
29481+ for (; !err && bindex <= bbot; bindex++, hdp++) {
1facf9fc 29482+ br = au_sbr(sb, bindex);
86dc4139 29483+ path.mnt = au_br_mnt(br);
5afbbe0d 29484+ path.dentry = hdp->hd_dentry;
1facf9fc 29485+ err = au_seq_path(seq, &path);
79b8bda9 29486+ if (!err) {
076b876e 29487+ au_optstr_br_perm(&perm, br->br_perm);
79b8bda9 29488+ seq_printf(seq, "=%s", perm.a);
5afbbe0d 29489+ if (bindex != bbot)
79b8bda9 29490+ seq_putc(seq, ':');
1e00d052 29491+ }
1facf9fc 29492+ }
79b8bda9
AM
29493+ if (unlikely(err || seq_has_overflowed(seq)))
29494+ err = -E2BIG;
1facf9fc 29495+
29496+ return err;
29497+}
29498+
f2c43d5f
AM
29499+static void au_gen_fmt(char *fmt, int len __maybe_unused, const char *pat,
29500+ const char *append)
29501+{
29502+ char *p;
29503+
29504+ p = fmt;
29505+ while (*pat != ':')
29506+ *p++ = *pat++;
29507+ *p++ = *pat++;
29508+ strcpy(p, append);
29509+ AuDebugOn(strlen(fmt) >= len);
29510+}
29511+
1facf9fc 29512+static void au_show_wbr_create(struct seq_file *m, int v,
29513+ struct au_sbinfo *sbinfo)
29514+{
29515+ const char *pat;
f2c43d5f
AM
29516+ char fmt[32];
29517+ struct au_wbr_mfs *mfs;
1facf9fc 29518+
dece6358
AM
29519+ AuRwMustAnyLock(&sbinfo->si_rwsem);
29520+
c2b27bf2 29521+ seq_puts(m, ",create=");
1facf9fc 29522+ pat = au_optstr_wbr_create(v);
f2c43d5f 29523+ mfs = &sbinfo->si_wbr_mfs;
1facf9fc 29524+ switch (v) {
29525+ case AuWbrCreate_TDP:
29526+ case AuWbrCreate_RR:
29527+ case AuWbrCreate_MFS:
29528+ case AuWbrCreate_PMFS:
c2b27bf2 29529+ seq_puts(m, pat);
1facf9fc 29530+ break;
f2c43d5f
AM
29531+ case AuWbrCreate_MFSRR:
29532+ case AuWbrCreate_TDMFS:
29533+ case AuWbrCreate_PMFSRR:
29534+ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu");
29535+ seq_printf(m, fmt, mfs->mfsrr_watermark);
1facf9fc 29536+ break;
f2c43d5f 29537+ case AuWbrCreate_MFSV:
1facf9fc 29538+ case AuWbrCreate_PMFSV:
f2c43d5f
AM
29539+ au_gen_fmt(fmt, sizeof(fmt), pat, "%lu");
29540+ seq_printf(m, fmt,
29541+ jiffies_to_msecs(mfs->mfs_expire)
e49829fe 29542+ / MSEC_PER_SEC);
1facf9fc 29543+ break;
1facf9fc 29544+ case AuWbrCreate_MFSRRV:
f2c43d5f 29545+ case AuWbrCreate_TDMFSV:
392086de 29546+ case AuWbrCreate_PMFSRRV:
f2c43d5f
AM
29547+ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu:%lu");
29548+ seq_printf(m, fmt, mfs->mfsrr_watermark,
29549+ jiffies_to_msecs(mfs->mfs_expire) / MSEC_PER_SEC);
392086de 29550+ break;
f2c43d5f
AM
29551+ default:
29552+ BUG();
1facf9fc 29553+ }
29554+}
29555+
7eafdf33 29556+static int au_show_xino(struct seq_file *seq, struct super_block *sb)
1facf9fc 29557+{
29558+#ifdef CONFIG_SYSFS
29559+ return 0;
29560+#else
29561+ int err;
29562+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
29563+ aufs_bindex_t bindex, brid;
1facf9fc 29564+ struct qstr *name;
29565+ struct file *f;
29566+ struct dentry *d, *h_root;
acd2b654 29567+ struct au_branch *br;
1facf9fc 29568+
dece6358
AM
29569+ AuRwMustAnyLock(&sbinfo->si_rwsem);
29570+
1facf9fc 29571+ err = 0;
1facf9fc 29572+ f = au_sbi(sb)->si_xib;
29573+ if (!f)
29574+ goto out;
29575+
29576+ /* stop printing the default xino path on the first writable branch */
29577+ h_root = NULL;
acd2b654
AM
29578+ bindex = au_xi_root(sb, f->f_path.dentry);
29579+ if (bindex >= 0) {
29580+ br = au_sbr_sb(sb, bindex);
29581+ h_root = au_br_dentry(br);
1facf9fc 29582+ }
acd2b654 29583+
2000de60 29584+ d = f->f_path.dentry;
1facf9fc 29585+ name = &d->d_name;
29586+ /* safe ->d_parent because the file is unlinked */
29587+ if (d->d_parent == h_root
29588+ && name->len == len
29589+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
29590+ goto out;
29591+
29592+ seq_puts(seq, ",xino=");
29593+ err = au_xino_path(seq, f);
29594+
4f0767ce 29595+out:
1facf9fc 29596+ return err;
29597+#endif
29598+}
29599+
29600+/* seq_file will re-call me in case of too long string */
7eafdf33 29601+static int aufs_show_options(struct seq_file *m, struct dentry *dentry)
1facf9fc 29602+{
027c5e7a 29603+ int err;
1facf9fc 29604+ unsigned int mnt_flags, v;
29605+ struct super_block *sb;
29606+ struct au_sbinfo *sbinfo;
29607+
29608+#define AuBool(name, str) do { \
29609+ v = au_opt_test(mnt_flags, name); \
29610+ if (v != au_opt_test(AuOpt_Def, name)) \
29611+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
29612+} while (0)
29613+
29614+#define AuStr(name, str) do { \
29615+ v = mnt_flags & AuOptMask_##name; \
29616+ if (v != (AuOpt_Def & AuOptMask_##name)) \
29617+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
29618+} while (0)
29619+
29620+#define AuUInt(name, str, val) do { \
29621+ if (val != AUFS_##name##_DEF) \
29622+ seq_printf(m, "," #str "=%u", val); \
29623+} while (0)
29624+
7eafdf33 29625+ sb = dentry->d_sb;
2121bcd9 29626+ if (sb->s_flags & SB_POSIXACL)
c1595e42 29627+ seq_puts(m, ",acl");
43982f53 29628+#if 0 /* reserved for future use */
be118d29
JR
29629+ if (sb->s_flags & SB_I_VERSION)
29630+ seq_puts(m, ",i_version");
29631+#endif
c1595e42
JR
29632+
29633+ /* lock free root dinfo */
1facf9fc 29634+ si_noflush_read_lock(sb);
29635+ sbinfo = au_sbi(sb);
29636+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
29637+
29638+ mnt_flags = au_mntflags(sb);
29639+ if (au_opt_test(mnt_flags, XINO)) {
7eafdf33 29640+ err = au_show_xino(m, sb);
1facf9fc 29641+ if (unlikely(err))
29642+ goto out;
29643+ } else
29644+ seq_puts(m, ",noxino");
29645+
29646+ AuBool(TRUNC_XINO, trunc_xino);
29647+ AuStr(UDBA, udba);
dece6358 29648+ AuBool(SHWH, shwh);
1facf9fc 29649+ AuBool(PLINK, plink);
4a4d8108 29650+ AuBool(DIO, dio);
076b876e 29651+ AuBool(DIRPERM1, dirperm1);
1facf9fc 29652+
29653+ v = sbinfo->si_wbr_create;
29654+ if (v != AuWbrCreate_Def)
29655+ au_show_wbr_create(m, v, sbinfo);
29656+
29657+ v = sbinfo->si_wbr_copyup;
29658+ if (v != AuWbrCopyup_Def)
29659+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
29660+
29661+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
29662+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
29663+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
29664+
29665+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
29666+
027c5e7a
AM
29667+ v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC;
29668+ AuUInt(RDCACHE, rdcache, v);
1facf9fc 29669+
29670+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
29671+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
29672+
076b876e
AM
29673+ au_fhsm_show(m, sbinfo);
29674+
8b6a4947 29675+ AuBool(DIRREN, dirren);
1facf9fc 29676+ AuBool(SUM, sum);
29677+ /* AuBool(SUM_W, wsum); */
29678+ AuBool(WARN_PERM, warn_perm);
29679+ AuBool(VERBOSE, verbose);
29680+
4f0767ce 29681+out:
1facf9fc 29682+ /* be sure to print "br:" last */
29683+ if (!sysaufs_brs) {
29684+ seq_puts(m, ",br:");
29685+ au_show_brs(m, sb);
29686+ }
29687+ si_read_unlock(sb);
29688+ return 0;
29689+
1facf9fc 29690+#undef AuBool
29691+#undef AuStr
4a4d8108 29692+#undef AuUInt
1facf9fc 29693+}
29694+
29695+/* ---------------------------------------------------------------------- */
29696+
29697+/* sum mode which returns the summation for statfs(2) */
29698+
29699+static u64 au_add_till_max(u64 a, u64 b)
29700+{
29701+ u64 old;
29702+
29703+ old = a;
29704+ a += b;
92d182d2
AM
29705+ if (old <= a)
29706+ return a;
29707+ return ULLONG_MAX;
29708+}
29709+
29710+static u64 au_mul_till_max(u64 a, long mul)
29711+{
29712+ u64 old;
29713+
29714+ old = a;
29715+ a *= mul;
29716+ if (old <= a)
1facf9fc 29717+ return a;
29718+ return ULLONG_MAX;
29719+}
29720+
29721+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
29722+{
29723+ int err;
92d182d2 29724+ long bsize, factor;
1facf9fc 29725+ u64 blocks, bfree, bavail, files, ffree;
5afbbe0d 29726+ aufs_bindex_t bbot, bindex, i;
1facf9fc 29727+ unsigned char shared;
7f207e10 29728+ struct path h_path;
1facf9fc 29729+ struct super_block *h_sb;
29730+
92d182d2
AM
29731+ err = 0;
29732+ bsize = LONG_MAX;
29733+ files = 0;
29734+ ffree = 0;
1facf9fc 29735+ blocks = 0;
29736+ bfree = 0;
29737+ bavail = 0;
5afbbe0d
AM
29738+ bbot = au_sbbot(sb);
29739+ for (bindex = 0; bindex <= bbot; bindex++) {
7f207e10
AM
29740+ h_path.mnt = au_sbr_mnt(sb, bindex);
29741+ h_sb = h_path.mnt->mnt_sb;
1facf9fc 29742+ shared = 0;
92d182d2 29743+ for (i = 0; !shared && i < bindex; i++)
1facf9fc 29744+ shared = (au_sbr_sb(sb, i) == h_sb);
29745+ if (shared)
29746+ continue;
29747+
29748+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
29749+ h_path.dentry = h_path.mnt->mnt_root;
29750+ err = vfs_statfs(&h_path, buf);
1facf9fc 29751+ if (unlikely(err))
29752+ goto out;
29753+
92d182d2
AM
29754+ if (bsize > buf->f_bsize) {
29755+ /*
29756+ * we will reduce bsize, so we have to expand blocks
29757+ * etc. to match them again
29758+ */
29759+ factor = (bsize / buf->f_bsize);
29760+ blocks = au_mul_till_max(blocks, factor);
29761+ bfree = au_mul_till_max(bfree, factor);
29762+ bavail = au_mul_till_max(bavail, factor);
29763+ bsize = buf->f_bsize;
29764+ }
29765+
29766+ factor = (buf->f_bsize / bsize);
29767+ blocks = au_add_till_max(blocks,
29768+ au_mul_till_max(buf->f_blocks, factor));
29769+ bfree = au_add_till_max(bfree,
29770+ au_mul_till_max(buf->f_bfree, factor));
29771+ bavail = au_add_till_max(bavail,
29772+ au_mul_till_max(buf->f_bavail, factor));
1facf9fc 29773+ files = au_add_till_max(files, buf->f_files);
29774+ ffree = au_add_till_max(ffree, buf->f_ffree);
29775+ }
29776+
92d182d2 29777+ buf->f_bsize = bsize;
1facf9fc 29778+ buf->f_blocks = blocks;
29779+ buf->f_bfree = bfree;
29780+ buf->f_bavail = bavail;
29781+ buf->f_files = files;
29782+ buf->f_ffree = ffree;
92d182d2 29783+ buf->f_frsize = 0;
1facf9fc 29784+
4f0767ce 29785+out:
1facf9fc 29786+ return err;
29787+}
29788+
29789+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
29790+{
29791+ int err;
7f207e10 29792+ struct path h_path;
1facf9fc 29793+ struct super_block *sb;
29794+
29795+ /* lock free root dinfo */
29796+ sb = dentry->d_sb;
29797+ si_noflush_read_lock(sb);
7f207e10 29798+ if (!au_opt_test(au_mntflags(sb), SUM)) {
1facf9fc 29799+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
29800+ h_path.mnt = au_sbr_mnt(sb, 0);
29801+ h_path.dentry = h_path.mnt->mnt_root;
29802+ err = vfs_statfs(&h_path, buf);
29803+ } else
1facf9fc 29804+ err = au_statfs_sum(sb, buf);
29805+ si_read_unlock(sb);
29806+
29807+ if (!err) {
29808+ buf->f_type = AUFS_SUPER_MAGIC;
4a4d8108 29809+ buf->f_namelen = AUFS_MAX_NAMELEN;
1facf9fc 29810+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
29811+ }
29812+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
29813+
29814+ return err;
29815+}
29816+
29817+/* ---------------------------------------------------------------------- */
29818+
537831f9
AM
29819+static int aufs_sync_fs(struct super_block *sb, int wait)
29820+{
29821+ int err, e;
5afbbe0d 29822+ aufs_bindex_t bbot, bindex;
537831f9
AM
29823+ struct au_branch *br;
29824+ struct super_block *h_sb;
29825+
29826+ err = 0;
29827+ si_noflush_read_lock(sb);
5afbbe0d
AM
29828+ bbot = au_sbbot(sb);
29829+ for (bindex = 0; bindex <= bbot; bindex++) {
537831f9
AM
29830+ br = au_sbr(sb, bindex);
29831+ if (!au_br_writable(br->br_perm))
29832+ continue;
29833+
29834+ h_sb = au_sbr_sb(sb, bindex);
a2654f78
AM
29835+ e = vfsub_sync_filesystem(h_sb, wait);
29836+ if (unlikely(e && !err))
29837+ err = e;
29838+ /* go on even if an error happens */
537831f9
AM
29839+ }
29840+ si_read_unlock(sb);
29841+
29842+ return err;
29843+}
29844+
29845+/* ---------------------------------------------------------------------- */
29846+
1facf9fc 29847+/* final actions when unmounting a file system */
29848+static void aufs_put_super(struct super_block *sb)
29849+{
29850+ struct au_sbinfo *sbinfo;
29851+
29852+ sbinfo = au_sbi(sb);
062440b3
AM
29853+ if (sbinfo)
29854+ kobject_put(&sbinfo->si_kobj);
1facf9fc 29855+}
29856+
29857+/* ---------------------------------------------------------------------- */
29858+
79b8bda9
AM
29859+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb,
29860+ struct super_block *sb, void *arg)
7f207e10
AM
29861+{
29862+ void *array;
076b876e 29863+ unsigned long long n, sz;
7f207e10
AM
29864+
29865+ array = NULL;
29866+ n = 0;
29867+ if (!*hint)
29868+ goto out;
29869+
29870+ if (*hint > ULLONG_MAX / sizeof(array)) {
29871+ array = ERR_PTR(-EMFILE);
29872+ pr_err("hint %llu\n", *hint);
29873+ goto out;
29874+ }
29875+
076b876e
AM
29876+ sz = sizeof(array) * *hint;
29877+ array = kzalloc(sz, GFP_NOFS);
7f207e10 29878+ if (unlikely(!array))
076b876e 29879+ array = vzalloc(sz);
7f207e10
AM
29880+ if (unlikely(!array)) {
29881+ array = ERR_PTR(-ENOMEM);
29882+ goto out;
29883+ }
29884+
79b8bda9 29885+ n = cb(sb, array, *hint, arg);
7f207e10
AM
29886+ AuDebugOn(n > *hint);
29887+
29888+out:
29889+ *hint = n;
29890+ return array;
29891+}
29892+
79b8bda9 29893+static unsigned long long au_iarray_cb(struct super_block *sb, void *a,
7f207e10
AM
29894+ unsigned long long max __maybe_unused,
29895+ void *arg)
29896+{
29897+ unsigned long long n;
29898+ struct inode **p, *inode;
29899+ struct list_head *head;
29900+
29901+ n = 0;
29902+ p = a;
29903+ head = arg;
79b8bda9 29904+ spin_lock(&sb->s_inode_list_lock);
7f207e10 29905+ list_for_each_entry(inode, head, i_sb_list) {
5afbbe0d
AM
29906+ if (!au_is_bad_inode(inode)
29907+ && au_ii(inode)->ii_btop >= 0) {
2cbb1c4b
JR
29908+ spin_lock(&inode->i_lock);
29909+ if (atomic_read(&inode->i_count)) {
29910+ au_igrab(inode);
29911+ *p++ = inode;
29912+ n++;
29913+ AuDebugOn(n > max);
29914+ }
29915+ spin_unlock(&inode->i_lock);
7f207e10
AM
29916+ }
29917+ }
79b8bda9 29918+ spin_unlock(&sb->s_inode_list_lock);
7f207e10
AM
29919+
29920+ return n;
29921+}
29922+
29923+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max)
29924+{
acd2b654
AM
29925+ struct au_sbinfo *sbi;
29926+
29927+ sbi = au_sbi(sb);
29928+ *max = au_lcnt_read(&sbi->si_ninodes, /*do_rev*/1);
79b8bda9 29929+ return au_array_alloc(max, au_iarray_cb, sb, &sb->s_inodes);
7f207e10
AM
29930+}
29931+
29932+void au_iarray_free(struct inode **a, unsigned long long max)
29933+{
29934+ unsigned long long ull;
29935+
29936+ for (ull = 0; ull < max; ull++)
29937+ iput(a[ull]);
be52b249 29938+ kvfree(a);
7f207e10
AM
29939+}
29940+
29941+/* ---------------------------------------------------------------------- */
29942+
1facf9fc 29943+/*
29944+ * refresh dentry and inode at remount time.
29945+ */
027c5e7a
AM
29946+/* todo: consolidate with simple_reval_dpath() and au_reval_for_attr() */
29947+static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags,
29948+ struct dentry *parent)
1facf9fc 29949+{
29950+ int err;
1facf9fc 29951+
29952+ di_write_lock_child(dentry);
1facf9fc 29953+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
29954+ err = au_refresh_dentry(dentry, parent);
29955+ if (!err && dir_flags)
5527c038 29956+ au_hn_reset(d_inode(dentry), dir_flags);
1facf9fc 29957+ di_read_unlock(parent, AuLock_IR);
1facf9fc 29958+ di_write_unlock(dentry);
29959+
29960+ return err;
29961+}
29962+
027c5e7a
AM
29963+static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen,
29964+ struct au_sbinfo *sbinfo,
b95c5147 29965+ const unsigned int dir_flags, unsigned int do_idop)
1facf9fc 29966+{
027c5e7a
AM
29967+ int err;
29968+ struct dentry *parent;
027c5e7a
AM
29969+
29970+ err = 0;
29971+ parent = dget_parent(dentry);
29972+ if (!au_digen_test(parent, sigen) && au_digen_test(dentry, sigen)) {
5527c038
JR
29973+ if (d_really_is_positive(dentry)) {
29974+ if (!d_is_dir(dentry))
027c5e7a
AM
29975+ err = au_do_refresh(dentry, /*dir_flags*/0,
29976+ parent);
29977+ else {
29978+ err = au_do_refresh(dentry, dir_flags, parent);
29979+ if (unlikely(err))
29980+ au_fset_si(sbinfo, FAILED_REFRESH_DIR);
29981+ }
29982+ } else
29983+ err = au_do_refresh(dentry, /*dir_flags*/0, parent);
29984+ AuDbgDentry(dentry);
29985+ }
29986+ dput(parent);
29987+
79b8bda9 29988+ if (!err) {
b95c5147 29989+ if (do_idop)
79b8bda9
AM
29990+ au_refresh_dop(dentry, /*force_reval*/0);
29991+ } else
29992+ au_refresh_dop(dentry, /*force_reval*/1);
29993+
027c5e7a
AM
29994+ AuTraceErr(err);
29995+ return err;
1facf9fc 29996+}
29997+
b95c5147 29998+static int au_refresh_d(struct super_block *sb, unsigned int do_idop)
1facf9fc 29999+{
30000+ int err, i, j, ndentry, e;
027c5e7a 30001+ unsigned int sigen;
1facf9fc 30002+ struct au_dcsub_pages dpages;
30003+ struct au_dpage *dpage;
027c5e7a
AM
30004+ struct dentry **dentries, *d;
30005+ struct au_sbinfo *sbinfo;
30006+ struct dentry *root = sb->s_root;
5527c038 30007+ const unsigned int dir_flags = au_hi_flags(d_inode(root), /*isdir*/1);
1facf9fc 30008+
b95c5147 30009+ if (do_idop)
79b8bda9
AM
30010+ au_refresh_dop(root, /*force_reval*/0);
30011+
027c5e7a
AM
30012+ err = au_dpages_init(&dpages, GFP_NOFS);
30013+ if (unlikely(err))
1facf9fc 30014+ goto out;
027c5e7a
AM
30015+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
30016+ if (unlikely(err))
1facf9fc 30017+ goto out_dpages;
1facf9fc 30018+
027c5e7a
AM
30019+ sigen = au_sigen(sb);
30020+ sbinfo = au_sbi(sb);
30021+ for (i = 0; i < dpages.ndpage; i++) {
1facf9fc 30022+ dpage = dpages.dpages + i;
30023+ dentries = dpage->dentries;
30024+ ndentry = dpage->ndentry;
027c5e7a 30025+ for (j = 0; j < ndentry; j++) {
1facf9fc 30026+ d = dentries[j];
79b8bda9 30027+ e = au_do_refresh_d(d, sigen, sbinfo, dir_flags,
b95c5147 30028+ do_idop);
027c5e7a
AM
30029+ if (unlikely(e && !err))
30030+ err = e;
30031+ /* go on even err */
1facf9fc 30032+ }
30033+ }
30034+
4f0767ce 30035+out_dpages:
1facf9fc 30036+ au_dpages_free(&dpages);
4f0767ce 30037+out:
1facf9fc 30038+ return err;
30039+}
30040+
b95c5147 30041+static int au_refresh_i(struct super_block *sb, unsigned int do_idop)
1facf9fc 30042+{
027c5e7a
AM
30043+ int err, e;
30044+ unsigned int sigen;
30045+ unsigned long long max, ull;
30046+ struct inode *inode, **array;
1facf9fc 30047+
027c5e7a
AM
30048+ array = au_iarray_alloc(sb, &max);
30049+ err = PTR_ERR(array);
30050+ if (IS_ERR(array))
30051+ goto out;
1facf9fc 30052+
30053+ err = 0;
027c5e7a
AM
30054+ sigen = au_sigen(sb);
30055+ for (ull = 0; ull < max; ull++) {
30056+ inode = array[ull];
076b876e
AM
30057+ if (unlikely(!inode))
30058+ break;
b95c5147
AM
30059+
30060+ e = 0;
30061+ ii_write_lock_child(inode);
537831f9 30062+ if (au_iigen(inode, NULL) != sigen) {
027c5e7a 30063+ e = au_refresh_hinode_self(inode);
1facf9fc 30064+ if (unlikely(e)) {
b95c5147 30065+ au_refresh_iop(inode, /*force_getattr*/1);
027c5e7a 30066+ pr_err("error %d, i%lu\n", e, inode->i_ino);
1facf9fc 30067+ if (!err)
30068+ err = e;
30069+ /* go on even if err */
30070+ }
30071+ }
b95c5147
AM
30072+ if (!e && do_idop)
30073+ au_refresh_iop(inode, /*force_getattr*/0);
30074+ ii_write_unlock(inode);
1facf9fc 30075+ }
30076+
027c5e7a 30077+ au_iarray_free(array, max);
1facf9fc 30078+
4f0767ce 30079+out:
1facf9fc 30080+ return err;
30081+}
30082+
b95c5147 30083+static void au_remount_refresh(struct super_block *sb, unsigned int do_idop)
1facf9fc 30084+{
027c5e7a
AM
30085+ int err, e;
30086+ unsigned int udba;
5afbbe0d 30087+ aufs_bindex_t bindex, bbot;
1facf9fc 30088+ struct dentry *root;
30089+ struct inode *inode;
027c5e7a 30090+ struct au_branch *br;
79b8bda9 30091+ struct au_sbinfo *sbi;
1facf9fc 30092+
30093+ au_sigen_inc(sb);
79b8bda9
AM
30094+ sbi = au_sbi(sb);
30095+ au_fclr_si(sbi, FAILED_REFRESH_DIR);
1facf9fc 30096+
30097+ root = sb->s_root;
30098+ DiMustNoWaiters(root);
5527c038 30099+ inode = d_inode(root);
1facf9fc 30100+ IiMustNoWaiters(inode);
1facf9fc 30101+
027c5e7a 30102+ udba = au_opt_udba(sb);
5afbbe0d
AM
30103+ bbot = au_sbbot(sb);
30104+ for (bindex = 0; bindex <= bbot; bindex++) {
027c5e7a
AM
30105+ br = au_sbr(sb, bindex);
30106+ err = au_hnotify_reset_br(udba, br, br->br_perm);
1facf9fc 30107+ if (unlikely(err))
027c5e7a
AM
30108+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
30109+ bindex, err);
30110+ /* go on even if err */
1facf9fc 30111+ }
027c5e7a 30112+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
1facf9fc 30113+
b95c5147 30114+ if (do_idop) {
79b8bda9
AM
30115+ if (au_ftest_si(sbi, NO_DREVAL)) {
30116+ AuDebugOn(sb->s_d_op == &aufs_dop_noreval);
30117+ sb->s_d_op = &aufs_dop_noreval;
b95c5147
AM
30118+ AuDebugOn(sbi->si_iop_array == aufs_iop_nogetattr);
30119+ sbi->si_iop_array = aufs_iop_nogetattr;
79b8bda9
AM
30120+ } else {
30121+ AuDebugOn(sb->s_d_op == &aufs_dop);
30122+ sb->s_d_op = &aufs_dop;
b95c5147
AM
30123+ AuDebugOn(sbi->si_iop_array == aufs_iop);
30124+ sbi->si_iop_array = aufs_iop;
79b8bda9 30125+ }
062440b3 30126+ pr_info("reset to %ps and %ps\n",
b95c5147 30127+ sb->s_d_op, sbi->si_iop_array);
79b8bda9
AM
30128+ }
30129+
027c5e7a 30130+ di_write_unlock(root);
b95c5147
AM
30131+ err = au_refresh_d(sb, do_idop);
30132+ e = au_refresh_i(sb, do_idop);
027c5e7a
AM
30133+ if (unlikely(e && !err))
30134+ err = e;
1facf9fc 30135+ /* aufs_write_lock() calls ..._child() */
30136+ di_write_lock_child(root);
027c5e7a
AM
30137+
30138+ au_cpup_attr_all(inode, /*force*/1);
30139+
30140+ if (unlikely(err))
30141+ AuIOErr("refresh failed, ignored, %d\n", err);
1facf9fc 30142+}
30143+
30144+/* stop extra interpretation of errno in mount(8), and strange error messages */
30145+static int cvt_err(int err)
30146+{
30147+ AuTraceErr(err);
30148+
30149+ switch (err) {
30150+ case -ENOENT:
30151+ case -ENOTDIR:
30152+ case -EEXIST:
30153+ case -EIO:
30154+ err = -EINVAL;
30155+ }
30156+ return err;
30157+}
30158+
30159+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
30160+{
4a4d8108
AM
30161+ int err, do_dx;
30162+ unsigned int mntflags;
be52b249
AM
30163+ struct au_opts opts = {
30164+ .opt = NULL
30165+ };
1facf9fc 30166+ struct dentry *root;
30167+ struct inode *inode;
30168+ struct au_sbinfo *sbinfo;
30169+
30170+ err = 0;
30171+ root = sb->s_root;
30172+ if (!data || !*data) {
e49829fe
JR
30173+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
30174+ if (!err) {
30175+ di_write_lock_child(root);
30176+ err = au_opts_verify(sb, *flags, /*pending*/0);
30177+ aufs_write_unlock(root);
30178+ }
1facf9fc 30179+ goto out;
30180+ }
30181+
30182+ err = -ENOMEM;
1facf9fc 30183+ opts.opt = (void *)__get_free_page(GFP_NOFS);
30184+ if (unlikely(!opts.opt))
30185+ goto out;
30186+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
30187+ opts.flags = AuOpts_REMOUNT;
30188+ opts.sb_flags = *flags;
30189+
30190+ /* parse it before aufs lock */
30191+ err = au_opts_parse(sb, data, &opts);
30192+ if (unlikely(err))
30193+ goto out_opts;
30194+
30195+ sbinfo = au_sbi(sb);
5527c038 30196+ inode = d_inode(root);
febd17d6 30197+ inode_lock(inode);
e49829fe
JR
30198+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
30199+ if (unlikely(err))
30200+ goto out_mtx;
30201+ di_write_lock_child(root);
1facf9fc 30202+
30203+ /* au_opts_remount() may return an error */
30204+ err = au_opts_remount(sb, &opts);
30205+ au_opts_free(&opts);
30206+
027c5e7a 30207+ if (au_ftest_opts(opts.flags, REFRESH))
b95c5147 30208+ au_remount_refresh(sb, au_ftest_opts(opts.flags, REFRESH_IDOP));
1facf9fc 30209+
4a4d8108
AM
30210+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
30211+ mntflags = au_mntflags(sb);
30212+ do_dx = !!au_opt_test(mntflags, DIO);
30213+ au_dy_arefresh(do_dx);
30214+ }
30215+
076b876e 30216+ au_fhsm_wrote_all(sb, /*force*/1); /* ?? */
1facf9fc 30217+ aufs_write_unlock(root);
953406b4 30218+
e49829fe 30219+out_mtx:
febd17d6 30220+ inode_unlock(inode);
4f0767ce 30221+out_opts:
1c60b727 30222+ free_page((unsigned long)opts.opt);
4f0767ce 30223+out:
1facf9fc 30224+ err = cvt_err(err);
30225+ AuTraceErr(err);
30226+ return err;
30227+}
30228+
4a4d8108 30229+static const struct super_operations aufs_sop = {
1facf9fc 30230+ .alloc_inode = aufs_alloc_inode,
30231+ .destroy_inode = aufs_destroy_inode,
fbc438ed 30232+ .free_inode = aufs_free_inode,
b752ccd1 30233+ /* always deleting, no clearing */
1facf9fc 30234+ .drop_inode = generic_delete_inode,
30235+ .show_options = aufs_show_options,
30236+ .statfs = aufs_statfs,
30237+ .put_super = aufs_put_super,
537831f9 30238+ .sync_fs = aufs_sync_fs,
1facf9fc 30239+ .remount_fs = aufs_remount_fs
30240+};
30241+
30242+/* ---------------------------------------------------------------------- */
30243+
30244+static int alloc_root(struct super_block *sb)
30245+{
30246+ int err;
30247+ struct inode *inode;
30248+ struct dentry *root;
30249+
30250+ err = -ENOMEM;
30251+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
30252+ err = PTR_ERR(inode);
30253+ if (IS_ERR(inode))
30254+ goto out;
30255+
b95c5147 30256+ inode->i_op = aufs_iop + AuIop_DIR; /* with getattr by default */
1facf9fc 30257+ inode->i_fop = &aufs_dir_fop;
30258+ inode->i_mode = S_IFDIR;
9dbd164d 30259+ set_nlink(inode, 2);
1facf9fc 30260+ unlock_new_inode(inode);
30261+
92d182d2 30262+ root = d_make_root(inode);
1facf9fc 30263+ if (unlikely(!root))
92d182d2 30264+ goto out;
1facf9fc 30265+ err = PTR_ERR(root);
30266+ if (IS_ERR(root))
92d182d2 30267+ goto out;
1facf9fc 30268+
4a4d8108 30269+ err = au_di_init(root);
1facf9fc 30270+ if (!err) {
30271+ sb->s_root = root;
30272+ return 0; /* success */
30273+ }
30274+ dput(root);
1facf9fc 30275+
4f0767ce 30276+out:
1facf9fc 30277+ return err;
1facf9fc 30278+}
30279+
30280+static int aufs_fill_super(struct super_block *sb, void *raw_data,
30281+ int silent __maybe_unused)
30282+{
30283+ int err;
be52b249
AM
30284+ struct au_opts opts = {
30285+ .opt = NULL
30286+ };
79b8bda9 30287+ struct au_sbinfo *sbinfo;
1facf9fc 30288+ struct dentry *root;
30289+ struct inode *inode;
30290+ char *arg = raw_data;
30291+
30292+ if (unlikely(!arg || !*arg)) {
30293+ err = -EINVAL;
4a4d8108 30294+ pr_err("no arg\n");
1facf9fc 30295+ goto out;
30296+ }
30297+
30298+ err = -ENOMEM;
1facf9fc 30299+ opts.opt = (void *)__get_free_page(GFP_NOFS);
30300+ if (unlikely(!opts.opt))
30301+ goto out;
30302+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
30303+ opts.sb_flags = sb->s_flags;
30304+
30305+ err = au_si_alloc(sb);
30306+ if (unlikely(err))
30307+ goto out_opts;
79b8bda9 30308+ sbinfo = au_sbi(sb);
1facf9fc 30309+
30310+ /* all timestamps always follow the ones on the branch */
2121bcd9 30311+ sb->s_flags |= SB_NOATIME | SB_NODIRATIME;
be118d29 30312+ sb->s_flags |= SB_I_VERSION; /* do we really need this? */
1facf9fc 30313+ sb->s_op = &aufs_sop;
027c5e7a 30314+ sb->s_d_op = &aufs_dop;
1facf9fc 30315+ sb->s_magic = AUFS_SUPER_MAGIC;
30316+ sb->s_maxbytes = 0;
c1595e42 30317+ sb->s_stack_depth = 1;
1facf9fc 30318+ au_export_init(sb);
f2c43d5f 30319+ au_xattr_init(sb);
1facf9fc 30320+
30321+ err = alloc_root(sb);
30322+ if (unlikely(err)) {
30323+ si_write_unlock(sb);
30324+ goto out_info;
30325+ }
30326+ root = sb->s_root;
5527c038 30327+ inode = d_inode(root);
1facf9fc 30328+
30329+ /*
30330+ * actually we can parse options regardless aufs lock here.
30331+ * but at remount time, parsing must be done before aufs lock.
30332+ * so we follow the same rule.
30333+ */
30334+ ii_write_lock_parent(inode);
30335+ aufs_write_unlock(root);
30336+ err = au_opts_parse(sb, arg, &opts);
30337+ if (unlikely(err))
30338+ goto out_root;
30339+
30340+ /* lock vfs_inode first, then aufs. */
febd17d6 30341+ inode_lock(inode);
1facf9fc 30342+ aufs_write_lock(root);
30343+ err = au_opts_mount(sb, &opts);
30344+ au_opts_free(&opts);
79b8bda9
AM
30345+ if (!err && au_ftest_si(sbinfo, NO_DREVAL)) {
30346+ sb->s_d_op = &aufs_dop_noreval;
062440b3 30347+ pr_info("%ps\n", sb->s_d_op);
79b8bda9 30348+ au_refresh_dop(root, /*force_reval*/0);
b95c5147
AM
30349+ sbinfo->si_iop_array = aufs_iop_nogetattr;
30350+ au_refresh_iop(inode, /*force_getattr*/0);
79b8bda9 30351+ }
1facf9fc 30352+ aufs_write_unlock(root);
febd17d6 30353+ inode_unlock(inode);
4a4d8108
AM
30354+ if (!err)
30355+ goto out_opts; /* success */
1facf9fc 30356+
4f0767ce 30357+out_root:
1facf9fc 30358+ dput(root);
30359+ sb->s_root = NULL;
4f0767ce 30360+out_info:
79b8bda9 30361+ kobject_put(&sbinfo->si_kobj);
1facf9fc 30362+ sb->s_fs_info = NULL;
4f0767ce 30363+out_opts:
1c60b727 30364+ free_page((unsigned long)opts.opt);
4f0767ce 30365+out:
1facf9fc 30366+ AuTraceErr(err);
30367+ err = cvt_err(err);
30368+ AuTraceErr(err);
30369+ return err;
30370+}
30371+
30372+/* ---------------------------------------------------------------------- */
30373+
027c5e7a
AM
30374+static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags,
30375+ const char *dev_name __maybe_unused,
30376+ void *raw_data)
1facf9fc 30377+{
027c5e7a 30378+ struct dentry *root;
1facf9fc 30379+
30380+ /* all timestamps always follow the ones on the branch */
30381+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
027c5e7a
AM
30382+ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super);
30383+ if (IS_ERR(root))
30384+ goto out;
30385+
062440b3 30386+ au_sbilist_add(root->d_sb);
027c5e7a
AM
30387+
30388+out:
30389+ return root;
1facf9fc 30390+}
30391+
e49829fe
JR
30392+static void aufs_kill_sb(struct super_block *sb)
30393+{
30394+ struct au_sbinfo *sbinfo;
30395+
30396+ sbinfo = au_sbi(sb);
30397+ if (sbinfo) {
30398+ au_sbilist_del(sb);
30399+ aufs_write_lock(sb->s_root);
076b876e 30400+ au_fhsm_fin(sb);
e49829fe
JR
30401+ if (sbinfo->si_wbr_create_ops->fin)
30402+ sbinfo->si_wbr_create_ops->fin(sb);
30403+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
30404+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
b95c5147 30405+ au_remount_refresh(sb, /*do_idop*/0);
e49829fe
JR
30406+ }
30407+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
30408+ au_plink_put(sb, /*verbose*/1);
30409+ au_xino_clr(sb);
8b6a4947 30410+ au_dr_opt_flush(sb);
1e00d052 30411+ sbinfo->si_sb = NULL;
e49829fe 30412+ aufs_write_unlock(sb->s_root);
e49829fe
JR
30413+ au_nwt_flush(&sbinfo->si_nowait);
30414+ }
98d9a5b1 30415+ kill_anon_super(sb);
e49829fe
JR
30416+}
30417+
1facf9fc 30418+struct file_system_type aufs_fs_type = {
30419+ .name = AUFS_FSTYPE,
c06a8ce3 30420+ /* a race between rename and others */
0b2a12c6
JR
30421+ .fs_flags = FS_RENAME_DOES_D_MOVE
30422+ /* untested */
30423+ /*| FS_ALLOW_IDMAP*/
30424+ ,
027c5e7a 30425+ .mount = aufs_mount,
e49829fe 30426+ .kill_sb = aufs_kill_sb,
1facf9fc 30427+ /* no need to __module_get() and module_put(). */
30428+ .owner = THIS_MODULE,
30429+};
7f207e10 30430diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
eca34b5c 30431--- /usr/share/empty/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 30432+++ linux/fs/aufs/super.h 2021-05-02 20:15:14.676670793 +0200
e37dd06a 30433@@ -0,0 +1,587 @@
062440b3 30434+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 30435+/*
d58c55f2 30436+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 30437+ *
30438+ * This program, aufs is free software; you can redistribute it and/or modify
30439+ * it under the terms of the GNU General Public License as published by
30440+ * the Free Software Foundation; either version 2 of the License, or
30441+ * (at your option) any later version.
dece6358
AM
30442+ *
30443+ * This program is distributed in the hope that it will be useful,
30444+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
30445+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30446+ * GNU General Public License for more details.
30447+ *
30448+ * You should have received a copy of the GNU General Public License
523b37e3 30449+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 30450+ */
30451+
30452+/*
30453+ * super_block operations
30454+ */
30455+
30456+#ifndef __AUFS_SUPER_H__
30457+#define __AUFS_SUPER_H__
30458+
30459+#ifdef __KERNEL__
30460+
30461+#include <linux/fs.h>
5527c038 30462+#include <linux/kobject.h>
8b6a4947 30463+#include "hbl.h"
acd2b654 30464+#include "lcnt.h"
1facf9fc 30465+#include "rwsem.h"
1facf9fc 30466+#include "wkq.h"
30467+
1facf9fc 30468+/* policies to select one among multiple writable branches */
30469+struct au_wbr_copyup_operations {
30470+ int (*copyup)(struct dentry *dentry);
30471+};
30472+
392086de
AM
30473+#define AuWbr_DIR 1 /* target is a dir */
30474+#define AuWbr_PARENT (1 << 1) /* always require a parent */
30475+
30476+#define au_ftest_wbr(flags, name) ((flags) & AuWbr_##name)
30477+#define au_fset_wbr(flags, name) { (flags) |= AuWbr_##name; }
30478+#define au_fclr_wbr(flags, name) { (flags) &= ~AuWbr_##name; }
30479+
1facf9fc 30480+struct au_wbr_create_operations {
392086de 30481+ int (*create)(struct dentry *dentry, unsigned int flags);
1facf9fc 30482+ int (*init)(struct super_block *sb);
30483+ int (*fin)(struct super_block *sb);
30484+};
30485+
30486+struct au_wbr_mfs {
30487+ struct mutex mfs_lock; /* protect this structure */
30488+ unsigned long mfs_jiffy;
30489+ unsigned long mfs_expire;
30490+ aufs_bindex_t mfs_bindex;
30491+
30492+ unsigned long long mfsrr_bytes;
30493+ unsigned long long mfsrr_watermark;
30494+};
30495+
86dc4139
AM
30496+#define AuPlink_NHASH 100
30497+static inline int au_plink_hash(ino_t ino)
30498+{
30499+ return ino % AuPlink_NHASH;
30500+}
30501+
076b876e
AM
30502+/* File-based Hierarchical Storage Management */
30503+struct au_fhsm {
30504+#ifdef CONFIG_AUFS_FHSM
30505+ /* allow only one process who can receive the notification */
30506+ spinlock_t fhsm_spin;
30507+ pid_t fhsm_pid;
30508+ wait_queue_head_t fhsm_wqh;
30509+ atomic_t fhsm_readable;
30510+
c1595e42 30511+ /* these are protected by si_rwsem */
076b876e 30512+ unsigned long fhsm_expire;
c1595e42 30513+ aufs_bindex_t fhsm_bottom;
076b876e
AM
30514+#endif
30515+};
30516+
1facf9fc 30517+struct au_branch;
30518+struct au_sbinfo {
30519+ /* nowait tasks in the system-wide workqueue */
30520+ struct au_nowait_tasks si_nowait;
30521+
b752ccd1 30522+ /*
acd2b654 30523+ * tried sb->s_umount, but failed due to the dependency between i_mutex.
b752ccd1
AM
30524+ * rwsem for au_sbinfo is necessary.
30525+ */
dece6358 30526+ struct au_rwsem si_rwsem;
1facf9fc 30527+
7f207e10 30528+ /*
523b37e3
AM
30529+ * dirty approach to protect sb->sb_inodes and ->s_files (gone) from
30530+ * remount.
7f207e10 30531+ */
acd2b654 30532+ au_lcnt_t si_ninodes, si_nfiles;
7f207e10 30533+
1facf9fc 30534+ /* branch management */
30535+ unsigned int si_generation;
30536+
2000de60 30537+ /* see AuSi_ flags */
1facf9fc 30538+ unsigned char au_si_status;
30539+
5afbbe0d 30540+ aufs_bindex_t si_bbot;
7f207e10
AM
30541+
30542+ /* dirty trick to keep br_id plus */
30543+ unsigned int si_last_br_id :
30544+ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1;
1facf9fc 30545+ struct au_branch **si_branch;
30546+
30547+ /* policy to select a writable branch */
30548+ unsigned char si_wbr_copyup;
30549+ unsigned char si_wbr_create;
30550+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
30551+ struct au_wbr_create_operations *si_wbr_create_ops;
30552+
30553+ /* round robin */
30554+ atomic_t si_wbr_rr_next;
30555+
30556+ /* most free space */
30557+ struct au_wbr_mfs si_wbr_mfs;
30558+
076b876e
AM
30559+ /* File-based Hierarchical Storage Management */
30560+ struct au_fhsm si_fhsm;
30561+
1facf9fc 30562+ /* mount flags */
30563+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
30564+ unsigned int si_mntflags;
30565+
30566+ /* external inode number (bitmap and translation table) */
acd2b654
AM
30567+ loff_t si_ximaxent; /* max entries in a xino */
30568+
1facf9fc 30569+ struct file *si_xib;
30570+ struct mutex si_xib_mtx; /* protect xib members */
30571+ unsigned long *si_xib_buf;
30572+ unsigned long si_xib_last_pindex;
30573+ int si_xib_next_bit;
acd2b654 30574+
392086de
AM
30575+ unsigned long si_xino_jiffy;
30576+ unsigned long si_xino_expire;
1facf9fc 30577+ /* reserved for future use */
30578+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
30579+
30580+#ifdef CONFIG_AUFS_EXPORT
30581+ /* i_generation */
acd2b654 30582+ /* todo: make xigen file an array to support many inode numbers */
1facf9fc 30583+ struct file *si_xigen;
30584+ atomic_t si_xigen_next;
30585+#endif
30586+
acd2b654 30587+ /* dirty trick to support atomic_open */
8b6a4947 30588+ struct hlist_bl_head si_aopen;
b912730e 30589+
1facf9fc 30590+ /* vdir parameters */
e49829fe 30591+ unsigned long si_rdcache; /* max cache time in jiffies */
1facf9fc 30592+ unsigned int si_rdblk; /* deblk size */
30593+ unsigned int si_rdhash; /* hash size */
30594+
30595+ /*
30596+ * If the number of whiteouts are larger than si_dirwh, leave all of
30597+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
30598+ * future fsck.aufs or kernel thread will remove them later.
30599+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
30600+ */
30601+ unsigned int si_dirwh;
30602+
1facf9fc 30603+ /* pseudo_link list */
8b6a4947 30604+ struct hlist_bl_head si_plink[AuPlink_NHASH];
1facf9fc 30605+ wait_queue_head_t si_plink_wq;
4a4d8108 30606+ spinlock_t si_plink_maint_lock;
e49829fe 30607+ pid_t si_plink_maint_pid;
1facf9fc 30608+
523b37e3 30609+ /* file list */
8b6a4947 30610+ struct hlist_bl_head si_files;
523b37e3 30611+
b95c5147 30612+ /* with/without getattr, brother of sb->s_d_op */
43982f53 30613+ const struct inode_operations *si_iop_array;
b95c5147 30614+
1facf9fc 30615+ /*
30616+ * sysfs and lifetime management.
30617+ * this is not a small structure and it may be a waste of memory in case
acd2b654 30618+ * of sysfs is disabled, particularly when many aufs-es are mounted.
1facf9fc 30619+ * but using sysfs is majority.
30620+ */
30621+ struct kobject si_kobj;
30622+#ifdef CONFIG_DEBUG_FS
86dc4139
AM
30623+ struct dentry *si_dbgaufs;
30624+ struct dentry *si_dbgaufs_plink;
30625+ struct dentry *si_dbgaufs_xib;
1facf9fc 30626+#ifdef CONFIG_AUFS_EXPORT
30627+ struct dentry *si_dbgaufs_xigen;
30628+#endif
30629+#endif
30630+
e49829fe 30631+#ifdef CONFIG_AUFS_SBILIST
8b6a4947 30632+ struct hlist_bl_node si_list;
e49829fe
JR
30633+#endif
30634+
1facf9fc 30635+ /* dirty, necessary for unmounting, sysfs and sysrq */
30636+ struct super_block *si_sb;
30637+};
30638+
dece6358
AM
30639+/* sbinfo status flags */
30640+/*
30641+ * set true when refresh_dirs() failed at remount time.
30642+ * then try refreshing dirs at access time again.
062440b3 30643+ * if it is false, refreshing dirs at access time is unnecessary
dece6358 30644+ */
027c5e7a 30645+#define AuSi_FAILED_REFRESH_DIR 1
076b876e 30646+#define AuSi_FHSM (1 << 1) /* fhsm is active now */
79b8bda9 30647+#define AuSi_NO_DREVAL (1 << 2) /* disable all d_revalidate */
076b876e
AM
30648+
30649+#ifndef CONFIG_AUFS_FHSM
30650+#undef AuSi_FHSM
30651+#define AuSi_FHSM 0
30652+#endif
30653+
dece6358
AM
30654+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
30655+ unsigned int flag)
30656+{
30657+ AuRwMustAnyLock(&sbi->si_rwsem);
30658+ return sbi->au_si_status & flag;
30659+}
30660+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
30661+#define au_fset_si(sbinfo, name) do { \
30662+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
30663+ (sbinfo)->au_si_status |= AuSi_##name; \
30664+} while (0)
30665+#define au_fclr_si(sbinfo, name) do { \
30666+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
30667+ (sbinfo)->au_si_status &= ~AuSi_##name; \
30668+} while (0)
30669+
1facf9fc 30670+/* ---------------------------------------------------------------------- */
30671+
30672+/* policy to select one among writable branches */
4a4d8108
AM
30673+#define AuWbrCopyup(sbinfo, ...) \
30674+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
30675+#define AuWbrCreate(sbinfo, ...) \
30676+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
1facf9fc 30677+
30678+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
30679+#define AuLock_DW 1 /* write-lock dentry */
30680+#define AuLock_IR (1 << 1) /* read-lock inode */
30681+#define AuLock_IW (1 << 2) /* write-lock inode */
30682+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
b95c5147 30683+#define AuLock_DIRS (1 << 4) /* target is a pair of dirs */
f2c43d5f 30684+ /* except RENAME_EXCHANGE */
e49829fe
JR
30685+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */
30686+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */
027c5e7a 30687+#define AuLock_GEN (1 << 7) /* test digen/iigen */
1facf9fc 30688+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
7f207e10
AM
30689+#define au_fset_lock(flags, name) \
30690+ do { (flags) |= AuLock_##name; } while (0)
30691+#define au_fclr_lock(flags, name) \
30692+ do { (flags) &= ~AuLock_##name; } while (0)
1facf9fc 30693+
30694+/* ---------------------------------------------------------------------- */
30695+
30696+/* super.c */
30697+extern struct file_system_type aufs_fs_type;
30698+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
79b8bda9
AM
30699+typedef unsigned long long (*au_arraycb_t)(struct super_block *sb, void *array,
30700+ unsigned long long max, void *arg);
79b8bda9
AM
30701+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb,
30702+ struct super_block *sb, void *arg);
7f207e10
AM
30703+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max);
30704+void au_iarray_free(struct inode **a, unsigned long long max);
1facf9fc 30705+
30706+/* sbinfo.c */
30707+void au_si_free(struct kobject *kobj);
30708+int au_si_alloc(struct super_block *sb);
e2f27e51 30709+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink);
1facf9fc 30710+
30711+unsigned int au_sigen_inc(struct super_block *sb);
30712+aufs_bindex_t au_new_br_id(struct super_block *sb);
30713+
e49829fe
JR
30714+int si_read_lock(struct super_block *sb, int flags);
30715+int si_write_lock(struct super_block *sb, int flags);
30716+int aufs_read_lock(struct dentry *dentry, int flags);
1facf9fc 30717+void aufs_read_unlock(struct dentry *dentry, int flags);
30718+void aufs_write_lock(struct dentry *dentry);
30719+void aufs_write_unlock(struct dentry *dentry);
e49829fe 30720+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags);
1facf9fc 30721+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
30722+
30723+/* wbr_policy.c */
30724+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
30725+extern struct au_wbr_create_operations au_wbr_create_ops[];
30726+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
c2b27bf2 30727+int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex);
5afbbe0d 30728+int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop);
c2b27bf2
AM
30729+
30730+/* mvdown.c */
30731+int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *arg);
1facf9fc 30732+
076b876e
AM
30733+#ifdef CONFIG_AUFS_FHSM
30734+/* fhsm.c */
30735+
30736+static inline pid_t au_fhsm_pid(struct au_fhsm *fhsm)
30737+{
30738+ pid_t pid;
30739+
30740+ spin_lock(&fhsm->fhsm_spin);
30741+ pid = fhsm->fhsm_pid;
30742+ spin_unlock(&fhsm->fhsm_spin);
30743+
30744+ return pid;
30745+}
30746+
30747+void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force);
30748+void au_fhsm_wrote_all(struct super_block *sb, int force);
30749+int au_fhsm_fd(struct super_block *sb, int oflags);
30750+int au_fhsm_br_alloc(struct au_branch *br);
c1595e42 30751+void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex);
076b876e
AM
30752+void au_fhsm_fin(struct super_block *sb);
30753+void au_fhsm_init(struct au_sbinfo *sbinfo);
30754+void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec);
30755+void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo);
30756+#else
30757+AuStubVoid(au_fhsm_wrote, struct super_block *sb, aufs_bindex_t bindex,
30758+ int force)
30759+AuStubVoid(au_fhsm_wrote_all, struct super_block *sb, int force)
30760+AuStub(int, au_fhsm_fd, return -EOPNOTSUPP, struct super_block *sb, int oflags)
c1595e42
JR
30761+AuStub(pid_t, au_fhsm_pid, return 0, struct au_fhsm *fhsm)
30762+AuStubInt0(au_fhsm_br_alloc, struct au_branch *br)
30763+AuStubVoid(au_fhsm_set_bottom, struct super_block *sb, aufs_bindex_t bindex)
076b876e
AM
30764+AuStubVoid(au_fhsm_fin, struct super_block *sb)
30765+AuStubVoid(au_fhsm_init, struct au_sbinfo *sbinfo)
30766+AuStubVoid(au_fhsm_set, struct au_sbinfo *sbinfo, unsigned int sec)
30767+AuStubVoid(au_fhsm_show, struct seq_file *seq, struct au_sbinfo *sbinfo)
30768+#endif
30769+
1facf9fc 30770+/* ---------------------------------------------------------------------- */
30771+
30772+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
30773+{
30774+ return sb->s_fs_info;
30775+}
30776+
30777+/* ---------------------------------------------------------------------- */
30778+
30779+#ifdef CONFIG_AUFS_EXPORT
a2a7ad62 30780+int au_test_nfsd(void);
1facf9fc 30781+void au_export_init(struct super_block *sb);
b752ccd1 30782+void au_xigen_inc(struct inode *inode);
1facf9fc 30783+int au_xigen_new(struct inode *inode);
062440b3 30784+int au_xigen_set(struct super_block *sb, struct path *path);
1facf9fc 30785+void au_xigen_clr(struct super_block *sb);
30786+
30787+static inline int au_busy_or_stale(void)
30788+{
b752ccd1 30789+ if (!au_test_nfsd())
1facf9fc 30790+ return -EBUSY;
30791+ return -ESTALE;
30792+}
30793+#else
b752ccd1 30794+AuStubInt0(au_test_nfsd, void)
a2a7ad62 30795+AuStubVoid(au_export_init, struct super_block *sb)
b752ccd1 30796+AuStubVoid(au_xigen_inc, struct inode *inode)
4a4d8108 30797+AuStubInt0(au_xigen_new, struct inode *inode)
062440b3 30798+AuStubInt0(au_xigen_set, struct super_block *sb, struct path *path)
4a4d8108 30799+AuStubVoid(au_xigen_clr, struct super_block *sb)
c1595e42 30800+AuStub(int, au_busy_or_stale, return -EBUSY, void)
1facf9fc 30801+#endif /* CONFIG_AUFS_EXPORT */
30802+
30803+/* ---------------------------------------------------------------------- */
30804+
e49829fe
JR
30805+#ifdef CONFIG_AUFS_SBILIST
30806+/* module.c */
8b6a4947 30807+extern struct hlist_bl_head au_sbilist;
e49829fe
JR
30808+
30809+static inline void au_sbilist_init(void)
30810+{
8b6a4947 30811+ INIT_HLIST_BL_HEAD(&au_sbilist);
e49829fe
JR
30812+}
30813+
30814+static inline void au_sbilist_add(struct super_block *sb)
30815+{
8b6a4947 30816+ au_hbl_add(&au_sbi(sb)->si_list, &au_sbilist);
e49829fe
JR
30817+}
30818+
30819+static inline void au_sbilist_del(struct super_block *sb)
30820+{
8b6a4947 30821+ au_hbl_del(&au_sbi(sb)->si_list, &au_sbilist);
e49829fe 30822+}
53392da6
AM
30823+
30824+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
30825+static inline void au_sbilist_lock(void)
30826+{
8b6a4947 30827+ hlist_bl_lock(&au_sbilist);
53392da6
AM
30828+}
30829+
30830+static inline void au_sbilist_unlock(void)
30831+{
8b6a4947 30832+ hlist_bl_unlock(&au_sbilist);
53392da6
AM
30833+}
30834+#define AuGFP_SBILIST GFP_ATOMIC
30835+#else
30836+AuStubVoid(au_sbilist_lock, void)
30837+AuStubVoid(au_sbilist_unlock, void)
30838+#define AuGFP_SBILIST GFP_NOFS
30839+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
e49829fe
JR
30840+#else
30841+AuStubVoid(au_sbilist_init, void)
c1595e42
JR
30842+AuStubVoid(au_sbilist_add, struct super_block *sb)
30843+AuStubVoid(au_sbilist_del, struct super_block *sb)
53392da6
AM
30844+AuStubVoid(au_sbilist_lock, void)
30845+AuStubVoid(au_sbilist_unlock, void)
30846+#define AuGFP_SBILIST GFP_NOFS
e49829fe
JR
30847+#endif
30848+
30849+/* ---------------------------------------------------------------------- */
30850+
1facf9fc 30851+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
30852+{
dece6358 30853+ /*
c1595e42 30854+ * This function is a dynamic '__init' function actually,
dece6358
AM
30855+ * so the tiny check for si_rwsem is unnecessary.
30856+ */
30857+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 30858+#ifdef CONFIG_DEBUG_FS
30859+ sbinfo->si_dbgaufs = NULL;
86dc4139 30860+ sbinfo->si_dbgaufs_plink = NULL;
1facf9fc 30861+ sbinfo->si_dbgaufs_xib = NULL;
30862+#ifdef CONFIG_AUFS_EXPORT
30863+ sbinfo->si_dbgaufs_xigen = NULL;
30864+#endif
30865+#endif
30866+}
30867+
30868+/* ---------------------------------------------------------------------- */
30869+
a2654f78
AM
30870+/* current->atomic_flags */
30871+/* this value should never corrupt the ones defined in linux/sched.h */
fbc438ed 30872+#define PFA_AUFS 0x10
a2654f78
AM
30873+
30874+TASK_PFA_TEST(AUFS, test_aufs) /* task_test_aufs */
30875+TASK_PFA_SET(AUFS, aufs) /* task_set_aufs */
30876+TASK_PFA_CLEAR(AUFS, aufs) /* task_clear_aufs */
b752ccd1
AM
30877+
30878+static inline int si_pid_test(struct super_block *sb)
30879+{
a2654f78 30880+ return !!task_test_aufs(current);
b752ccd1
AM
30881+}
30882+
30883+static inline void si_pid_clr(struct super_block *sb)
30884+{
a2654f78
AM
30885+ AuDebugOn(!task_test_aufs(current));
30886+ task_clear_aufs(current);
b752ccd1
AM
30887+}
30888+
a2654f78
AM
30889+static inline void si_pid_set(struct super_block *sb)
30890+{
30891+ AuDebugOn(task_test_aufs(current));
30892+ task_set_aufs(current);
30893+}
febd17d6 30894+
b752ccd1
AM
30895+/* ---------------------------------------------------------------------- */
30896+
1facf9fc 30897+/* lock superblock. mainly for entry point functions */
8b6a4947
AM
30898+#define __si_read_lock(sb) au_rw_read_lock(&au_sbi(sb)->si_rwsem)
30899+#define __si_write_lock(sb) au_rw_write_lock(&au_sbi(sb)->si_rwsem)
30900+#define __si_read_trylock(sb) au_rw_read_trylock(&au_sbi(sb)->si_rwsem)
30901+#define __si_write_trylock(sb) au_rw_write_trylock(&au_sbi(sb)->si_rwsem)
30902+/*
30903+#define __si_read_trylock_nested(sb) \
30904+ au_rw_read_trylock_nested(&au_sbi(sb)->si_rwsem)
30905+#define __si_write_trylock_nested(sb) \
30906+ au_rw_write_trylock_nested(&au_sbi(sb)->si_rwsem)
30907+*/
30908+
30909+#define __si_read_unlock(sb) au_rw_read_unlock(&au_sbi(sb)->si_rwsem)
30910+#define __si_write_unlock(sb) au_rw_write_unlock(&au_sbi(sb)->si_rwsem)
30911+#define __si_downgrade_lock(sb) au_rw_dgrade_lock(&au_sbi(sb)->si_rwsem)
1facf9fc 30912+
dece6358
AM
30913+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
30914+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
30915+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
30916+
b752ccd1
AM
30917+static inline void si_noflush_read_lock(struct super_block *sb)
30918+{
30919+ __si_read_lock(sb);
30920+ si_pid_set(sb);
30921+}
30922+
30923+static inline int si_noflush_read_trylock(struct super_block *sb)
30924+{
076b876e
AM
30925+ int locked;
30926+
30927+ locked = __si_read_trylock(sb);
b752ccd1
AM
30928+ if (locked)
30929+ si_pid_set(sb);
30930+ return locked;
30931+}
30932+
30933+static inline void si_noflush_write_lock(struct super_block *sb)
30934+{
30935+ __si_write_lock(sb);
30936+ si_pid_set(sb);
30937+}
30938+
30939+static inline int si_noflush_write_trylock(struct super_block *sb)
30940+{
076b876e
AM
30941+ int locked;
30942+
30943+ locked = __si_write_trylock(sb);
b752ccd1
AM
30944+ if (locked)
30945+ si_pid_set(sb);
30946+ return locked;
30947+}
30948+
7e9cd9fe 30949+#if 0 /* reserved */
1facf9fc 30950+static inline int si_read_trylock(struct super_block *sb, int flags)
30951+{
30952+ if (au_ftest_lock(flags, FLUSH))
30953+ au_nwt_flush(&au_sbi(sb)->si_nowait);
30954+ return si_noflush_read_trylock(sb);
30955+}
e49829fe 30956+#endif
1facf9fc 30957+
b752ccd1
AM
30958+static inline void si_read_unlock(struct super_block *sb)
30959+{
30960+ si_pid_clr(sb);
30961+ __si_read_unlock(sb);
30962+}
30963+
7e9cd9fe 30964+#if 0 /* reserved */
1facf9fc 30965+static inline int si_write_trylock(struct super_block *sb, int flags)
30966+{
30967+ if (au_ftest_lock(flags, FLUSH))
30968+ au_nwt_flush(&au_sbi(sb)->si_nowait);
30969+ return si_noflush_write_trylock(sb);
30970+}
b752ccd1
AM
30971+#endif
30972+
30973+static inline void si_write_unlock(struct super_block *sb)
30974+{
30975+ si_pid_clr(sb);
30976+ __si_write_unlock(sb);
30977+}
30978+
7e9cd9fe 30979+#if 0 /* reserved */
b752ccd1
AM
30980+static inline void si_downgrade_lock(struct super_block *sb)
30981+{
30982+ __si_downgrade_lock(sb);
30983+}
30984+#endif
1facf9fc 30985+
30986+/* ---------------------------------------------------------------------- */
30987+
5afbbe0d 30988+static inline aufs_bindex_t au_sbbot(struct super_block *sb)
1facf9fc 30989+{
dece6358 30990+ SiMustAnyLock(sb);
5afbbe0d 30991+ return au_sbi(sb)->si_bbot;
1facf9fc 30992+}
30993+
30994+static inline unsigned int au_mntflags(struct super_block *sb)
30995+{
dece6358 30996+ SiMustAnyLock(sb);
1facf9fc 30997+ return au_sbi(sb)->si_mntflags;
30998+}
30999+
31000+static inline unsigned int au_sigen(struct super_block *sb)
31001+{
dece6358 31002+ SiMustAnyLock(sb);
1facf9fc 31003+ return au_sbi(sb)->si_generation;
31004+}
31005+
31006+static inline struct au_branch *au_sbr(struct super_block *sb,
31007+ aufs_bindex_t bindex)
31008+{
dece6358 31009+ SiMustAnyLock(sb);
1facf9fc 31010+ return au_sbi(sb)->si_branch[0 + bindex];
31011+}
31012+
acd2b654 31013+static inline loff_t au_xi_maxent(struct super_block *sb)
1facf9fc 31014+{
dece6358 31015+ SiMustAnyLock(sb);
acd2b654 31016+ return au_sbi(sb)->si_ximaxent;
1facf9fc 31017+}
31018+
31019+#endif /* __KERNEL__ */
31020+#endif /* __AUFS_SUPER_H__ */
7f207e10 31021diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
eca34b5c 31022--- /usr/share/empty/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 31023+++ linux/fs/aufs/sysaufs.c 2021-05-02 20:15:14.676670793 +0200
062440b3 31024@@ -0,0 +1,93 @@
cd7a4cd9 31025+// SPDX-License-Identifier: GPL-2.0
1facf9fc 31026+/*
d58c55f2 31027+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 31028+ *
31029+ * This program, aufs is free software; you can redistribute it and/or modify
31030+ * it under the terms of the GNU General Public License as published by
31031+ * the Free Software Foundation; either version 2 of the License, or
31032+ * (at your option) any later version.
dece6358
AM
31033+ *
31034+ * This program is distributed in the hope that it will be useful,
31035+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31036+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31037+ * GNU General Public License for more details.
31038+ *
31039+ * You should have received a copy of the GNU General Public License
523b37e3 31040+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31041+ */
31042+
31043+/*
31044+ * sysfs interface and lifetime management
31045+ * they are necessary regardless sysfs is disabled.
31046+ */
31047+
1facf9fc 31048+#include <linux/random.h>
1facf9fc 31049+#include "aufs.h"
31050+
31051+unsigned long sysaufs_si_mask;
e49829fe 31052+struct kset *sysaufs_kset;
1facf9fc 31053+
31054+#define AuSiAttr(_name) { \
31055+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
31056+ .show = sysaufs_si_##_name, \
31057+}
31058+
31059+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
31060+struct attribute *sysaufs_si_attrs[] = {
31061+ &sysaufs_si_attr_xi_path.attr,
31062+ NULL,
31063+};
31064+
4a4d8108 31065+static const struct sysfs_ops au_sbi_ops = {
1facf9fc 31066+ .show = sysaufs_si_show
31067+};
31068+
31069+static struct kobj_type au_sbi_ktype = {
31070+ .release = au_si_free,
31071+ .sysfs_ops = &au_sbi_ops,
31072+ .default_attrs = sysaufs_si_attrs
31073+};
31074+
31075+/* ---------------------------------------------------------------------- */
31076+
31077+int sysaufs_si_init(struct au_sbinfo *sbinfo)
31078+{
31079+ int err;
31080+
e49829fe 31081+ sbinfo->si_kobj.kset = sysaufs_kset;
1facf9fc 31082+ /* cf. sysaufs_name() */
31083+ err = kobject_init_and_add
e49829fe 31084+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL,
1facf9fc 31085+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
31086+
1facf9fc 31087+ return err;
31088+}
31089+
31090+void sysaufs_fin(void)
31091+{
e49829fe
JR
31092+ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group);
31093+ kset_unregister(sysaufs_kset);
1facf9fc 31094+}
31095+
31096+int __init sysaufs_init(void)
31097+{
31098+ int err;
31099+
31100+ do {
31101+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
31102+ } while (!sysaufs_si_mask);
31103+
4a4d8108 31104+ err = -EINVAL;
e49829fe
JR
31105+ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
31106+ if (unlikely(!sysaufs_kset))
4a4d8108 31107+ goto out;
e49829fe
JR
31108+ err = PTR_ERR(sysaufs_kset);
31109+ if (IS_ERR(sysaufs_kset))
1facf9fc 31110+ goto out;
e49829fe 31111+ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group);
062440b3 31112+ if (unlikely(err))
e49829fe 31113+ kset_unregister(sysaufs_kset);
1facf9fc 31114+
4f0767ce 31115+out:
1facf9fc 31116+ return err;
31117+}
7f207e10 31118diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
eca34b5c 31119--- /usr/share/empty/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 31120+++ linux/fs/aufs/sysaufs.h 2021-05-02 20:15:14.676670793 +0200
062440b3
AM
31121@@ -0,0 +1,102 @@
31122+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 31123+/*
d58c55f2 31124+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 31125+ *
31126+ * This program, aufs is free software; you can redistribute it and/or modify
31127+ * it under the terms of the GNU General Public License as published by
31128+ * the Free Software Foundation; either version 2 of the License, or
31129+ * (at your option) any later version.
dece6358
AM
31130+ *
31131+ * This program is distributed in the hope that it will be useful,
31132+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31133+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31134+ * GNU General Public License for more details.
31135+ *
31136+ * You should have received a copy of the GNU General Public License
523b37e3 31137+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31138+ */
31139+
31140+/*
31141+ * sysfs interface and mount lifetime management
31142+ */
31143+
31144+#ifndef __SYSAUFS_H__
31145+#define __SYSAUFS_H__
31146+
31147+#ifdef __KERNEL__
31148+
1facf9fc 31149+#include <linux/sysfs.h>
1facf9fc 31150+#include "module.h"
31151+
dece6358
AM
31152+struct super_block;
31153+struct au_sbinfo;
31154+
1facf9fc 31155+struct sysaufs_si_attr {
31156+ struct attribute attr;
31157+ int (*show)(struct seq_file *seq, struct super_block *sb);
31158+};
31159+
31160+/* ---------------------------------------------------------------------- */
31161+
31162+/* sysaufs.c */
31163+extern unsigned long sysaufs_si_mask;
e49829fe 31164+extern struct kset *sysaufs_kset;
1facf9fc 31165+extern struct attribute *sysaufs_si_attrs[];
31166+int sysaufs_si_init(struct au_sbinfo *sbinfo);
31167+int __init sysaufs_init(void);
31168+void sysaufs_fin(void);
31169+
31170+/* ---------------------------------------------------------------------- */
31171+
31172+/* some people doesn't like to show a pointer in kernel */
31173+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
31174+{
31175+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
31176+}
31177+
31178+#define SysaufsSiNamePrefix "si_"
31179+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
31180+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
31181+{
31182+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
31183+ sysaufs_si_id(sbinfo));
31184+}
31185+
31186+struct au_branch;
31187+#ifdef CONFIG_SYSFS
31188+/* sysfs.c */
31189+extern struct attribute_group *sysaufs_attr_group;
31190+
31191+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
31192+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
31193+ char *buf);
076b876e
AM
31194+long au_brinfo_ioctl(struct file *file, unsigned long arg);
31195+#ifdef CONFIG_COMPAT
31196+long au_brinfo_compat_ioctl(struct file *file, unsigned long arg);
31197+#endif
1facf9fc 31198+
31199+void sysaufs_br_init(struct au_branch *br);
31200+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
31201+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
31202+
31203+#define sysaufs_brs_init() do {} while (0)
31204+
31205+#else
31206+#define sysaufs_attr_group NULL
31207+
4a4d8108 31208+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
c1595e42
JR
31209+AuStub(ssize_t, sysaufs_si_show, return 0, struct kobject *kobj,
31210+ struct attribute *attr, char *buf)
4a4d8108
AM
31211+AuStubVoid(sysaufs_br_init, struct au_branch *br)
31212+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
31213+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
1facf9fc 31214+
31215+static inline void sysaufs_brs_init(void)
31216+{
31217+ sysaufs_brs = 0;
31218+}
31219+
31220+#endif /* CONFIG_SYSFS */
31221+
31222+#endif /* __KERNEL__ */
31223+#endif /* __SYSAUFS_H__ */
7f207e10 31224diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
eca34b5c 31225--- /usr/share/empty/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 31226+++ linux/fs/aufs/sysfs.c 2021-05-02 20:15:14.676670793 +0200
ba1aed25 31227@@ -0,0 +1,374 @@
cd7a4cd9 31228+// SPDX-License-Identifier: GPL-2.0
1facf9fc 31229+/*
d58c55f2 31230+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 31231+ *
31232+ * This program, aufs is free software; you can redistribute it and/or modify
31233+ * it under the terms of the GNU General Public License as published by
31234+ * the Free Software Foundation; either version 2 of the License, or
31235+ * (at your option) any later version.
dece6358
AM
31236+ *
31237+ * This program is distributed in the hope that it will be useful,
31238+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31239+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31240+ * GNU General Public License for more details.
31241+ *
31242+ * You should have received a copy of the GNU General Public License
523b37e3 31243+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31244+ */
31245+
31246+/*
31247+ * sysfs interface
31248+ */
31249+
076b876e 31250+#include <linux/compat.h>
1facf9fc 31251+#include <linux/seq_file.h>
1facf9fc 31252+#include "aufs.h"
31253+
4a4d8108
AM
31254+#ifdef CONFIG_AUFS_FS_MODULE
31255+/* this entry violates the "one line per file" policy of sysfs */
31256+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
31257+ char *buf)
31258+{
31259+ ssize_t err;
31260+ static char *conf =
31261+/* this file is generated at compiling */
31262+#include "conf.str"
31263+ ;
31264+
31265+ err = snprintf(buf, PAGE_SIZE, conf);
31266+ if (unlikely(err >= PAGE_SIZE))
31267+ err = -EFBIG;
31268+ return err;
31269+}
31270+
31271+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
31272+#endif
31273+
1facf9fc 31274+static struct attribute *au_attr[] = {
4a4d8108
AM
31275+#ifdef CONFIG_AUFS_FS_MODULE
31276+ &au_config_attr.attr,
31277+#endif
1facf9fc 31278+ NULL, /* need to NULL terminate the list of attributes */
31279+};
31280+
31281+static struct attribute_group sysaufs_attr_group_body = {
31282+ .attrs = au_attr
31283+};
31284+
31285+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
31286+
31287+/* ---------------------------------------------------------------------- */
31288+
31289+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
31290+{
31291+ int err;
31292+
dece6358
AM
31293+ SiMustAnyLock(sb);
31294+
1facf9fc 31295+ err = 0;
31296+ if (au_opt_test(au_mntflags(sb), XINO)) {
31297+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
31298+ seq_putc(seq, '\n');
31299+ }
31300+ return err;
31301+}
31302+
31303+/*
31304+ * the lifetime of branch is independent from the entry under sysfs.
31305+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
31306+ * unlinked.
31307+ */
31308+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
392086de 31309+ aufs_bindex_t bindex, int idx)
1facf9fc 31310+{
1e00d052 31311+ int err;
1facf9fc 31312+ struct path path;
31313+ struct dentry *root;
31314+ struct au_branch *br;
076b876e 31315+ au_br_perm_str_t perm;
1facf9fc 31316+
31317+ AuDbg("b%d\n", bindex);
31318+
1e00d052 31319+ err = 0;
1facf9fc 31320+ root = sb->s_root;
31321+ di_read_lock_parent(root, !AuLock_IR);
31322+ br = au_sbr(sb, bindex);
392086de
AM
31323+
31324+ switch (idx) {
31325+ case AuBrSysfs_BR:
31326+ path.mnt = au_br_mnt(br);
31327+ path.dentry = au_h_dptr(root, bindex);
79b8bda9
AM
31328+ err = au_seq_path(seq, &path);
31329+ if (!err) {
31330+ au_optstr_br_perm(&perm, br->br_perm);
31331+ seq_printf(seq, "=%s\n", perm.a);
31332+ }
392086de
AM
31333+ break;
31334+ case AuBrSysfs_BRID:
79b8bda9 31335+ seq_printf(seq, "%d\n", br->br_id);
392086de
AM
31336+ break;
31337+ }
076b876e 31338+ di_read_unlock(root, !AuLock_IR);
79b8bda9 31339+ if (unlikely(err || seq_has_overflowed(seq)))
076b876e 31340+ err = -E2BIG;
392086de 31341+
1e00d052 31342+ return err;
1facf9fc 31343+}
31344+
31345+/* ---------------------------------------------------------------------- */
31346+
31347+static struct seq_file *au_seq(char *p, ssize_t len)
31348+{
31349+ struct seq_file *seq;
31350+
31351+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
31352+ if (seq) {
31353+ /* mutex_init(&seq.lock); */
31354+ seq->buf = p;
31355+ seq->size = len;
31356+ return seq; /* success */
31357+ }
31358+
31359+ seq = ERR_PTR(-ENOMEM);
31360+ return seq;
31361+}
31362+
392086de
AM
31363+#define SysaufsBr_PREFIX "br"
31364+#define SysaufsBrid_PREFIX "brid"
1facf9fc 31365+
31366+/* todo: file size may exceed PAGE_SIZE */
31367+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
1308ab2a 31368+ char *buf)
1facf9fc 31369+{
31370+ ssize_t err;
392086de 31371+ int idx;
1facf9fc 31372+ long l;
5afbbe0d 31373+ aufs_bindex_t bbot;
1facf9fc 31374+ struct au_sbinfo *sbinfo;
31375+ struct super_block *sb;
31376+ struct seq_file *seq;
31377+ char *name;
31378+ struct attribute **cattr;
31379+
31380+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
31381+ sb = sbinfo->si_sb;
1308ab2a 31382+
31383+ /*
31384+ * prevent a race condition between sysfs and aufs.
31385+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which
31386+ * prohibits maintaining the sysfs entries.
31387+ * hew we acquire read lock after sysfs_get_active_two().
31388+ * on the other hand, the remount process may maintain the sysfs/aufs
31389+ * entries after acquiring write lock.
31390+ * it can cause a deadlock.
31391+ * simply we gave up processing read here.
31392+ */
31393+ err = -EBUSY;
31394+ if (unlikely(!si_noflush_read_trylock(sb)))
31395+ goto out;
1facf9fc 31396+
31397+ seq = au_seq(buf, PAGE_SIZE);
31398+ err = PTR_ERR(seq);
31399+ if (IS_ERR(seq))
1308ab2a 31400+ goto out_unlock;
1facf9fc 31401+
31402+ name = (void *)attr->name;
31403+ cattr = sysaufs_si_attrs;
31404+ while (*cattr) {
31405+ if (!strcmp(name, (*cattr)->name)) {
31406+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
31407+ ->show(seq, sb);
31408+ goto out_seq;
31409+ }
31410+ cattr++;
31411+ }
31412+
392086de
AM
31413+ if (!strncmp(name, SysaufsBrid_PREFIX,
31414+ sizeof(SysaufsBrid_PREFIX) - 1)) {
31415+ idx = AuBrSysfs_BRID;
31416+ name += sizeof(SysaufsBrid_PREFIX) - 1;
31417+ } else if (!strncmp(name, SysaufsBr_PREFIX,
31418+ sizeof(SysaufsBr_PREFIX) - 1)) {
31419+ idx = AuBrSysfs_BR;
1facf9fc 31420+ name += sizeof(SysaufsBr_PREFIX) - 1;
392086de
AM
31421+ } else
31422+ BUG();
31423+
31424+ err = kstrtol(name, 10, &l);
31425+ if (!err) {
5afbbe0d
AM
31426+ bbot = au_sbbot(sb);
31427+ if (l <= bbot)
392086de
AM
31428+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l, idx);
31429+ else
31430+ err = -ENOENT;
1facf9fc 31431+ }
1facf9fc 31432+
4f0767ce 31433+out_seq:
1facf9fc 31434+ if (!err) {
31435+ err = seq->count;
31436+ /* sysfs limit */
31437+ if (unlikely(err == PAGE_SIZE))
31438+ err = -EFBIG;
31439+ }
9f237c51 31440+ au_kfree_rcu(seq);
4f0767ce 31441+out_unlock:
1facf9fc 31442+ si_read_unlock(sb);
4f0767ce 31443+out:
1facf9fc 31444+ return err;
31445+}
31446+
31447+/* ---------------------------------------------------------------------- */
31448+
076b876e
AM
31449+static int au_brinfo(struct super_block *sb, union aufs_brinfo __user *arg)
31450+{
31451+ int err;
31452+ int16_t brid;
5afbbe0d 31453+ aufs_bindex_t bindex, bbot;
076b876e
AM
31454+ size_t sz;
31455+ char *buf;
31456+ struct seq_file *seq;
31457+ struct au_branch *br;
31458+
31459+ si_read_lock(sb, AuLock_FLUSH);
5afbbe0d
AM
31460+ bbot = au_sbbot(sb);
31461+ err = bbot + 1;
076b876e
AM
31462+ if (!arg)
31463+ goto out;
31464+
31465+ err = -ENOMEM;
31466+ buf = (void *)__get_free_page(GFP_NOFS);
31467+ if (unlikely(!buf))
31468+ goto out;
31469+
31470+ seq = au_seq(buf, PAGE_SIZE);
31471+ err = PTR_ERR(seq);
31472+ if (IS_ERR(seq))
31473+ goto out_buf;
31474+
31475+ sz = sizeof(*arg) - offsetof(union aufs_brinfo, path);
5afbbe0d 31476+ for (bindex = 0; bindex <= bbot; bindex++, arg++) {
ba1aed25
AM
31477+ /* VERIFY_WRITE */
31478+ err = !access_ok(arg, sizeof(*arg));
076b876e
AM
31479+ if (unlikely(err))
31480+ break;
31481+
31482+ br = au_sbr(sb, bindex);
31483+ brid = br->br_id;
31484+ BUILD_BUG_ON(sizeof(brid) != sizeof(arg->id));
31485+ err = __put_user(brid, &arg->id);
31486+ if (unlikely(err))
31487+ break;
31488+
31489+ BUILD_BUG_ON(sizeof(br->br_perm) != sizeof(arg->perm));
31490+ err = __put_user(br->br_perm, &arg->perm);
31491+ if (unlikely(err))
31492+ break;
31493+
79b8bda9
AM
31494+ err = au_seq_path(seq, &br->br_path);
31495+ if (unlikely(err))
31496+ break;
31497+ seq_putc(seq, '\0');
31498+ if (!seq_has_overflowed(seq)) {
076b876e
AM
31499+ err = copy_to_user(arg->path, seq->buf, seq->count);
31500+ seq->count = 0;
31501+ if (unlikely(err))
31502+ break;
31503+ } else {
31504+ err = -E2BIG;
31505+ goto out_seq;
31506+ }
31507+ }
31508+ if (unlikely(err))
31509+ err = -EFAULT;
31510+
31511+out_seq:
9f237c51 31512+ au_kfree_rcu(seq);
076b876e 31513+out_buf:
1c60b727 31514+ free_page((unsigned long)buf);
076b876e
AM
31515+out:
31516+ si_read_unlock(sb);
31517+ return err;
31518+}
31519+
31520+long au_brinfo_ioctl(struct file *file, unsigned long arg)
31521+{
2000de60 31522+ return au_brinfo(file->f_path.dentry->d_sb, (void __user *)arg);
076b876e
AM
31523+}
31524+
31525+#ifdef CONFIG_COMPAT
31526+long au_brinfo_compat_ioctl(struct file *file, unsigned long arg)
31527+{
2000de60 31528+ return au_brinfo(file->f_path.dentry->d_sb, compat_ptr(arg));
076b876e
AM
31529+}
31530+#endif
31531+
31532+/* ---------------------------------------------------------------------- */
31533+
1facf9fc 31534+void sysaufs_br_init(struct au_branch *br)
31535+{
392086de
AM
31536+ int i;
31537+ struct au_brsysfs *br_sysfs;
31538+ struct attribute *attr;
4a4d8108 31539+
392086de
AM
31540+ br_sysfs = br->br_sysfs;
31541+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
31542+ attr = &br_sysfs->attr;
31543+ sysfs_attr_init(attr);
31544+ attr->name = br_sysfs->name;
cd7a4cd9 31545+ attr->mode = 0444;
392086de
AM
31546+ br_sysfs++;
31547+ }
1facf9fc 31548+}
31549+
31550+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
31551+{
31552+ struct au_branch *br;
31553+ struct kobject *kobj;
392086de
AM
31554+ struct au_brsysfs *br_sysfs;
31555+ int i;
5afbbe0d 31556+ aufs_bindex_t bbot;
1facf9fc 31557+
1facf9fc 31558+ if (!sysaufs_brs)
31559+ return;
31560+
31561+ kobj = &au_sbi(sb)->si_kobj;
5afbbe0d
AM
31562+ bbot = au_sbbot(sb);
31563+ for (; bindex <= bbot; bindex++) {
1facf9fc 31564+ br = au_sbr(sb, bindex);
392086de
AM
31565+ br_sysfs = br->br_sysfs;
31566+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
31567+ sysfs_remove_file(kobj, &br_sysfs->attr);
31568+ br_sysfs++;
31569+ }
1facf9fc 31570+ }
31571+}
31572+
31573+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
31574+{
392086de 31575+ int err, i;
5afbbe0d 31576+ aufs_bindex_t bbot;
1facf9fc 31577+ struct kobject *kobj;
31578+ struct au_branch *br;
392086de 31579+ struct au_brsysfs *br_sysfs;
1facf9fc 31580+
1facf9fc 31581+ if (!sysaufs_brs)
31582+ return;
31583+
31584+ kobj = &au_sbi(sb)->si_kobj;
5afbbe0d
AM
31585+ bbot = au_sbbot(sb);
31586+ for (; bindex <= bbot; bindex++) {
1facf9fc 31587+ br = au_sbr(sb, bindex);
392086de
AM
31588+ br_sysfs = br->br_sysfs;
31589+ snprintf(br_sysfs[AuBrSysfs_BR].name, sizeof(br_sysfs->name),
31590+ SysaufsBr_PREFIX "%d", bindex);
31591+ snprintf(br_sysfs[AuBrSysfs_BRID].name, sizeof(br_sysfs->name),
31592+ SysaufsBrid_PREFIX "%d", bindex);
31593+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
31594+ err = sysfs_create_file(kobj, &br_sysfs->attr);
31595+ if (unlikely(err))
31596+ pr_warn("failed %s under sysfs(%d)\n",
31597+ br_sysfs->name, err);
31598+ br_sysfs++;
31599+ }
1facf9fc 31600+ }
31601+}
7f207e10 31602diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
eca34b5c 31603--- /usr/share/empty/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 31604+++ linux/fs/aufs/sysrq.c 2021-05-02 20:15:14.676670793 +0200
43982f53 31605@@ -0,0 +1,149 @@
cd7a4cd9 31606+// SPDX-License-Identifier: GPL-2.0
1facf9fc 31607+/*
d58c55f2 31608+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 31609+ *
31610+ * This program, aufs is free software; you can redistribute it and/or modify
31611+ * it under the terms of the GNU General Public License as published by
31612+ * the Free Software Foundation; either version 2 of the License, or
31613+ * (at your option) any later version.
dece6358
AM
31614+ *
31615+ * This program is distributed in the hope that it will be useful,
31616+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31617+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31618+ * GNU General Public License for more details.
31619+ *
31620+ * You should have received a copy of the GNU General Public License
523b37e3 31621+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31622+ */
31623+
31624+/*
acd2b654 31625+ * magic sysrq handler
1facf9fc 31626+ */
31627+
1facf9fc 31628+/* #include <linux/sysrq.h> */
027c5e7a 31629+#include <linux/writeback.h>
1facf9fc 31630+#include "aufs.h"
31631+
31632+/* ---------------------------------------------------------------------- */
31633+
31634+static void sysrq_sb(struct super_block *sb)
31635+{
31636+ char *plevel;
31637+ struct au_sbinfo *sbinfo;
31638+ struct file *file;
8b6a4947
AM
31639+ struct hlist_bl_head *files;
31640+ struct hlist_bl_node *pos;
523b37e3 31641+ struct au_finfo *finfo;
43982f53 31642+ struct inode *i;
1facf9fc 31643+
31644+ plevel = au_plevel;
31645+ au_plevel = KERN_WARNING;
1facf9fc 31646+
4a4d8108 31647+ /* since we define pr_fmt, call printk directly */
c06a8ce3
AM
31648+#define pr(str) printk(KERN_WARNING AUFS_NAME ": " str)
31649+
31650+ sbinfo = au_sbi(sb);
4a4d8108 31651+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
c06a8ce3 31652+ pr("superblock\n");
1facf9fc 31653+ au_dpri_sb(sb);
027c5e7a 31654+
43982f53 31655+#if 0 /* reserved */
027c5e7a
AM
31656+ do {
31657+ int err, i, j, ndentry;
31658+ struct au_dcsub_pages dpages;
31659+ struct au_dpage *dpage;
31660+
31661+ err = au_dpages_init(&dpages, GFP_ATOMIC);
31662+ if (unlikely(err))
31663+ break;
31664+ err = au_dcsub_pages(&dpages, sb->s_root, NULL, NULL);
31665+ if (!err)
31666+ for (i = 0; i < dpages.ndpage; i++) {
31667+ dpage = dpages.dpages + i;
31668+ ndentry = dpage->ndentry;
31669+ for (j = 0; j < ndentry; j++)
31670+ au_dpri_dentry(dpage->dentries[j]);
31671+ }
31672+ au_dpages_free(&dpages);
31673+ } while (0);
31674+#endif
31675+
43982f53
AM
31676+ pr("isolated inode\n");
31677+ spin_lock(&sb->s_inode_list_lock);
31678+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
31679+ spin_lock(&i->i_lock);
31680+ if (hlist_empty(&i->i_dentry))
31681+ au_dpri_inode(i);
31682+ spin_unlock(&i->i_lock);
027c5e7a 31683+ }
43982f53
AM
31684+ spin_unlock(&sb->s_inode_list_lock);
31685+
c06a8ce3 31686+ pr("files\n");
523b37e3 31687+ files = &au_sbi(sb)->si_files;
8b6a4947
AM
31688+ hlist_bl_lock(files);
31689+ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) {
4a4d8108 31690+ umode_t mode;
076b876e 31691+
523b37e3 31692+ file = finfo->fi_file;
c06a8ce3 31693+ mode = file_inode(file)->i_mode;
38d290e6 31694+ if (!special_file(mode))
1facf9fc 31695+ au_dpri_file(file);
523b37e3 31696+ }
8b6a4947 31697+ hlist_bl_unlock(files);
c06a8ce3 31698+ pr("done\n");
1facf9fc 31699+
c06a8ce3 31700+#undef pr
1facf9fc 31701+ au_plevel = plevel;
1facf9fc 31702+}
31703+
31704+/* ---------------------------------------------------------------------- */
31705+
31706+/* module parameter */
31707+static char *aufs_sysrq_key = "a";
cd7a4cd9 31708+module_param_named(sysrq, aufs_sysrq_key, charp, 0444);
1facf9fc 31709+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
31710+
0c5527e5 31711+static void au_sysrq(int key __maybe_unused)
1facf9fc 31712+{
1facf9fc 31713+ struct au_sbinfo *sbinfo;
8b6a4947 31714+ struct hlist_bl_node *pos;
1facf9fc 31715+
027c5e7a 31716+ lockdep_off();
53392da6 31717+ au_sbilist_lock();
8b6a4947 31718+ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list)
1facf9fc 31719+ sysrq_sb(sbinfo->si_sb);
53392da6 31720+ au_sbilist_unlock();
027c5e7a 31721+ lockdep_on();
1facf9fc 31722+}
31723+
31724+static struct sysrq_key_op au_sysrq_op = {
31725+ .handler = au_sysrq,
31726+ .help_msg = "Aufs",
31727+ .action_msg = "Aufs",
31728+ .enable_mask = SYSRQ_ENABLE_DUMP
31729+};
31730+
31731+/* ---------------------------------------------------------------------- */
31732+
31733+int __init au_sysrq_init(void)
31734+{
31735+ int err;
31736+ char key;
31737+
31738+ err = -1;
31739+ key = *aufs_sysrq_key;
31740+ if ('a' <= key && key <= 'z')
31741+ err = register_sysrq_key(key, &au_sysrq_op);
31742+ if (unlikely(err))
4a4d8108 31743+ pr_err("err %d, sysrq=%c\n", err, key);
1facf9fc 31744+ return err;
31745+}
31746+
31747+void au_sysrq_fin(void)
31748+{
31749+ int err;
076b876e 31750+
1facf9fc 31751+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
31752+ if (unlikely(err))
4a4d8108 31753+ pr_err("err %d (ignored)\n", err);
1facf9fc 31754+}
7f207e10 31755diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
eca34b5c 31756--- /usr/share/empty/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 31757+++ linux/fs/aufs/vdir.c 2021-05-02 20:15:14.676670793 +0200
eca801bf 31758@@ -0,0 +1,896 @@
cd7a4cd9 31759+// SPDX-License-Identifier: GPL-2.0
1facf9fc 31760+/*
d58c55f2 31761+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 31762+ *
31763+ * This program, aufs is free software; you can redistribute it and/or modify
31764+ * it under the terms of the GNU General Public License as published by
31765+ * the Free Software Foundation; either version 2 of the License, or
31766+ * (at your option) any later version.
dece6358
AM
31767+ *
31768+ * This program is distributed in the hope that it will be useful,
31769+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31770+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31771+ * GNU General Public License for more details.
31772+ *
31773+ * You should have received a copy of the GNU General Public License
523b37e3 31774+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31775+ */
31776+
31777+/*
31778+ * virtual or vertical directory
31779+ */
31780+
eca801bf 31781+#include <linux/iversion.h>
1facf9fc 31782+#include "aufs.h"
31783+
dece6358 31784+static unsigned int calc_size(int nlen)
1facf9fc 31785+{
dece6358 31786+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 31787+}
31788+
31789+static int set_deblk_end(union au_vdir_deblk_p *p,
31790+ union au_vdir_deblk_p *deblk_end)
31791+{
31792+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
31793+ p->de->de_str.len = 0;
31794+ /* smp_mb(); */
31795+ return 0;
31796+ }
31797+ return -1; /* error */
31798+}
31799+
31800+/* returns true or false */
31801+static int is_deblk_end(union au_vdir_deblk_p *p,
31802+ union au_vdir_deblk_p *deblk_end)
31803+{
31804+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
31805+ return !p->de->de_str.len;
31806+ return 1;
31807+}
31808+
31809+static unsigned char *last_deblk(struct au_vdir *vdir)
31810+{
31811+ return vdir->vd_deblk[vdir->vd_nblk - 1];
31812+}
31813+
31814+/* ---------------------------------------------------------------------- */
31815+
79b8bda9 31816+/* estimate the appropriate size for name hash table */
1308ab2a 31817+unsigned int au_rdhash_est(loff_t sz)
31818+{
31819+ unsigned int n;
31820+
31821+ n = UINT_MAX;
31822+ sz >>= 10;
31823+ if (sz < n)
31824+ n = sz;
31825+ if (sz < AUFS_RDHASH_DEF)
31826+ n = AUFS_RDHASH_DEF;
4a4d8108 31827+ /* pr_info("n %u\n", n); */
1308ab2a 31828+ return n;
31829+}
31830+
1facf9fc 31831+/*
31832+ * the allocated memory has to be freed by
dece6358 31833+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 31834+ */
dece6358 31835+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 31836+{
1facf9fc 31837+ struct hlist_head *head;
dece6358 31838+ unsigned int u;
076b876e 31839+ size_t sz;
1facf9fc 31840+
076b876e
AM
31841+ sz = sizeof(*nhash->nh_head) * num_hash;
31842+ head = kmalloc(sz, gfp);
dece6358
AM
31843+ if (head) {
31844+ nhash->nh_num = num_hash;
31845+ nhash->nh_head = head;
31846+ for (u = 0; u < num_hash; u++)
1facf9fc 31847+ INIT_HLIST_HEAD(head++);
dece6358 31848+ return 0; /* success */
1facf9fc 31849+ }
1facf9fc 31850+
dece6358 31851+ return -ENOMEM;
1facf9fc 31852+}
31853+
dece6358
AM
31854+static void nhash_count(struct hlist_head *head)
31855+{
43982f53 31856+#if 0 /* debugging */
dece6358
AM
31857+ unsigned long n;
31858+ struct hlist_node *pos;
31859+
31860+ n = 0;
31861+ hlist_for_each(pos, head)
31862+ n++;
4a4d8108 31863+ pr_info("%lu\n", n);
dece6358
AM
31864+#endif
31865+}
31866+
31867+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 31868+{
c06a8ce3
AM
31869+ struct au_vdir_wh *pos;
31870+ struct hlist_node *node;
1facf9fc 31871+
c06a8ce3 31872+ hlist_for_each_entry_safe(pos, node, head, wh_hash)
9f237c51 31873+ au_kfree_rcu(pos);
1facf9fc 31874+}
31875+
dece6358 31876+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 31877+{
c06a8ce3
AM
31878+ struct au_vdir_dehstr *pos;
31879+ struct hlist_node *node;
1facf9fc 31880+
c06a8ce3 31881+ hlist_for_each_entry_safe(pos, node, head, hash)
1c60b727 31882+ au_cache_free_vdir_dehstr(pos);
1facf9fc 31883+}
31884+
dece6358
AM
31885+static void au_nhash_do_free(struct au_nhash *nhash,
31886+ void (*free)(struct hlist_head *head))
1facf9fc 31887+{
1308ab2a 31888+ unsigned int n;
1facf9fc 31889+ struct hlist_head *head;
1facf9fc 31890+
dece6358 31891+ n = nhash->nh_num;
1308ab2a 31892+ if (!n)
31893+ return;
31894+
dece6358 31895+ head = nhash->nh_head;
1308ab2a 31896+ while (n-- > 0) {
dece6358
AM
31897+ nhash_count(head);
31898+ free(head++);
1facf9fc 31899+ }
9f237c51 31900+ au_kfree_try_rcu(nhash->nh_head);
1facf9fc 31901+}
31902+
dece6358 31903+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 31904+{
dece6358
AM
31905+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
31906+}
1facf9fc 31907+
dece6358
AM
31908+static void au_nhash_de_free(struct au_nhash *delist)
31909+{
31910+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 31911+}
31912+
31913+/* ---------------------------------------------------------------------- */
31914+
31915+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
31916+ int limit)
31917+{
31918+ int num;
31919+ unsigned int u, n;
31920+ struct hlist_head *head;
c06a8ce3 31921+ struct au_vdir_wh *pos;
1facf9fc 31922+
31923+ num = 0;
31924+ n = whlist->nh_num;
31925+ head = whlist->nh_head;
1308ab2a 31926+ for (u = 0; u < n; u++, head++)
c06a8ce3
AM
31927+ hlist_for_each_entry(pos, head, wh_hash)
31928+ if (pos->wh_bindex == btgt && ++num > limit)
1facf9fc 31929+ return 1;
1facf9fc 31930+ return 0;
31931+}
31932+
31933+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 31934+ unsigned char *name,
1facf9fc 31935+ unsigned int len)
31936+{
dece6358
AM
31937+ unsigned int v;
31938+ /* const unsigned int magic_bit = 12; */
31939+
1308ab2a 31940+ AuDebugOn(!nhash->nh_num || !nhash->nh_head);
31941+
dece6358 31942+ v = 0;
f0c0a007
AM
31943+ if (len > 8)
31944+ len = 8;
dece6358
AM
31945+ while (len--)
31946+ v += *name++;
31947+ /* v = hash_long(v, magic_bit); */
31948+ v %= nhash->nh_num;
31949+ return nhash->nh_head + v;
31950+}
31951+
31952+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
31953+ int nlen)
31954+{
31955+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 31956+}
31957+
31958+/* returns found or not */
dece6358 31959+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 31960+{
31961+ struct hlist_head *head;
c06a8ce3 31962+ struct au_vdir_wh *pos;
1facf9fc 31963+ struct au_vdir_destr *str;
31964+
dece6358 31965+ head = au_name_hash(whlist, name, nlen);
c06a8ce3
AM
31966+ hlist_for_each_entry(pos, head, wh_hash) {
31967+ str = &pos->wh_str;
1facf9fc 31968+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
31969+ if (au_nhash_test_name(str, name, nlen))
31970+ return 1;
31971+ }
31972+ return 0;
31973+}
31974+
31975+/* returns found(true) or not */
31976+static int test_known(struct au_nhash *delist, char *name, int nlen)
31977+{
31978+ struct hlist_head *head;
c06a8ce3 31979+ struct au_vdir_dehstr *pos;
dece6358
AM
31980+ struct au_vdir_destr *str;
31981+
31982+ head = au_name_hash(delist, name, nlen);
c06a8ce3
AM
31983+ hlist_for_each_entry(pos, head, hash) {
31984+ str = pos->str;
dece6358
AM
31985+ AuDbg("%.*s\n", str->len, str->name);
31986+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 31987+ return 1;
31988+ }
31989+ return 0;
31990+}
31991+
dece6358
AM
31992+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
31993+ unsigned char d_type)
31994+{
31995+#ifdef CONFIG_AUFS_SHWH
31996+ wh->wh_ino = ino;
31997+ wh->wh_type = d_type;
31998+#endif
31999+}
32000+
32001+/* ---------------------------------------------------------------------- */
32002+
32003+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
32004+ unsigned int d_type, aufs_bindex_t bindex,
32005+ unsigned char shwh)
1facf9fc 32006+{
32007+ int err;
32008+ struct au_vdir_destr *str;
32009+ struct au_vdir_wh *wh;
32010+
dece6358 32011+ AuDbg("%.*s\n", nlen, name);
1308ab2a 32012+ AuDebugOn(!whlist->nh_num || !whlist->nh_head);
32013+
1facf9fc 32014+ err = -ENOMEM;
dece6358 32015+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 32016+ if (unlikely(!wh))
32017+ goto out;
32018+
32019+ err = 0;
32020+ wh->wh_bindex = bindex;
dece6358
AM
32021+ if (shwh)
32022+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 32023+ str = &wh->wh_str;
dece6358
AM
32024+ str->len = nlen;
32025+ memcpy(str->name, name, nlen);
32026+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 32027+ /* smp_mb(); */
32028+
4f0767ce 32029+out:
1facf9fc 32030+ return err;
32031+}
32032+
1facf9fc 32033+static int append_deblk(struct au_vdir *vdir)
32034+{
32035+ int err;
dece6358 32036+ unsigned long ul;
1facf9fc 32037+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
32038+ union au_vdir_deblk_p p, deblk_end;
32039+ unsigned char **o;
32040+
32041+ err = -ENOMEM;
e2f27e51
AM
32042+ o = au_krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
32043+ GFP_NOFS, /*may_shrink*/0);
1facf9fc 32044+ if (unlikely(!o))
32045+ goto out;
32046+
32047+ vdir->vd_deblk = o;
32048+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
32049+ if (p.deblk) {
32050+ ul = vdir->vd_nblk++;
32051+ vdir->vd_deblk[ul] = p.deblk;
32052+ vdir->vd_last.ul = ul;
32053+ vdir->vd_last.p.deblk = p.deblk;
32054+ deblk_end.deblk = p.deblk + deblk_sz;
32055+ err = set_deblk_end(&p, &deblk_end);
32056+ }
32057+
4f0767ce 32058+out:
1facf9fc 32059+ return err;
32060+}
32061+
dece6358
AM
32062+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
32063+ unsigned int d_type, struct au_nhash *delist)
32064+{
32065+ int err;
32066+ unsigned int sz;
32067+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
32068+ union au_vdir_deblk_p p, *room, deblk_end;
32069+ struct au_vdir_dehstr *dehstr;
32070+
32071+ p.deblk = last_deblk(vdir);
32072+ deblk_end.deblk = p.deblk + deblk_sz;
32073+ room = &vdir->vd_last.p;
32074+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
32075+ || !is_deblk_end(room, &deblk_end));
32076+
32077+ sz = calc_size(nlen);
32078+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
32079+ err = append_deblk(vdir);
32080+ if (unlikely(err))
32081+ goto out;
32082+
32083+ p.deblk = last_deblk(vdir);
32084+ deblk_end.deblk = p.deblk + deblk_sz;
32085+ /* smp_mb(); */
32086+ AuDebugOn(room->deblk != p.deblk);
32087+ }
32088+
32089+ err = -ENOMEM;
4a4d8108 32090+ dehstr = au_cache_alloc_vdir_dehstr();
dece6358
AM
32091+ if (unlikely(!dehstr))
32092+ goto out;
32093+
32094+ dehstr->str = &room->de->de_str;
32095+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
32096+ room->de->de_ino = ino;
32097+ room->de->de_type = d_type;
32098+ room->de->de_str.len = nlen;
32099+ memcpy(room->de->de_str.name, name, nlen);
32100+
32101+ err = 0;
32102+ room->deblk += sz;
32103+ if (unlikely(set_deblk_end(room, &deblk_end)))
32104+ err = append_deblk(vdir);
32105+ /* smp_mb(); */
32106+
4f0767ce 32107+out:
dece6358
AM
32108+ return err;
32109+}
32110+
32111+/* ---------------------------------------------------------------------- */
32112+
1c60b727 32113+void au_vdir_free(struct au_vdir *vdir)
dece6358
AM
32114+{
32115+ unsigned char **deblk;
32116+
32117+ deblk = vdir->vd_deblk;
1c60b727 32118+ while (vdir->vd_nblk--)
9f237c51
AM
32119+ au_kfree_try_rcu(*deblk++);
32120+ au_kfree_try_rcu(vdir->vd_deblk);
1c60b727 32121+ au_cache_free_vdir(vdir);
dece6358
AM
32122+}
32123+
1308ab2a 32124+static struct au_vdir *alloc_vdir(struct file *file)
1facf9fc 32125+{
32126+ struct au_vdir *vdir;
1308ab2a 32127+ struct super_block *sb;
1facf9fc 32128+ int err;
32129+
2000de60 32130+ sb = file->f_path.dentry->d_sb;
dece6358
AM
32131+ SiMustAnyLock(sb);
32132+
1facf9fc 32133+ err = -ENOMEM;
32134+ vdir = au_cache_alloc_vdir();
32135+ if (unlikely(!vdir))
32136+ goto out;
32137+
32138+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
32139+ if (unlikely(!vdir->vd_deblk))
32140+ goto out_free;
32141+
32142+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
1308ab2a 32143+ if (!vdir->vd_deblk_sz) {
79b8bda9 32144+ /* estimate the appropriate size for deblk */
1308ab2a 32145+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
4a4d8108 32146+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
1308ab2a 32147+ }
1facf9fc 32148+ vdir->vd_nblk = 0;
32149+ vdir->vd_version = 0;
32150+ vdir->vd_jiffy = 0;
32151+ err = append_deblk(vdir);
32152+ if (!err)
32153+ return vdir; /* success */
32154+
9f237c51 32155+ au_kfree_try_rcu(vdir->vd_deblk);
1facf9fc 32156+
4f0767ce 32157+out_free:
1c60b727 32158+ au_cache_free_vdir(vdir);
4f0767ce 32159+out:
1facf9fc 32160+ vdir = ERR_PTR(err);
32161+ return vdir;
32162+}
32163+
32164+static int reinit_vdir(struct au_vdir *vdir)
32165+{
32166+ int err;
32167+ union au_vdir_deblk_p p, deblk_end;
32168+
32169+ while (vdir->vd_nblk > 1) {
9f237c51 32170+ au_kfree_try_rcu(vdir->vd_deblk[vdir->vd_nblk - 1]);
1facf9fc 32171+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
32172+ vdir->vd_nblk--;
32173+ }
32174+ p.deblk = vdir->vd_deblk[0];
32175+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
32176+ err = set_deblk_end(&p, &deblk_end);
32177+ /* keep vd_dblk_sz */
32178+ vdir->vd_last.ul = 0;
32179+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
32180+ vdir->vd_version = 0;
32181+ vdir->vd_jiffy = 0;
32182+ /* smp_mb(); */
32183+ return err;
32184+}
32185+
32186+/* ---------------------------------------------------------------------- */
32187+
1facf9fc 32188+#define AuFillVdir_CALLED 1
32189+#define AuFillVdir_WHABLE (1 << 1)
dece6358 32190+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 32191+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
7f207e10
AM
32192+#define au_fset_fillvdir(flags, name) \
32193+ do { (flags) |= AuFillVdir_##name; } while (0)
32194+#define au_fclr_fillvdir(flags, name) \
32195+ do { (flags) &= ~AuFillVdir_##name; } while (0)
1facf9fc 32196+
dece6358
AM
32197+#ifndef CONFIG_AUFS_SHWH
32198+#undef AuFillVdir_SHWH
32199+#define AuFillVdir_SHWH 0
32200+#endif
32201+
1facf9fc 32202+struct fillvdir_arg {
392086de 32203+ struct dir_context ctx;
1facf9fc 32204+ struct file *file;
32205+ struct au_vdir *vdir;
dece6358
AM
32206+ struct au_nhash delist;
32207+ struct au_nhash whlist;
1facf9fc 32208+ aufs_bindex_t bindex;
32209+ unsigned int flags;
32210+ int err;
32211+};
32212+
392086de 32213+static int fillvdir(struct dir_context *ctx, const char *__name, int nlen,
1facf9fc 32214+ loff_t offset __maybe_unused, u64 h_ino,
32215+ unsigned int d_type)
32216+{
392086de 32217+ struct fillvdir_arg *arg = container_of(ctx, struct fillvdir_arg, ctx);
1facf9fc 32218+ char *name = (void *)__name;
32219+ struct super_block *sb;
1facf9fc 32220+ ino_t ino;
dece6358 32221+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 32222+
1facf9fc 32223+ arg->err = 0;
2000de60 32224+ sb = arg->file->f_path.dentry->d_sb;
1facf9fc 32225+ au_fset_fillvdir(arg->flags, CALLED);
32226+ /* smp_mb(); */
dece6358 32227+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 32228+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
32229+ if (test_known(&arg->delist, name, nlen)
32230+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
32231+ goto out; /* already exists or whiteouted */
1facf9fc 32232+
dece6358 32233+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
4a4d8108
AM
32234+ if (!arg->err) {
32235+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
32236+ d_type = DT_UNKNOWN;
dece6358
AM
32237+ arg->err = append_de(arg->vdir, name, nlen, ino,
32238+ d_type, &arg->delist);
4a4d8108 32239+ }
1facf9fc 32240+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
32241+ name += AUFS_WH_PFX_LEN;
dece6358
AM
32242+ nlen -= AUFS_WH_PFX_LEN;
32243+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
32244+ goto out; /* already whiteouted */
1facf9fc 32245+
acd2b654 32246+ ino = 0; /* just to suppress a warning */
dece6358
AM
32247+ if (shwh)
32248+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
32249+ &ino);
4a4d8108
AM
32250+ if (!arg->err) {
32251+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
32252+ d_type = DT_UNKNOWN;
1facf9fc 32253+ arg->err = au_nhash_append_wh
dece6358
AM
32254+ (&arg->whlist, name, nlen, ino, d_type,
32255+ arg->bindex, shwh);
4a4d8108 32256+ }
1facf9fc 32257+ }
32258+
4f0767ce 32259+out:
1facf9fc 32260+ if (!arg->err)
32261+ arg->vdir->vd_jiffy = jiffies;
32262+ /* smp_mb(); */
32263+ AuTraceErr(arg->err);
32264+ return arg->err;
32265+}
32266+
dece6358
AM
32267+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
32268+ struct au_nhash *whlist, struct au_nhash *delist)
32269+{
32270+#ifdef CONFIG_AUFS_SHWH
32271+ int err;
32272+ unsigned int nh, u;
32273+ struct hlist_head *head;
c06a8ce3
AM
32274+ struct au_vdir_wh *pos;
32275+ struct hlist_node *n;
dece6358
AM
32276+ char *p, *o;
32277+ struct au_vdir_destr *destr;
32278+
32279+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
32280+
32281+ err = -ENOMEM;
537831f9 32282+ o = p = (void *)__get_free_page(GFP_NOFS);
dece6358
AM
32283+ if (unlikely(!p))
32284+ goto out;
32285+
32286+ err = 0;
32287+ nh = whlist->nh_num;
32288+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
32289+ p += AUFS_WH_PFX_LEN;
32290+ for (u = 0; u < nh; u++) {
32291+ head = whlist->nh_head + u;
c06a8ce3
AM
32292+ hlist_for_each_entry_safe(pos, n, head, wh_hash) {
32293+ destr = &pos->wh_str;
dece6358
AM
32294+ memcpy(p, destr->name, destr->len);
32295+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
c06a8ce3 32296+ pos->wh_ino, pos->wh_type, delist);
dece6358
AM
32297+ if (unlikely(err))
32298+ break;
32299+ }
32300+ }
32301+
1c60b727 32302+ free_page((unsigned long)o);
dece6358 32303+
4f0767ce 32304+out:
dece6358
AM
32305+ AuTraceErr(err);
32306+ return err;
32307+#else
32308+ return 0;
32309+#endif
32310+}
32311+
1facf9fc 32312+static int au_do_read_vdir(struct fillvdir_arg *arg)
32313+{
32314+ int err;
dece6358 32315+ unsigned int rdhash;
1facf9fc 32316+ loff_t offset;
5afbbe0d 32317+ aufs_bindex_t bbot, bindex, btop;
dece6358 32318+ unsigned char shwh;
1facf9fc 32319+ struct file *hf, *file;
32320+ struct super_block *sb;
32321+
1facf9fc 32322+ file = arg->file;
2000de60 32323+ sb = file->f_path.dentry->d_sb;
dece6358
AM
32324+ SiMustAnyLock(sb);
32325+
32326+ rdhash = au_sbi(sb)->si_rdhash;
1308ab2a 32327+ if (!rdhash)
32328+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
dece6358
AM
32329+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
32330+ if (unlikely(err))
1facf9fc 32331+ goto out;
dece6358
AM
32332+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
32333+ if (unlikely(err))
1facf9fc 32334+ goto out_delist;
32335+
32336+ err = 0;
32337+ arg->flags = 0;
dece6358
AM
32338+ shwh = 0;
32339+ if (au_opt_test(au_mntflags(sb), SHWH)) {
32340+ shwh = 1;
32341+ au_fset_fillvdir(arg->flags, SHWH);
32342+ }
5afbbe0d
AM
32343+ btop = au_fbtop(file);
32344+ bbot = au_fbbot_dir(file);
32345+ for (bindex = btop; !err && bindex <= bbot; bindex++) {
4a4d8108 32346+ hf = au_hf_dir(file, bindex);
1facf9fc 32347+ if (!hf)
32348+ continue;
32349+
32350+ offset = vfsub_llseek(hf, 0, SEEK_SET);
32351+ err = offset;
32352+ if (unlikely(offset))
32353+ break;
32354+
32355+ arg->bindex = bindex;
32356+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358 32357+ if (shwh
5afbbe0d 32358+ || (bindex != bbot
dece6358 32359+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 32360+ au_fset_fillvdir(arg->flags, WHABLE);
32361+ do {
32362+ arg->err = 0;
32363+ au_fclr_fillvdir(arg->flags, CALLED);
32364+ /* smp_mb(); */
392086de 32365+ err = vfsub_iterate_dir(hf, &arg->ctx);
1facf9fc 32366+ if (err >= 0)
32367+ err = arg->err;
32368+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
392086de
AM
32369+
32370+ /*
32371+ * dir_relax() may be good for concurrency, but aufs should not
32372+ * use it since it will cause a lockdep problem.
32373+ */
1facf9fc 32374+ }
dece6358
AM
32375+
32376+ if (!err && shwh)
32377+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
32378+
32379+ au_nhash_wh_free(&arg->whlist);
1facf9fc 32380+
4f0767ce 32381+out_delist:
dece6358 32382+ au_nhash_de_free(&arg->delist);
4f0767ce 32383+out:
1facf9fc 32384+ return err;
32385+}
32386+
32387+static int read_vdir(struct file *file, int may_read)
32388+{
32389+ int err;
32390+ unsigned long expire;
32391+ unsigned char do_read;
392086de
AM
32392+ struct fillvdir_arg arg = {
32393+ .ctx = {
2000de60 32394+ .actor = fillvdir
392086de
AM
32395+ }
32396+ };
1facf9fc 32397+ struct inode *inode;
32398+ struct au_vdir *vdir, *allocated;
32399+
32400+ err = 0;
c06a8ce3 32401+ inode = file_inode(file);
1facf9fc 32402+ IMustLock(inode);
5afbbe0d 32403+ IiMustWriteLock(inode);
dece6358
AM
32404+ SiMustAnyLock(inode->i_sb);
32405+
1facf9fc 32406+ allocated = NULL;
32407+ do_read = 0;
32408+ expire = au_sbi(inode->i_sb)->si_rdcache;
32409+ vdir = au_ivdir(inode);
32410+ if (!vdir) {
32411+ do_read = 1;
1308ab2a 32412+ vdir = alloc_vdir(file);
1facf9fc 32413+ err = PTR_ERR(vdir);
32414+ if (IS_ERR(vdir))
32415+ goto out;
32416+ err = 0;
32417+ allocated = vdir;
32418+ } else if (may_read
be118d29 32419+ && (!inode_eq_iversion(inode, vdir->vd_version)
1facf9fc 32420+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
32421+ do_read = 1;
32422+ err = reinit_vdir(vdir);
32423+ if (unlikely(err))
32424+ goto out;
32425+ }
32426+
32427+ if (!do_read)
32428+ return 0; /* success */
32429+
32430+ arg.file = file;
32431+ arg.vdir = vdir;
32432+ err = au_do_read_vdir(&arg);
32433+ if (!err) {
392086de 32434+ /* file->f_pos = 0; */ /* todo: ctx->pos? */
be118d29 32435+ vdir->vd_version = inode_query_iversion(inode);
1facf9fc 32436+ vdir->vd_last.ul = 0;
32437+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
32438+ if (allocated)
32439+ au_set_ivdir(inode, allocated);
32440+ } else if (allocated)
1c60b727 32441+ au_vdir_free(allocated);
1facf9fc 32442+
4f0767ce 32443+out:
1facf9fc 32444+ return err;
32445+}
32446+
32447+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
32448+{
32449+ int err, rerr;
32450+ unsigned long ul, n;
32451+ const unsigned int deblk_sz = src->vd_deblk_sz;
32452+
32453+ AuDebugOn(tgt->vd_nblk != 1);
32454+
32455+ err = -ENOMEM;
32456+ if (tgt->vd_nblk < src->vd_nblk) {
32457+ unsigned char **p;
32458+
e2f27e51
AM
32459+ p = au_krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
32460+ GFP_NOFS, /*may_shrink*/0);
1facf9fc 32461+ if (unlikely(!p))
32462+ goto out;
32463+ tgt->vd_deblk = p;
32464+ }
32465+
1308ab2a 32466+ if (tgt->vd_deblk_sz != deblk_sz) {
32467+ unsigned char *p;
32468+
32469+ tgt->vd_deblk_sz = deblk_sz;
e2f27e51
AM
32470+ p = au_krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS,
32471+ /*may_shrink*/1);
1308ab2a 32472+ if (unlikely(!p))
32473+ goto out;
32474+ tgt->vd_deblk[0] = p;
32475+ }
1facf9fc 32476+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
1facf9fc 32477+ tgt->vd_version = src->vd_version;
32478+ tgt->vd_jiffy = src->vd_jiffy;
32479+
32480+ n = src->vd_nblk;
32481+ for (ul = 1; ul < n; ul++) {
dece6358
AM
32482+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
32483+ GFP_NOFS);
32484+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 32485+ goto out;
1308ab2a 32486+ tgt->vd_nblk++;
1facf9fc 32487+ }
1308ab2a 32488+ tgt->vd_nblk = n;
32489+ tgt->vd_last.ul = tgt->vd_last.ul;
32490+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
32491+ tgt->vd_last.p.deblk += src->vd_last.p.deblk
32492+ - src->vd_deblk[src->vd_last.ul];
1facf9fc 32493+ /* smp_mb(); */
32494+ return 0; /* success */
32495+
4f0767ce 32496+out:
1facf9fc 32497+ rerr = reinit_vdir(tgt);
32498+ BUG_ON(rerr);
32499+ return err;
32500+}
32501+
32502+int au_vdir_init(struct file *file)
32503+{
32504+ int err;
32505+ struct inode *inode;
32506+ struct au_vdir *vdir_cache, *allocated;
32507+
392086de 32508+ /* test file->f_pos here instead of ctx->pos */
1facf9fc 32509+ err = read_vdir(file, !file->f_pos);
32510+ if (unlikely(err))
32511+ goto out;
32512+
32513+ allocated = NULL;
32514+ vdir_cache = au_fvdir_cache(file);
32515+ if (!vdir_cache) {
1308ab2a 32516+ vdir_cache = alloc_vdir(file);
1facf9fc 32517+ err = PTR_ERR(vdir_cache);
32518+ if (IS_ERR(vdir_cache))
32519+ goto out;
32520+ allocated = vdir_cache;
32521+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
392086de 32522+ /* test file->f_pos here instead of ctx->pos */
1facf9fc 32523+ err = reinit_vdir(vdir_cache);
32524+ if (unlikely(err))
32525+ goto out;
32526+ } else
32527+ return 0; /* success */
32528+
c06a8ce3 32529+ inode = file_inode(file);
1facf9fc 32530+ err = copy_vdir(vdir_cache, au_ivdir(inode));
32531+ if (!err) {
be118d29 32532+ file->f_version = inode_query_iversion(inode);
1facf9fc 32533+ if (allocated)
32534+ au_set_fvdir_cache(file, allocated);
32535+ } else if (allocated)
1c60b727 32536+ au_vdir_free(allocated);
1facf9fc 32537+
4f0767ce 32538+out:
1facf9fc 32539+ return err;
32540+}
32541+
32542+static loff_t calc_offset(struct au_vdir *vdir)
32543+{
32544+ loff_t offset;
32545+ union au_vdir_deblk_p p;
32546+
32547+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
32548+ offset = vdir->vd_last.p.deblk - p.deblk;
32549+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
32550+ return offset;
32551+}
32552+
32553+/* returns true or false */
392086de 32554+static int seek_vdir(struct file *file, struct dir_context *ctx)
1facf9fc 32555+{
32556+ int valid;
32557+ unsigned int deblk_sz;
32558+ unsigned long ul, n;
32559+ loff_t offset;
32560+ union au_vdir_deblk_p p, deblk_end;
32561+ struct au_vdir *vdir_cache;
32562+
32563+ valid = 1;
32564+ vdir_cache = au_fvdir_cache(file);
32565+ offset = calc_offset(vdir_cache);
32566+ AuDbg("offset %lld\n", offset);
392086de 32567+ if (ctx->pos == offset)
1facf9fc 32568+ goto out;
32569+
32570+ vdir_cache->vd_last.ul = 0;
32571+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
392086de 32572+ if (!ctx->pos)
1facf9fc 32573+ goto out;
32574+
32575+ valid = 0;
32576+ deblk_sz = vdir_cache->vd_deblk_sz;
392086de 32577+ ul = div64_u64(ctx->pos, deblk_sz);
1facf9fc 32578+ AuDbg("ul %lu\n", ul);
32579+ if (ul >= vdir_cache->vd_nblk)
32580+ goto out;
32581+
32582+ n = vdir_cache->vd_nblk;
32583+ for (; ul < n; ul++) {
32584+ p.deblk = vdir_cache->vd_deblk[ul];
32585+ deblk_end.deblk = p.deblk + deblk_sz;
32586+ offset = ul;
32587+ offset *= deblk_sz;
392086de 32588+ while (!is_deblk_end(&p, &deblk_end) && offset < ctx->pos) {
1facf9fc 32589+ unsigned int l;
32590+
32591+ l = calc_size(p.de->de_str.len);
32592+ offset += l;
32593+ p.deblk += l;
32594+ }
32595+ if (!is_deblk_end(&p, &deblk_end)) {
32596+ valid = 1;
32597+ vdir_cache->vd_last.ul = ul;
32598+ vdir_cache->vd_last.p = p;
32599+ break;
32600+ }
32601+ }
32602+
4f0767ce 32603+out:
1facf9fc 32604+ /* smp_mb(); */
b00004a5
AM
32605+ if (!valid)
32606+ AuDbg("valid %d\n", !valid);
1facf9fc 32607+ return valid;
32608+}
32609+
392086de 32610+int au_vdir_fill_de(struct file *file, struct dir_context *ctx)
1facf9fc 32611+{
1facf9fc 32612+ unsigned int l, deblk_sz;
32613+ union au_vdir_deblk_p deblk_end;
32614+ struct au_vdir *vdir_cache;
32615+ struct au_vdir_de *de;
32616+
392086de 32617+ if (!seek_vdir(file, ctx))
1facf9fc 32618+ return 0;
32619+
acd2b654 32620+ vdir_cache = au_fvdir_cache(file);
1facf9fc 32621+ deblk_sz = vdir_cache->vd_deblk_sz;
32622+ while (1) {
32623+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
32624+ deblk_end.deblk += deblk_sz;
32625+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
32626+ de = vdir_cache->vd_last.p.de;
32627+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
392086de 32628+ de->de_str.len, de->de_str.name, ctx->pos,
1facf9fc 32629+ (unsigned long)de->de_ino, de->de_type);
392086de
AM
32630+ if (unlikely(!dir_emit(ctx, de->de_str.name,
32631+ de->de_str.len, de->de_ino,
32632+ de->de_type))) {
1facf9fc 32633+ /* todo: ignore the error caused by udba? */
32634+ /* return err; */
32635+ return 0;
32636+ }
32637+
32638+ l = calc_size(de->de_str.len);
32639+ vdir_cache->vd_last.p.deblk += l;
392086de 32640+ ctx->pos += l;
1facf9fc 32641+ }
32642+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
32643+ vdir_cache->vd_last.ul++;
32644+ vdir_cache->vd_last.p.deblk
32645+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
392086de 32646+ ctx->pos = deblk_sz * vdir_cache->vd_last.ul;
1facf9fc 32647+ continue;
32648+ }
32649+ break;
32650+ }
32651+
32652+ /* smp_mb(); */
32653+ return 0;
32654+}
7f207e10 32655diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
eca34b5c 32656--- /usr/share/empty/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6
JR
32657+++ linux/fs/aufs/vfsub.c 2021-05-02 20:15:14.676670793 +0200
32658@@ -0,0 +1,916 @@
cd7a4cd9 32659+// SPDX-License-Identifier: GPL-2.0
1facf9fc 32660+/*
d58c55f2 32661+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 32662+ *
32663+ * This program, aufs is free software; you can redistribute it and/or modify
32664+ * it under the terms of the GNU General Public License as published by
32665+ * the Free Software Foundation; either version 2 of the License, or
32666+ * (at your option) any later version.
dece6358
AM
32667+ *
32668+ * This program is distributed in the hope that it will be useful,
32669+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
32670+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32671+ * GNU General Public License for more details.
32672+ *
32673+ * You should have received a copy of the GNU General Public License
523b37e3 32674+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 32675+ */
32676+
32677+/*
32678+ * sub-routines for VFS
32679+ */
32680+
8b6a4947 32681+#include <linux/mnt_namespace.h>
dece6358 32682+#include <linux/namei.h>
8cdd5066 32683+#include <linux/nsproxy.h>
dece6358
AM
32684+#include <linux/security.h>
32685+#include <linux/splice.h>
1facf9fc 32686+#include "aufs.h"
32687+
8cdd5066
JR
32688+#ifdef CONFIG_AUFS_BR_FUSE
32689+int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb)
32690+{
8cdd5066
JR
32691+ if (!au_test_fuse(h_sb) || !au_userns)
32692+ return 0;
32693+
8b6a4947 32694+ return is_current_mnt_ns(mnt) ? 0 : -EACCES;
8cdd5066
JR
32695+}
32696+#endif
32697+
a2654f78
AM
32698+int vfsub_sync_filesystem(struct super_block *h_sb, int wait)
32699+{
32700+ int err;
32701+
32702+ lockdep_off();
32703+ down_read(&h_sb->s_umount);
32704+ err = __sync_filesystem(h_sb, wait);
32705+ up_read(&h_sb->s_umount);
32706+ lockdep_on();
32707+
32708+ return err;
32709+}
32710+
8cdd5066
JR
32711+/* ---------------------------------------------------------------------- */
32712+
1facf9fc 32713+int vfsub_update_h_iattr(struct path *h_path, int *did)
32714+{
32715+ int err;
32716+ struct kstat st;
32717+ struct super_block *h_sb;
32718+
32719+ /* for remote fs, leave work for its getattr or d_revalidate */
32720+ /* for bad i_attr fs, handle them in aufs_getattr() */
32721+ /* still some fs may acquire i_mutex. we need to skip them */
32722+ err = 0;
32723+ if (!did)
32724+ did = &err;
32725+ h_sb = h_path->dentry->d_sb;
32726+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
32727+ if (*did)
521ced18 32728+ err = vfsub_getattr(h_path, &st);
1facf9fc 32729+
32730+ return err;
32731+}
32732+
32733+/* ---------------------------------------------------------------------- */
32734+
4a4d8108 32735+struct file *vfsub_dentry_open(struct path *path, int flags)
1308ab2a 32736+{
42b5c33a 32737+ return dentry_open(path, flags /* | __FMODE_NONOTIFY */,
7f207e10 32738+ current_cred());
1308ab2a 32739+}
32740+
1facf9fc 32741+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
32742+{
32743+ struct file *file;
32744+
2cbb1c4b 32745+ lockdep_off();
7f207e10 32746+ file = filp_open(path,
2cbb1c4b 32747+ oflags /* | __FMODE_NONOTIFY */,
7f207e10 32748+ mode);
2cbb1c4b 32749+ lockdep_on();
1facf9fc 32750+ if (IS_ERR(file))
32751+ goto out;
32752+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
32753+
4f0767ce 32754+out:
1facf9fc 32755+ return file;
32756+}
32757+
b912730e
AM
32758+/*
32759+ * Ideally this function should call VFS:do_last() in order to keep all its
32760+ * checkings. But it is very hard for aufs to regenerate several VFS internal
32761+ * structure such as nameidata. This is a second (or third) best approach.
32762+ * cf. linux/fs/namei.c:do_last(), lookup_open() and atomic_open().
32763+ */
32764+int vfsub_atomic_open(struct inode *dir, struct dentry *dentry,
acd2b654 32765+ struct vfsub_aopen_args *args)
b912730e
AM
32766+{
32767+ int err;
acd2b654 32768+ struct au_branch *br = args->br;
b912730e
AM
32769+ struct file *file = args->file;
32770+ /* copied from linux/fs/namei.c:atomic_open() */
32771+ struct dentry *const DENTRY_NOT_SET = (void *)-1UL;
32772+
32773+ IMustLock(dir);
32774+ AuDebugOn(!dir->i_op->atomic_open);
32775+
32776+ err = au_br_test_oflag(args->open_flag, br);
32777+ if (unlikely(err))
32778+ goto out;
32779+
acd2b654
AM
32780+ au_lcnt_inc(&br->br_nfiles);
32781+ file->f_path.dentry = DENTRY_NOT_SET;
32782+ file->f_path.mnt = au_br_mnt(br);
32783+ AuDbg("%ps\n", dir->i_op->atomic_open);
b912730e 32784+ err = dir->i_op->atomic_open(dir, dentry, file, args->open_flag,
acd2b654
AM
32785+ args->create_mode);
32786+ if (unlikely(err < 0)) {
32787+ au_lcnt_dec(&br->br_nfiles);
b912730e 32788+ goto out;
acd2b654 32789+ }
b912730e 32790+
acd2b654
AM
32791+ /* temporary workaround for nfsv4 branch */
32792+ if (au_test_nfs(dir->i_sb))
32793+ nfs_mark_for_revalidate(dir);
b912730e 32794+
acd2b654
AM
32795+ if (file->f_mode & FMODE_CREATED)
32796+ fsnotify_create(dir, dentry);
32797+ if (!(file->f_mode & FMODE_OPENED)) {
32798+ au_lcnt_dec(&br->br_nfiles);
32799+ goto out;
b912730e
AM
32800+ }
32801+
acd2b654
AM
32802+ /* todo: call VFS:may_open() here */
32803+ /* todo: ima_file_check() too? */
32804+ if (!err && (args->open_flag & __FMODE_EXEC))
32805+ err = deny_write_access(file);
32806+ if (!err)
32807+ fsnotify_open(file);
32808+ else
32809+ au_lcnt_dec(&br->br_nfiles);
32810+ /* note that the file is created and still opened */
b912730e
AM
32811+
32812+out:
32813+ return err;
32814+}
32815+
1facf9fc 32816+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
32817+{
32818+ int err;
32819+
1facf9fc 32820+ err = kern_path(name, flags, path);
5527c038 32821+ if (!err && d_is_positive(path->dentry))
1facf9fc 32822+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
32823+ return err;
32824+}
32825+
febd17d6
JR
32826+struct dentry *vfsub_lookup_one_len_unlocked(const char *name,
32827+ struct dentry *parent, int len)
32828+{
32829+ struct path path = {
32830+ .mnt = NULL
32831+ };
32832+
32833+ path.dentry = lookup_one_len_unlocked(name, parent, len);
32834+ if (IS_ERR(path.dentry))
32835+ goto out;
32836+ if (d_is_positive(path.dentry))
32837+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
32838+
32839+out:
32840+ AuTraceErrPtr(path.dentry);
32841+ return path.dentry;
32842+}
32843+
1facf9fc 32844+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
32845+ int len)
32846+{
32847+ struct path path = {
32848+ .mnt = NULL
32849+ };
32850+
1308ab2a 32851+ /* VFS checks it too, but by WARN_ON_ONCE() */
5527c038 32852+ IMustLock(d_inode(parent));
1facf9fc 32853+
32854+ path.dentry = lookup_one_len(name, parent, len);
32855+ if (IS_ERR(path.dentry))
32856+ goto out;
5527c038 32857+ if (d_is_positive(path.dentry))
1facf9fc 32858+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
32859+
4f0767ce 32860+out:
4a4d8108 32861+ AuTraceErrPtr(path.dentry);
1facf9fc 32862+ return path.dentry;
32863+}
32864+
b4510431 32865+void vfsub_call_lkup_one(void *args)
2cbb1c4b 32866+{
b4510431
AM
32867+ struct vfsub_lkup_one_args *a = args;
32868+ *a->errp = vfsub_lkup_one(a->name, a->parent);
2cbb1c4b
JR
32869+}
32870+
1facf9fc 32871+/* ---------------------------------------------------------------------- */
32872+
32873+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
32874+ struct dentry *d2, struct au_hinode *hdir2)
32875+{
32876+ struct dentry *d;
32877+
2cbb1c4b 32878+ lockdep_off();
1facf9fc 32879+ d = lock_rename(d1, d2);
2cbb1c4b 32880+ lockdep_on();
4a4d8108 32881+ au_hn_suspend(hdir1);
1facf9fc 32882+ if (hdir1 != hdir2)
4a4d8108 32883+ au_hn_suspend(hdir2);
1facf9fc 32884+
32885+ return d;
32886+}
32887+
32888+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
32889+ struct dentry *d2, struct au_hinode *hdir2)
32890+{
4a4d8108 32891+ au_hn_resume(hdir1);
1facf9fc 32892+ if (hdir1 != hdir2)
4a4d8108 32893+ au_hn_resume(hdir2);
2cbb1c4b 32894+ lockdep_off();
1facf9fc 32895+ unlock_rename(d1, d2);
2cbb1c4b 32896+ lockdep_on();
1facf9fc 32897+}
32898+
32899+/* ---------------------------------------------------------------------- */
32900+
b4510431 32901+int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl)
1facf9fc 32902+{
32903+ int err;
32904+ struct dentry *d;
0b2a12c6 32905+ struct user_namespace *userns;
1facf9fc 32906+
32907+ IMustLock(dir);
32908+
32909+ d = path->dentry;
32910+ path->dentry = d->d_parent;
b752ccd1 32911+ err = security_path_mknod(path, d, mode, 0);
1facf9fc 32912+ path->dentry = d;
32913+ if (unlikely(err))
32914+ goto out;
0b2a12c6 32915+ userns = mnt_user_ns(path->mnt);
1facf9fc 32916+
c1595e42 32917+ lockdep_off();
0b2a12c6 32918+ err = vfs_create(userns, dir, path->dentry, mode, want_excl);
c1595e42 32919+ lockdep_on();
1facf9fc 32920+ if (!err) {
32921+ struct path tmp = *path;
32922+ int did;
32923+
32924+ vfsub_update_h_iattr(&tmp, &did);
32925+ if (did) {
32926+ tmp.dentry = path->dentry->d_parent;
32927+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
32928+ }
32929+ /*ignore*/
32930+ }
32931+
4f0767ce 32932+out:
1facf9fc 32933+ return err;
32934+}
32935+
32936+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
32937+{
32938+ int err;
32939+ struct dentry *d;
0b2a12c6 32940+ struct user_namespace *userns;
1facf9fc 32941+
32942+ IMustLock(dir);
32943+
32944+ d = path->dentry;
32945+ path->dentry = d->d_parent;
b752ccd1 32946+ err = security_path_symlink(path, d, symname);
1facf9fc 32947+ path->dentry = d;
32948+ if (unlikely(err))
32949+ goto out;
0b2a12c6 32950+ userns = mnt_user_ns(path->mnt);
1facf9fc 32951+
c1595e42 32952+ lockdep_off();
0b2a12c6 32953+ err = vfs_symlink(userns, dir, path->dentry, symname);
c1595e42 32954+ lockdep_on();
1facf9fc 32955+ if (!err) {
32956+ struct path tmp = *path;
32957+ int did;
32958+
32959+ vfsub_update_h_iattr(&tmp, &did);
32960+ if (did) {
32961+ tmp.dentry = path->dentry->d_parent;
32962+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
32963+ }
32964+ /*ignore*/
32965+ }
32966+
4f0767ce 32967+out:
1facf9fc 32968+ return err;
32969+}
32970+
32971+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
32972+{
32973+ int err;
32974+ struct dentry *d;
0b2a12c6 32975+ struct user_namespace *userns;
1facf9fc 32976+
32977+ IMustLock(dir);
32978+
32979+ d = path->dentry;
32980+ path->dentry = d->d_parent;
027c5e7a 32981+ err = security_path_mknod(path, d, mode, new_encode_dev(dev));
1facf9fc 32982+ path->dentry = d;
32983+ if (unlikely(err))
32984+ goto out;
0b2a12c6 32985+ userns = mnt_user_ns(path->mnt);
1facf9fc 32986+
c1595e42 32987+ lockdep_off();
0b2a12c6 32988+ err = vfs_mknod(userns, dir, path->dentry, mode, dev);
c1595e42 32989+ lockdep_on();
1facf9fc 32990+ if (!err) {
32991+ struct path tmp = *path;
32992+ int did;
32993+
32994+ vfsub_update_h_iattr(&tmp, &did);
32995+ if (did) {
32996+ tmp.dentry = path->dentry->d_parent;
32997+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
32998+ }
32999+ /*ignore*/
33000+ }
33001+
4f0767ce 33002+out:
1facf9fc 33003+ return err;
33004+}
33005+
33006+static int au_test_nlink(struct inode *inode)
33007+{
33008+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
33009+
33010+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
33011+ || inode->i_nlink < link_max)
33012+ return 0;
33013+ return -EMLINK;
33014+}
33015+
523b37e3
AM
33016+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path,
33017+ struct inode **delegated_inode)
1facf9fc 33018+{
33019+ int err;
33020+ struct dentry *d;
0b2a12c6 33021+ struct user_namespace *userns;
1facf9fc 33022+
33023+ IMustLock(dir);
33024+
5527c038 33025+ err = au_test_nlink(d_inode(src_dentry));
1facf9fc 33026+ if (unlikely(err))
33027+ return err;
33028+
b4510431 33029+ /* we don't call may_linkat() */
1facf9fc 33030+ d = path->dentry;
33031+ path->dentry = d->d_parent;
b752ccd1 33032+ err = security_path_link(src_dentry, path, d);
1facf9fc 33033+ path->dentry = d;
33034+ if (unlikely(err))
33035+ goto out;
0b2a12c6 33036+ userns = mnt_user_ns(path->mnt);
1facf9fc 33037+
2cbb1c4b 33038+ lockdep_off();
0b2a12c6 33039+ err = vfs_link(src_dentry, userns, dir, path->dentry, delegated_inode);
2cbb1c4b 33040+ lockdep_on();
1facf9fc 33041+ if (!err) {
33042+ struct path tmp = *path;
33043+ int did;
33044+
33045+ /* fuse has different memory inode for the same inumber */
33046+ vfsub_update_h_iattr(&tmp, &did);
33047+ if (did) {
33048+ tmp.dentry = path->dentry->d_parent;
33049+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33050+ tmp.dentry = src_dentry;
33051+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33052+ }
33053+ /*ignore*/
33054+ }
33055+
4f0767ce 33056+out:
1facf9fc 33057+ return err;
33058+}
33059+
33060+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
523b37e3 33061+ struct inode *dir, struct path *path,
f2c43d5f 33062+ struct inode **delegated_inode, unsigned int flags)
1facf9fc 33063+{
33064+ int err;
0b2a12c6 33065+ struct renamedata rd;
1facf9fc 33066+ struct path tmp = {
33067+ .mnt = path->mnt
33068+ };
33069+ struct dentry *d;
33070+
33071+ IMustLock(dir);
33072+ IMustLock(src_dir);
33073+
33074+ d = path->dentry;
33075+ path->dentry = d->d_parent;
33076+ tmp.dentry = src_dentry->d_parent;
38d290e6 33077+ err = security_path_rename(&tmp, src_dentry, path, d, /*flags*/0);
1facf9fc 33078+ path->dentry = d;
33079+ if (unlikely(err))
33080+ goto out;
33081+
0b2a12c6
JR
33082+ rd.old_mnt_userns = mnt_user_ns(path->mnt);
33083+ rd.old_dir = src_dir;
33084+ rd.old_dentry = src_dentry;
33085+ rd.new_mnt_userns = rd.old_mnt_userns;
33086+ rd.new_dir = dir;
33087+ rd.new_dentry = path->dentry;
33088+ rd.delegated_inode = delegated_inode;
33089+ rd.flags = flags;
2cbb1c4b 33090+ lockdep_off();
0b2a12c6 33091+ err = vfs_rename(&rd);
2cbb1c4b 33092+ lockdep_on();
1facf9fc 33093+ if (!err) {
33094+ int did;
33095+
33096+ tmp.dentry = d->d_parent;
33097+ vfsub_update_h_iattr(&tmp, &did);
33098+ if (did) {
33099+ tmp.dentry = src_dentry;
33100+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33101+ tmp.dentry = src_dentry->d_parent;
33102+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33103+ }
33104+ /*ignore*/
33105+ }
33106+
4f0767ce 33107+out:
1facf9fc 33108+ return err;
33109+}
33110+
33111+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
33112+{
33113+ int err;
33114+ struct dentry *d;
0b2a12c6 33115+ struct user_namespace *userns;
1facf9fc 33116+
33117+ IMustLock(dir);
33118+
33119+ d = path->dentry;
33120+ path->dentry = d->d_parent;
b752ccd1 33121+ err = security_path_mkdir(path, d, mode);
1facf9fc 33122+ path->dentry = d;
33123+ if (unlikely(err))
33124+ goto out;
0b2a12c6 33125+ userns = mnt_user_ns(path->mnt);
1facf9fc 33126+
c1595e42 33127+ lockdep_off();
0b2a12c6 33128+ err = vfs_mkdir(userns, dir, path->dentry, mode);
c1595e42 33129+ lockdep_on();
1facf9fc 33130+ if (!err) {
33131+ struct path tmp = *path;
33132+ int did;
33133+
33134+ vfsub_update_h_iattr(&tmp, &did);
33135+ if (did) {
33136+ tmp.dentry = path->dentry->d_parent;
33137+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33138+ }
33139+ /*ignore*/
33140+ }
33141+
4f0767ce 33142+out:
1facf9fc 33143+ return err;
33144+}
33145+
33146+int vfsub_rmdir(struct inode *dir, struct path *path)
33147+{
33148+ int err;
33149+ struct dentry *d;
0b2a12c6 33150+ struct user_namespace *userns;
1facf9fc 33151+
33152+ IMustLock(dir);
33153+
33154+ d = path->dentry;
33155+ path->dentry = d->d_parent;
b752ccd1 33156+ err = security_path_rmdir(path, d);
1facf9fc 33157+ path->dentry = d;
33158+ if (unlikely(err))
33159+ goto out;
0b2a12c6 33160+ userns = mnt_user_ns(path->mnt);
1facf9fc 33161+
2cbb1c4b 33162+ lockdep_off();
0b2a12c6 33163+ err = vfs_rmdir(userns, dir, path->dentry);
2cbb1c4b 33164+ lockdep_on();
1facf9fc 33165+ if (!err) {
33166+ struct path tmp = {
33167+ .dentry = path->dentry->d_parent,
33168+ .mnt = path->mnt
33169+ };
33170+
33171+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
33172+ }
33173+
4f0767ce 33174+out:
1facf9fc 33175+ return err;
33176+}
33177+
33178+/* ---------------------------------------------------------------------- */
33179+
9dbd164d 33180+/* todo: support mmap_sem? */
1facf9fc 33181+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
33182+ loff_t *ppos)
33183+{
33184+ ssize_t err;
33185+
2cbb1c4b 33186+ lockdep_off();
1facf9fc 33187+ err = vfs_read(file, ubuf, count, ppos);
2cbb1c4b 33188+ lockdep_on();
1facf9fc 33189+ if (err >= 0)
33190+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
33191+ return err;
33192+}
33193+
1facf9fc 33194+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
33195+ loff_t *ppos)
33196+{
33197+ ssize_t err;
1facf9fc 33198+
e37dd06a
AM
33199+ lockdep_off();
33200+ err = kernel_read(file, kbuf, count, ppos);
33201+ lockdep_on();
33202+ AuTraceErr(err);
33203+ if (err >= 0)
33204+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
1facf9fc 33205+ return err;
33206+}
33207+
33208+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
33209+ loff_t *ppos)
33210+{
33211+ ssize_t err;
33212+
2cbb1c4b 33213+ lockdep_off();
1facf9fc 33214+ err = vfs_write(file, ubuf, count, ppos);
2cbb1c4b 33215+ lockdep_on();
1facf9fc 33216+ if (err >= 0)
33217+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
33218+ return err;
33219+}
33220+
33221+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
33222+{
33223+ ssize_t err;
1facf9fc 33224+
e37dd06a
AM
33225+ lockdep_off();
33226+ err = kernel_write(file, kbuf, count, ppos);
33227+ lockdep_on();
33228+ if (err >= 0)
33229+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
1facf9fc 33230+ return err;
33231+}
33232+
4a4d8108
AM
33233+int vfsub_flush(struct file *file, fl_owner_t id)
33234+{
33235+ int err;
33236+
33237+ err = 0;
523b37e3 33238+ if (file->f_op->flush) {
2000de60 33239+ if (!au_test_nfs(file->f_path.dentry->d_sb))
2cbb1c4b
JR
33240+ err = file->f_op->flush(file, id);
33241+ else {
33242+ lockdep_off();
33243+ err = file->f_op->flush(file, id);
33244+ lockdep_on();
33245+ }
4a4d8108
AM
33246+ if (!err)
33247+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
33248+ /*ignore*/
33249+ }
33250+ return err;
33251+}
33252+
392086de 33253+int vfsub_iterate_dir(struct file *file, struct dir_context *ctx)
1facf9fc 33254+{
33255+ int err;
33256+
062440b3 33257+ AuDbg("%pD, ctx{%ps, %llu}\n", file, ctx->actor, ctx->pos);
392086de 33258+
2cbb1c4b 33259+ lockdep_off();
392086de 33260+ err = iterate_dir(file, ctx);
2cbb1c4b 33261+ lockdep_on();
1facf9fc 33262+ if (err >= 0)
33263+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
1c60b727 33264+
1facf9fc 33265+ return err;
33266+}
33267+
33268+long vfsub_splice_to(struct file *in, loff_t *ppos,
33269+ struct pipe_inode_info *pipe, size_t len,
33270+ unsigned int flags)
33271+{
33272+ long err;
33273+
2cbb1c4b 33274+ lockdep_off();
0fc653ad 33275+ err = do_splice_to(in, ppos, pipe, len, flags);
2cbb1c4b 33276+ lockdep_on();
4a4d8108 33277+ file_accessed(in);
1facf9fc 33278+ if (err >= 0)
33279+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
33280+ return err;
33281+}
33282+
33283+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
33284+ loff_t *ppos, size_t len, unsigned int flags)
33285+{
33286+ long err;
33287+
2cbb1c4b 33288+ lockdep_off();
0fc653ad 33289+ err = do_splice_from(pipe, out, ppos, len, flags);
2cbb1c4b 33290+ lockdep_on();
1facf9fc 33291+ if (err >= 0)
33292+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
33293+ return err;
33294+}
33295+
53392da6
AM
33296+int vfsub_fsync(struct file *file, struct path *path, int datasync)
33297+{
33298+ int err;
33299+
33300+ /* file can be NULL */
33301+ lockdep_off();
33302+ err = vfs_fsync(file, datasync);
33303+ lockdep_on();
33304+ if (!err) {
33305+ if (!path) {
33306+ AuDebugOn(!file);
33307+ path = &file->f_path;
33308+ }
33309+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
33310+ }
33311+ return err;
33312+}
33313+
1facf9fc 33314+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
33315+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
33316+ struct file *h_file)
33317+{
33318+ int err;
33319+ struct inode *h_inode;
c06a8ce3 33320+ struct super_block *h_sb;
0b2a12c6 33321+ struct user_namespace *h_userns;
1facf9fc 33322+
1facf9fc 33323+ if (!h_file) {
c06a8ce3
AM
33324+ err = vfsub_truncate(h_path, length);
33325+ goto out;
1facf9fc 33326+ }
33327+
5527c038 33328+ h_inode = d_inode(h_path->dentry);
c06a8ce3
AM
33329+ h_sb = h_inode->i_sb;
33330+ lockdep_off();
33331+ sb_start_write(h_sb);
33332+ lockdep_on();
1facf9fc 33333+ err = locks_verify_truncate(h_inode, h_file, length);
33334+ if (!err)
953406b4 33335+ err = security_path_truncate(h_path);
2cbb1c4b 33336+ if (!err) {
0b2a12c6 33337+ h_userns = mnt_user_ns(h_path->mnt);
2cbb1c4b 33338+ lockdep_off();
0b2a12c6
JR
33339+ err = do_truncate(h_userns, h_path->dentry, length, attr,
33340+ h_file);
2cbb1c4b
JR
33341+ lockdep_on();
33342+ }
c06a8ce3
AM
33343+ lockdep_off();
33344+ sb_end_write(h_sb);
33345+ lockdep_on();
1facf9fc 33346+
4f0767ce 33347+out:
1facf9fc 33348+ return err;
33349+}
33350+
33351+/* ---------------------------------------------------------------------- */
33352+
33353+struct au_vfsub_mkdir_args {
33354+ int *errp;
33355+ struct inode *dir;
33356+ struct path *path;
33357+ int mode;
33358+};
33359+
33360+static void au_call_vfsub_mkdir(void *args)
33361+{
33362+ struct au_vfsub_mkdir_args *a = args;
33363+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
33364+}
33365+
33366+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
33367+{
33368+ int err, do_sio, wkq_err;
0b2a12c6 33369+ struct user_namespace *userns;
1facf9fc 33370+
0b2a12c6
JR
33371+ userns = mnt_user_ns(path->mnt);
33372+ do_sio = au_test_h_perm_sio(userns, dir, MAY_EXEC | MAY_WRITE);
c1595e42
JR
33373+ if (!do_sio) {
33374+ lockdep_off();
1facf9fc 33375+ err = vfsub_mkdir(dir, path, mode);
c1595e42
JR
33376+ lockdep_on();
33377+ } else {
1facf9fc 33378+ struct au_vfsub_mkdir_args args = {
33379+ .errp = &err,
33380+ .dir = dir,
33381+ .path = path,
33382+ .mode = mode
33383+ };
33384+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
33385+ if (unlikely(wkq_err))
33386+ err = wkq_err;
33387+ }
33388+
33389+ return err;
33390+}
33391+
33392+struct au_vfsub_rmdir_args {
33393+ int *errp;
33394+ struct inode *dir;
33395+ struct path *path;
33396+};
33397+
33398+static void au_call_vfsub_rmdir(void *args)
33399+{
33400+ struct au_vfsub_rmdir_args *a = args;
33401+ *a->errp = vfsub_rmdir(a->dir, a->path);
33402+}
33403+
33404+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
33405+{
33406+ int err, do_sio, wkq_err;
0b2a12c6 33407+ struct user_namespace *userns;
1facf9fc 33408+
0b2a12c6
JR
33409+ userns = mnt_user_ns(path->mnt);
33410+ do_sio = au_test_h_perm_sio(userns, dir, MAY_EXEC | MAY_WRITE);
c1595e42
JR
33411+ if (!do_sio) {
33412+ lockdep_off();
1facf9fc 33413+ err = vfsub_rmdir(dir, path);
c1595e42
JR
33414+ lockdep_on();
33415+ } else {
1facf9fc 33416+ struct au_vfsub_rmdir_args args = {
33417+ .errp = &err,
33418+ .dir = dir,
33419+ .path = path
33420+ };
33421+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
33422+ if (unlikely(wkq_err))
33423+ err = wkq_err;
33424+ }
33425+
33426+ return err;
33427+}
33428+
33429+/* ---------------------------------------------------------------------- */
33430+
33431+struct notify_change_args {
33432+ int *errp;
33433+ struct path *path;
33434+ struct iattr *ia;
523b37e3 33435+ struct inode **delegated_inode;
1facf9fc 33436+};
33437+
33438+static void call_notify_change(void *args)
33439+{
33440+ struct notify_change_args *a = args;
33441+ struct inode *h_inode;
0b2a12c6 33442+ struct user_namespace *userns;
1facf9fc 33443+
5527c038 33444+ h_inode = d_inode(a->path->dentry);
1facf9fc 33445+ IMustLock(h_inode);
33446+
33447+ *a->errp = -EPERM;
33448+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
0b2a12c6 33449+ userns = mnt_user_ns(a->path->mnt);
c1595e42 33450+ lockdep_off();
0b2a12c6 33451+ *a->errp = notify_change(userns, a->path->dentry, a->ia,
523b37e3 33452+ a->delegated_inode);
c1595e42 33453+ lockdep_on();
1facf9fc 33454+ if (!*a->errp)
33455+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
33456+ }
33457+ AuTraceErr(*a->errp);
33458+}
33459+
523b37e3
AM
33460+int vfsub_notify_change(struct path *path, struct iattr *ia,
33461+ struct inode **delegated_inode)
1facf9fc 33462+{
33463+ int err;
33464+ struct notify_change_args args = {
523b37e3
AM
33465+ .errp = &err,
33466+ .path = path,
33467+ .ia = ia,
33468+ .delegated_inode = delegated_inode
1facf9fc 33469+ };
33470+
33471+ call_notify_change(&args);
33472+
33473+ return err;
33474+}
33475+
523b37e3
AM
33476+int vfsub_sio_notify_change(struct path *path, struct iattr *ia,
33477+ struct inode **delegated_inode)
1facf9fc 33478+{
33479+ int err, wkq_err;
33480+ struct notify_change_args args = {
523b37e3
AM
33481+ .errp = &err,
33482+ .path = path,
33483+ .ia = ia,
33484+ .delegated_inode = delegated_inode
1facf9fc 33485+ };
33486+
33487+ wkq_err = au_wkq_wait(call_notify_change, &args);
33488+ if (unlikely(wkq_err))
33489+ err = wkq_err;
33490+
33491+ return err;
33492+}
33493+
33494+/* ---------------------------------------------------------------------- */
33495+
33496+struct unlink_args {
33497+ int *errp;
33498+ struct inode *dir;
33499+ struct path *path;
523b37e3 33500+ struct inode **delegated_inode;
1facf9fc 33501+};
33502+
33503+static void call_unlink(void *args)
33504+{
33505+ struct unlink_args *a = args;
33506+ struct dentry *d = a->path->dentry;
33507+ struct inode *h_inode;
0b2a12c6 33508+ struct user_namespace *userns;
1facf9fc 33509+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
c1595e42 33510+ && au_dcount(d) == 1);
1facf9fc 33511+
33512+ IMustLock(a->dir);
33513+
33514+ a->path->dentry = d->d_parent;
33515+ *a->errp = security_path_unlink(a->path, d);
33516+ a->path->dentry = d;
33517+ if (unlikely(*a->errp))
33518+ return;
33519+
33520+ if (!stop_sillyrename)
33521+ dget(d);
5527c038
JR
33522+ h_inode = NULL;
33523+ if (d_is_positive(d)) {
33524+ h_inode = d_inode(d);
027c5e7a 33525+ ihold(h_inode);
5527c038 33526+ }
1facf9fc 33527+
0b2a12c6 33528+ userns = mnt_user_ns(a->path->mnt);
2cbb1c4b 33529+ lockdep_off();
0b2a12c6 33530+ *a->errp = vfs_unlink(userns, a->dir, d, a->delegated_inode);
2cbb1c4b 33531+ lockdep_on();
1facf9fc 33532+ if (!*a->errp) {
33533+ struct path tmp = {
33534+ .dentry = d->d_parent,
33535+ .mnt = a->path->mnt
33536+ };
33537+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
33538+ }
33539+
33540+ if (!stop_sillyrename)
33541+ dput(d);
33542+ if (h_inode)
33543+ iput(h_inode);
33544+
33545+ AuTraceErr(*a->errp);
33546+}
33547+
33548+/*
33549+ * @dir: must be locked.
33550+ * @dentry: target dentry.
33551+ */
523b37e3
AM
33552+int vfsub_unlink(struct inode *dir, struct path *path,
33553+ struct inode **delegated_inode, int force)
1facf9fc 33554+{
33555+ int err;
33556+ struct unlink_args args = {
523b37e3
AM
33557+ .errp = &err,
33558+ .dir = dir,
33559+ .path = path,
33560+ .delegated_inode = delegated_inode
1facf9fc 33561+ };
33562+
33563+ if (!force)
33564+ call_unlink(&args);
33565+ else {
33566+ int wkq_err;
33567+
33568+ wkq_err = au_wkq_wait(call_unlink, &args);
33569+ if (unlikely(wkq_err))
33570+ err = wkq_err;
33571+ }
33572+
33573+ return err;
33574+}
7f207e10 33575diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
eca34b5c 33576--- /usr/share/empty/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6
JR
33577+++ linux/fs/aufs/vfsub.h 2021-05-02 20:15:14.676670793 +0200
33578@@ -0,0 +1,358 @@
062440b3 33579+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 33580+/*
d58c55f2 33581+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 33582+ *
33583+ * This program, aufs is free software; you can redistribute it and/or modify
33584+ * it under the terms of the GNU General Public License as published by
33585+ * the Free Software Foundation; either version 2 of the License, or
33586+ * (at your option) any later version.
dece6358
AM
33587+ *
33588+ * This program is distributed in the hope that it will be useful,
33589+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
33590+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33591+ * GNU General Public License for more details.
33592+ *
33593+ * You should have received a copy of the GNU General Public License
523b37e3 33594+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 33595+ */
33596+
33597+/*
33598+ * sub-routines for VFS
33599+ */
33600+
33601+#ifndef __AUFS_VFSUB_H__
33602+#define __AUFS_VFSUB_H__
33603+
33604+#ifdef __KERNEL__
33605+
33606+#include <linux/fs.h>
b4510431 33607+#include <linux/mount.h>
8cdd5066 33608+#include <linux/posix_acl.h>
c1595e42 33609+#include <linux/xattr.h>
7f207e10 33610+#include "debug.h"
1facf9fc 33611+
7f207e10 33612+/* copied from linux/fs/internal.h */
2cbb1c4b 33613+/* todo: BAD approach!! */
c06a8ce3 33614+extern void __mnt_drop_write(struct vfsmount *);
acd2b654 33615+extern struct file *alloc_empty_file(int, const struct cred *);
7f207e10
AM
33616+
33617+/* ---------------------------------------------------------------------- */
1facf9fc 33618+
33619+/* lock subclass for lower inode */
33620+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
33621+/* reduce? gave up. */
33622+enum {
c1595e42 33623+ AuLsc_I_Begin = I_MUTEX_PARENT2, /* 5 */
1facf9fc 33624+ AuLsc_I_PARENT, /* lower inode, parent first */
33625+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 33626+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 33627+ AuLsc_I_CHILD,
33628+ AuLsc_I_CHILD2,
33629+ AuLsc_I_End
33630+};
33631+
33632+/* to debug easier, do not make them inlined functions */
33633+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
febd17d6 33634+#define IMustLock(i) AuDebugOn(!inode_is_locked(i))
1facf9fc 33635+
33636+/* ---------------------------------------------------------------------- */
33637+
7f207e10
AM
33638+static inline void vfsub_drop_nlink(struct inode *inode)
33639+{
33640+ AuDebugOn(!inode->i_nlink);
33641+ drop_nlink(inode);
33642+}
33643+
027c5e7a
AM
33644+static inline void vfsub_dead_dir(struct inode *inode)
33645+{
33646+ AuDebugOn(!S_ISDIR(inode->i_mode));
33647+ inode->i_flags |= S_DEAD;
33648+ clear_nlink(inode);
33649+}
33650+
392086de
AM
33651+static inline int vfsub_native_ro(struct inode *inode)
33652+{
8b6a4947 33653+ return sb_rdonly(inode->i_sb)
392086de
AM
33654+ || IS_RDONLY(inode)
33655+ /* || IS_APPEND(inode) */
33656+ || IS_IMMUTABLE(inode);
33657+}
33658+
8cdd5066
JR
33659+#ifdef CONFIG_AUFS_BR_FUSE
33660+int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb);
33661+#else
33662+AuStubInt0(vfsub_test_mntns, struct vfsmount *mnt, struct super_block *h_sb);
33663+#endif
33664+
a2654f78
AM
33665+int vfsub_sync_filesystem(struct super_block *h_sb, int wait);
33666+
7f207e10
AM
33667+/* ---------------------------------------------------------------------- */
33668+
33669+int vfsub_update_h_iattr(struct path *h_path, int *did);
33670+struct file *vfsub_dentry_open(struct path *path, int flags);
33671+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
acd2b654 33672+struct au_branch;
b912730e 33673+struct vfsub_aopen_args {
acd2b654
AM
33674+ struct file *file;
33675+ unsigned int open_flag;
33676+ umode_t create_mode;
33677+ struct au_branch *br;
b912730e 33678+};
b912730e 33679+int vfsub_atomic_open(struct inode *dir, struct dentry *dentry,
acd2b654 33680+ struct vfsub_aopen_args *args);
1facf9fc 33681+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
b4510431 33682+
febd17d6
JR
33683+struct dentry *vfsub_lookup_one_len_unlocked(const char *name,
33684+ struct dentry *parent, int len);
1facf9fc 33685+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
33686+ int len);
b4510431
AM
33687+
33688+struct vfsub_lkup_one_args {
33689+ struct dentry **errp;
33690+ struct qstr *name;
33691+ struct dentry *parent;
33692+};
33693+
33694+static inline struct dentry *vfsub_lkup_one(struct qstr *name,
33695+ struct dentry *parent)
33696+{
33697+ return vfsub_lookup_one_len(name->name, parent, name->len);
33698+}
33699+
33700+void vfsub_call_lkup_one(void *args);
33701+
33702+/* ---------------------------------------------------------------------- */
33703+
33704+static inline int vfsub_mnt_want_write(struct vfsmount *mnt)
33705+{
33706+ int err;
076b876e 33707+
b4510431
AM
33708+ lockdep_off();
33709+ err = mnt_want_write(mnt);
33710+ lockdep_on();
33711+ return err;
33712+}
33713+
33714+static inline void vfsub_mnt_drop_write(struct vfsmount *mnt)
33715+{
33716+ lockdep_off();
33717+ mnt_drop_write(mnt);
33718+ lockdep_on();
33719+}
1facf9fc 33720+
7e9cd9fe 33721+#if 0 /* reserved */
c06a8ce3
AM
33722+static inline void vfsub_mnt_drop_write_file(struct file *file)
33723+{
33724+ lockdep_off();
33725+ mnt_drop_write_file(file);
33726+ lockdep_on();
33727+}
7e9cd9fe 33728+#endif
c06a8ce3 33729+
1facf9fc 33730+/* ---------------------------------------------------------------------- */
33731+
33732+struct au_hinode;
33733+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
33734+ struct dentry *d2, struct au_hinode *hdir2);
33735+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
33736+ struct dentry *d2, struct au_hinode *hdir2);
33737+
537831f9
AM
33738+int vfsub_create(struct inode *dir, struct path *path, int mode,
33739+ bool want_excl);
1facf9fc 33740+int vfsub_symlink(struct inode *dir, struct path *path,
33741+ const char *symname);
33742+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
33743+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
523b37e3 33744+ struct path *path, struct inode **delegated_inode);
1facf9fc 33745+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
523b37e3 33746+ struct inode *hdir, struct path *path,
f2c43d5f 33747+ struct inode **delegated_inode, unsigned int flags);
1facf9fc 33748+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
33749+int vfsub_rmdir(struct inode *dir, struct path *path);
33750+
33751+/* ---------------------------------------------------------------------- */
33752+
33753+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
33754+ loff_t *ppos);
33755+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
33756+ loff_t *ppos);
33757+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
33758+ loff_t *ppos);
33759+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
33760+ loff_t *ppos);
4a4d8108 33761+int vfsub_flush(struct file *file, fl_owner_t id);
392086de
AM
33762+int vfsub_iterate_dir(struct file *file, struct dir_context *ctx);
33763+
c06a8ce3
AM
33764+static inline loff_t vfsub_f_size_read(struct file *file)
33765+{
33766+ return i_size_read(file_inode(file));
33767+}
33768+
4a4d8108
AM
33769+static inline unsigned int vfsub_file_flags(struct file *file)
33770+{
33771+ unsigned int flags;
33772+
33773+ spin_lock(&file->f_lock);
33774+ flags = file->f_flags;
33775+ spin_unlock(&file->f_lock);
33776+
33777+ return flags;
33778+}
1308ab2a 33779+
f0c0a007
AM
33780+static inline int vfsub_file_execed(struct file *file)
33781+{
33782+ /* todo: direct access f_flags */
33783+ return !!(vfsub_file_flags(file) & __FMODE_EXEC);
33784+}
33785+
7e9cd9fe 33786+#if 0 /* reserved */
1facf9fc 33787+static inline void vfsub_file_accessed(struct file *h_file)
33788+{
33789+ file_accessed(h_file);
33790+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
33791+}
7e9cd9fe 33792+#endif
1facf9fc 33793+
79b8bda9 33794+#if 0 /* reserved */
1facf9fc 33795+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
33796+ struct dentry *h_dentry)
33797+{
33798+ struct path h_path = {
33799+ .dentry = h_dentry,
33800+ .mnt = h_mnt
33801+ };
92d182d2 33802+ touch_atime(&h_path);
1facf9fc 33803+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
33804+}
79b8bda9 33805+#endif
1facf9fc 33806+
cd7a4cd9
AM
33807+static inline int vfsub_update_time(struct inode *h_inode,
33808+ struct timespec64 *ts, int flags)
0c3ec466 33809+{
5afbbe0d 33810+ return update_time(h_inode, ts, flags);
0c3ec466
AM
33811+ /* no vfsub_update_h_iattr() since we don't have struct path */
33812+}
33813+
8cdd5066 33814+#ifdef CONFIG_FS_POSIX_ACL
0b2a12c6
JR
33815+static inline int vfsub_acl_chmod(struct user_namespace *h_userns,
33816+ struct inode *h_inode, umode_t h_mode)
8cdd5066
JR
33817+{
33818+ int err;
33819+
0b2a12c6 33820+ err = posix_acl_chmod(h_userns, h_inode, h_mode);
8cdd5066
JR
33821+ if (err == -EOPNOTSUPP)
33822+ err = 0;
33823+ return err;
33824+}
33825+#else
0b2a12c6
JR
33826+AuStubInt0(vfsub_acl_chmod, struct user_namespace *h_userns,
33827+ struct inode *h_inode, umode_t h_mode);
8cdd5066
JR
33828+#endif
33829+
4a4d8108
AM
33830+long vfsub_splice_to(struct file *in, loff_t *ppos,
33831+ struct pipe_inode_info *pipe, size_t len,
33832+ unsigned int flags);
33833+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
33834+ loff_t *ppos, size_t len, unsigned int flags);
c06a8ce3
AM
33835+
33836+static inline long vfsub_truncate(struct path *path, loff_t length)
33837+{
33838+ long err;
076b876e 33839+
c06a8ce3
AM
33840+ lockdep_off();
33841+ err = vfs_truncate(path, length);
33842+ lockdep_on();
33843+ return err;
33844+}
33845+
4a4d8108
AM
33846+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
33847+ struct file *h_file);
53392da6 33848+int vfsub_fsync(struct file *file, struct path *path, int datasync);
4a4d8108 33849+
521ced18
JR
33850+/*
33851+ * re-use branch fs's ioctl(FICLONE) while aufs itself doesn't support such
33852+ * ioctl.
33853+ */
9f237c51
AM
33854+static inline loff_t vfsub_clone_file_range(struct file *src, struct file *dst,
33855+ loff_t len)
521ced18 33856+{
9f237c51 33857+ loff_t err;
521ced18
JR
33858+
33859+ lockdep_off();
9f237c51 33860+ err = vfs_clone_file_range(src, 0, dst, 0, len, /*remap_flags*/0);
521ced18
JR
33861+ lockdep_on();
33862+
33863+ return err;
33864+}
33865+
33866+/* copy_file_range(2) is a systemcall */
33867+static inline ssize_t vfsub_copy_file_range(struct file *src, loff_t src_pos,
33868+ struct file *dst, loff_t dst_pos,
33869+ size_t len, unsigned int flags)
33870+{
33871+ ssize_t ssz;
33872+
33873+ lockdep_off();
33874+ ssz = vfs_copy_file_range(src, src_pos, dst, dst_pos, len, flags);
33875+ lockdep_on();
33876+
33877+ return ssz;
33878+}
33879+
1facf9fc 33880+/* ---------------------------------------------------------------------- */
33881+
33882+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
33883+{
33884+ loff_t err;
33885+
2cbb1c4b 33886+ lockdep_off();
1facf9fc 33887+ err = vfs_llseek(file, offset, origin);
2cbb1c4b 33888+ lockdep_on();
1facf9fc 33889+ return err;
33890+}
33891+
33892+/* ---------------------------------------------------------------------- */
33893+
4a4d8108
AM
33894+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
33895+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
523b37e3
AM
33896+int vfsub_sio_notify_change(struct path *path, struct iattr *ia,
33897+ struct inode **delegated_inode);
33898+int vfsub_notify_change(struct path *path, struct iattr *ia,
33899+ struct inode **delegated_inode);
33900+int vfsub_unlink(struct inode *dir, struct path *path,
33901+ struct inode **delegated_inode, int force);
4a4d8108 33902+
521ced18
JR
33903+static inline int vfsub_getattr(const struct path *path, struct kstat *st)
33904+{
33905+ return vfs_getattr(path, st, STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT);
33906+}
33907+
c1595e42
JR
33908+/* ---------------------------------------------------------------------- */
33909+
0b2a12c6
JR
33910+static inline int vfsub_setxattr(struct user_namespace *userns,
33911+ struct dentry *dentry, const char *name,
c1595e42
JR
33912+ const void *value, size_t size, int flags)
33913+{
33914+ int err;
33915+
33916+ lockdep_off();
0b2a12c6 33917+ err = vfs_setxattr(userns, dentry, name, value, size, flags);
c1595e42
JR
33918+ lockdep_on();
33919+
33920+ return err;
33921+}
33922+
0b2a12c6
JR
33923+static inline int vfsub_removexattr(struct user_namespace *userns,
33924+ struct dentry *dentry, const char *name)
c1595e42
JR
33925+{
33926+ int err;
33927+
33928+ lockdep_off();
0b2a12c6 33929+ err = vfs_removexattr(userns, dentry, name);
c1595e42
JR
33930+ lockdep_on();
33931+
33932+ return err;
33933+}
33934+
1facf9fc 33935+#endif /* __KERNEL__ */
33936+#endif /* __AUFS_VFSUB_H__ */
7f207e10 33937diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
eca34b5c 33938--- /usr/share/empty/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 33939+++ linux/fs/aufs/wbr_policy.c 2021-05-02 20:15:14.676670793 +0200
cd7a4cd9
AM
33940@@ -0,0 +1,830 @@
33941+// SPDX-License-Identifier: GPL-2.0
1facf9fc 33942+/*
d58c55f2 33943+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 33944+ *
33945+ * This program, aufs is free software; you can redistribute it and/or modify
33946+ * it under the terms of the GNU General Public License as published by
33947+ * the Free Software Foundation; either version 2 of the License, or
33948+ * (at your option) any later version.
dece6358
AM
33949+ *
33950+ * This program is distributed in the hope that it will be useful,
33951+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
33952+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33953+ * GNU General Public License for more details.
33954+ *
33955+ * You should have received a copy of the GNU General Public License
523b37e3 33956+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 33957+ */
33958+
33959+/*
33960+ * policies for selecting one among multiple writable branches
33961+ */
33962+
33963+#include <linux/statfs.h>
33964+#include "aufs.h"
33965+
33966+/* subset of cpup_attr() */
33967+static noinline_for_stack
33968+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
33969+{
33970+ int err, sbits;
33971+ struct iattr ia;
33972+ struct inode *h_isrc;
33973+
5527c038 33974+ h_isrc = d_inode(h_src);
1facf9fc 33975+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
33976+ ia.ia_mode = h_isrc->i_mode;
33977+ ia.ia_uid = h_isrc->i_uid;
33978+ ia.ia_gid = h_isrc->i_gid;
33979+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
5527c038 33980+ au_cpup_attr_flags(d_inode(h_path->dentry), h_isrc->i_flags);
523b37e3
AM
33981+ /* no delegation since it is just created */
33982+ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL);
1facf9fc 33983+
33984+ /* is this nfs only? */
33985+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
33986+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
33987+ ia.ia_mode = h_isrc->i_mode;
523b37e3 33988+ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL);
1facf9fc 33989+ }
33990+
33991+ return err;
33992+}
33993+
33994+#define AuCpdown_PARENT_OPQ 1
33995+#define AuCpdown_WHED (1 << 1)
33996+#define AuCpdown_MADE_DIR (1 << 2)
33997+#define AuCpdown_DIROPQ (1 << 3)
33998+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
7f207e10
AM
33999+#define au_fset_cpdown(flags, name) \
34000+ do { (flags) |= AuCpdown_##name; } while (0)
34001+#define au_fclr_cpdown(flags, name) \
34002+ do { (flags) &= ~AuCpdown_##name; } while (0)
1facf9fc 34003+
1facf9fc 34004+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
c2b27bf2 34005+ unsigned int *flags)
1facf9fc 34006+{
34007+ int err;
34008+ struct dentry *opq_dentry;
34009+
34010+ opq_dentry = au_diropq_create(dentry, bdst);
34011+ err = PTR_ERR(opq_dentry);
34012+ if (IS_ERR(opq_dentry))
34013+ goto out;
34014+ dput(opq_dentry);
c2b27bf2 34015+ au_fset_cpdown(*flags, DIROPQ);
1facf9fc 34016+
4f0767ce 34017+out:
1facf9fc 34018+ return err;
34019+}
34020+
34021+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
34022+ struct inode *dir, aufs_bindex_t bdst)
34023+{
34024+ int err;
34025+ struct path h_path;
34026+ struct au_branch *br;
34027+
34028+ br = au_sbr(dentry->d_sb, bdst);
34029+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
34030+ err = PTR_ERR(h_path.dentry);
34031+ if (IS_ERR(h_path.dentry))
34032+ goto out;
34033+
34034+ err = 0;
5527c038 34035+ if (d_is_positive(h_path.dentry)) {
86dc4139 34036+ h_path.mnt = au_br_mnt(br);
1facf9fc 34037+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
34038+ dentry);
34039+ }
34040+ dput(h_path.dentry);
34041+
4f0767ce 34042+out:
1facf9fc 34043+ return err;
34044+}
34045+
34046+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 34047+ struct au_pin *pin,
1facf9fc 34048+ struct dentry *h_parent, void *arg)
34049+{
34050+ int err, rerr;
5afbbe0d 34051+ aufs_bindex_t bopq, btop;
1facf9fc 34052+ struct path h_path;
34053+ struct dentry *parent;
34054+ struct inode *h_dir, *h_inode, *inode, *dir;
c2b27bf2 34055+ unsigned int *flags = arg;
1facf9fc 34056+
5afbbe0d 34057+ btop = au_dbtop(dentry);
1facf9fc 34058+ /* dentry is di-locked */
34059+ parent = dget_parent(dentry);
5527c038
JR
34060+ dir = d_inode(parent);
34061+ h_dir = d_inode(h_parent);
1facf9fc 34062+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
34063+ IMustLock(h_dir);
34064+
86dc4139 34065+ err = au_lkup_neg(dentry, bdst, /*wh*/0);
1facf9fc 34066+ if (unlikely(err < 0))
34067+ goto out;
34068+ h_path.dentry = au_h_dptr(dentry, bdst);
34069+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
cd7a4cd9 34070+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path, 0755);
1facf9fc 34071+ if (unlikely(err))
34072+ goto out_put;
c2b27bf2 34073+ au_fset_cpdown(*flags, MADE_DIR);
1facf9fc 34074+
1facf9fc 34075+ bopq = au_dbdiropq(dentry);
c2b27bf2
AM
34076+ au_fclr_cpdown(*flags, WHED);
34077+ au_fclr_cpdown(*flags, DIROPQ);
1facf9fc 34078+ if (au_dbwh(dentry) == bdst)
c2b27bf2
AM
34079+ au_fset_cpdown(*flags, WHED);
34080+ if (!au_ftest_cpdown(*flags, PARENT_OPQ) && bopq <= bdst)
34081+ au_fset_cpdown(*flags, PARENT_OPQ);
5527c038 34082+ h_inode = d_inode(h_path.dentry);
febd17d6 34083+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
c2b27bf2
AM
34084+ if (au_ftest_cpdown(*flags, WHED)) {
34085+ err = au_cpdown_dir_opq(dentry, bdst, flags);
1facf9fc 34086+ if (unlikely(err)) {
febd17d6 34087+ inode_unlock(h_inode);
1facf9fc 34088+ goto out_dir;
34089+ }
34090+ }
34091+
5afbbe0d 34092+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, btop));
febd17d6 34093+ inode_unlock(h_inode);
1facf9fc 34094+ if (unlikely(err))
34095+ goto out_opq;
34096+
c2b27bf2 34097+ if (au_ftest_cpdown(*flags, WHED)) {
1facf9fc 34098+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
34099+ if (unlikely(err))
34100+ goto out_opq;
34101+ }
34102+
5527c038 34103+ inode = d_inode(dentry);
5afbbe0d
AM
34104+ if (au_ibbot(inode) < bdst)
34105+ au_set_ibbot(inode, bdst);
1facf9fc 34106+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
34107+ au_hi_flags(inode, /*isdir*/1));
076b876e 34108+ au_fhsm_wrote(dentry->d_sb, bdst, /*force*/0);
1facf9fc 34109+ goto out; /* success */
34110+
34111+ /* revert */
4f0767ce 34112+out_opq:
c2b27bf2 34113+ if (au_ftest_cpdown(*flags, DIROPQ)) {
febd17d6 34114+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
1facf9fc 34115+ rerr = au_diropq_remove(dentry, bdst);
febd17d6 34116+ inode_unlock(h_inode);
1facf9fc 34117+ if (unlikely(rerr)) {
523b37e3
AM
34118+ AuIOErr("failed removing diropq for %pd b%d (%d)\n",
34119+ dentry, bdst, rerr);
1facf9fc 34120+ err = -EIO;
34121+ goto out;
34122+ }
34123+ }
4f0767ce 34124+out_dir:
c2b27bf2 34125+ if (au_ftest_cpdown(*flags, MADE_DIR)) {
1facf9fc 34126+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
34127+ if (unlikely(rerr)) {
523b37e3
AM
34128+ AuIOErr("failed removing %pd b%d (%d)\n",
34129+ dentry, bdst, rerr);
1facf9fc 34130+ err = -EIO;
34131+ }
34132+ }
4f0767ce 34133+out_put:
1facf9fc 34134+ au_set_h_dptr(dentry, bdst, NULL);
5afbbe0d
AM
34135+ if (au_dbbot(dentry) == bdst)
34136+ au_update_dbbot(dentry);
4f0767ce 34137+out:
1facf9fc 34138+ dput(parent);
34139+ return err;
34140+}
34141+
34142+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
34143+{
34144+ int err;
c2b27bf2 34145+ unsigned int flags;
1facf9fc 34146+
c2b27bf2
AM
34147+ flags = 0;
34148+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &flags);
1facf9fc 34149+
34150+ return err;
34151+}
34152+
34153+/* ---------------------------------------------------------------------- */
34154+
34155+/* policies for create */
34156+
c2b27bf2 34157+int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
4a4d8108
AM
34158+{
34159+ int err, i, j, ndentry;
34160+ aufs_bindex_t bopq;
34161+ struct au_dcsub_pages dpages;
34162+ struct au_dpage *dpage;
34163+ struct dentry **dentries, *parent, *d;
34164+
34165+ err = au_dpages_init(&dpages, GFP_NOFS);
34166+ if (unlikely(err))
34167+ goto out;
34168+ parent = dget_parent(dentry);
027c5e7a 34169+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0);
4a4d8108
AM
34170+ if (unlikely(err))
34171+ goto out_free;
34172+
34173+ err = bindex;
34174+ for (i = 0; i < dpages.ndpage; i++) {
34175+ dpage = dpages.dpages + i;
34176+ dentries = dpage->dentries;
34177+ ndentry = dpage->ndentry;
34178+ for (j = 0; j < ndentry; j++) {
34179+ d = dentries[j];
34180+ di_read_lock_parent2(d, !AuLock_IR);
34181+ bopq = au_dbdiropq(d);
34182+ di_read_unlock(d, !AuLock_IR);
34183+ if (bopq >= 0 && bopq < err)
34184+ err = bopq;
34185+ }
34186+ }
34187+
34188+out_free:
34189+ dput(parent);
34190+ au_dpages_free(&dpages);
34191+out:
34192+ return err;
34193+}
34194+
1facf9fc 34195+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
34196+{
34197+ for (; bindex >= 0; bindex--)
34198+ if (!au_br_rdonly(au_sbr(sb, bindex)))
34199+ return bindex;
34200+ return -EROFS;
34201+}
34202+
34203+/* top down parent */
392086de
AM
34204+static int au_wbr_create_tdp(struct dentry *dentry,
34205+ unsigned int flags __maybe_unused)
1facf9fc 34206+{
34207+ int err;
5afbbe0d 34208+ aufs_bindex_t btop, bindex;
1facf9fc 34209+ struct super_block *sb;
34210+ struct dentry *parent, *h_parent;
34211+
34212+ sb = dentry->d_sb;
5afbbe0d
AM
34213+ btop = au_dbtop(dentry);
34214+ err = btop;
34215+ if (!au_br_rdonly(au_sbr(sb, btop)))
1facf9fc 34216+ goto out;
34217+
34218+ err = -EROFS;
34219+ parent = dget_parent(dentry);
5afbbe0d 34220+ for (bindex = au_dbtop(parent); bindex < btop; bindex++) {
1facf9fc 34221+ h_parent = au_h_dptr(parent, bindex);
5527c038 34222+ if (!h_parent || d_is_negative(h_parent))
1facf9fc 34223+ continue;
34224+
34225+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
34226+ err = bindex;
34227+ break;
34228+ }
34229+ }
34230+ dput(parent);
34231+
34232+ /* bottom up here */
4a4d8108 34233+ if (unlikely(err < 0)) {
5afbbe0d 34234+ err = au_wbr_bu(sb, btop - 1);
4a4d8108
AM
34235+ if (err >= 0)
34236+ err = au_wbr_nonopq(dentry, err);
34237+ }
1facf9fc 34238+
4f0767ce 34239+out:
1facf9fc 34240+ AuDbg("b%d\n", err);
34241+ return err;
34242+}
34243+
34244+/* ---------------------------------------------------------------------- */
34245+
34246+/* an exception for the policy other than tdp */
34247+static int au_wbr_create_exp(struct dentry *dentry)
34248+{
34249+ int err;
34250+ aufs_bindex_t bwh, bdiropq;
34251+ struct dentry *parent;
34252+
34253+ err = -1;
34254+ bwh = au_dbwh(dentry);
34255+ parent = dget_parent(dentry);
34256+ bdiropq = au_dbdiropq(parent);
34257+ if (bwh >= 0) {
34258+ if (bdiropq >= 0)
34259+ err = min(bdiropq, bwh);
34260+ else
34261+ err = bwh;
34262+ AuDbg("%d\n", err);
34263+ } else if (bdiropq >= 0) {
34264+ err = bdiropq;
34265+ AuDbg("%d\n", err);
34266+ }
34267+ dput(parent);
34268+
4a4d8108
AM
34269+ if (err >= 0)
34270+ err = au_wbr_nonopq(dentry, err);
34271+
1facf9fc 34272+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
34273+ err = -1;
34274+
34275+ AuDbg("%d\n", err);
34276+ return err;
34277+}
34278+
34279+/* ---------------------------------------------------------------------- */
34280+
34281+/* round robin */
34282+static int au_wbr_create_init_rr(struct super_block *sb)
34283+{
34284+ int err;
34285+
5afbbe0d 34286+ err = au_wbr_bu(sb, au_sbbot(sb));
1facf9fc 34287+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 34288+ /* smp_mb(); */
1facf9fc 34289+
34290+ AuDbg("b%d\n", err);
34291+ return err;
34292+}
34293+
392086de 34294+static int au_wbr_create_rr(struct dentry *dentry, unsigned int flags)
1facf9fc 34295+{
34296+ int err, nbr;
34297+ unsigned int u;
5afbbe0d 34298+ aufs_bindex_t bindex, bbot;
1facf9fc 34299+ struct super_block *sb;
34300+ atomic_t *next;
34301+
34302+ err = au_wbr_create_exp(dentry);
34303+ if (err >= 0)
34304+ goto out;
34305+
34306+ sb = dentry->d_sb;
34307+ next = &au_sbi(sb)->si_wbr_rr_next;
5afbbe0d
AM
34308+ bbot = au_sbbot(sb);
34309+ nbr = bbot + 1;
34310+ for (bindex = 0; bindex <= bbot; bindex++) {
392086de 34311+ if (!au_ftest_wbr(flags, DIR)) {
1facf9fc 34312+ err = atomic_dec_return(next) + 1;
34313+ /* modulo for 0 is meaningless */
34314+ if (unlikely(!err))
34315+ err = atomic_dec_return(next) + 1;
34316+ } else
34317+ err = atomic_read(next);
34318+ AuDbg("%d\n", err);
34319+ u = err;
34320+ err = u % nbr;
34321+ AuDbg("%d\n", err);
34322+ if (!au_br_rdonly(au_sbr(sb, err)))
34323+ break;
34324+ err = -EROFS;
34325+ }
34326+
4a4d8108
AM
34327+ if (err >= 0)
34328+ err = au_wbr_nonopq(dentry, err);
34329+
4f0767ce 34330+out:
1facf9fc 34331+ AuDbg("%d\n", err);
34332+ return err;
34333+}
34334+
34335+/* ---------------------------------------------------------------------- */
34336+
34337+/* most free space */
392086de 34338+static void au_mfs(struct dentry *dentry, struct dentry *parent)
1facf9fc 34339+{
34340+ struct super_block *sb;
34341+ struct au_branch *br;
34342+ struct au_wbr_mfs *mfs;
392086de 34343+ struct dentry *h_parent;
5afbbe0d 34344+ aufs_bindex_t bindex, bbot;
1facf9fc 34345+ int err;
34346+ unsigned long long b, bavail;
7f207e10 34347+ struct path h_path;
1facf9fc 34348+ /* reduce the stack usage */
34349+ struct kstatfs *st;
34350+
34351+ st = kmalloc(sizeof(*st), GFP_NOFS);
34352+ if (unlikely(!st)) {
34353+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
34354+ return;
34355+ }
34356+
34357+ bavail = 0;
34358+ sb = dentry->d_sb;
34359+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 34360+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 34361+ mfs->mfs_bindex = -EROFS;
34362+ mfs->mfsrr_bytes = 0;
392086de
AM
34363+ if (!parent) {
34364+ bindex = 0;
5afbbe0d 34365+ bbot = au_sbbot(sb);
392086de 34366+ } else {
5afbbe0d
AM
34367+ bindex = au_dbtop(parent);
34368+ bbot = au_dbtaildir(parent);
392086de
AM
34369+ }
34370+
5afbbe0d 34371+ for (; bindex <= bbot; bindex++) {
392086de
AM
34372+ if (parent) {
34373+ h_parent = au_h_dptr(parent, bindex);
5527c038 34374+ if (!h_parent || d_is_negative(h_parent))
392086de
AM
34375+ continue;
34376+ }
1facf9fc 34377+ br = au_sbr(sb, bindex);
34378+ if (au_br_rdonly(br))
34379+ continue;
34380+
34381+ /* sb->s_root for NFS is unreliable */
86dc4139 34382+ h_path.mnt = au_br_mnt(br);
7f207e10
AM
34383+ h_path.dentry = h_path.mnt->mnt_root;
34384+ err = vfs_statfs(&h_path, st);
1facf9fc 34385+ if (unlikely(err)) {
34386+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
34387+ continue;
34388+ }
34389+
34390+ /* when the available size is equal, select the lower one */
34391+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
34392+ || sizeof(b) < sizeof(st->f_bsize));
34393+ b = st->f_bavail * st->f_bsize;
34394+ br->br_wbr->wbr_bytes = b;
34395+ if (b >= bavail) {
34396+ bavail = b;
34397+ mfs->mfs_bindex = bindex;
34398+ mfs->mfs_jiffy = jiffies;
34399+ }
34400+ }
34401+
34402+ mfs->mfsrr_bytes = bavail;
34403+ AuDbg("b%d\n", mfs->mfs_bindex);
9f237c51 34404+ au_kfree_rcu(st);
1facf9fc 34405+}
34406+
392086de 34407+static int au_wbr_create_mfs(struct dentry *dentry, unsigned int flags)
1facf9fc 34408+{
34409+ int err;
392086de 34410+ struct dentry *parent;
1facf9fc 34411+ struct super_block *sb;
34412+ struct au_wbr_mfs *mfs;
34413+
34414+ err = au_wbr_create_exp(dentry);
34415+ if (err >= 0)
34416+ goto out;
34417+
34418+ sb = dentry->d_sb;
392086de
AM
34419+ parent = NULL;
34420+ if (au_ftest_wbr(flags, PARENT))
34421+ parent = dget_parent(dentry);
1facf9fc 34422+ mfs = &au_sbi(sb)->si_wbr_mfs;
34423+ mutex_lock(&mfs->mfs_lock);
34424+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
34425+ || mfs->mfs_bindex < 0
34426+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
392086de 34427+ au_mfs(dentry, parent);
1facf9fc 34428+ mutex_unlock(&mfs->mfs_lock);
34429+ err = mfs->mfs_bindex;
392086de 34430+ dput(parent);
1facf9fc 34431+
4a4d8108
AM
34432+ if (err >= 0)
34433+ err = au_wbr_nonopq(dentry, err);
34434+
4f0767ce 34435+out:
1facf9fc 34436+ AuDbg("b%d\n", err);
34437+ return err;
34438+}
34439+
34440+static int au_wbr_create_init_mfs(struct super_block *sb)
34441+{
34442+ struct au_wbr_mfs *mfs;
34443+
34444+ mfs = &au_sbi(sb)->si_wbr_mfs;
34445+ mutex_init(&mfs->mfs_lock);
34446+ mfs->mfs_jiffy = 0;
34447+ mfs->mfs_bindex = -EROFS;
34448+
34449+ return 0;
34450+}
34451+
34452+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
34453+{
34454+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
34455+ return 0;
34456+}
34457+
34458+/* ---------------------------------------------------------------------- */
34459+
f2c43d5f
AM
34460+/* top down regardless parent, and then mfs */
34461+static int au_wbr_create_tdmfs(struct dentry *dentry,
34462+ unsigned int flags __maybe_unused)
34463+{
34464+ int err;
34465+ aufs_bindex_t bwh, btail, bindex, bfound, bmfs;
34466+ unsigned long long watermark;
34467+ struct super_block *sb;
34468+ struct au_wbr_mfs *mfs;
34469+ struct au_branch *br;
34470+ struct dentry *parent;
34471+
34472+ sb = dentry->d_sb;
34473+ mfs = &au_sbi(sb)->si_wbr_mfs;
34474+ mutex_lock(&mfs->mfs_lock);
34475+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
34476+ || mfs->mfs_bindex < 0)
34477+ au_mfs(dentry, /*parent*/NULL);
34478+ watermark = mfs->mfsrr_watermark;
34479+ bmfs = mfs->mfs_bindex;
34480+ mutex_unlock(&mfs->mfs_lock);
34481+
34482+ /* another style of au_wbr_create_exp() */
34483+ bwh = au_dbwh(dentry);
34484+ parent = dget_parent(dentry);
34485+ btail = au_dbtaildir(parent);
34486+ if (bwh >= 0 && bwh < btail)
34487+ btail = bwh;
34488+
34489+ err = au_wbr_nonopq(dentry, btail);
34490+ if (unlikely(err < 0))
34491+ goto out;
34492+ btail = err;
34493+ bfound = -1;
34494+ for (bindex = 0; bindex <= btail; bindex++) {
34495+ br = au_sbr(sb, bindex);
34496+ if (au_br_rdonly(br))
34497+ continue;
34498+ if (br->br_wbr->wbr_bytes > watermark) {
34499+ bfound = bindex;
34500+ break;
34501+ }
34502+ }
34503+ err = bfound;
34504+ if (err < 0)
34505+ err = bmfs;
34506+
34507+out:
34508+ dput(parent);
34509+ AuDbg("b%d\n", err);
34510+ return err;
34511+}
34512+
34513+/* ---------------------------------------------------------------------- */
34514+
1facf9fc 34515+/* most free space and then round robin */
392086de 34516+static int au_wbr_create_mfsrr(struct dentry *dentry, unsigned int flags)
1facf9fc 34517+{
34518+ int err;
34519+ struct au_wbr_mfs *mfs;
34520+
392086de 34521+ err = au_wbr_create_mfs(dentry, flags);
1facf9fc 34522+ if (err >= 0) {
34523+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 34524+ mutex_lock(&mfs->mfs_lock);
1facf9fc 34525+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
392086de 34526+ err = au_wbr_create_rr(dentry, flags);
dece6358 34527+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 34528+ }
34529+
34530+ AuDbg("b%d\n", err);
34531+ return err;
34532+}
34533+
34534+static int au_wbr_create_init_mfsrr(struct super_block *sb)
34535+{
34536+ int err;
34537+
34538+ au_wbr_create_init_mfs(sb); /* ignore */
34539+ err = au_wbr_create_init_rr(sb);
34540+
34541+ return err;
34542+}
34543+
34544+/* ---------------------------------------------------------------------- */
34545+
34546+/* top down parent and most free space */
392086de 34547+static int au_wbr_create_pmfs(struct dentry *dentry, unsigned int flags)
1facf9fc 34548+{
34549+ int err, e2;
34550+ unsigned long long b;
5afbbe0d 34551+ aufs_bindex_t bindex, btop, bbot;
1facf9fc 34552+ struct super_block *sb;
34553+ struct dentry *parent, *h_parent;
34554+ struct au_branch *br;
34555+
392086de 34556+ err = au_wbr_create_tdp(dentry, flags);
1facf9fc 34557+ if (unlikely(err < 0))
34558+ goto out;
34559+ parent = dget_parent(dentry);
5afbbe0d
AM
34560+ btop = au_dbtop(parent);
34561+ bbot = au_dbtaildir(parent);
34562+ if (btop == bbot)
1facf9fc 34563+ goto out_parent; /* success */
34564+
392086de 34565+ e2 = au_wbr_create_mfs(dentry, flags);
1facf9fc 34566+ if (e2 < 0)
34567+ goto out_parent; /* success */
34568+
34569+ /* when the available size is equal, select upper one */
34570+ sb = dentry->d_sb;
34571+ br = au_sbr(sb, err);
34572+ b = br->br_wbr->wbr_bytes;
34573+ AuDbg("b%d, %llu\n", err, b);
34574+
5afbbe0d 34575+ for (bindex = btop; bindex <= bbot; bindex++) {
1facf9fc 34576+ h_parent = au_h_dptr(parent, bindex);
5527c038 34577+ if (!h_parent || d_is_negative(h_parent))
1facf9fc 34578+ continue;
34579+
34580+ br = au_sbr(sb, bindex);
34581+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
34582+ b = br->br_wbr->wbr_bytes;
34583+ err = bindex;
34584+ AuDbg("b%d, %llu\n", err, b);
34585+ }
34586+ }
34587+
4a4d8108
AM
34588+ if (err >= 0)
34589+ err = au_wbr_nonopq(dentry, err);
34590+
4f0767ce 34591+out_parent:
1facf9fc 34592+ dput(parent);
4f0767ce 34593+out:
1facf9fc 34594+ AuDbg("b%d\n", err);
34595+ return err;
34596+}
34597+
34598+/* ---------------------------------------------------------------------- */
34599+
392086de
AM
34600+/*
34601+ * - top down parent
34602+ * - most free space with parent
34603+ * - most free space round-robin regardless parent
34604+ */
34605+static int au_wbr_create_pmfsrr(struct dentry *dentry, unsigned int flags)
34606+{
34607+ int err;
34608+ unsigned long long watermark;
34609+ struct super_block *sb;
34610+ struct au_branch *br;
34611+ struct au_wbr_mfs *mfs;
34612+
34613+ err = au_wbr_create_pmfs(dentry, flags | AuWbr_PARENT);
34614+ if (unlikely(err < 0))
34615+ goto out;
34616+
34617+ sb = dentry->d_sb;
34618+ br = au_sbr(sb, err);
34619+ mfs = &au_sbi(sb)->si_wbr_mfs;
34620+ mutex_lock(&mfs->mfs_lock);
34621+ watermark = mfs->mfsrr_watermark;
34622+ mutex_unlock(&mfs->mfs_lock);
34623+ if (br->br_wbr->wbr_bytes < watermark)
34624+ /* regardless the parent dir */
34625+ err = au_wbr_create_mfsrr(dentry, flags);
34626+
34627+out:
34628+ AuDbg("b%d\n", err);
34629+ return err;
34630+}
34631+
34632+/* ---------------------------------------------------------------------- */
34633+
1facf9fc 34634+/* policies for copyup */
34635+
34636+/* top down parent */
34637+static int au_wbr_copyup_tdp(struct dentry *dentry)
34638+{
392086de 34639+ return au_wbr_create_tdp(dentry, /*flags, anything is ok*/0);
1facf9fc 34640+}
34641+
34642+/* bottom up parent */
34643+static int au_wbr_copyup_bup(struct dentry *dentry)
34644+{
34645+ int err;
5afbbe0d 34646+ aufs_bindex_t bindex, btop;
1facf9fc 34647+ struct dentry *parent, *h_parent;
34648+ struct super_block *sb;
34649+
34650+ err = -EROFS;
34651+ sb = dentry->d_sb;
34652+ parent = dget_parent(dentry);
5afbbe0d
AM
34653+ btop = au_dbtop(parent);
34654+ for (bindex = au_dbtop(dentry); bindex >= btop; bindex--) {
1facf9fc 34655+ h_parent = au_h_dptr(parent, bindex);
5527c038 34656+ if (!h_parent || d_is_negative(h_parent))
1facf9fc 34657+ continue;
34658+
34659+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
34660+ err = bindex;
34661+ break;
34662+ }
34663+ }
34664+ dput(parent);
34665+
34666+ /* bottom up here */
34667+ if (unlikely(err < 0))
5afbbe0d 34668+ err = au_wbr_bu(sb, btop - 1);
1facf9fc 34669+
34670+ AuDbg("b%d\n", err);
34671+ return err;
34672+}
34673+
34674+/* bottom up */
5afbbe0d 34675+int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop)
1facf9fc 34676+{
34677+ int err;
34678+
5afbbe0d 34679+ err = au_wbr_bu(dentry->d_sb, btop);
4a4d8108 34680+ AuDbg("b%d\n", err);
5afbbe0d 34681+ if (err > btop)
4a4d8108 34682+ err = au_wbr_nonopq(dentry, err);
1facf9fc 34683+
34684+ AuDbg("b%d\n", err);
34685+ return err;
34686+}
34687+
076b876e
AM
34688+static int au_wbr_copyup_bu(struct dentry *dentry)
34689+{
34690+ int err;
5afbbe0d 34691+ aufs_bindex_t btop;
076b876e 34692+
5afbbe0d
AM
34693+ btop = au_dbtop(dentry);
34694+ err = au_wbr_do_copyup_bu(dentry, btop);
076b876e
AM
34695+ return err;
34696+}
34697+
1facf9fc 34698+/* ---------------------------------------------------------------------- */
34699+
34700+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
34701+ [AuWbrCopyup_TDP] = {
34702+ .copyup = au_wbr_copyup_tdp
34703+ },
34704+ [AuWbrCopyup_BUP] = {
34705+ .copyup = au_wbr_copyup_bup
34706+ },
34707+ [AuWbrCopyup_BU] = {
34708+ .copyup = au_wbr_copyup_bu
34709+ }
34710+};
34711+
34712+struct au_wbr_create_operations au_wbr_create_ops[] = {
34713+ [AuWbrCreate_TDP] = {
34714+ .create = au_wbr_create_tdp
34715+ },
34716+ [AuWbrCreate_RR] = {
34717+ .create = au_wbr_create_rr,
34718+ .init = au_wbr_create_init_rr
34719+ },
34720+ [AuWbrCreate_MFS] = {
34721+ .create = au_wbr_create_mfs,
34722+ .init = au_wbr_create_init_mfs,
34723+ .fin = au_wbr_create_fin_mfs
34724+ },
34725+ [AuWbrCreate_MFSV] = {
34726+ .create = au_wbr_create_mfs,
34727+ .init = au_wbr_create_init_mfs,
34728+ .fin = au_wbr_create_fin_mfs
34729+ },
34730+ [AuWbrCreate_MFSRR] = {
34731+ .create = au_wbr_create_mfsrr,
34732+ .init = au_wbr_create_init_mfsrr,
34733+ .fin = au_wbr_create_fin_mfs
34734+ },
34735+ [AuWbrCreate_MFSRRV] = {
34736+ .create = au_wbr_create_mfsrr,
34737+ .init = au_wbr_create_init_mfsrr,
34738+ .fin = au_wbr_create_fin_mfs
34739+ },
f2c43d5f
AM
34740+ [AuWbrCreate_TDMFS] = {
34741+ .create = au_wbr_create_tdmfs,
34742+ .init = au_wbr_create_init_mfs,
34743+ .fin = au_wbr_create_fin_mfs
34744+ },
34745+ [AuWbrCreate_TDMFSV] = {
34746+ .create = au_wbr_create_tdmfs,
34747+ .init = au_wbr_create_init_mfs,
34748+ .fin = au_wbr_create_fin_mfs
34749+ },
1facf9fc 34750+ [AuWbrCreate_PMFS] = {
34751+ .create = au_wbr_create_pmfs,
34752+ .init = au_wbr_create_init_mfs,
34753+ .fin = au_wbr_create_fin_mfs
34754+ },
34755+ [AuWbrCreate_PMFSV] = {
34756+ .create = au_wbr_create_pmfs,
34757+ .init = au_wbr_create_init_mfs,
34758+ .fin = au_wbr_create_fin_mfs
392086de
AM
34759+ },
34760+ [AuWbrCreate_PMFSRR] = {
34761+ .create = au_wbr_create_pmfsrr,
34762+ .init = au_wbr_create_init_mfsrr,
34763+ .fin = au_wbr_create_fin_mfs
34764+ },
34765+ [AuWbrCreate_PMFSRRV] = {
34766+ .create = au_wbr_create_pmfsrr,
34767+ .init = au_wbr_create_init_mfsrr,
34768+ .fin = au_wbr_create_fin_mfs
1facf9fc 34769+ }
34770+};
7f207e10 34771diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
eca34b5c 34772--- /usr/share/empty/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6
JR
34773+++ linux/fs/aufs/whout.c 2021-05-02 20:15:14.676670793 +0200
34774@@ -0,0 +1,1070 @@
cd7a4cd9 34775+// SPDX-License-Identifier: GPL-2.0
1facf9fc 34776+/*
d58c55f2 34777+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 34778+ *
34779+ * This program, aufs is free software; you can redistribute it and/or modify
34780+ * it under the terms of the GNU General Public License as published by
34781+ * the Free Software Foundation; either version 2 of the License, or
34782+ * (at your option) any later version.
dece6358
AM
34783+ *
34784+ * This program is distributed in the hope that it will be useful,
34785+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
34786+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34787+ * GNU General Public License for more details.
34788+ *
34789+ * You should have received a copy of the GNU General Public License
523b37e3 34790+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 34791+ */
34792+
34793+/*
34794+ * whiteout for logical deletion and opaque directory
34795+ */
34796+
1facf9fc 34797+#include "aufs.h"
34798+
cd7a4cd9 34799+#define WH_MASK 0444
1facf9fc 34800+
34801+/*
34802+ * If a directory contains this file, then it is opaque. We start with the
34803+ * .wh. flag so that it is blocked by lookup.
34804+ */
0c3ec466
AM
34805+static struct qstr diropq_name = QSTR_INIT(AUFS_WH_DIROPQ,
34806+ sizeof(AUFS_WH_DIROPQ) - 1);
1facf9fc 34807+
34808+/*
34809+ * generate whiteout name, which is NOT terminated by NULL.
34810+ * @name: original d_name.name
34811+ * @len: original d_name.len
34812+ * @wh: whiteout qstr
34813+ * returns zero when succeeds, otherwise error.
34814+ * succeeded value as wh->name should be freed by kfree().
34815+ */
34816+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
34817+{
34818+ char *p;
34819+
34820+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
34821+ return -ENAMETOOLONG;
34822+
34823+ wh->len = name->len + AUFS_WH_PFX_LEN;
34824+ p = kmalloc(wh->len, GFP_NOFS);
34825+ wh->name = p;
34826+ if (p) {
34827+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
34828+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
34829+ /* smp_mb(); */
34830+ return 0;
34831+ }
34832+ return -ENOMEM;
34833+}
34834+
34835+/* ---------------------------------------------------------------------- */
34836+
34837+/*
34838+ * test if the @wh_name exists under @h_parent.
34839+ * @try_sio specifies the necessary of super-io.
34840+ */
0b2a12c6
JR
34841+int au_wh_test(struct user_namespace *h_userns, struct dentry *h_parent,
34842+ struct qstr *wh_name, int try_sio)
1facf9fc 34843+{
34844+ int err;
34845+ struct dentry *wh_dentry;
1facf9fc 34846+
1facf9fc 34847+ if (!try_sio)
b4510431 34848+ wh_dentry = vfsub_lkup_one(wh_name, h_parent);
1facf9fc 34849+ else
0b2a12c6 34850+ wh_dentry = au_sio_lkup_one(h_userns, wh_name, h_parent);
1facf9fc 34851+ err = PTR_ERR(wh_dentry);
2000de60
JR
34852+ if (IS_ERR(wh_dentry)) {
34853+ if (err == -ENAMETOOLONG)
34854+ err = 0;
1facf9fc 34855+ goto out;
2000de60 34856+ }
1facf9fc 34857+
34858+ err = 0;
5527c038 34859+ if (d_is_negative(wh_dentry))
1facf9fc 34860+ goto out_wh; /* success */
34861+
34862+ err = 1;
7e9cd9fe 34863+ if (d_is_reg(wh_dentry))
1facf9fc 34864+ goto out_wh; /* success */
34865+
34866+ err = -EIO;
523b37e3 34867+ AuIOErr("%pd Invalid whiteout entry type 0%o.\n",
5527c038 34868+ wh_dentry, d_inode(wh_dentry)->i_mode);
1facf9fc 34869+
4f0767ce 34870+out_wh:
1facf9fc 34871+ dput(wh_dentry);
4f0767ce 34872+out:
1facf9fc 34873+ return err;
34874+}
34875+
34876+/*
34877+ * test if the @h_dentry sets opaque or not.
34878+ */
0b2a12c6 34879+int au_diropq_test(struct user_namespace *h_userns, struct dentry *h_dentry)
1facf9fc 34880+{
34881+ int err;
34882+ struct inode *h_dir;
34883+
5527c038 34884+ h_dir = d_inode(h_dentry);
0b2a12c6
JR
34885+ err = au_wh_test(h_userns, h_dentry, &diropq_name,
34886+ au_test_h_perm_sio(h_userns, h_dir, MAY_EXEC));
1facf9fc 34887+ return err;
34888+}
34889+
34890+/*
34891+ * returns a negative dentry whose name is unique and temporary.
34892+ */
34893+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
34894+ struct qstr *prefix)
34895+{
1facf9fc 34896+ struct dentry *dentry;
34897+ int i;
027c5e7a 34898+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1],
4a4d8108 34899+ *name, *p;
027c5e7a 34900+ /* strict atomic_t is unnecessary here */
1facf9fc 34901+ static unsigned short cnt;
34902+ struct qstr qs;
0b2a12c6 34903+ struct user_namespace *h_userns;
1facf9fc 34904+
4a4d8108
AM
34905+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
34906+
1facf9fc 34907+ name = defname;
027c5e7a
AM
34908+ qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1;
34909+ if (unlikely(prefix->len > DNAME_INLINE_LEN)) {
1facf9fc 34910+ dentry = ERR_PTR(-ENAMETOOLONG);
4a4d8108 34911+ if (unlikely(qs.len > NAME_MAX))
1facf9fc 34912+ goto out;
34913+ dentry = ERR_PTR(-ENOMEM);
34914+ name = kmalloc(qs.len + 1, GFP_NOFS);
34915+ if (unlikely(!name))
34916+ goto out;
34917+ }
34918+
34919+ /* doubly whiteout-ed */
34920+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
34921+ p = name + AUFS_WH_PFX_LEN * 2;
34922+ memcpy(p, prefix->name, prefix->len);
34923+ p += prefix->len;
34924+ *p++ = '.';
4a4d8108 34925+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
1facf9fc 34926+
0b2a12c6 34927+ h_userns = au_br_userns(br);
1facf9fc 34928+ qs.name = name;
34929+ for (i = 0; i < 3; i++) {
b752ccd1 34930+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
0b2a12c6 34931+ dentry = au_sio_lkup_one(h_userns, &qs, h_parent);
5527c038 34932+ if (IS_ERR(dentry) || d_is_negative(dentry))
1facf9fc 34933+ goto out_name;
34934+ dput(dentry);
34935+ }
0c3ec466 34936+ /* pr_warn("could not get random name\n"); */
1facf9fc 34937+ dentry = ERR_PTR(-EEXIST);
34938+ AuDbg("%.*s\n", AuLNPair(&qs));
34939+ BUG();
34940+
4f0767ce 34941+out_name:
1facf9fc 34942+ if (name != defname)
9f237c51 34943+ au_kfree_try_rcu(name);
4f0767ce 34944+out:
4a4d8108 34945+ AuTraceErrPtr(dentry);
1facf9fc 34946+ return dentry;
1facf9fc 34947+}
34948+
34949+/*
34950+ * rename the @h_dentry on @br to the whiteouted temporary name.
34951+ */
34952+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
34953+{
34954+ int err;
34955+ struct path h_path = {
86dc4139 34956+ .mnt = au_br_mnt(br)
1facf9fc 34957+ };
523b37e3 34958+ struct inode *h_dir, *delegated;
1facf9fc 34959+ struct dentry *h_parent;
34960+
34961+ h_parent = h_dentry->d_parent; /* dir inode is locked */
5527c038 34962+ h_dir = d_inode(h_parent);
1facf9fc 34963+ IMustLock(h_dir);
34964+
34965+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
34966+ err = PTR_ERR(h_path.dentry);
34967+ if (IS_ERR(h_path.dentry))
34968+ goto out;
34969+
34970+ /* under the same dir, no need to lock_rename() */
523b37e3 34971+ delegated = NULL;
f2c43d5f
AM
34972+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path, &delegated,
34973+ /*flags*/0);
1facf9fc 34974+ AuTraceErr(err);
523b37e3
AM
34975+ if (unlikely(err == -EWOULDBLOCK)) {
34976+ pr_warn("cannot retry for NFSv4 delegation"
34977+ " for an internal rename\n");
34978+ iput(delegated);
34979+ }
1facf9fc 34980+ dput(h_path.dentry);
34981+
4f0767ce 34982+out:
4a4d8108 34983+ AuTraceErr(err);
1facf9fc 34984+ return err;
34985+}
34986+
34987+/* ---------------------------------------------------------------------- */
34988+/*
34989+ * functions for removing a whiteout
34990+ */
34991+
34992+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
34993+{
523b37e3
AM
34994+ int err, force;
34995+ struct inode *delegated;
1facf9fc 34996+
34997+ /*
34998+ * forces superio when the dir has a sticky bit.
34999+ * this may be a violation of unix fs semantics.
35000+ */
35001+ force = (h_dir->i_mode & S_ISVTX)
5527c038 35002+ && !uid_eq(current_fsuid(), d_inode(h_path->dentry)->i_uid);
523b37e3
AM
35003+ delegated = NULL;
35004+ err = vfsub_unlink(h_dir, h_path, &delegated, force);
35005+ if (unlikely(err == -EWOULDBLOCK)) {
35006+ pr_warn("cannot retry for NFSv4 delegation"
35007+ " for an internal unlink\n");
35008+ iput(delegated);
35009+ }
35010+ return err;
1facf9fc 35011+}
35012+
35013+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
35014+ struct dentry *dentry)
35015+{
35016+ int err;
35017+
35018+ err = do_unlink_wh(h_dir, h_path);
35019+ if (!err && dentry)
35020+ au_set_dbwh(dentry, -1);
35021+
35022+ return err;
35023+}
35024+
35025+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
35026+ struct au_branch *br)
35027+{
35028+ int err;
35029+ struct path h_path = {
86dc4139 35030+ .mnt = au_br_mnt(br)
1facf9fc 35031+ };
35032+
35033+ err = 0;
b4510431 35034+ h_path.dentry = vfsub_lkup_one(wh, h_parent);
1facf9fc 35035+ if (IS_ERR(h_path.dentry))
35036+ err = PTR_ERR(h_path.dentry);
35037+ else {
5527c038
JR
35038+ if (d_is_reg(h_path.dentry))
35039+ err = do_unlink_wh(d_inode(h_parent), &h_path);
1facf9fc 35040+ dput(h_path.dentry);
35041+ }
35042+
35043+ return err;
35044+}
35045+
35046+/* ---------------------------------------------------------------------- */
35047+/*
35048+ * initialize/clean whiteout for a branch
35049+ */
35050+
35051+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
35052+ const int isdir)
35053+{
35054+ int err;
523b37e3 35055+ struct inode *delegated;
1facf9fc 35056+
5527c038 35057+ if (d_is_negative(whpath->dentry))
1facf9fc 35058+ return;
35059+
86dc4139
AM
35060+ if (isdir)
35061+ err = vfsub_rmdir(h_dir, whpath);
523b37e3
AM
35062+ else {
35063+ delegated = NULL;
35064+ err = vfsub_unlink(h_dir, whpath, &delegated, /*force*/0);
35065+ if (unlikely(err == -EWOULDBLOCK)) {
35066+ pr_warn("cannot retry for NFSv4 delegation"
35067+ " for an internal unlink\n");
35068+ iput(delegated);
35069+ }
35070+ }
1facf9fc 35071+ if (unlikely(err))
523b37e3
AM
35072+ pr_warn("failed removing %pd (%d), ignored.\n",
35073+ whpath->dentry, err);
1facf9fc 35074+}
35075+
35076+static int test_linkable(struct dentry *h_root)
35077+{
5527c038 35078+ struct inode *h_dir = d_inode(h_root);
1facf9fc 35079+
35080+ if (h_dir->i_op->link)
35081+ return 0;
35082+
523b37e3
AM
35083+ pr_err("%pd (%s) doesn't support link(2), use noplink and rw+nolwh\n",
35084+ h_root, au_sbtype(h_root->d_sb));
43982f53 35085+ return -ENOSYS; /* the branch doesn't have its ->link() */
1facf9fc 35086+}
35087+
35088+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
35089+static int au_whdir(struct inode *h_dir, struct path *path)
35090+{
35091+ int err;
35092+
35093+ err = -EEXIST;
5527c038 35094+ if (d_is_negative(path->dentry)) {
cd7a4cd9 35095+ int mode = 0700;
1facf9fc 35096+
35097+ if (au_test_nfs(path->dentry->d_sb))
cd7a4cd9 35098+ mode |= 0111;
86dc4139 35099+ err = vfsub_mkdir(h_dir, path, mode);
2000de60 35100+ } else if (d_is_dir(path->dentry))
1facf9fc 35101+ err = 0;
35102+ else
523b37e3 35103+ pr_err("unknown %pd exists\n", path->dentry);
1facf9fc 35104+
35105+ return err;
35106+}
35107+
35108+struct au_wh_base {
35109+ const struct qstr *name;
35110+ struct dentry *dentry;
35111+};
35112+
35113+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
35114+ struct path *h_path)
35115+{
35116+ h_path->dentry = base[AuBrWh_BASE].dentry;
35117+ au_wh_clean(h_dir, h_path, /*isdir*/0);
35118+ h_path->dentry = base[AuBrWh_PLINK].dentry;
35119+ au_wh_clean(h_dir, h_path, /*isdir*/1);
35120+ h_path->dentry = base[AuBrWh_ORPH].dentry;
35121+ au_wh_clean(h_dir, h_path, /*isdir*/1);
35122+}
35123+
35124+/*
35125+ * returns tri-state,
c1595e42 35126+ * minus: error, caller should print the message
acd2b654 35127+ * zero: success
c1595e42 35128+ * plus: error, caller should NOT print the message
1facf9fc 35129+ */
35130+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
35131+ int do_plink, struct au_wh_base base[],
35132+ struct path *h_path)
35133+{
35134+ int err;
35135+ struct inode *h_dir;
35136+
5527c038 35137+ h_dir = d_inode(h_root);
1facf9fc 35138+ h_path->dentry = base[AuBrWh_BASE].dentry;
35139+ au_wh_clean(h_dir, h_path, /*isdir*/0);
35140+ h_path->dentry = base[AuBrWh_PLINK].dentry;
35141+ if (do_plink) {
35142+ err = test_linkable(h_root);
35143+ if (unlikely(err)) {
35144+ err = 1;
35145+ goto out;
35146+ }
35147+
35148+ err = au_whdir(h_dir, h_path);
35149+ if (unlikely(err))
35150+ goto out;
35151+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
35152+ } else
35153+ au_wh_clean(h_dir, h_path, /*isdir*/1);
35154+ h_path->dentry = base[AuBrWh_ORPH].dentry;
35155+ err = au_whdir(h_dir, h_path);
35156+ if (unlikely(err))
35157+ goto out;
35158+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
35159+
4f0767ce 35160+out:
1facf9fc 35161+ return err;
35162+}
35163+
35164+/*
35165+ * for the moment, aufs supports the branch filesystem which does not support
35166+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
35167+ * copyup failed. finally, such filesystem will not be used as the writable
35168+ * branch.
35169+ *
35170+ * returns tri-state, see above.
35171+ */
35172+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
35173+ int do_plink, struct au_wh_base base[],
35174+ struct path *h_path)
35175+{
35176+ int err;
35177+ struct inode *h_dir;
35178+
1308ab2a 35179+ WbrWhMustWriteLock(wbr);
35180+
1facf9fc 35181+ err = test_linkable(h_root);
35182+ if (unlikely(err)) {
35183+ err = 1;
35184+ goto out;
35185+ }
35186+
35187+ /*
35188+ * todo: should this create be done in /sbin/mount.aufs helper?
35189+ */
35190+ err = -EEXIST;
5527c038
JR
35191+ h_dir = d_inode(h_root);
35192+ if (d_is_negative(base[AuBrWh_BASE].dentry)) {
86dc4139
AM
35193+ h_path->dentry = base[AuBrWh_BASE].dentry;
35194+ err = vfsub_create(h_dir, h_path, WH_MASK, /*want_excl*/true);
7e9cd9fe 35195+ } else if (d_is_reg(base[AuBrWh_BASE].dentry))
1facf9fc 35196+ err = 0;
35197+ else
523b37e3 35198+ pr_err("unknown %pd2 exists\n", base[AuBrWh_BASE].dentry);
1facf9fc 35199+ if (unlikely(err))
35200+ goto out;
35201+
35202+ h_path->dentry = base[AuBrWh_PLINK].dentry;
35203+ if (do_plink) {
35204+ err = au_whdir(h_dir, h_path);
35205+ if (unlikely(err))
35206+ goto out;
35207+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
35208+ } else
35209+ au_wh_clean(h_dir, h_path, /*isdir*/1);
35210+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
35211+
35212+ h_path->dentry = base[AuBrWh_ORPH].dentry;
35213+ err = au_whdir(h_dir, h_path);
35214+ if (unlikely(err))
35215+ goto out;
35216+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
35217+
4f0767ce 35218+out:
1facf9fc 35219+ return err;
35220+}
35221+
35222+/*
35223+ * initialize the whiteout base file/dir for @br.
35224+ */
86dc4139 35225+int au_wh_init(struct au_branch *br, struct super_block *sb)
1facf9fc 35226+{
35227+ int err, i;
35228+ const unsigned char do_plink
35229+ = !!au_opt_test(au_mntflags(sb), PLINK);
1facf9fc 35230+ struct inode *h_dir;
86dc4139
AM
35231+ struct path path = br->br_path;
35232+ struct dentry *h_root = path.dentry;
1facf9fc 35233+ struct au_wbr *wbr = br->br_wbr;
35234+ static const struct qstr base_name[] = {
0c3ec466
AM
35235+ [AuBrWh_BASE] = QSTR_INIT(AUFS_BASE_NAME,
35236+ sizeof(AUFS_BASE_NAME) - 1),
35237+ [AuBrWh_PLINK] = QSTR_INIT(AUFS_PLINKDIR_NAME,
35238+ sizeof(AUFS_PLINKDIR_NAME) - 1),
35239+ [AuBrWh_ORPH] = QSTR_INIT(AUFS_ORPHDIR_NAME,
35240+ sizeof(AUFS_ORPHDIR_NAME) - 1)
1facf9fc 35241+ };
35242+ struct au_wh_base base[] = {
35243+ [AuBrWh_BASE] = {
35244+ .name = base_name + AuBrWh_BASE,
35245+ .dentry = NULL
35246+ },
35247+ [AuBrWh_PLINK] = {
35248+ .name = base_name + AuBrWh_PLINK,
35249+ .dentry = NULL
35250+ },
35251+ [AuBrWh_ORPH] = {
35252+ .name = base_name + AuBrWh_ORPH,
35253+ .dentry = NULL
35254+ }
35255+ };
35256+
1308ab2a 35257+ if (wbr)
35258+ WbrWhMustWriteLock(wbr);
1facf9fc 35259+
1facf9fc 35260+ for (i = 0; i < AuBrWh_Last; i++) {
35261+ /* doubly whiteouted */
35262+ struct dentry *d;
35263+
35264+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
35265+ err = PTR_ERR(d);
35266+ if (IS_ERR(d))
35267+ goto out;
35268+
35269+ base[i].dentry = d;
35270+ AuDebugOn(wbr
35271+ && wbr->wbr_wh[i]
35272+ && wbr->wbr_wh[i] != base[i].dentry);
35273+ }
35274+
35275+ if (wbr)
35276+ for (i = 0; i < AuBrWh_Last; i++) {
35277+ dput(wbr->wbr_wh[i]);
35278+ wbr->wbr_wh[i] = NULL;
35279+ }
35280+
35281+ err = 0;
1e00d052 35282+ if (!au_br_writable(br->br_perm)) {
5527c038 35283+ h_dir = d_inode(h_root);
1facf9fc 35284+ au_wh_init_ro(h_dir, base, &path);
1e00d052 35285+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 35286+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
35287+ if (err > 0)
35288+ goto out;
35289+ else if (err)
35290+ goto out_err;
1e00d052 35291+ } else {
1facf9fc 35292+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
35293+ if (err > 0)
35294+ goto out;
35295+ else if (err)
35296+ goto out_err;
1facf9fc 35297+ }
35298+ goto out; /* success */
35299+
4f0767ce 35300+out_err:
523b37e3
AM
35301+ pr_err("an error(%d) on the writable branch %pd(%s)\n",
35302+ err, h_root, au_sbtype(h_root->d_sb));
4f0767ce 35303+out:
1facf9fc 35304+ for (i = 0; i < AuBrWh_Last; i++)
35305+ dput(base[i].dentry);
35306+ return err;
35307+}
35308+
35309+/* ---------------------------------------------------------------------- */
35310+/*
35311+ * whiteouts are all hard-linked usually.
35312+ * when its link count reaches a ceiling, we create a new whiteout base
35313+ * asynchronously.
35314+ */
35315+
35316+struct reinit_br_wh {
35317+ struct super_block *sb;
35318+ struct au_branch *br;
35319+};
35320+
35321+static void reinit_br_wh(void *arg)
35322+{
35323+ int err;
35324+ aufs_bindex_t bindex;
35325+ struct path h_path;
35326+ struct reinit_br_wh *a = arg;
35327+ struct au_wbr *wbr;
523b37e3 35328+ struct inode *dir, *delegated;
1facf9fc 35329+ struct dentry *h_root;
35330+ struct au_hinode *hdir;
35331+
35332+ err = 0;
35333+ wbr = a->br->br_wbr;
35334+ /* big aufs lock */
35335+ si_noflush_write_lock(a->sb);
35336+ if (!au_br_writable(a->br->br_perm))
35337+ goto out;
35338+ bindex = au_br_index(a->sb, a->br->br_id);
35339+ if (unlikely(bindex < 0))
35340+ goto out;
35341+
1308ab2a 35342+ di_read_lock_parent(a->sb->s_root, AuLock_IR);
5527c038 35343+ dir = d_inode(a->sb->s_root);
1facf9fc 35344+ hdir = au_hi(dir, bindex);
35345+ h_root = au_h_dptr(a->sb->s_root, bindex);
86dc4139 35346+ AuDebugOn(h_root != au_br_dentry(a->br));
1facf9fc 35347+
5afbbe0d 35348+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 35349+ wbr_wh_write_lock(wbr);
35350+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
35351+ h_root, a->br);
35352+ if (!err) {
86dc4139
AM
35353+ h_path.dentry = wbr->wbr_whbase;
35354+ h_path.mnt = au_br_mnt(a->br);
523b37e3
AM
35355+ delegated = NULL;
35356+ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated,
35357+ /*force*/0);
35358+ if (unlikely(err == -EWOULDBLOCK)) {
35359+ pr_warn("cannot retry for NFSv4 delegation"
35360+ " for an internal unlink\n");
35361+ iput(delegated);
35362+ }
1facf9fc 35363+ } else {
523b37e3 35364+ pr_warn("%pd is moved, ignored\n", wbr->wbr_whbase);
1facf9fc 35365+ err = 0;
35366+ }
35367+ dput(wbr->wbr_whbase);
35368+ wbr->wbr_whbase = NULL;
35369+ if (!err)
86dc4139 35370+ err = au_wh_init(a->br, a->sb);
1facf9fc 35371+ wbr_wh_write_unlock(wbr);
5afbbe0d 35372+ au_hn_inode_unlock(hdir);
1308ab2a 35373+ di_read_unlock(a->sb->s_root, AuLock_IR);
076b876e
AM
35374+ if (!err)
35375+ au_fhsm_wrote(a->sb, bindex, /*force*/0);
1facf9fc 35376+
4f0767ce 35377+out:
1facf9fc 35378+ if (wbr)
35379+ atomic_dec(&wbr->wbr_wh_running);
acd2b654 35380+ au_lcnt_dec(&a->br->br_count);
1facf9fc 35381+ si_write_unlock(a->sb);
027c5e7a 35382+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
9f237c51 35383+ au_kfree_rcu(a);
1facf9fc 35384+ if (unlikely(err))
35385+ AuIOErr("err %d\n", err);
35386+}
35387+
35388+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
35389+{
35390+ int do_dec, wkq_err;
35391+ struct reinit_br_wh *arg;
35392+
35393+ do_dec = 1;
35394+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
35395+ goto out;
35396+
35397+ /* ignore ENOMEM */
35398+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
35399+ if (arg) {
35400+ /*
35401+ * dec(wh_running), kfree(arg) and dec(br_count)
35402+ * in reinit function
35403+ */
35404+ arg->sb = sb;
35405+ arg->br = br;
acd2b654 35406+ au_lcnt_inc(&br->br_count);
53392da6 35407+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*flags*/0);
1facf9fc 35408+ if (unlikely(wkq_err)) {
35409+ atomic_dec(&br->br_wbr->wbr_wh_running);
acd2b654 35410+ au_lcnt_dec(&br->br_count);
9f237c51 35411+ au_kfree_rcu(arg);
1facf9fc 35412+ }
35413+ do_dec = 0;
35414+ }
35415+
4f0767ce 35416+out:
1facf9fc 35417+ if (do_dec)
35418+ atomic_dec(&br->br_wbr->wbr_wh_running);
35419+}
35420+
35421+/* ---------------------------------------------------------------------- */
35422+
35423+/*
35424+ * create the whiteout @wh.
35425+ */
35426+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
35427+ struct dentry *wh)
35428+{
35429+ int err;
35430+ struct path h_path = {
35431+ .dentry = wh
35432+ };
35433+ struct au_branch *br;
35434+ struct au_wbr *wbr;
35435+ struct dentry *h_parent;
523b37e3 35436+ struct inode *h_dir, *delegated;
1facf9fc 35437+
35438+ h_parent = wh->d_parent; /* dir inode is locked */
5527c038 35439+ h_dir = d_inode(h_parent);
1facf9fc 35440+ IMustLock(h_dir);
35441+
35442+ br = au_sbr(sb, bindex);
86dc4139 35443+ h_path.mnt = au_br_mnt(br);
1facf9fc 35444+ wbr = br->br_wbr;
35445+ wbr_wh_read_lock(wbr);
35446+ if (wbr->wbr_whbase) {
523b37e3
AM
35447+ delegated = NULL;
35448+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path, &delegated);
35449+ if (unlikely(err == -EWOULDBLOCK)) {
35450+ pr_warn("cannot retry for NFSv4 delegation"
35451+ " for an internal link\n");
35452+ iput(delegated);
35453+ }
1facf9fc 35454+ if (!err || err != -EMLINK)
35455+ goto out;
35456+
35457+ /* link count full. re-initialize br_whbase. */
35458+ kick_reinit_br_wh(sb, br);
35459+ }
35460+
35461+ /* return this error in this context */
b4510431 35462+ err = vfsub_create(h_dir, &h_path, WH_MASK, /*want_excl*/true);
076b876e
AM
35463+ if (!err)
35464+ au_fhsm_wrote(sb, bindex, /*force*/0);
1facf9fc 35465+
4f0767ce 35466+out:
1facf9fc 35467+ wbr_wh_read_unlock(wbr);
35468+ return err;
35469+}
35470+
35471+/* ---------------------------------------------------------------------- */
35472+
35473+/*
35474+ * create or remove the diropq.
35475+ */
35476+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
35477+ unsigned int flags)
35478+{
35479+ struct dentry *opq_dentry, *h_dentry;
35480+ struct super_block *sb;
35481+ struct au_branch *br;
35482+ int err;
35483+
35484+ sb = dentry->d_sb;
35485+ br = au_sbr(sb, bindex);
35486+ h_dentry = au_h_dptr(dentry, bindex);
b4510431 35487+ opq_dentry = vfsub_lkup_one(&diropq_name, h_dentry);
1facf9fc 35488+ if (IS_ERR(opq_dentry))
35489+ goto out;
35490+
35491+ if (au_ftest_diropq(flags, CREATE)) {
35492+ err = link_or_create_wh(sb, bindex, opq_dentry);
35493+ if (!err) {
35494+ au_set_dbdiropq(dentry, bindex);
35495+ goto out; /* success */
35496+ }
35497+ } else {
35498+ struct path tmp = {
35499+ .dentry = opq_dentry,
86dc4139 35500+ .mnt = au_br_mnt(br)
1facf9fc 35501+ };
5527c038 35502+ err = do_unlink_wh(au_h_iptr(d_inode(dentry), bindex), &tmp);
1facf9fc 35503+ if (!err)
35504+ au_set_dbdiropq(dentry, -1);
35505+ }
35506+ dput(opq_dentry);
35507+ opq_dentry = ERR_PTR(err);
35508+
4f0767ce 35509+out:
1facf9fc 35510+ return opq_dentry;
35511+}
35512+
35513+struct do_diropq_args {
35514+ struct dentry **errp;
35515+ struct dentry *dentry;
35516+ aufs_bindex_t bindex;
35517+ unsigned int flags;
35518+};
35519+
35520+static void call_do_diropq(void *args)
35521+{
35522+ struct do_diropq_args *a = args;
35523+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
35524+}
35525+
35526+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
35527+ unsigned int flags)
35528+{
35529+ struct dentry *diropq, *h_dentry;
0b2a12c6 35530+ struct user_namespace *h_userns;
1facf9fc 35531+
0b2a12c6 35532+ h_userns = au_sbr_userns(dentry->d_sb, bindex);
1facf9fc 35533+ h_dentry = au_h_dptr(dentry, bindex);
0b2a12c6
JR
35534+ if (!au_test_h_perm_sio(h_userns, d_inode(h_dentry),
35535+ MAY_EXEC | MAY_WRITE))
1facf9fc 35536+ diropq = do_diropq(dentry, bindex, flags);
35537+ else {
35538+ int wkq_err;
35539+ struct do_diropq_args args = {
35540+ .errp = &diropq,
35541+ .dentry = dentry,
35542+ .bindex = bindex,
35543+ .flags = flags
35544+ };
35545+
35546+ wkq_err = au_wkq_wait(call_do_diropq, &args);
35547+ if (unlikely(wkq_err))
35548+ diropq = ERR_PTR(wkq_err);
35549+ }
35550+
35551+ return diropq;
35552+}
35553+
35554+/* ---------------------------------------------------------------------- */
35555+
35556+/*
35557+ * lookup whiteout dentry.
35558+ * @h_parent: lower parent dentry which must exist and be locked
35559+ * @base_name: name of dentry which will be whiteouted
35560+ * returns dentry for whiteout.
35561+ */
35562+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
35563+ struct au_branch *br)
35564+{
35565+ int err;
35566+ struct qstr wh_name;
35567+ struct dentry *wh_dentry;
35568+
35569+ err = au_wh_name_alloc(&wh_name, base_name);
35570+ wh_dentry = ERR_PTR(err);
35571+ if (!err) {
b4510431 35572+ wh_dentry = vfsub_lkup_one(&wh_name, h_parent);
9f237c51 35573+ au_kfree_try_rcu(wh_name.name);
1facf9fc 35574+ }
35575+ return wh_dentry;
35576+}
35577+
35578+/*
35579+ * link/create a whiteout for @dentry on @bindex.
35580+ */
35581+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
35582+ struct dentry *h_parent)
35583+{
35584+ struct dentry *wh_dentry;
35585+ struct super_block *sb;
35586+ int err;
35587+
35588+ sb = dentry->d_sb;
35589+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
5527c038 35590+ if (!IS_ERR(wh_dentry) && d_is_negative(wh_dentry)) {
1facf9fc 35591+ err = link_or_create_wh(sb, bindex, wh_dentry);
076b876e 35592+ if (!err) {
1facf9fc 35593+ au_set_dbwh(dentry, bindex);
076b876e
AM
35594+ au_fhsm_wrote(sb, bindex, /*force*/0);
35595+ } else {
1facf9fc 35596+ dput(wh_dentry);
35597+ wh_dentry = ERR_PTR(err);
35598+ }
35599+ }
35600+
35601+ return wh_dentry;
35602+}
35603+
35604+/* ---------------------------------------------------------------------- */
35605+
35606+/* Delete all whiteouts in this directory on branch bindex. */
35607+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
35608+ aufs_bindex_t bindex, struct au_branch *br)
35609+{
35610+ int err;
35611+ unsigned long ul, n;
35612+ struct qstr wh_name;
35613+ char *p;
35614+ struct hlist_head *head;
c06a8ce3 35615+ struct au_vdir_wh *pos;
1facf9fc 35616+ struct au_vdir_destr *str;
35617+
35618+ err = -ENOMEM;
537831f9 35619+ p = (void *)__get_free_page(GFP_NOFS);
1facf9fc 35620+ wh_name.name = p;
35621+ if (unlikely(!wh_name.name))
35622+ goto out;
35623+
35624+ err = 0;
35625+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
35626+ p += AUFS_WH_PFX_LEN;
35627+ n = whlist->nh_num;
35628+ head = whlist->nh_head;
35629+ for (ul = 0; !err && ul < n; ul++, head++) {
c06a8ce3
AM
35630+ hlist_for_each_entry(pos, head, wh_hash) {
35631+ if (pos->wh_bindex != bindex)
1facf9fc 35632+ continue;
35633+
c06a8ce3 35634+ str = &pos->wh_str;
1facf9fc 35635+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
35636+ memcpy(p, str->name, str->len);
35637+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
35638+ err = unlink_wh_name(h_dentry, &wh_name, br);
35639+ if (!err)
35640+ continue;
35641+ break;
35642+ }
35643+ AuIOErr("whiteout name too long %.*s\n",
35644+ str->len, str->name);
35645+ err = -EIO;
35646+ break;
35647+ }
35648+ }
1c60b727 35649+ free_page((unsigned long)wh_name.name);
1facf9fc 35650+
4f0767ce 35651+out:
1facf9fc 35652+ return err;
35653+}
35654+
35655+struct del_wh_children_args {
35656+ int *errp;
35657+ struct dentry *h_dentry;
1308ab2a 35658+ struct au_nhash *whlist;
1facf9fc 35659+ aufs_bindex_t bindex;
35660+ struct au_branch *br;
35661+};
35662+
35663+static void call_del_wh_children(void *args)
35664+{
35665+ struct del_wh_children_args *a = args;
1308ab2a 35666+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
1facf9fc 35667+}
35668+
35669+/* ---------------------------------------------------------------------- */
35670+
35671+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
35672+{
35673+ struct au_whtmp_rmdir *whtmp;
dece6358 35674+ int err;
1308ab2a 35675+ unsigned int rdhash;
dece6358
AM
35676+
35677+ SiMustAnyLock(sb);
1facf9fc 35678+
be52b249 35679+ whtmp = kzalloc(sizeof(*whtmp), gfp);
dece6358
AM
35680+ if (unlikely(!whtmp)) {
35681+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 35682+ goto out;
dece6358 35683+ }
1facf9fc 35684+
1308ab2a 35685+ /* no estimation for dir size */
35686+ rdhash = au_sbi(sb)->si_rdhash;
35687+ if (!rdhash)
35688+ rdhash = AUFS_RDHASH_DEF;
35689+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
35690+ if (unlikely(err)) {
9f237c51 35691+ au_kfree_rcu(whtmp);
1308ab2a 35692+ whtmp = ERR_PTR(err);
35693+ }
dece6358 35694+
4f0767ce 35695+out:
dece6358 35696+ return whtmp;
1facf9fc 35697+}
35698+
35699+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
35700+{
027c5e7a 35701+ if (whtmp->br)
acd2b654 35702+ au_lcnt_dec(&whtmp->br->br_count);
1facf9fc 35703+ dput(whtmp->wh_dentry);
35704+ iput(whtmp->dir);
dece6358 35705+ au_nhash_wh_free(&whtmp->whlist);
9f237c51 35706+ au_kfree_rcu(whtmp);
1facf9fc 35707+}
35708+
35709+/*
35710+ * rmdir the whiteouted temporary named dir @h_dentry.
35711+ * @whlist: whiteouted children.
35712+ */
35713+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
35714+ struct dentry *wh_dentry, struct au_nhash *whlist)
35715+{
35716+ int err;
2000de60 35717+ unsigned int h_nlink;
1facf9fc 35718+ struct path h_tmp;
35719+ struct inode *wh_inode, *h_dir;
35720+ struct au_branch *br;
0b2a12c6 35721+ struct user_namespace *h_userns;
1facf9fc 35722+
5527c038 35723+ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */
1facf9fc 35724+ IMustLock(h_dir);
35725+
35726+ br = au_sbr(dir->i_sb, bindex);
0b2a12c6 35727+ h_userns = au_br_userns(br);
5527c038 35728+ wh_inode = d_inode(wh_dentry);
febd17d6 35729+ inode_lock_nested(wh_inode, AuLsc_I_CHILD);
1facf9fc 35730+
35731+ /*
35732+ * someone else might change some whiteouts while we were sleeping.
35733+ * it means this whlist may have an obsoleted entry.
35734+ */
0b2a12c6 35735+ if (!au_test_h_perm_sio(h_userns, wh_inode, MAY_EXEC | MAY_WRITE))
1facf9fc 35736+ err = del_wh_children(wh_dentry, whlist, bindex, br);
35737+ else {
35738+ int wkq_err;
35739+ struct del_wh_children_args args = {
35740+ .errp = &err,
35741+ .h_dentry = wh_dentry,
1308ab2a 35742+ .whlist = whlist,
1facf9fc 35743+ .bindex = bindex,
35744+ .br = br
35745+ };
35746+
35747+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
35748+ if (unlikely(wkq_err))
35749+ err = wkq_err;
35750+ }
febd17d6 35751+ inode_unlock(wh_inode);
1facf9fc 35752+
35753+ if (!err) {
35754+ h_tmp.dentry = wh_dentry;
86dc4139 35755+ h_tmp.mnt = au_br_mnt(br);
2000de60 35756+ h_nlink = h_dir->i_nlink;
1facf9fc 35757+ err = vfsub_rmdir(h_dir, &h_tmp);
2000de60
JR
35758+ /* some fs doesn't change the parent nlink in some cases */
35759+ h_nlink -= h_dir->i_nlink;
1facf9fc 35760+ }
35761+
35762+ if (!err) {
5afbbe0d 35763+ if (au_ibtop(dir) == bindex) {
7f207e10 35764+ /* todo: dir->i_mutex is necessary */
1facf9fc 35765+ au_cpup_attr_timesizes(dir);
2000de60
JR
35766+ if (h_nlink)
35767+ vfsub_drop_nlink(dir);
1facf9fc 35768+ }
35769+ return 0; /* success */
35770+ }
35771+
523b37e3 35772+ pr_warn("failed removing %pd(%d), ignored\n", wh_dentry, err);
1facf9fc 35773+ return err;
35774+}
35775+
35776+static void call_rmdir_whtmp(void *args)
35777+{
35778+ int err;
e49829fe 35779+ aufs_bindex_t bindex;
1facf9fc 35780+ struct au_whtmp_rmdir *a = args;
35781+ struct super_block *sb;
35782+ struct dentry *h_parent;
35783+ struct inode *h_dir;
1facf9fc 35784+ struct au_hinode *hdir;
35785+
35786+ /* rmdir by nfsd may cause deadlock with this i_mutex */
febd17d6 35787+ /* inode_lock(a->dir); */
e49829fe 35788+ err = -EROFS;
1facf9fc 35789+ sb = a->dir->i_sb;
e49829fe
JR
35790+ si_read_lock(sb, !AuLock_FLUSH);
35791+ if (!au_br_writable(a->br->br_perm))
35792+ goto out;
35793+ bindex = au_br_index(sb, a->br->br_id);
35794+ if (unlikely(bindex < 0))
1facf9fc 35795+ goto out;
35796+
35797+ err = -EIO;
1facf9fc 35798+ ii_write_lock_parent(a->dir);
35799+ h_parent = dget_parent(a->wh_dentry);
5527c038 35800+ h_dir = d_inode(h_parent);
e49829fe 35801+ hdir = au_hi(a->dir, bindex);
86dc4139
AM
35802+ err = vfsub_mnt_want_write(au_br_mnt(a->br));
35803+ if (unlikely(err))
35804+ goto out_mnt;
5afbbe0d 35805+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
e49829fe
JR
35806+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent,
35807+ a->br);
86dc4139
AM
35808+ if (!err)
35809+ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry, &a->whlist);
5afbbe0d 35810+ au_hn_inode_unlock(hdir);
86dc4139
AM
35811+ vfsub_mnt_drop_write(au_br_mnt(a->br));
35812+
35813+out_mnt:
1facf9fc 35814+ dput(h_parent);
35815+ ii_write_unlock(a->dir);
4f0767ce 35816+out:
febd17d6 35817+ /* inode_unlock(a->dir); */
1facf9fc 35818+ au_whtmp_rmdir_free(a);
027c5e7a
AM
35819+ si_read_unlock(sb);
35820+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 35821+ if (unlikely(err))
35822+ AuIOErr("err %d\n", err);
35823+}
35824+
35825+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
35826+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
35827+{
35828+ int wkq_err;
e49829fe 35829+ struct super_block *sb;
1facf9fc 35830+
35831+ IMustLock(dir);
35832+
35833+ /* all post-process will be done in do_rmdir_whtmp(). */
e49829fe 35834+ sb = dir->i_sb;
1facf9fc 35835+ args->dir = au_igrab(dir);
e49829fe 35836+ args->br = au_sbr(sb, bindex);
acd2b654 35837+ au_lcnt_inc(&args->br->br_count);
1facf9fc 35838+ args->wh_dentry = dget(wh_dentry);
53392da6 35839+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb, /*flags*/0);
1facf9fc 35840+ if (unlikely(wkq_err)) {
523b37e3 35841+ pr_warn("rmdir error %pd (%d), ignored\n", wh_dentry, wkq_err);
1facf9fc 35842+ au_whtmp_rmdir_free(args);
35843+ }
35844+}
7f207e10 35845diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
eca34b5c 35846--- /usr/share/empty/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6
JR
35847+++ linux/fs/aufs/whout.h 2021-05-02 20:15:14.676670793 +0200
35848@@ -0,0 +1,87 @@
062440b3 35849+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 35850+/*
d58c55f2 35851+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 35852+ *
35853+ * This program, aufs is free software; you can redistribute it and/or modify
35854+ * it under the terms of the GNU General Public License as published by
35855+ * the Free Software Foundation; either version 2 of the License, or
35856+ * (at your option) any later version.
dece6358
AM
35857+ *
35858+ * This program is distributed in the hope that it will be useful,
35859+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
35860+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35861+ * GNU General Public License for more details.
35862+ *
35863+ * You should have received a copy of the GNU General Public License
523b37e3 35864+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 35865+ */
35866+
35867+/*
35868+ * whiteout for logical deletion and opaque directory
35869+ */
35870+
35871+#ifndef __AUFS_WHOUT_H__
35872+#define __AUFS_WHOUT_H__
35873+
35874+#ifdef __KERNEL__
35875+
1facf9fc 35876+#include "dir.h"
35877+
35878+/* whout.c */
35879+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
0b2a12c6
JR
35880+int au_wh_test(struct user_namespace *h_userns, struct dentry *h_parent,
35881+ struct qstr *wh_name, int try_sio);
35882+int au_diropq_test(struct user_namespace *h_userns, struct dentry *h_dentry);
3c1bdaff 35883+struct au_branch;
1facf9fc 35884+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
35885+ struct qstr *prefix);
35886+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
35887+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
35888+ struct dentry *dentry);
86dc4139 35889+int au_wh_init(struct au_branch *br, struct super_block *sb);
1facf9fc 35890+
35891+/* diropq flags */
35892+#define AuDiropq_CREATE 1
35893+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
7f207e10
AM
35894+#define au_fset_diropq(flags, name) \
35895+ do { (flags) |= AuDiropq_##name; } while (0)
35896+#define au_fclr_diropq(flags, name) \
35897+ do { (flags) &= ~AuDiropq_##name; } while (0)
1facf9fc 35898+
35899+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
35900+ unsigned int flags);
35901+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
35902+ struct au_branch *br);
35903+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
35904+ struct dentry *h_parent);
35905+
35906+/* real rmdir for the whiteout-ed dir */
35907+struct au_whtmp_rmdir {
35908+ struct inode *dir;
e49829fe 35909+ struct au_branch *br;
1facf9fc 35910+ struct dentry *wh_dentry;
dece6358 35911+ struct au_nhash whlist;
1facf9fc 35912+};
35913+
35914+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
35915+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
35916+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
35917+ struct dentry *wh_dentry, struct au_nhash *whlist);
35918+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
35919+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
35920+
35921+/* ---------------------------------------------------------------------- */
35922+
35923+static inline struct dentry *au_diropq_create(struct dentry *dentry,
35924+ aufs_bindex_t bindex)
35925+{
35926+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
35927+}
35928+
35929+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
35930+{
35931+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
35932+}
35933+
35934+#endif /* __KERNEL__ */
35935+#endif /* __AUFS_WHOUT_H__ */
7f207e10 35936diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
eca34b5c 35937--- /usr/share/empty/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 35938+++ linux/fs/aufs/wkq.c 2021-05-02 20:15:14.676670793 +0200
43982f53 35939@@ -0,0 +1,372 @@
cd7a4cd9 35940+// SPDX-License-Identifier: GPL-2.0
1facf9fc 35941+/*
d58c55f2 35942+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 35943+ *
35944+ * This program, aufs is free software; you can redistribute it and/or modify
35945+ * it under the terms of the GNU General Public License as published by
35946+ * the Free Software Foundation; either version 2 of the License, or
35947+ * (at your option) any later version.
dece6358
AM
35948+ *
35949+ * This program is distributed in the hope that it will be useful,
35950+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
35951+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35952+ * GNU General Public License for more details.
35953+ *
35954+ * You should have received a copy of the GNU General Public License
523b37e3 35955+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 35956+ */
35957+
35958+/*
35959+ * workqueue for asynchronous/super-io operations
acd2b654 35960+ * todo: try new credential scheme
1facf9fc 35961+ */
35962+
dece6358 35963+#include <linux/module.h>
1facf9fc 35964+#include "aufs.h"
35965+
9dbd164d 35966+/* internal workqueue named AUFS_WKQ_NAME */
b752ccd1 35967+
9dbd164d 35968+static struct workqueue_struct *au_wkq;
1facf9fc 35969+
35970+struct au_wkinfo {
35971+ struct work_struct wk;
7f207e10 35972+ struct kobject *kobj;
1facf9fc 35973+
35974+ unsigned int flags; /* see wkq.h */
35975+
35976+ au_wkq_func_t func;
35977+ void *args;
35978+
8b6a4947
AM
35979+#ifdef CONFIG_LOCKDEP
35980+ int dont_check;
35981+ struct held_lock **hlock;
35982+#endif
35983+
1facf9fc 35984+ struct completion *comp;
35985+};
35986+
35987+/* ---------------------------------------------------------------------- */
8b6a4947
AM
35988+/*
35989+ * Aufs passes some operations to the workqueue such as the internal copyup.
35990+ * This scheme looks rather unnatural for LOCKDEP debugging feature, since the
35991+ * job run by workqueue depends upon the locks acquired in the other task.
35992+ * Delegating a small operation to the workqueue, aufs passes its lockdep
35993+ * information too. And the job in the workqueue restores the info in order to
35994+ * pretend as if it acquired those locks. This is just to make LOCKDEP work
35995+ * correctly and expectedly.
35996+ */
35997+
35998+#ifndef CONFIG_LOCKDEP
35999+AuStubInt0(au_wkq_lockdep_alloc, struct au_wkinfo *wkinfo);
36000+AuStubVoid(au_wkq_lockdep_free, struct au_wkinfo *wkinfo);
36001+AuStubVoid(au_wkq_lockdep_pre, struct au_wkinfo *wkinfo);
36002+AuStubVoid(au_wkq_lockdep_post, struct au_wkinfo *wkinfo);
36003+AuStubVoid(au_wkq_lockdep_init, struct au_wkinfo *wkinfo);
36004+#else
36005+static void au_wkq_lockdep_init(struct au_wkinfo *wkinfo)
36006+{
36007+ wkinfo->hlock = NULL;
36008+ wkinfo->dont_check = 0;
36009+}
36010+
36011+/*
36012+ * 1: matched
36013+ * 0: unmatched
36014+ */
36015+static int au_wkq_lockdep_test(struct lock_class_key *key, const char *name)
36016+{
36017+ static DEFINE_SPINLOCK(spin);
36018+ static struct {
36019+ char *name;
36020+ struct lock_class_key *key;
36021+ } a[] = {
36022+ { .name = "&sbinfo->si_rwsem" },
36023+ { .name = "&finfo->fi_rwsem" },
36024+ { .name = "&dinfo->di_rwsem" },
36025+ { .name = "&iinfo->ii_rwsem" }
36026+ };
36027+ static int set;
36028+ int i;
36029+
36030+ /* lockless read from 'set.' see below */
36031+ if (set == ARRAY_SIZE(a)) {
36032+ for (i = 0; i < ARRAY_SIZE(a); i++)
36033+ if (a[i].key == key)
36034+ goto match;
36035+ goto unmatch;
36036+ }
36037+
36038+ spin_lock(&spin);
36039+ if (set)
36040+ for (i = 0; i < ARRAY_SIZE(a); i++)
36041+ if (a[i].key == key) {
36042+ spin_unlock(&spin);
36043+ goto match;
36044+ }
36045+ for (i = 0; i < ARRAY_SIZE(a); i++) {
36046+ if (a[i].key) {
36047+ if (unlikely(a[i].key == key)) { /* rare but possible */
36048+ spin_unlock(&spin);
36049+ goto match;
36050+ } else
36051+ continue;
36052+ }
36053+ if (strstr(a[i].name, name)) {
36054+ /*
36055+ * the order of these three lines is important for the
36056+ * lockless read above.
36057+ */
36058+ a[i].key = key;
36059+ spin_unlock(&spin);
36060+ set++;
36061+ /* AuDbg("%d, %s\n", set, name); */
36062+ goto match;
36063+ }
36064+ }
36065+ spin_unlock(&spin);
36066+ goto unmatch;
36067+
36068+match:
36069+ return 1;
36070+unmatch:
36071+ return 0;
36072+}
36073+
36074+static int au_wkq_lockdep_alloc(struct au_wkinfo *wkinfo)
36075+{
36076+ int err, n;
36077+ struct task_struct *curr;
36078+ struct held_lock **hl, *held_locks, *p;
36079+
36080+ err = 0;
36081+ curr = current;
36082+ wkinfo->dont_check = lockdep_recursing(curr);
36083+ if (wkinfo->dont_check)
36084+ goto out;
36085+ n = curr->lockdep_depth;
36086+ if (!n)
36087+ goto out;
36088+
36089+ err = -ENOMEM;
36090+ wkinfo->hlock = kmalloc_array(n + 1, sizeof(*wkinfo->hlock), GFP_NOFS);
36091+ if (unlikely(!wkinfo->hlock))
36092+ goto out;
36093+
36094+ err = 0;
43982f53
AM
36095+#if 0 /* left for debugging */
36096+ if (0 && au_debug_test())
8b6a4947
AM
36097+ lockdep_print_held_locks(curr);
36098+#endif
36099+ held_locks = curr->held_locks;
36100+ hl = wkinfo->hlock;
36101+ while (n--) {
36102+ p = held_locks++;
36103+ if (au_wkq_lockdep_test(p->instance->key, p->instance->name))
36104+ *hl++ = p;
36105+ }
36106+ *hl = NULL;
36107+
36108+out:
36109+ return err;
36110+}
36111+
36112+static void au_wkq_lockdep_free(struct au_wkinfo *wkinfo)
36113+{
9f237c51 36114+ au_kfree_try_rcu(wkinfo->hlock);
8b6a4947
AM
36115+}
36116+
36117+static void au_wkq_lockdep_pre(struct au_wkinfo *wkinfo)
36118+{
36119+ struct held_lock *p, **hl = wkinfo->hlock;
36120+ int subclass;
36121+
36122+ if (wkinfo->dont_check)
36123+ lockdep_off();
36124+ if (!hl)
36125+ return;
36126+ while ((p = *hl++)) { /* assignment */
36127+ subclass = lockdep_hlock_class(p)->subclass;
36128+ /* AuDbg("%s, %d\n", p->instance->name, subclass); */
36129+ if (p->read)
36130+ rwsem_acquire_read(p->instance, subclass, 0,
36131+ /*p->acquire_ip*/_RET_IP_);
36132+ else
36133+ rwsem_acquire(p->instance, subclass, 0,
36134+ /*p->acquire_ip*/_RET_IP_);
36135+ }
36136+}
36137+
36138+static void au_wkq_lockdep_post(struct au_wkinfo *wkinfo)
36139+{
36140+ struct held_lock *p, **hl = wkinfo->hlock;
36141+
36142+ if (wkinfo->dont_check)
36143+ lockdep_on();
36144+ if (!hl)
36145+ return;
36146+ while ((p = *hl++)) /* assignment */
d58c55f2 36147+ rwsem_release(p->instance, /*p->acquire_ip*/_RET_IP_);
8b6a4947
AM
36148+}
36149+#endif
1facf9fc 36150+
1facf9fc 36151+static void wkq_func(struct work_struct *wk)
36152+{
36153+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
36154+
2dfbb274 36155+ AuDebugOn(!uid_eq(current_fsuid(), GLOBAL_ROOT_UID));
7f207e10
AM
36156+ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
36157+
8b6a4947 36158+ au_wkq_lockdep_pre(wkinfo);
1facf9fc 36159+ wkinfo->func(wkinfo->args);
8b6a4947 36160+ au_wkq_lockdep_post(wkinfo);
1facf9fc 36161+ if (au_ftest_wkq(wkinfo->flags, WAIT))
36162+ complete(wkinfo->comp);
36163+ else {
7f207e10 36164+ kobject_put(wkinfo->kobj);
9dbd164d 36165+ module_put(THIS_MODULE); /* todo: ?? */
9f237c51 36166+ au_kfree_rcu(wkinfo);
1facf9fc 36167+ }
36168+}
36169+
36170+/*
36171+ * Since struct completion is large, try allocating it dynamically.
36172+ */
1facf9fc 36173+#define AuWkqCompDeclare(name) struct completion *comp = NULL
36174+
36175+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
36176+{
36177+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
36178+ if (*comp) {
36179+ init_completion(*comp);
36180+ wkinfo->comp = *comp;
36181+ return 0;
36182+ }
36183+ return -ENOMEM;
36184+}
36185+
36186+static void au_wkq_comp_free(struct completion *comp)
36187+{
9f237c51 36188+ au_kfree_rcu(comp);
1facf9fc 36189+}
36190+
53392da6 36191+static void au_wkq_run(struct au_wkinfo *wkinfo)
1facf9fc 36192+{
53392da6
AM
36193+ if (au_ftest_wkq(wkinfo->flags, NEST)) {
36194+ if (au_wkq_test()) {
38d290e6 36195+ AuWarn1("wkq from wkq, unless silly-rename on NFS,"
acd2b654
AM
36196+ " due to a dead dir by UDBA,"
36197+ " or async xino write?\n");
53392da6
AM
36198+ AuDebugOn(au_ftest_wkq(wkinfo->flags, WAIT));
36199+ }
36200+ } else
36201+ au_dbg_verify_kthread();
36202+
36203+ if (au_ftest_wkq(wkinfo->flags, WAIT)) {
a1f66529 36204+ INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func);
9dbd164d 36205+ queue_work(au_wkq, &wkinfo->wk);
4a4d8108
AM
36206+ } else {
36207+ INIT_WORK(&wkinfo->wk, wkq_func);
36208+ schedule_work(&wkinfo->wk);
36209+ }
1facf9fc 36210+}
36211+
7f207e10
AM
36212+/*
36213+ * Be careful. It is easy to make deadlock happen.
36214+ * processA: lock, wkq and wait
36215+ * processB: wkq and wait, lock in wkq
36216+ * --> deadlock
36217+ */
b752ccd1 36218+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
1facf9fc 36219+{
36220+ int err;
36221+ AuWkqCompDeclare(comp);
36222+ struct au_wkinfo wkinfo = {
b752ccd1 36223+ .flags = flags,
1facf9fc 36224+ .func = func,
36225+ .args = args
36226+ };
36227+
36228+ err = au_wkq_comp_alloc(&wkinfo, &comp);
8b6a4947
AM
36229+ if (unlikely(err))
36230+ goto out;
36231+ err = au_wkq_lockdep_alloc(&wkinfo);
36232+ if (unlikely(err))
36233+ goto out_comp;
1facf9fc 36234+ if (!err) {
53392da6 36235+ au_wkq_run(&wkinfo);
1facf9fc 36236+ /* no timeout, no interrupt */
36237+ wait_for_completion(wkinfo.comp);
1facf9fc 36238+ }
8b6a4947 36239+ au_wkq_lockdep_free(&wkinfo);
1facf9fc 36240+
8b6a4947
AM
36241+out_comp:
36242+ au_wkq_comp_free(comp);
36243+out:
36244+ destroy_work_on_stack(&wkinfo.wk);
1facf9fc 36245+ return err;
1facf9fc 36246+}
36247+
027c5e7a
AM
36248+/*
36249+ * Note: dget/dput() in func for aufs dentries are not supported. It will be a
36250+ * problem in a concurrent umounting.
36251+ */
53392da6
AM
36252+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
36253+ unsigned int flags)
1facf9fc 36254+{
36255+ int err;
36256+ struct au_wkinfo *wkinfo;
36257+
f0c0a007 36258+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
1facf9fc 36259+
36260+ /*
36261+ * wkq_func() must free this wkinfo.
36262+ * it highly depends upon the implementation of workqueue.
36263+ */
36264+ err = 0;
36265+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
36266+ if (wkinfo) {
7f207e10 36267+ wkinfo->kobj = &au_sbi(sb)->si_kobj;
53392da6 36268+ wkinfo->flags = flags & ~AuWkq_WAIT;
1facf9fc 36269+ wkinfo->func = func;
36270+ wkinfo->args = args;
36271+ wkinfo->comp = NULL;
8b6a4947 36272+ au_wkq_lockdep_init(wkinfo);
7f207e10 36273+ kobject_get(wkinfo->kobj);
9dbd164d 36274+ __module_get(THIS_MODULE); /* todo: ?? */
1facf9fc 36275+
53392da6 36276+ au_wkq_run(wkinfo);
1facf9fc 36277+ } else {
36278+ err = -ENOMEM;
e49829fe 36279+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 36280+ }
36281+
36282+ return err;
36283+}
36284+
36285+/* ---------------------------------------------------------------------- */
36286+
36287+void au_nwt_init(struct au_nowait_tasks *nwt)
36288+{
f0c0a007
AM
36289+ atomic_set(&nwt->nw_len, 0);
36290+ /* smp_mb(); */ /* atomic_set */
1facf9fc 36291+ init_waitqueue_head(&nwt->nw_wq);
36292+}
36293+
36294+void au_wkq_fin(void)
36295+{
9dbd164d 36296+ destroy_workqueue(au_wkq);
1facf9fc 36297+}
36298+
36299+int __init au_wkq_init(void)
36300+{
9dbd164d 36301+ int err;
b752ccd1
AM
36302+
36303+ err = 0;
86dc4139 36304+ au_wkq = alloc_workqueue(AUFS_WKQ_NAME, 0, WQ_DFL_ACTIVE);
9dbd164d
AM
36305+ if (IS_ERR(au_wkq))
36306+ err = PTR_ERR(au_wkq);
36307+ else if (!au_wkq)
36308+ err = -ENOMEM;
b752ccd1
AM
36309+
36310+ return err;
1facf9fc 36311+}
7f207e10 36312diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
eca34b5c 36313--- /usr/share/empty/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 36314+++ linux/fs/aufs/wkq.h 2021-05-02 20:15:14.676670793 +0200
acd2b654 36315@@ -0,0 +1,89 @@
062440b3 36316+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 36317+/*
d58c55f2 36318+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 36319+ *
36320+ * This program, aufs is free software; you can redistribute it and/or modify
36321+ * it under the terms of the GNU General Public License as published by
36322+ * the Free Software Foundation; either version 2 of the License, or
36323+ * (at your option) any later version.
dece6358
AM
36324+ *
36325+ * This program is distributed in the hope that it will be useful,
36326+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36327+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36328+ * GNU General Public License for more details.
36329+ *
36330+ * You should have received a copy of the GNU General Public License
523b37e3 36331+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 36332+ */
36333+
36334+/*
36335+ * workqueue for asynchronous/super-io operations
36336+ * todo: try new credentials management scheme
36337+ */
36338+
36339+#ifndef __AUFS_WKQ_H__
36340+#define __AUFS_WKQ_H__
36341+
36342+#ifdef __KERNEL__
36343+
8b6a4947 36344+#include <linux/wait.h>
5afbbe0d 36345+
dece6358
AM
36346+struct super_block;
36347+
1facf9fc 36348+/* ---------------------------------------------------------------------- */
36349+
36350+/*
36351+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
36352+ */
36353+struct au_nowait_tasks {
f0c0a007 36354+ atomic_t nw_len;
1facf9fc 36355+ wait_queue_head_t nw_wq;
36356+};
36357+
36358+/* ---------------------------------------------------------------------- */
36359+
36360+typedef void (*au_wkq_func_t)(void *args);
36361+
36362+/* wkq flags */
36363+#define AuWkq_WAIT 1
9dbd164d 36364+#define AuWkq_NEST (1 << 1)
1facf9fc 36365+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
7f207e10
AM
36366+#define au_fset_wkq(flags, name) \
36367+ do { (flags) |= AuWkq_##name; } while (0)
36368+#define au_fclr_wkq(flags, name) \
36369+ do { (flags) &= ~AuWkq_##name; } while (0)
1facf9fc 36370+
36371+/* wkq.c */
b752ccd1 36372+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
53392da6
AM
36373+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
36374+ unsigned int flags);
1facf9fc 36375+void au_nwt_init(struct au_nowait_tasks *nwt);
36376+int __init au_wkq_init(void);
36377+void au_wkq_fin(void);
36378+
36379+/* ---------------------------------------------------------------------- */
36380+
53392da6
AM
36381+static inline int au_wkq_test(void)
36382+{
36383+ return current->flags & PF_WQ_WORKER;
36384+}
36385+
b752ccd1 36386+static inline int au_wkq_wait(au_wkq_func_t func, void *args)
1facf9fc 36387+{
b752ccd1 36388+ return au_wkq_do_wait(AuWkq_WAIT, func, args);
1facf9fc 36389+}
36390+
36391+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
36392+{
f0c0a007 36393+ if (atomic_dec_and_test(&nwt->nw_len))
1facf9fc 36394+ wake_up_all(&nwt->nw_wq);
36395+}
36396+
36397+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
36398+{
f0c0a007 36399+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
1facf9fc 36400+ return 0;
36401+}
36402+
36403+#endif /* __KERNEL__ */
36404+#endif /* __AUFS_WKQ_H__ */
c1595e42 36405diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c
eca34b5c 36406--- /usr/share/empty/fs/aufs/xattr.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6
JR
36407+++ linux/fs/aufs/xattr.c 2021-05-02 20:15:14.676670793 +0200
36408@@ -0,0 +1,368 @@
cd7a4cd9 36409+// SPDX-License-Identifier: GPL-2.0
c1595e42 36410+/*
d58c55f2 36411+ * Copyright (C) 2014-2020 Junjiro R. Okajima
c1595e42
JR
36412+ *
36413+ * This program, aufs is free software; you can redistribute it and/or modify
36414+ * it under the terms of the GNU General Public License as published by
36415+ * the Free Software Foundation; either version 2 of the License, or
36416+ * (at your option) any later version.
36417+ *
36418+ * This program is distributed in the hope that it will be useful,
36419+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36420+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36421+ * GNU General Public License for more details.
36422+ *
36423+ * You should have received a copy of the GNU General Public License
36424+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
36425+ */
36426+
36427+/*
36428+ * handling xattr functions
36429+ */
36430+
a2654f78
AM
36431+#include <linux/fs.h>
36432+#include <linux/posix_acl_xattr.h>
c1595e42
JR
36433+#include <linux/xattr.h>
36434+#include "aufs.h"
36435+
36436+static int au_xattr_ignore(int err, char *name, unsigned int ignore_flags)
36437+{
36438+ if (!ignore_flags)
36439+ goto out;
36440+ switch (err) {
36441+ case -ENOMEM:
36442+ case -EDQUOT:
36443+ goto out;
36444+ }
36445+
36446+ if ((ignore_flags & AuBrAttr_ICEX) == AuBrAttr_ICEX) {
36447+ err = 0;
36448+ goto out;
36449+ }
36450+
36451+#define cmp(brattr, prefix) do { \
36452+ if (!strncmp(name, XATTR_##prefix##_PREFIX, \
36453+ XATTR_##prefix##_PREFIX_LEN)) { \
36454+ if (ignore_flags & AuBrAttr_ICEX_##brattr) \
36455+ err = 0; \
36456+ goto out; \
36457+ } \
36458+ } while (0)
36459+
36460+ cmp(SEC, SECURITY);
36461+ cmp(SYS, SYSTEM);
36462+ cmp(TR, TRUSTED);
36463+ cmp(USR, USER);
36464+#undef cmp
36465+
36466+ if (ignore_flags & AuBrAttr_ICEX_OTH)
36467+ err = 0;
36468+
36469+out:
36470+ return err;
36471+}
36472+
36473+static const int au_xattr_out_of_list = AuBrAttr_ICEX_OTH << 1;
36474+
0b2a12c6 36475+static int au_do_cpup_xattr(struct path *h_dst, struct path *h_src,
7e9cd9fe
AM
36476+ char *name, char **buf, unsigned int ignore_flags,
36477+ unsigned int verbose)
c1595e42
JR
36478+{
36479+ int err;
36480+ ssize_t ssz;
36481+ struct inode *h_idst;
0b2a12c6
JR
36482+ struct dentry *h_dst_dentry, *h_src_dentry;
36483+ struct user_namespace *h_dst_userns, *h_src_userns;
c1595e42 36484+
0b2a12c6
JR
36485+ h_src_userns = mnt_user_ns(h_src->mnt);
36486+ h_src_dentry = h_src->dentry;
36487+ ssz = vfs_getxattr_alloc(h_src_userns, h_src_dentry, name, buf, 0,
36488+ GFP_NOFS);
c1595e42
JR
36489+ err = ssz;
36490+ if (unlikely(err <= 0)) {
c1595e42
JR
36491+ if (err == -ENODATA
36492+ || (err == -EOPNOTSUPP
b912730e 36493+ && ((ignore_flags & au_xattr_out_of_list)
0b2a12c6 36494+ || (au_test_nfs_noacl(d_inode(h_src_dentry))
b912730e
AM
36495+ && (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS)
36496+ || !strcmp(name,
36497+ XATTR_NAME_POSIX_ACL_DEFAULT))))
36498+ ))
c1595e42 36499+ err = 0;
b912730e
AM
36500+ if (err && (verbose || au_debug_test()))
36501+ pr_err("%s, err %d\n", name, err);
c1595e42
JR
36502+ goto out;
36503+ }
36504+
36505+ /* unlock it temporary */
0b2a12c6
JR
36506+ h_dst_userns = mnt_user_ns(h_dst->mnt);
36507+ h_dst_dentry = h_dst->dentry;
36508+ h_idst = d_inode(h_dst_dentry);
febd17d6 36509+ inode_unlock(h_idst);
0b2a12c6
JR
36510+ err = vfsub_setxattr(h_dst_userns, h_dst_dentry, name, *buf, ssz,
36511+ /*flags*/0);
febd17d6 36512+ inode_lock_nested(h_idst, AuLsc_I_CHILD2);
c1595e42 36513+ if (unlikely(err)) {
7e9cd9fe
AM
36514+ if (verbose || au_debug_test())
36515+ pr_err("%s, err %d\n", name, err);
c1595e42
JR
36516+ err = au_xattr_ignore(err, name, ignore_flags);
36517+ }
36518+
36519+out:
36520+ return err;
36521+}
36522+
0b2a12c6 36523+int au_cpup_xattr(struct path *h_dst, struct path *h_src, int ignore_flags,
7e9cd9fe 36524+ unsigned int verbose)
c1595e42
JR
36525+{
36526+ int err, unlocked, acl_access, acl_default;
36527+ ssize_t ssz;
0b2a12c6 36528+ struct dentry *h_dst_dentry, *h_src_dentry;
c1595e42
JR
36529+ struct inode *h_isrc, *h_idst;
36530+ char *value, *p, *o, *e;
36531+
36532+ /* try stopping to update the source inode while we are referencing */
7e9cd9fe 36533+ /* there should not be the parent-child relationship between them */
0b2a12c6
JR
36534+ h_dst_dentry = h_dst->dentry;
36535+ h_idst = d_inode(h_dst_dentry);
36536+ h_src_dentry = h_src->dentry;
36537+ h_isrc = d_inode(h_src_dentry);
febd17d6 36538+ inode_unlock(h_idst);
be118d29 36539+ inode_lock_shared_nested(h_isrc, AuLsc_I_CHILD);
febd17d6 36540+ inode_lock_nested(h_idst, AuLsc_I_CHILD2);
c1595e42
JR
36541+ unlocked = 0;
36542+
36543+ /* some filesystems don't list POSIX ACL, for example tmpfs */
0b2a12c6 36544+ ssz = vfs_listxattr(h_src_dentry, NULL, 0);
c1595e42
JR
36545+ err = ssz;
36546+ if (unlikely(err < 0)) {
36547+ AuTraceErr(err);
36548+ if (err == -ENODATA
36549+ || err == -EOPNOTSUPP)
36550+ err = 0; /* ignore */
36551+ goto out;
36552+ }
36553+
36554+ err = 0;
36555+ p = NULL;
36556+ o = NULL;
36557+ if (ssz) {
36558+ err = -ENOMEM;
36559+ p = kmalloc(ssz, GFP_NOFS);
36560+ o = p;
36561+ if (unlikely(!p))
36562+ goto out;
0b2a12c6 36563+ err = vfs_listxattr(h_src_dentry, p, ssz);
c1595e42 36564+ }
3c1bdaff 36565+ inode_unlock_shared(h_isrc);
c1595e42
JR
36566+ unlocked = 1;
36567+ AuDbg("err %d, ssz %zd\n", err, ssz);
36568+ if (unlikely(err < 0))
36569+ goto out_free;
36570+
36571+ err = 0;
36572+ e = p + ssz;
36573+ value = NULL;
36574+ acl_access = 0;
36575+ acl_default = 0;
36576+ while (!err && p < e) {
36577+ acl_access |= !strncmp(p, XATTR_NAME_POSIX_ACL_ACCESS,
36578+ sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1);
36579+ acl_default |= !strncmp(p, XATTR_NAME_POSIX_ACL_DEFAULT,
36580+ sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)
36581+ - 1);
7e9cd9fe
AM
36582+ err = au_do_cpup_xattr(h_dst, h_src, p, &value, ignore_flags,
36583+ verbose);
c1595e42
JR
36584+ p += strlen(p) + 1;
36585+ }
36586+ AuTraceErr(err);
36587+ ignore_flags |= au_xattr_out_of_list;
36588+ if (!err && !acl_access) {
36589+ err = au_do_cpup_xattr(h_dst, h_src,
36590+ XATTR_NAME_POSIX_ACL_ACCESS, &value,
7e9cd9fe 36591+ ignore_flags, verbose);
c1595e42
JR
36592+ AuTraceErr(err);
36593+ }
36594+ if (!err && !acl_default) {
36595+ err = au_do_cpup_xattr(h_dst, h_src,
36596+ XATTR_NAME_POSIX_ACL_DEFAULT, &value,
7e9cd9fe 36597+ ignore_flags, verbose);
c1595e42
JR
36598+ AuTraceErr(err);
36599+ }
36600+
9f237c51 36601+ au_kfree_try_rcu(value);
c1595e42
JR
36602+
36603+out_free:
9f237c51 36604+ au_kfree_try_rcu(o);
c1595e42
JR
36605+out:
36606+ if (!unlocked)
3c1bdaff 36607+ inode_unlock_shared(h_isrc);
c1595e42
JR
36608+ AuTraceErr(err);
36609+ return err;
36610+}
36611+
36612+/* ---------------------------------------------------------------------- */
36613+
a2654f78
AM
36614+static int au_smack_reentering(struct super_block *sb)
36615+{
42b5c33a 36616+#if IS_ENABLED(CONFIG_SECURITY_SMACK) || IS_ENABLED(CONFIG_SECURITY_SELINUX)
a2654f78
AM
36617+ /*
36618+ * as a part of lookup, smack_d_instantiate() is called, and it calls
36619+ * i_op->getxattr(). ouch.
36620+ */
36621+ return si_pid_test(sb);
36622+#else
36623+ return 0;
36624+#endif
36625+}
36626+
c1595e42
JR
36627+enum {
36628+ AU_XATTR_LIST,
36629+ AU_XATTR_GET
36630+};
36631+
36632+struct au_lgxattr {
36633+ int type;
36634+ union {
36635+ struct {
36636+ char *list;
36637+ size_t size;
36638+ } list;
36639+ struct {
36640+ const char *name;
36641+ void *value;
36642+ size_t size;
36643+ } get;
36644+ } u;
36645+};
36646+
42b5c33a
AM
36647+static ssize_t au_lgxattr(struct dentry *dentry, struct inode *inode,
36648+ struct au_lgxattr *arg)
c1595e42
JR
36649+{
36650+ ssize_t err;
a2654f78 36651+ int reenter;
c1595e42
JR
36652+ struct path h_path;
36653+ struct super_block *sb;
36654+
36655+ sb = dentry->d_sb;
a2654f78
AM
36656+ reenter = au_smack_reentering(sb);
36657+ if (!reenter) {
36658+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
36659+ if (unlikely(err))
36660+ goto out;
36661+ }
42b5c33a 36662+ err = au_h_path_getattr(dentry, inode, /*force*/1, &h_path, reenter);
c1595e42
JR
36663+ if (unlikely(err))
36664+ goto out_si;
36665+ if (unlikely(!h_path.dentry))
36666+ /* illegally overlapped or something */
36667+ goto out_di; /* pretending success */
36668+
36669+ /* always topmost entry only */
36670+ switch (arg->type) {
36671+ case AU_XATTR_LIST:
36672+ err = vfs_listxattr(h_path.dentry,
36673+ arg->u.list.list, arg->u.list.size);
36674+ break;
36675+ case AU_XATTR_GET:
5afbbe0d 36676+ AuDebugOn(d_is_negative(h_path.dentry));
0b2a12c6 36677+ err = vfs_getxattr(mnt_user_ns(h_path.mnt), h_path.dentry,
c1595e42
JR
36678+ arg->u.get.name, arg->u.get.value,
36679+ arg->u.get.size);
36680+ break;
36681+ }
36682+
36683+out_di:
a2654f78
AM
36684+ if (!reenter)
36685+ di_read_unlock(dentry, AuLock_IR);
c1595e42 36686+out_si:
a2654f78
AM
36687+ if (!reenter)
36688+ si_read_unlock(sb);
c1595e42
JR
36689+out:
36690+ AuTraceErr(err);
36691+ return err;
36692+}
36693+
36694+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size)
36695+{
36696+ struct au_lgxattr arg = {
36697+ .type = AU_XATTR_LIST,
36698+ .u.list = {
36699+ .list = list,
36700+ .size = size
36701+ },
36702+ };
36703+
42b5c33a 36704+ return au_lgxattr(dentry, /*inode*/NULL, &arg);
c1595e42
JR
36705+}
36706+
42b5c33a 36707+static ssize_t au_getxattr(struct dentry *dentry, struct inode *inode,
f2c43d5f 36708+ const char *name, void *value, size_t size)
c1595e42
JR
36709+{
36710+ struct au_lgxattr arg = {
36711+ .type = AU_XATTR_GET,
36712+ .u.get = {
36713+ .name = name,
36714+ .value = value,
36715+ .size = size
36716+ },
36717+ };
36718+
42b5c33a 36719+ return au_lgxattr(dentry, inode, &arg);
c1595e42
JR
36720+}
36721+
f2c43d5f
AM
36722+static int au_setxattr(struct dentry *dentry, struct inode *inode,
36723+ const char *name, const void *value, size_t size,
36724+ int flags)
c1595e42 36725+{
f2c43d5f 36726+ struct au_sxattr arg = {
c1595e42
JR
36727+ .type = AU_XATTR_SET,
36728+ .u.set = {
36729+ .name = name,
36730+ .value = value,
36731+ .size = size,
36732+ .flags = flags
36733+ },
36734+ };
36735+
f2c43d5f 36736+ return au_sxattr(dentry, inode, &arg);
c1595e42
JR
36737+}
36738+
36739+/* ---------------------------------------------------------------------- */
36740+
f2c43d5f
AM
36741+static int au_xattr_get(const struct xattr_handler *handler,
36742+ struct dentry *dentry, struct inode *inode,
36743+ const char *name, void *buffer, size_t size)
c1595e42 36744+{
f2c43d5f 36745+ return au_getxattr(dentry, inode, name, buffer, size);
c1595e42
JR
36746+}
36747+
f2c43d5f 36748+static int au_xattr_set(const struct xattr_handler *handler,
0b2a12c6 36749+ struct user_namespace *userns,
f2c43d5f
AM
36750+ struct dentry *dentry, struct inode *inode,
36751+ const char *name, const void *value, size_t size,
36752+ int flags)
c1595e42 36753+{
f2c43d5f 36754+ return au_setxattr(dentry, inode, name, value, size, flags);
c1595e42
JR
36755+}
36756+
36757+static const struct xattr_handler au_xattr_handler = {
f2c43d5f
AM
36758+ .name = "",
36759+ .prefix = "",
c1595e42
JR
36760+ .get = au_xattr_get,
36761+ .set = au_xattr_set
c1595e42
JR
36762+};
36763+
36764+static const struct xattr_handler *au_xattr_handlers[] = {
a2654f78
AM
36765+#ifdef CONFIG_FS_POSIX_ACL
36766+ &posix_acl_access_xattr_handler,
36767+ &posix_acl_default_xattr_handler,
36768+#endif
36769+ &au_xattr_handler, /* must be last */
f2c43d5f 36770+ NULL
c1595e42
JR
36771+};
36772+
36773+void au_xattr_init(struct super_block *sb)
36774+{
f2c43d5f 36775+ sb->s_xattr = au_xattr_handlers;
c1595e42 36776+}
7f207e10 36777diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
eca34b5c 36778--- /usr/share/empty/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 36779+++ linux/fs/aufs/xino.c 2021-05-02 20:15:14.676670793 +0200
e37dd06a 36780@@ -0,0 +1,1925 @@
cd7a4cd9 36781+// SPDX-License-Identifier: GPL-2.0
1facf9fc 36782+/*
d58c55f2 36783+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 36784+ *
36785+ * This program, aufs is free software; you can redistribute it and/or modify
36786+ * it under the terms of the GNU General Public License as published by
36787+ * the Free Software Foundation; either version 2 of the License, or
36788+ * (at your option) any later version.
dece6358
AM
36789+ *
36790+ * This program is distributed in the hope that it will be useful,
36791+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36792+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36793+ * GNU General Public License for more details.
36794+ *
36795+ * You should have received a copy of the GNU General Public License
523b37e3 36796+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 36797+ */
36798+
36799+/*
36800+ * external inode number translation table and bitmap
062440b3
AM
36801+ *
36802+ * things to consider
36803+ * - the lifetime
36804+ * + au_xino object
36805+ * + XINO files (xino, xib, xigen)
36806+ * + dynamic debugfs entries (xiN)
36807+ * + static debugfs entries (xib, xigen)
36808+ * + static sysfs entry (xi_path)
36809+ * - several entry points to handle them.
36810+ * + mount(2) without xino option (default)
36811+ * + mount(2) with xino option
36812+ * + mount(2) with noxino option
36813+ * + umount(2)
36814+ * + remount with add/del branches
36815+ * + remount with xino/noxino options
1facf9fc 36816+ */
36817+
36818+#include <linux/seq_file.h>
392086de 36819+#include <linux/statfs.h>
1facf9fc 36820+#include "aufs.h"
36821+
062440b3
AM
36822+static aufs_bindex_t sbr_find_shared(struct super_block *sb, aufs_bindex_t btop,
36823+ aufs_bindex_t bbot,
36824+ struct super_block *h_sb)
1facf9fc 36825+{
062440b3
AM
36826+ /* todo: try binary-search if the branches are many */
36827+ for (; btop <= bbot; btop++)
36828+ if (h_sb == au_sbr_sb(sb, btop))
36829+ return btop;
36830+ return -1;
be52b249
AM
36831+}
36832+
062440b3
AM
36833+/*
36834+ * find another branch who is on the same filesystem of the specified
36835+ * branch{@btgt}. search until @bbot.
36836+ */
36837+static aufs_bindex_t is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
36838+ aufs_bindex_t bbot)
1facf9fc 36839+{
062440b3
AM
36840+ aufs_bindex_t bindex;
36841+ struct super_block *tgt_sb;
1facf9fc 36842+
062440b3
AM
36843+ tgt_sb = au_sbr_sb(sb, btgt);
36844+ bindex = sbr_find_shared(sb, /*btop*/0, btgt - 1, tgt_sb);
36845+ if (bindex < 0)
36846+ bindex = sbr_find_shared(sb, btgt + 1, bbot, tgt_sb);
1facf9fc 36847+
062440b3 36848+ return bindex;
1facf9fc 36849+}
36850+
36851+/* ---------------------------------------------------------------------- */
36852+
36853+/*
062440b3 36854+ * stop unnecessary notify events at creating xino files
1facf9fc 36855+ */
acd2b654
AM
36856+
36857+aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry)
36858+{
36859+ aufs_bindex_t bfound, bindex, bbot;
36860+ struct dentry *parent;
36861+ struct au_branch *br;
36862+
36863+ bfound = -1;
36864+ parent = dentry->d_parent; /* safe d_parent access */
36865+ bbot = au_sbbot(sb);
36866+ for (bindex = 0; bindex <= bbot; bindex++) {
36867+ br = au_sbr(sb, bindex);
36868+ if (au_br_dentry(br) == parent) {
36869+ bfound = bindex;
36870+ break;
36871+ }
36872+ }
36873+
36874+ AuDbg("bfound b%d\n", bfound);
36875+ return bfound;
36876+}
36877+
062440b3
AM
36878+struct au_xino_lock_dir {
36879+ struct au_hinode *hdir;
36880+ struct dentry *parent;
36881+ struct inode *dir;
36882+};
36883+
36884+static struct dentry *au_dget_parent_lock(struct dentry *dentry,
36885+ unsigned int lsc)
1facf9fc 36886+{
062440b3
AM
36887+ struct dentry *parent;
36888+ struct inode *dir;
1facf9fc 36889+
062440b3 36890+ parent = dget_parent(dentry);
5527c038 36891+ dir = d_inode(parent);
062440b3
AM
36892+ inode_lock_nested(dir, lsc);
36893+#if 0 /* it should not happen */
36894+ spin_lock(&dentry->d_lock);
36895+ if (unlikely(dentry->d_parent != parent)) {
36896+ spin_unlock(&dentry->d_lock);
36897+ inode_unlock(dir);
36898+ dput(parent);
36899+ parent = NULL;
1facf9fc 36900+ goto out;
36901+ }
062440b3 36902+ spin_unlock(&dentry->d_lock);
1facf9fc 36903+
4f0767ce 36904+out:
062440b3
AM
36905+#endif
36906+ return parent;
1facf9fc 36907+}
36908+
062440b3 36909+static void au_xino_lock_dir(struct super_block *sb, struct path *xipath,
1facf9fc 36910+ struct au_xino_lock_dir *ldir)
36911+{
acd2b654 36912+ aufs_bindex_t bindex;
1facf9fc 36913+
36914+ ldir->hdir = NULL;
acd2b654 36915+ bindex = au_xi_root(sb, xipath->dentry);
1facf9fc 36916+ if (bindex >= 0) {
062440b3 36917+ /* rw branch root */
5527c038 36918+ ldir->hdir = au_hi(d_inode(sb->s_root), bindex);
5afbbe0d 36919+ au_hn_inode_lock_nested(ldir->hdir, AuLsc_I_PARENT);
1facf9fc 36920+ } else {
062440b3
AM
36921+ /* other */
36922+ ldir->parent = au_dget_parent_lock(xipath->dentry,
36923+ AuLsc_I_PARENT);
febd17d6 36924+ ldir->dir = d_inode(ldir->parent);
1facf9fc 36925+ }
36926+}
36927+
36928+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
36929+{
36930+ if (ldir->hdir)
5afbbe0d 36931+ au_hn_inode_unlock(ldir->hdir);
1facf9fc 36932+ else {
febd17d6 36933+ inode_unlock(ldir->dir);
1facf9fc 36934+ dput(ldir->parent);
36935+ }
36936+}
36937+
36938+/* ---------------------------------------------------------------------- */
36939+
062440b3
AM
36940+/*
36941+ * create and set a new xino file
36942+ */
83b672a5
AM
36943+struct file *au_xino_create(struct super_block *sb, char *fpath, int silent,
36944+ int wbrtop)
062440b3
AM
36945+{
36946+ struct file *file;
36947+ struct dentry *h_parent, *d;
36948+ struct inode *h_dir, *inode;
36949+ int err;
83b672a5 36950+ static DEFINE_MUTEX(mtx);
062440b3
AM
36951+
36952+ /*
36953+ * at mount-time, and the xino file is the default path,
36954+ * hnotify is disabled so we have no notify events to ignore.
36955+ * when a user specified the xino, we cannot get au_hdir to be ignored.
36956+ */
83b672a5
AM
36957+ if (!wbrtop)
36958+ mutex_lock(&mtx);
062440b3
AM
36959+ file = vfsub_filp_open(fpath, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
36960+ /* | __FMODE_NONOTIFY */,
cd7a4cd9 36961+ 0666);
062440b3 36962+ if (IS_ERR(file)) {
83b672a5
AM
36963+ if (!wbrtop)
36964+ mutex_unlock(&mtx);
062440b3
AM
36965+ if (!silent)
36966+ pr_err("open %s(%ld)\n", fpath, PTR_ERR(file));
36967+ return file;
36968+ }
36969+
36970+ /* keep file count */
36971+ err = 0;
36972+ d = file->f_path.dentry;
36973+ h_parent = au_dget_parent_lock(d, AuLsc_I_PARENT);
83b672a5
AM
36974+ if (!wbrtop)
36975+ mutex_unlock(&mtx);
062440b3
AM
36976+ /* mnt_want_write() is unnecessary here */
36977+ h_dir = d_inode(h_parent);
36978+ inode = file_inode(file);
36979+ /* no delegation since it is just created */
36980+ if (inode->i_nlink)
36981+ err = vfsub_unlink(h_dir, &file->f_path, /*delegated*/NULL,
36982+ /*force*/0);
36983+ inode_unlock(h_dir);
36984+ dput(h_parent);
36985+ if (unlikely(err)) {
36986+ if (!silent)
36987+ pr_err("unlink %s(%d)\n", fpath, err);
36988+ goto out;
36989+ }
36990+
36991+ err = -EINVAL;
36992+ if (unlikely(sb == d->d_sb)) {
36993+ if (!silent)
36994+ pr_err("%s must be outside\n", fpath);
36995+ goto out;
36996+ }
36997+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
36998+ if (!silent)
36999+ pr_err("xino doesn't support %s(%s)\n",
37000+ fpath, au_sbtype(d->d_sb));
37001+ goto out;
37002+ }
37003+ return file; /* success */
37004+
37005+out:
37006+ fput(file);
37007+ file = ERR_PTR(err);
37008+ return file;
37009+}
37010+
37011+/*
37012+ * create a new xinofile at the same place/path as @base.
37013+ */
37014+struct file *au_xino_create2(struct super_block *sb, struct path *base,
37015+ struct file *copy_src)
37016+{
37017+ struct file *file;
37018+ struct dentry *dentry, *parent;
37019+ struct inode *dir, *delegated;
37020+ struct qstr *name;
37021+ struct path path;
37022+ int err, do_unlock;
37023+ struct au_xino_lock_dir ldir;
37024+
37025+ do_unlock = 1;
37026+ au_xino_lock_dir(sb, base, &ldir);
37027+ dentry = base->dentry;
37028+ parent = dentry->d_parent; /* dir inode is locked */
37029+ dir = d_inode(parent);
37030+ IMustLock(dir);
37031+
37032+ name = &dentry->d_name;
37033+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
37034+ if (IS_ERR(path.dentry)) {
37035+ file = (void *)path.dentry;
37036+ pr_err("%pd lookup err %ld\n", dentry, PTR_ERR(path.dentry));
37037+ goto out;
37038+ }
37039+
37040+ /* no need to mnt_want_write() since we call dentry_open() later */
0b2a12c6 37041+ err = vfs_create(mnt_user_ns(base->mnt), dir, path.dentry, 0666, NULL);
062440b3
AM
37042+ if (unlikely(err)) {
37043+ file = ERR_PTR(err);
37044+ pr_err("%pd create err %d\n", dentry, err);
37045+ goto out_dput;
37046+ }
37047+
37048+ path.mnt = base->mnt;
37049+ file = vfsub_dentry_open(&path,
37050+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
37051+ /* | __FMODE_NONOTIFY */);
37052+ if (IS_ERR(file)) {
37053+ pr_err("%pd open err %ld\n", dentry, PTR_ERR(file));
37054+ goto out_dput;
37055+ }
37056+
37057+ delegated = NULL;
37058+ err = vfsub_unlink(dir, &file->f_path, &delegated, /*force*/0);
37059+ au_xino_unlock_dir(&ldir);
37060+ do_unlock = 0;
37061+ if (unlikely(err == -EWOULDBLOCK)) {
37062+ pr_warn("cannot retry for NFSv4 delegation"
37063+ " for an internal unlink\n");
37064+ iput(delegated);
37065+ }
37066+ if (unlikely(err)) {
37067+ pr_err("%pd unlink err %d\n", dentry, err);
37068+ goto out_fput;
37069+ }
37070+
37071+ if (copy_src) {
37072+ /* no one can touch copy_src xino */
37073+ err = au_copy_file(file, copy_src, vfsub_f_size_read(copy_src));
37074+ if (unlikely(err)) {
37075+ pr_err("%pd copy err %d\n", dentry, err);
37076+ goto out_fput;
37077+ }
37078+ }
37079+ goto out_dput; /* success */
1facf9fc 37080+
062440b3
AM
37081+out_fput:
37082+ fput(file);
37083+ file = ERR_PTR(err);
37084+out_dput:
37085+ dput(path.dentry);
37086+out:
37087+ if (do_unlock)
37088+ au_xino_unlock_dir(&ldir);
37089+ return file;
37090+}
37091+
acd2b654
AM
37092+struct file *au_xino_file1(struct au_xino *xi)
37093+{
37094+ struct file *file;
37095+ unsigned int u, nfile;
37096+
37097+ file = NULL;
37098+ nfile = xi->xi_nfile;
37099+ for (u = 0; u < nfile; u++) {
37100+ file = xi->xi_file[u];
37101+ if (file)
37102+ break;
37103+ }
37104+
37105+ return file;
37106+}
37107+
37108+static int au_xino_file_set(struct au_xino *xi, int idx, struct file *file)
37109+{
37110+ int err;
37111+ struct file *f;
37112+ void *p;
37113+
37114+ if (file)
37115+ get_file(file);
37116+
37117+ err = 0;
37118+ f = NULL;
37119+ if (idx < xi->xi_nfile) {
37120+ f = xi->xi_file[idx];
37121+ if (f)
37122+ fput(f);
37123+ } else {
37124+ p = au_kzrealloc(xi->xi_file,
37125+ sizeof(*xi->xi_file) * xi->xi_nfile,
37126+ sizeof(*xi->xi_file) * (idx + 1),
37127+ GFP_NOFS, /*may_shrink*/0);
37128+ if (p) {
37129+ MtxMustLock(&xi->xi_mtx);
37130+ xi->xi_file = p;
37131+ xi->xi_nfile = idx + 1;
37132+ } else {
37133+ err = -ENOMEM;
37134+ if (file)
37135+ fput(file);
37136+ goto out;
37137+ }
37138+ }
37139+ xi->xi_file[idx] = file;
37140+
37141+out:
37142+ return err;
37143+}
37144+
37145+/*
37146+ * if @xinew->xi is not set, then create new xigen file.
37147+ */
37148+struct file *au_xi_new(struct super_block *sb, struct au_xi_new *xinew)
37149+{
37150+ struct file *file;
37151+ int err;
37152+
37153+ SiMustAnyLock(sb);
37154+
37155+ file = au_xino_create2(sb, xinew->base, xinew->copy_src);
37156+ if (IS_ERR(file)) {
37157+ err = PTR_ERR(file);
37158+ pr_err("%s[%d], err %d\n",
37159+ xinew->xi ? "xino" : "xigen",
37160+ xinew->idx, err);
37161+ goto out;
37162+ }
37163+
37164+ if (xinew->xi)
37165+ err = au_xino_file_set(xinew->xi, xinew->idx, file);
37166+ else {
37167+ BUG();
37168+ /* todo: make xigen file an array */
37169+ /* err = au_xigen_file_set(sb, xinew->idx, file); */
37170+ }
37171+ fput(file);
37172+ if (unlikely(err))
37173+ file = ERR_PTR(err);
37174+
37175+out:
37176+ return file;
37177+}
37178+
062440b3
AM
37179+/* ---------------------------------------------------------------------- */
37180+
37181+/*
37182+ * truncate xino files
37183+ */
acd2b654
AM
37184+static int au_xino_do_trunc(struct super_block *sb, aufs_bindex_t bindex,
37185+ int idx, struct kstatfs *st)
1facf9fc 37186+{
37187+ int err;
392086de 37188+ blkcnt_t blocks;
acd2b654
AM
37189+ struct file *file, *new_xino;
37190+ struct au_xi_new xinew = {
37191+ .idx = idx
37192+ };
37193+
37194+ err = 0;
37195+ xinew.xi = au_sbr(sb, bindex)->br_xino;
37196+ file = au_xino_file(xinew.xi, idx);
37197+ if (!file)
37198+ goto out;
37199+
37200+ xinew.base = &file->f_path;
37201+ err = vfs_statfs(xinew.base, st);
37202+ if (unlikely(err)) {
37203+ AuErr1("statfs err %d, ignored\n", err);
37204+ err = 0;
37205+ goto out;
37206+ }
37207+
37208+ blocks = file_inode(file)->i_blocks;
37209+ pr_info("begin truncating xino(b%d-%d), ib%llu, %llu/%llu free blks\n",
37210+ bindex, idx, (u64)blocks, st->f_bfree, st->f_blocks);
37211+
37212+ xinew.copy_src = file;
37213+ new_xino = au_xi_new(sb, &xinew);
37214+ if (IS_ERR(new_xino)) {
37215+ err = PTR_ERR(new_xino);
37216+ pr_err("xino(b%d-%d), err %d, ignored\n", bindex, idx, err);
37217+ goto out;
37218+ }
37219+
37220+ err = vfs_statfs(&new_xino->f_path, st);
37221+ if (!err)
37222+ pr_info("end truncating xino(b%d-%d), ib%llu, %llu/%llu free blks\n",
37223+ bindex, idx, (u64)file_inode(new_xino)->i_blocks,
37224+ st->f_bfree, st->f_blocks);
37225+ else {
37226+ AuErr1("statfs err %d, ignored\n", err);
37227+ err = 0;
37228+ }
37229+
37230+out:
37231+ return err;
37232+}
37233+
37234+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin)
37235+{
37236+ int err, i;
37237+ unsigned long jiffy;
062440b3 37238+ aufs_bindex_t bbot;
392086de 37239+ struct kstatfs *st;
1facf9fc 37240+ struct au_branch *br;
acd2b654 37241+ struct au_xino *xi;
1facf9fc 37242+
392086de 37243+ err = -ENOMEM;
be52b249 37244+ st = kmalloc(sizeof(*st), GFP_NOFS);
392086de
AM
37245+ if (unlikely(!st))
37246+ goto out;
37247+
1facf9fc 37248+ err = -EINVAL;
5afbbe0d
AM
37249+ bbot = au_sbbot(sb);
37250+ if (unlikely(bindex < 0 || bbot < bindex))
392086de 37251+ goto out_st;
392086de 37252+
1facf9fc 37253+ err = 0;
acd2b654
AM
37254+ jiffy = jiffies;
37255+ br = au_sbr(sb, bindex);
37256+ xi = br->br_xino;
37257+ for (i = idx_begin; !err && i < xi->xi_nfile; i++)
37258+ err = au_xino_do_trunc(sb, bindex, i, st);
37259+ if (!err)
37260+ au_sbi(sb)->si_xino_jiffy = jiffy;
392086de
AM
37261+
37262+out_st:
9f237c51 37263+ au_kfree_rcu(st);
4f0767ce 37264+out:
1facf9fc 37265+ return err;
37266+}
37267+
37268+struct xino_do_trunc_args {
37269+ struct super_block *sb;
37270+ struct au_branch *br;
acd2b654 37271+ int idx;
1facf9fc 37272+};
37273+
37274+static void xino_do_trunc(void *_args)
37275+{
37276+ struct xino_do_trunc_args *args = _args;
37277+ struct super_block *sb;
37278+ struct au_branch *br;
37279+ struct inode *dir;
acd2b654 37280+ int err, idx;
1facf9fc 37281+ aufs_bindex_t bindex;
37282+
37283+ err = 0;
37284+ sb = args->sb;
5527c038 37285+ dir = d_inode(sb->s_root);
1facf9fc 37286+ br = args->br;
acd2b654 37287+ idx = args->idx;
1facf9fc 37288+
37289+ si_noflush_write_lock(sb);
37290+ ii_read_lock_parent(dir);
37291+ bindex = au_br_index(sb, br->br_id);
acd2b654 37292+ err = au_xino_trunc(sb, bindex, idx);
1facf9fc 37293+ ii_read_unlock(dir);
37294+ if (unlikely(err))
392086de 37295+ pr_warn("err b%d, (%d)\n", bindex, err);
062440b3 37296+ atomic_dec(&br->br_xino->xi_truncating);
acd2b654 37297+ au_lcnt_dec(&br->br_count);
1facf9fc 37298+ si_write_unlock(sb);
027c5e7a 37299+ au_nwt_done(&au_sbi(sb)->si_nowait);
9f237c51 37300+ au_kfree_rcu(args);
1facf9fc 37301+}
37302+
acd2b654
AM
37303+/*
37304+ * returns the index in the xi_file array whose corresponding file is necessary
37305+ * to truncate, or -1 which means no need to truncate.
37306+ */
392086de
AM
37307+static int xino_trunc_test(struct super_block *sb, struct au_branch *br)
37308+{
37309+ int err;
acd2b654 37310+ unsigned int u;
392086de
AM
37311+ struct kstatfs st;
37312+ struct au_sbinfo *sbinfo;
acd2b654 37313+ struct au_xino *xi;
062440b3 37314+ struct file *file;
392086de
AM
37315+
37316+ /* todo: si_xino_expire and the ratio should be customizable */
37317+ sbinfo = au_sbi(sb);
37318+ if (time_before(jiffies,
37319+ sbinfo->si_xino_jiffy + sbinfo->si_xino_expire))
acd2b654 37320+ return -1;
392086de
AM
37321+
37322+ /* truncation border */
acd2b654
AM
37323+ xi = br->br_xino;
37324+ for (u = 0; u < xi->xi_nfile; u++) {
37325+ file = au_xino_file(xi, u);
37326+ if (!file)
37327+ continue;
37328+
37329+ err = vfs_statfs(&file->f_path, &st);
37330+ if (unlikely(err)) {
37331+ AuErr1("statfs err %d, ignored\n", err);
37332+ return -1;
37333+ }
37334+ if (div64_u64(st.f_bfree * 100, st.f_blocks)
37335+ >= AUFS_XINO_DEF_TRUNC)
37336+ return u;
392086de 37337+ }
392086de 37338+
acd2b654 37339+ return -1;
392086de
AM
37340+}
37341+
1facf9fc 37342+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
37343+{
acd2b654 37344+ int idx;
1facf9fc 37345+ struct xino_do_trunc_args *args;
37346+ int wkq_err;
37347+
acd2b654
AM
37348+ idx = xino_trunc_test(sb, br);
37349+ if (idx < 0)
1facf9fc 37350+ return;
37351+
062440b3 37352+ if (atomic_inc_return(&br->br_xino->xi_truncating) > 1)
1facf9fc 37353+ goto out;
37354+
37355+ /* lock and kfree() will be called in trunc_xino() */
37356+ args = kmalloc(sizeof(*args), GFP_NOFS);
37357+ if (unlikely(!args)) {
37358+ AuErr1("no memory\n");
f0c0a007 37359+ goto out;
1facf9fc 37360+ }
37361+
acd2b654 37362+ au_lcnt_inc(&br->br_count);
1facf9fc 37363+ args->sb = sb;
37364+ args->br = br;
acd2b654 37365+ args->idx = idx;
53392da6 37366+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb, /*flags*/0);
1facf9fc 37367+ if (!wkq_err)
37368+ return; /* success */
37369+
4a4d8108 37370+ pr_err("wkq %d\n", wkq_err);
acd2b654 37371+ au_lcnt_dec(&br->br_count);
9f237c51 37372+ au_kfree_rcu(args);
1facf9fc 37373+
4f0767ce 37374+out:
062440b3 37375+ atomic_dec(&br->br_xino->xi_truncating);
1facf9fc 37376+}
37377+
37378+/* ---------------------------------------------------------------------- */
37379+
acd2b654
AM
37380+struct au_xi_calc {
37381+ int idx;
37382+ loff_t pos;
37383+};
37384+
37385+static void au_xi_calc(struct super_block *sb, ino_t h_ino,
37386+ struct au_xi_calc *calc)
37387+{
37388+ loff_t maxent;
37389+
37390+ maxent = au_xi_maxent(sb);
37391+ calc->idx = div64_u64_rem(h_ino, maxent, &calc->pos);
37392+ calc->pos *= sizeof(ino_t);
37393+}
37394+
37395+static int au_xino_do_new_async(struct super_block *sb, struct au_branch *br,
37396+ struct au_xi_calc *calc)
37397+{
37398+ int err;
37399+ struct file *file;
37400+ struct au_xino *xi = br->br_xino;
37401+ struct au_xi_new xinew = {
37402+ .xi = xi
37403+ };
37404+
37405+ SiMustAnyLock(sb);
37406+
37407+ err = 0;
37408+ if (!xi)
37409+ goto out;
37410+
37411+ mutex_lock(&xi->xi_mtx);
37412+ file = au_xino_file(xi, calc->idx);
37413+ if (file)
37414+ goto out_mtx;
37415+
37416+ file = au_xino_file(xi, /*idx*/-1);
37417+ AuDebugOn(!file);
37418+ xinew.idx = calc->idx;
37419+ xinew.base = &file->f_path;
37420+ /* xinew.copy_src = NULL; */
37421+ file = au_xi_new(sb, &xinew);
37422+ if (IS_ERR(file))
37423+ err = PTR_ERR(file);
37424+
37425+out_mtx:
37426+ mutex_unlock(&xi->xi_mtx);
37427+out:
37428+ return err;
37429+}
37430+
37431+struct au_xino_do_new_async_args {
37432+ struct super_block *sb;
37433+ struct au_branch *br;
37434+ struct au_xi_calc calc;
37435+ ino_t ino;
37436+};
37437+
9f237c51
AM
37438+struct au_xi_writing {
37439+ struct hlist_bl_node node;
37440+ ino_t h_ino, ino;
37441+};
37442+
e37dd06a
AM
37443+static int au_xino_do_write(struct file *file, struct au_xi_calc *calc,
37444+ ino_t ino);
acd2b654
AM
37445+
37446+static void au_xino_call_do_new_async(void *args)
37447+{
37448+ struct au_xino_do_new_async_args *a = args;
37449+ struct au_branch *br;
37450+ struct super_block *sb;
37451+ struct au_sbinfo *sbi;
37452+ struct inode *root;
37453+ struct file *file;
9f237c51
AM
37454+ struct au_xi_writing *del, *p;
37455+ struct hlist_bl_head *hbl;
37456+ struct hlist_bl_node *pos;
acd2b654
AM
37457+ int err;
37458+
37459+ br = a->br;
37460+ sb = a->sb;
37461+ sbi = au_sbi(sb);
37462+ si_noflush_read_lock(sb);
37463+ root = d_inode(sb->s_root);
37464+ ii_read_lock_child(root);
37465+ err = au_xino_do_new_async(sb, br, &a->calc);
9f237c51
AM
37466+ if (unlikely(err)) {
37467+ AuIOErr("err %d\n", err);
37468+ goto out;
37469+ }
37470+
37471+ file = au_xino_file(br->br_xino, a->calc.idx);
37472+ AuDebugOn(!file);
e37dd06a 37473+ err = au_xino_do_write(file, &a->calc, a->ino);
9f237c51 37474+ if (unlikely(err)) {
acd2b654 37475+ AuIOErr("err %d\n", err);
9f237c51
AM
37476+ goto out;
37477+ }
37478+
37479+ del = NULL;
37480+ hbl = &br->br_xino->xi_writing;
37481+ hlist_bl_lock(hbl);
37482+ au_hbl_for_each(pos, hbl) {
37483+ p = container_of(pos, struct au_xi_writing, node);
37484+ if (p->ino == a->ino) {
37485+ del = p;
37486+ hlist_bl_del(&p->node);
37487+ break;
37488+ }
37489+ }
37490+ hlist_bl_unlock(hbl);
37491+ au_kfree_rcu(del);
37492+
37493+out:
acd2b654
AM
37494+ au_lcnt_dec(&br->br_count);
37495+ ii_read_unlock(root);
37496+ si_read_unlock(sb);
37497+ au_nwt_done(&sbi->si_nowait);
9f237c51 37498+ au_kfree_rcu(a);
acd2b654
AM
37499+}
37500+
37501+/*
37502+ * create a new xino file asynchronously
37503+ */
37504+static int au_xino_new_async(struct super_block *sb, struct au_branch *br,
37505+ struct au_xi_calc *calc, ino_t ino)
37506+{
37507+ int err;
37508+ struct au_xino_do_new_async_args *arg;
37509+
37510+ err = -ENOMEM;
37511+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
37512+ if (unlikely(!arg))
37513+ goto out;
37514+
37515+ arg->sb = sb;
37516+ arg->br = br;
37517+ arg->calc = *calc;
37518+ arg->ino = ino;
37519+ au_lcnt_inc(&br->br_count);
37520+ err = au_wkq_nowait(au_xino_call_do_new_async, arg, sb, AuWkq_NEST);
37521+ if (unlikely(err)) {
37522+ pr_err("wkq %d\n", err);
37523+ au_lcnt_dec(&br->br_count);
9f237c51 37524+ au_kfree_rcu(arg);
acd2b654
AM
37525+ }
37526+
37527+out:
37528+ return err;
37529+}
37530+
062440b3
AM
37531+/*
37532+ * read @ino from xinofile for the specified branch{@sb, @bindex}
37533+ * at the position of @h_ino.
37534+ */
37535+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
37536+ ino_t *ino)
37537+{
37538+ int err;
37539+ ssize_t sz;
acd2b654 37540+ struct au_xi_calc calc;
062440b3 37541+ struct au_sbinfo *sbinfo;
acd2b654 37542+ struct file *file;
9f237c51
AM
37543+ struct au_xino *xi;
37544+ struct hlist_bl_head *hbl;
37545+ struct hlist_bl_node *pos;
37546+ struct au_xi_writing *p;
062440b3
AM
37547+
37548+ *ino = 0;
37549+ if (!au_opt_test(au_mntflags(sb), XINO))
37550+ return 0; /* no xino */
37551+
37552+ err = 0;
acd2b654 37553+ au_xi_calc(sb, h_ino, &calc);
9f237c51
AM
37554+ xi = au_sbr(sb, bindex)->br_xino;
37555+ file = au_xino_file(xi, calc.idx);
37556+ if (!file) {
37557+ hbl = &xi->xi_writing;
37558+ hlist_bl_lock(hbl);
37559+ au_hbl_for_each(pos, hbl) {
37560+ p = container_of(pos, struct au_xi_writing, node);
37561+ if (p->h_ino == h_ino) {
37562+ AuDbg("hi%llu, i%llu, found\n",
37563+ (u64)p->h_ino, (u64)p->ino);
37564+ *ino = p->ino;
37565+ break;
37566+ }
37567+ }
37568+ hlist_bl_unlock(hbl);
37569+ return 0;
37570+ } else if (vfsub_f_size_read(file) < calc.pos + sizeof(*ino))
37571+ return 0; /* no xino */
062440b3 37572+
acd2b654 37573+ sbinfo = au_sbi(sb);
e37dd06a 37574+ sz = xino_fread(file, ino, sizeof(*ino), &calc.pos);
062440b3
AM
37575+ if (sz == sizeof(*ino))
37576+ return 0; /* success */
37577+
37578+ err = sz;
37579+ if (unlikely(sz >= 0)) {
37580+ err = -EIO;
37581+ AuIOErr("xino read error (%zd)\n", sz);
37582+ }
062440b3
AM
37583+ return err;
37584+}
37585+
e37dd06a
AM
37586+static int au_xino_do_write(struct file *file, struct au_xi_calc *calc,
37587+ ino_t ino)
1facf9fc 37588+{
1facf9fc 37589+ ssize_t sz;
37590+
e37dd06a 37591+ sz = xino_fwrite(file, &ino, sizeof(ino), &calc->pos);
1facf9fc 37592+ if (sz == sizeof(ino))
37593+ return 0; /* success */
37594+
37595+ AuIOErr("write failed (%zd)\n", sz);
37596+ return -EIO;
37597+}
37598+
37599+/*
37600+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
37601+ * at the position of @h_ino.
37602+ * even if @ino is zero, it is written to the xinofile and means no entry.
37603+ * if the size of the xino file on a specific filesystem exceeds the watermark,
37604+ * try truncating it.
37605+ */
37606+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
37607+ ino_t ino)
37608+{
37609+ int err;
37610+ unsigned int mnt_flags;
acd2b654
AM
37611+ struct au_xi_calc calc;
37612+ struct file *file;
1facf9fc 37613+ struct au_branch *br;
acd2b654 37614+ struct au_xino *xi;
9f237c51 37615+ struct au_xi_writing *p;
1facf9fc 37616+
dece6358 37617+ SiMustAnyLock(sb);
1facf9fc 37618+
37619+ mnt_flags = au_mntflags(sb);
37620+ if (!au_opt_test(mnt_flags, XINO))
37621+ return 0;
37622+
acd2b654 37623+ au_xi_calc(sb, h_ino, &calc);
1facf9fc 37624+ br = au_sbr(sb, bindex);
acd2b654
AM
37625+ xi = br->br_xino;
37626+ file = au_xino_file(xi, calc.idx);
37627+ if (!file) {
9f237c51
AM
37628+ /* store the inum pair into the list */
37629+ p = kmalloc(sizeof(*p), GFP_NOFS | __GFP_NOFAIL);
37630+ p->h_ino = h_ino;
37631+ p->ino = ino;
37632+ au_hbl_add(&p->node, &xi->xi_writing);
37633+
acd2b654
AM
37634+ /* create and write a new xino file asynchronously */
37635+ err = au_xino_new_async(sb, br, &calc, ino);
37636+ if (!err)
37637+ return 0; /* success */
37638+ goto out;
37639+ }
37640+
e37dd06a 37641+ err = au_xino_do_write(file, &calc, ino);
1facf9fc 37642+ if (!err) {
acd2b654 37643+ br = au_sbr(sb, bindex);
1facf9fc 37644+ if (au_opt_test(mnt_flags, TRUNC_XINO)
86dc4139 37645+ && au_test_fs_trunc_xino(au_br_sb(br)))
1facf9fc 37646+ xino_try_trunc(sb, br);
37647+ return 0; /* success */
37648+ }
37649+
acd2b654 37650+out:
1facf9fc 37651+ AuIOErr("write failed (%d)\n", err);
37652+ return -EIO;
37653+}
37654+
e37dd06a
AM
37655+static ssize_t xino_fread_wkq(struct file *file, void *buf, size_t size,
37656+ loff_t *pos);
1facf9fc 37657+
062440b3 37658+/* todo: unnecessary to support mmap_sem since kernel-space? */
e37dd06a 37659+ssize_t xino_fread(struct file *file, void *kbuf, size_t size, loff_t *pos)
062440b3
AM
37660+{
37661+ ssize_t err;
062440b3
AM
37662+ int i;
37663+ const int prevent_endless = 10;
1facf9fc 37664+
062440b3 37665+ i = 0;
062440b3 37666+ do {
e37dd06a 37667+ err = vfsub_read_k(file, kbuf, size, pos);
062440b3
AM
37668+ if (err == -EINTR
37669+ && !au_wkq_test()
37670+ && fatal_signal_pending(current)) {
e37dd06a 37671+ err = xino_fread_wkq(file, kbuf, size, pos);
062440b3 37672+ BUG_ON(err == -EINTR);
062440b3
AM
37673+ }
37674+ } while (i++ < prevent_endless
37675+ && (err == -EAGAIN || err == -EINTR));
062440b3
AM
37676+
37677+#if 0 /* reserved for future use */
37678+ if (err > 0)
37679+ fsnotify_access(file->f_path.dentry);
37680+#endif
37681+
37682+ return err;
37683+}
37684+
37685+struct xino_fread_args {
37686+ ssize_t *errp;
062440b3
AM
37687+ struct file *file;
37688+ void *buf;
37689+ size_t size;
37690+ loff_t *pos;
37691+};
37692+
37693+static void call_xino_fread(void *args)
37694+{
37695+ struct xino_fread_args *a = args;
e37dd06a 37696+ *a->errp = xino_fread(a->file, a->buf, a->size, a->pos);
062440b3
AM
37697+}
37698+
e37dd06a
AM
37699+static ssize_t xino_fread_wkq(struct file *file, void *buf, size_t size,
37700+ loff_t *pos)
062440b3
AM
37701+{
37702+ ssize_t err;
37703+ int wkq_err;
37704+ struct xino_fread_args args = {
37705+ .errp = &err,
062440b3
AM
37706+ .file = file,
37707+ .buf = buf,
37708+ .size = size,
37709+ .pos = pos
37710+ };
37711+
37712+ wkq_err = au_wkq_wait(call_xino_fread, &args);
37713+ if (unlikely(wkq_err))
37714+ err = wkq_err;
37715+
37716+ return err;
37717+}
37718+
e37dd06a
AM
37719+static ssize_t xino_fwrite_wkq(struct file *file, void *buf, size_t size,
37720+ loff_t *pos);
062440b3 37721+
e37dd06a
AM
37722+static ssize_t do_xino_fwrite(struct file *file, void *kbuf, size_t size,
37723+ loff_t *pos)
062440b3
AM
37724+{
37725+ ssize_t err;
062440b3
AM
37726+ int i;
37727+ const int prevent_endless = 10;
37728+
37729+ i = 0;
062440b3 37730+ do {
e37dd06a 37731+ err = vfsub_write_k(file, kbuf, size, pos);
062440b3
AM
37732+ if (err == -EINTR
37733+ && !au_wkq_test()
37734+ && fatal_signal_pending(current)) {
e37dd06a 37735+ err = xino_fwrite_wkq(file, kbuf, size, pos);
062440b3 37736+ BUG_ON(err == -EINTR);
062440b3
AM
37737+ }
37738+ } while (i++ < prevent_endless
37739+ && (err == -EAGAIN || err == -EINTR));
062440b3
AM
37740+
37741+#if 0 /* reserved for future use */
37742+ if (err > 0)
37743+ fsnotify_modify(file->f_path.dentry);
37744+#endif
37745+
37746+ return err;
37747+}
37748+
37749+struct do_xino_fwrite_args {
37750+ ssize_t *errp;
062440b3
AM
37751+ struct file *file;
37752+ void *buf;
37753+ size_t size;
37754+ loff_t *pos;
37755+};
37756+
37757+static void call_do_xino_fwrite(void *args)
37758+{
37759+ struct do_xino_fwrite_args *a = args;
e37dd06a 37760+ *a->errp = do_xino_fwrite(a->file, a->buf, a->size, a->pos);
062440b3
AM
37761+}
37762+
e37dd06a
AM
37763+static ssize_t xino_fwrite_wkq(struct file *file, void *buf, size_t size,
37764+ loff_t *pos)
062440b3
AM
37765+{
37766+ ssize_t err;
37767+ int wkq_err;
37768+ struct do_xino_fwrite_args args = {
37769+ .errp = &err,
062440b3
AM
37770+ .file = file,
37771+ .buf = buf,
37772+ .size = size,
37773+ .pos = pos
37774+ };
37775+
37776+ /*
37777+ * it breaks RLIMIT_FSIZE and normal user's limit,
37778+ * users should care about quota and real 'filesystem full.'
37779+ */
37780+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
37781+ if (unlikely(wkq_err))
37782+ err = wkq_err;
37783+
37784+ return err;
37785+}
37786+
e37dd06a 37787+ssize_t xino_fwrite(struct file *file, void *buf, size_t size, loff_t *pos)
062440b3
AM
37788+{
37789+ ssize_t err;
37790+
37791+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
37792+ lockdep_off();
e37dd06a 37793+ err = do_xino_fwrite(file, buf, size, pos);
062440b3
AM
37794+ lockdep_on();
37795+ } else {
37796+ lockdep_off();
e37dd06a 37797+ err = xino_fwrite_wkq(file, buf, size, pos);
062440b3
AM
37798+ lockdep_on();
37799+ }
37800+
37801+ return err;
37802+}
37803+
37804+/* ---------------------------------------------------------------------- */
37805+
37806+/*
37807+ * inode number bitmap
37808+ */
1facf9fc 37809+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
37810+static ino_t xib_calc_ino(unsigned long pindex, int bit)
37811+{
37812+ ino_t ino;
37813+
37814+ AuDebugOn(bit < 0 || page_bits <= bit);
37815+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
37816+ return ino;
37817+}
37818+
37819+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
37820+{
37821+ AuDebugOn(ino < AUFS_FIRST_INO);
37822+ ino -= AUFS_FIRST_INO;
37823+ *pindex = ino / page_bits;
37824+ *bit = ino % page_bits;
37825+}
37826+
37827+static int xib_pindex(struct super_block *sb, unsigned long pindex)
37828+{
37829+ int err;
37830+ loff_t pos;
37831+ ssize_t sz;
37832+ struct au_sbinfo *sbinfo;
37833+ struct file *xib;
37834+ unsigned long *p;
37835+
37836+ sbinfo = au_sbi(sb);
37837+ MtxMustLock(&sbinfo->si_xib_mtx);
37838+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
37839+ || !au_opt_test(sbinfo->si_mntflags, XINO));
37840+
37841+ if (pindex == sbinfo->si_xib_last_pindex)
37842+ return 0;
37843+
37844+ xib = sbinfo->si_xib;
37845+ p = sbinfo->si_xib_buf;
37846+ pos = sbinfo->si_xib_last_pindex;
37847+ pos *= PAGE_SIZE;
e37dd06a 37848+ sz = xino_fwrite(xib, p, PAGE_SIZE, &pos);
1facf9fc 37849+ if (unlikely(sz != PAGE_SIZE))
37850+ goto out;
37851+
37852+ pos = pindex;
37853+ pos *= PAGE_SIZE;
c06a8ce3 37854+ if (vfsub_f_size_read(xib) >= pos + PAGE_SIZE)
e37dd06a 37855+ sz = xino_fread(xib, p, PAGE_SIZE, &pos);
1facf9fc 37856+ else {
37857+ memset(p, 0, PAGE_SIZE);
e37dd06a 37858+ sz = xino_fwrite(xib, p, PAGE_SIZE, &pos);
1facf9fc 37859+ }
37860+ if (sz == PAGE_SIZE) {
37861+ sbinfo->si_xib_last_pindex = pindex;
37862+ return 0; /* success */
37863+ }
37864+
4f0767ce 37865+out:
b752ccd1
AM
37866+ AuIOErr1("write failed (%zd)\n", sz);
37867+ err = sz;
37868+ if (sz >= 0)
37869+ err = -EIO;
37870+ return err;
37871+}
37872+
b752ccd1
AM
37873+static void au_xib_clear_bit(struct inode *inode)
37874+{
37875+ int err, bit;
37876+ unsigned long pindex;
37877+ struct super_block *sb;
37878+ struct au_sbinfo *sbinfo;
37879+
37880+ AuDebugOn(inode->i_nlink);
37881+
37882+ sb = inode->i_sb;
37883+ xib_calc_bit(inode->i_ino, &pindex, &bit);
37884+ AuDebugOn(page_bits <= bit);
37885+ sbinfo = au_sbi(sb);
37886+ mutex_lock(&sbinfo->si_xib_mtx);
37887+ err = xib_pindex(sb, pindex);
37888+ if (!err) {
37889+ clear_bit(bit, sbinfo->si_xib_buf);
37890+ sbinfo->si_xib_next_bit = bit;
37891+ }
37892+ mutex_unlock(&sbinfo->si_xib_mtx);
37893+}
37894+
1facf9fc 37895+/* ---------------------------------------------------------------------- */
37896+
1facf9fc 37897+/*
062440b3 37898+ * truncate a xino bitmap file
1facf9fc 37899+ */
1facf9fc 37900+
37901+/* todo: slow */
37902+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
37903+{
37904+ int err, bit;
37905+ ssize_t sz;
37906+ unsigned long pindex;
37907+ loff_t pos, pend;
37908+ struct au_sbinfo *sbinfo;
1facf9fc 37909+ ino_t *ino;
37910+ unsigned long *p;
37911+
37912+ err = 0;
37913+ sbinfo = au_sbi(sb);
dece6358 37914+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 37915+ p = sbinfo->si_xib_buf;
c06a8ce3 37916+ pend = vfsub_f_size_read(file);
1facf9fc 37917+ pos = 0;
37918+ while (pos < pend) {
e37dd06a 37919+ sz = xino_fread(file, page, PAGE_SIZE, &pos);
1facf9fc 37920+ err = sz;
37921+ if (unlikely(sz <= 0))
37922+ goto out;
37923+
37924+ err = 0;
37925+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
37926+ if (unlikely(*ino < AUFS_FIRST_INO))
37927+ continue;
37928+
37929+ xib_calc_bit(*ino, &pindex, &bit);
37930+ AuDebugOn(page_bits <= bit);
37931+ err = xib_pindex(sb, pindex);
37932+ if (!err)
37933+ set_bit(bit, p);
37934+ else
37935+ goto out;
37936+ }
37937+ }
37938+
4f0767ce 37939+out:
1facf9fc 37940+ return err;
37941+}
37942+
37943+static int xib_restore(struct super_block *sb)
37944+{
acd2b654
AM
37945+ int err, i;
37946+ unsigned int nfile;
5afbbe0d 37947+ aufs_bindex_t bindex, bbot;
1facf9fc 37948+ void *page;
062440b3 37949+ struct au_branch *br;
acd2b654
AM
37950+ struct au_xino *xi;
37951+ struct file *file;
1facf9fc 37952+
37953+ err = -ENOMEM;
37954+ page = (void *)__get_free_page(GFP_NOFS);
37955+ if (unlikely(!page))
37956+ goto out;
37957+
37958+ err = 0;
5afbbe0d
AM
37959+ bbot = au_sbbot(sb);
37960+ for (bindex = 0; !err && bindex <= bbot; bindex++)
062440b3
AM
37961+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0) {
37962+ br = au_sbr(sb, bindex);
acd2b654
AM
37963+ xi = br->br_xino;
37964+ nfile = xi->xi_nfile;
37965+ for (i = 0; i < nfile; i++) {
37966+ file = au_xino_file(xi, i);
37967+ if (file)
37968+ err = do_xib_restore(sb, file, page);
37969+ }
062440b3
AM
37970+ } else
37971+ AuDbg("skip shared b%d\n", bindex);
1c60b727 37972+ free_page((unsigned long)page);
1facf9fc 37973+
4f0767ce 37974+out:
1facf9fc 37975+ return err;
37976+}
37977+
37978+int au_xib_trunc(struct super_block *sb)
37979+{
37980+ int err;
37981+ ssize_t sz;
37982+ loff_t pos;
1facf9fc 37983+ struct au_sbinfo *sbinfo;
37984+ unsigned long *p;
37985+ struct file *file;
37986+
dece6358
AM
37987+ SiMustWriteLock(sb);
37988+
1facf9fc 37989+ err = 0;
37990+ sbinfo = au_sbi(sb);
37991+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
37992+ goto out;
37993+
37994+ file = sbinfo->si_xib;
c06a8ce3 37995+ if (vfsub_f_size_read(file) <= PAGE_SIZE)
1facf9fc 37996+ goto out;
37997+
062440b3 37998+ file = au_xino_create2(sb, &sbinfo->si_xib->f_path, NULL);
1facf9fc 37999+ err = PTR_ERR(file);
38000+ if (IS_ERR(file))
38001+ goto out;
38002+ fput(sbinfo->si_xib);
38003+ sbinfo->si_xib = file;
38004+
38005+ p = sbinfo->si_xib_buf;
38006+ memset(p, 0, PAGE_SIZE);
38007+ pos = 0;
e37dd06a 38008+ sz = xino_fwrite(sbinfo->si_xib, p, PAGE_SIZE, &pos);
1facf9fc 38009+ if (unlikely(sz != PAGE_SIZE)) {
38010+ err = sz;
38011+ AuIOErr("err %d\n", err);
38012+ if (sz >= 0)
38013+ err = -EIO;
38014+ goto out;
38015+ }
38016+
38017+ mutex_lock(&sbinfo->si_xib_mtx);
38018+ /* mnt_want_write() is unnecessary here */
38019+ err = xib_restore(sb);
38020+ mutex_unlock(&sbinfo->si_xib_mtx);
38021+
38022+out:
38023+ return err;
38024+}
38025+
38026+/* ---------------------------------------------------------------------- */
38027+
acd2b654 38028+struct au_xino *au_xino_alloc(unsigned int nfile)
062440b3
AM
38029+{
38030+ struct au_xino *xi;
38031+
38032+ xi = kzalloc(sizeof(*xi), GFP_NOFS);
38033+ if (unlikely(!xi))
38034+ goto out;
acd2b654
AM
38035+ xi->xi_nfile = nfile;
38036+ xi->xi_file = kcalloc(nfile, sizeof(*xi->xi_file), GFP_NOFS);
38037+ if (unlikely(!xi->xi_file))
38038+ goto out_free;
062440b3
AM
38039+
38040+ xi->xi_nondir.total = 8; /* initial size */
38041+ xi->xi_nondir.array = kcalloc(xi->xi_nondir.total, sizeof(ino_t),
38042+ GFP_NOFS);
38043+ if (unlikely(!xi->xi_nondir.array))
acd2b654 38044+ goto out_file;
062440b3
AM
38045+
38046+ spin_lock_init(&xi->xi_nondir.spin);
38047+ init_waitqueue_head(&xi->xi_nondir.wqh);
acd2b654 38048+ mutex_init(&xi->xi_mtx);
9f237c51 38049+ INIT_HLIST_BL_HEAD(&xi->xi_writing);
062440b3
AM
38050+ atomic_set(&xi->xi_truncating, 0);
38051+ kref_init(&xi->xi_kref);
38052+ goto out; /* success */
38053+
acd2b654 38054+out_file:
9f237c51 38055+ au_kfree_try_rcu(xi->xi_file);
062440b3 38056+out_free:
9f237c51 38057+ au_kfree_rcu(xi);
062440b3
AM
38058+ xi = NULL;
38059+out:
38060+ return xi;
38061+}
38062+
acd2b654 38063+static int au_xino_init(struct au_branch *br, int idx, struct file *file)
062440b3
AM
38064+{
38065+ int err;
38066+ struct au_xino *xi;
38067+
38068+ err = 0;
acd2b654 38069+ xi = au_xino_alloc(idx + 1);
062440b3
AM
38070+ if (unlikely(!xi)) {
38071+ err = -ENOMEM;
38072+ goto out;
38073+ }
38074+
acd2b654
AM
38075+ if (file)
38076+ get_file(file);
38077+ xi->xi_file[idx] = file;
062440b3
AM
38078+ AuDebugOn(br->br_xino);
38079+ br->br_xino = xi;
38080+
38081+out:
38082+ return err;
38083+}
38084+
38085+static void au_xino_release(struct kref *kref)
38086+{
38087+ struct au_xino *xi;
38088+ int i;
9f237c51
AM
38089+ unsigned long ul;
38090+ struct hlist_bl_head *hbl;
38091+ struct hlist_bl_node *pos, *n;
38092+ struct au_xi_writing *p;
062440b3
AM
38093+
38094+ xi = container_of(kref, struct au_xino, xi_kref);
acd2b654
AM
38095+ for (i = 0; i < xi->xi_nfile; i++)
38096+ if (xi->xi_file[i])
38097+ fput(xi->xi_file[i]);
062440b3
AM
38098+ for (i = xi->xi_nondir.total - 1; i >= 0; i--)
38099+ AuDebugOn(xi->xi_nondir.array[i]);
acd2b654 38100+ mutex_destroy(&xi->xi_mtx);
9f237c51
AM
38101+ hbl = &xi->xi_writing;
38102+ ul = au_hbl_count(hbl);
38103+ if (unlikely(ul)) {
38104+ pr_warn("xi_writing %lu\n", ul);
38105+ hlist_bl_lock(hbl);
43982f53 38106+ hlist_bl_for_each_entry_safe(p, pos, n, hbl, node) {
9f237c51 38107+ hlist_bl_del(&p->node);
394e211a
AM
38108+ /* kmemleak reported au_kfree_rcu() doesn't free it */
38109+ kfree(p);
9f237c51
AM
38110+ }
38111+ hlist_bl_unlock(hbl);
38112+ }
38113+ au_kfree_try_rcu(xi->xi_file);
38114+ au_kfree_try_rcu(xi->xi_nondir.array);
38115+ au_kfree_rcu(xi);
062440b3
AM
38116+}
38117+
38118+int au_xino_put(struct au_branch *br)
38119+{
38120+ int ret;
38121+ struct au_xino *xi;
38122+
38123+ ret = 0;
38124+ xi = br->br_xino;
38125+ if (xi) {
38126+ br->br_xino = NULL;
38127+ ret = kref_put(&xi->xi_kref, au_xino_release);
38128+ }
38129+
38130+ return ret;
38131+}
38132+
062440b3
AM
38133+/* ---------------------------------------------------------------------- */
38134+
1facf9fc 38135+/*
38136+ * xino mount option handlers
38137+ */
1facf9fc 38138+
38139+/* xino bitmap */
38140+static void xino_clear_xib(struct super_block *sb)
38141+{
38142+ struct au_sbinfo *sbinfo;
38143+
dece6358
AM
38144+ SiMustWriteLock(sb);
38145+
1facf9fc 38146+ sbinfo = au_sbi(sb);
1facf9fc 38147+ if (sbinfo->si_xib)
38148+ fput(sbinfo->si_xib);
38149+ sbinfo->si_xib = NULL;
f0c0a007 38150+ if (sbinfo->si_xib_buf)
1c60b727 38151+ free_page((unsigned long)sbinfo->si_xib_buf);
1facf9fc 38152+ sbinfo->si_xib_buf = NULL;
38153+}
38154+
062440b3 38155+static int au_xino_set_xib(struct super_block *sb, struct path *path)
1facf9fc 38156+{
38157+ int err;
38158+ loff_t pos;
38159+ struct au_sbinfo *sbinfo;
38160+ struct file *file;
acd2b654 38161+ struct super_block *xi_sb;
1facf9fc 38162+
dece6358
AM
38163+ SiMustWriteLock(sb);
38164+
1facf9fc 38165+ sbinfo = au_sbi(sb);
062440b3 38166+ file = au_xino_create2(sb, path, sbinfo->si_xib);
1facf9fc 38167+ err = PTR_ERR(file);
38168+ if (IS_ERR(file))
38169+ goto out;
38170+ if (sbinfo->si_xib)
38171+ fput(sbinfo->si_xib);
38172+ sbinfo->si_xib = file;
acd2b654
AM
38173+ xi_sb = file_inode(file)->i_sb;
38174+ sbinfo->si_ximaxent = xi_sb->s_maxbytes;
38175+ if (unlikely(sbinfo->si_ximaxent < PAGE_SIZE)) {
38176+ err = -EIO;
38177+ pr_err("s_maxbytes(%llu) on %s is too small\n",
38178+ (u64)sbinfo->si_ximaxent, au_sbtype(xi_sb));
38179+ goto out_unset;
38180+ }
38181+ sbinfo->si_ximaxent /= sizeof(ino_t);
1facf9fc 38182+
38183+ err = -ENOMEM;
38184+ if (!sbinfo->si_xib_buf)
38185+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
38186+ if (unlikely(!sbinfo->si_xib_buf))
38187+ goto out_unset;
38188+
38189+ sbinfo->si_xib_last_pindex = 0;
38190+ sbinfo->si_xib_next_bit = 0;
c06a8ce3 38191+ if (vfsub_f_size_read(file) < PAGE_SIZE) {
1facf9fc 38192+ pos = 0;
e37dd06a 38193+ err = xino_fwrite(file, sbinfo->si_xib_buf, PAGE_SIZE, &pos);
1facf9fc 38194+ if (unlikely(err != PAGE_SIZE))
38195+ goto out_free;
38196+ }
38197+ err = 0;
38198+ goto out; /* success */
38199+
4f0767ce 38200+out_free:
f0c0a007 38201+ if (sbinfo->si_xib_buf)
1c60b727 38202+ free_page((unsigned long)sbinfo->si_xib_buf);
b752ccd1
AM
38203+ sbinfo->si_xib_buf = NULL;
38204+ if (err >= 0)
38205+ err = -EIO;
4f0767ce 38206+out_unset:
b752ccd1
AM
38207+ fput(sbinfo->si_xib);
38208+ sbinfo->si_xib = NULL;
4f0767ce 38209+out:
062440b3 38210+ AuTraceErr(err);
b752ccd1 38211+ return err;
1facf9fc 38212+}
38213+
b752ccd1
AM
38214+/* xino for each branch */
38215+static void xino_clear_br(struct super_block *sb)
38216+{
5afbbe0d 38217+ aufs_bindex_t bindex, bbot;
b752ccd1 38218+ struct au_branch *br;
1facf9fc 38219+
5afbbe0d
AM
38220+ bbot = au_sbbot(sb);
38221+ for (bindex = 0; bindex <= bbot; bindex++) {
b752ccd1 38222+ br = au_sbr(sb, bindex);
062440b3
AM
38223+ AuDebugOn(!br);
38224+ au_xino_put(br);
38225+ }
38226+}
38227+
38228+static void au_xino_set_br_shared(struct super_block *sb, struct au_branch *br,
38229+ aufs_bindex_t bshared)
38230+{
38231+ struct au_branch *brshared;
b752ccd1 38232+
062440b3
AM
38233+ brshared = au_sbr(sb, bshared);
38234+ AuDebugOn(!brshared->br_xino);
38235+ AuDebugOn(!brshared->br_xino->xi_file);
38236+ if (br->br_xino != brshared->br_xino) {
38237+ au_xino_get(brshared);
38238+ au_xino_put(br);
38239+ br->br_xino = brshared->br_xino;
b752ccd1
AM
38240+ }
38241+}
38242+
062440b3 38243+struct au_xino_do_set_br {
062440b3
AM
38244+ struct au_branch *br;
38245+ ino_t h_ino;
38246+ aufs_bindex_t bshared;
38247+};
38248+
38249+static int au_xino_do_set_br(struct super_block *sb, struct path *path,
38250+ struct au_xino_do_set_br *args)
1facf9fc 38251+{
38252+ int err;
acd2b654 38253+ struct au_xi_calc calc;
062440b3 38254+ struct file *file;
acd2b654
AM
38255+ struct au_branch *br;
38256+ struct au_xi_new xinew = {
38257+ .base = path
38258+ };
062440b3 38259+
acd2b654
AM
38260+ br = args->br;
38261+ xinew.xi = br->br_xino;
38262+ au_xi_calc(sb, args->h_ino, &calc);
38263+ xinew.copy_src = au_xino_file(xinew.xi, calc.idx);
38264+ if (args->bshared >= 0)
062440b3 38265+ /* shared xino */
acd2b654
AM
38266+ au_xino_set_br_shared(sb, br, args->bshared);
38267+ else if (!xinew.xi) {
38268+ /* new xino */
38269+ err = au_xino_init(br, calc.idx, xinew.copy_src);
38270+ if (unlikely(err))
38271+ goto out;
062440b3
AM
38272+ }
38273+
acd2b654
AM
38274+ /* force re-creating */
38275+ xinew.xi = br->br_xino;
38276+ xinew.idx = calc.idx;
38277+ mutex_lock(&xinew.xi->xi_mtx);
38278+ file = au_xi_new(sb, &xinew);
38279+ mutex_unlock(&xinew.xi->xi_mtx);
062440b3
AM
38280+ err = PTR_ERR(file);
38281+ if (IS_ERR(file))
38282+ goto out;
acd2b654
AM
38283+ AuDebugOn(!file);
38284+
e37dd06a 38285+ err = au_xino_do_write(file, &calc, AUFS_ROOT_INO);
acd2b654
AM
38286+ if (unlikely(err))
38287+ au_xino_put(br);
062440b3 38288+
062440b3
AM
38289+out:
38290+ AuTraceErr(err);
38291+ return err;
38292+}
38293+
38294+static int au_xino_set_br(struct super_block *sb, struct path *path)
38295+{
38296+ int err;
38297+ aufs_bindex_t bindex, bbot;
38298+ struct au_xino_do_set_br args;
b752ccd1 38299+ struct inode *inode;
1facf9fc 38300+
b752ccd1
AM
38301+ SiMustWriteLock(sb);
38302+
5afbbe0d 38303+ bbot = au_sbbot(sb);
5527c038 38304+ inode = d_inode(sb->s_root);
062440b3
AM
38305+ for (bindex = 0; bindex <= bbot; bindex++) {
38306+ args.h_ino = au_h_iptr(inode, bindex)->i_ino;
38307+ args.br = au_sbr(sb, bindex);
38308+ args.bshared = is_sb_shared(sb, bindex, bindex - 1);
38309+ err = au_xino_do_set_br(sb, path, &args);
b752ccd1 38310+ if (unlikely(err))
062440b3 38311+ break;
b752ccd1 38312+ }
1facf9fc 38313+
062440b3 38314+ AuTraceErr(err);
1facf9fc 38315+ return err;
38316+}
b752ccd1
AM
38317+
38318+void au_xino_clr(struct super_block *sb)
38319+{
38320+ struct au_sbinfo *sbinfo;
38321+
38322+ au_xigen_clr(sb);
38323+ xino_clear_xib(sb);
38324+ xino_clear_br(sb);
062440b3 38325+ dbgaufs_brs_del(sb, 0);
b752ccd1
AM
38326+ sbinfo = au_sbi(sb);
38327+ /* lvalue, do not call au_mntflags() */
38328+ au_opt_clr(sbinfo->si_mntflags, XINO);
38329+}
38330+
062440b3 38331+int au_xino_set(struct super_block *sb, struct au_opt_xino *xiopt, int remount)
b752ccd1
AM
38332+{
38333+ int err, skip;
062440b3 38334+ struct dentry *dentry, *parent, *cur_dentry, *cur_parent;
b752ccd1
AM
38335+ struct qstr *dname, *cur_name;
38336+ struct file *cur_xino;
b752ccd1 38337+ struct au_sbinfo *sbinfo;
062440b3 38338+ struct path *path, *cur_path;
b752ccd1
AM
38339+
38340+ SiMustWriteLock(sb);
38341+
38342+ err = 0;
38343+ sbinfo = au_sbi(sb);
062440b3
AM
38344+ path = &xiopt->file->f_path;
38345+ dentry = path->dentry;
38346+ parent = dget_parent(dentry);
b752ccd1
AM
38347+ if (remount) {
38348+ skip = 0;
b752ccd1
AM
38349+ cur_xino = sbinfo->si_xib;
38350+ if (cur_xino) {
062440b3
AM
38351+ cur_path = &cur_xino->f_path;
38352+ cur_dentry = cur_path->dentry;
38353+ cur_parent = dget_parent(cur_dentry);
38354+ cur_name = &cur_dentry->d_name;
38355+ dname = &dentry->d_name;
b752ccd1 38356+ skip = (cur_parent == parent
38d290e6 38357+ && au_qstreq(dname, cur_name));
b752ccd1
AM
38358+ dput(cur_parent);
38359+ }
38360+ if (skip)
38361+ goto out;
38362+ }
38363+
38364+ au_opt_set(sbinfo->si_mntflags, XINO);
062440b3
AM
38365+ err = au_xino_set_xib(sb, path);
38366+ /* si_x{read,write} are set */
b752ccd1 38367+ if (!err)
062440b3 38368+ err = au_xigen_set(sb, path);
b752ccd1 38369+ if (!err)
062440b3
AM
38370+ err = au_xino_set_br(sb, path);
38371+ if (!err) {
38372+ dbgaufs_brs_add(sb, 0, /*topdown*/1);
b752ccd1 38373+ goto out; /* success */
062440b3 38374+ }
b752ccd1
AM
38375+
38376+ /* reset all */
062440b3
AM
38377+ AuIOErr("failed setting xino(%d).\n", err);
38378+ au_xino_clr(sb);
b752ccd1 38379+
4f0767ce 38380+out:
b752ccd1
AM
38381+ dput(parent);
38382+ return err;
38383+}
38384+
b752ccd1
AM
38385+/*
38386+ * create a xinofile at the default place/path.
38387+ */
38388+struct file *au_xino_def(struct super_block *sb)
38389+{
38390+ struct file *file;
38391+ char *page, *p;
38392+ struct au_branch *br;
38393+ struct super_block *h_sb;
38394+ struct path path;
5afbbe0d 38395+ aufs_bindex_t bbot, bindex, bwr;
b752ccd1
AM
38396+
38397+ br = NULL;
5afbbe0d 38398+ bbot = au_sbbot(sb);
b752ccd1 38399+ bwr = -1;
5afbbe0d 38400+ for (bindex = 0; bindex <= bbot; bindex++) {
b752ccd1
AM
38401+ br = au_sbr(sb, bindex);
38402+ if (au_br_writable(br->br_perm)
86dc4139 38403+ && !au_test_fs_bad_xino(au_br_sb(br))) {
b752ccd1
AM
38404+ bwr = bindex;
38405+ break;
38406+ }
38407+ }
38408+
7f207e10
AM
38409+ if (bwr >= 0) {
38410+ file = ERR_PTR(-ENOMEM);
537831f9 38411+ page = (void *)__get_free_page(GFP_NOFS);
7f207e10
AM
38412+ if (unlikely(!page))
38413+ goto out;
86dc4139 38414+ path.mnt = au_br_mnt(br);
7f207e10
AM
38415+ path.dentry = au_h_dptr(sb->s_root, bwr);
38416+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
38417+ file = (void *)p;
38418+ if (!IS_ERR(p)) {
38419+ strcat(p, "/" AUFS_XINO_FNAME);
38420+ AuDbg("%s\n", p);
83b672a5 38421+ file = au_xino_create(sb, p, /*silent*/0, /*wbrtop*/1);
7f207e10 38422+ }
1c60b727 38423+ free_page((unsigned long)page);
7f207e10 38424+ } else {
83b672a5
AM
38425+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0,
38426+ /*wbrtop*/0);
7f207e10
AM
38427+ if (IS_ERR(file))
38428+ goto out;
2000de60 38429+ h_sb = file->f_path.dentry->d_sb;
7f207e10
AM
38430+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
38431+ pr_err("xino doesn't support %s(%s)\n",
38432+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
38433+ fput(file);
38434+ file = ERR_PTR(-EINVAL);
38435+ }
7f207e10 38436+ }
0c5527e5 38437+
7f207e10
AM
38438+out:
38439+ return file;
38440+}
38441+
38442+/* ---------------------------------------------------------------------- */
38443+
062440b3
AM
38444+/*
38445+ * initialize the xinofile for the specified branch @br
38446+ * at the place/path where @base_file indicates.
38447+ * test whether another branch is on the same filesystem or not,
38448+ * if found then share the xinofile with another branch.
38449+ */
38450+int au_xino_init_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
38451+ struct path *base)
7f207e10
AM
38452+{
38453+ int err;
062440b3
AM
38454+ struct au_xino_do_set_br args = {
38455+ .h_ino = h_ino,
38456+ .br = br
38457+ };
7f207e10 38458+
062440b3
AM
38459+ args.bshared = sbr_find_shared(sb, /*btop*/0, au_sbbot(sb),
38460+ au_br_sb(br));
38461+ err = au_xino_do_set_br(sb, base, &args);
79b8bda9 38462+ if (unlikely(err))
062440b3 38463+ au_xino_put(br);
7f207e10 38464+
7f207e10
AM
38465+ return err;
38466+}
521ced18
JR
38467+
38468+/* ---------------------------------------------------------------------- */
38469+
062440b3
AM
38470+/*
38471+ * get an unused inode number from bitmap
38472+ */
38473+ino_t au_xino_new_ino(struct super_block *sb)
38474+{
38475+ ino_t ino;
38476+ unsigned long *p, pindex, ul, pend;
38477+ struct au_sbinfo *sbinfo;
38478+ struct file *file;
38479+ int free_bit, err;
38480+
38481+ if (!au_opt_test(au_mntflags(sb), XINO))
38482+ return iunique(sb, AUFS_FIRST_INO);
38483+
38484+ sbinfo = au_sbi(sb);
38485+ mutex_lock(&sbinfo->si_xib_mtx);
38486+ p = sbinfo->si_xib_buf;
38487+ free_bit = sbinfo->si_xib_next_bit;
38488+ if (free_bit < page_bits && !test_bit(free_bit, p))
38489+ goto out; /* success */
38490+ free_bit = find_first_zero_bit(p, page_bits);
38491+ if (free_bit < page_bits)
38492+ goto out; /* success */
38493+
38494+ pindex = sbinfo->si_xib_last_pindex;
38495+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
38496+ err = xib_pindex(sb, ul);
38497+ if (unlikely(err))
38498+ goto out_err;
38499+ free_bit = find_first_zero_bit(p, page_bits);
38500+ if (free_bit < page_bits)
38501+ goto out; /* success */
38502+ }
38503+
38504+ file = sbinfo->si_xib;
38505+ pend = vfsub_f_size_read(file) / PAGE_SIZE;
38506+ for (ul = pindex + 1; ul <= pend; ul++) {
38507+ err = xib_pindex(sb, ul);
38508+ if (unlikely(err))
38509+ goto out_err;
38510+ free_bit = find_first_zero_bit(p, page_bits);
38511+ if (free_bit < page_bits)
38512+ goto out; /* success */
38513+ }
38514+ BUG();
38515+
38516+out:
38517+ set_bit(free_bit, p);
38518+ sbinfo->si_xib_next_bit = free_bit + 1;
38519+ pindex = sbinfo->si_xib_last_pindex;
38520+ mutex_unlock(&sbinfo->si_xib_mtx);
38521+ ino = xib_calc_ino(pindex, free_bit);
38522+ AuDbg("i%lu\n", (unsigned long)ino);
38523+ return ino;
38524+out_err:
38525+ mutex_unlock(&sbinfo->si_xib_mtx);
38526+ AuDbg("i0\n");
38527+ return 0;
38528+}
38529+
38530+/* for s_op->delete_inode() */
38531+void au_xino_delete_inode(struct inode *inode, const int unlinked)
521ced18 38532+{
062440b3
AM
38533+ int err;
38534+ unsigned int mnt_flags;
38535+ aufs_bindex_t bindex, bbot, bi;
38536+ unsigned char try_trunc;
38537+ struct au_iinfo *iinfo;
38538+ struct super_block *sb;
38539+ struct au_hinode *hi;
38540+ struct inode *h_inode;
38541+ struct au_branch *br;
acd2b654
AM
38542+ struct au_xi_calc calc;
38543+ struct file *file;
521ced18 38544+
062440b3 38545+ AuDebugOn(au_is_bad_inode(inode));
521ced18 38546+
062440b3
AM
38547+ sb = inode->i_sb;
38548+ mnt_flags = au_mntflags(sb);
38549+ if (!au_opt_test(mnt_flags, XINO)
38550+ || inode->i_ino == AUFS_ROOT_INO)
38551+ return;
38552+
38553+ if (unlinked) {
38554+ au_xigen_inc(inode);
38555+ au_xib_clear_bit(inode);
38556+ }
38557+
38558+ iinfo = au_ii(inode);
38559+ bindex = iinfo->ii_btop;
38560+ if (bindex < 0)
38561+ return;
38562+
062440b3
AM
38563+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
38564+ hi = au_hinode(iinfo, bindex);
38565+ bbot = iinfo->ii_bbot;
38566+ for (; bindex <= bbot; bindex++, hi++) {
38567+ h_inode = hi->hi_inode;
38568+ if (!h_inode
38569+ || (!unlinked && h_inode->i_nlink))
38570+ continue;
38571+
38572+ /* inode may not be revalidated */
38573+ bi = au_br_index(sb, hi->hi_id);
38574+ if (bi < 0)
38575+ continue;
38576+
38577+ br = au_sbr(sb, bi);
acd2b654
AM
38578+ au_xi_calc(sb, h_inode->i_ino, &calc);
38579+ file = au_xino_file(br->br_xino, calc.idx);
38580+ if (IS_ERR_OR_NULL(file))
38581+ continue;
38582+
e37dd06a 38583+ err = au_xino_do_write(file, &calc, /*ino*/0);
062440b3
AM
38584+ if (!err && try_trunc
38585+ && au_test_fs_trunc_xino(au_br_sb(br)))
38586+ xino_try_trunc(sb, br);
38587+ }
521ced18
JR
38588+}
38589+
062440b3
AM
38590+/* ---------------------------------------------------------------------- */
38591+
38592+static int au_xinondir_find(struct au_xino *xi, ino_t h_ino)
521ced18
JR
38593+{
38594+ int found, total, i;
38595+
38596+ found = -1;
062440b3 38597+ total = xi->xi_nondir.total;
521ced18 38598+ for (i = 0; i < total; i++) {
062440b3 38599+ if (xi->xi_nondir.array[i] != h_ino)
521ced18
JR
38600+ continue;
38601+ found = i;
38602+ break;
38603+ }
38604+
38605+ return found;
38606+}
38607+
062440b3 38608+static int au_xinondir_expand(struct au_xino *xi)
521ced18
JR
38609+{
38610+ int err, sz;
38611+ ino_t *p;
38612+
38613+ BUILD_BUG_ON(KMALLOC_MAX_SIZE > INT_MAX);
38614+
38615+ err = -ENOMEM;
062440b3 38616+ sz = xi->xi_nondir.total * sizeof(ino_t);
521ced18
JR
38617+ if (unlikely(sz > KMALLOC_MAX_SIZE / 2))
38618+ goto out;
062440b3 38619+ p = au_kzrealloc(xi->xi_nondir.array, sz, sz << 1, GFP_ATOMIC,
521ced18
JR
38620+ /*may_shrink*/0);
38621+ if (p) {
062440b3
AM
38622+ xi->xi_nondir.array = p;
38623+ xi->xi_nondir.total <<= 1;
38624+ AuDbg("xi_nondir.total %d\n", xi->xi_nondir.total);
521ced18
JR
38625+ err = 0;
38626+ }
38627+
38628+out:
38629+ return err;
38630+}
38631+
062440b3
AM
38632+void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex,
38633+ ino_t h_ino, int idx)
38634+{
38635+ struct au_xino *xi;
38636+
38637+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
38638+ xi = au_sbr(sb, bindex)->br_xino;
38639+ AuDebugOn(idx < 0 || xi->xi_nondir.total <= idx);
38640+
38641+ spin_lock(&xi->xi_nondir.spin);
38642+ AuDebugOn(xi->xi_nondir.array[idx] != h_ino);
38643+ xi->xi_nondir.array[idx] = 0;
38644+ spin_unlock(&xi->xi_nondir.spin);
38645+ wake_up_all(&xi->xi_nondir.wqh);
38646+}
38647+
521ced18
JR
38648+int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
38649+ int *idx)
38650+{
38651+ int err, found, empty;
062440b3 38652+ struct au_xino *xi;
521ced18
JR
38653+
38654+ err = 0;
38655+ *idx = -1;
38656+ if (!au_opt_test(au_mntflags(sb), XINO))
38657+ goto out; /* no xino */
38658+
062440b3 38659+ xi = au_sbr(sb, bindex)->br_xino;
521ced18
JR
38660+
38661+again:
062440b3
AM
38662+ spin_lock(&xi->xi_nondir.spin);
38663+ found = au_xinondir_find(xi, h_ino);
521ced18 38664+ if (found == -1) {
062440b3 38665+ empty = au_xinondir_find(xi, /*h_ino*/0);
521ced18 38666+ if (empty == -1) {
062440b3
AM
38667+ empty = xi->xi_nondir.total;
38668+ err = au_xinondir_expand(xi);
521ced18
JR
38669+ if (unlikely(err))
38670+ goto out_unlock;
38671+ }
062440b3 38672+ xi->xi_nondir.array[empty] = h_ino;
521ced18
JR
38673+ *idx = empty;
38674+ } else {
062440b3
AM
38675+ spin_unlock(&xi->xi_nondir.spin);
38676+ wait_event(xi->xi_nondir.wqh,
38677+ xi->xi_nondir.array[found] != h_ino);
521ced18
JR
38678+ goto again;
38679+ }
38680+
38681+out_unlock:
062440b3
AM
38682+ spin_unlock(&xi->xi_nondir.spin);
38683+out:
38684+ return err;
38685+}
38686+
38687+/* ---------------------------------------------------------------------- */
38688+
38689+int au_xino_path(struct seq_file *seq, struct file *file)
38690+{
38691+ int err;
38692+
38693+ err = au_seq_path(seq, &file->f_path);
38694+ if (unlikely(err))
38695+ goto out;
38696+
38697+#define Deleted "\\040(deleted)"
38698+ seq->count -= sizeof(Deleted) - 1;
38699+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
38700+ sizeof(Deleted) - 1));
38701+#undef Deleted
38702+
521ced18
JR
38703+out:
38704+ return err;
38705+}
537831f9 38706diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/linux/aufs_type.h
eca34b5c 38707--- /usr/share/empty/include/uapi/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
0b2a12c6 38708+++ linux/include/uapi/linux/aufs_type.h 2021-05-02 20:15:14.676670793 +0200
eca34b5c
AM
38709@@ -0,0 +1,452 @@
38710+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
7f207e10 38711+/*
d58c55f2 38712+ * Copyright (C) 2005-2020 Junjiro R. Okajima
7f207e10
AM
38713+ *
38714+ * This program, aufs is free software; you can redistribute it and/or modify
38715+ * it under the terms of the GNU General Public License as published by
38716+ * the Free Software Foundation; either version 2 of the License, or
38717+ * (at your option) any later version.
38718+ *
38719+ * This program is distributed in the hope that it will be useful,
38720+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
38721+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38722+ * GNU General Public License for more details.
38723+ *
38724+ * You should have received a copy of the GNU General Public License
523b37e3 38725+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
7f207e10
AM
38726+ */
38727+
38728+#ifndef __AUFS_TYPE_H__
38729+#define __AUFS_TYPE_H__
38730+
f6c5ef8b
AM
38731+#define AUFS_NAME "aufs"
38732+
9dbd164d 38733+#ifdef __KERNEL__
f6c5ef8b
AM
38734+/*
38735+ * define it before including all other headers.
38736+ * sched.h may use pr_* macros before defining "current", so define the
38737+ * no-current version first, and re-define later.
38738+ */
38739+#define pr_fmt(fmt) AUFS_NAME " %s:%d: " fmt, __func__, __LINE__
38740+#include <linux/sched.h>
38741+#undef pr_fmt
a2a7ad62
AM
38742+#define pr_fmt(fmt) \
38743+ AUFS_NAME " %s:%d:%.*s[%d]: " fmt, __func__, __LINE__, \
38744+ (int)sizeof(current->comm), current->comm, current->pid
43982f53 38745+#include <linux/limits.h>
9dbd164d
AM
38746+#else
38747+#include <stdint.h>
38748+#include <sys/types.h>
43982f53 38749+#include <limits.h>
f6c5ef8b 38750+#endif /* __KERNEL__ */
7f207e10 38751+
0b2a12c6 38752+#define AUFS_VERSION "5.12-20210503"
7f207e10
AM
38753+
38754+/* todo? move this to linux-2.6.19/include/magic.h */
38755+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
38756+
38757+/* ---------------------------------------------------------------------- */
38758+
43982f53 38759+#ifdef __KERNEL__
7f207e10 38760+#ifdef CONFIG_AUFS_BRANCH_MAX_127
9dbd164d 38761+typedef int8_t aufs_bindex_t;
7f207e10
AM
38762+#define AUFS_BRANCH_MAX 127
38763+#else
9dbd164d 38764+typedef int16_t aufs_bindex_t;
7f207e10
AM
38765+#ifdef CONFIG_AUFS_BRANCH_MAX_511
38766+#define AUFS_BRANCH_MAX 511
38767+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
38768+#define AUFS_BRANCH_MAX 1023
38769+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
38770+#define AUFS_BRANCH_MAX 32767
38771+#endif
38772+#endif
38773+
7f207e10
AM
38774+#ifndef AUFS_BRANCH_MAX
38775+#error unknown CONFIG_AUFS_BRANCH_MAX value
38776+#endif
38777+#endif /* __KERNEL__ */
38778+
38779+/* ---------------------------------------------------------------------- */
38780+
7f207e10
AM
38781+#define AUFS_FSTYPE AUFS_NAME
38782+
38783+#define AUFS_ROOT_INO 2
38784+#define AUFS_FIRST_INO 11
38785+
38786+#define AUFS_WH_PFX ".wh."
38787+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
38788+#define AUFS_WH_TMP_LEN 4
86dc4139 38789+/* a limit for rmdir/rename a dir and copyup */
7f207e10
AM
38790+#define AUFS_MAX_NAMELEN (NAME_MAX \
38791+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
38792+ - 1 /* dot */\
38793+ - AUFS_WH_TMP_LEN) /* hex */
38794+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
38795+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
392086de
AM
38796+#define AUFS_XINO_DEF_SEC 30 /* seconds */
38797+#define AUFS_XINO_DEF_TRUNC 45 /* percentage */
7f207e10
AM
38798+#define AUFS_DIRWH_DEF 3
38799+#define AUFS_RDCACHE_DEF 10 /* seconds */
027c5e7a 38800+#define AUFS_RDCACHE_MAX 3600 /* seconds */
7f207e10
AM
38801+#define AUFS_RDBLK_DEF 512 /* bytes */
38802+#define AUFS_RDHASH_DEF 32
38803+#define AUFS_WKQ_NAME AUFS_NAME "d"
027c5e7a
AM
38804+#define AUFS_MFS_DEF_SEC 30 /* seconds */
38805+#define AUFS_MFS_MAX_SEC 3600 /* seconds */
076b876e 38806+#define AUFS_FHSM_CACHE_DEF_SEC 30 /* seconds */
86dc4139 38807+#define AUFS_PLINK_WARN 50 /* number of plinks in a single bucket */
7f207e10
AM
38808+
38809+/* pseudo-link maintenace under /proc */
38810+#define AUFS_PLINK_MAINT_NAME "plink_maint"
38811+#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME
38812+#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME
38813+
8b6a4947
AM
38814+/* dirren, renamed dir */
38815+#define AUFS_DR_INFO_PFX AUFS_WH_PFX ".dr."
38816+#define AUFS_DR_BRHINO_NAME AUFS_WH_PFX "hino"
38817+/* whiteouted doubly */
38818+#define AUFS_WH_DR_INFO_PFX AUFS_WH_PFX AUFS_DR_INFO_PFX
38819+#define AUFS_WH_DR_BRHINO AUFS_WH_PFX AUFS_DR_BRHINO_NAME
38820+
7f207e10
AM
38821+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
38822+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
38823+
38824+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
38825+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
38826+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
38827+
38828+/* doubly whiteouted */
38829+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
38830+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
38831+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
38832+
1e00d052 38833+/* branch permissions and attributes */
7f207e10
AM
38834+#define AUFS_BRPERM_RW "rw"
38835+#define AUFS_BRPERM_RO "ro"
38836+#define AUFS_BRPERM_RR "rr"
076b876e
AM
38837+#define AUFS_BRATTR_COO_REG "coo_reg"
38838+#define AUFS_BRATTR_COO_ALL "coo_all"
38839+#define AUFS_BRATTR_FHSM "fhsm"
38840+#define AUFS_BRATTR_UNPIN "unpin"
c1595e42
JR
38841+#define AUFS_BRATTR_ICEX "icex"
38842+#define AUFS_BRATTR_ICEX_SEC "icexsec"
38843+#define AUFS_BRATTR_ICEX_SYS "icexsys"
38844+#define AUFS_BRATTR_ICEX_TR "icextr"
38845+#define AUFS_BRATTR_ICEX_USR "icexusr"
38846+#define AUFS_BRATTR_ICEX_OTH "icexoth"
1e00d052
AM
38847+#define AUFS_BRRATTR_WH "wh"
38848+#define AUFS_BRWATTR_NLWH "nolwh"
076b876e
AM
38849+#define AUFS_BRWATTR_MOO "moo"
38850+
38851+#define AuBrPerm_RW 1 /* writable, hardlinkable wh */
38852+#define AuBrPerm_RO (1 << 1) /* readonly */
38853+#define AuBrPerm_RR (1 << 2) /* natively readonly */
38854+#define AuBrPerm_Mask (AuBrPerm_RW | AuBrPerm_RO | AuBrPerm_RR)
38855+
38856+#define AuBrAttr_COO_REG (1 << 3) /* copy-up on open */
38857+#define AuBrAttr_COO_ALL (1 << 4)
38858+#define AuBrAttr_COO_Mask (AuBrAttr_COO_REG | AuBrAttr_COO_ALL)
38859+
38860+#define AuBrAttr_FHSM (1 << 5) /* file-based hsm */
38861+#define AuBrAttr_UNPIN (1 << 6) /* rename-able top dir of
c1595e42
JR
38862+ branch. meaningless since
38863+ linux-3.18-rc1 */
38864+
38865+/* ignore error in copying XATTR */
38866+#define AuBrAttr_ICEX_SEC (1 << 7)
38867+#define AuBrAttr_ICEX_SYS (1 << 8)
38868+#define AuBrAttr_ICEX_TR (1 << 9)
38869+#define AuBrAttr_ICEX_USR (1 << 10)
38870+#define AuBrAttr_ICEX_OTH (1 << 11)
38871+#define AuBrAttr_ICEX (AuBrAttr_ICEX_SEC \
38872+ | AuBrAttr_ICEX_SYS \
38873+ | AuBrAttr_ICEX_TR \
38874+ | AuBrAttr_ICEX_USR \
38875+ | AuBrAttr_ICEX_OTH)
38876+
38877+#define AuBrRAttr_WH (1 << 12) /* whiteout-able */
076b876e
AM
38878+#define AuBrRAttr_Mask AuBrRAttr_WH
38879+
c1595e42
JR
38880+#define AuBrWAttr_NoLinkWH (1 << 13) /* un-hardlinkable whiteouts */
38881+#define AuBrWAttr_MOO (1 << 14) /* move-up on open */
076b876e
AM
38882+#define AuBrWAttr_Mask (AuBrWAttr_NoLinkWH | AuBrWAttr_MOO)
38883+
38884+#define AuBrAttr_CMOO_Mask (AuBrAttr_COO_Mask | AuBrWAttr_MOO)
38885+
c1595e42 38886+/* #warning test userspace */
076b876e
AM
38887+#ifdef __KERNEL__
38888+#ifndef CONFIG_AUFS_FHSM
38889+#undef AuBrAttr_FHSM
38890+#define AuBrAttr_FHSM 0
38891+#endif
c1595e42
JR
38892+#ifndef CONFIG_AUFS_XATTR
38893+#undef AuBrAttr_ICEX
38894+#define AuBrAttr_ICEX 0
38895+#undef AuBrAttr_ICEX_SEC
38896+#define AuBrAttr_ICEX_SEC 0
38897+#undef AuBrAttr_ICEX_SYS
38898+#define AuBrAttr_ICEX_SYS 0
38899+#undef AuBrAttr_ICEX_TR
38900+#define AuBrAttr_ICEX_TR 0
38901+#undef AuBrAttr_ICEX_USR
38902+#define AuBrAttr_ICEX_USR 0
38903+#undef AuBrAttr_ICEX_OTH
38904+#define AuBrAttr_ICEX_OTH 0
38905+#endif
076b876e
AM
38906+#endif
38907+
38908+/* the longest combination */
c1595e42
JR
38909+/* AUFS_BRATTR_ICEX and AUFS_BRATTR_ICEX_TR don't affect here */
38910+#define AuBrPermStrSz sizeof(AUFS_BRPERM_RW \
38911+ "+" AUFS_BRATTR_COO_REG \
38912+ "+" AUFS_BRATTR_FHSM \
38913+ "+" AUFS_BRATTR_UNPIN \
7e9cd9fe
AM
38914+ "+" AUFS_BRATTR_ICEX_SEC \
38915+ "+" AUFS_BRATTR_ICEX_SYS \
38916+ "+" AUFS_BRATTR_ICEX_USR \
38917+ "+" AUFS_BRATTR_ICEX_OTH \
076b876e
AM
38918+ "+" AUFS_BRWATTR_NLWH)
38919+
38920+typedef struct {
38921+ char a[AuBrPermStrSz];
38922+} au_br_perm_str_t;
38923+
38924+static inline int au_br_writable(int brperm)
38925+{
38926+ return brperm & AuBrPerm_RW;
38927+}
38928+
38929+static inline int au_br_whable(int brperm)
38930+{
38931+ return brperm & (AuBrPerm_RW | AuBrRAttr_WH);
38932+}
38933+
38934+static inline int au_br_wh_linkable(int brperm)
38935+{
38936+ return !(brperm & AuBrWAttr_NoLinkWH);
38937+}
38938+
38939+static inline int au_br_cmoo(int brperm)
38940+{
38941+ return brperm & AuBrAttr_CMOO_Mask;
38942+}
38943+
38944+static inline int au_br_fhsm(int brperm)
38945+{
38946+ return brperm & AuBrAttr_FHSM;
38947+}
7f207e10
AM
38948+
38949+/* ---------------------------------------------------------------------- */
38950+
38951+/* ioctl */
38952+enum {
38953+ /* readdir in userspace */
38954+ AuCtl_RDU,
38955+ AuCtl_RDU_INO,
38956+
076b876e
AM
38957+ AuCtl_WBR_FD, /* pathconf wrapper */
38958+ AuCtl_IBUSY, /* busy inode */
38959+ AuCtl_MVDOWN, /* move-down */
38960+ AuCtl_BR, /* info about branches */
38961+ AuCtl_FHSM_FD /* connection for fhsm */
7f207e10
AM
38962+};
38963+
38964+/* borrowed from linux/include/linux/kernel.h */
38965+#ifndef ALIGN
eca34b5c 38966+#ifdef _GNU_SOURCE
7f207e10 38967+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
eca34b5c
AM
38968+#else
38969+#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
38970+#endif
7f207e10
AM
38971+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
38972+#endif
38973+
38974+/* borrowed from linux/include/linux/compiler-gcc3.h */
38975+#ifndef __aligned
38976+#define __aligned(x) __attribute__((aligned(x)))
53392da6
AM
38977+#endif
38978+
38979+#ifdef __KERNEL__
38980+#ifndef __packed
7f207e10
AM
38981+#define __packed __attribute__((packed))
38982+#endif
53392da6 38983+#endif
7f207e10
AM
38984+
38985+struct au_rdu_cookie {
9dbd164d
AM
38986+ uint64_t h_pos;
38987+ int16_t bindex;
38988+ uint8_t flags;
38989+ uint8_t pad;
38990+ uint32_t generation;
7f207e10
AM
38991+} __aligned(8);
38992+
38993+struct au_rdu_ent {
9dbd164d
AM
38994+ uint64_t ino;
38995+ int16_t bindex;
38996+ uint8_t type;
38997+ uint8_t nlen;
38998+ uint8_t wh;
42b5c33a 38999+ char name[];
7f207e10
AM
39000+} __aligned(8);
39001+
39002+static inline int au_rdu_len(int nlen)
39003+{
39004+ /* include the terminating NULL */
39005+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
9dbd164d 39006+ sizeof(uint64_t));
7f207e10
AM
39007+}
39008+
39009+union au_rdu_ent_ul {
39010+ struct au_rdu_ent __user *e;
9dbd164d 39011+ uint64_t ul;
7f207e10
AM
39012+};
39013+
39014+enum {
39015+ AufsCtlRduV_SZ,
39016+ AufsCtlRduV_End
39017+};
39018+
39019+struct aufs_rdu {
39020+ /* input */
39021+ union {
9dbd164d
AM
39022+ uint64_t sz; /* AuCtl_RDU */
39023+ uint64_t nent; /* AuCtl_RDU_INO */
7f207e10
AM
39024+ };
39025+ union au_rdu_ent_ul ent;
9dbd164d 39026+ uint16_t verify[AufsCtlRduV_End];
7f207e10
AM
39027+
39028+ /* input/output */
9dbd164d 39029+ uint32_t blk;
7f207e10
AM
39030+
39031+ /* output */
39032+ union au_rdu_ent_ul tail;
39033+ /* number of entries which were added in a single call */
9dbd164d
AM
39034+ uint64_t rent;
39035+ uint8_t full;
39036+ uint8_t shwh;
7f207e10
AM
39037+
39038+ struct au_rdu_cookie cookie;
39039+} __aligned(8);
39040+
1e00d052
AM
39041+/* ---------------------------------------------------------------------- */
39042+
8b6a4947
AM
39043+/* dirren. the branch is identified by the filename who contains this */
39044+struct au_drinfo {
39045+ uint64_t ino;
39046+ union {
39047+ uint8_t oldnamelen;
39048+ uint64_t _padding;
39049+ };
42b5c33a 39050+ uint8_t oldname[];
8b6a4947
AM
39051+} __aligned(8);
39052+
39053+struct au_drinfo_fdata {
39054+ uint32_t magic;
39055+ struct au_drinfo drinfo;
39056+} __aligned(8);
39057+
39058+#define AUFS_DRINFO_MAGIC_V1 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x01)
39059+/* future */
39060+#define AUFS_DRINFO_MAGIC_V2 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x02)
39061+
39062+/* ---------------------------------------------------------------------- */
39063+
1e00d052 39064+struct aufs_wbr_fd {
9dbd164d
AM
39065+ uint32_t oflags;
39066+ int16_t brid;
1e00d052
AM
39067+} __aligned(8);
39068+
39069+/* ---------------------------------------------------------------------- */
39070+
027c5e7a 39071+struct aufs_ibusy {
9dbd164d
AM
39072+ uint64_t ino, h_ino;
39073+ int16_t bindex;
027c5e7a
AM
39074+} __aligned(8);
39075+
1e00d052
AM
39076+/* ---------------------------------------------------------------------- */
39077+
392086de
AM
39078+/* error code for move-down */
39079+/* the actual message strings are implemented in aufs-util.git */
39080+enum {
39081+ EAU_MVDOWN_OPAQUE = 1,
39082+ EAU_MVDOWN_WHITEOUT,
39083+ EAU_MVDOWN_UPPER,
39084+ EAU_MVDOWN_BOTTOM,
39085+ EAU_MVDOWN_NOUPPER,
39086+ EAU_MVDOWN_NOLOWERBR,
39087+ EAU_Last
39088+};
39089+
c2b27bf2 39090+/* flags for move-down */
392086de
AM
39091+#define AUFS_MVDOWN_DMSG 1
39092+#define AUFS_MVDOWN_OWLOWER (1 << 1) /* overwrite lower */
39093+#define AUFS_MVDOWN_KUPPER (1 << 2) /* keep upper */
39094+#define AUFS_MVDOWN_ROLOWER (1 << 3) /* do even if lower is RO */
39095+#define AUFS_MVDOWN_ROLOWER_R (1 << 4) /* did on lower RO */
39096+#define AUFS_MVDOWN_ROUPPER (1 << 5) /* do even if upper is RO */
39097+#define AUFS_MVDOWN_ROUPPER_R (1 << 6) /* did on upper RO */
39098+#define AUFS_MVDOWN_BRID_UPPER (1 << 7) /* upper brid */
39099+#define AUFS_MVDOWN_BRID_LOWER (1 << 8) /* lower brid */
076b876e
AM
39100+#define AUFS_MVDOWN_FHSM_LOWER (1 << 9) /* find fhsm attr for lower */
39101+#define AUFS_MVDOWN_STFS (1 << 10) /* req. stfs */
39102+#define AUFS_MVDOWN_STFS_FAILED (1 << 11) /* output: stfs is unusable */
39103+#define AUFS_MVDOWN_BOTTOM (1 << 12) /* output: no more lowers */
c2b27bf2 39104+
076b876e 39105+/* index for move-down */
392086de
AM
39106+enum {
39107+ AUFS_MVDOWN_UPPER,
39108+ AUFS_MVDOWN_LOWER,
39109+ AUFS_MVDOWN_NARRAY
39110+};
39111+
076b876e
AM
39112+/*
39113+ * additional info of move-down
39114+ * number of free blocks and inodes.
39115+ * subset of struct kstatfs, but smaller and always 64bit.
39116+ */
39117+struct aufs_stfs {
39118+ uint64_t f_blocks;
39119+ uint64_t f_bavail;
39120+ uint64_t f_files;
39121+ uint64_t f_ffree;
39122+};
39123+
39124+struct aufs_stbr {
39125+ int16_t brid; /* optional input */
39126+ int16_t bindex; /* output */
39127+ struct aufs_stfs stfs; /* output when AUFS_MVDOWN_STFS set */
39128+} __aligned(8);
39129+
c2b27bf2 39130+struct aufs_mvdown {
076b876e
AM
39131+ uint32_t flags; /* input/output */
39132+ struct aufs_stbr stbr[AUFS_MVDOWN_NARRAY]; /* input/output */
39133+ int8_t au_errno; /* output */
39134+} __aligned(8);
39135+
39136+/* ---------------------------------------------------------------------- */
39137+
39138+union aufs_brinfo {
39139+ /* PATH_MAX may differ between kernel-space and user-space */
39140+ char _spacer[4096];
392086de 39141+ struct {
076b876e
AM
39142+ int16_t id;
39143+ int perm;
42b5c33a 39144+ char path[];
076b876e 39145+ };
c2b27bf2
AM
39146+} __aligned(8);
39147+
39148+/* ---------------------------------------------------------------------- */
39149+
7f207e10
AM
39150+#define AuCtlType 'A'
39151+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
39152+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
1e00d052
AM
39153+#define AUFS_CTL_WBR_FD _IOW(AuCtlType, AuCtl_WBR_FD, \
39154+ struct aufs_wbr_fd)
027c5e7a 39155+#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy)
392086de
AM
39156+#define AUFS_CTL_MVDOWN _IOWR(AuCtlType, AuCtl_MVDOWN, \
39157+ struct aufs_mvdown)
076b876e
AM
39158+#define AUFS_CTL_BRINFO _IOW(AuCtlType, AuCtl_BR, union aufs_brinfo)
39159+#define AUFS_CTL_FHSM_FD _IOW(AuCtlType, AuCtl_FHSM_FD, int)
7f207e10
AM
39160+
39161+#endif /* __AUFS_TYPE_H__ */
2121bcd9 39162SPDX-License-Identifier: GPL-2.0
0b2a12c6 39163aufs5.12 loopback patch
5527c038
JR
39164
39165diff --git a/drivers/block/loop.c b/drivers/block/loop.c
0b2a12c6 39166index 01ca256575fb2..f5a76bacf6c85 100644
5527c038
JR
39167--- a/drivers/block/loop.c
39168+++ b/drivers/block/loop.c
42a736d3
AM
39169@@ -646,6 +646,15 @@ static inline void loop_update_dio(struct loop_device *lo)
39170 lo->use_dio);
5527c038
JR
39171 }
39172
5527c038
JR
39173+static struct file *loop_real_file(struct file *file)
39174+{
39175+ struct file *f = NULL;
39176+
39177+ if (file->f_path.dentry->d_sb->s_op->real_loop)
39178+ f = file->f_path.dentry->d_sb->s_op->real_loop(file);
39179+ return f;
8b6a4947
AM
39180+}
39181+
c2c0f25c 39182 static void loop_reread_partitions(struct loop_device *lo,
8b6a4947
AM
39183 struct block_device *bdev)
39184 {
42a736d3 39185@@ -701,6 +710,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
5527c038
JR
39186 unsigned int arg)
39187 {
e1106418 39188 struct file *file = NULL, *old_file;
5527c038 39189+ struct file *f, *virt_file = NULL, *old_virt_file;
5527c038 39190 int error;
ba1aed25 39191 bool partscan;
5527c038 39192
42a736d3 39193@@ -720,12 +730,19 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
cd7a4cd9
AM
39194 file = fget(arg);
39195 if (!file)
e1106418 39196 goto out_err;
5527c038
JR
39197+ f = loop_real_file(file);
39198+ if (f) {
39199+ virt_file = file;
39200+ file = f;
39201+ get_file(file);
39202+ }
39203
cd7a4cd9
AM
39204 error = loop_validate_file(file, bdev);
39205 if (error)
e1106418 39206 goto out_err;
cd7a4cd9 39207
5527c038
JR
39208 old_file = lo->lo_backing_file;
39209+ old_virt_file = lo->lo_backing_virt_file;
39210
39211 error = -EINVAL;
39212
42a736d3 39213@@ -737,6 +754,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
8b6a4947
AM
39214 blk_mq_freeze_queue(lo->lo_queue);
39215 mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask);
39216 lo->lo_backing_file = file;
39217+ lo->lo_backing_virt_file = virt_file;
39218 lo->old_gfp_mask = mapping_gfp_mask(file->f_mapping);
39219 mapping_set_gfp_mask(file->f_mapping,
39220 lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
42a736d3 39221@@ -750,6 +768,8 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
e1106418
JR
39222 * dependency.
39223 */
5527c038
JR
39224 fput(old_file);
39225+ if (old_virt_file)
39226+ fput(old_virt_file);
e1106418 39227 if (partscan)
c2c0f25c 39228 loop_reread_partitions(lo, bdev);
5527c038 39229 return 0;
42a736d3 39230@@ -758,6 +778,8 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
13f235e5 39231 mutex_unlock(&lo->lo_mutex);
e1106418
JR
39232 if (file)
39233 fput(file);
5527c038
JR
39234+ if (virt_file)
39235+ fput(virt_file);
5527c038
JR
39236 return error;
39237 }
e1106418 39238
42a736d3
AM
39239@@ -1084,7 +1106,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
39240 struct block_device *bdev,
39241 const struct loop_config *config)
5527c038 39242 {
062440b3 39243- struct file *file;
5527c038
JR
39244+ struct file *file, *f, *virt_file = NULL;
39245 struct inode *inode;
39246 struct address_space *mapping;
42a736d3
AM
39247 int error;
39248@@ -1099,6 +1121,12 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
39249 file = fget(config->fd);
5527c038
JR
39250 if (!file)
39251 goto out;
39252+ f = loop_real_file(file);
39253+ if (f) {
39254+ virt_file = file;
39255+ file = f;
39256+ get_file(file);
39257+ }
39258
fbc438ed
JR
39259 /*
39260 * If we don't hold exclusive handle for the device, upgrade to it
42a736d3 39261@@ -1153,6 +1181,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
f24b0ddd 39262 lo->use_dio = lo->lo_flags & LO_FLAGS_DIRECT_IO;
5527c038 39263 lo->lo_device = bdev;
5527c038
JR
39264 lo->lo_backing_file = file;
39265+ lo->lo_backing_virt_file = virt_file;
f24b0ddd
JR
39266 lo->old_gfp_mask = mapping_gfp_mask(mapping);
39267 mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
39268
42a736d3
AM
39269@@ -1203,6 +1232,8 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
39270 bd_abort_claiming(bdev, loop_configure);
e1106418 39271 out_putf:
5527c038
JR
39272 fput(file);
39273+ if (virt_file)
39274+ fput(virt_file);
e1106418 39275 out:
5527c038
JR
39276 /* This is safe: open() is still holding a reference. */
39277 module_put(THIS_MODULE);
42a736d3 39278@@ -1212,6 +1243,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
ba1aed25 39279 static int __loop_clr_fd(struct loop_device *lo, bool release)
5527c038 39280 {
e1106418 39281 struct file *filp = NULL;
5527c038
JR
39282+ struct file *virt_filp = lo->lo_backing_virt_file;
39283 gfp_t gfp = lo->old_gfp_mask;
39284 struct block_device *bdev = lo->lo_device;
ba1aed25 39285 int err = 0;
0b2a12c6 39286@@ -1238,6 +1270,7 @@ static int __loop_clr_fd(struct loop_device *lo, bool release)
5527c038 39287
5527c038 39288 spin_lock_irq(&lo->lo_lock);
5527c038
JR
39289 lo->lo_backing_file = NULL;
39290+ lo->lo_backing_virt_file = NULL;
39291 spin_unlock_irq(&lo->lo_lock);
39292
39293 loop_release_xfer(lo);
0b2a12c6 39294@@ -1319,6 +1352,8 @@ static int __loop_clr_fd(struct loop_device *lo, bool release)
5527c038 39295 */
e1106418
JR
39296 if (filp)
39297 fput(filp);
5527c038
JR
39298+ if (virt_filp)
39299+ fput(virt_filp);
e1106418 39300 return err;
5527c038
JR
39301 }
39302
39303diff --git a/drivers/block/loop.h b/drivers/block/loop.h
0b2a12c6 39304index a3c04f310672e..161c3c5d1c22b 100644
5527c038
JR
39305--- a/drivers/block/loop.h
39306+++ b/drivers/block/loop.h
39307@@ -46,7 +46,7 @@ struct loop_device {
39308 int (*ioctl)(struct loop_device *, int cmd,
39309 unsigned long arg);
39310
39311- struct file * lo_backing_file;
43982f53 39312+ struct file *lo_backing_file, *lo_backing_virt_file;
5527c038 39313 struct block_device *lo_device;
5527c038 39314 void *key_data;
8b6a4947 39315
5527c038 39316diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c
0b2a12c6 39317index 9f58ba0cb769f..1c2267a5a2ae1 100644
5527c038
JR
39318--- a/fs/aufs/f_op.c
39319+++ b/fs/aufs/f_op.c
42a736d3 39320@@ -304,7 +304,7 @@ static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter)
5527c038
JR
39321 if (IS_ERR(h_file))
39322 goto out;
39323
39324- if (au_test_loopback_kthread()) {
39325+ if (0 && au_test_loopback_kthread()) {
39326 au_warn_loopback(h_file->f_path.dentry->d_sb);
39327 if (file->f_mapping != h_file->f_mapping) {
39328 file->f_mapping = h_file->f_mapping;
39329diff --git a/fs/aufs/loop.c b/fs/aufs/loop.c
42b5c33a 39330index a8b63acc62045..9d97c3af5686a 100644
5527c038
JR
39331--- a/fs/aufs/loop.c
39332+++ b/fs/aufs/loop.c
2121bcd9 39333@@ -133,3 +133,19 @@ void au_loopback_fin(void)
79b8bda9 39334 symbol_put(loop_backing_file);
9f237c51 39335 au_kfree_try_rcu(au_warn_loopback_array);
5527c038
JR
39336 }
39337+
39338+/* ---------------------------------------------------------------------- */
39339+
39340+/* support the loopback block device insude aufs */
39341+
39342+struct file *aufs_real_loop(struct file *file)
39343+{
39344+ struct file *f;
39345+
39346+ BUG_ON(!au_test_aufs(file->f_path.dentry->d_sb));
39347+ fi_read_lock(file);
39348+ f = au_hf_top(file);
39349+ fi_read_unlock(file);
39350+ AuDebugOn(!f);
39351+ return f;
39352+}
39353diff --git a/fs/aufs/loop.h b/fs/aufs/loop.h
42b5c33a 39354index 94f4f80ae33bf..ca1194354aff4 100644
5527c038
JR
39355--- a/fs/aufs/loop.h
39356+++ b/fs/aufs/loop.h
eca801bf 39357@@ -26,6 +26,8 @@ void au_warn_loopback(struct super_block *h_sb);
5527c038
JR
39358
39359 int au_loopback_init(void);
39360 void au_loopback_fin(void);
39361+
39362+struct file *aufs_real_loop(struct file *file);
39363 #else
83b672a5 39364 AuStub(struct file *, loop_backing_file, return NULL, struct super_block *sb)
eca801bf
AM
39365
39366@@ -36,6 +38,8 @@ AuStubVoid(au_warn_loopback, struct super_block *h_sb)
5527c038
JR
39367
39368 AuStubInt0(au_loopback_init, void)
39369 AuStubVoid(au_loopback_fin, void)
39370+
39371+AuStub(struct file *, aufs_real_loop, return NULL, struct file *file)
39372 #endif /* BLK_DEV_LOOP */
39373
39374 #endif /* __KERNEL__ */
39375diff --git a/fs/aufs/super.c b/fs/aufs/super.c
0b2a12c6 39376index d252963a87b53..ecfc5fc96ad8c 100644
5527c038
JR
39377--- a/fs/aufs/super.c
39378+++ b/fs/aufs/super.c
fbc438ed 39379@@ -844,7 +844,10 @@ static const struct super_operations aufs_sop = {
5527c038
JR
39380 .statfs = aufs_statfs,
39381 .put_super = aufs_put_super,
39382 .sync_fs = aufs_sync_fs,
39383- .remount_fs = aufs_remount_fs
39384+ .remount_fs = aufs_remount_fs,
39385+#ifdef CONFIG_AUFS_BDEV_LOOP
39386+ .real_loop = aufs_real_loop
39387+#endif
39388 };
39389
39390 /* ---------------------------------------------------------------------- */
39391diff --git a/include/linux/fs.h b/include/linux/fs.h
0b2a12c6 39392index 4fa4b24535fde..2aec4bc9f5aa1 100644
5527c038
JR
39393--- a/include/linux/fs.h
39394+++ b/include/linux/fs.h
0b2a12c6 39395@@ -2041,6 +2041,10 @@ struct super_operations {
5527c038
JR
39396 struct shrink_control *);
39397 long (*free_cached_objects)(struct super_block *,
39398 struct shrink_control *);
43982f53 39399+#if IS_ENABLED(CONFIG_BLK_DEV_LOOP) || IS_ENABLED(CONFIG_BLK_DEV_LOOP_MODULE)
5527c038
JR
39400+ /* and aufs */
39401+ struct file *(*real_loop)(struct file *);
39402+#endif
39403 };
39404
39405 /*
This page took 7.424566 seconds and 4 git commands to generate.