]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs5.patch
Up to 5.15.72.
[packages/kernel.git] / kernel-aufs5.patch
CommitLineData
2121bcd9 1SPDX-License-Identifier: GPL-2.0
319657f6 2aufs5.15.5 kbuild patch
7f207e10 3
fbc438ed 4diff --git a/fs/Kconfig b/fs/Kconfig
758e9dad 5index a6313a969bc5f..aca4b89d41a14 100644
fbc438ed
JR
6--- a/fs/Kconfig
7+++ b/fs/Kconfig
758e9dad 8@@ -312,6 +312,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
758e9dad 17index 84c5e4cdfee5a..b4fcdad8412ed 100644
7f207e10
AM
18--- a/fs/Makefile
19+++ b/fs/Makefile
758e9dad 20@@ -138,3 +138,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
319657f6 26aufs5.15.5 base patch
7f207e10 27
c1595e42 28diff --git a/MAINTAINERS b/MAINTAINERS
614c9df0 29index 3b79fd441dde8..3fb0a57f61b05 100644
c1595e42
JR
30--- a/MAINTAINERS
31+++ b/MAINTAINERS
758e9dad 32@@ -3122,6 +3122,19 @@ F: include/uapi/linux/audit.h
c1595e42 33 F: kernel/audit*
46016270 34 F: lib/*audit.c
c1595e42
JR
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
319657f6 53index dfc72a1f6500d..c9d1ef703673c 100644
392086de
AM
54--- a/drivers/block/loop.c
55+++ b/drivers/block/loop.c
319657f6 56@@ -798,6 +798,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
46016270 82index cf871a81f4fdc..bc5095b734f58 100644
c1595e42
JR
83--- a/fs/dcache.c
84+++ b/fs/dcache.c
46016270 85@@ -1320,7 +1320,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
758e9dad 95index 9c6c6a3e2de51..02382fa9bd341 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
8b6a4947 116diff --git a/fs/namespace.c b/fs/namespace.c
758e9dad 117index 659a8f39c61af..1283670737826 100644
8b6a4947
AM
118--- a/fs/namespace.c
119+++ b/fs/namespace.c
758e9dad 120@@ -808,6 +808,12 @@ static inline int check_mnt(struct mount *mnt)
8b6a4947
AM
121 return mnt->mnt_ns == current->nsproxy->mnt_ns;
122 }
123
124+/* for aufs, CONFIG_AUFS_BR_FUSE */
125+int is_current_mnt_ns(struct vfsmount *mnt)
126+{
127+ return check_mnt(real_mount(mnt));
128+}
129+
130 /*
131 * vfsmount lock must be held for write
132 */
7f207e10 133diff --git a/fs/splice.c b/fs/splice.c
0b2a12c6 134index 5dbce4dcc1a7d..3e6ba363b7775 100644
7f207e10
AM
135--- a/fs/splice.c
136+++ b/fs/splice.c
0b2a12c6 137@@ -759,8 +759,8 @@ static int warn_unsupported(struct file *file, const char *op)
7f207e10
AM
138 /*
139 * Attempt to initiate a splice from pipe to file.
140 */
141-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
142- loff_t *ppos, size_t len, unsigned int flags)
143+long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
144+ loff_t *ppos, size_t len, unsigned int flags)
145 {
42a736d3
AM
146 if (unlikely(!out->f_op->splice_write))
147 return warn_unsupported(out, "write");
0b2a12c6 148@@ -770,9 +770,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
7f207e10
AM
149 /*
150 * Attempt to initiate a splice from a file to a pipe.
151 */
152-static long do_splice_to(struct file *in, loff_t *ppos,
153- struct pipe_inode_info *pipe, size_t len,
154- unsigned int flags)
155+long do_splice_to(struct file *in, loff_t *ppos,
156+ struct pipe_inode_info *pipe, size_t len,
157+ unsigned int flags)
158 {
13f235e5 159 unsigned int p_space;
42a736d3 160 int ret;
5527c038 161diff --git a/include/linux/fs.h b/include/linux/fs.h
319657f6 162index 56eba723477e3..e60d8ad854004 100644
5527c038
JR
163--- a/include/linux/fs.h
164+++ b/include/linux/fs.h
758e9dad 165@@ -1381,6 +1381,7 @@ extern void fasync_free(struct fasync_struct *);
febd17d6
JR
166 /* can be called from interrupts */
167 extern void kill_fasync(struct fasync_struct **, int, int);
168
43982f53 169+extern int setfl(int fd, struct file *filp, unsigned long arg);
febd17d6 170 extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int force);
3c1bdaff 171 extern int f_setown(struct file *filp, unsigned long arg, int force);
febd17d6 172 extern void f_delown(struct file *filp);
758e9dad 173@@ -2092,6 +2093,7 @@ struct file_operations {
febd17d6
JR
174 ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
175 unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
176 int (*check_flags)(int);
177+ int (*setfl)(struct file *, unsigned long);
178 int (*flock) (struct file *, int, struct file_lock *);
179 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
180 ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
319657f6
AM
181@@ -2615,6 +2617,7 @@ extern int current_umask(void);
182 extern void ihold(struct inode * inode);
183 extern void iput(struct inode *);
184 extern int generic_update_time(struct inode *, struct timespec64 *, int);
185+extern int update_time(struct inode *, struct timespec64 *, int);
186
187 /* /sys/fs */
188 extern struct kobject *fs_kobj;
8b6a4947 189diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
758e9dad 190index 9fe165beb0f9e..e47f7e15eeaf7 100644
8b6a4947
AM
191--- a/include/linux/lockdep.h
192+++ b/include/linux/lockdep.h
0b2a12c6 193@@ -248,6 +248,8 @@ static inline int lockdep_match_key(struct lockdep_map *lock,
8b6a4947
AM
194 return lock->key == key;
195 }
196
197+struct lock_class *lockdep_hlock_class(struct held_lock *hlock);
198+
199 /*
200 * Acquire a lock.
201 *
8b6a4947 202diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
42a736d3 203index 8f882f5881e87..6b9808f098435 100644
8b6a4947
AM
204--- a/include/linux/mnt_namespace.h
205+++ b/include/linux/mnt_namespace.h
42a736d3 206@@ -7,12 +7,15 @@ struct mnt_namespace;
8b6a4947
AM
207 struct fs_struct;
208 struct user_namespace;
f24b0ddd 209 struct ns_common;
8b6a4947
AM
210+struct vfsmount;
211
212 extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
213 struct user_namespace *, struct fs_struct *);
214 extern void put_mnt_ns(struct mnt_namespace *ns);
f24b0ddd 215 extern struct ns_common *from_mnt_ns(struct mnt_namespace *);
8b6a4947
AM
216
217+extern int is_current_mnt_ns(struct vfsmount *mnt);
218+
219 extern const struct file_operations proc_mounts_operations;
220 extern const struct file_operations proc_mountinfo_operations;
221 extern const struct file_operations proc_mountstats_operations;
1e00d052 222diff --git a/include/linux/splice.h b/include/linux/splice.h
42a736d3 223index a55179fd60fc3..8e21c53cf8831 100644
1e00d052
AM
224--- a/include/linux/splice.h
225+++ b/include/linux/splice.h
42a736d3 226@@ -93,4 +93,10 @@ extern void splice_shrink_spd(struct splice_pipe_desc *);
4b3da204
AM
227
228 extern const struct pipe_buf_operations page_cache_pipe_buf_ops;
106341ce 229 extern const struct pipe_buf_operations default_pipe_buf_ops;
1e00d052
AM
230+
231+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
232+ loff_t *ppos, size_t len, unsigned int flags);
233+extern long do_splice_to(struct file *in, loff_t *ppos,
234+ struct pipe_inode_info *pipe, size_t len,
235+ unsigned int flags);
236 #endif
8b6a4947 237diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
319657f6 238index d624231eab2bb..eff2ca26e6c58 100644
8b6a4947
AM
239--- a/kernel/locking/lockdep.c
240+++ b/kernel/locking/lockdep.c
46016270 241@@ -189,7 +189,7 @@ static
9f237c51 242 struct lock_class lock_classes[MAX_LOCKDEP_KEYS];
4df42b26 243 DECLARE_BITMAP(lock_classes_in_use, MAX_LOCKDEP_KEYS);
8b6a4947
AM
244
245-static inline struct lock_class *hlock_class(struct held_lock *hlock)
246+inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock)
247 {
eca34b5c
AM
248 unsigned int class_idx = hlock->class_idx;
249
46016270 250@@ -210,6 +210,7 @@ static inline struct lock_class *hlock_class(struct held_lock *hlock)
eca34b5c
AM
251 */
252 return lock_classes + class_idx;
8b6a4947
AM
253 }
254+#define hlock_class(hlock) lockdep_hlock_class(hlock)
255
256 #ifdef CONFIG_LOCK_STAT
257 static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], cpu_lock_stats);
2121bcd9 258SPDX-License-Identifier: GPL-2.0
319657f6 259aufs5.15.5 mmap patch
fb47a38f 260
c1595e42 261diff --git a/fs/proc/base.c b/fs/proc/base.c
319657f6 262index 1f394095eb880..93f2479ef319e 100644
c1595e42
JR
263--- a/fs/proc/base.c
264+++ b/fs/proc/base.c
319657f6 265@@ -2189,7 +2189,7 @@ static int map_files_get_link(struct dentry *dentry, struct path *path)
eca34b5c 266 rc = -ENOENT;
c1595e42
JR
267 vma = find_exact_vma(mm, vm_start, vm_end);
268 if (vma && vma->vm_file) {
269- *path = vma->vm_file->f_path;
270+ *path = vma_pr_or_file(vma)->f_path;
271 path_get(path);
272 rc = 0;
273 }
fb47a38f 274diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c
42a736d3 275index 13452b32e2bd5..38acccfef9d49 100644
fb47a38f
JR
276--- a/fs/proc/nommu.c
277+++ b/fs/proc/nommu.c
42a736d3 278@@ -40,7 +40,10 @@ static int nommu_region_show(struct seq_file *m, struct vm_region *region)
fb47a38f
JR
279 file = region->vm_file;
280
281 if (file) {
282- struct inode *inode = file_inode(region->vm_file);
283+ struct inode *inode;
076b876e 284+
fb47a38f
JR
285+ file = vmr_pr_or_file(region);
286+ inode = file_inode(file);
287 dev = inode->i_sb->s_dev;
288 ino = inode->i_ino;
289 }
290diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
758e9dad 291index cf25be3e03212..70af1c25ffa22 100644
fb47a38f
JR
292--- a/fs/proc/task_mmu.c
293+++ b/fs/proc/task_mmu.c
42b5c33a 294@@ -280,7 +280,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
fb47a38f
JR
295 const char *name = NULL;
296
297 if (file) {
298- struct inode *inode = file_inode(vma->vm_file);
299+ struct inode *inode;
076b876e 300+
fb47a38f
JR
301+ file = vma_pr_or_file(vma);
302+ inode = file_inode(file);
303 dev = inode->i_sb->s_dev;
304 ino = inode->i_ino;
305 pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
758e9dad 306@@ -1865,7 +1868,7 @@ static int show_numa_map(struct seq_file *m, void *v)
076b876e
AM
307 struct proc_maps_private *proc_priv = &numa_priv->proc_maps;
308 struct vm_area_struct *vma = v;
309 struct numa_maps *md = &numa_priv->md;
310- struct file *file = vma->vm_file;
311+ struct file *file = vma_pr_or_file(vma);
076b876e 312 struct mm_struct *mm = vma->vm_mm;
43982f53
AM
313 struct mempolicy *pol;
314 char buffer[64];
fb47a38f 315diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
42a736d3 316index a6d21fc0033c6..02c2de31196e0 100644
fb47a38f
JR
317--- a/fs/proc/task_nommu.c
318+++ b/fs/proc/task_nommu.c
acd2b654 319@@ -155,7 +155,10 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
fb47a38f
JR
320 file = vma->vm_file;
321
322 if (file) {
323- struct inode *inode = file_inode(vma->vm_file);
324+ struct inode *inode;
076b876e 325+
b912730e 326+ file = vma_pr_or_file(vma);
fb47a38f
JR
327+ inode = file_inode(file);
328 dev = inode->i_sb->s_dev;
329 ino = inode->i_ino;
330 pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
331diff --git a/include/linux/mm.h b/include/linux/mm.h
758e9dad 332index 73a52aba448f9..5dd42acf0707b 100644
fb47a38f
JR
333--- a/include/linux/mm.h
334+++ b/include/linux/mm.h
758e9dad 335@@ -1806,6 +1806,28 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping,
a3232e84 336 unmap_mapping_range(mapping, holebegin, holelen, 0);
fb47a38f 337 }
fb47a38f 338
076b876e
AM
339+extern void vma_do_file_update_time(struct vm_area_struct *, const char[], int);
340+extern struct file *vma_do_pr_or_file(struct vm_area_struct *, const char[],
f2c43d5f 341+ int);
076b876e
AM
342+extern void vma_do_get_file(struct vm_area_struct *, const char[], int);
343+extern void vma_do_fput(struct vm_area_struct *, const char[], int);
fb47a38f 344+
f2c43d5f
AM
345+#define vma_file_update_time(vma) vma_do_file_update_time(vma, __func__, \
346+ __LINE__)
347+#define vma_pr_or_file(vma) vma_do_pr_or_file(vma, __func__, \
348+ __LINE__)
349+#define vma_get_file(vma) vma_do_get_file(vma, __func__, __LINE__)
350+#define vma_fput(vma) vma_do_fput(vma, __func__, __LINE__)
b912730e
AM
351+
352+#ifndef CONFIG_MMU
076b876e
AM
353+extern struct file *vmr_do_pr_or_file(struct vm_region *, const char[], int);
354+extern void vmr_do_fput(struct vm_region *, const char[], int);
355+
f2c43d5f
AM
356+#define vmr_pr_or_file(region) vmr_do_pr_or_file(region, __func__, \
357+ __LINE__)
358+#define vmr_fput(region) vmr_do_fput(region, __func__, __LINE__)
b912730e 359+#endif /* !CONFIG_MMU */
fb47a38f 360+
a3232e84
JR
361 extern int access_process_vm(struct task_struct *tsk, unsigned long addr,
362 void *buf, int len, unsigned int gup_flags);
fb47a38f 363 extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
fb47a38f 364diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
758e9dad 365index 7f8ee09c711f4..3a9a798a4ae1f 100644
fb47a38f
JR
366--- a/include/linux/mm_types.h
367+++ b/include/linux/mm_types.h
758e9dad 368@@ -294,6 +294,7 @@ struct vm_region {
fb47a38f
JR
369 unsigned long vm_top; /* region allocated to here */
370 unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */
371 struct file *vm_file; /* the backing file or NULL */
372+ struct file *vm_prfile; /* the virtual backing file or NULL */
373
374 int vm_usage; /* region usage count (access under nommu_region_sem) */
375 bool vm_icache_flushed : 1; /* true if the icache has been flushed for
758e9dad 376@@ -373,6 +374,7 @@ struct vm_area_struct {
fb47a38f 377 unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE
5afbbe0d 378 units */
fb47a38f
JR
379 struct file * vm_file; /* File we map to (can be NULL). */
380+ struct file *vm_prfile; /* shadow of vm_file */
381 void * vm_private_data; /* was vm_pte (shared mem) */
382
eca34b5c 383 #ifdef CONFIG_SWAP
fb47a38f 384diff --git a/kernel/fork.c b/kernel/fork.c
319657f6 385index 10885c649ca42..f3a9cd12011b3 100644
fb47a38f
JR
386--- a/kernel/fork.c
387+++ b/kernel/fork.c
758e9dad
AM
388@@ -573,7 +573,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
389 if (file) {
fb47a38f
JR
390 struct address_space *mapping = file->f_mapping;
391
392- get_file(file);
393+ vma_get_file(tmp);
2000de60 394 i_mmap_lock_write(mapping);
758e9dad
AM
395 if (tmp->vm_flags & VM_SHARED)
396 mapping_allow_writable(mapping);
076b876e 397diff --git a/mm/Makefile b/mm/Makefile
758e9dad 398index fc60a40ce954b..c715b0138237b 100644
076b876e
AM
399--- a/mm/Makefile
400+++ b/mm/Makefile
42a736d3
AM
401@@ -52,7 +52,7 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \
402 mm_init.o percpu.o slab_common.o \
b00004a5 403 compaction.o vmacache.o \
076b876e 404 interval_tree.o list_lru.o workingset.o \
42a736d3
AM
405- debug.o gup.o mmap_lock.o $(mmu-y)
406+ prfile.o debug.o gup.o mmap_lock.o $(mmu-y)
076b876e 407
fbc438ed
JR
408 # Give 'page_alloc' its own module-parameter namespace
409 page-alloc-y := page_alloc.o
fb47a38f 410diff --git a/mm/filemap.c b/mm/filemap.c
319657f6 411index 82a17c35eb96b..348e22067abdc 100644
fb47a38f
JR
412--- a/mm/filemap.c
413+++ b/mm/filemap.c
319657f6 414@@ -3349,7 +3349,7 @@ vm_fault_t filemap_page_mkwrite(struct vm_fault *vmf)
cd7a4cd9 415 vm_fault_t ret = VM_FAULT_LOCKED;
fb47a38f 416
42a736d3 417 sb_start_pagefault(mapping->host->i_sb);
521ced18
JR
418- file_update_time(vmf->vma->vm_file);
419+ vma_file_update_time(vmf->vma);
fb47a38f 420 lock_page(page);
42a736d3 421 if (page->mapping != mapping) {
fb47a38f 422 unlock_page(page);
fb47a38f 423diff --git a/mm/mmap.c b/mm/mmap.c
758e9dad 424index 88dcc5c252255..6c276614ca962 100644
fb47a38f
JR
425--- a/mm/mmap.c
426+++ b/mm/mmap.c
758e9dad 427@@ -183,7 +183,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma)
fb47a38f
JR
428 if (vma->vm_ops && vma->vm_ops->close)
429 vma->vm_ops->close(vma);
430 if (vma->vm_file)
431- fput(vma->vm_file);
432+ vma_fput(vma);
433 mpol_put(vma_policy(vma));
cd7a4cd9 434 vm_area_free(vma);
fb47a38f 435 return next;
758e9dad 436@@ -952,7 +952,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
fb47a38f
JR
437 if (remove_next) {
438 if (file) {
439 uprobe_munmap(next, next->vm_start, next->vm_end);
440- fput(file);
441+ vma_fput(vma);
442 }
443 if (next->anon_vma)
444 anon_vma_merge(vma, next);
758e9dad 445@@ -1873,7 +1873,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
35939ee7
JR
446 return addr;
447
fb47a38f 448 unmap_and_free_vma:
42a736d3 449- fput(vma->vm_file);
fb47a38f
JR
450+ vma_fput(vma);
451 vma->vm_file = NULL;
fb47a38f
JR
452
453 /* Undo any partial mapping done by a device driver. */
758e9dad 454@@ -2731,7 +2731,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
fb47a38f
JR
455 goto out_free_mpol;
456
457 if (new->vm_file)
458- get_file(new->vm_file);
459+ vma_get_file(new);
460
461 if (new->vm_ops && new->vm_ops->open)
462 new->vm_ops->open(new);
758e9dad 463@@ -2750,7 +2750,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
fb47a38f
JR
464 if (new->vm_ops && new->vm_ops->close)
465 new->vm_ops->close(new);
466 if (new->vm_file)
467- fput(new->vm_file);
468+ vma_fput(new);
469 unlink_anon_vmas(new);
470 out_free_mpol:
471 mpol_put(vma_policy(new));
758e9dad 472@@ -2945,7 +2945,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
7e9cd9fe
AM
473 struct vm_area_struct *vma;
474 unsigned long populate = 0;
475 unsigned long ret = -EINVAL;
476- struct file *file;
5afbbe0d 477+ struct file *file, *prfile;
7e9cd9fe 478
cd7a4cd9 479 pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/vm/remap_file_pages.rst.\n",
5afbbe0d 480 current->comm, current->pid);
758e9dad 481@@ -3001,10 +3001,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
46016270
AM
482 if (vma->vm_flags & VM_LOCKED)
483 flags |= MAP_LOCKED;
7e9cd9fe
AM
484
485- file = get_file(vma->vm_file);
486+ vma_get_file(vma);
5afbbe0d
AM
487+ file = vma->vm_file;
488+ prfile = vma->vm_prfile;
6803432e 489 ret = do_mmap(vma->vm_file, start, size,
521ced18 490 prot, flags, pgoff, &populate, NULL);
5afbbe0d
AM
491+ if (!IS_ERR_VALUE(ret) && file && prfile) {
492+ struct vm_area_struct *new_vma;
493+
494+ new_vma = find_vma(mm, ret);
495+ if (!new_vma->vm_prfile)
496+ new_vma->vm_prfile = prfile;
497+ if (new_vma != vma)
498+ get_file(prfile);
499+ }
500+ /*
501+ * two fput()s instead of vma_fput(vma),
502+ * coz vma may not be available anymore.
503+ */
504 fput(file);
505+ if (prfile)
506+ fput(prfile);
7e9cd9fe 507 out:
42a736d3 508 mmap_write_unlock(mm);
7e9cd9fe 509 if (populate)
758e9dad 510@@ -3285,7 +3302,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
79b8bda9
AM
511 if (anon_vma_clone(new_vma, vma))
512 goto out_free_mempol;
513 if (new_vma->vm_file)
514- get_file(new_vma->vm_file);
515+ vma_get_file(new_vma);
516 if (new_vma->vm_ops && new_vma->vm_ops->open)
517 new_vma->vm_ops->open(new_vma);
518 vma_link(mm, new_vma, prev, rb_link, rb_parent);
fb47a38f 519diff --git a/mm/nommu.c b/mm/nommu.c
758e9dad 520index 02d2427b8f9e8..a7419302ab4ed 100644
fb47a38f
JR
521--- a/mm/nommu.c
522+++ b/mm/nommu.c
46016270 523@@ -523,7 +523,7 @@ static void __put_nommu_region(struct vm_region *region)
fb47a38f
JR
524 up_write(&nommu_region_sem);
525
526 if (region->vm_file)
527- fput(region->vm_file);
528+ vmr_fput(region);
529
530 /* IO memory and memory shared directly out of the pagecache
531 * from ramfs/tmpfs mustn't be released here */
46016270 532@@ -655,7 +655,7 @@ static void delete_vma(struct mm_struct *mm, struct vm_area_struct *vma)
fb47a38f
JR
533 if (vma->vm_ops && vma->vm_ops->close)
534 vma->vm_ops->close(vma);
535 if (vma->vm_file)
536- fput(vma->vm_file);
537+ vma_fput(vma);
538 put_nommu_region(vma->vm_region);
cd7a4cd9 539 vm_area_free(vma);
fb47a38f 540 }
758e9dad 541@@ -1175,7 +1175,7 @@ unsigned long do_mmap(struct file *file,
fb47a38f
JR
542 goto error_just_free;
543 }
544 }
545- fput(region->vm_file);
546+ vmr_fput(region);
547 kmem_cache_free(vm_region_jar, region);
548 region = pregion;
549 result = start;
758e9dad 550@@ -1252,10 +1252,10 @@ unsigned long do_mmap(struct file *file,
fb47a38f
JR
551 up_write(&nommu_region_sem);
552 error:
553 if (region->vm_file)
554- fput(region->vm_file);
555+ vmr_fput(region);
556 kmem_cache_free(vm_region_jar, region);
557 if (vma->vm_file)
eca801bf
AM
558- fput(vma->vm_file);
559+ vma_fput(vma);
560 vm_area_free(vma);
561 return ret;
562
076b876e
AM
563diff --git a/mm/prfile.c b/mm/prfile.c
564new file mode 100644
6d176551 565index 0000000000000..511543ab1b418
076b876e
AM
566--- /dev/null
567+++ b/mm/prfile.c
2121bcd9 568@@ -0,0 +1,86 @@
cd7a4cd9 569+// SPDX-License-Identifier: GPL-2.0
076b876e 570+/*
1c60b727
AM
571+ * Mainly for aufs which mmap(2) different file and wants to print different
572+ * path in /proc/PID/maps.
076b876e
AM
573+ * Call these functions via macros defined in linux/mm.h.
574+ *
575+ * See Documentation/filesystems/aufs/design/06mmap.txt
576+ *
6d176551 577+ * Copyright (c) 2014-2021 Junjro R. Okajima
076b876e
AM
578+ * Copyright (c) 2014 Ian Campbell
579+ */
580+
581+#include <linux/mm.h>
582+#include <linux/file.h>
583+#include <linux/fs.h>
584+
585+/* #define PRFILE_TRACE */
586+static inline void prfile_trace(struct file *f, struct file *pr,
587+ const char func[], int line, const char func2[])
588+{
589+#ifdef PRFILE_TRACE
590+ if (pr)
1c60b727 591+ pr_info("%s:%d: %s, %pD2\n", func, line, func2, f);
076b876e
AM
592+#endif
593+}
594+
076b876e
AM
595+void vma_do_file_update_time(struct vm_area_struct *vma, const char func[],
596+ int line)
597+{
598+ struct file *f = vma->vm_file, *pr = vma->vm_prfile;
599+
600+ prfile_trace(f, pr, func, line, __func__);
601+ file_update_time(f);
602+ if (f && pr)
603+ file_update_time(pr);
604+}
605+
606+struct file *vma_do_pr_or_file(struct vm_area_struct *vma, const char func[],
607+ int line)
608+{
609+ struct file *f = vma->vm_file, *pr = vma->vm_prfile;
610+
611+ prfile_trace(f, pr, func, line, __func__);
612+ return (f && pr) ? pr : f;
613+}
614+
615+void vma_do_get_file(struct vm_area_struct *vma, const char func[], int line)
616+{
617+ struct file *f = vma->vm_file, *pr = vma->vm_prfile;
618+
619+ prfile_trace(f, pr, func, line, __func__);
620+ get_file(f);
621+ if (f && pr)
622+ get_file(pr);
623+}
624+
625+void vma_do_fput(struct vm_area_struct *vma, const char func[], int line)
626+{
627+ struct file *f = vma->vm_file, *pr = vma->vm_prfile;
628+
629+ prfile_trace(f, pr, func, line, __func__);
630+ fput(f);
631+ if (f && pr)
632+ fput(pr);
633+}
b912730e
AM
634+
635+#ifndef CONFIG_MMU
076b876e
AM
636+struct file *vmr_do_pr_or_file(struct vm_region *region, const char func[],
637+ int line)
638+{
639+ struct file *f = region->vm_file, *pr = region->vm_prfile;
640+
641+ prfile_trace(f, pr, func, line, __func__);
642+ return (f && pr) ? pr : f;
643+}
644+
645+void vmr_do_fput(struct vm_region *region, const char func[], int line)
646+{
647+ struct file *f = region->vm_file, *pr = region->vm_prfile;
648+
649+ prfile_trace(f, pr, func, line, __func__);
650+ fput(f);
651+ if (f && pr)
652+ fput(pr);
653+}
b912730e 654+#endif /* !CONFIG_MMU */
2121bcd9 655SPDX-License-Identifier: GPL-2.0
319657f6 656aufs5.15.5 standalone patch
7f207e10 657
c1595e42 658diff --git a/fs/dcache.c b/fs/dcache.c
46016270 659index bc5095b734f58..9508bd57a3bc0 100644
c1595e42
JR
660--- a/fs/dcache.c
661+++ b/fs/dcache.c
46016270 662@@ -1425,6 +1425,7 @@ void d_walk(struct dentry *parent, void *data,
c1595e42
JR
663 seq = 1;
664 goto again;
665 }
febd17d6 666+EXPORT_SYMBOL_GPL(d_walk);
c1595e42 667
a2654f78
AM
668 struct check_mount {
669 struct vfsmount *mnt;
46016270 670@@ -2970,6 +2971,7 @@ void d_exchange(struct dentry *dentry1, struct dentry *dentry2)
f2c43d5f
AM
671
672 write_sequnlock(&rename_lock);
673 }
674+EXPORT_SYMBOL_GPL(d_exchange);
675
676 /**
677 * d_ancestor - search for an ancestor
79b8bda9 678diff --git a/fs/exec.c b/fs/exec.c
319657f6 679index ac7b51b51f38a..52a8be4ebc1e1 100644
79b8bda9
AM
680--- a/fs/exec.c
681+++ b/fs/exec.c
6d176551 682@@ -111,6 +111,7 @@ bool path_noexec(const struct path *path)
79b8bda9
AM
683 return (path->mnt->mnt_flags & MNT_NOEXEC) ||
684 (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC);
685 }
febd17d6 686+EXPORT_SYMBOL_GPL(path_noexec);
79b8bda9
AM
687
688 #ifdef CONFIG_USELIB
689 /*
febd17d6 690diff --git a/fs/fcntl.c b/fs/fcntl.c
758e9dad 691index 02382fa9bd341..3418c60b90146 100644
febd17d6
JR
692--- a/fs/fcntl.c
693+++ b/fs/fcntl.c
0b2a12c6 694@@ -86,6 +86,7 @@ int setfl(int fd, struct file *filp, unsigned long arg)
febd17d6
JR
695 out:
696 return error;
697 }
698+EXPORT_SYMBOL_GPL(setfl);
699
700 static void f_modown(struct file *filp, struct pid *pid, enum pid_type type,
701 int force)
b912730e 702diff --git a/fs/file_table.c b/fs/file_table.c
42a736d3 703index 45437f8e1003e..786af52904fcf 100644
b912730e
AM
704--- a/fs/file_table.c
705+++ b/fs/file_table.c
42a736d3 706@@ -161,6 +161,7 @@ struct file *alloc_empty_file(int flags, const struct cred *cred)
b912730e
AM
707 }
708 return ERR_PTR(-ENFILE);
709 }
acd2b654 710+EXPORT_SYMBOL_GPL(alloc_empty_file);
b912730e 711
acd2b654
AM
712 /*
713 * Variant of alloc_empty_file() that doesn't check and modify nr_files.
7f207e10 714diff --git a/fs/namespace.c b/fs/namespace.c
758e9dad 715index 1283670737826..db99365620118 100644
7f207e10
AM
716--- a/fs/namespace.c
717+++ b/fs/namespace.c
758e9dad 718@@ -439,6 +439,7 @@ void __mnt_drop_write(struct vfsmount *mnt)
c06a8ce3
AM
719 mnt_dec_writers(real_mount(mnt));
720 preempt_enable();
721 }
722+EXPORT_SYMBOL_GPL(__mnt_drop_write);
723
724 /**
725 * mnt_drop_write - give up write access to a mount
758e9dad 726@@ -813,6 +814,7 @@ int is_current_mnt_ns(struct vfsmount *mnt)
8b6a4947
AM
727 {
728 return check_mnt(real_mount(mnt));
729 }
730+EXPORT_SYMBOL_GPL(is_current_mnt_ns);
731
732 /*
733 * vfsmount lock must be held for write
758e9dad 734@@ -2011,6 +2013,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
7f207e10
AM
735 }
736 return 0;
737 }
febd17d6 738+EXPORT_SYMBOL_GPL(iterate_mounts);
7f207e10 739
fbc438ed 740 static void lock_mnt_tree(struct mount *mnt)
7f207e10 741 {
43982f53 742diff --git a/fs/notify/group.c b/fs/notify/group.c
46016270 743index fb89c351295d6..460ad19c2570a 100644
43982f53
AM
744--- a/fs/notify/group.c
745+++ b/fs/notify/group.c
42a736d3 746@@ -100,6 +100,7 @@ void fsnotify_get_group(struct fsnotify_group *group)
1716fcea 747 {
2121bcd9 748 refcount_inc(&group->refcnt);
1716fcea 749 }
febd17d6 750+EXPORT_SYMBOL_GPL(fsnotify_get_group);
1716fcea
AM
751
752 /*
753 * Drop a reference to a group. Free it if it's through.
7f207e10 754diff --git a/fs/open.c b/fs/open.c
319657f6 755index e0df1536eb69f..81b2d7c83addb 100644
7f207e10
AM
756--- a/fs/open.c
757+++ b/fs/open.c
0b2a12c6 758@@ -65,6 +65,7 @@ int do_truncate(struct user_namespace *mnt_userns, struct dentry *dentry,
febd17d6 759 inode_unlock(dentry->d_inode);
7f207e10
AM
760 return ret;
761 }
febd17d6 762+EXPORT_SYMBOL_GPL(do_truncate);
7f207e10 763
5afbbe0d 764 long vfs_truncate(const struct path *path, loff_t length)
7f207e10 765 {
5527c038 766diff --git a/fs/read_write.c b/fs/read_write.c
758e9dad 767index af057c57bdc64..76017f8331fbf 100644
5527c038
JR
768--- a/fs/read_write.c
769+++ b/fs/read_write.c
758e9dad 770@@ -492,6 +492,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
42a736d3 771 inc_syscr(current);
8b6a4947
AM
772 return ret;
773 }
774+EXPORT_SYMBOL_GPL(vfs_read);
775
776 static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
777 {
758e9dad 778@@ -602,6 +603,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
42a736d3 779 file_end_write(file);
8b6a4947
AM
780 return ret;
781 }
782+EXPORT_SYMBOL_GPL(vfs_write);
783
fbc438ed
JR
784 /* file_ppos returns &file->f_pos or NULL if file is stream */
785 static inline loff_t *file_ppos(struct file *file)
7f207e10 786diff --git a/fs/splice.c b/fs/splice.c
0b2a12c6 787index 3e6ba363b7775..7c1be373eb7cd 100644
7f207e10
AM
788--- a/fs/splice.c
789+++ b/fs/splice.c
0b2a12c6 790@@ -766,6 +766,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
42a736d3
AM
791 return warn_unsupported(out, "write");
792 return out->f_op->splice_write(pipe, out, ppos, len, flags);
7f207e10 793 }
febd17d6 794+EXPORT_SYMBOL_GPL(do_splice_from);
7f207e10
AM
795
796 /*
797 * Attempt to initiate a splice from a file to a pipe.
0b2a12c6 798@@ -795,6 +796,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
42a736d3
AM
799 return warn_unsupported(in, "read");
800 return in->f_op->splice_read(in, ppos, pipe, len, flags);
7f207e10 801 }
febd17d6 802+EXPORT_SYMBOL_GPL(do_splice_to);
7f207e10
AM
803
804 /**
805 * splice_direct_to_actor - splices data directly between two non-pipes
c1595e42 806diff --git a/fs/xattr.c b/fs/xattr.c
46016270 807index 5c8c5175b385c..ff7e9ff774b73 100644
c1595e42
JR
808--- a/fs/xattr.c
809+++ b/fs/xattr.c
46016270 810@@ -384,6 +384,7 @@ vfs_getxattr_alloc(struct user_namespace *mnt_userns, struct dentry *dentry,
c1595e42
JR
811 *xattr_value = value;
812 return error;
813 }
febd17d6 814+EXPORT_SYMBOL_GPL(vfs_getxattr_alloc);
c1595e42 815
febd17d6 816 ssize_t
f2c43d5f 817 __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
8b6a4947 818diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
319657f6 819index eff2ca26e6c58..0627584f7872a 100644
8b6a4947
AM
820--- a/kernel/locking/lockdep.c
821+++ b/kernel/locking/lockdep.c
46016270 822@@ -210,6 +210,7 @@ inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock)
eca34b5c
AM
823 */
824 return lock_classes + class_idx;
8b6a4947
AM
825 }
826+EXPORT_SYMBOL_GPL(lockdep_hlock_class);
827 #define hlock_class(hlock) lockdep_hlock_class(hlock)
828
829 #ifdef CONFIG_LOCK_STAT
8cdd5066 830diff --git a/kernel/task_work.c b/kernel/task_work.c
46016270 831index 1698fbe6f0e13..081b05acadf82 100644
8cdd5066
JR
832--- a/kernel/task_work.c
833+++ b/kernel/task_work.c
46016270 834@@ -167,3 +167,4 @@ void task_work_run(void)
8cdd5066
JR
835 } while (work);
836 }
837 }
febd17d6 838+EXPORT_SYMBOL_GPL(task_work_run);
7f207e10 839diff --git a/security/security.c b/security/security.c
319657f6 840index 67264cb08fb31..0d78065d71fe1 100644
7f207e10
AM
841--- a/security/security.c
842+++ b/security/security.c
6d176551 843@@ -1147,6 +1147,7 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry)
7f207e10 844 return 0;
c2c0f25c 845 return call_int_hook(path_rmdir, 0, dir, dentry);
7f207e10 846 }
febd17d6 847+EXPORT_SYMBOL_GPL(security_path_rmdir);
7f207e10 848
5afbbe0d 849 int security_path_unlink(const struct path *dir, struct dentry *dentry)
7f207e10 850 {
6d176551 851@@ -1163,6 +1164,7 @@ int security_path_symlink(const struct path *dir, struct dentry *dentry,
7f207e10 852 return 0;
c2c0f25c 853 return call_int_hook(path_symlink, 0, dir, dentry, old_name);
7f207e10 854 }
febd17d6 855+EXPORT_SYMBOL_GPL(security_path_symlink);
7f207e10 856
5afbbe0d 857 int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
7f207e10 858 struct dentry *new_dentry)
6d176551 859@@ -1171,6 +1173,7 @@ int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
7f207e10 860 return 0;
c2c0f25c 861 return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry);
7f207e10 862 }
febd17d6 863+EXPORT_SYMBOL_GPL(security_path_link);
7f207e10 864
5afbbe0d
AM
865 int security_path_rename(const struct path *old_dir, struct dentry *old_dentry,
866 const struct path *new_dir, struct dentry *new_dentry,
6d176551 867@@ -1198,6 +1201,7 @@ int security_path_truncate(const struct path *path)
7f207e10 868 return 0;
c2c0f25c 869 return call_int_hook(path_truncate, 0, path);
7f207e10 870 }
febd17d6 871+EXPORT_SYMBOL_GPL(security_path_truncate);
7f207e10 872
5afbbe0d 873 int security_path_chmod(const struct path *path, umode_t mode)
7eafdf33 874 {
6d176551 875@@ -1205,6 +1209,7 @@ int security_path_chmod(const struct path *path, umode_t mode)
7f207e10 876 return 0;
c2c0f25c 877 return call_int_hook(path_chmod, 0, path, mode);
7f207e10 878 }
febd17d6 879+EXPORT_SYMBOL_GPL(security_path_chmod);
7f207e10 880
5afbbe0d 881 int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
7f207e10 882 {
6d176551 883@@ -1212,6 +1217,7 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
7f207e10 884 return 0;
c2c0f25c 885 return call_int_hook(path_chown, 0, path, uid, gid);
7f207e10 886 }
febd17d6 887+EXPORT_SYMBOL_GPL(security_path_chown);
7f207e10 888
5afbbe0d 889 int security_path_chroot(const struct path *path)
7f207e10 890 {
6d176551 891@@ -1312,6 +1318,7 @@ int security_inode_permission(struct inode *inode, int mask)
7f207e10 892 return 0;
c2c0f25c 893 return call_int_hook(inode_permission, 0, inode, mask);
7f207e10 894 }
febd17d6 895+EXPORT_SYMBOL_GPL(security_inode_permission);
7f207e10 896
1e00d052 897 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
7f207e10 898 {
6d176551 899@@ -1509,6 +1516,7 @@ int security_file_permission(struct file *file, int mask)
7f207e10
AM
900
901 return fsnotify_perm(file, mask);
902 }
febd17d6 903+EXPORT_SYMBOL_GPL(security_file_permission);
7f207e10
AM
904
905 int security_file_alloc(struct file *file)
906 {
7f207e10 907diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Documentation/ABI/testing/debugfs-aufs
eca34b5c 908--- /usr/share/empty/Documentation/ABI/testing/debugfs-aufs 1970-01-01 01:00:00.000000000 +0100
319657f6 909+++ linux/Documentation/ABI/testing/debugfs-aufs 2021-12-03 15:38:59.926647310 +0100
062440b3 910@@ -0,0 +1,55 @@
7f207e10
AM
911+What: /debug/aufs/si_<id>/
912+Date: March 2009
f6b6e03d 913+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
914+Description:
915+ Under /debug/aufs, a directory named si_<id> is created
916+ per aufs mount, where <id> is a unique id generated
917+ internally.
1facf9fc 918+
86dc4139
AM
919+What: /debug/aufs/si_<id>/plink
920+Date: Apr 2013
f6b6e03d 921+Contact: J. R. Okajima <hooanon05g@gmail.com>
86dc4139
AM
922+Description:
923+ It has three lines and shows the information about the
924+ pseudo-link. The first line is a single number
925+ representing a number of buckets. The second line is a
926+ number of pseudo-links per buckets (separated by a
927+ blank). The last line is a single number representing a
928+ total number of psedo-links.
929+ When the aufs mount option 'noplink' is specified, it
930+ will show "1\n0\n0\n".
931+
7f207e10
AM
932+What: /debug/aufs/si_<id>/xib
933+Date: March 2009
f6b6e03d 934+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
935+Description:
936+ It shows the consumed blocks by xib (External Inode Number
937+ Bitmap), its block size and file size.
938+ When the aufs mount option 'noxino' is specified, it
939+ will be empty. About XINO files, see the aufs manual.
940+
0b2a12c6 941+What: /debug/aufs/si_<id>/xi<branch-index>
7f207e10 942+Date: March 2009
f6b6e03d 943+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
944+Description:
945+ It shows the consumed blocks by xino (External Inode Number
946+ Translation Table), its link count, block size and file
947+ size.
062440b3
AM
948+ Due to the file size limit, there may exist multiple
949+ xino files per branch. In this case, "-N" is added to
950+ the filename and it corresponds to the index of the
951+ internal xino array. "-0" is omitted.
952+ When the aufs mount option 'noxino' is specified, Those
953+ entries won't exist. About XINO files, see the aufs
954+ manual.
7f207e10
AM
955+
956+What: /debug/aufs/si_<id>/xigen
957+Date: March 2009
f6b6e03d 958+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
959+Description:
960+ It shows the consumed blocks by xigen (External Inode
961+ Generation Table), its block size and file size.
962+ If CONFIG_AUFS_EXPORT is disabled, this entry will not
963+ be created.
964+ When the aufs mount option 'noxino' is specified, it
965+ will be empty. About XINO files, see the aufs manual.
966diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentation/ABI/testing/sysfs-aufs
eca34b5c 967--- /usr/share/empty/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100
319657f6 968+++ linux/Documentation/ABI/testing/sysfs-aufs 2021-12-03 15:38:59.926647310 +0100
392086de 969@@ -0,0 +1,31 @@
7f207e10
AM
970+What: /sys/fs/aufs/si_<id>/
971+Date: March 2009
f6b6e03d 972+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
973+Description:
974+ Under /sys/fs/aufs, a directory named si_<id> is created
975+ per aufs mount, where <id> is a unique id generated
976+ internally.
977+
0b2a12c6 978+What: /sys/fs/aufs/si_<id>/br<idx>
7f207e10 979+Date: March 2009
f6b6e03d 980+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
981+Description:
982+ It shows the abolute path of a member directory (which
983+ is called branch) in aufs, and its permission.
984+
0b2a12c6 985+What: /sys/fs/aufs/si_<id>/brid<idx>
392086de 986+Date: July 2013
f6b6e03d 987+Contact: J. R. Okajima <hooanon05g@gmail.com>
392086de
AM
988+Description:
989+ It shows the id of a member directory (which is called
990+ branch) in aufs.
991+
7f207e10
AM
992+What: /sys/fs/aufs/si_<id>/xi_path
993+Date: March 2009
f6b6e03d 994+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
995+Description:
996+ It shows the abolute path of XINO (External Inode Number
997+ Bitmap, Translation Table and Generation Table) file
998+ even if it is the default path.
999+ When the aufs mount option 'noxino' is specified, it
1000+ will be empty. About XINO files, see the aufs manual.
53392da6 1001diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt linux/Documentation/filesystems/aufs/design/01intro.txt
eca34b5c 1002--- /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt 1970-01-01 01:00:00.000000000 +0100
319657f6 1003+++ linux/Documentation/filesystems/aufs/design/01intro.txt 2021-12-03 15:38:59.929980643 +0100
1c60b727 1004@@ -0,0 +1,171 @@
53392da6 1005+
6d176551 1006+# Copyright (C) 2005-2021 Junjiro R. Okajima
53392da6
AM
1007+#
1008+# This program is free software; you can redistribute it and/or modify
1009+# it under the terms of the GNU General Public License as published by
1010+# the Free Software Foundation; either version 2 of the License, or
1011+# (at your option) any later version.
1012+#
1013+# This program is distributed in the hope that it will be useful,
1014+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1015+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1016+# GNU General Public License for more details.
1017+#
1018+# You should have received a copy of the GNU General Public License
523b37e3 1019+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1020+
1021+Introduction
1022+----------------------------------------
1023+
3c1bdaff 1024+aufs [ei ju: ef es] | /ey-yoo-ef-es/ | [a u f s]
53392da6
AM
1025+1. abbrev. for "advanced multi-layered unification filesystem".
1026+2. abbrev. for "another unionfs".
1027+3. abbrev. for "auf das" in German which means "on the" in English.
1028+ Ex. "Butter aufs Brot"(G) means "butter onto bread"(E).
1029+ But "Filesystem aufs Filesystem" is hard to understand.
1c60b727 1030+4. abbrev. for "African Urban Fashion Show".
53392da6
AM
1031+
1032+AUFS is a filesystem with features:
1033+- multi layered stackable unification filesystem, the member directory
1034+ is called as a branch.
1035+- branch permission and attribute, 'readonly', 'real-readonly',
7e9cd9fe 1036+ 'readwrite', 'whiteout-able', 'link-able whiteout', etc. and their
53392da6
AM
1037+ combination.
1038+- internal "file copy-on-write".
1039+- logical deletion, whiteout.
1040+- dynamic branch manipulation, adding, deleting and changing permission.
1041+- allow bypassing aufs, user's direct branch access.
1042+- external inode number translation table and bitmap which maintains the
1043+ persistent aufs inode number.
1044+- seekable directory, including NFS readdir.
1045+- file mapping, mmap and sharing pages.
1046+- pseudo-link, hardlink over branches.
1047+- loopback mounted filesystem as a branch.
1048+- several policies to select one among multiple writable branches.
1049+- revert a single systemcall when an error occurs in aufs.
1050+- and more...
1051+
1052+
1053+Multi Layered Stackable Unification Filesystem
1054+----------------------------------------------------------------------
1055+Most people already knows what it is.
1056+It is a filesystem which unifies several directories and provides a
1057+merged single directory. When users access a file, the access will be
1058+passed/re-directed/converted (sorry, I am not sure which English word is
1059+correct) to the real file on the member filesystem. The member
1060+filesystem is called 'lower filesystem' or 'branch' and has a mode
1061+'readonly' and 'readwrite.' And the deletion for a file on the lower
1062+readonly branch is handled by creating 'whiteout' on the upper writable
1063+branch.
1064+
1065+On LKML, there have been discussions about UnionMount (Jan Blunck,
1066+Bharata B Rao and Valerie Aurora) and Unionfs (Erez Zadok). They took
1067+different approaches to implement the merged-view.
1068+The former tries putting it into VFS, and the latter implements as a
1069+separate filesystem.
1070+(If I misunderstand about these implementations, please let me know and
1071+I shall correct it. Because it is a long time ago when I read their
1072+source files last time).
1073+
1074+UnionMount's approach will be able to small, but may be hard to share
1075+branches between several UnionMount since the whiteout in it is
1076+implemented in the inode on branch filesystem and always
1077+shared. According to Bharata's post, readdir does not seems to be
1078+finished yet.
1079+There are several missing features known in this implementations such as
1080+- for users, the inode number may change silently. eg. copy-up.
1081+- link(2) may break by copy-up.
1082+- read(2) may get an obsoleted filedata (fstat(2) too).
1083+- fcntl(F_SETLK) may be broken by copy-up.
1084+- unnecessary copy-up may happen, for example mmap(MAP_PRIVATE) after
1085+ open(O_RDWR).
1086+
7e9cd9fe
AM
1087+In linux-3.18, "overlay" filesystem (formerly known as "overlayfs") was
1088+merged into mainline. This is another implementation of UnionMount as a
1089+separated filesystem. All the limitations and known problems which
1090+UnionMount are equally inherited to "overlay" filesystem.
1091+
1092+Unionfs has a longer history. When I started implementing a stackable
1093+filesystem (Aug 2005), it already existed. It has virtual super_block,
1094+inode, dentry and file objects and they have an array pointing lower
1095+same kind objects. After contributing many patches for Unionfs, I
1096+re-started my project AUFS (Jun 2006).
53392da6
AM
1097+
1098+In AUFS, the structure of filesystem resembles to Unionfs, but I
1099+implemented my own ideas, approaches and enhancements and it became
1100+totally different one.
1101+
1102+Comparing DM snapshot and fs based implementation
1103+- the number of bytes to be copied between devices is much smaller.
1104+- the type of filesystem must be one and only.
1105+- the fs must be writable, no readonly fs, even for the lower original
1106+ device. so the compression fs will not be usable. but if we use
1107+ loopback mount, we may address this issue.
1108+ for instance,
1109+ mount /cdrom/squashfs.img /sq
1110+ losetup /sq/ext2.img
1111+ losetup /somewhere/cow
1112+ dmsetup "snapshot /dev/loop0 /dev/loop1 ..."
1113+- it will be difficult (or needs more operations) to extract the
1114+ difference between the original device and COW.
1115+- DM snapshot-merge may help a lot when users try merging. in the
1116+ fs-layer union, users will use rsync(1).
1117+
7e9cd9fe
AM
1118+You may want to read my old paper "Filesystems in LiveCD"
1119+(http://aufs.sourceforge.net/aufs2/report/sq/sq.pdf).
53392da6 1120+
7e9cd9fe
AM
1121+
1122+Several characters/aspects/persona of aufs
53392da6
AM
1123+----------------------------------------------------------------------
1124+
7e9cd9fe 1125+Aufs has several characters, aspects or persona.
53392da6
AM
1126+1. a filesystem, callee of VFS helper
1127+2. sub-VFS, caller of VFS helper for branches
1128+3. a virtual filesystem which maintains persistent inode number
1129+4. reader/writer of files on branches such like an application
1130+
1131+1. Callee of VFS Helper
1132+As an ordinary linux filesystem, aufs is a callee of VFS. For instance,
1133+unlink(2) from an application reaches sys_unlink() kernel function and
1134+then vfs_unlink() is called. vfs_unlink() is one of VFS helper and it
1135+calls filesystem specific unlink operation. Actually aufs implements the
1136+unlink operation but it behaves like a redirector.
1137+
1138+2. Caller of VFS Helper for Branches
1139+aufs_unlink() passes the unlink request to the branch filesystem as if
1140+it were called from VFS. So the called unlink operation of the branch
1141+filesystem acts as usual. As a caller of VFS helper, aufs should handle
1142+every necessary pre/post operation for the branch filesystem.
1143+- acquire the lock for the parent dir on a branch
1144+- lookup in a branch
1145+- revalidate dentry on a branch
1146+- mnt_want_write() for a branch
1147+- vfs_unlink() for a branch
1148+- mnt_drop_write() for a branch
1149+- release the lock on a branch
1150+
1151+3. Persistent Inode Number
1152+One of the most important issue for a filesystem is to maintain inode
1153+numbers. This is particularly important to support exporting a
1154+filesystem via NFS. Aufs is a virtual filesystem which doesn't have a
1155+backend block device for its own. But some storage is necessary to
7e9cd9fe
AM
1156+keep and maintain the inode numbers. It may be a large space and may not
1157+suit to keep in memory. Aufs rents some space from its first writable
1158+branch filesystem (by default) and creates file(s) on it. These files
1159+are created by aufs internally and removed soon (currently) keeping
1160+opened.
53392da6
AM
1161+Note: Because these files are removed, they are totally gone after
1162+ unmounting aufs. It means the inode numbers are not persistent
1163+ across unmount or reboot. I have a plan to make them really
1164+ persistent which will be important for aufs on NFS server.
1165+
1166+4. Read/Write Files Internally (copy-on-write)
1167+Because a branch can be readonly, when you write a file on it, aufs will
1168+"copy-up" it to the upper writable branch internally. And then write the
1169+originally requested thing to the file. Generally kernel doesn't
1170+open/read/write file actively. In aufs, even a single write may cause a
1171+internal "file copy". This behaviour is very similar to cp(1) command.
1172+
1173+Some people may think it is better to pass such work to user space
1174+helper, instead of doing in kernel space. Actually I am still thinking
1175+about it. But currently I have implemented it in kernel space.
1176diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt linux/Documentation/filesystems/aufs/design/02struct.txt
eca34b5c 1177--- /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt 1970-01-01 01:00:00.000000000 +0100
319657f6 1178+++ linux/Documentation/filesystems/aufs/design/02struct.txt 2021-12-03 15:38:59.929980643 +0100
7e9cd9fe 1179@@ -0,0 +1,258 @@
53392da6 1180+
6d176551 1181+# Copyright (C) 2005-2021 Junjiro R. Okajima
53392da6
AM
1182+#
1183+# This program is free software; you can redistribute it and/or modify
1184+# it under the terms of the GNU General Public License as published by
1185+# the Free Software Foundation; either version 2 of the License, or
1186+# (at your option) any later version.
1187+#
1188+# This program is distributed in the hope that it will be useful,
1189+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1190+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1191+# GNU General Public License for more details.
1192+#
1193+# You should have received a copy of the GNU General Public License
523b37e3 1194+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1195+
1196+Basic Aufs Internal Structure
1197+
1198+Superblock/Inode/Dentry/File Objects
1199+----------------------------------------------------------------------
1200+As like an ordinary filesystem, aufs has its own
1201+superblock/inode/dentry/file objects. All these objects have a
1202+dynamically allocated array and store the same kind of pointers to the
1203+lower filesystem, branch.
1204+For example, when you build a union with one readwrite branch and one
1205+readonly, mounted /au, /rw and /ro respectively.
1206+- /au = /rw + /ro
1207+- /ro/fileA exists but /rw/fileA
1208+
1209+Aufs lookup operation finds /ro/fileA and gets dentry for that. These
1210+pointers are stored in a aufs dentry. The array in aufs dentry will be,
7e9cd9fe 1211+- [0] = NULL (because /rw/fileA doesn't exist)
53392da6
AM
1212+- [1] = /ro/fileA
1213+
1214+This style of an array is essentially same to the aufs
1215+superblock/inode/dentry/file objects.
1216+
1217+Because aufs supports manipulating branches, ie. add/delete/change
7e9cd9fe
AM
1218+branches dynamically, these objects has its own generation. When
1219+branches are changed, the generation in aufs superblock is
1220+incremented. And a generation in other object are compared when it is
1221+accessed. When a generation in other objects are obsoleted, aufs
1222+refreshes the internal array.
53392da6
AM
1223+
1224+
1225+Superblock
1226+----------------------------------------------------------------------
1227+Additionally aufs superblock has some data for policies to select one
1228+among multiple writable branches, XIB files, pseudo-links and kobject.
1229+See below in detail.
7e9cd9fe
AM
1230+About the policies which supports copy-down a directory, see
1231+wbr_policy.txt too.
53392da6
AM
1232+
1233+
1234+Branch and XINO(External Inode Number Translation Table)
1235+----------------------------------------------------------------------
1236+Every branch has its own xino (external inode number translation table)
1237+file. The xino file is created and unlinked by aufs internally. When two
1238+members of a union exist on the same filesystem, they share the single
1239+xino file.
1240+The struct of a xino file is simple, just a sequence of aufs inode
1241+numbers which is indexed by the lower inode number.
1242+In the above sample, assume the inode number of /ro/fileA is i111 and
1243+aufs assigns the inode number i999 for fileA. Then aufs writes 999 as
1244+4(8) bytes at 111 * 4(8) bytes offset in the xino file.
1245+
1246+When the inode numbers are not contiguous, the xino file will be sparse
1247+which has a hole in it and doesn't consume as much disk space as it
1248+might appear. If your branch filesystem consumes disk space for such
1249+holes, then you should specify 'xino=' option at mounting aufs.
1250+
7e9cd9fe
AM
1251+Aufs has a mount option to free the disk blocks for such holes in XINO
1252+files on tmpfs or ramdisk. But it is not so effective actually. If you
1253+meet a problem of disk shortage due to XINO files, then you should try
1254+"tmpfs-ino.patch" (and "vfs-ino.patch" too) in aufs4-standalone.git.
1255+The patch localizes the assignment inumbers per tmpfs-mount and avoid
1256+the holes in XINO files.
1257+
53392da6 1258+Also a writable branch has three kinds of "whiteout bases". All these
7e9cd9fe 1259+are existed when the branch is joined to aufs, and their names are
53392da6
AM
1260+whiteout-ed doubly, so that users will never see their names in aufs
1261+hierarchy.
7e9cd9fe 1262+1. a regular file which will be hardlinked to all whiteouts.
53392da6 1263+2. a directory to store a pseudo-link.
7e9cd9fe 1264+3. a directory to store an "orphan"-ed file temporary.
53392da6
AM
1265+
1266+1. Whiteout Base
1267+ When you remove a file on a readonly branch, aufs handles it as a
1268+ logical deletion and creates a whiteout on the upper writable branch
1269+ as a hardlink of this file in order not to consume inode on the
1270+ writable branch.
1271+2. Pseudo-link Dir
1272+ See below, Pseudo-link.
1273+3. Step-Parent Dir
1274+ When "fileC" exists on the lower readonly branch only and it is
1275+ opened and removed with its parent dir, and then user writes
1276+ something into it, then aufs copies-up fileC to this
1277+ directory. Because there is no other dir to store fileC. After
1278+ creating a file under this dir, the file is unlinked.
1279+
1280+Because aufs supports manipulating branches, ie. add/delete/change
7e9cd9fe
AM
1281+dynamically, a branch has its own id. When the branch order changes,
1282+aufs finds the new index by searching the branch id.
53392da6
AM
1283+
1284+
1285+Pseudo-link
1286+----------------------------------------------------------------------
1287+Assume "fileA" exists on the lower readonly branch only and it is
1288+hardlinked to "fileB" on the branch. When you write something to fileA,
1289+aufs copies-up it to the upper writable branch. Additionally aufs
1290+creates a hardlink under the Pseudo-link Directory of the writable
1291+branch. The inode of a pseudo-link is kept in aufs super_block as a
1292+simple list. If fileB is read after unlinking fileA, aufs returns
1293+filedata from the pseudo-link instead of the lower readonly
1294+branch. Because the pseudo-link is based upon the inode, to keep the
7e9cd9fe 1295+inode number by xino (see above) is essentially necessary.
53392da6
AM
1296+
1297+All the hardlinks under the Pseudo-link Directory of the writable branch
1298+should be restored in a proper location later. Aufs provides a utility
1299+to do this. The userspace helpers executed at remounting and unmounting
1300+aufs by default.
1301+During this utility is running, it puts aufs into the pseudo-link
1302+maintenance mode. In this mode, only the process which began the
1303+maintenance mode (and its child processes) is allowed to operate in
1304+aufs. Some other processes which are not related to the pseudo-link will
1305+be allowed to run too, but the rest have to return an error or wait
1306+until the maintenance mode ends. If a process already acquires an inode
1307+mutex (in VFS), it has to return an error.
1308+
1309+
1310+XIB(external inode number bitmap)
1311+----------------------------------------------------------------------
1312+Addition to the xino file per a branch, aufs has an external inode number
7e9cd9fe
AM
1313+bitmap in a superblock object. It is also an internal file such like a
1314+xino file.
53392da6
AM
1315+It is a simple bitmap to mark whether the aufs inode number is in-use or
1316+not.
1317+To reduce the file I/O, aufs prepares a single memory page to cache xib.
1318+
7e9cd9fe 1319+As well as XINO files, aufs has a feature to truncate/refresh XIB to
53392da6
AM
1320+reduce the number of consumed disk blocks for these files.
1321+
1322+
1323+Virtual or Vertical Dir, and Readdir in Userspace
1324+----------------------------------------------------------------------
1325+In order to support multiple layers (branches), aufs readdir operation
1326+constructs a virtual dir block on memory. For readdir, aufs calls
1327+vfs_readdir() internally for each dir on branches, merges their entries
1328+with eliminating the whiteout-ed ones, and sets it to file (dir)
1329+object. So the file object has its entry list until it is closed. The
1330+entry list will be updated when the file position is zero and becomes
7e9cd9fe 1331+obsoleted. This decision is made in aufs automatically.
53392da6
AM
1332+
1333+The dynamically allocated memory block for the name of entries has a
1334+unit of 512 bytes (by default) and stores the names contiguously (no
1335+padding). Another block for each entry is handled by kmem_cache too.
1336+During building dir blocks, aufs creates hash list and judging whether
1337+the entry is whiteouted by its upper branch or already listed.
1338+The merged result is cached in the corresponding inode object and
1339+maintained by a customizable life-time option.
1340+
1341+Some people may call it can be a security hole or invite DoS attack
1342+since the opened and once readdir-ed dir (file object) holds its entry
1343+list and becomes a pressure for system memory. But I'd say it is similar
1344+to files under /proc or /sys. The virtual files in them also holds a
1345+memory page (generally) while they are opened. When an idea to reduce
1346+memory for them is introduced, it will be applied to aufs too.
1347+For those who really hate this situation, I've developed readdir(3)
1348+library which operates this merging in userspace. You just need to set
1349+LD_PRELOAD environment variable, and aufs will not consume no memory in
1350+kernel space for readdir(3).
1351+
1352+
1353+Workqueue
1354+----------------------------------------------------------------------
1355+Aufs sometimes requires privilege access to a branch. For instance,
1356+in copy-up/down operation. When a user process is going to make changes
1357+to a file which exists in the lower readonly branch only, and the mode
1358+of one of ancestor directories may not be writable by a user
1359+process. Here aufs copy-up the file with its ancestors and they may
1360+require privilege to set its owner/group/mode/etc.
1361+This is a typical case of a application character of aufs (see
1362+Introduction).
1363+
1364+Aufs uses workqueue synchronously for this case. It creates its own
1365+workqueue. The workqueue is a kernel thread and has privilege. Aufs
1366+passes the request to call mkdir or write (for example), and wait for
1367+its completion. This approach solves a problem of a signal handler
1368+simply.
1369+If aufs didn't adopt the workqueue and changed the privilege of the
7e9cd9fe
AM
1370+process, then the process may receive the unexpected SIGXFSZ or other
1371+signals.
53392da6
AM
1372+
1373+Also aufs uses the system global workqueue ("events" kernel thread) too
1374+for asynchronous tasks, such like handling inotify/fsnotify, re-creating a
1375+whiteout base and etc. This is unrelated to a privilege.
1376+Most of aufs operation tries acquiring a rw_semaphore for aufs
1377+superblock at the beginning, at the same time waits for the completion
1378+of all queued asynchronous tasks.
1379+
1380+
1381+Whiteout
1382+----------------------------------------------------------------------
1383+The whiteout in aufs is very similar to Unionfs's. That is represented
1384+by its filename. UnionMount takes an approach of a file mode, but I am
1385+afraid several utilities (find(1) or something) will have to support it.
1386+
1387+Basically the whiteout represents "logical deletion" which stops aufs to
1388+lookup further, but also it represents "dir is opaque" which also stop
7e9cd9fe 1389+further lookup.
53392da6
AM
1390+
1391+In aufs, rmdir(2) and rename(2) for dir uses whiteout alternatively.
1392+In order to make several functions in a single systemcall to be
1393+revertible, aufs adopts an approach to rename a directory to a temporary
1394+unique whiteouted name.
1395+For example, in rename(2) dir where the target dir already existed, aufs
1396+renames the target dir to a temporary unique whiteouted name before the
7e9cd9fe 1397+actual rename on a branch, and then handles other actions (make it opaque,
53392da6
AM
1398+update the attributes, etc). If an error happens in these actions, aufs
1399+simply renames the whiteouted name back and returns an error. If all are
1400+succeeded, aufs registers a function to remove the whiteouted unique
1401+temporary name completely and asynchronously to the system global
1402+workqueue.
1403+
1404+
1405+Copy-up
1406+----------------------------------------------------------------------
1407+It is a well-known feature or concept.
1408+When user modifies a file on a readonly branch, aufs operate "copy-up"
1409+internally and makes change to the new file on the upper writable branch.
1410+When the trigger systemcall does not update the timestamps of the parent
1411+dir, aufs reverts it after copy-up.
c2b27bf2
AM
1412+
1413+
1414+Move-down (aufs3.9 and later)
1415+----------------------------------------------------------------------
1416+"Copy-up" is one of the essential feature in aufs. It copies a file from
1417+the lower readonly branch to the upper writable branch when a user
1418+changes something about the file.
1419+"Move-down" is an opposite action of copy-up. Basically this action is
1420+ran manually instead of automatically and internally.
076b876e
AM
1421+For desgin and implementation, aufs has to consider these issues.
1422+- whiteout for the file may exist on the lower branch.
1423+- ancestor directories may not exist on the lower branch.
1424+- diropq for the ancestor directories may exist on the upper branch.
1425+- free space on the lower branch will reduce.
1426+- another access to the file may happen during moving-down, including
7e9cd9fe 1427+ UDBA (see "Revalidate Dentry and UDBA").
076b876e
AM
1428+- the file should not be hard-linked nor pseudo-linked. they should be
1429+ handled by auplink utility later.
c2b27bf2
AM
1430+
1431+Sometimes users want to move-down a file from the upper writable branch
1432+to the lower readonly or writable branch. For instance,
1433+- the free space of the upper writable branch is going to run out.
1434+- create a new intermediate branch between the upper and lower branch.
1435+- etc.
1436+
1437+For this purpose, use "aumvdown" command in aufs-util.git.
b912730e 1438diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/03atomic_open.txt linux/Documentation/filesystems/aufs/design/03atomic_open.txt
eca34b5c 1439--- /usr/share/empty/Documentation/filesystems/aufs/design/03atomic_open.txt 1970-01-01 01:00:00.000000000 +0100
319657f6 1440+++ linux/Documentation/filesystems/aufs/design/03atomic_open.txt 2021-12-03 15:38:59.929980643 +0100
b912730e
AM
1441@@ -0,0 +1,85 @@
1442+
6d176551 1443+# Copyright (C) 2015-2021 Junjiro R. Okajima
b912730e
AM
1444+#
1445+# This program is free software; you can redistribute it and/or modify
1446+# it under the terms of the GNU General Public License as published by
1447+# the Free Software Foundation; either version 2 of the License, or
1448+# (at your option) any later version.
1449+#
1450+# This program is distributed in the hope that it will be useful,
1451+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1452+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1453+# GNU General Public License for more details.
1454+#
1455+# You should have received a copy of the GNU General Public License
1456+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1457+
1458+Support for a branch who has its ->atomic_open()
1459+----------------------------------------------------------------------
1460+The filesystems who implement its ->atomic_open() are not majority. For
1461+example NFSv4 does, and aufs should call NFSv4 ->atomic_open,
1462+particularly for open(O_CREAT|O_EXCL, 0400) case. Other than
1463+->atomic_open(), NFSv4 returns an error for this open(2). While I am not
1464+sure whether all filesystems who have ->atomic_open() behave like this,
1465+but NFSv4 surely returns the error.
1466+
1467+In order to support ->atomic_open() for aufs, there are a few
1468+approaches.
1469+
1470+A. Introduce aufs_atomic_open()
1471+ - calls one of VFS:do_last(), lookup_open() or atomic_open() for
1472+ branch fs.
1473+B. Introduce aufs_atomic_open() calling create, open and chmod. this is
1474+ an aufs user Pip Cet's approach
1475+ - calls aufs_create(), VFS finish_open() and notify_change().
1476+ - pass fake-mode to finish_open(), and then correct the mode by
1477+ notify_change().
1478+C. Extend aufs_open() to call branch fs's ->atomic_open()
1479+ - no aufs_atomic_open().
1480+ - aufs_lookup() registers the TID to an aufs internal object.
1481+ - aufs_create() does nothing when the matching TID is registered, but
1482+ registers the mode.
1483+ - aufs_open() calls branch fs's ->atomic_open() when the matching
1484+ TID is registered.
1485+D. Extend aufs_open() to re-try branch fs's ->open() with superuser's
1486+ credential
1487+ - no aufs_atomic_open().
1488+ - aufs_create() registers the TID to an internal object. this info
1489+ represents "this process created this file just now."
1490+ - when aufs gets EACCES from branch fs's ->open(), then confirm the
1491+ registered TID and re-try open() with superuser's credential.
1492+
1493+Pros and cons for each approach.
1494+
1495+A.
1496+ - straightforward but highly depends upon VFS internal.
1497+ - the atomic behavaiour is kept.
1498+ - some of parameters such as nameidata are hard to reproduce for
1499+ branch fs.
1500+ - large overhead.
1501+B.
1502+ - easy to implement.
1503+ - the atomic behavaiour is lost.
1504+C.
1505+ - the atomic behavaiour is kept.
1506+ - dirty and tricky.
1507+ - VFS checks whether the file is created correctly after calling
1508+ ->create(), which means this approach doesn't work.
1509+D.
1510+ - easy to implement.
1511+ - the atomic behavaiour is lost.
1512+ - to open a file with superuser's credential and give it to a user
1513+ process is a bad idea, since the file object keeps the credential
1514+ in it. It may affect LSM or something. This approach doesn't work
1515+ either.
1516+
1517+The approach A is ideal, but it hard to implement. So here is a
1518+variation of A, which is to be implemented.
1519+
1520+A-1. Introduce aufs_atomic_open()
1521+ - calls branch fs ->atomic_open() if exists. otherwise calls
1522+ vfs_create() and finish_open().
1523+ - the demerit is that the several checks after branch fs
1524+ ->atomic_open() are lost. in the ordinary case, the checks are
1525+ done by VFS:do_last(), lookup_open() and atomic_open(). some can
1526+ be implemented in aufs, but not all I am afraid.
53392da6 1527diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt linux/Documentation/filesystems/aufs/design/03lookup.txt
eca34b5c 1528--- /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt 1970-01-01 01:00:00.000000000 +0100
319657f6 1529+++ linux/Documentation/filesystems/aufs/design/03lookup.txt 2021-12-03 15:38:59.929980643 +0100
7e9cd9fe 1530@@ -0,0 +1,113 @@
53392da6 1531+
6d176551 1532+# Copyright (C) 2005-2021 Junjiro R. Okajima
53392da6
AM
1533+#
1534+# This program is free software; you can redistribute it and/or modify
1535+# it under the terms of the GNU General Public License as published by
1536+# the Free Software Foundation; either version 2 of the License, or
1537+# (at your option) any later version.
1538+#
1539+# This program is distributed in the hope that it will be useful,
1540+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1541+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1542+# GNU General Public License for more details.
1543+#
1544+# You should have received a copy of the GNU General Public License
523b37e3 1545+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1546+
1547+Lookup in a Branch
1548+----------------------------------------------------------------------
1549+Since aufs has a character of sub-VFS (see Introduction), it operates
7e9cd9fe
AM
1550+lookup for branches as VFS does. It may be a heavy work. But almost all
1551+lookup operation in aufs is the simplest case, ie. lookup only an entry
1552+directly connected to its parent. Digging down the directory hierarchy
1553+is unnecessary. VFS has a function lookup_one_len() for that use, and
1554+aufs calls it.
1555+
1556+When a branch is a remote filesystem, aufs basically relies upon its
53392da6
AM
1557+->d_revalidate(), also aufs forces the hardest revalidate tests for
1558+them.
1559+For d_revalidate, aufs implements three levels of revalidate tests. See
1560+"Revalidate Dentry and UDBA" in detail.
1561+
1562+
076b876e
AM
1563+Test Only the Highest One for the Directory Permission (dirperm1 option)
1564+----------------------------------------------------------------------
1565+Let's try case study.
1566+- aufs has two branches, upper readwrite and lower readonly.
1567+ /au = /rw + /ro
1568+- "dirA" exists under /ro, but /rw. and its mode is 0700.
1569+- user invoked "chmod a+rx /au/dirA"
1570+- the internal copy-up is activated and "/rw/dirA" is created and its
7e9cd9fe 1571+ permission bits are set to world readable.
076b876e
AM
1572+- then "/au/dirA" becomes world readable?
1573+
1574+In this case, /ro/dirA is still 0700 since it exists in readonly branch,
1575+or it may be a natively readonly filesystem. If aufs respects the lower
1576+branch, it should not respond readdir request from other users. But user
1577+allowed it by chmod. Should really aufs rejects showing the entries
1578+under /ro/dirA?
1579+
7e9cd9fe
AM
1580+To be honest, I don't have a good solution for this case. So aufs
1581+implements 'dirperm1' and 'nodirperm1' mount options, and leave it to
1582+users.
076b876e
AM
1583+When dirperm1 is specified, aufs checks only the highest one for the
1584+directory permission, and shows the entries. Otherwise, as usual, checks
1585+every dir existing on all branches and rejects the request.
1586+
1587+As a side effect, dirperm1 option improves the performance of aufs
1588+because the number of permission check is reduced when the number of
1589+branch is many.
1590+
1591+
53392da6
AM
1592+Revalidate Dentry and UDBA (User's Direct Branch Access)
1593+----------------------------------------------------------------------
1594+Generally VFS helpers re-validate a dentry as a part of lookup.
1595+0. digging down the directory hierarchy.
1596+1. lock the parent dir by its i_mutex.
1597+2. lookup the final (child) entry.
1598+3. revalidate it.
1599+4. call the actual operation (create, unlink, etc.)
1600+5. unlock the parent dir
1601+
1602+If the filesystem implements its ->d_revalidate() (step 3), then it is
1603+called. Actually aufs implements it and checks the dentry on a branch is
1604+still valid.
1605+But it is not enough. Because aufs has to release the lock for the
1606+parent dir on a branch at the end of ->lookup() (step 2) and
1607+->d_revalidate() (step 3) while the i_mutex of the aufs dir is still
1608+held by VFS.
1609+If the file on a branch is changed directly, eg. bypassing aufs, after
1610+aufs released the lock, then the subsequent operation may cause
1611+something unpleasant result.
1612+
1613+This situation is a result of VFS architecture, ->lookup() and
1614+->d_revalidate() is separated. But I never say it is wrong. It is a good
1615+design from VFS's point of view. It is just not suitable for sub-VFS
1616+character in aufs.
1617+
1618+Aufs supports such case by three level of revalidation which is
1619+selectable by user.
1620+1. Simple Revalidate
1621+ Addition to the native flow in VFS's, confirm the child-parent
1622+ relationship on the branch just after locking the parent dir on the
1623+ branch in the "actual operation" (step 4). When this validation
1624+ fails, aufs returns EBUSY. ->d_revalidate() (step 3) in aufs still
1625+ checks the validation of the dentry on branches.
1626+2. Monitor Changes Internally by Inotify/Fsnotify
1627+ Addition to above, in the "actual operation" (step 4) aufs re-lookup
1628+ the dentry on the branch, and returns EBUSY if it finds different
1629+ dentry.
1630+ Additionally, aufs sets the inotify/fsnotify watch for every dir on branches
1631+ during it is in cache. When the event is notified, aufs registers a
1632+ function to kernel 'events' thread by schedule_work(). And the
1633+ function sets some special status to the cached aufs dentry and inode
1634+ private data. If they are not cached, then aufs has nothing to
1635+ do. When the same file is accessed through aufs (step 0-3) later,
1636+ aufs will detect the status and refresh all necessary data.
1637+ In this mode, aufs has to ignore the event which is fired by aufs
1638+ itself.
1639+3. No Extra Validation
1640+ This is the simplest test and doesn't add any additional revalidation
7e9cd9fe 1641+ test, and skip the revalidation in step 4. It is useful and improves
53392da6
AM
1642+ aufs performance when system surely hide the aufs branches from user,
1643+ by over-mounting something (or another method).
1644diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt linux/Documentation/filesystems/aufs/design/04branch.txt
eca34b5c 1645--- /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt 1970-01-01 01:00:00.000000000 +0100
319657f6 1646+++ linux/Documentation/filesystems/aufs/design/04branch.txt 2021-12-03 15:38:59.929980643 +0100
7e9cd9fe 1647@@ -0,0 +1,74 @@
53392da6 1648+
6d176551 1649+# Copyright (C) 2005-2021 Junjiro R. Okajima
53392da6
AM
1650+#
1651+# This program is free software; you can redistribute it and/or modify
1652+# it under the terms of the GNU General Public License as published by
1653+# the Free Software Foundation; either version 2 of the License, or
1654+# (at your option) any later version.
1655+#
1656+# This program is distributed in the hope that it will be useful,
1657+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1658+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1659+# GNU General Public License for more details.
1660+#
1661+# You should have received a copy of the GNU General Public License
523b37e3 1662+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1663+
1664+Branch Manipulation
1665+
1666+Since aufs supports dynamic branch manipulation, ie. add/remove a branch
1667+and changing its permission/attribute, there are a lot of works to do.
1668+
1669+
1670+Add a Branch
1671+----------------------------------------------------------------------
1672+o Confirm the adding dir exists outside of aufs, including loopback
7e9cd9fe 1673+ mount, and its various attributes.
53392da6
AM
1674+o Initialize the xino file and whiteout bases if necessary.
1675+ See struct.txt.
1676+
1677+o Check the owner/group/mode of the directory
1678+ When the owner/group/mode of the adding directory differs from the
1679+ existing branch, aufs issues a warning because it may impose a
1680+ security risk.
1681+ For example, when a upper writable branch has a world writable empty
1682+ top directory, a malicious user can create any files on the writable
1683+ branch directly, like copy-up and modify manually. If something like
1684+ /etc/{passwd,shadow} exists on the lower readonly branch but the upper
1685+ writable branch, and the writable branch is world-writable, then a
1686+ malicious guy may create /etc/passwd on the writable branch directly
1687+ and the infected file will be valid in aufs.
7e9cd9fe 1688+ I am afraid it can be a security issue, but aufs can do nothing except
53392da6
AM
1689+ producing a warning.
1690+
1691+
1692+Delete a Branch
1693+----------------------------------------------------------------------
1694+o Confirm the deleting branch is not busy
1695+ To be general, there is one merit to adopt "remount" interface to
1696+ manipulate branches. It is to discard caches. At deleting a branch,
1697+ aufs checks the still cached (and connected) dentries and inodes. If
1698+ there are any, then they are all in-use. An inode without its
1699+ corresponding dentry can be alive alone (for example, inotify/fsnotify case).
1700+
1701+ For the cached one, aufs checks whether the same named entry exists on
1702+ other branches.
1703+ If the cached one is a directory, because aufs provides a merged view
1704+ to users, as long as one dir is left on any branch aufs can show the
1705+ dir to users. In this case, the branch can be removed from aufs.
1706+ Otherwise aufs rejects deleting the branch.
1707+
1708+ If any file on the deleting branch is opened by aufs, then aufs
1709+ rejects deleting.
1710+
1711+
1712+Modify the Permission of a Branch
1713+----------------------------------------------------------------------
1714+o Re-initialize or remove the xino file and whiteout bases if necessary.
1715+ See struct.txt.
1716+
1717+o rw --> ro: Confirm the modifying branch is not busy
1718+ Aufs rejects the request if any of these conditions are true.
1719+ - a file on the branch is mmap-ed.
1720+ - a regular file on the branch is opened for write and there is no
1721+ same named entry on the upper branch.
1722diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt linux/Documentation/filesystems/aufs/design/05wbr_policy.txt
eca34b5c 1723--- /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt 1970-01-01 01:00:00.000000000 +0100
319657f6 1724+++ linux/Documentation/filesystems/aufs/design/05wbr_policy.txt 2021-12-03 15:38:59.929980643 +0100
523b37e3 1725@@ -0,0 +1,64 @@
53392da6 1726+
6d176551 1727+# Copyright (C) 2005-2021 Junjiro R. Okajima
53392da6
AM
1728+#
1729+# This program is free software; you can redistribute it and/or modify
1730+# it under the terms of the GNU General Public License as published by
1731+# the Free Software Foundation; either version 2 of the License, or
1732+# (at your option) any later version.
1733+#
1734+# This program is distributed in the hope that it will be useful,
1735+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1736+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1737+# GNU General Public License for more details.
1738+#
1739+# You should have received a copy of the GNU General Public License
523b37e3 1740+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1741+
1742+Policies to Select One among Multiple Writable Branches
1743+----------------------------------------------------------------------
1744+When the number of writable branch is more than one, aufs has to decide
1745+the target branch for file creation or copy-up. By default, the highest
1746+writable branch which has the parent (or ancestor) dir of the target
1747+file is chosen (top-down-parent policy).
1748+By user's request, aufs implements some other policies to select the
7e9cd9fe
AM
1749+writable branch, for file creation several policies, round-robin,
1750+most-free-space, and other policies. For copy-up, top-down-parent,
1751+bottom-up-parent, bottom-up and others.
53392da6
AM
1752+
1753+As expected, the round-robin policy selects the branch in circular. When
1754+you have two writable branches and creates 10 new files, 5 files will be
1755+created for each branch. mkdir(2) systemcall is an exception. When you
1756+create 10 new directories, all will be created on the same branch.
1757+And the most-free-space policy selects the one which has most free
1758+space among the writable branches. The amount of free space will be
1759+checked by aufs internally, and users can specify its time interval.
1760+
1761+The policies for copy-up is more simple,
1762+top-down-parent is equivalent to the same named on in create policy,
1763+bottom-up-parent selects the writable branch where the parent dir
1764+exists and the nearest upper one from the copyup-source,
1765+bottom-up selects the nearest upper writable branch from the
1766+copyup-source, regardless the existence of the parent dir.
1767+
1768+There are some rules or exceptions to apply these policies.
1769+- If there is a readonly branch above the policy-selected branch and
1770+ the parent dir is marked as opaque (a variation of whiteout), or the
1771+ target (creating) file is whiteout-ed on the upper readonly branch,
1772+ then the result of the policy is ignored and the target file will be
1773+ created on the nearest upper writable branch than the readonly branch.
1774+- If there is a writable branch above the policy-selected branch and
1775+ the parent dir is marked as opaque or the target file is whiteouted
1776+ on the branch, then the result of the policy is ignored and the target
1777+ file will be created on the highest one among the upper writable
1778+ branches who has diropq or whiteout. In case of whiteout, aufs removes
1779+ it as usual.
1780+- link(2) and rename(2) systemcalls are exceptions in every policy.
1781+ They try selecting the branch where the source exists as possible
1782+ since copyup a large file will take long time. If it can't be,
1783+ ie. the branch where the source exists is readonly, then they will
1784+ follow the copyup policy.
1785+- There is an exception for rename(2) when the target exists.
1786+ If the rename target exists, aufs compares the index of the branches
1787+ where the source and the target exists and selects the higher
1788+ one. If the selected branch is readonly, then aufs follows the
1789+ copyup policy.
8b6a4947 1790diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.dot linux/Documentation/filesystems/aufs/design/06dirren.dot
eca34b5c 1791--- /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.dot 1970-01-01 01:00:00.000000000 +0100
319657f6 1792+++ linux/Documentation/filesystems/aufs/design/06dirren.dot 2021-12-03 15:38:59.929980643 +0100
8b6a4947
AM
1793@@ -0,0 +1,31 @@
1794+
1795+// to view this graph, run dot(1) command in GRAPHVIZ.
1796+
1797+digraph G {
1798+node [shape=box];
1799+whinfo [label="detailed info file\n(lower_brid_root-hinum, h_inum, namelen, old name)"];
1800+
1801+node [shape=oval];
1802+
1803+aufs_rename -> whinfo [label="store/remove"];
1804+
1805+node [shape=oval];
1806+inode_list [label="h_inum list in branch\ncache"];
1807+
1808+node [shape=box];
1809+whinode [label="h_inum list file"];
1810+
1811+node [shape=oval];
1812+brmgmt [label="br_add/del/mod/umount"];
1813+
1814+brmgmt -> inode_list [label="create/remove"];
1815+brmgmt -> whinode [label="load/store"];
1816+
1817+inode_list -> whinode [style=dashed,dir=both];
1818+
1819+aufs_rename -> inode_list [label="add/del"];
1820+
1821+aufs_lookup -> inode_list [label="search"];
1822+
1823+aufs_lookup -> whinfo [label="load/remove"];
1824+}
1825diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.txt linux/Documentation/filesystems/aufs/design/06dirren.txt
eca34b5c 1826--- /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.txt 1970-01-01 01:00:00.000000000 +0100
319657f6 1827+++ linux/Documentation/filesystems/aufs/design/06dirren.txt 2021-12-03 15:38:59.929980643 +0100
8b6a4947
AM
1828@@ -0,0 +1,102 @@
1829+
6d176551 1830+# Copyright (C) 2017-2021 Junjiro R. Okajima
8b6a4947
AM
1831+#
1832+# This program is free software; you can redistribute it and/or modify
1833+# it under the terms of the GNU General Public License as published by
1834+# the Free Software Foundation; either version 2 of the License, or
1835+# (at your option) any later version.
1836+#
1837+# This program is distributed in the hope that it will be useful,
1838+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1839+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1840+# GNU General Public License for more details.
1841+#
1842+# You should have received a copy of the GNU General Public License
1843+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1844+
1845+Special handling for renaming a directory (DIRREN)
1846+----------------------------------------------------------------------
1847+First, let's assume we have a simple usecase.
1848+
1849+- /u = /rw + /ro
1850+- /rw/dirA exists
1851+- /ro/dirA and /ro/dirA/file exist too
1852+- there is no dirB on both branches
1853+- a user issues rename("dirA", "dirB")
1854+
1855+Now, what should aufs behave against this rename(2)?
1856+There are a few possible cases.
1857+
1858+A. returns EROFS.
1859+ since dirA exists on a readonly branch which cannot be renamed.
1860+B. returns EXDEV.
1861+ it is possible to copy-up dirA (only the dir itself), but the child
1862+ entries ("file" in this case) should not be. it must be a bad
1863+ approach to copy-up recursively.
1864+C. returns a success.
1865+ even the branch /ro is readonly, aufs tries renaming it. Obviously it
1866+ is a violation of aufs' policy.
1867+D. construct an extra information which indicates that /ro/dirA should
1868+ be handled as the name of dirB.
1869+ overlayfs has a similar feature called REDIRECT.
1870+
1871+Until now, aufs implements the case B only which returns EXDEV, and
1872+expects the userspace application behaves like mv(1) which tries
1873+issueing rename(2) recursively.
1874+
1875+A new aufs feature called DIRREN is introduced which implements the case
1876+D. There are several "extra information" added.
1877+
1878+1. detailed info per renamed directory
1879+ path: /rw/dirB/$AUFS_WH_DR_INFO_PFX.<lower branch-id>
1880+2. the inode-number list of directories on a branch
1881+ path: /rw/dirB/$AUFS_WH_DR_BRHINO
1882+
1883+The filename of "detailed info per directory" represents the lower
1884+branch, and its format is
1885+- a type of the branch id
1886+ one of these.
1887+ + uuid (not implemented yet)
1888+ + fsid
1889+ + dev
1890+- the inode-number of the branch root dir
1891+
1892+And it contains these info in a single regular file.
1893+- magic number
1894+- branch's inode-number of the logically renamed dir
1895+- the name of the before-renamed dir
1896+
1897+The "detailed info per directory" file is created in aufs rename(2), and
1898+loaded in any lookup.
1899+The info is considered in lookup for the matching case only. Here
1900+"matching" means that the root of branch (in the info filename) is same
1901+to the current looking-up branch. After looking-up the before-renamed
1902+name, the inode-number is compared. And the matched dentry is used.
1903+
1904+The "inode-number list of directories" is a regular file which contains
1905+simply the inode-numbers on the branch. The file is created or updated
1906+in removing the branch, and loaded in adding the branch. Its lifetime is
1907+equal to the branch.
1908+The list is refered in lookup, and when the current target inode is
1909+found in the list, the aufs tries loading the "detailed info per
1910+directory" and get the changed and valid name of the dir.
1911+
1912+Theoretically these "extra informaiton" may be able to be put into XATTR
1913+in the dir inode. But aufs doesn't choose this way because
1914+1. XATTR may not be supported by the branch (or its configuration)
1915+2. XATTR may have its size limit.
1916+3. XATTR may be less easy to convert than a regular file, when the
1917+ format of the info is changed in the future.
1918+At the same time, I agree that the regular file approach is much slower
1919+than XATTR approach. So, in the future, aufs may take the XATTR or other
1920+better approach.
1921+
1922+This DIRREN feature is enabled by aufs configuration, and is activated
1923+by a new mount option.
1924+
1925+For the more complicated case, there is a work with UDBA option, which
1926+is to dected the direct access to the branches (by-passing aufs) and to
1927+maintain the cashes in aufs. Since a single cached aufs dentry may
1928+contains two names, before- and after-rename, the name comparision in
1929+UDBA handler may not work correctly. In this case, the behaviour will be
1930+equivalen to udba=reval case.
076b876e 1931diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06fhsm.txt linux/Documentation/filesystems/aufs/design/06fhsm.txt
eca34b5c 1932--- /usr/share/empty/Documentation/filesystems/aufs/design/06fhsm.txt 1970-01-01 01:00:00.000000000 +0100
319657f6 1933+++ linux/Documentation/filesystems/aufs/design/06fhsm.txt 2021-12-03 15:38:59.929980643 +0100
076b876e
AM
1934@@ -0,0 +1,120 @@
1935+
6d176551 1936+# Copyright (C) 2011-2021 Junjiro R. Okajima
076b876e
AM
1937+#
1938+# This program is free software; you can redistribute it and/or modify
1939+# it under the terms of the GNU General Public License as published by
1940+# the Free Software Foundation; either version 2 of the License, or
1941+# (at your option) any later version.
1942+#
1943+# This program is distributed in the hope that it will be useful,
1944+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1945+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1946+# GNU General Public License for more details.
1947+#
1948+# You should have received a copy of the GNU General Public License
1949+# along with this program; if not, write to the Free Software
1950+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1951+
1952+
1953+File-based Hierarchical Storage Management (FHSM)
1954+----------------------------------------------------------------------
1955+Hierarchical Storage Management (or HSM) is a well-known feature in the
1956+storage world. Aufs provides this feature as file-based with multiple
7e9cd9fe 1957+writable branches, based upon the principle of "Colder, the Lower".
076b876e 1958+Here the word "colder" means that the less used files, and "lower" means
7e9cd9fe 1959+that the position in the order of the stacked branches vertically.
076b876e
AM
1960+These multiple writable branches are prioritized, ie. the topmost one
1961+should be the fastest drive and be used heavily.
1962+
1963+o Characters in aufs FHSM story
1964+- aufs itself and a new branch attribute.
1965+- a new ioctl interface to move-down and to establish a connection with
1966+ the daemon ("move-down" is a converse of "copy-up").
1967+- userspace tool and daemon.
1968+
1969+The userspace daemon establishes a connection with aufs and waits for
1970+the notification. The notified information is very similar to struct
1971+statfs containing the number of consumed blocks and inodes.
1972+When the consumed blocks/inodes of a branch exceeds the user-specified
1973+upper watermark, the daemon activates its move-down process until the
1974+consumed blocks/inodes reaches the user-specified lower watermark.
1975+
1976+The actual move-down is done by aufs based upon the request from
1977+user-space since we need to maintain the inode number and the internal
1978+pointer arrays in aufs.
1979+
1980+Currently aufs FHSM handles the regular files only. Additionally they
1981+must not be hard-linked nor pseudo-linked.
1982+
1983+
1984+o Cowork of aufs and the user-space daemon
1985+ During the userspace daemon established the connection, aufs sends a
1986+ small notification to it whenever aufs writes something into the
1987+ writable branch. But it may cost high since aufs issues statfs(2)
1988+ internally. So user can specify a new option to cache the
1989+ info. Actually the notification is controlled by these factors.
1990+ + the specified cache time.
1991+ + classified as "force" by aufs internally.
1992+ Until the specified time expires, aufs doesn't send the info
1993+ except the forced cases. When aufs decide forcing, the info is always
1994+ notified to userspace.
1995+ For example, the number of free inodes is generally large enough and
1996+ the shortage of it happens rarely. So aufs doesn't force the
1997+ notification when creating a new file, directory and others. This is
1998+ the typical case which aufs doesn't force.
1999+ When aufs writes the actual filedata and the files consumes any of new
2000+ blocks, the aufs forces notifying.
2001+
2002+
2003+o Interfaces in aufs
2004+- New branch attribute.
2005+ + fhsm
2006+ Specifies that the branch is managed by FHSM feature. In other word,
2007+ participant in the FHSM.
2008+ When nofhsm is set to the branch, it will not be the source/target
2009+ branch of the move-down operation. This attribute is set
2010+ independently from coo and moo attributes, and if you want full
2011+ FHSM, you should specify them as well.
2012+- New mount option.
2013+ + fhsm_sec
2014+ Specifies a second to suppress many less important info to be
2015+ notified.
2016+- New ioctl.
2017+ + AUFS_CTL_FHSM_FD
2018+ create a new file descriptor which userspace can read the notification
2019+ (a subset of struct statfs) from aufs.
2020+- Module parameter 'brs'
2021+ It has to be set to 1. Otherwise the new mount option 'fhsm' will not
2022+ be set.
2023+- mount helpers /sbin/mount.aufs and /sbin/umount.aufs
2024+ When there are two or more branches with fhsm attributes,
2025+ /sbin/mount.aufs invokes the user-space daemon and /sbin/umount.aufs
2026+ terminates it. As a result of remounting and branch-manipulation, the
2027+ number of branches with fhsm attribute can be one. In this case,
2028+ /sbin/mount.aufs will terminate the user-space daemon.
2029+
2030+
2031+Finally the operation is done as these steps in kernel-space.
2032+- make sure that,
2033+ + no one else is using the file.
2034+ + the file is not hard-linked.
2035+ + the file is not pseudo-linked.
2036+ + the file is a regular file.
2037+ + the parent dir is not opaqued.
2038+- find the target writable branch.
2039+- make sure the file is not whiteout-ed by the upper (than the target)
2040+ branch.
2041+- make the parent dir on the target branch.
2042+- mutex lock the inode on the branch.
2043+- unlink the whiteout on the target branch (if exists).
2044+- lookup and create the whiteout-ed temporary name on the target branch.
2045+- copy the file as the whiteout-ed temporary name on the target branch.
2046+- rename the whiteout-ed temporary name to the original name.
2047+- unlink the file on the source branch.
2048+- maintain the internal pointer array and the external inode number
2049+ table (XINO).
2050+- maintain the timestamps and other attributes of the parent dir and the
2051+ file.
2052+
2053+And of course, in every step, an error may happen. So the operation
2054+should restore the original file state after an error happens.
53392da6 2055diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt linux/Documentation/filesystems/aufs/design/06mmap.txt
eca34b5c 2056--- /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt 1970-01-01 01:00:00.000000000 +0100
319657f6 2057+++ linux/Documentation/filesystems/aufs/design/06mmap.txt 2021-12-03 15:38:59.929980643 +0100
b912730e 2058@@ -0,0 +1,72 @@
53392da6 2059+
6d176551 2060+# Copyright (C) 2005-2021 Junjiro R. Okajima
53392da6
AM
2061+#
2062+# This program is free software; you can redistribute it and/or modify
2063+# it under the terms of the GNU General Public License as published by
2064+# the Free Software Foundation; either version 2 of the License, or
2065+# (at your option) any later version.
2066+#
2067+# This program is distributed in the hope that it will be useful,
2068+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2069+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2070+# GNU General Public License for more details.
2071+#
2072+# You should have received a copy of the GNU General Public License
523b37e3 2073+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
2074+
2075+mmap(2) -- File Memory Mapping
2076+----------------------------------------------------------------------
2077+In aufs, the file-mapped pages are handled by a branch fs directly, no
2078+interaction with aufs. It means aufs_mmap() calls the branch fs's
2079+->mmap().
2080+This approach is simple and good, but there is one problem.
7e9cd9fe 2081+Under /proc, several entries show the mmapped files by its path (with
53392da6
AM
2082+device and inode number), and the printed path will be the path on the
2083+branch fs's instead of virtual aufs's.
2084+This is not a problem in most cases, but some utilities lsof(1) (and its
2085+user) may expect the path on aufs.
2086+
2087+To address this issue, aufs adds a new member called vm_prfile in struct
2088+vm_area_struct (and struct vm_region). The original vm_file points to
2089+the file on the branch fs in order to handle everything correctly as
2090+usual. The new vm_prfile points to a virtual file in aufs, and the
2091+show-functions in procfs refers to vm_prfile if it is set.
2092+Also we need to maintain several other places where touching vm_file
2093+such like
2094+- fork()/clone() copies vma and the reference count of vm_file is
2095+ incremented.
2096+- merging vma maintains the ref count too.
2097+
7e9cd9fe 2098+This is not a good approach. It just fakes the printed path. But it
53392da6
AM
2099+leaves all behaviour around f_mapping unchanged. This is surely an
2100+advantage.
2101+Actually aufs had adopted another complicated approach which calls
2102+generic_file_mmap() and handles struct vm_operations_struct. In this
2103+approach, aufs met a hard problem and I could not solve it without
2104+switching the approach.
b912730e
AM
2105+
2106+There may be one more another approach which is
2107+- bind-mount the branch-root onto the aufs-root internally
2108+- grab the new vfsmount (ie. struct mount)
2109+- lazy-umount the branch-root internally
2110+- in open(2) the aufs-file, open the branch-file with the hidden
2111+ vfsmount (instead of the original branch's vfsmount)
2112+- ideally this "bind-mount and lazy-umount" should be done atomically,
2113+ but it may be possible from userspace by the mount helper.
2114+
2115+Adding the internal hidden vfsmount and using it in opening a file, the
2116+file path under /proc will be printed correctly. This approach looks
2117+smarter, but is not possible I am afraid.
2118+- aufs-root may be bind-mount later. when it happens, another hidden
2119+ vfsmount will be required.
2120+- it is hard to get the chance to bind-mount and lazy-umount
2121+ + in kernel-space, FS can have vfsmount in open(2) via
2122+ file->f_path, and aufs can know its vfsmount. But several locks are
2123+ already acquired, and if aufs tries to bind-mount and lazy-umount
2124+ here, then it may cause a deadlock.
2125+ + in user-space, bind-mount doesn't invoke the mount helper.
2126+- since /proc shows dev and ino, aufs has to give vma these info. it
2127+ means a new member vm_prinode will be necessary. this is essentially
2128+ equivalent to vm_prfile described above.
2129+
2130+I have to give up this "looks-smater" approach.
c1595e42 2131diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06xattr.txt linux/Documentation/filesystems/aufs/design/06xattr.txt
eca34b5c 2132--- /usr/share/empty/Documentation/filesystems/aufs/design/06xattr.txt 1970-01-01 01:00:00.000000000 +0100
319657f6 2133+++ linux/Documentation/filesystems/aufs/design/06xattr.txt 2021-12-03 15:38:59.929980643 +0100
c1595e42
JR
2134@@ -0,0 +1,96 @@
2135+
6d176551 2136+# Copyright (C) 2014-2021 Junjiro R. Okajima
c1595e42
JR
2137+#
2138+# This program is free software; you can redistribute it and/or modify
2139+# it under the terms of the GNU General Public License as published by
2140+# the Free Software Foundation; either version 2 of the License, or
2141+# (at your option) any later version.
2142+#
2143+# This program is distributed in the hope that it will be useful,
2144+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2145+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2146+# GNU General Public License for more details.
2147+#
2148+# You should have received a copy of the GNU General Public License
2149+# along with this program; if not, write to the Free Software
2150+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2151+
2152+
2153+Listing XATTR/EA and getting the value
2154+----------------------------------------------------------------------
2155+For the inode standard attributes (owner, group, timestamps, etc.), aufs
2156+shows the values from the topmost existing file. This behaviour is good
7e9cd9fe 2157+for the non-dir entries since the bahaviour exactly matches the shown
c1595e42
JR
2158+information. But for the directories, aufs considers all the same named
2159+entries on the lower branches. Which means, if one of the lower entry
2160+rejects readdir call, then aufs returns an error even if the topmost
2161+entry allows it. This behaviour is necessary to respect the branch fs's
2162+security, but can make users confused since the user-visible standard
2163+attributes don't match the behaviour.
2164+To address this issue, aufs has a mount option called dirperm1 which
2165+checks the permission for the topmost entry only, and ignores the lower
2166+entry's permission.
2167+
2168+A similar issue can happen around XATTR.
2169+getxattr(2) and listxattr(2) families behave as if dirperm1 option is
7e9cd9fe
AM
2170+always set. Otherwise these very unpleasant situation would happen.
2171+- listxattr(2) may return the duplicated entries.
c1595e42
JR
2172+- users may not be able to remove or reset the XATTR forever,
2173+
2174+
2175+XATTR/EA support in the internal (copy,move)-(up,down)
2176+----------------------------------------------------------------------
7e9cd9fe 2177+Generally the extended attributes of inode are categorized as these.
c1595e42
JR
2178+- "security" for LSM and capability.
2179+- "system" for posix ACL, 'acl' mount option is required for the branch
2180+ fs generally.
2181+- "trusted" for userspace, CAP_SYS_ADMIN is required.
2182+- "user" for userspace, 'user_xattr' mount option is required for the
2183+ branch fs generally.
2184+
2185+Moreover there are some other categories. Aufs handles these rather
2186+unpopular categories as the ordinary ones, ie. there is no special
2187+condition nor exception.
2188+
2189+In copy-up, the support for XATTR on the dst branch may differ from the
2190+src branch. In this case, the copy-up operation will get an error and
7e9cd9fe
AM
2191+the original user operation which triggered the copy-up will fail. It
2192+can happen that even all copy-up will fail.
c1595e42
JR
2193+When both of src and dst branches support XATTR and if an error occurs
2194+during copying XATTR, then the copy-up should fail obviously. That is a
2195+good reason and aufs should return an error to userspace. But when only
7e9cd9fe 2196+the src branch support that XATTR, aufs should not return an error.
c1595e42
JR
2197+For example, the src branch supports ACL but the dst branch doesn't
2198+because the dst branch may natively un-support it or temporary
2199+un-support it due to "noacl" mount option. Of course, the dst branch fs
2200+may NOT return an error even if the XATTR is not supported. It is
2201+totally up to the branch fs.
2202+
2203+Anyway when the aufs internal copy-up gets an error from the dst branch
2204+fs, then aufs tries removing the just copied entry and returns the error
2205+to the userspace. The worst case of this situation will be all copy-up
2206+will fail.
2207+
2208+For the copy-up operation, there two basic approaches.
2209+- copy the specified XATTR only (by category above), and return the
7e9cd9fe 2210+ error unconditionally if it happens.
c1595e42
JR
2211+- copy all XATTR, and ignore the error on the specified category only.
2212+
2213+In order to support XATTR and to implement the correct behaviour, aufs
7e9cd9fe
AM
2214+chooses the latter approach and introduces some new branch attributes,
2215+"icexsec", "icexsys", "icextr", "icexusr", and "icexoth".
c1595e42 2216+They correspond to the XATTR namespaces (see above). Additionally, to be
7e9cd9fe
AM
2217+convenient, "icex" is also provided which means all "icex*" attributes
2218+are set (here the word "icex" stands for "ignore copy-error on XATTR").
c1595e42
JR
2219+
2220+The meaning of these attributes is to ignore the error from setting
2221+XATTR on that branch.
2222+Note that aufs tries copying all XATTR unconditionally, and ignores the
2223+error from the dst branch according to the specified attributes.
2224+
2225+Some XATTR may have its default value. The default value may come from
2226+the parent dir or the environment. If the default value is set at the
2227+file creating-time, it will be overwritten by copy-up.
2228+Some contradiction may happen I am afraid.
2229+Do we need another attribute to stop copying XATTR? I am unsure. For
2230+now, aufs implements the branch attributes to ignore the error.
53392da6 2231diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt linux/Documentation/filesystems/aufs/design/07export.txt
eca34b5c 2232--- /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt 1970-01-01 01:00:00.000000000 +0100
319657f6 2233+++ linux/Documentation/filesystems/aufs/design/07export.txt 2021-12-03 15:38:59.929980643 +0100
523b37e3 2234@@ -0,0 +1,58 @@
53392da6 2235+
6d176551 2236+# Copyright (C) 2005-2021 Junjiro R. Okajima
53392da6
AM
2237+#
2238+# This program is free software; you can redistribute it and/or modify
2239+# it under the terms of the GNU General Public License as published by
2240+# the Free Software Foundation; either version 2 of the License, or
2241+# (at your option) any later version.
2242+#
2243+# This program is distributed in the hope that it will be useful,
2244+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2245+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2246+# GNU General Public License for more details.
2247+#
2248+# You should have received a copy of the GNU General Public License
523b37e3 2249+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
2250+
2251+Export Aufs via NFS
2252+----------------------------------------------------------------------
2253+Here is an approach.
2254+- like xino/xib, add a new file 'xigen' which stores aufs inode
2255+ generation.
2256+- iget_locked(): initialize aufs inode generation for a new inode, and
2257+ store it in xigen file.
2258+- destroy_inode(): increment aufs inode generation and store it in xigen
2259+ file. it is necessary even if it is not unlinked, because any data of
2260+ inode may be changed by UDBA.
2261+- encode_fh(): for a root dir, simply return FILEID_ROOT. otherwise
2262+ build file handle by
2263+ + branch id (4 bytes)
2264+ + superblock generation (4 bytes)
2265+ + inode number (4 or 8 bytes)
2266+ + parent dir inode number (4 or 8 bytes)
2267+ + inode generation (4 bytes))
2268+ + return value of exportfs_encode_fh() for the parent on a branch (4
2269+ bytes)
2270+ + file handle for a branch (by exportfs_encode_fh())
2271+- fh_to_dentry():
2272+ + find the index of a branch from its id in handle, and check it is
2273+ still exist in aufs.
2274+ + 1st level: get the inode number from handle and search it in cache.
7e9cd9fe
AM
2275+ + 2nd level: if not found in cache, get the parent inode number from
2276+ the handle and search it in cache. and then open the found parent
2277+ dir, find the matching inode number by vfs_readdir() and get its
2278+ name, and call lookup_one_len() for the target dentry.
53392da6
AM
2279+ + 3rd level: if the parent dir is not cached, call
2280+ exportfs_decode_fh() for a branch and get the parent on a branch,
2281+ build a pathname of it, convert it a pathname in aufs, call
2282+ path_lookup(). now aufs gets a parent dir dentry, then handle it as
2283+ the 2nd level.
2284+ + to open the dir, aufs needs struct vfsmount. aufs keeps vfsmount
2285+ for every branch, but not itself. to get this, (currently) aufs
2286+ searches in current->nsproxy->mnt_ns list. it may not be a good
2287+ idea, but I didn't get other approach.
2288+ + test the generation of the gotten inode.
2289+- every inode operation: they may get EBUSY due to UDBA. in this case,
2290+ convert it into ESTALE for NFSD.
2291+- readdir(): call lockdep_on/off() because filldir in NFSD calls
2292+ lookup_one_len(), vfs_getattr(), encode_fh() and others.
2293diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt linux/Documentation/filesystems/aufs/design/08shwh.txt
eca34b5c 2294--- /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt 1970-01-01 01:00:00.000000000 +0100
319657f6 2295+++ linux/Documentation/filesystems/aufs/design/08shwh.txt 2021-12-03 15:38:59.929980643 +0100
523b37e3 2296@@ -0,0 +1,52 @@
53392da6 2297+
6d176551 2298+# Copyright (C) 2005-2021 Junjiro R. Okajima
53392da6
AM
2299+#
2300+# This program is free software; you can redistribute it and/or modify
2301+# it under the terms of the GNU General Public License as published by
2302+# the Free Software Foundation; either version 2 of the License, or
2303+# (at your option) any later version.
2304+#
2305+# This program is distributed in the hope that it will be useful,
2306+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2307+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2308+# GNU General Public License for more details.
2309+#
2310+# You should have received a copy of the GNU General Public License
523b37e3 2311+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
2312+
2313+Show Whiteout Mode (shwh)
2314+----------------------------------------------------------------------
2315+Generally aufs hides the name of whiteouts. But in some cases, to show
2316+them is very useful for users. For instance, creating a new middle layer
2317+(branch) by merging existing layers.
2318+
2319+(borrowing aufs1 HOW-TO from a user, Michael Towers)
2320+When you have three branches,
2321+- Bottom: 'system', squashfs (underlying base system), read-only
2322+- Middle: 'mods', squashfs, read-only
2323+- Top: 'overlay', ram (tmpfs), read-write
2324+
2325+The top layer is loaded at boot time and saved at shutdown, to preserve
2326+the changes made to the system during the session.
2327+When larger changes have been made, or smaller changes have accumulated,
2328+the size of the saved top layer data grows. At this point, it would be
2329+nice to be able to merge the two overlay branches ('mods' and 'overlay')
2330+and rewrite the 'mods' squashfs, clearing the top layer and thus
2331+restoring save and load speed.
2332+
2333+This merging is simplified by the use of another aufs mount, of just the
2334+two overlay branches using the 'shwh' option.
2335+# mount -t aufs -o ro,shwh,br:/livesys/overlay=ro+wh:/livesys/mods=rr+wh \
2336+ aufs /livesys/merge_union
2337+
2338+A merged view of these two branches is then available at
2339+/livesys/merge_union, and the new feature is that the whiteouts are
2340+visible!
2341+Note that in 'shwh' mode the aufs mount must be 'ro', which will disable
2342+writing to all branches. Also the default mode for all branches is 'ro'.
2343+It is now possible to save the combined contents of the two overlay
2344+branches to a new squashfs, e.g.:
2345+# mksquashfs /livesys/merge_union /path/to/newmods.squash
2346+
2347+This new squashfs archive can be stored on the boot device and the
2348+initramfs will use it to replace the old one at the next boot.
2349diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt linux/Documentation/filesystems/aufs/design/10dynop.txt
eca34b5c 2350--- /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt 1970-01-01 01:00:00.000000000 +0100
319657f6 2351+++ linux/Documentation/filesystems/aufs/design/10dynop.txt 2021-12-03 15:38:59.929980643 +0100
7e9cd9fe 2352@@ -0,0 +1,47 @@
53392da6 2353+
6d176551 2354+# Copyright (C) 2010-2021 Junjiro R. Okajima
53392da6
AM
2355+#
2356+# This program is free software; you can redistribute it and/or modify
2357+# it under the terms of the GNU General Public License as published by
2358+# the Free Software Foundation; either version 2 of the License, or
2359+# (at your option) any later version.
2360+#
2361+# This program is distributed in the hope that it will be useful,
2362+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2363+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2364+# GNU General Public License for more details.
2365+#
2366+# You should have received a copy of the GNU General Public License
523b37e3 2367+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
2368+
2369+Dynamically customizable FS operations
2370+----------------------------------------------------------------------
2371+Generally FS operations (struct inode_operations, struct
2372+address_space_operations, struct file_operations, etc.) are defined as
2373+"static const", but it never means that FS have only one set of
2374+operation. Some FS have multiple sets of them. For instance, ext2 has
2375+three sets, one for XIP, for NOBH, and for normal.
2376+Since aufs overrides and redirects these operations, sometimes aufs has
7e9cd9fe 2377+to change its behaviour according to the branch FS type. More importantly
53392da6
AM
2378+VFS acts differently if a function (member in the struct) is set or
2379+not. It means aufs should have several sets of operations and select one
2380+among them according to the branch FS definition.
2381+
7e9cd9fe 2382+In order to solve this problem and not to affect the behaviour of VFS,
53392da6 2383+aufs defines these operations dynamically. For instance, aufs defines
7e9cd9fe
AM
2384+dummy direct_IO function for struct address_space_operations, but it may
2385+not be set to the address_space_operations actually. When the branch FS
2386+doesn't have it, aufs doesn't set it to its address_space_operations
2387+while the function definition itself is still alive. So the behaviour
2388+itself will not change, and it will return an error when direct_IO is
2389+not set.
53392da6
AM
2390+
2391+The lifetime of these dynamically generated operation object is
2392+maintained by aufs branch object. When the branch is removed from aufs,
2393+the reference counter of the object is decremented. When it reaches
2394+zero, the dynamically generated operation object will be freed.
2395+
7e9cd9fe
AM
2396+This approach is designed to support AIO (io_submit), Direct I/O and
2397+XIP (DAX) mainly.
2398+Currently this approach is applied to address_space_operations for
2399+regular files only.
53392da6 2400diff -urN /usr/share/empty/Documentation/filesystems/aufs/README linux/Documentation/filesystems/aufs/README
eca34b5c 2401--- /usr/share/empty/Documentation/filesystems/aufs/README 1970-01-01 01:00:00.000000000 +0100
319657f6 2402+++ linux/Documentation/filesystems/aufs/README 2021-12-03 15:40:58.233313963 +0100
46016270 2403@@ -0,0 +1,396 @@
53392da6 2404+
fbc438ed 2405+Aufs5 -- advanced multi layered unification filesystem version 5.x
53392da6
AM
2406+http://aufs.sf.net
2407+Junjiro R. Okajima
2408+
2409+
2410+0. Introduction
2411+----------------------------------------
2412+In the early days, aufs was entirely re-designed and re-implemented
7e9cd9fe 2413+Unionfs Version 1.x series. Adding many original ideas, approaches,
fbc438ed 2414+improvements and implementations, it became totally different from
53392da6 2415+Unionfs while keeping the basic features.
fbc438ed 2416+Later, Unionfs Version 2.x series began taking some of the same
53392da6 2417+approaches to aufs1's.
fbc438ed 2418+Unionfs was being developed by Professor Erez Zadok at Stony Brook
53392da6
AM
2419+University and his team.
2420+
fbc438ed
JR
2421+Aufs5 supports linux-v5.0 and later, If you want older kernel version
2422+support,
2423+- for linux-v4.x series, try aufs4-linux.git or aufs4-standalone.git
2424+- for linux-v3.x series, try aufs3-linux.git or aufs3-standalone.git
2425+- for linux-v2.6.16 and later, try aufs2-2.6.git, aufs2-standalone.git
2426+ or aufs1 from CVS on SourceForge.
53392da6
AM
2427+
2428+Note: it becomes clear that "Aufs was rejected. Let's give it up."
38d290e6
JR
2429+ According to Christoph Hellwig, linux rejects all union-type
2430+ filesystems but UnionMount.
53392da6
AM
2431+<http://marc.info/?l=linux-kernel&m=123938533724484&w=2>
2432+
38d290e6
JR
2433+PS. Al Viro seems have a plan to merge aufs as well as overlayfs and
2434+ UnionMount, and he pointed out an issue around a directory mutex
2435+ lock and aufs addressed it. But it is still unsure whether aufs will
2436+ be merged (or any other union solution).
076b876e 2437+<http://marc.info/?l=linux-kernel&m=136312705029295&w=1>
38d290e6 2438+
53392da6
AM
2439+
2440+1. Features
2441+----------------------------------------
2442+- unite several directories into a single virtual filesystem. The member
2443+ directory is called as a branch.
2444+- you can specify the permission flags to the branch, which are 'readonly',
2445+ 'readwrite' and 'whiteout-able.'
2446+- by upper writable branch, internal copyup and whiteout, files/dirs on
2447+ readonly branch are modifiable logically.
2448+- dynamic branch manipulation, add, del.
2449+- etc...
2450+
7e9cd9fe
AM
2451+Also there are many enhancements in aufs, such as:
2452+- test only the highest one for the directory permission (dirperm1)
2453+- copyup on open (coo=)
2454+- 'move' policy for copy-up between two writable branches, after
2455+ checking free space.
2456+- xattr, acl
53392da6
AM
2457+- readdir(3) in userspace.
2458+- keep inode number by external inode number table
2459+- keep the timestamps of file/dir in internal copyup operation
2460+- seekable directory, supporting NFS readdir.
2461+- whiteout is hardlinked in order to reduce the consumption of inodes
2462+ on branch
2463+- do not copyup, nor create a whiteout when it is unnecessary
2464+- revert a single systemcall when an error occurs in aufs
2465+- remount interface instead of ioctl
2466+- maintain /etc/mtab by an external command, /sbin/mount.aufs.
2467+- loopback mounted filesystem as a branch
2468+- kernel thread for removing the dir who has a plenty of whiteouts
2469+- support copyup sparse file (a file which has a 'hole' in it)
2470+- default permission flags for branches
2471+- selectable permission flags for ro branch, whether whiteout can
2472+ exist or not
2473+- export via NFS.
2474+- support <sysfs>/fs/aufs and <debugfs>/aufs.
2475+- support multiple writable branches, some policies to select one
2476+ among multiple writable branches.
2477+- a new semantics for link(2) and rename(2) to support multiple
2478+ writable branches.
2479+- no glibc changes are required.
2480+- pseudo hardlink (hardlink over branches)
2481+- allow a direct access manually to a file on branch, e.g. bypassing aufs.
2482+ including NFS or remote filesystem branch.
2483+- userspace wrapper for pathconf(3)/fpathconf(3) with _PC_LINK_MAX.
2484+- and more...
2485+
fbc438ed 2486+Currently these features are dropped temporary from aufs5.
53392da6 2487+See design/08plan.txt in detail.
53392da6
AM
2488+- nested mount, i.e. aufs as readonly no-whiteout branch of another aufs
2489+ (robr)
2490+- statistics of aufs thread (/sys/fs/aufs/stat)
53392da6
AM
2491+
2492+Features or just an idea in the future (see also design/*.txt),
2493+- reorder the branch index without del/re-add.
2494+- permanent xino files for NFSD
2495+- an option for refreshing the opened files after add/del branches
53392da6
AM
2496+- light version, without branch manipulation. (unnecessary?)
2497+- copyup in userspace
2498+- inotify in userspace
2499+- readv/writev
53392da6
AM
2500+
2501+
2502+2. Download
2503+----------------------------------------
fbc438ed
JR
2504+There are three GIT trees for aufs5, aufs5-linux.git,
2505+aufs5-standalone.git, and aufs-util.git. Note that there is no "5" in
1e00d052 2506+"aufs-util.git."
fbc438ed
JR
2507+While the aufs-util is always necessary, you need either of aufs5-linux
2508+or aufs5-standalone.
1e00d052 2509+
fbc438ed 2510+The aufs5-linux tree includes the whole linux mainline GIT tree,
1e00d052
AM
2511+git://git.kernel.org/.../torvalds/linux.git.
2512+And you cannot select CONFIG_AUFS_FS=m for this version, eg. you cannot
fbc438ed 2513+build aufs5 as an external kernel module.
2000de60 2514+Several extra patches are not included in this tree. Only
fbc438ed 2515+aufs5-standalone tree contains them. They are described in the later
2000de60 2516+section "Configuration and Compilation."
1e00d052 2517+
fbc438ed 2518+On the other hand, the aufs5-standalone tree has only aufs source files
53392da6 2519+and necessary patches, and you can select CONFIG_AUFS_FS=m.
2000de60 2520+But you need to apply all aufs patches manually.
53392da6 2521+
fbc438ed
JR
2522+You will find GIT branches whose name is in form of "aufs5.x" where "x"
2523+represents the linux kernel version, "linux-5.x". For instance,
2524+"aufs5.0" is for linux-5.0. For latest "linux-5.x-rcN", use
2525+"aufs5.x-rcN" branch.
1e00d052 2526+
fbc438ed 2527+o aufs5-linux tree
1e00d052 2528+$ git clone --reference /your/linux/git/tree \
fbc438ed 2529+ git://github.com/sfjro/aufs5-linux.git aufs5-linux.git
1e00d052 2530+- if you don't have linux GIT tree, then remove "--reference ..."
fbc438ed
JR
2531+$ cd aufs5-linux.git
2532+$ git checkout origin/aufs5.0
53392da6 2533+
2000de60
JR
2534+Or You may want to directly git-pull aufs into your linux GIT tree, and
2535+leave the patch-work to GIT.
2536+$ cd /your/linux/git/tree
fbc438ed
JR
2537+$ git remote add aufs5 git://github.com/sfjro/aufs5-linux.git
2538+$ git fetch aufs5
2539+$ git checkout -b my5.0 v5.0
5527c038 2540+$ (add your local change...)
fbc438ed
JR
2541+$ git pull aufs5 aufs5.0
2542+- now you have v5.0 + your_changes + aufs5.0 in you my5.0 branch.
2000de60 2543+- you may need to solve some conflicts between your_changes and
fbc438ed
JR
2544+ aufs5.0. in this case, git-rerere is recommended so that you can
2545+ solve the similar conflicts automatically when you upgrade to 5.1 or
2000de60
JR
2546+ later in the future.
2547+
fbc438ed
JR
2548+o aufs5-standalone tree
2549+$ git clone git://github.com/sfjro/aufs5-standalone.git aufs5-standalone.git
2550+$ cd aufs5-standalone.git
2551+$ git checkout origin/aufs5.0
53392da6
AM
2552+
2553+o aufs-util tree
5527c038
JR
2554+$ git clone git://git.code.sf.net/p/aufs/aufs-util aufs-util.git
2555+- note that the public aufs-util.git is on SourceForge instead of
2556+ GitHUB.
53392da6 2557+$ cd aufs-util.git
fbc438ed 2558+$ git checkout origin/aufs5.0
53392da6 2559+
fbc438ed
JR
2560+Note: The 5.x-rcN branch is to be used with `rc' kernel versions ONLY.
2561+The minor version number, 'x' in '5.x', of aufs may not always
9dbd164d
AM
2562+follow the minor version number of the kernel.
2563+Because changes in the kernel that cause the use of a new
2564+minor version number do not always require changes to aufs-util.
2565+
2566+Since aufs-util has its own minor version number, you may not be
2567+able to find a GIT branch in aufs-util for your kernel's
2568+exact minor version number.
2569+In this case, you should git-checkout the branch for the
53392da6 2570+nearest lower number.
9dbd164d
AM
2571+
2572+For (an unreleased) example:
fbc438ed
JR
2573+If you are using "linux-5.10" and the "aufs5.10" branch
2574+does not exist in aufs-util repository, then "aufs5.9", "aufs5.8"
9dbd164d
AM
2575+or something numerically smaller is the branch for your kernel.
2576+
53392da6
AM
2577+Also you can view all branches by
2578+ $ git branch -a
2579+
2580+
2581+3. Configuration and Compilation
2582+----------------------------------------
2583+Make sure you have git-checkout'ed the correct branch.
2584+
fbc438ed 2585+For aufs5-linux tree,
c06a8ce3 2586+- enable CONFIG_AUFS_FS.
1e00d052 2587+- set other aufs configurations if necessary.
46016270
AM
2588+- for aufs5.13 and later
2589+ Because aufs is not only an ordinary filesystem (callee of VFS), but
2590+ also a caller of VFS functions for branch filesystems, subclassing of
2591+ the internal locks for LOCKDEP is necessary. LOCKDEP is a debugging
2592+ feature of linux kernel. If you enable CONFIG_LOCKDEP, then you will
2593+ need to customize some LOCKDEP numbers. Here are what I use on my
2594+ test environment.
2595+ CONFIG_LOCKDEP_BITS=21
2596+ CONFIG_LOCKDEP_CHAINS_BITS=21
2597+ CONFIG_LOCKDEP_STACK_TRACE_BITS=24
1e00d052 2598+
fbc438ed 2599+For aufs5-standalone tree,
53392da6
AM
2600+There are several ways to build.
2601+
2602+1.
fbc438ed
JR
2603+- apply ./aufs5-kbuild.patch to your kernel source files.
2604+- apply ./aufs5-base.patch too.
2605+- apply ./aufs5-mmap.patch too.
2606+- apply ./aufs5-standalone.patch too, if you have a plan to set
2607+ CONFIG_AUFS_FS=m. otherwise you don't need ./aufs5-standalone.patch.
537831f9
AM
2608+- copy ./{Documentation,fs,include/uapi/linux/aufs_type.h} files to your
2609+ kernel source tree. Never copy $PWD/include/uapi/linux/Kbuild.
c06a8ce3 2610+- enable CONFIG_AUFS_FS, you can select either
53392da6
AM
2611+ =m or =y.
2612+- and build your kernel as usual.
2613+- install the built kernel.
7eafdf33
AM
2614+- install the header files too by "make headers_install" to the
2615+ directory where you specify. By default, it is $PWD/usr.
b4510431 2616+ "make help" shows a brief note for headers_install.
53392da6
AM
2617+- and reboot your system.
2618+
2619+2.
2620+- module only (CONFIG_AUFS_FS=m).
fbc438ed
JR
2621+- apply ./aufs5-base.patch to your kernel source files.
2622+- apply ./aufs5-mmap.patch too.
2623+- apply ./aufs5-standalone.patch too.
53392da6
AM
2624+- build your kernel, don't forget "make headers_install", and reboot.
2625+- edit ./config.mk and set other aufs configurations if necessary.
b4510431 2626+ Note: You should read $PWD/fs/aufs/Kconfig carefully which describes
53392da6
AM
2627+ every aufs configurations.
2628+- build the module by simple "make".
2629+- you can specify ${KDIR} make variable which points to your kernel
2630+ source tree.
2631+- install the files
2632+ + run "make install" to install the aufs module, or copy the built
b4510431
AM
2633+ $PWD/aufs.ko to /lib/modules/... and run depmod -a (or reboot simply).
2634+ + run "make install_headers" (instead of headers_install) to install
2635+ the modified aufs header file (you can specify DESTDIR which is
2636+ available in aufs standalone version's Makefile only), or copy
2637+ $PWD/usr/include/linux/aufs_type.h to /usr/include/linux or wherever
2638+ you like manually. By default, the target directory is $PWD/usr.
fbc438ed 2639+- no need to apply aufs5-kbuild.patch, nor copying source files to your
53392da6
AM
2640+ kernel source tree.
2641+
b4510431 2642+Note: The header file aufs_type.h is necessary to build aufs-util
53392da6
AM
2643+ as well as "make headers_install" in the kernel source tree.
2644+ headers_install is subject to be forgotten, but it is essentially
2645+ necessary, not only for building aufs-util.
2646+ You may not meet problems without headers_install in some older
2647+ version though.
2648+
2649+And then,
2650+- read README in aufs-util, build and install it
9dbd164d
AM
2651+- note that your distribution may contain an obsoleted version of
2652+ aufs_type.h in /usr/include/linux or something. When you build aufs
2653+ utilities, make sure that your compiler refers the correct aufs header
2654+ file which is built by "make headers_install."
53392da6
AM
2655+- if you want to use readdir(3) in userspace or pathconf(3) wrapper,
2656+ then run "make install_ulib" too. And refer to the aufs manual in
2657+ detail.
2658+
fbc438ed 2659+There several other patches in aufs5-standalone.git. They are all
38d290e6 2660+optional. When you meet some problems, they will help you.
fbc438ed 2661+- aufs5-loopback.patch
38d290e6
JR
2662+ Supports a nested loopback mount in a branch-fs. This patch is
2663+ unnecessary until aufs produces a message like "you may want to try
2664+ another patch for loopback file".
2665+- vfs-ino.patch
2666+ Modifies a system global kernel internal function get_next_ino() in
2667+ order to stop assigning 0 for an inode-number. Not directly related to
2668+ aufs, but recommended generally.
2669+- tmpfs-idr.patch
2670+ Keeps the tmpfs inode number as the lowest value. Effective to reduce
2671+ the size of aufs XINO files for tmpfs branch. Also it prevents the
2672+ duplication of inode number, which is important for backup tools and
2673+ other utilities. When you find aufs XINO files for tmpfs branch
2674+ growing too much, try this patch.
2675+
53392da6
AM
2676+
2677+4. Usage
2678+----------------------------------------
2679+At first, make sure aufs-util are installed, and please read the aufs
2680+manual, aufs.5 in aufs-util.git tree.
2681+$ man -l aufs.5
2682+
2683+And then,
2684+$ mkdir /tmp/rw /tmp/aufs
2685+# mount -t aufs -o br=/tmp/rw:${HOME} none /tmp/aufs
2686+
2687+Here is another example. The result is equivalent.
2688+# mount -t aufs -o br=/tmp/rw=rw:${HOME}=ro none /tmp/aufs
2689+ Or
2690+# mount -t aufs -o br:/tmp/rw none /tmp/aufs
2691+# mount -o remount,append:${HOME} /tmp/aufs
2692+
2693+Then, you can see whole tree of your home dir through /tmp/aufs. If
2694+you modify a file under /tmp/aufs, the one on your home directory is
2695+not affected, instead the same named file will be newly created under
2696+/tmp/rw. And all of your modification to a file will be applied to
2697+the one under /tmp/rw. This is called the file based Copy on Write
2698+(COW) method.
2699+Aufs mount options are described in aufs.5.
2700+If you run chroot or something and make your aufs as a root directory,
2701+then you need to customize the shutdown script. See the aufs manual in
2702+detail.
2703+
2704+Additionally, there are some sample usages of aufs which are a
2705+diskless system with network booting, and LiveCD over NFS.
2706+See sample dir in CVS tree on SourceForge.
2707+
2708+
2709+5. Contact
2710+----------------------------------------
2711+When you have any problems or strange behaviour in aufs, please let me
2712+know with:
2713+- /proc/mounts (instead of the output of mount(8))
2714+- /sys/module/aufs/*
2715+- /sys/fs/aufs/* (if you have them)
2716+- /debug/aufs/* (if you have them)
2717+- linux kernel version
2718+ if your kernel is not plain, for example modified by distributor,
2719+ the url where i can download its source is necessary too.
2720+- aufs version which was printed at loading the module or booting the
2721+ system, instead of the date you downloaded.
2722+- configuration (define/undefine CONFIG_AUFS_xxx)
2723+- kernel configuration or /proc/config.gz (if you have it)
43982f53 2724+- LSM (linux security module, if you are using)
53392da6
AM
2725+- behaviour which you think to be incorrect
2726+- actual operation, reproducible one is better
2727+- mailto: aufs-users at lists.sourceforge.net
2728+
2729+Usually, I don't watch the Public Areas(Bugs, Support Requests, Patches,
2730+and Feature Requests) on SourceForge. Please join and write to
2731+aufs-users ML.
2732+
2733+
2734+6. Acknowledgements
2735+----------------------------------------
2736+Thanks to everyone who have tried and are using aufs, whoever
2737+have reported a bug or any feedback.
2738+
2739+Especially donators:
2740+Tomas Matejicek(slax.org) made a donation (much more than once).
2741+ Since Apr 2010, Tomas M (the author of Slax and Linux Live
2742+ scripts) is making "doubling" donations.
2743+ Unfortunately I cannot list all of the donators, but I really
b4510431 2744+ appreciate.
53392da6
AM
2745+ It ends Aug 2010, but the ordinary donation URL is still available.
2746+ <http://sourceforge.net/donate/index.php?group_id=167503>
2747+Dai Itasaka made a donation (2007/8).
2748+Chuck Smith made a donation (2008/4, 10 and 12).
2749+Henk Schoneveld made a donation (2008/9).
2750+Chih-Wei Huang, ASUS, CTC donated Eee PC 4G (2008/10).
2751+Francois Dupoux made a donation (2008/11).
2752+Bruno Cesar Ribas and Luis Carlos Erpen de Bona, C3SL serves public
2753+ aufs2 GIT tree (2009/2).
2754+William Grant made a donation (2009/3).
2755+Patrick Lane made a donation (2009/4).
2756+The Mail Archive (mail-archive.com) made donations (2009/5).
2757+Nippy Networks (Ed Wildgoose) made a donation (2009/7).
2758+New Dream Network, LLC (www.dreamhost.com) made a donation (2009/11).
2759+Pavel Pronskiy made a donation (2011/2).
2760+Iridium and Inmarsat satellite phone retailer (www.mailasail.com), Nippy
2761+ Networks (Ed Wildgoose) made a donation for hardware (2011/3).
537831f9
AM
2762+Max Lekomcev (DOM-TV project) made a donation (2011/7, 12, 2012/3, 6 and
2763+11).
1e00d052 2764+Sam Liddicott made a donation (2011/9).
86dc4139
AM
2765+Era Scarecrow made a donation (2013/4).
2766+Bor Ratajc made a donation (2013/4).
2767+Alessandro Gorreta made a donation (2013/4).
2768+POIRETTE Marc made a donation (2013/4).
2769+Alessandro Gorreta made a donation (2013/4).
2770+lauri kasvandik made a donation (2013/5).
392086de 2771+"pemasu from Finland" made a donation (2013/7).
523b37e3
AM
2772+The Parted Magic Project made a donation (2013/9 and 11).
2773+Pavel Barta made a donation (2013/10).
38d290e6 2774+Nikolay Pertsev made a donation (2014/5).
c2c0f25c 2775+James B made a donation (2014/7 and 2015/7).
076b876e 2776+Stefano Di Biase made a donation (2014/8).
2000de60 2777+Daniel Epellei made a donation (2015/1).
c4adf169 2778+OmegaPhil made a donation (2016/1, 2018/4).
5afbbe0d 2779+Tomasz Szewczyk made a donation (2016/4).
f2c43d5f 2780+James Burry made a donation (2016/12).
acd2b654 2781+Carsten Rose made a donation (2018/9).
9f237c51 2782+Porteus Kiosk made a donation (2018/10).
53392da6
AM
2783+
2784+Thank you very much.
2785+Donations are always, including future donations, very important and
2786+helpful for me to keep on developing aufs.
2787+
2788+
2789+7.
2790+----------------------------------------
2791+If you are an experienced user, no explanation is needed. Aufs is
2792+just a linux filesystem.
2793+
2794+
2795+Enjoy!
2796+
2797+# Local variables: ;
2798+# mode: text;
2799+# End: ;
7f207e10 2800diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
eca34b5c 2801--- /usr/share/empty/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
319657f6 2802+++ linux/fs/aufs/aufs.h 2021-12-03 15:38:59.929980643 +0100
acd2b654 2803@@ -0,0 +1,62 @@
062440b3 2804+/* SPDX-License-Identifier: GPL-2.0 */
7f207e10 2805+/*
6d176551 2806+ * Copyright (C) 2005-2021 Junjiro R. Okajima
7f207e10
AM
2807+ *
2808+ * This program, aufs is free software; you can redistribute it and/or modify
2809+ * it under the terms of the GNU General Public License as published by
2810+ * the Free Software Foundation; either version 2 of the License, or
2811+ * (at your option) any later version.
2812+ *
2813+ * This program is distributed in the hope that it will be useful,
2814+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2815+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2816+ * GNU General Public License for more details.
2817+ *
2818+ * You should have received a copy of the GNU General Public License
523b37e3 2819+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
7f207e10
AM
2820+ */
2821+
2822+/*
2823+ * all header files
2824+ */
2825+
2826+#ifndef __AUFS_H__
2827+#define __AUFS_H__
2828+
2829+#ifdef __KERNEL__
2830+
2831+#define AuStub(type, name, body, ...) \
2832+ static inline type name(__VA_ARGS__) { body; }
2833+
2834+#define AuStubVoid(name, ...) \
2835+ AuStub(void, name, , __VA_ARGS__)
2836+#define AuStubInt0(name, ...) \
2837+ AuStub(int, name, return 0, __VA_ARGS__)
2838+
2839+#include "debug.h"
2840+
2841+#include "branch.h"
2842+#include "cpup.h"
2843+#include "dcsub.h"
2844+#include "dbgaufs.h"
2845+#include "dentry.h"
2846+#include "dir.h"
8b6a4947 2847+#include "dirren.h"
7f207e10
AM
2848+#include "dynop.h"
2849+#include "file.h"
2850+#include "fstype.h"
8b6a4947 2851+#include "hbl.h"
7f207e10 2852+#include "inode.h"
acd2b654 2853+#include "lcnt.h"
7f207e10
AM
2854+#include "loop.h"
2855+#include "module.h"
7f207e10
AM
2856+#include "opts.h"
2857+#include "rwsem.h"
7f207e10
AM
2858+#include "super.h"
2859+#include "sysaufs.h"
2860+#include "vfsub.h"
2861+#include "whout.h"
2862+#include "wkq.h"
2863+
2864+#endif /* __KERNEL__ */
2865+#endif /* __AUFS_H__ */
2866diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
eca34b5c 2867--- /usr/share/empty/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
319657f6 2868+++ linux/fs/aufs/branch.c 2021-12-03 15:38:59.933313976 +0100
42b5c33a 2869@@ -0,0 +1,1427 @@
cd7a4cd9 2870+// SPDX-License-Identifier: GPL-2.0
7f207e10 2871+/*
6d176551 2872+ * Copyright (C) 2005-2021 Junjiro R. Okajima
7f207e10
AM
2873+ *
2874+ * This program, aufs is free software; you can redistribute it and/or modify
2875+ * it under the terms of the GNU General Public License as published by
2876+ * the Free Software Foundation; either version 2 of the License, or
2877+ * (at your option) any later version.
2878+ *
2879+ * This program is distributed in the hope that it will be useful,
2880+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2881+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2882+ * GNU General Public License for more details.
2883+ *
2884+ * You should have received a copy of the GNU General Public License
523b37e3 2885+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
7f207e10
AM
2886+ */
2887+
2888+/*
2889+ * branch management
2890+ */
2891+
027c5e7a 2892+#include <linux/compat.h>
7f207e10
AM
2893+#include <linux/statfs.h>
2894+#include "aufs.h"
2895+
2896+/*
2897+ * free a single branch
1facf9fc 2898+ */
2899+static void au_br_do_free(struct au_branch *br)
2900+{
2901+ int i;
2902+ struct au_wbr *wbr;
4a4d8108 2903+ struct au_dykey **key;
1facf9fc 2904+
027c5e7a 2905+ au_hnotify_fin_br(br);
8b6a4947
AM
2906+ /* always, regardless the mount option */
2907+ au_dr_hino_free(&br->br_dirren);
062440b3 2908+ au_xino_put(br);
1facf9fc 2909+
acd2b654
AM
2910+ AuLCntZero(au_lcnt_read(&br->br_nfiles, /*do_rev*/0));
2911+ au_lcnt_fin(&br->br_nfiles, /*do_sync*/0);
2912+ AuLCntZero(au_lcnt_read(&br->br_count, /*do_rev*/0));
2913+ au_lcnt_fin(&br->br_count, /*do_sync*/0);
1facf9fc 2914+
2915+ wbr = br->br_wbr;
2916+ if (wbr) {
2917+ for (i = 0; i < AuBrWh_Last; i++)
2918+ dput(wbr->wbr_wh[i]);
2919+ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
dece6358 2920+ AuRwDestroy(&wbr->wbr_wh_rwsem);
1facf9fc 2921+ }
2922+
076b876e
AM
2923+ if (br->br_fhsm) {
2924+ au_br_fhsm_fin(br->br_fhsm);
9f237c51 2925+ au_kfree_try_rcu(br->br_fhsm);
076b876e
AM
2926+ }
2927+
4a4d8108
AM
2928+ key = br->br_dykey;
2929+ for (i = 0; i < AuBrDynOp; i++, key++)
2930+ if (*key)
2931+ au_dy_put(*key);
2932+ else
2933+ break;
2934+
537831f9 2935+ /* recursive lock, s_umount of branch's */
acd2b654 2936+ /* synchronize_rcu(); */ /* why? */
537831f9 2937+ lockdep_off();
86dc4139 2938+ path_put(&br->br_path);
537831f9 2939+ lockdep_on();
9f237c51 2940+ au_kfree_rcu(wbr);
acd2b654
AM
2941+ au_lcnt_wait_for_fin(&br->br_nfiles);
2942+ au_lcnt_wait_for_fin(&br->br_count);
2943+ /* I don't know why, but percpu_refcount requires this */
2944+ /* synchronize_rcu(); */
9f237c51 2945+ au_kfree_rcu(br);
1facf9fc 2946+}
2947+
2948+/*
2949+ * frees all branches
2950+ */
2951+void au_br_free(struct au_sbinfo *sbinfo)
2952+{
2953+ aufs_bindex_t bmax;
2954+ struct au_branch **br;
2955+
dece6358
AM
2956+ AuRwMustWriteLock(&sbinfo->si_rwsem);
2957+
5afbbe0d 2958+ bmax = sbinfo->si_bbot + 1;
1facf9fc 2959+ br = sbinfo->si_branch;
2960+ while (bmax--)
2961+ au_br_do_free(*br++);
2962+}
2963+
2964+/*
2965+ * find the index of a branch which is specified by @br_id.
2966+ */
2967+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
2968+{
5afbbe0d 2969+ aufs_bindex_t bindex, bbot;
1facf9fc 2970+
5afbbe0d
AM
2971+ bbot = au_sbbot(sb);
2972+ for (bindex = 0; bindex <= bbot; bindex++)
1facf9fc 2973+ if (au_sbr_id(sb, bindex) == br_id)
2974+ return bindex;
2975+ return -1;
2976+}
2977+
2978+/* ---------------------------------------------------------------------- */
2979+
2980+/*
2981+ * add a branch
2982+ */
2983+
b752ccd1
AM
2984+static int test_overlap(struct super_block *sb, struct dentry *h_adding,
2985+ struct dentry *h_root)
1facf9fc 2986+{
b752ccd1
AM
2987+ if (unlikely(h_adding == h_root
2988+ || au_test_loopback_overlap(sb, h_adding)))
1facf9fc 2989+ return 1;
b752ccd1
AM
2990+ if (h_adding->d_sb != h_root->d_sb)
2991+ return 0;
2992+ return au_test_subdir(h_adding, h_root)
2993+ || au_test_subdir(h_root, h_adding);
1facf9fc 2994+}
2995+
2996+/*
2997+ * returns a newly allocated branch. @new_nbranch is a number of branches
2998+ * after adding a branch.
2999+ */
3000+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
3001+ int perm)
3002+{
3003+ struct au_branch *add_branch;
3004+ struct dentry *root;
5527c038 3005+ struct inode *inode;
4a4d8108 3006+ int err;
1facf9fc 3007+
4a4d8108 3008+ err = -ENOMEM;
be52b249 3009+ add_branch = kzalloc(sizeof(*add_branch), GFP_NOFS);
1facf9fc 3010+ if (unlikely(!add_branch))
3011+ goto out;
acd2b654 3012+ add_branch->br_xino = au_xino_alloc(/*nfile*/1);
062440b3 3013+ if (unlikely(!add_branch->br_xino))
521ced18 3014+ goto out_br;
027c5e7a
AM
3015+ err = au_hnotify_init_br(add_branch, perm);
3016+ if (unlikely(err))
062440b3 3017+ goto out_xino;
027c5e7a 3018+
1facf9fc 3019+ if (au_br_writable(perm)) {
3020+ /* may be freed separately at changing the branch permission */
be52b249 3021+ add_branch->br_wbr = kzalloc(sizeof(*add_branch->br_wbr),
1facf9fc 3022+ GFP_NOFS);
3023+ if (unlikely(!add_branch->br_wbr))
027c5e7a 3024+ goto out_hnotify;
1facf9fc 3025+ }
3026+
076b876e
AM
3027+ if (au_br_fhsm(perm)) {
3028+ err = au_fhsm_br_alloc(add_branch);
3029+ if (unlikely(err))
3030+ goto out_wbr;
3031+ }
3032+
521ced18 3033+ root = sb->s_root;
e2f27e51 3034+ err = au_sbr_realloc(au_sbi(sb), new_nbranch, /*may_shrink*/0);
4a4d8108 3035+ if (!err)
e2f27e51 3036+ err = au_di_realloc(au_di(root), new_nbranch, /*may_shrink*/0);
5527c038
JR
3037+ if (!err) {
3038+ inode = d_inode(root);
1c60b727
AM
3039+ err = au_hinode_realloc(au_ii(inode), new_nbranch,
3040+ /*may_shrink*/0);
5527c038 3041+ }
4a4d8108
AM
3042+ if (!err)
3043+ return add_branch; /* success */
1facf9fc 3044+
076b876e 3045+out_wbr:
9f237c51 3046+ au_kfree_rcu(add_branch->br_wbr);
027c5e7a
AM
3047+out_hnotify:
3048+ au_hnotify_fin_br(add_branch);
062440b3
AM
3049+out_xino:
3050+ au_xino_put(add_branch);
4f0767ce 3051+out_br:
9f237c51 3052+ au_kfree_rcu(add_branch);
4f0767ce 3053+out:
4a4d8108 3054+ return ERR_PTR(err);
1facf9fc 3055+}
3056+
3057+/*
3058+ * test if the branch permission is legal or not.
3059+ */
3060+static int test_br(struct inode *inode, int brperm, char *path)
3061+{
3062+ int err;
3063+
4a4d8108
AM
3064+ err = (au_br_writable(brperm) && IS_RDONLY(inode));
3065+ if (!err)
3066+ goto out;
1facf9fc 3067+
4a4d8108
AM
3068+ err = -EINVAL;
3069+ pr_err("write permission for readonly mount or inode, %s\n", path);
3070+
4f0767ce 3071+out:
1facf9fc 3072+ return err;
3073+}
3074+
3075+/*
3076+ * returns:
3077+ * 0: success, the caller will add it
3078+ * plus: success, it is already unified, the caller should ignore it
3079+ * minus: error
3080+ */
3081+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
3082+{
3083+ int err;
5afbbe0d 3084+ aufs_bindex_t bbot, bindex;
5527c038 3085+ struct dentry *root, *h_dentry;
1facf9fc 3086+ struct inode *inode, *h_inode;
3087+
3088+ root = sb->s_root;
5afbbe0d
AM
3089+ bbot = au_sbbot(sb);
3090+ if (unlikely(bbot >= 0
1facf9fc 3091+ && au_find_dbindex(root, add->path.dentry) >= 0)) {
3092+ err = 1;
3093+ if (!remount) {
3094+ err = -EINVAL;
4a4d8108 3095+ pr_err("%s duplicated\n", add->pathname);
1facf9fc 3096+ }
3097+ goto out;
3098+ }
3099+
3100+ err = -ENOSPC; /* -E2BIG; */
3101+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
5afbbe0d 3102+ || AUFS_BRANCH_MAX - 1 <= bbot)) {
4a4d8108 3103+ pr_err("number of branches exceeded %s\n", add->pathname);
1facf9fc 3104+ goto out;
3105+ }
3106+
3107+ err = -EDOM;
5afbbe0d 3108+ if (unlikely(add->bindex < 0 || bbot + 1 < add->bindex)) {
4a4d8108 3109+ pr_err("bad index %d\n", add->bindex);
1facf9fc 3110+ goto out;
3111+ }
3112+
5527c038 3113+ inode = d_inode(add->path.dentry);
1facf9fc 3114+ err = -ENOENT;
3115+ if (unlikely(!inode->i_nlink)) {
4a4d8108 3116+ pr_err("no existence %s\n", add->pathname);
1facf9fc 3117+ goto out;
3118+ }
3119+
3120+ err = -EINVAL;
3121+ if (unlikely(inode->i_sb == sb)) {
4a4d8108 3122+ pr_err("%s must be outside\n", add->pathname);
1facf9fc 3123+ goto out;
3124+ }
3125+
3126+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
4a4d8108
AM
3127+ pr_err("unsupported filesystem, %s (%s)\n",
3128+ add->pathname, au_sbtype(inode->i_sb));
1facf9fc 3129+ goto out;
3130+ }
3131+
c1595e42
JR
3132+ if (unlikely(inode->i_sb->s_stack_depth)) {
3133+ pr_err("already stacked, %s (%s)\n",
3134+ add->pathname, au_sbtype(inode->i_sb));
3135+ goto out;
3136+ }
3137+
5527c038 3138+ err = test_br(d_inode(add->path.dentry), add->perm, add->pathname);
1facf9fc 3139+ if (unlikely(err))
3140+ goto out;
3141+
5afbbe0d 3142+ if (bbot < 0)
1facf9fc 3143+ return 0; /* success */
3144+
3145+ err = -EINVAL;
5afbbe0d 3146+ for (bindex = 0; bindex <= bbot; bindex++)
1facf9fc 3147+ if (unlikely(test_overlap(sb, add->path.dentry,
3148+ au_h_dptr(root, bindex)))) {
4a4d8108 3149+ pr_err("%s is overlapped\n", add->pathname);
1facf9fc 3150+ goto out;
3151+ }
3152+
3153+ err = 0;
3154+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
5527c038
JR
3155+ h_dentry = au_h_dptr(root, 0);
3156+ h_inode = d_inode(h_dentry);
1facf9fc 3157+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
0c3ec466
AM
3158+ || !uid_eq(h_inode->i_uid, inode->i_uid)
3159+ || !gid_eq(h_inode->i_gid, inode->i_gid))
3160+ pr_warn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
3161+ add->pathname,
3162+ i_uid_read(inode), i_gid_read(inode),
3163+ (inode->i_mode & S_IALLUGO),
3164+ i_uid_read(h_inode), i_gid_read(h_inode),
3165+ (h_inode->i_mode & S_IALLUGO));
1facf9fc 3166+ }
3167+
4f0767ce 3168+out:
1facf9fc 3169+ return err;
3170+}
3171+
3172+/*
3173+ * initialize or clean the whiteouts for an adding branch
3174+ */
3175+static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
86dc4139 3176+ int new_perm)
1facf9fc 3177+{
3178+ int err, old_perm;
3179+ aufs_bindex_t bindex;
febd17d6 3180+ struct inode *h_inode;
1facf9fc 3181+ struct au_wbr *wbr;
3182+ struct au_hinode *hdir;
5527c038 3183+ struct dentry *h_dentry;
1facf9fc 3184+
86dc4139
AM
3185+ err = vfsub_mnt_want_write(au_br_mnt(br));
3186+ if (unlikely(err))
3187+ goto out;
3188+
1facf9fc 3189+ wbr = br->br_wbr;
3190+ old_perm = br->br_perm;
3191+ br->br_perm = new_perm;
3192+ hdir = NULL;
febd17d6 3193+ h_inode = NULL;
1facf9fc 3194+ bindex = au_br_index(sb, br->br_id);
3195+ if (0 <= bindex) {
5527c038 3196+ hdir = au_hi(d_inode(sb->s_root), bindex);
5afbbe0d 3197+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 3198+ } else {
5527c038 3199+ h_dentry = au_br_dentry(br);
febd17d6
JR
3200+ h_inode = d_inode(h_dentry);
3201+ inode_lock_nested(h_inode, AuLsc_I_PARENT);
1facf9fc 3202+ }
3203+ if (!wbr)
86dc4139 3204+ err = au_wh_init(br, sb);
1facf9fc 3205+ else {
3206+ wbr_wh_write_lock(wbr);
86dc4139 3207+ err = au_wh_init(br, sb);
1facf9fc 3208+ wbr_wh_write_unlock(wbr);
3209+ }
3210+ if (hdir)
5afbbe0d 3211+ au_hn_inode_unlock(hdir);
1facf9fc 3212+ else
febd17d6 3213+ inode_unlock(h_inode);
86dc4139 3214+ vfsub_mnt_drop_write(au_br_mnt(br));
1facf9fc 3215+ br->br_perm = old_perm;
3216+
3217+ if (!err && wbr && !au_br_writable(new_perm)) {
9f237c51 3218+ au_kfree_rcu(wbr);
1facf9fc 3219+ br->br_wbr = NULL;
3220+ }
3221+
86dc4139 3222+out:
1facf9fc 3223+ return err;
3224+}
3225+
3226+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
86dc4139 3227+ int perm)
1facf9fc 3228+{
3229+ int err;
4a4d8108 3230+ struct kstatfs kst;
1facf9fc 3231+ struct au_wbr *wbr;
3232+
3233+ wbr = br->br_wbr;
dece6358 3234+ au_rw_init(&wbr->wbr_wh_rwsem);
1facf9fc 3235+ atomic_set(&wbr->wbr_wh_running, 0);
1facf9fc 3236+
4a4d8108
AM
3237+ /*
3238+ * a limit for rmdir/rename a dir
523b37e3 3239+ * cf. AUFS_MAX_NAMELEN in include/uapi/linux/aufs_type.h
4a4d8108 3240+ */
86dc4139 3241+ err = vfs_statfs(&br->br_path, &kst);
4a4d8108
AM
3242+ if (unlikely(err))
3243+ goto out;
3244+ err = -EINVAL;
3245+ if (kst.f_namelen >= NAME_MAX)
86dc4139 3246+ err = au_br_init_wh(sb, br, perm);
4a4d8108 3247+ else
523b37e3
AM
3248+ pr_err("%pd(%s), unsupported namelen %ld\n",
3249+ au_br_dentry(br),
86dc4139 3250+ au_sbtype(au_br_dentry(br)->d_sb), kst.f_namelen);
1facf9fc 3251+
4f0767ce 3252+out:
1facf9fc 3253+ return err;
3254+}
3255+
c1595e42 3256+/* initialize a new branch */
1facf9fc 3257+static int au_br_init(struct au_branch *br, struct super_block *sb,
3258+ struct au_opt_add *add)
3259+{
3260+ int err;
062440b3
AM
3261+ struct au_branch *brbase;
3262+ struct file *xf;
5527c038 3263+ struct inode *h_inode;
1facf9fc 3264+
3265+ err = 0;
1facf9fc 3266+ br->br_perm = add->perm;
86dc4139 3267+ br->br_path = add->path; /* set first, path_get() later */
4a4d8108 3268+ spin_lock_init(&br->br_dykey_lock);
acd2b654
AM
3269+ au_lcnt_init(&br->br_nfiles, /*release*/NULL);
3270+ au_lcnt_init(&br->br_count, /*release*/NULL);
1facf9fc 3271+ br->br_id = au_new_br_id(sb);
7f207e10 3272+ AuDebugOn(br->br_id < 0);
1facf9fc 3273+
8b6a4947
AM
3274+ /* always, regardless the given option */
3275+ err = au_dr_br_init(sb, br, &add->path);
3276+ if (unlikely(err))
3277+ goto out_err;
3278+
1facf9fc 3279+ if (au_br_writable(add->perm)) {
86dc4139 3280+ err = au_wbr_init(br, sb, add->perm);
1facf9fc 3281+ if (unlikely(err))
b752ccd1 3282+ goto out_err;
1facf9fc 3283+ }
3284+
3285+ if (au_opt_test(au_mntflags(sb), XINO)) {
062440b3 3286+ brbase = au_sbr(sb, 0);
acd2b654 3287+ xf = au_xino_file(brbase->br_xino, /*idx*/-1);
062440b3 3288+ AuDebugOn(!xf);
5527c038 3289+ h_inode = d_inode(add->path.dentry);
062440b3 3290+ err = au_xino_init_br(sb, br, h_inode->i_ino, &xf->f_path);
1facf9fc 3291+ if (unlikely(err)) {
acd2b654 3292+ AuDebugOn(au_xino_file(br->br_xino, /*idx*/-1));
b752ccd1 3293+ goto out_err;
1facf9fc 3294+ }
3295+ }
3296+
3297+ sysaufs_br_init(br);
86dc4139 3298+ path_get(&br->br_path);
b752ccd1 3299+ goto out; /* success */
1facf9fc 3300+
4f0767ce 3301+out_err:
86dc4139 3302+ memset(&br->br_path, 0, sizeof(br->br_path));
4f0767ce 3303+out:
1facf9fc 3304+ return err;
3305+}
3306+
3307+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
5afbbe0d 3308+ struct au_branch *br, aufs_bindex_t bbot,
1facf9fc 3309+ aufs_bindex_t amount)
3310+{
3311+ struct au_branch **brp;
3312+
dece6358
AM
3313+ AuRwMustWriteLock(&sbinfo->si_rwsem);
3314+
1facf9fc 3315+ brp = sbinfo->si_branch + bindex;
3316+ memmove(brp + 1, brp, sizeof(*brp) * amount);
3317+ *brp = br;
5afbbe0d
AM
3318+ sbinfo->si_bbot++;
3319+ if (unlikely(bbot < 0))
3320+ sbinfo->si_bbot = 0;
1facf9fc 3321+}
3322+
3323+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
5afbbe0d 3324+ aufs_bindex_t bbot, aufs_bindex_t amount)
1facf9fc 3325+{
3326+ struct au_hdentry *hdp;
3327+
1308ab2a 3328+ AuRwMustWriteLock(&dinfo->di_rwsem);
3329+
5afbbe0d 3330+ hdp = au_hdentry(dinfo, bindex);
1facf9fc 3331+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
3332+ au_h_dentry_init(hdp);
5afbbe0d
AM
3333+ dinfo->di_bbot++;
3334+ if (unlikely(bbot < 0))
3335+ dinfo->di_btop = 0;
1facf9fc 3336+}
3337+
3338+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
5afbbe0d 3339+ aufs_bindex_t bbot, aufs_bindex_t amount)
1facf9fc 3340+{
3341+ struct au_hinode *hip;
3342+
1308ab2a 3343+ AuRwMustWriteLock(&iinfo->ii_rwsem);
3344+
5afbbe0d 3345+ hip = au_hinode(iinfo, bindex);
1facf9fc 3346+ memmove(hip + 1, hip, sizeof(*hip) * amount);
5afbbe0d
AM
3347+ au_hinode_init(hip);
3348+ iinfo->ii_bbot++;
3349+ if (unlikely(bbot < 0))
3350+ iinfo->ii_btop = 0;
1facf9fc 3351+}
3352+
86dc4139
AM
3353+static void au_br_do_add(struct super_block *sb, struct au_branch *br,
3354+ aufs_bindex_t bindex)
1facf9fc 3355+{
86dc4139 3356+ struct dentry *root, *h_dentry;
5527c038 3357+ struct inode *root_inode, *h_inode;
5afbbe0d 3358+ aufs_bindex_t bbot, amount;
1facf9fc 3359+
3360+ root = sb->s_root;
5527c038 3361+ root_inode = d_inode(root);
5afbbe0d
AM
3362+ bbot = au_sbbot(sb);
3363+ amount = bbot + 1 - bindex;
86dc4139 3364+ h_dentry = au_br_dentry(br);
53392da6 3365+ au_sbilist_lock();
5afbbe0d
AM
3366+ au_br_do_add_brp(au_sbi(sb), bindex, br, bbot, amount);
3367+ au_br_do_add_hdp(au_di(root), bindex, bbot, amount);
3368+ au_br_do_add_hip(au_ii(root_inode), bindex, bbot, amount);
1facf9fc 3369+ au_set_h_dptr(root, bindex, dget(h_dentry));
5527c038
JR
3370+ h_inode = d_inode(h_dentry);
3371+ au_set_h_iptr(root_inode, bindex, au_igrab(h_inode), /*flags*/0);
53392da6 3372+ au_sbilist_unlock();
1facf9fc 3373+}
3374+
3375+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
3376+{
3377+ int err;
5afbbe0d 3378+ aufs_bindex_t bbot, add_bindex;
1facf9fc 3379+ struct dentry *root, *h_dentry;
3380+ struct inode *root_inode;
3381+ struct au_branch *add_branch;
3382+
3383+ root = sb->s_root;
5527c038 3384+ root_inode = d_inode(root);
1facf9fc 3385+ IMustLock(root_inode);
5afbbe0d 3386+ IiMustWriteLock(root_inode);
1facf9fc 3387+ err = test_add(sb, add, remount);
3388+ if (unlikely(err < 0))
3389+ goto out;
3390+ if (err) {
3391+ err = 0;
3392+ goto out; /* success */
3393+ }
3394+
5afbbe0d
AM
3395+ bbot = au_sbbot(sb);
3396+ add_branch = au_br_alloc(sb, bbot + 2, add->perm);
1facf9fc 3397+ err = PTR_ERR(add_branch);
3398+ if (IS_ERR(add_branch))
3399+ goto out;
3400+
3401+ err = au_br_init(add_branch, sb, add);
3402+ if (unlikely(err)) {
3403+ au_br_do_free(add_branch);
3404+ goto out;
3405+ }
3406+
3407+ add_bindex = add->bindex;
062440b3
AM
3408+ sysaufs_brs_del(sb, add_bindex); /* remove successors */
3409+ au_br_do_add(sb, add_branch, add_bindex);
3410+ sysaufs_brs_add(sb, add_bindex); /* append successors */
3411+ dbgaufs_brs_add(sb, add_bindex, /*topdown*/0); /* rename successors */
1facf9fc 3412+
86dc4139 3413+ h_dentry = add->path.dentry;
1308ab2a 3414+ if (!add_bindex) {
1facf9fc 3415+ au_cpup_attr_all(root_inode, /*force*/1);
1308ab2a 3416+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
3417+ } else
5527c038 3418+ au_add_nlink(root_inode, d_inode(h_dentry));
1facf9fc 3419+
4f0767ce 3420+out:
1facf9fc 3421+ return err;
3422+}
3423+
3424+/* ---------------------------------------------------------------------- */
3425+
79b8bda9 3426+static unsigned long long au_farray_cb(struct super_block *sb, void *a,
076b876e
AM
3427+ unsigned long long max __maybe_unused,
3428+ void *arg)
3429+{
3430+ unsigned long long n;
3431+ struct file **p, *f;
8b6a4947
AM
3432+ struct hlist_bl_head *files;
3433+ struct hlist_bl_node *pos;
076b876e 3434+ struct au_finfo *finfo;
076b876e
AM
3435+
3436+ n = 0;
3437+ p = a;
3438+ files = &au_sbi(sb)->si_files;
8b6a4947
AM
3439+ hlist_bl_lock(files);
3440+ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) {
076b876e
AM
3441+ f = finfo->fi_file;
3442+ if (file_count(f)
3443+ && !special_file(file_inode(f)->i_mode)) {
3444+ get_file(f);
3445+ *p++ = f;
3446+ n++;
3447+ AuDebugOn(n > max);
3448+ }
3449+ }
8b6a4947 3450+ hlist_bl_unlock(files);
076b876e
AM
3451+
3452+ return n;
3453+}
3454+
3455+static struct file **au_farray_alloc(struct super_block *sb,
3456+ unsigned long long *max)
3457+{
acd2b654
AM
3458+ struct au_sbinfo *sbi;
3459+
3460+ sbi = au_sbi(sb);
3461+ *max = au_lcnt_read(&sbi->si_nfiles, /*do_rev*/1);
79b8bda9 3462+ return au_array_alloc(max, au_farray_cb, sb, /*arg*/NULL);
076b876e
AM
3463+}
3464+
3465+static void au_farray_free(struct file **a, unsigned long long max)
3466+{
3467+ unsigned long long ull;
3468+
3469+ for (ull = 0; ull < max; ull++)
3470+ if (a[ull])
3471+ fput(a[ull]);
be52b249 3472+ kvfree(a);
076b876e
AM
3473+}
3474+
3475+/* ---------------------------------------------------------------------- */
3476+
1facf9fc 3477+/*
3478+ * delete a branch
3479+ */
3480+
3481+/* to show the line number, do not make it inlined function */
4a4d8108 3482+#define AuVerbose(do_info, fmt, ...) do { \
1facf9fc 3483+ if (do_info) \
4a4d8108 3484+ pr_info(fmt, ##__VA_ARGS__); \
1facf9fc 3485+} while (0)
3486+
5afbbe0d
AM
3487+static int au_test_ibusy(struct inode *inode, aufs_bindex_t btop,
3488+ aufs_bindex_t bbot)
027c5e7a 3489+{
5afbbe0d 3490+ return (inode && !S_ISDIR(inode->i_mode)) || btop == bbot;
027c5e7a
AM
3491+}
3492+
5afbbe0d
AM
3493+static int au_test_dbusy(struct dentry *dentry, aufs_bindex_t btop,
3494+ aufs_bindex_t bbot)
027c5e7a 3495+{
5afbbe0d 3496+ return au_test_ibusy(d_inode(dentry), btop, bbot);
027c5e7a
AM
3497+}
3498+
1facf9fc 3499+/*
3500+ * test if the branch is deletable or not.
3501+ */
3502+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
b752ccd1 3503+ unsigned int sigen, const unsigned int verbose)
1facf9fc 3504+{
3505+ int err, i, j, ndentry;
5afbbe0d 3506+ aufs_bindex_t btop, bbot;
1facf9fc 3507+ struct au_dcsub_pages dpages;
3508+ struct au_dpage *dpage;
3509+ struct dentry *d;
1facf9fc 3510+
3511+ err = au_dpages_init(&dpages, GFP_NOFS);
3512+ if (unlikely(err))
3513+ goto out;
3514+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
3515+ if (unlikely(err))
3516+ goto out_dpages;
3517+
1facf9fc 3518+ for (i = 0; !err && i < dpages.ndpage; i++) {
3519+ dpage = dpages.dpages + i;
3520+ ndentry = dpage->ndentry;
3521+ for (j = 0; !err && j < ndentry; j++) {
3522+ d = dpage->dentries[j];
c1595e42 3523+ AuDebugOn(au_dcount(d) <= 0);
027c5e7a 3524+ if (!au_digen_test(d, sigen)) {
1facf9fc 3525+ di_read_lock_child(d, AuLock_IR);
027c5e7a
AM
3526+ if (unlikely(au_dbrange_test(d))) {
3527+ di_read_unlock(d, AuLock_IR);
3528+ continue;
3529+ }
3530+ } else {
1facf9fc 3531+ di_write_lock_child(d);
027c5e7a
AM
3532+ if (unlikely(au_dbrange_test(d))) {
3533+ di_write_unlock(d);
3534+ continue;
3535+ }
1facf9fc 3536+ err = au_reval_dpath(d, sigen);
3537+ if (!err)
3538+ di_downgrade_lock(d, AuLock_IR);
3539+ else {
3540+ di_write_unlock(d);
3541+ break;
3542+ }
3543+ }
3544+
027c5e7a 3545+ /* AuDbgDentry(d); */
5afbbe0d
AM
3546+ btop = au_dbtop(d);
3547+ bbot = au_dbbot(d);
3548+ if (btop <= bindex
3549+ && bindex <= bbot
1facf9fc 3550+ && au_h_dptr(d, bindex)
5afbbe0d 3551+ && au_test_dbusy(d, btop, bbot)) {
1facf9fc 3552+ err = -EBUSY;
523b37e3 3553+ AuVerbose(verbose, "busy %pd\n", d);
027c5e7a 3554+ AuDbgDentry(d);
1facf9fc 3555+ }
3556+ di_read_unlock(d, AuLock_IR);
3557+ }
3558+ }
3559+
4f0767ce 3560+out_dpages:
1facf9fc 3561+ au_dpages_free(&dpages);
4f0767ce 3562+out:
1facf9fc 3563+ return err;
3564+}
3565+
3566+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
b752ccd1 3567+ unsigned int sigen, const unsigned int verbose)
1facf9fc 3568+{
3569+ int err;
7f207e10
AM
3570+ unsigned long long max, ull;
3571+ struct inode *i, **array;
5afbbe0d 3572+ aufs_bindex_t btop, bbot;
1facf9fc 3573+
7f207e10
AM
3574+ array = au_iarray_alloc(sb, &max);
3575+ err = PTR_ERR(array);
3576+ if (IS_ERR(array))
3577+ goto out;
3578+
1facf9fc 3579+ err = 0;
7f207e10
AM
3580+ AuDbg("b%d\n", bindex);
3581+ for (ull = 0; !err && ull < max; ull++) {
3582+ i = array[ull];
076b876e
AM
3583+ if (unlikely(!i))
3584+ break;
7f207e10 3585+ if (i->i_ino == AUFS_ROOT_INO)
1facf9fc 3586+ continue;
3587+
7f207e10 3588+ /* AuDbgInode(i); */
537831f9 3589+ if (au_iigen(i, NULL) == sigen)
1facf9fc 3590+ ii_read_lock_child(i);
3591+ else {
3592+ ii_write_lock_child(i);
027c5e7a
AM
3593+ err = au_refresh_hinode_self(i);
3594+ au_iigen_dec(i);
1facf9fc 3595+ if (!err)
3596+ ii_downgrade_lock(i);
3597+ else {
3598+ ii_write_unlock(i);
3599+ break;
3600+ }
3601+ }
3602+
5afbbe0d
AM
3603+ btop = au_ibtop(i);
3604+ bbot = au_ibbot(i);
3605+ if (btop <= bindex
3606+ && bindex <= bbot
1facf9fc 3607+ && au_h_iptr(i, bindex)
5afbbe0d 3608+ && au_test_ibusy(i, btop, bbot)) {
1facf9fc 3609+ err = -EBUSY;
3610+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
7f207e10 3611+ AuDbgInode(i);
1facf9fc 3612+ }
3613+ ii_read_unlock(i);
3614+ }
7f207e10 3615+ au_iarray_free(array, max);
1facf9fc 3616+
7f207e10 3617+out:
1facf9fc 3618+ return err;
3619+}
3620+
b752ccd1
AM
3621+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
3622+ const unsigned int verbose)
1facf9fc 3623+{
3624+ int err;
3625+ unsigned int sigen;
3626+
3627+ sigen = au_sigen(root->d_sb);
3628+ DiMustNoWaiters(root);
5527c038 3629+ IiMustNoWaiters(d_inode(root));
1facf9fc 3630+ di_write_unlock(root);
b752ccd1 3631+ err = test_dentry_busy(root, bindex, sigen, verbose);
1facf9fc 3632+ if (!err)
b752ccd1 3633+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose);
1facf9fc 3634+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
3635+
3636+ return err;
3637+}
3638+
076b876e
AM
3639+static int test_dir_busy(struct file *file, aufs_bindex_t br_id,
3640+ struct file **to_free, int *idx)
3641+{
3642+ int err;
c1595e42 3643+ unsigned char matched, root;
5afbbe0d 3644+ aufs_bindex_t bindex, bbot;
076b876e
AM
3645+ struct au_fidir *fidir;
3646+ struct au_hfile *hfile;
3647+
3648+ err = 0;
2000de60 3649+ root = IS_ROOT(file->f_path.dentry);
c1595e42
JR
3650+ if (root) {
3651+ get_file(file);
3652+ to_free[*idx] = file;
3653+ (*idx)++;
3654+ goto out;
3655+ }
3656+
076b876e 3657+ matched = 0;
076b876e
AM
3658+ fidir = au_fi(file)->fi_hdir;
3659+ AuDebugOn(!fidir);
5afbbe0d
AM
3660+ bbot = au_fbbot_dir(file);
3661+ for (bindex = au_fbtop(file); bindex <= bbot; bindex++) {
076b876e
AM
3662+ hfile = fidir->fd_hfile + bindex;
3663+ if (!hfile->hf_file)
3664+ continue;
3665+
c1595e42 3666+ if (hfile->hf_br->br_id == br_id) {
076b876e 3667+ matched = 1;
076b876e 3668+ break;
c1595e42 3669+ }
076b876e 3670+ }
c1595e42 3671+ if (matched)
076b876e
AM
3672+ err = -EBUSY;
3673+
3674+out:
3675+ return err;
3676+}
3677+
3678+static int test_file_busy(struct super_block *sb, aufs_bindex_t br_id,
3679+ struct file **to_free, int opened)
3680+{
3681+ int err, idx;
3682+ unsigned long long ull, max;
5afbbe0d 3683+ aufs_bindex_t btop;
076b876e 3684+ struct file *file, **array;
076b876e
AM
3685+ struct dentry *root;
3686+ struct au_hfile *hfile;
3687+
3688+ array = au_farray_alloc(sb, &max);
3689+ err = PTR_ERR(array);
3690+ if (IS_ERR(array))
3691+ goto out;
3692+
3693+ err = 0;
3694+ idx = 0;
3695+ root = sb->s_root;
3696+ di_write_unlock(root);
3697+ for (ull = 0; ull < max; ull++) {
3698+ file = array[ull];
3699+ if (unlikely(!file))
3700+ break;
3701+
3702+ /* AuDbg("%pD\n", file); */
3703+ fi_read_lock(file);
5afbbe0d 3704+ btop = au_fbtop(file);
2000de60 3705+ if (!d_is_dir(file->f_path.dentry)) {
076b876e
AM
3706+ hfile = &au_fi(file)->fi_htop;
3707+ if (hfile->hf_br->br_id == br_id)
3708+ err = -EBUSY;
3709+ } else
3710+ err = test_dir_busy(file, br_id, to_free, &idx);
3711+ fi_read_unlock(file);
3712+ if (unlikely(err))
3713+ break;
3714+ }
3715+ di_write_lock_child(root);
3716+ au_farray_free(array, max);
3717+ AuDebugOn(idx > opened);
3718+
3719+out:
3720+ return err;
3721+}
3722+
3723+static void br_del_file(struct file **to_free, unsigned long long opened,
062440b3 3724+ aufs_bindex_t br_id)
076b876e
AM
3725+{
3726+ unsigned long long ull;
5afbbe0d 3727+ aufs_bindex_t bindex, btop, bbot, bfound;
076b876e
AM
3728+ struct file *file;
3729+ struct au_fidir *fidir;
3730+ struct au_hfile *hfile;
3731+
3732+ for (ull = 0; ull < opened; ull++) {
3733+ file = to_free[ull];
3734+ if (unlikely(!file))
3735+ break;
3736+
3737+ /* AuDbg("%pD\n", file); */
2000de60 3738+ AuDebugOn(!d_is_dir(file->f_path.dentry));
076b876e
AM
3739+ bfound = -1;
3740+ fidir = au_fi(file)->fi_hdir;
3741+ AuDebugOn(!fidir);
3742+ fi_write_lock(file);
5afbbe0d
AM
3743+ btop = au_fbtop(file);
3744+ bbot = au_fbbot_dir(file);
3745+ for (bindex = btop; bindex <= bbot; bindex++) {
076b876e
AM
3746+ hfile = fidir->fd_hfile + bindex;
3747+ if (!hfile->hf_file)
3748+ continue;
3749+
3750+ if (hfile->hf_br->br_id == br_id) {
3751+ bfound = bindex;
3752+ break;
3753+ }
3754+ }
3755+ AuDebugOn(bfound < 0);
3756+ au_set_h_fptr(file, bfound, NULL);
5afbbe0d
AM
3757+ if (bfound == btop) {
3758+ for (btop++; btop <= bbot; btop++)
3759+ if (au_hf_dir(file, btop)) {
3760+ au_set_fbtop(file, btop);
076b876e
AM
3761+ break;
3762+ }
3763+ }
3764+ fi_write_unlock(file);
3765+ }
3766+}
3767+
1facf9fc 3768+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
3769+ const aufs_bindex_t bindex,
5afbbe0d 3770+ const aufs_bindex_t bbot)
1facf9fc 3771+{
3772+ struct au_branch **brp, **p;
3773+
dece6358
AM
3774+ AuRwMustWriteLock(&sbinfo->si_rwsem);
3775+
1facf9fc 3776+ brp = sbinfo->si_branch + bindex;
5afbbe0d
AM
3777+ if (bindex < bbot)
3778+ memmove(brp, brp + 1, sizeof(*brp) * (bbot - bindex));
3779+ sbinfo->si_branch[0 + bbot] = NULL;
3780+ sbinfo->si_bbot--;
1facf9fc 3781+
e2f27e51
AM
3782+ p = au_krealloc(sbinfo->si_branch, sizeof(*p) * bbot, AuGFP_SBILIST,
3783+ /*may_shrink*/1);
1facf9fc 3784+ if (p)
3785+ sbinfo->si_branch = p;
4a4d8108 3786+ /* harmless error */
1facf9fc 3787+}
3788+
3789+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
5afbbe0d 3790+ const aufs_bindex_t bbot)
1facf9fc 3791+{
3792+ struct au_hdentry *hdp, *p;
3793+
1308ab2a 3794+ AuRwMustWriteLock(&dinfo->di_rwsem);
3795+
5afbbe0d
AM
3796+ hdp = au_hdentry(dinfo, bindex);
3797+ if (bindex < bbot)
3798+ memmove(hdp, hdp + 1, sizeof(*hdp) * (bbot - bindex));
3799+ /* au_h_dentry_init(au_hdentry(dinfo, bbot); */
3800+ dinfo->di_bbot--;
1facf9fc 3801+
e2f27e51
AM
3802+ p = au_krealloc(dinfo->di_hdentry, sizeof(*p) * bbot, AuGFP_SBILIST,
3803+ /*may_shrink*/1);
1facf9fc 3804+ if (p)
3805+ dinfo->di_hdentry = p;
4a4d8108 3806+ /* harmless error */
1facf9fc 3807+}
3808+
3809+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
5afbbe0d 3810+ const aufs_bindex_t bbot)
1facf9fc 3811+{
3812+ struct au_hinode *hip, *p;
3813+
1308ab2a 3814+ AuRwMustWriteLock(&iinfo->ii_rwsem);
3815+
5afbbe0d
AM
3816+ hip = au_hinode(iinfo, bindex);
3817+ if (bindex < bbot)
3818+ memmove(hip, hip + 1, sizeof(*hip) * (bbot - bindex));
3819+ /* au_hinode_init(au_hinode(iinfo, bbot)); */
3820+ iinfo->ii_bbot--;
1facf9fc 3821+
e2f27e51
AM
3822+ p = au_krealloc(iinfo->ii_hinode, sizeof(*p) * bbot, AuGFP_SBILIST,
3823+ /*may_shrink*/1);
1facf9fc 3824+ if (p)
3825+ iinfo->ii_hinode = p;
4a4d8108 3826+ /* harmless error */
1facf9fc 3827+}
3828+
3829+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
3830+ struct au_branch *br)
3831+{
5afbbe0d 3832+ aufs_bindex_t bbot;
1facf9fc 3833+ struct au_sbinfo *sbinfo;
53392da6
AM
3834+ struct dentry *root, *h_root;
3835+ struct inode *inode, *h_inode;
3836+ struct au_hinode *hinode;
1facf9fc 3837+
dece6358
AM
3838+ SiMustWriteLock(sb);
3839+
1facf9fc 3840+ root = sb->s_root;
5527c038 3841+ inode = d_inode(root);
1facf9fc 3842+ sbinfo = au_sbi(sb);
5afbbe0d 3843+ bbot = sbinfo->si_bbot;
1facf9fc 3844+
53392da6
AM
3845+ h_root = au_h_dptr(root, bindex);
3846+ hinode = au_hi(inode, bindex);
3847+ h_inode = au_igrab(hinode->hi_inode);
3848+ au_hiput(hinode);
1facf9fc 3849+
53392da6 3850+ au_sbilist_lock();
5afbbe0d
AM
3851+ au_br_do_del_brp(sbinfo, bindex, bbot);
3852+ au_br_do_del_hdp(au_di(root), bindex, bbot);
3853+ au_br_do_del_hip(au_ii(inode), bindex, bbot);
53392da6
AM
3854+ au_sbilist_unlock();
3855+
8b6a4947
AM
3856+ /* ignore an error */
3857+ au_dr_br_fin(sb, br); /* always, regardless the mount option */
3858+
53392da6
AM
3859+ dput(h_root);
3860+ iput(h_inode);
3861+ au_br_do_free(br);
1facf9fc 3862+}
3863+
79b8bda9
AM
3864+static unsigned long long empty_cb(struct super_block *sb, void *array,
3865+ unsigned long long max, void *arg)
076b876e
AM
3866+{
3867+ return max;
3868+}
3869+
1facf9fc 3870+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
3871+{
3872+ int err, rerr, i;
076b876e 3873+ unsigned long long opened;
1facf9fc 3874+ unsigned int mnt_flags;
5afbbe0d 3875+ aufs_bindex_t bindex, bbot, br_id;
1facf9fc 3876+ unsigned char do_wh, verbose;
3877+ struct au_branch *br;
3878+ struct au_wbr *wbr;
076b876e
AM
3879+ struct dentry *root;
3880+ struct file **to_free;
1facf9fc 3881+
3882+ err = 0;
076b876e
AM
3883+ opened = 0;
3884+ to_free = NULL;
3885+ root = sb->s_root;
3886+ bindex = au_find_dbindex(root, del->h_path.dentry);
1facf9fc 3887+ if (bindex < 0) {
3888+ if (remount)
3889+ goto out; /* success */
3890+ err = -ENOENT;
4a4d8108 3891+ pr_err("%s no such branch\n", del->pathname);
1facf9fc 3892+ goto out;
3893+ }
3894+ AuDbg("bindex b%d\n", bindex);
3895+
3896+ err = -EBUSY;
3897+ mnt_flags = au_mntflags(sb);
3898+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
5afbbe0d
AM
3899+ bbot = au_sbbot(sb);
3900+ if (unlikely(!bbot)) {
1facf9fc 3901+ AuVerbose(verbose, "no more branches left\n");
3902+ goto out;
3903+ }
acd2b654 3904+
1facf9fc 3905+ br = au_sbr(sb, bindex);
86dc4139 3906+ AuDebugOn(!path_equal(&br->br_path, &del->h_path));
acd2b654
AM
3907+ if (unlikely(au_lcnt_read(&br->br_count, /*do_rev*/1))) {
3908+ AuVerbose(verbose, "br %pd2 is busy now\n", del->h_path.dentry);
3909+ goto out;
3910+ }
076b876e
AM
3911+
3912+ br_id = br->br_id;
acd2b654 3913+ opened = au_lcnt_read(&br->br_nfiles, /*do_rev*/1);
076b876e 3914+ if (unlikely(opened)) {
79b8bda9 3915+ to_free = au_array_alloc(&opened, empty_cb, sb, NULL);
076b876e
AM
3916+ err = PTR_ERR(to_free);
3917+ if (IS_ERR(to_free))
3918+ goto out;
3919+
3920+ err = test_file_busy(sb, br_id, to_free, opened);
3921+ if (unlikely(err)) {
3922+ AuVerbose(verbose, "%llu file(s) opened\n", opened);
3923+ goto out;
3924+ }
1facf9fc 3925+ }
3926+
3927+ wbr = br->br_wbr;
3928+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
3929+ if (do_wh) {
1308ab2a 3930+ /* instead of WbrWhMustWriteLock(wbr) */
3931+ SiMustWriteLock(sb);
1facf9fc 3932+ for (i = 0; i < AuBrWh_Last; i++) {
3933+ dput(wbr->wbr_wh[i]);
3934+ wbr->wbr_wh[i] = NULL;
3935+ }
3936+ }
3937+
076b876e 3938+ err = test_children_busy(root, bindex, verbose);
1facf9fc 3939+ if (unlikely(err)) {
3940+ if (do_wh)
3941+ goto out_wh;
3942+ goto out;
3943+ }
3944+
3945+ err = 0;
076b876e
AM
3946+ if (to_free) {
3947+ /*
3948+ * now we confirmed the branch is deletable.
3949+ * let's free the remaining opened dirs on the branch.
3950+ */
3951+ di_write_unlock(root);
3952+ br_del_file(to_free, opened, br_id);
3953+ di_write_lock_child(root);
3954+ }
3955+
062440b3
AM
3956+ sysaufs_brs_del(sb, bindex); /* remove successors */
3957+ dbgaufs_xino_del(br); /* remove one */
3958+ au_br_do_del(sb, bindex, br);
3959+ sysaufs_brs_add(sb, bindex); /* append successors */
3960+ dbgaufs_brs_add(sb, bindex, /*topdown*/1); /* rename successors */
1facf9fc 3961+
1308ab2a 3962+ if (!bindex) {
5527c038 3963+ au_cpup_attr_all(d_inode(root), /*force*/1);
1308ab2a 3964+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
3965+ } else
5527c038 3966+ au_sub_nlink(d_inode(root), d_inode(del->h_path.dentry));
1facf9fc 3967+ if (au_opt_test(mnt_flags, PLINK))
3968+ au_plink_half_refresh(sb, br_id);
3969+
1facf9fc 3970+ goto out; /* success */
3971+
4f0767ce 3972+out_wh:
1facf9fc 3973+ /* revert */
86dc4139 3974+ rerr = au_br_init_wh(sb, br, br->br_perm);
1facf9fc 3975+ if (rerr)
0c3ec466
AM
3976+ pr_warn("failed re-creating base whiteout, %s. (%d)\n",
3977+ del->pathname, rerr);
4f0767ce 3978+out:
076b876e
AM
3979+ if (to_free)
3980+ au_farray_free(to_free, opened);
1facf9fc 3981+ return err;
3982+}
3983+
3984+/* ---------------------------------------------------------------------- */
3985+
027c5e7a
AM
3986+static int au_ibusy(struct super_block *sb, struct aufs_ibusy __user *arg)
3987+{
3988+ int err;
5afbbe0d 3989+ aufs_bindex_t btop, bbot;
027c5e7a
AM
3990+ struct aufs_ibusy ibusy;
3991+ struct inode *inode, *h_inode;
3992+
3993+ err = -EPERM;
3994+ if (unlikely(!capable(CAP_SYS_ADMIN)))
3995+ goto out;
3996+
3997+ err = copy_from_user(&ibusy, arg, sizeof(ibusy));
3998+ if (!err)
ba1aed25
AM
3999+ /* VERIFY_WRITE */
4000+ err = !access_ok(&arg->h_ino, sizeof(arg->h_ino));
027c5e7a
AM
4001+ if (unlikely(err)) {
4002+ err = -EFAULT;
4003+ AuTraceErr(err);
4004+ goto out;
4005+ }
4006+
4007+ err = -EINVAL;
4008+ si_read_lock(sb, AuLock_FLUSH);
5afbbe0d 4009+ if (unlikely(ibusy.bindex < 0 || ibusy.bindex > au_sbbot(sb)))
027c5e7a
AM
4010+ goto out_unlock;
4011+
4012+ err = 0;
4013+ ibusy.h_ino = 0; /* invalid */
4014+ inode = ilookup(sb, ibusy.ino);
4015+ if (!inode
4016+ || inode->i_ino == AUFS_ROOT_INO
5afbbe0d 4017+ || au_is_bad_inode(inode))
027c5e7a
AM
4018+ goto out_unlock;
4019+
4020+ ii_read_lock_child(inode);
5afbbe0d
AM
4021+ btop = au_ibtop(inode);
4022+ bbot = au_ibbot(inode);
4023+ if (btop <= ibusy.bindex && ibusy.bindex <= bbot) {
027c5e7a 4024+ h_inode = au_h_iptr(inode, ibusy.bindex);
5afbbe0d 4025+ if (h_inode && au_test_ibusy(inode, btop, bbot))
027c5e7a
AM
4026+ ibusy.h_ino = h_inode->i_ino;
4027+ }
4028+ ii_read_unlock(inode);
4029+ iput(inode);
4030+
4031+out_unlock:
4032+ si_read_unlock(sb);
4033+ if (!err) {
4034+ err = __put_user(ibusy.h_ino, &arg->h_ino);
4035+ if (unlikely(err)) {
4036+ err = -EFAULT;
4037+ AuTraceErr(err);
4038+ }
4039+ }
4040+out:
4041+ return err;
4042+}
4043+
4044+long au_ibusy_ioctl(struct file *file, unsigned long arg)
4045+{
2000de60 4046+ return au_ibusy(file->f_path.dentry->d_sb, (void __user *)arg);
027c5e7a
AM
4047+}
4048+
4049+#ifdef CONFIG_COMPAT
4050+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg)
4051+{
2000de60 4052+ return au_ibusy(file->f_path.dentry->d_sb, compat_ptr(arg));
027c5e7a
AM
4053+}
4054+#endif
4055+
4056+/* ---------------------------------------------------------------------- */
4057+
1facf9fc 4058+/*
4059+ * change a branch permission
4060+ */
4061+
dece6358
AM
4062+static void au_warn_ima(void)
4063+{
4064+#ifdef CONFIG_IMA
1308ab2a 4065+ /* since it doesn't support mark_files_ro() */
027c5e7a 4066+ AuWarn1("RW -> RO makes IMA to produce wrong message\n");
dece6358
AM
4067+#endif
4068+}
4069+
1facf9fc 4070+static int do_need_sigen_inc(int a, int b)
4071+{
4072+ return au_br_whable(a) && !au_br_whable(b);
4073+}
4074+
4075+static int need_sigen_inc(int old, int new)
4076+{
4077+ return do_need_sigen_inc(old, new)
4078+ || do_need_sigen_inc(new, old);
4079+}
4080+
4081+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
4082+{
7f207e10 4083+ int err, do_warn;
027c5e7a 4084+ unsigned int mnt_flags;
7f207e10 4085+ unsigned long long ull, max;
e49829fe 4086+ aufs_bindex_t br_id;
38d290e6 4087+ unsigned char verbose, writer;
7f207e10 4088+ struct file *file, *hf, **array;
e49829fe 4089+ struct au_hfile *hfile;
eca34b5c 4090+ struct inode *h_inode;
1facf9fc 4091+
027c5e7a
AM
4092+ mnt_flags = au_mntflags(sb);
4093+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
4094+
7f207e10
AM
4095+ array = au_farray_alloc(sb, &max);
4096+ err = PTR_ERR(array);
4097+ if (IS_ERR(array))
1facf9fc 4098+ goto out;
4099+
7f207e10 4100+ do_warn = 0;
e49829fe 4101+ br_id = au_sbr_id(sb, bindex);
7f207e10
AM
4102+ for (ull = 0; ull < max; ull++) {
4103+ file = array[ull];
076b876e
AM
4104+ if (unlikely(!file))
4105+ break;
1facf9fc 4106+
523b37e3 4107+ /* AuDbg("%pD\n", file); */
1facf9fc 4108+ fi_read_lock(file);
4109+ if (unlikely(au_test_mmapped(file))) {
4110+ err = -EBUSY;
523b37e3 4111+ AuVerbose(verbose, "mmapped %pD\n", file);
7f207e10 4112+ AuDbgFile(file);
1facf9fc 4113+ FiMustNoWaiters(file);
4114+ fi_read_unlock(file);
7f207e10 4115+ goto out_array;
1facf9fc 4116+ }
4117+
e49829fe
JR
4118+ hfile = &au_fi(file)->fi_htop;
4119+ hf = hfile->hf_file;
7e9cd9fe 4120+ if (!d_is_reg(file->f_path.dentry)
1facf9fc 4121+ || !(file->f_mode & FMODE_WRITE)
e49829fe 4122+ || hfile->hf_br->br_id != br_id
7f207e10
AM
4123+ || !(hf->f_mode & FMODE_WRITE))
4124+ array[ull] = NULL;
4125+ else {
4126+ do_warn = 1;
4127+ get_file(file);
1facf9fc 4128+ }
4129+
1facf9fc 4130+ FiMustNoWaiters(file);
4131+ fi_read_unlock(file);
7f207e10
AM
4132+ fput(file);
4133+ }
1facf9fc 4134+
4135+ err = 0;
7f207e10 4136+ if (do_warn)
dece6358 4137+ au_warn_ima();
7f207e10
AM
4138+
4139+ for (ull = 0; ull < max; ull++) {
4140+ file = array[ull];
4141+ if (!file)
4142+ continue;
4143+
1facf9fc 4144+ /* todo: already flushed? */
523b37e3
AM
4145+ /*
4146+ * fs/super.c:mark_files_ro() is gone, but aufs keeps its
4147+ * approach which resets f_mode and calls mnt_drop_write() and
4148+ * file_release_write() for each file, because the branch
4149+ * attribute in aufs world is totally different from the native
4150+ * fs rw/ro mode.
4151+ */
7f207e10
AM
4152+ /* fi_read_lock(file); */
4153+ hfile = &au_fi(file)->fi_htop;
4154+ hf = hfile->hf_file;
4155+ /* fi_read_unlock(file); */
027c5e7a 4156+ spin_lock(&hf->f_lock);
38d290e6
JR
4157+ writer = !!(hf->f_mode & FMODE_WRITER);
4158+ hf->f_mode &= ~(FMODE_WRITE | FMODE_WRITER);
027c5e7a 4159+ spin_unlock(&hf->f_lock);
38d290e6 4160+ if (writer) {
eca34b5c 4161+ h_inode = file_inode(hf);
42b5c33a
AM
4162+ if (hf->f_mode & FMODE_READ)
4163+ i_readcount_inc(h_inode);
eca34b5c 4164+ put_write_access(h_inode);
c06a8ce3 4165+ __mnt_drop_write(hf->f_path.mnt);
1facf9fc 4166+ }
4167+ }
4168+
7f207e10
AM
4169+out_array:
4170+ au_farray_free(array, max);
4f0767ce 4171+out:
7f207e10 4172+ AuTraceErr(err);
1facf9fc 4173+ return err;
4174+}
4175+
4176+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 4177+ int *do_refresh)
1facf9fc 4178+{
4179+ int err, rerr;
4180+ aufs_bindex_t bindex;
4181+ struct dentry *root;
4182+ struct au_branch *br;
076b876e 4183+ struct au_br_fhsm *bf;
1facf9fc 4184+
4185+ root = sb->s_root;
1facf9fc 4186+ bindex = au_find_dbindex(root, mod->h_root);
4187+ if (bindex < 0) {
4188+ if (remount)
4189+ return 0; /* success */
4190+ err = -ENOENT;
4a4d8108 4191+ pr_err("%s no such branch\n", mod->path);
1facf9fc 4192+ goto out;
4193+ }
4194+ AuDbg("bindex b%d\n", bindex);
4195+
5527c038 4196+ err = test_br(d_inode(mod->h_root), mod->perm, mod->path);
1facf9fc 4197+ if (unlikely(err))
4198+ goto out;
4199+
4200+ br = au_sbr(sb, bindex);
86dc4139 4201+ AuDebugOn(mod->h_root != au_br_dentry(br));
1facf9fc 4202+ if (br->br_perm == mod->perm)
4203+ return 0; /* success */
4204+
076b876e
AM
4205+ /* pre-allocate for non-fhsm --> fhsm */
4206+ bf = NULL;
4207+ if (!au_br_fhsm(br->br_perm) && au_br_fhsm(mod->perm)) {
4208+ err = au_fhsm_br_alloc(br);
4209+ if (unlikely(err))
4210+ goto out;
4211+ bf = br->br_fhsm;
4212+ br->br_fhsm = NULL;
4213+ }
4214+
1facf9fc 4215+ if (au_br_writable(br->br_perm)) {
4216+ /* remove whiteout base */
86dc4139 4217+ err = au_br_init_wh(sb, br, mod->perm);
1facf9fc 4218+ if (unlikely(err))
076b876e 4219+ goto out_bf;
1facf9fc 4220+
4221+ if (!au_br_writable(mod->perm)) {
4222+ /* rw --> ro, file might be mmapped */
4223+ DiMustNoWaiters(root);
5527c038 4224+ IiMustNoWaiters(d_inode(root));
1facf9fc 4225+ di_write_unlock(root);
4226+ err = au_br_mod_files_ro(sb, bindex);
4227+ /* aufs_write_lock() calls ..._child() */
4228+ di_write_lock_child(root);
4229+
4230+ if (unlikely(err)) {
4231+ rerr = -ENOMEM;
be52b249 4232+ br->br_wbr = kzalloc(sizeof(*br->br_wbr),
1facf9fc 4233+ GFP_NOFS);
86dc4139
AM
4234+ if (br->br_wbr)
4235+ rerr = au_wbr_init(br, sb, br->br_perm);
1facf9fc 4236+ if (unlikely(rerr)) {
4237+ AuIOErr("nested error %d (%d)\n",
4238+ rerr, err);
4239+ br->br_perm = mod->perm;
4240+ }
4241+ }
4242+ }
4243+ } else if (au_br_writable(mod->perm)) {
4244+ /* ro --> rw */
4245+ err = -ENOMEM;
be52b249 4246+ br->br_wbr = kzalloc(sizeof(*br->br_wbr), GFP_NOFS);
1facf9fc 4247+ if (br->br_wbr) {
86dc4139 4248+ err = au_wbr_init(br, sb, mod->perm);
1facf9fc 4249+ if (unlikely(err)) {
9f237c51 4250+ au_kfree_rcu(br->br_wbr);
1facf9fc 4251+ br->br_wbr = NULL;
4252+ }
4253+ }
4254+ }
076b876e
AM
4255+ if (unlikely(err))
4256+ goto out_bf;
4257+
4258+ if (au_br_fhsm(br->br_perm)) {
4259+ if (!au_br_fhsm(mod->perm)) {
4260+ /* fhsm --> non-fhsm */
4261+ au_br_fhsm_fin(br->br_fhsm);
9f237c51 4262+ au_kfree_rcu(br->br_fhsm);
076b876e
AM
4263+ br->br_fhsm = NULL;
4264+ }
4265+ } else if (au_br_fhsm(mod->perm))
4266+ /* non-fhsm --> fhsm */
4267+ br->br_fhsm = bf;
4268+
076b876e
AM
4269+ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm);
4270+ br->br_perm = mod->perm;
4271+ goto out; /* success */
1facf9fc 4272+
076b876e 4273+out_bf:
9f237c51 4274+ au_kfree_try_rcu(bf);
076b876e
AM
4275+out:
4276+ AuTraceErr(err);
4277+ return err;
4278+}
4279+
4280+/* ---------------------------------------------------------------------- */
4281+
4282+int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs)
4283+{
4284+ int err;
4285+ struct kstatfs kstfs;
4286+
4287+ err = vfs_statfs(&br->br_path, &kstfs);
1facf9fc 4288+ if (!err) {
076b876e
AM
4289+ stfs->f_blocks = kstfs.f_blocks;
4290+ stfs->f_bavail = kstfs.f_bavail;
4291+ stfs->f_files = kstfs.f_files;
4292+ stfs->f_ffree = kstfs.f_ffree;
1facf9fc 4293+ }
4294+
1facf9fc 4295+ return err;
4296+}
7f207e10 4297diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
eca34b5c 4298--- /usr/share/empty/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
319657f6 4299+++ linux/fs/aufs/branch.h 2021-12-03 15:40:58.233313963 +0100
0b2a12c6 4300@@ -0,0 +1,375 @@
062440b3 4301+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 4302+/*
6d176551 4303+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 4304+ *
4305+ * This program, aufs is free software; you can redistribute it and/or modify
4306+ * it under the terms of the GNU General Public License as published by
4307+ * the Free Software Foundation; either version 2 of the License, or
4308+ * (at your option) any later version.
dece6358
AM
4309+ *
4310+ * This program is distributed in the hope that it will be useful,
4311+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4312+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4313+ * GNU General Public License for more details.
4314+ *
4315+ * You should have received a copy of the GNU General Public License
523b37e3 4316+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 4317+ */
4318+
4319+/*
4320+ * branch filesystems and xino for them
4321+ */
4322+
4323+#ifndef __AUFS_BRANCH_H__
4324+#define __AUFS_BRANCH_H__
4325+
4326+#ifdef __KERNEL__
4327+
1facf9fc 4328+#include <linux/mount.h>
8b6a4947 4329+#include "dirren.h"
4a4d8108 4330+#include "dynop.h"
acd2b654 4331+#include "lcnt.h"
1facf9fc 4332+#include "rwsem.h"
4333+#include "super.h"
4334+
4335+/* ---------------------------------------------------------------------- */
4336+
4337+/* a xino file */
062440b3 4338+struct au_xino {
acd2b654
AM
4339+ struct file **xi_file;
4340+ unsigned int xi_nfile;
4341+
521ced18
JR
4342+ struct {
4343+ spinlock_t spin;
4344+ ino_t *array;
4345+ int total;
4346+ /* reserved for future use */
4347+ /* unsigned long *bitmap; */
4348+ wait_queue_head_t wqh;
4349+ } xi_nondir;
1facf9fc 4350+
acd2b654 4351+ struct mutex xi_mtx; /* protects xi_file array */
9f237c51 4352+ struct hlist_bl_head xi_writing;
acd2b654 4353+
062440b3 4354+ atomic_t xi_truncating;
1facf9fc 4355+
062440b3 4356+ struct kref xi_kref;
1facf9fc 4357+};
4358+
076b876e
AM
4359+/* File-based Hierarchical Storage Management */
4360+struct au_br_fhsm {
4361+#ifdef CONFIG_AUFS_FHSM
4362+ struct mutex bf_lock;
4363+ unsigned long bf_jiffy;
4364+ struct aufs_stfs bf_stfs;
4365+ int bf_readable;
4366+#endif
4367+};
4368+
1facf9fc 4369+/* members for writable branch only */
4370+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
4371+struct au_wbr {
dece6358 4372+ struct au_rwsem wbr_wh_rwsem;
1facf9fc 4373+ struct dentry *wbr_wh[AuBrWh_Last];
4a4d8108 4374+ atomic_t wbr_wh_running;
1facf9fc 4375+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
4376+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
4377+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
4378+
4379+ /* mfs mode */
4380+ unsigned long long wbr_bytes;
4381+};
4382+
4a4d8108
AM
4383+/* ext2 has 3 types of operations at least, ext3 has 4 */
4384+#define AuBrDynOp (AuDyLast * 4)
4385+
1716fcea
AM
4386+#ifdef CONFIG_AUFS_HFSNOTIFY
4387+/* support for asynchronous destruction */
4388+struct au_br_hfsnotify {
4389+ struct fsnotify_group *hfsn_group;
4390+};
4391+#endif
4392+
392086de
AM
4393+/* sysfs entries */
4394+struct au_brsysfs {
4395+ char name[16];
4396+ struct attribute attr;
4397+};
4398+
4399+enum {
4400+ AuBrSysfs_BR,
4401+ AuBrSysfs_BRID,
4402+ AuBrSysfs_Last
4403+};
4404+
1facf9fc 4405+/* protected by superblock rwsem */
4406+struct au_branch {
062440b3 4407+ struct au_xino *br_xino;
1facf9fc 4408+
4409+ aufs_bindex_t br_id;
4410+
4411+ int br_perm;
86dc4139 4412+ struct path br_path;
4a4d8108
AM
4413+ spinlock_t br_dykey_lock;
4414+ struct au_dykey *br_dykey[AuBrDynOp];
acd2b654
AM
4415+ au_lcnt_t br_nfiles; /* opened files */
4416+ au_lcnt_t br_count; /* in-use for other */
1facf9fc 4417+
4418+ struct au_wbr *br_wbr;
076b876e 4419+ struct au_br_fhsm *br_fhsm;
1facf9fc 4420+
027c5e7a 4421+#ifdef CONFIG_AUFS_HFSNOTIFY
1716fcea 4422+ struct au_br_hfsnotify *br_hfsn;
027c5e7a
AM
4423+#endif
4424+
1facf9fc 4425+#ifdef CONFIG_SYSFS
392086de
AM
4426+ /* entries under sysfs per mount-point */
4427+ struct au_brsysfs br_sysfs[AuBrSysfs_Last];
1facf9fc 4428+#endif
8b6a4947 4429+
062440b3
AM
4430+#ifdef CONFIG_DEBUG_FS
4431+ struct dentry *br_dbgaufs; /* xino */
4432+#endif
4433+
8b6a4947 4434+ struct au_dr_br br_dirren;
1facf9fc 4435+};
4436+
4437+/* ---------------------------------------------------------------------- */
4438+
86dc4139
AM
4439+static inline struct vfsmount *au_br_mnt(struct au_branch *br)
4440+{
4441+ return br->br_path.mnt;
4442+}
4443+
4444+static inline struct dentry *au_br_dentry(struct au_branch *br)
4445+{
4446+ return br->br_path.dentry;
4447+}
4448+
0b2a12c6
JR
4449+static inline struct user_namespace *au_br_userns(struct au_branch *br)
4450+{
4451+ return mnt_user_ns(br->br_path.mnt);
4452+}
4453+
86dc4139
AM
4454+static inline struct super_block *au_br_sb(struct au_branch *br)
4455+{
4456+ return au_br_mnt(br)->mnt_sb;
4457+}
4458+
1facf9fc 4459+static inline int au_br_rdonly(struct au_branch *br)
4460+{
8b6a4947 4461+ return (sb_rdonly(au_br_sb(br))
1facf9fc 4462+ || !au_br_writable(br->br_perm))
4463+ ? -EROFS : 0;
4464+}
4465+
4a4d8108 4466+static inline int au_br_hnotifyable(int brperm __maybe_unused)
1facf9fc 4467+{
4a4d8108 4468+#ifdef CONFIG_AUFS_HNOTIFY
1e00d052 4469+ return !(brperm & AuBrPerm_RR);
1facf9fc 4470+#else
4471+ return 0;
4472+#endif
4473+}
4474+
b912730e
AM
4475+static inline int au_br_test_oflag(int oflag, struct au_branch *br)
4476+{
4477+ int err, exec_flag;
4478+
4479+ err = 0;
4480+ exec_flag = oflag & __FMODE_EXEC;
79b8bda9 4481+ if (unlikely(exec_flag && path_noexec(&br->br_path)))
b912730e
AM
4482+ err = -EACCES;
4483+
4484+ return err;
4485+}
4486+
062440b3
AM
4487+static inline void au_xino_get(struct au_branch *br)
4488+{
4489+ struct au_xino *xi;
4490+
4491+ xi = br->br_xino;
4492+ if (xi)
4493+ kref_get(&xi->xi_kref);
4494+}
4495+
4496+static inline int au_xino_count(struct au_branch *br)
4497+{
4498+ int v;
4499+ struct au_xino *xi;
4500+
4501+ v = 0;
4502+ xi = br->br_xino;
4503+ if (xi)
4504+ v = kref_read(&xi->xi_kref);
4505+
4506+ return v;
4507+}
4508+
1facf9fc 4509+/* ---------------------------------------------------------------------- */
4510+
4511+/* branch.c */
4512+struct au_sbinfo;
4513+void au_br_free(struct au_sbinfo *sinfo);
4514+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
4515+struct au_opt_add;
4516+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
4517+struct au_opt_del;
4518+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
027c5e7a
AM
4519+long au_ibusy_ioctl(struct file *file, unsigned long arg);
4520+#ifdef CONFIG_COMPAT
4521+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg);
4522+#endif
1facf9fc 4523+struct au_opt_mod;
4524+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 4525+ int *do_refresh);
076b876e
AM
4526+struct aufs_stfs;
4527+int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs);
1facf9fc 4528+
4529+/* xino.c */
4530+static const loff_t au_loff_max = LLONG_MAX;
4531+
acd2b654 4532+aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry);
83b672a5
AM
4533+struct file *au_xino_create(struct super_block *sb, char *fpath, int silent,
4534+ int wbrtop);
062440b3
AM
4535+struct file *au_xino_create2(struct super_block *sb, struct path *base,
4536+ struct file *copy_src);
acd2b654
AM
4537+struct au_xi_new {
4538+ struct au_xino *xi; /* switch between xino and xigen */
4539+ int idx;
4540+ struct path *base;
4541+ struct file *copy_src;
4542+};
4543+struct file *au_xi_new(struct super_block *sb, struct au_xi_new *xinew);
062440b3
AM
4544+
4545+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
4546+ ino_t *ino);
4547+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
4548+ ino_t ino);
e37dd06a
AM
4549+ssize_t xino_fread(struct file *file, void *buf, size_t size, loff_t *pos);
4550+ssize_t xino_fwrite(struct file *file, void *buf, size_t size, loff_t *pos);
062440b3
AM
4551+
4552+int au_xib_trunc(struct super_block *sb);
acd2b654 4553+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin);
1facf9fc 4554+
acd2b654 4555+struct au_xino *au_xino_alloc(unsigned int nfile);
062440b3 4556+int au_xino_put(struct au_branch *br);
acd2b654 4557+struct file *au_xino_file1(struct au_xino *xi);
062440b3 4558+
1facf9fc 4559+struct au_opt_xino;
1facf9fc 4560+void au_xino_clr(struct super_block *sb);
062440b3 4561+int au_xino_set(struct super_block *sb, struct au_opt_xino *xiopt, int remount);
1facf9fc 4562+struct file *au_xino_def(struct super_block *sb);
062440b3
AM
4563+int au_xino_init_br(struct super_block *sb, struct au_branch *br, ino_t hino,
4564+ struct path *base);
4565+
4566+ino_t au_xino_new_ino(struct super_block *sb);
4567+void au_xino_delete_inode(struct inode *inode, const int unlinked);
1facf9fc 4568+
521ced18
JR
4569+void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex,
4570+ ino_t h_ino, int idx);
4571+int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
4572+ int *idx);
4573+
062440b3
AM
4574+int au_xino_path(struct seq_file *seq, struct file *file);
4575+
1facf9fc 4576+/* ---------------------------------------------------------------------- */
4577+
acd2b654
AM
4578+/* @idx is signed to accept -1 meaning the first file */
4579+static inline struct file *au_xino_file(struct au_xino *xi, int idx)
4580+{
4581+ struct file *file;
4582+
4583+ file = NULL;
4584+ if (!xi)
4585+ goto out;
4586+
4587+ if (idx >= 0) {
4588+ if (idx < xi->xi_nfile)
4589+ file = xi->xi_file[idx];
4590+ } else
4591+ file = au_xino_file1(xi);
4592+
4593+out:
4594+ return file;
4595+}
4596+
4597+/* ---------------------------------------------------------------------- */
4598+
1facf9fc 4599+/* Superblock to branch */
4600+static inline
4601+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
4602+{
4603+ return au_sbr(sb, bindex)->br_id;
4604+}
4605+
4606+static inline
4607+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
4608+{
86dc4139 4609+ return au_br_mnt(au_sbr(sb, bindex));
1facf9fc 4610+}
4611+
4612+static inline
0b2a12c6
JR
4613+struct user_namespace *au_sbr_userns(struct super_block *sb, aufs_bindex_t bindex)
4614+{
4615+ return au_br_userns(au_sbr(sb, bindex));
4616+}
4617+
4618+static inline
1facf9fc 4619+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
4620+{
86dc4139 4621+ return au_br_sb(au_sbr(sb, bindex));
1facf9fc 4622+}
4623+
1facf9fc 4624+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
4625+{
4626+ return au_sbr(sb, bindex)->br_perm;
4627+}
4628+
4629+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
4630+{
4631+ return au_br_whable(au_sbr_perm(sb, bindex));
4632+}
4633+
4634+/* ---------------------------------------------------------------------- */
4635+
8b6a4947
AM
4636+#define wbr_wh_read_lock(wbr) au_rw_read_lock(&(wbr)->wbr_wh_rwsem)
4637+#define wbr_wh_write_lock(wbr) au_rw_write_lock(&(wbr)->wbr_wh_rwsem)
4638+#define wbr_wh_read_trylock(wbr) au_rw_read_trylock(&(wbr)->wbr_wh_rwsem)
4639+#define wbr_wh_write_trylock(wbr) au_rw_write_trylock(&(wbr)->wbr_wh_rwsem)
1facf9fc 4640+/*
8b6a4947
AM
4641+#define wbr_wh_read_trylock_nested(wbr) \
4642+ au_rw_read_trylock_nested(&(wbr)->wbr_wh_rwsem)
4643+#define wbr_wh_write_trylock_nested(wbr) \
4644+ au_rw_write_trylock_nested(&(wbr)->wbr_wh_rwsem)
4645+*/
1facf9fc 4646+
8b6a4947
AM
4647+#define wbr_wh_read_unlock(wbr) au_rw_read_unlock(&(wbr)->wbr_wh_rwsem)
4648+#define wbr_wh_write_unlock(wbr) au_rw_write_unlock(&(wbr)->wbr_wh_rwsem)
4649+#define wbr_wh_downgrade_lock(wbr) au_rw_dgrade_lock(&(wbr)->wbr_wh_rwsem)
4650+
4651+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&(wbr)->wbr_wh_rwsem)
4652+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&(wbr)->wbr_wh_rwsem)
4653+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&(wbr)->wbr_wh_rwsem)
dece6358 4654+
076b876e
AM
4655+/* ---------------------------------------------------------------------- */
4656+
4657+#ifdef CONFIG_AUFS_FHSM
4658+static inline void au_br_fhsm_init(struct au_br_fhsm *brfhsm)
4659+{
4660+ mutex_init(&brfhsm->bf_lock);
4661+ brfhsm->bf_jiffy = 0;
4662+ brfhsm->bf_readable = 0;
4663+}
4664+
4665+static inline void au_br_fhsm_fin(struct au_br_fhsm *brfhsm)
4666+{
4667+ mutex_destroy(&brfhsm->bf_lock);
4668+}
4669+#else
4670+AuStubVoid(au_br_fhsm_init, struct au_br_fhsm *brfhsm)
4671+AuStubVoid(au_br_fhsm_fin, struct au_br_fhsm *brfhsm)
4672+#endif
4673+
1facf9fc 4674+#endif /* __KERNEL__ */
4675+#endif /* __AUFS_BRANCH_H__ */
7f207e10 4676diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
eca34b5c 4677--- /usr/share/empty/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100
319657f6 4678+++ linux/fs/aufs/conf.mk 2021-12-03 15:38:59.933313976 +0100
2121bcd9
AM
4679@@ -0,0 +1,40 @@
4680+# SPDX-License-Identifier: GPL-2.0
4a4d8108
AM
4681+
4682+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
4683+
4684+define AuConf
4685+ifdef ${1}
4686+AuConfStr += ${1}=${${1}}
4687+endif
4688+endef
4689+
b752ccd1 4690+AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
e49829fe 4691+ SBILIST \
7f207e10 4692+ HNOTIFY HFSNOTIFY \
4a4d8108 4693+ EXPORT INO_T_64 \
c1595e42 4694+ XATTR \
076b876e 4695+ FHSM \
4a4d8108 4696+ RDU \
8b6a4947 4697+ DIRREN \
4a4d8108
AM
4698+ SHWH \
4699+ BR_RAMFS \
4700+ BR_FUSE POLL \
4701+ BR_HFSPLUS \
4702+ BDEV_LOOP \
b752ccd1
AM
4703+ DEBUG MAGIC_SYSRQ
4704+$(foreach i, ${AuConfAll}, \
4a4d8108
AM
4705+ $(eval $(call AuConf,CONFIG_AUFS_${i})))
4706+
4707+AuConfName = ${obj}/conf.str
4708+${AuConfName}.tmp: FORCE
4709+ @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
4710+${AuConfName}: ${AuConfName}.tmp
4711+ @diff -q $< $@ > /dev/null 2>&1 || { \
4712+ echo ' GEN ' $@; \
4713+ cp -p $< $@; \
4714+ }
4715+FORCE:
4716+clean-files += ${AuConfName} ${AuConfName}.tmp
4717+${obj}/sysfs.o: ${AuConfName}
b752ccd1
AM
4718+
4719+-include ${srctree}/${src}/conf_priv.mk
7f207e10 4720diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
eca34b5c 4721--- /usr/share/empty/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
319657f6 4722+++ linux/fs/aufs/cpup.c 2021-12-03 15:40:58.233313963 +0100
758e9dad 4723@@ -0,0 +1,1459 @@
cd7a4cd9 4724+// SPDX-License-Identifier: GPL-2.0
1facf9fc 4725+/*
6d176551 4726+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 4727+ *
4728+ * This program, aufs is free software; you can redistribute it and/or modify
4729+ * it under the terms of the GNU General Public License as published by
4730+ * the Free Software Foundation; either version 2 of the License, or
4731+ * (at your option) any later version.
dece6358
AM
4732+ *
4733+ * This program is distributed in the hope that it will be useful,
4734+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4735+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4736+ * GNU General Public License for more details.
4737+ *
4738+ * You should have received a copy of the GNU General Public License
523b37e3 4739+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 4740+ */
4741+
4742+/*
4743+ * copy-up functions, see wbr_policy.c for copy-down
4744+ */
4745+
4746+#include <linux/fs_stack.h>
dece6358 4747+#include <linux/mm.h>
8cdd5066 4748+#include <linux/task_work.h>
1facf9fc 4749+#include "aufs.h"
4750+
86dc4139 4751+void au_cpup_attr_flags(struct inode *dst, unsigned int iflags)
1facf9fc 4752+{
4753+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
367653fa 4754+ | S_NOATIME | S_NOCMTIME | S_AUTOMOUNT;
1facf9fc 4755+
86dc4139
AM
4756+ BUILD_BUG_ON(sizeof(iflags) != sizeof(dst->i_flags));
4757+
4758+ dst->i_flags |= iflags & ~mask;
1facf9fc 4759+ if (au_test_fs_notime(dst->i_sb))
4760+ dst->i_flags |= S_NOATIME | S_NOCMTIME;
4761+}
4762+
4763+void au_cpup_attr_timesizes(struct inode *inode)
4764+{
4765+ struct inode *h_inode;
4766+
5afbbe0d 4767+ h_inode = au_h_iptr(inode, au_ibtop(inode));
1facf9fc 4768+ fsstack_copy_attr_times(inode, h_inode);
4a4d8108 4769+ fsstack_copy_inode_size(inode, h_inode);
1facf9fc 4770+}
4771+
4772+void au_cpup_attr_nlink(struct inode *inode, int force)
4773+{
4774+ struct inode *h_inode;
4775+ struct super_block *sb;
5afbbe0d 4776+ aufs_bindex_t bindex, bbot;
1facf9fc 4777+
4778+ sb = inode->i_sb;
5afbbe0d 4779+ bindex = au_ibtop(inode);
1facf9fc 4780+ h_inode = au_h_iptr(inode, bindex);
4781+ if (!force
4782+ && !S_ISDIR(h_inode->i_mode)
4783+ && au_opt_test(au_mntflags(sb), PLINK)
4784+ && au_plink_test(inode))
4785+ return;
4786+
7eafdf33
AM
4787+ /*
4788+ * 0 can happen in revalidating.
38d290e6
JR
4789+ * h_inode->i_mutex may not be held here, but it is harmless since once
4790+ * i_nlink reaches 0, it will never become positive except O_TMPFILE
4791+ * case.
4792+ * todo: O_TMPFILE+linkat(AT_SYMLINK_FOLLOW) bypassing aufs may cause
4793+ * the incorrect link count.
7eafdf33 4794+ */
92d182d2 4795+ set_nlink(inode, h_inode->i_nlink);
1facf9fc 4796+
4797+ /*
4798+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
4799+ * it may includes whplink directory.
4800+ */
4801+ if (S_ISDIR(h_inode->i_mode)) {
5afbbe0d
AM
4802+ bbot = au_ibbot(inode);
4803+ for (bindex++; bindex <= bbot; bindex++) {
1facf9fc 4804+ h_inode = au_h_iptr(inode, bindex);
4805+ if (h_inode)
4806+ au_add_nlink(inode, h_inode);
4807+ }
4808+ }
4809+}
4810+
4811+void au_cpup_attr_changeable(struct inode *inode)
4812+{
4813+ struct inode *h_inode;
4814+
5afbbe0d 4815+ h_inode = au_h_iptr(inode, au_ibtop(inode));
1facf9fc 4816+ inode->i_mode = h_inode->i_mode;
4817+ inode->i_uid = h_inode->i_uid;
4818+ inode->i_gid = h_inode->i_gid;
4819+ au_cpup_attr_timesizes(inode);
86dc4139 4820+ au_cpup_attr_flags(inode, h_inode->i_flags);
1facf9fc 4821+}
4822+
4823+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
4824+{
4825+ struct au_iinfo *iinfo = au_ii(inode);
4826+
1308ab2a 4827+ IiMustWriteLock(inode);
4828+
1facf9fc 4829+ iinfo->ii_higen = h_inode->i_generation;
4830+ iinfo->ii_hsb1 = h_inode->i_sb;
4831+}
4832+
4833+void au_cpup_attr_all(struct inode *inode, int force)
4834+{
4835+ struct inode *h_inode;
4836+
5afbbe0d 4837+ h_inode = au_h_iptr(inode, au_ibtop(inode));
1facf9fc 4838+ au_cpup_attr_changeable(inode);
4839+ if (inode->i_nlink > 0)
4840+ au_cpup_attr_nlink(inode, force);
4841+ inode->i_rdev = h_inode->i_rdev;
4842+ inode->i_blkbits = h_inode->i_blkbits;
4843+ au_cpup_igen(inode, h_inode);
4844+}
4845+
4846+/* ---------------------------------------------------------------------- */
4847+
4848+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
4849+
4850+/* keep the timestamps of the parent dir when cpup */
4851+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
4852+ struct path *h_path)
4853+{
4854+ struct inode *h_inode;
4855+
4856+ dt->dt_dentry = dentry;
4857+ dt->dt_h_path = *h_path;
5527c038 4858+ h_inode = d_inode(h_path->dentry);
1facf9fc 4859+ dt->dt_atime = h_inode->i_atime;
4860+ dt->dt_mtime = h_inode->i_mtime;
4861+ /* smp_mb(); */
4862+}
4863+
4864+void au_dtime_revert(struct au_dtime *dt)
4865+{
4866+ struct iattr attr;
4867+ int err;
4868+
4869+ attr.ia_atime = dt->dt_atime;
4870+ attr.ia_mtime = dt->dt_mtime;
4871+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
4872+ | ATTR_ATIME | ATTR_ATIME_SET;
4873+
523b37e3
AM
4874+ /* no delegation since this is a directory */
4875+ err = vfsub_notify_change(&dt->dt_h_path, &attr, /*delegated*/NULL);
1facf9fc 4876+ if (unlikely(err))
0c3ec466 4877+ pr_warn("restoring timestamps failed(%d). ignored\n", err);
1facf9fc 4878+}
4879+
4880+/* ---------------------------------------------------------------------- */
4881+
86dc4139
AM
4882+/* internal use only */
4883+struct au_cpup_reg_attr {
4884+ int valid;
4885+ struct kstat st;
4886+ unsigned int iflags; /* inode->i_flags */
4887+};
4888+
1facf9fc 4889+static noinline_for_stack
0b2a12c6 4890+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct path *h_src,
86dc4139 4891+ struct au_cpup_reg_attr *h_src_attr)
1facf9fc 4892+{
c1595e42 4893+ int err, sbits, icex;
7e9cd9fe
AM
4894+ unsigned int mnt_flags;
4895+ unsigned char verbose;
1facf9fc 4896+ struct iattr ia;
4897+ struct path h_path;
1308ab2a 4898+ struct inode *h_isrc, *h_idst;
86dc4139 4899+ struct kstat *h_st;
c1595e42 4900+ struct au_branch *br;
1facf9fc 4901+
c1595e42
JR
4902+ br = au_sbr(dst->d_sb, bindex);
4903+ h_path.mnt = au_br_mnt(br);
0b2a12c6
JR
4904+ h_path.dentry = au_h_dptr(dst, bindex);
4905+ h_idst = d_inode(h_path.dentry);
4906+ h_isrc = d_inode(h_src->dentry);
1308ab2a 4907+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
1facf9fc 4908+ | ATTR_ATIME | ATTR_MTIME
4909+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
86dc4139
AM
4910+ if (h_src_attr && h_src_attr->valid) {
4911+ h_st = &h_src_attr->st;
4912+ ia.ia_uid = h_st->uid;
4913+ ia.ia_gid = h_st->gid;
4914+ ia.ia_atime = h_st->atime;
4915+ ia.ia_mtime = h_st->mtime;
4916+ if (h_idst->i_mode != h_st->mode
4917+ && !S_ISLNK(h_idst->i_mode)) {
4918+ ia.ia_valid |= ATTR_MODE;
4919+ ia.ia_mode = h_st->mode;
4920+ }
4921+ sbits = !!(h_st->mode & (S_ISUID | S_ISGID));
4922+ au_cpup_attr_flags(h_idst, h_src_attr->iflags);
4923+ } else {
4924+ ia.ia_uid = h_isrc->i_uid;
4925+ ia.ia_gid = h_isrc->i_gid;
4926+ ia.ia_atime = h_isrc->i_atime;
4927+ ia.ia_mtime = h_isrc->i_mtime;
4928+ if (h_idst->i_mode != h_isrc->i_mode
4929+ && !S_ISLNK(h_idst->i_mode)) {
4930+ ia.ia_valid |= ATTR_MODE;
4931+ ia.ia_mode = h_isrc->i_mode;
4932+ }
4933+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
4934+ au_cpup_attr_flags(h_idst, h_isrc->i_flags);
1308ab2a 4935+ }
523b37e3
AM
4936+ /* no delegation since it is just created */
4937+ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL);
1facf9fc 4938+
4939+ /* is this nfs only? */
4940+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
4941+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
4942+ ia.ia_mode = h_isrc->i_mode;
523b37e3 4943+ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL);
1facf9fc 4944+ }
4945+
c1595e42 4946+ icex = br->br_perm & AuBrAttr_ICEX;
7e9cd9fe
AM
4947+ if (!err) {
4948+ mnt_flags = au_mntflags(dst->d_sb);
4949+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
0b2a12c6 4950+ err = au_cpup_xattr(&h_path, h_src, icex, verbose);
7e9cd9fe 4951+ }
c1595e42 4952+
1facf9fc 4953+ return err;
4954+}
4955+
4956+/* ---------------------------------------------------------------------- */
4957+
4958+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
4959+ char *buf, unsigned long blksize)
4960+{
4961+ int err;
4962+ size_t sz, rbytes, wbytes;
4963+ unsigned char all_zero;
4964+ char *p, *zp;
febd17d6 4965+ struct inode *h_inode;
1facf9fc 4966+ /* reduce stack usage */
4967+ struct iattr *ia;
4968+
4969+ zp = page_address(ZERO_PAGE(0));
4970+ if (unlikely(!zp))
4971+ return -ENOMEM; /* possible? */
4972+
4973+ err = 0;
4974+ all_zero = 0;
4975+ while (len) {
4976+ AuDbg("len %lld\n", len);
4977+ sz = blksize;
4978+ if (len < blksize)
4979+ sz = len;
4980+
4981+ rbytes = 0;
4982+ /* todo: signal_pending? */
4983+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
4984+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
4985+ err = rbytes;
4986+ }
4987+ if (unlikely(err < 0))
4988+ break;
4989+
4990+ all_zero = 0;
4991+ if (len >= rbytes && rbytes == blksize)
4992+ all_zero = !memcmp(buf, zp, rbytes);
4993+ if (!all_zero) {
4994+ wbytes = rbytes;
4995+ p = buf;
4996+ while (wbytes) {
4997+ size_t b;
4998+
4999+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
5000+ err = b;
5001+ /* todo: signal_pending? */
5002+ if (unlikely(err == -EAGAIN || err == -EINTR))
5003+ continue;
5004+ if (unlikely(err < 0))
5005+ break;
5006+ wbytes -= b;
5007+ p += b;
5008+ }
392086de
AM
5009+ if (unlikely(err < 0))
5010+ break;
1facf9fc 5011+ } else {
5012+ loff_t res;
5013+
5014+ AuLabel(hole);
5015+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
5016+ err = res;
5017+ if (unlikely(res < 0))
5018+ break;
5019+ }
5020+ len -= rbytes;
5021+ err = 0;
5022+ }
5023+
5024+ /* the last block may be a hole */
5025+ if (!err && all_zero) {
5026+ AuLabel(last hole);
5027+
5028+ err = 1;
2000de60 5029+ if (au_test_nfs(dst->f_path.dentry->d_sb)) {
1facf9fc 5030+ /* nfs requires this step to make last hole */
5031+ /* is this only nfs? */
5032+ do {
5033+ /* todo: signal_pending? */
5034+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
5035+ } while (err == -EAGAIN || err == -EINTR);
5036+ if (err == 1)
5037+ dst->f_pos--;
5038+ }
5039+
5040+ if (err == 1) {
5041+ ia = (void *)buf;
5042+ ia->ia_size = dst->f_pos;
5043+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
5044+ ia->ia_file = dst;
febd17d6
JR
5045+ h_inode = file_inode(dst);
5046+ inode_lock_nested(h_inode, AuLsc_I_CHILD2);
523b37e3
AM
5047+ /* no delegation since it is just created */
5048+ err = vfsub_notify_change(&dst->f_path, ia,
5049+ /*delegated*/NULL);
febd17d6 5050+ inode_unlock(h_inode);
1facf9fc 5051+ }
5052+ }
5053+
5054+ return err;
5055+}
5056+
5057+int au_copy_file(struct file *dst, struct file *src, loff_t len)
5058+{
5059+ int err;
5060+ unsigned long blksize;
5061+ unsigned char do_kfree;
5062+ char *buf;
9f237c51 5063+ struct super_block *h_sb;
1facf9fc 5064+
5065+ err = -ENOMEM;
9f237c51
AM
5066+ h_sb = file_inode(dst)->i_sb;
5067+ blksize = h_sb->s_blocksize;
1facf9fc 5068+ if (!blksize || PAGE_SIZE < blksize)
5069+ blksize = PAGE_SIZE;
5070+ AuDbg("blksize %lu\n", blksize);
5071+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
5072+ if (do_kfree)
5073+ buf = kmalloc(blksize, GFP_NOFS);
5074+ else
5075+ buf = (void *)__get_free_page(GFP_NOFS);
5076+ if (unlikely(!buf))
5077+ goto out;
5078+
5079+ if (len > (1 << 22))
5080+ AuDbg("copying a large file %lld\n", (long long)len);
5081+
5082+ src->f_pos = 0;
5083+ dst->f_pos = 0;
5084+ err = au_do_copy_file(dst, src, len, buf, blksize);
9f237c51
AM
5085+ if (do_kfree) {
5086+ AuDebugOn(!au_kfree_do_sz_test(blksize));
5087+ au_kfree_do_rcu(buf);
5088+ } else
1c60b727 5089+ free_page((unsigned long)buf);
1facf9fc 5090+
4f0767ce 5091+out:
1facf9fc 5092+ return err;
5093+}
5094+
1c60b727
AM
5095+static int au_do_copy(struct file *dst, struct file *src, loff_t len)
5096+{
5097+ int err;
5098+ struct super_block *h_src_sb;
5099+ struct inode *h_src_inode;
5100+
5101+ h_src_inode = file_inode(src);
5102+ h_src_sb = h_src_inode->i_sb;
5103+
5104+ /* XFS acquires inode_lock */
5105+ if (!au_test_xfs(h_src_sb))
5106+ err = au_copy_file(dst, src, len);
5107+ else {
3c1bdaff 5108+ inode_unlock_shared(h_src_inode);
1c60b727 5109+ err = au_copy_file(dst, src, len);
be118d29 5110+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
1c60b727
AM
5111+ }
5112+
5113+ return err;
5114+}
5115+
5116+static int au_clone_or_copy(struct file *dst, struct file *src, loff_t len)
5117+{
5118+ int err;
9f237c51 5119+ loff_t lo;
1c60b727
AM
5120+ struct super_block *h_src_sb;
5121+ struct inode *h_src_inode;
5122+
5123+ h_src_inode = file_inode(src);
5124+ h_src_sb = h_src_inode->i_sb;
5125+ if (h_src_sb != file_inode(dst)->i_sb
9f237c51 5126+ || !dst->f_op->remap_file_range) {
1c60b727
AM
5127+ err = au_do_copy(dst, src, len);
5128+ goto out;
5129+ }
5130+
5131+ if (!au_test_nfs(h_src_sb)) {
3c1bdaff 5132+ inode_unlock_shared(h_src_inode);
9f237c51 5133+ lo = vfsub_clone_file_range(src, dst, len);
be118d29 5134+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
1c60b727 5135+ } else
9f237c51
AM
5136+ lo = vfsub_clone_file_range(src, dst, len);
5137+ if (lo == len) {
5138+ err = 0;
5139+ goto out; /* success */
5140+ } else if (lo >= 0)
5141+ /* todo: possible? */
5142+ /* paritially succeeded */
5143+ AuDbg("lo %lld, len %lld. Retrying.\n", lo, len);
5144+ else if (lo != -EOPNOTSUPP) {
5145+ /* older XFS has a condition in cloning */
5146+ err = lo;
1c60b727 5147+ goto out;
9f237c51 5148+ }
1c60b727
AM
5149+
5150+ /* the backend fs on NFS may not support cloning */
5151+ err = au_do_copy(dst, src, len);
5152+
5153+out:
5154+ AuTraceErr(err);
5155+ return err;
5156+}
5157+
1facf9fc 5158+/*
5159+ * to support a sparse file which is opened with O_APPEND,
5160+ * we need to close the file.
5161+ */
c2b27bf2 5162+static int au_cp_regular(struct au_cp_generic *cpg)
1facf9fc 5163+{
5164+ int err, i;
5165+ enum { SRC, DST };
5166+ struct {
5167+ aufs_bindex_t bindex;
5168+ unsigned int flags;
5169+ struct dentry *dentry;
392086de 5170+ int force_wr;
1facf9fc 5171+ struct file *file;
1facf9fc 5172+ } *f, file[] = {
5173+ {
c2b27bf2 5174+ .bindex = cpg->bsrc,
1facf9fc 5175+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
1facf9fc 5176+ },
5177+ {
c2b27bf2 5178+ .bindex = cpg->bdst,
1facf9fc 5179+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
392086de 5180+ .force_wr = !!au_ftest_cpup(cpg->flags, RWDST),
1facf9fc 5181+ }
5182+ };
acd2b654 5183+ struct au_branch *br;
521ced18 5184+ struct super_block *sb, *h_src_sb;
e2f27e51 5185+ struct inode *h_src_inode;
8cdd5066 5186+ struct task_struct *tsk = current;
1facf9fc 5187+
5188+ /* bsrc branch can be ro/rw. */
c2b27bf2 5189+ sb = cpg->dentry->d_sb;
1facf9fc 5190+ f = file;
5191+ for (i = 0; i < 2; i++, f++) {
c2b27bf2
AM
5192+ f->dentry = au_h_dptr(cpg->dentry, f->bindex);
5193+ f->file = au_h_open(cpg->dentry, f->bindex, f->flags,
392086de 5194+ /*file*/NULL, f->force_wr);
9f237c51
AM
5195+ if (IS_ERR(f->file)) {
5196+ err = PTR_ERR(f->file);
5197+ if (i == SRC)
5198+ goto out;
5199+ else
5200+ goto out_src;
5201+ }
1facf9fc 5202+ }
5203+
5204+ /* try stopping to update while we copyup */
e2f27e51 5205+ h_src_inode = d_inode(file[SRC].dentry);
521ced18
JR
5206+ h_src_sb = h_src_inode->i_sb;
5207+ if (!au_test_nfs(h_src_sb))
e2f27e51 5208+ IMustLock(h_src_inode);
1c60b727 5209+ err = au_clone_or_copy(file[DST].file, file[SRC].file, cpg->len);
1facf9fc 5210+
8cdd5066
JR
5211+ /* i wonder if we had O_NO_DELAY_FPUT flag */
5212+ if (tsk->flags & PF_KTHREAD)
5213+ __fput_sync(file[DST].file);
5214+ else {
062440b3 5215+ /* it happened actually */
8cdd5066
JR
5216+ fput(file[DST].file);
5217+ /*
5218+ * too bad.
5219+ * we have to call both since we don't know which place the file
5220+ * was added to.
5221+ */
5222+ task_work_run();
5223+ flush_delayed_fput();
5224+ }
acd2b654
AM
5225+ br = au_sbr(sb, file[DST].bindex);
5226+ au_lcnt_dec(&br->br_nfiles);
523b37e3 5227+
4f0767ce 5228+out_src:
1facf9fc 5229+ fput(file[SRC].file);
acd2b654
AM
5230+ br = au_sbr(sb, file[SRC].bindex);
5231+ au_lcnt_dec(&br->br_nfiles);
4f0767ce 5232+out:
1facf9fc 5233+ return err;
5234+}
5235+
c2b27bf2 5236+static int au_do_cpup_regular(struct au_cp_generic *cpg,
86dc4139 5237+ struct au_cpup_reg_attr *h_src_attr)
1facf9fc 5238+{
5239+ int err, rerr;
5240+ loff_t l;
86dc4139 5241+ struct path h_path;
38d290e6 5242+ struct inode *h_src_inode, *h_dst_inode;
1facf9fc 5243+
5244+ err = 0;
5527c038 5245+ h_src_inode = au_h_iptr(d_inode(cpg->dentry), cpg->bsrc);
86dc4139 5246+ l = i_size_read(h_src_inode);
c2b27bf2
AM
5247+ if (cpg->len == -1 || l < cpg->len)
5248+ cpg->len = l;
5249+ if (cpg->len) {
86dc4139 5250+ /* try stopping to update while we are referencing */
be118d29 5251+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
c2b27bf2 5252+ au_pin_hdir_unlock(cpg->pin);
1facf9fc 5253+
c2b27bf2
AM
5254+ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bsrc);
5255+ h_path.mnt = au_sbr_mnt(cpg->dentry->d_sb, cpg->bsrc);
86dc4139 5256+ h_src_attr->iflags = h_src_inode->i_flags;
5527c038 5257+ if (!au_test_nfs(h_src_inode->i_sb))
521ced18 5258+ err = vfsub_getattr(&h_path, &h_src_attr->st);
5527c038 5259+ else {
3c1bdaff 5260+ inode_unlock_shared(h_src_inode);
521ced18 5261+ err = vfsub_getattr(&h_path, &h_src_attr->st);
be118d29 5262+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
5527c038 5263+ }
86dc4139 5264+ if (unlikely(err)) {
3c1bdaff 5265+ inode_unlock_shared(h_src_inode);
86dc4139
AM
5266+ goto out;
5267+ }
5268+ h_src_attr->valid = 1;
e2f27e51
AM
5269+ if (!au_test_nfs(h_src_inode->i_sb)) {
5270+ err = au_cp_regular(cpg);
3c1bdaff 5271+ inode_unlock_shared(h_src_inode);
e2f27e51 5272+ } else {
3c1bdaff 5273+ inode_unlock_shared(h_src_inode);
e2f27e51
AM
5274+ err = au_cp_regular(cpg);
5275+ }
c2b27bf2 5276+ rerr = au_pin_hdir_relock(cpg->pin);
86dc4139
AM
5277+ if (!err && rerr)
5278+ err = rerr;
1facf9fc 5279+ }
38d290e6
JR
5280+ if (!err && (h_src_inode->i_state & I_LINKABLE)) {
5281+ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bdst);
5527c038 5282+ h_dst_inode = d_inode(h_path.dentry);
38d290e6
JR
5283+ spin_lock(&h_dst_inode->i_lock);
5284+ h_dst_inode->i_state |= I_LINKABLE;
5285+ spin_unlock(&h_dst_inode->i_lock);
5286+ }
1facf9fc 5287+
4f0767ce 5288+out:
1facf9fc 5289+ return err;
5290+}
5291+
5292+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
5293+ struct inode *h_dir)
5294+{
e37dd06a
AM
5295+ int err;
5296+ DEFINE_DELAYED_CALL(done);
5297+ const char *sym;
1facf9fc 5298+
e37dd06a
AM
5299+ sym = vfs_get_link(h_src, &done);
5300+ err = PTR_ERR(sym);
5301+ if (IS_ERR(sym))
1facf9fc 5302+ goto out;
5303+
e37dd06a 5304+ err = vfsub_symlink(h_dir, h_path, sym);
1facf9fc 5305+
4f0767ce 5306+out:
e37dd06a 5307+ do_delayed_call(&done);
1facf9fc 5308+ return err;
5309+}
5310+
8cdd5066
JR
5311+/*
5312+ * regardless 'acl' option, reset all ACL.
5313+ * All ACL will be copied up later from the original entry on the lower branch.
5314+ */
5315+static int au_reset_acl(struct inode *h_dir, struct path *h_path, umode_t mode)
5316+{
5317+ int err;
5318+ struct dentry *h_dentry;
5319+ struct inode *h_inode;
0b2a12c6 5320+ struct user_namespace *h_userns;
8cdd5066 5321+
0b2a12c6 5322+ h_userns = mnt_user_ns(h_path->mnt);
8cdd5066
JR
5323+ h_dentry = h_path->dentry;
5324+ h_inode = d_inode(h_dentry);
5325+ /* forget_all_cached_acls(h_inode)); */
0b2a12c6 5326+ err = vfsub_removexattr(h_userns, h_dentry, XATTR_NAME_POSIX_ACL_ACCESS);
8cdd5066
JR
5327+ AuTraceErr(err);
5328+ if (err == -EOPNOTSUPP)
5329+ err = 0;
5330+ if (!err)
0b2a12c6 5331+ err = vfsub_acl_chmod(h_userns, h_inode, mode);
8cdd5066
JR
5332+
5333+ AuTraceErr(err);
5334+ return err;
5335+}
5336+
5337+static int au_do_cpup_dir(struct au_cp_generic *cpg, struct dentry *dst_parent,
5338+ struct inode *h_dir, struct path *h_path)
5339+{
5340+ int err;
5341+ struct inode *dir, *inode;
0b2a12c6 5342+ struct user_namespace *h_userns;
8cdd5066 5343+
0b2a12c6
JR
5344+ h_userns = mnt_user_ns(h_path->mnt);
5345+ err = vfsub_removexattr(h_userns, h_path->dentry,
5346+ XATTR_NAME_POSIX_ACL_DEFAULT);
8cdd5066
JR
5347+ AuTraceErr(err);
5348+ if (err == -EOPNOTSUPP)
5349+ err = 0;
5350+ if (unlikely(err))
5351+ goto out;
5352+
5353+ /*
5354+ * strange behaviour from the users view,
acd2b654 5355+ * particularly setattr case
8cdd5066
JR
5356+ */
5357+ dir = d_inode(dst_parent);
5afbbe0d 5358+ if (au_ibtop(dir) == cpg->bdst)
8cdd5066
JR
5359+ au_cpup_attr_nlink(dir, /*force*/1);
5360+ inode = d_inode(cpg->dentry);
5361+ au_cpup_attr_nlink(inode, /*force*/1);
5362+
5363+out:
5364+ return err;
5365+}
5366+
1facf9fc 5367+static noinline_for_stack
c2b27bf2 5368+int cpup_entry(struct au_cp_generic *cpg, struct dentry *dst_parent,
86dc4139 5369+ struct au_cpup_reg_attr *h_src_attr)
1facf9fc 5370+{
5371+ int err;
5372+ umode_t mode;
5373+ unsigned int mnt_flags;
076b876e 5374+ unsigned char isdir, isreg, force;
c2b27bf2 5375+ const unsigned char do_dt = !!au_ftest_cpup(cpg->flags, DTIME);
1facf9fc 5376+ struct au_dtime dt;
5377+ struct path h_path;
5378+ struct dentry *h_src, *h_dst, *h_parent;
8cdd5066 5379+ struct inode *h_inode, *h_dir;
1facf9fc 5380+ struct super_block *sb;
5381+
5382+ /* bsrc branch can be ro/rw. */
c2b27bf2 5383+ h_src = au_h_dptr(cpg->dentry, cpg->bsrc);
5527c038
JR
5384+ h_inode = d_inode(h_src);
5385+ AuDebugOn(h_inode != au_h_iptr(d_inode(cpg->dentry), cpg->bsrc));
1facf9fc 5386+
5387+ /* try stopping to be referenced while we are creating */
c2b27bf2
AM
5388+ h_dst = au_h_dptr(cpg->dentry, cpg->bdst);
5389+ if (au_ftest_cpup(cpg->flags, RENAME))
86dc4139
AM
5390+ AuDebugOn(strncmp(h_dst->d_name.name, AUFS_WH_PFX,
5391+ AUFS_WH_PFX_LEN));
1facf9fc 5392+ h_parent = h_dst->d_parent; /* dir inode is locked */
5527c038 5393+ h_dir = d_inode(h_parent);
1facf9fc 5394+ IMustLock(h_dir);
5395+ AuDebugOn(h_parent != h_dst->d_parent);
5396+
c2b27bf2
AM
5397+ sb = cpg->dentry->d_sb;
5398+ h_path.mnt = au_sbr_mnt(sb, cpg->bdst);
1facf9fc 5399+ if (do_dt) {
5400+ h_path.dentry = h_parent;
5401+ au_dtime_store(&dt, dst_parent, &h_path);
5402+ }
5403+ h_path.dentry = h_dst;
5404+
076b876e 5405+ isreg = 0;
1facf9fc 5406+ isdir = 0;
5407+ mode = h_inode->i_mode;
5408+ switch (mode & S_IFMT) {
5409+ case S_IFREG:
076b876e 5410+ isreg = 1;
cd7a4cd9 5411+ err = vfsub_create(h_dir, &h_path, 0600, /*want_excl*/true);
1facf9fc 5412+ if (!err)
c2b27bf2 5413+ err = au_do_cpup_regular(cpg, h_src_attr);
1facf9fc 5414+ break;
5415+ case S_IFDIR:
5416+ isdir = 1;
5417+ err = vfsub_mkdir(h_dir, &h_path, mode);
8cdd5066
JR
5418+ if (!err)
5419+ err = au_do_cpup_dir(cpg, dst_parent, h_dir, &h_path);
1facf9fc 5420+ break;
5421+ case S_IFLNK:
5422+ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
5423+ break;
5424+ case S_IFCHR:
5425+ case S_IFBLK:
5426+ AuDebugOn(!capable(CAP_MKNOD));
42a736d3 5427+ fallthrough;
1facf9fc 5428+ case S_IFIFO:
5429+ case S_IFSOCK:
5430+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
5431+ break;
5432+ default:
5433+ AuIOErr("Unknown inode type 0%o\n", mode);
5434+ err = -EIO;
5435+ }
8cdd5066
JR
5436+ if (!err)
5437+ err = au_reset_acl(h_dir, &h_path, mode);
1facf9fc 5438+
5439+ mnt_flags = au_mntflags(sb);
5440+ if (!au_opt_test(mnt_flags, UDBA_NONE)
5441+ && !isdir
5442+ && au_opt_test(mnt_flags, XINO)
38d290e6
JR
5443+ && (h_inode->i_nlink == 1
5444+ || (h_inode->i_state & I_LINKABLE))
1facf9fc 5445+ /* todo: unnecessary? */
5527c038 5446+ /* && d_inode(cpg->dentry)->i_nlink == 1 */
c2b27bf2
AM
5447+ && cpg->bdst < cpg->bsrc
5448+ && !au_ftest_cpup(cpg->flags, KEEPLINO))
5449+ au_xino_write(sb, cpg->bsrc, h_inode->i_ino, /*ino*/0);
1facf9fc 5450+ /* ignore this error */
5451+
076b876e
AM
5452+ if (!err) {
5453+ force = 0;
5454+ if (isreg) {
5455+ force = !!cpg->len;
5456+ if (cpg->len == -1)
5457+ force = !!i_size_read(h_inode);
5458+ }
5459+ au_fhsm_wrote(sb, cpg->bdst, force);
5460+ }
5461+
1facf9fc 5462+ if (do_dt)
5463+ au_dtime_revert(&dt);
5464+ return err;
5465+}
5466+
392086de 5467+static int au_do_ren_after_cpup(struct au_cp_generic *cpg, struct path *h_path)
86dc4139
AM
5468+{
5469+ int err;
392086de 5470+ struct dentry *dentry, *h_dentry, *h_parent, *parent;
758e9dad 5471+ struct path h_ppath;
86dc4139 5472+ struct inode *h_dir;
392086de 5473+ aufs_bindex_t bdst;
86dc4139 5474+
392086de
AM
5475+ dentry = cpg->dentry;
5476+ bdst = cpg->bdst;
758e9dad 5477+ h_ppath.mnt = au_sbr_mnt(dentry->d_sb, bdst);
392086de
AM
5478+ h_dentry = au_h_dptr(dentry, bdst);
5479+ if (!au_ftest_cpup(cpg->flags, OVERWRITE)) {
5480+ dget(h_dentry);
5481+ au_set_h_dptr(dentry, bdst, NULL);
5482+ err = au_lkup_neg(dentry, bdst, /*wh*/0);
5483+ if (!err)
5484+ h_path->dentry = dget(au_h_dptr(dentry, bdst));
86dc4139 5485+ au_set_h_dptr(dentry, bdst, h_dentry);
392086de
AM
5486+ } else {
5487+ err = 0;
5488+ parent = dget_parent(dentry);
758e9dad 5489+ h_ppath.dentry = au_h_dptr(parent, bdst);
392086de 5490+ dput(parent);
758e9dad 5491+ h_path->dentry = vfsub_lkup_one(&dentry->d_name, &h_ppath);
392086de
AM
5492+ if (IS_ERR(h_path->dentry))
5493+ err = PTR_ERR(h_path->dentry);
86dc4139 5494+ }
392086de
AM
5495+ if (unlikely(err))
5496+ goto out;
86dc4139 5497+
86dc4139 5498+ h_parent = h_dentry->d_parent; /* dir inode is locked */
5527c038 5499+ h_dir = d_inode(h_parent);
86dc4139 5500+ IMustLock(h_dir);
523b37e3
AM
5501+ AuDbg("%pd %pd\n", h_dentry, h_path->dentry);
5502+ /* no delegation since it is just created */
f2c43d5f
AM
5503+ err = vfsub_rename(h_dir, h_dentry, h_dir, h_path, /*delegated*/NULL,
5504+ /*flags*/0);
86dc4139
AM
5505+ dput(h_path->dentry);
5506+
5507+out:
5508+ return err;
5509+}
5510+
1facf9fc 5511+/*
5512+ * copyup the @dentry from @bsrc to @bdst.
5513+ * the caller must set the both of lower dentries.
5514+ * @len is for truncating when it is -1 copyup the entire file.
5515+ * in link/rename cases, @dst_parent may be different from the real one.
c2b27bf2 5516+ * basic->bsrc can be larger than basic->bdst.
f2c43d5f 5517+ * aufs doesn't touch the credential so
acd2b654 5518+ * security_inode_copy_up{,_xattr}() are unnecessary.
1facf9fc 5519+ */
c2b27bf2 5520+static int au_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent)
1facf9fc 5521+{
5522+ int err, rerr;
5afbbe0d 5523+ aufs_bindex_t old_ibtop;
1facf9fc 5524+ unsigned char isdir, plink;
1facf9fc 5525+ struct dentry *h_src, *h_dst, *h_parent;
5527c038 5526+ struct inode *dst_inode, *h_dir, *inode, *delegated, *src_inode;
1facf9fc 5527+ struct super_block *sb;
86dc4139 5528+ struct au_branch *br;
0b2a12c6 5529+ struct path h_src_path;
acd2b654 5530+ /* to reduce stack size */
c2b27bf2
AM
5531+ struct {
5532+ struct au_dtime dt;
5533+ struct path h_path;
5534+ struct au_cpup_reg_attr h_src_attr;
5535+ } *a;
1facf9fc 5536+
c2b27bf2
AM
5537+ err = -ENOMEM;
5538+ a = kmalloc(sizeof(*a), GFP_NOFS);
5539+ if (unlikely(!a))
5540+ goto out;
5541+ a->h_src_attr.valid = 0;
1facf9fc 5542+
c2b27bf2
AM
5543+ sb = cpg->dentry->d_sb;
5544+ br = au_sbr(sb, cpg->bdst);
5545+ a->h_path.mnt = au_br_mnt(br);
5546+ h_dst = au_h_dptr(cpg->dentry, cpg->bdst);
1facf9fc 5547+ h_parent = h_dst->d_parent; /* dir inode is locked */
5527c038 5548+ h_dir = d_inode(h_parent);
1facf9fc 5549+ IMustLock(h_dir);
5550+
c2b27bf2 5551+ h_src = au_h_dptr(cpg->dentry, cpg->bsrc);
5527c038 5552+ inode = d_inode(cpg->dentry);
1facf9fc 5553+
5554+ if (!dst_parent)
c2b27bf2 5555+ dst_parent = dget_parent(cpg->dentry);
1facf9fc 5556+ else
5557+ dget(dst_parent);
5558+
5559+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
c2b27bf2 5560+ dst_inode = au_h_iptr(inode, cpg->bdst);
1facf9fc 5561+ if (dst_inode) {
5562+ if (unlikely(!plink)) {
5563+ err = -EIO;
027c5e7a
AM
5564+ AuIOErr("hi%lu(i%lu) exists on b%d "
5565+ "but plink is disabled\n",
c2b27bf2
AM
5566+ dst_inode->i_ino, inode->i_ino, cpg->bdst);
5567+ goto out_parent;
1facf9fc 5568+ }
5569+
5570+ if (dst_inode->i_nlink) {
c2b27bf2 5571+ const int do_dt = au_ftest_cpup(cpg->flags, DTIME);
1facf9fc 5572+
c2b27bf2 5573+ h_src = au_plink_lkup(inode, cpg->bdst);
1facf9fc 5574+ err = PTR_ERR(h_src);
5575+ if (IS_ERR(h_src))
c2b27bf2 5576+ goto out_parent;
5527c038 5577+ if (unlikely(d_is_negative(h_src))) {
1facf9fc 5578+ err = -EIO;
79b8bda9 5579+ AuIOErr("i%lu exists on b%d "
027c5e7a 5580+ "but not pseudo-linked\n",
79b8bda9 5581+ inode->i_ino, cpg->bdst);
1facf9fc 5582+ dput(h_src);
c2b27bf2 5583+ goto out_parent;
1facf9fc 5584+ }
5585+
5586+ if (do_dt) {
c2b27bf2
AM
5587+ a->h_path.dentry = h_parent;
5588+ au_dtime_store(&a->dt, dst_parent, &a->h_path);
1facf9fc 5589+ }
86dc4139 5590+
c2b27bf2 5591+ a->h_path.dentry = h_dst;
523b37e3
AM
5592+ delegated = NULL;
5593+ err = vfsub_link(h_src, h_dir, &a->h_path, &delegated);
c2b27bf2 5594+ if (!err && au_ftest_cpup(cpg->flags, RENAME))
392086de 5595+ err = au_do_ren_after_cpup(cpg, &a->h_path);
1facf9fc 5596+ if (do_dt)
c2b27bf2 5597+ au_dtime_revert(&a->dt);
523b37e3
AM
5598+ if (unlikely(err == -EWOULDBLOCK)) {
5599+ pr_warn("cannot retry for NFSv4 delegation"
5600+ " for an internal link\n");
5601+ iput(delegated);
5602+ }
1facf9fc 5603+ dput(h_src);
c2b27bf2 5604+ goto out_parent;
1facf9fc 5605+ } else
5606+ /* todo: cpup_wh_file? */
5607+ /* udba work */
4a4d8108 5608+ au_update_ibrange(inode, /*do_put_zero*/1);
1facf9fc 5609+ }
5610+
86dc4139 5611+ isdir = S_ISDIR(inode->i_mode);
5afbbe0d 5612+ old_ibtop = au_ibtop(inode);
c2b27bf2 5613+ err = cpup_entry(cpg, dst_parent, &a->h_src_attr);
1facf9fc 5614+ if (unlikely(err))
86dc4139 5615+ goto out_rev;
5527c038 5616+ dst_inode = d_inode(h_dst);
febd17d6 5617+ inode_lock_nested(dst_inode, AuLsc_I_CHILD2);
86dc4139 5618+ /* todo: necessary? */
c2b27bf2 5619+ /* au_pin_hdir_unlock(cpg->pin); */
1facf9fc 5620+
0b2a12c6
JR
5621+ h_src_path.dentry = h_src;
5622+ h_src_path.mnt = au_sbr_mnt(sb, cpg->bsrc);
5623+ err = cpup_iattr(cpg->dentry, cpg->bdst, &h_src_path, &a->h_src_attr);
86dc4139
AM
5624+ if (unlikely(err)) {
5625+ /* todo: necessary? */
c2b27bf2 5626+ /* au_pin_hdir_relock(cpg->pin); */ /* ignore an error */
febd17d6 5627+ inode_unlock(dst_inode);
86dc4139
AM
5628+ goto out_rev;
5629+ }
5630+
5afbbe0d 5631+ if (cpg->bdst < old_ibtop) {
86dc4139 5632+ if (S_ISREG(inode->i_mode)) {
c2b27bf2 5633+ err = au_dy_iaop(inode, cpg->bdst, dst_inode);
86dc4139 5634+ if (unlikely(err)) {
c2b27bf2
AM
5635+ /* ignore an error */
5636+ /* au_pin_hdir_relock(cpg->pin); */
febd17d6 5637+ inode_unlock(dst_inode);
86dc4139 5638+ goto out_rev;
4a4d8108 5639+ }
4a4d8108 5640+ }
5afbbe0d 5641+ au_set_ibtop(inode, cpg->bdst);
c2b27bf2 5642+ } else
5afbbe0d 5643+ au_set_ibbot(inode, cpg->bdst);
c2b27bf2 5644+ au_set_h_iptr(inode, cpg->bdst, au_igrab(dst_inode),
86dc4139
AM
5645+ au_hi_flags(inode, isdir));
5646+
5647+ /* todo: necessary? */
c2b27bf2 5648+ /* err = au_pin_hdir_relock(cpg->pin); */
febd17d6 5649+ inode_unlock(dst_inode);
86dc4139
AM
5650+ if (unlikely(err))
5651+ goto out_rev;
5652+
5527c038 5653+ src_inode = d_inode(h_src);
86dc4139 5654+ if (!isdir
5527c038
JR
5655+ && (src_inode->i_nlink > 1
5656+ || src_inode->i_state & I_LINKABLE)
86dc4139 5657+ && plink)
c2b27bf2 5658+ au_plink_append(inode, cpg->bdst, h_dst);
86dc4139 5659+
c2b27bf2
AM
5660+ if (au_ftest_cpup(cpg->flags, RENAME)) {
5661+ a->h_path.dentry = h_dst;
392086de 5662+ err = au_do_ren_after_cpup(cpg, &a->h_path);
86dc4139
AM
5663+ }
5664+ if (!err)
c2b27bf2 5665+ goto out_parent; /* success */
1facf9fc 5666+
5667+ /* revert */
4a4d8108 5668+out_rev:
c2b27bf2
AM
5669+ a->h_path.dentry = h_parent;
5670+ au_dtime_store(&a->dt, dst_parent, &a->h_path);
5671+ a->h_path.dentry = h_dst;
86dc4139 5672+ rerr = 0;
5527c038 5673+ if (d_is_positive(h_dst)) {
523b37e3
AM
5674+ if (!isdir) {
5675+ /* no delegation since it is just created */
5676+ rerr = vfsub_unlink(h_dir, &a->h_path,
5677+ /*delegated*/NULL, /*force*/0);
5678+ } else
c2b27bf2 5679+ rerr = vfsub_rmdir(h_dir, &a->h_path);
86dc4139 5680+ }
c2b27bf2 5681+ au_dtime_revert(&a->dt);
1facf9fc 5682+ if (rerr) {
5683+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
5684+ err = -EIO;
5685+ }
c2b27bf2 5686+out_parent:
1facf9fc 5687+ dput(dst_parent);
9f237c51 5688+ au_kfree_rcu(a);
c2b27bf2 5689+out:
1facf9fc 5690+ return err;
5691+}
5692+
7e9cd9fe 5693+#if 0 /* reserved */
1facf9fc 5694+struct au_cpup_single_args {
5695+ int *errp;
c2b27bf2 5696+ struct au_cp_generic *cpg;
1facf9fc 5697+ struct dentry *dst_parent;
5698+};
5699+
5700+static void au_call_cpup_single(void *args)
5701+{
5702+ struct au_cpup_single_args *a = args;
86dc4139 5703+
c2b27bf2
AM
5704+ au_pin_hdir_acquire_nest(a->cpg->pin);
5705+ *a->errp = au_cpup_single(a->cpg, a->dst_parent);
5706+ au_pin_hdir_release(a->cpg->pin);
1facf9fc 5707+}
c2b27bf2 5708+#endif
1facf9fc 5709+
53392da6
AM
5710+/*
5711+ * prevent SIGXFSZ in copy-up.
5712+ * testing CAP_MKNOD is for generic fs,
5713+ * but CAP_FSETID is for xfs only, currently.
5714+ */
86dc4139 5715+static int au_cpup_sio_test(struct au_pin *pin, umode_t mode)
53392da6
AM
5716+{
5717+ int do_sio;
86dc4139
AM
5718+ struct super_block *sb;
5719+ struct inode *h_dir;
53392da6
AM
5720+
5721+ do_sio = 0;
86dc4139 5722+ sb = au_pinned_parent(pin)->d_sb;
53392da6
AM
5723+ if (!au_wkq_test()
5724+ && (!au_sbi(sb)->si_plink_maint_pid
5725+ || au_plink_maint(sb, AuLock_NOPLM))) {
5726+ switch (mode & S_IFMT) {
5727+ case S_IFREG:
5728+ /* no condition about RLIMIT_FSIZE and the file size */
5729+ do_sio = 1;
5730+ break;
5731+ case S_IFCHR:
5732+ case S_IFBLK:
5733+ do_sio = !capable(CAP_MKNOD);
5734+ break;
5735+ }
5736+ if (!do_sio)
5737+ do_sio = ((mode & (S_ISUID | S_ISGID))
5738+ && !capable(CAP_FSETID));
86dc4139
AM
5739+ /* this workaround may be removed in the future */
5740+ if (!do_sio) {
5741+ h_dir = au_pinned_h_dir(pin);
5742+ do_sio = h_dir->i_mode & S_ISVTX;
5743+ }
53392da6
AM
5744+ }
5745+
5746+ return do_sio;
5747+}
5748+
7e9cd9fe 5749+#if 0 /* reserved */
c2b27bf2 5750+int au_sio_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent)
1facf9fc 5751+{
5752+ int err, wkq_err;
1facf9fc 5753+ struct dentry *h_dentry;
5754+
c2b27bf2 5755+ h_dentry = au_h_dptr(cpg->dentry, cpg->bsrc);
5527c038 5756+ if (!au_cpup_sio_test(pin, d_inode(h_dentry)->i_mode))
c2b27bf2 5757+ err = au_cpup_single(cpg, dst_parent);
1facf9fc 5758+ else {
5759+ struct au_cpup_single_args args = {
5760+ .errp = &err,
c2b27bf2
AM
5761+ .cpg = cpg,
5762+ .dst_parent = dst_parent
1facf9fc 5763+ };
5764+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
5765+ if (unlikely(wkq_err))
5766+ err = wkq_err;
5767+ }
5768+
5769+ return err;
5770+}
c2b27bf2 5771+#endif
1facf9fc 5772+
5773+/*
5774+ * copyup the @dentry from the first active lower branch to @bdst,
5775+ * using au_cpup_single().
5776+ */
c2b27bf2 5777+static int au_cpup_simple(struct au_cp_generic *cpg)
1facf9fc 5778+{
5779+ int err;
c2b27bf2
AM
5780+ unsigned int flags_orig;
5781+ struct dentry *dentry;
5782+
5783+ AuDebugOn(cpg->bsrc < 0);
1facf9fc 5784+
c2b27bf2 5785+ dentry = cpg->dentry;
86dc4139 5786+ DiMustWriteLock(dentry);
1facf9fc 5787+
c2b27bf2 5788+ err = au_lkup_neg(dentry, cpg->bdst, /*wh*/1);
1facf9fc 5789+ if (!err) {
c2b27bf2
AM
5790+ flags_orig = cpg->flags;
5791+ au_fset_cpup(cpg->flags, RENAME);
5792+ err = au_cpup_single(cpg, NULL);
5793+ cpg->flags = flags_orig;
1facf9fc 5794+ if (!err)
5795+ return 0; /* success */
5796+
5797+ /* revert */
c2b27bf2 5798+ au_set_h_dptr(dentry, cpg->bdst, NULL);
5afbbe0d 5799+ au_set_dbtop(dentry, cpg->bsrc);
1facf9fc 5800+ }
5801+
5802+ return err;
5803+}
5804+
5805+struct au_cpup_simple_args {
5806+ int *errp;
c2b27bf2 5807+ struct au_cp_generic *cpg;
1facf9fc 5808+};
5809+
5810+static void au_call_cpup_simple(void *args)
5811+{
5812+ struct au_cpup_simple_args *a = args;
86dc4139 5813+
c2b27bf2
AM
5814+ au_pin_hdir_acquire_nest(a->cpg->pin);
5815+ *a->errp = au_cpup_simple(a->cpg);
5816+ au_pin_hdir_release(a->cpg->pin);
1facf9fc 5817+}
5818+
c2b27bf2 5819+static int au_do_sio_cpup_simple(struct au_cp_generic *cpg)
1facf9fc 5820+{
5821+ int err, wkq_err;
c2b27bf2
AM
5822+ struct dentry *dentry, *parent;
5823+ struct file *h_file;
1facf9fc 5824+ struct inode *h_dir;
0b2a12c6 5825+ struct user_namespace *h_userns;
1facf9fc 5826+
c2b27bf2
AM
5827+ dentry = cpg->dentry;
5828+ h_file = NULL;
5829+ if (au_ftest_cpup(cpg->flags, HOPEN)) {
5830+ AuDebugOn(cpg->bsrc < 0);
392086de 5831+ h_file = au_h_open_pre(dentry, cpg->bsrc, /*force_wr*/0);
c2b27bf2
AM
5832+ err = PTR_ERR(h_file);
5833+ if (IS_ERR(h_file))
5834+ goto out;
5835+ }
5836+
1facf9fc 5837+ parent = dget_parent(dentry);
5527c038 5838+ h_dir = au_h_iptr(d_inode(parent), cpg->bdst);
0b2a12c6
JR
5839+ h_userns = au_sbr_userns(dentry->d_sb, cpg->bdst);
5840+ if (!au_test_h_perm_sio(h_userns, h_dir, MAY_EXEC | MAY_WRITE)
5527c038 5841+ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode))
c2b27bf2 5842+ err = au_cpup_simple(cpg);
1facf9fc 5843+ else {
5844+ struct au_cpup_simple_args args = {
5845+ .errp = &err,
c2b27bf2 5846+ .cpg = cpg
1facf9fc 5847+ };
5848+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
5849+ if (unlikely(wkq_err))
5850+ err = wkq_err;
5851+ }
5852+
5853+ dput(parent);
c2b27bf2
AM
5854+ if (h_file)
5855+ au_h_open_post(dentry, cpg->bsrc, h_file);
5856+
5857+out:
1facf9fc 5858+ return err;
5859+}
5860+
c2b27bf2 5861+int au_sio_cpup_simple(struct au_cp_generic *cpg)
367653fa 5862+{
5afbbe0d 5863+ aufs_bindex_t bsrc, bbot;
c2b27bf2 5864+ struct dentry *dentry, *h_dentry;
367653fa 5865+
c2b27bf2
AM
5866+ if (cpg->bsrc < 0) {
5867+ dentry = cpg->dentry;
5afbbe0d
AM
5868+ bbot = au_dbbot(dentry);
5869+ for (bsrc = cpg->bdst + 1; bsrc <= bbot; bsrc++) {
c2b27bf2
AM
5870+ h_dentry = au_h_dptr(dentry, bsrc);
5871+ if (h_dentry) {
5527c038 5872+ AuDebugOn(d_is_negative(h_dentry));
c2b27bf2
AM
5873+ break;
5874+ }
5875+ }
5afbbe0d 5876+ AuDebugOn(bsrc > bbot);
c2b27bf2 5877+ cpg->bsrc = bsrc;
367653fa 5878+ }
c2b27bf2
AM
5879+ AuDebugOn(cpg->bsrc <= cpg->bdst);
5880+ return au_do_sio_cpup_simple(cpg);
5881+}
367653fa 5882+
c2b27bf2
AM
5883+int au_sio_cpdown_simple(struct au_cp_generic *cpg)
5884+{
5885+ AuDebugOn(cpg->bdst <= cpg->bsrc);
5886+ return au_do_sio_cpup_simple(cpg);
367653fa
AM
5887+}
5888+
1facf9fc 5889+/* ---------------------------------------------------------------------- */
5890+
5891+/*
5892+ * copyup the deleted file for writing.
5893+ */
c2b27bf2
AM
5894+static int au_do_cpup_wh(struct au_cp_generic *cpg, struct dentry *wh_dentry,
5895+ struct file *file)
1facf9fc 5896+{
5897+ int err;
c2b27bf2
AM
5898+ unsigned int flags_orig;
5899+ aufs_bindex_t bsrc_orig;
c2b27bf2 5900+ struct au_dinfo *dinfo;
5afbbe0d
AM
5901+ struct {
5902+ struct au_hdentry *hd;
5903+ struct dentry *h_dentry;
5904+ } hdst, hsrc;
1facf9fc 5905+
c2b27bf2 5906+ dinfo = au_di(cpg->dentry);
1308ab2a 5907+ AuRwMustWriteLock(&dinfo->di_rwsem);
5908+
c2b27bf2 5909+ bsrc_orig = cpg->bsrc;
5afbbe0d
AM
5910+ cpg->bsrc = dinfo->di_btop;
5911+ hdst.hd = au_hdentry(dinfo, cpg->bdst);
5912+ hdst.h_dentry = hdst.hd->hd_dentry;
5913+ hdst.hd->hd_dentry = wh_dentry;
5914+ dinfo->di_btop = cpg->bdst;
5915+
5916+ hsrc.h_dentry = NULL;
027c5e7a 5917+ if (file) {
5afbbe0d
AM
5918+ hsrc.hd = au_hdentry(dinfo, cpg->bsrc);
5919+ hsrc.h_dentry = hsrc.hd->hd_dentry;
5920+ hsrc.hd->hd_dentry = au_hf_top(file)->f_path.dentry;
027c5e7a 5921+ }
c2b27bf2
AM
5922+ flags_orig = cpg->flags;
5923+ cpg->flags = !AuCpup_DTIME;
5924+ err = au_cpup_single(cpg, /*h_parent*/NULL);
5925+ cpg->flags = flags_orig;
027c5e7a
AM
5926+ if (file) {
5927+ if (!err)
5928+ err = au_reopen_nondir(file);
5afbbe0d 5929+ hsrc.hd->hd_dentry = hsrc.h_dentry;
1facf9fc 5930+ }
5afbbe0d
AM
5931+ hdst.hd->hd_dentry = hdst.h_dentry;
5932+ dinfo->di_btop = cpg->bsrc;
c2b27bf2 5933+ cpg->bsrc = bsrc_orig;
1facf9fc 5934+
5935+ return err;
5936+}
5937+
c2b27bf2 5938+static int au_cpup_wh(struct au_cp_generic *cpg, struct file *file)
1facf9fc 5939+{
5940+ int err;
c2b27bf2 5941+ aufs_bindex_t bdst;
1facf9fc 5942+ struct au_dtime dt;
c2b27bf2 5943+ struct dentry *dentry, *parent, *h_parent, *wh_dentry;
1facf9fc 5944+ struct au_branch *br;
5945+ struct path h_path;
5946+
c2b27bf2
AM
5947+ dentry = cpg->dentry;
5948+ bdst = cpg->bdst;
1facf9fc 5949+ br = au_sbr(dentry->d_sb, bdst);
5950+ parent = dget_parent(dentry);
5951+ h_parent = au_h_dptr(parent, bdst);
5952+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
5953+ err = PTR_ERR(wh_dentry);
5954+ if (IS_ERR(wh_dentry))
5955+ goto out;
5956+
5957+ h_path.dentry = h_parent;
86dc4139 5958+ h_path.mnt = au_br_mnt(br);
1facf9fc 5959+ au_dtime_store(&dt, parent, &h_path);
c2b27bf2 5960+ err = au_do_cpup_wh(cpg, wh_dentry, file);
1facf9fc 5961+ if (unlikely(err))
5962+ goto out_wh;
5963+
5964+ dget(wh_dentry);
5965+ h_path.dentry = wh_dentry;
2000de60 5966+ if (!d_is_dir(wh_dentry)) {
523b37e3 5967+ /* no delegation since it is just created */
5527c038 5968+ err = vfsub_unlink(d_inode(h_parent), &h_path,
523b37e3
AM
5969+ /*delegated*/NULL, /*force*/0);
5970+ } else
5527c038 5971+ err = vfsub_rmdir(d_inode(h_parent), &h_path);
1facf9fc 5972+ if (unlikely(err)) {
523b37e3
AM
5973+ AuIOErr("failed remove copied-up tmp file %pd(%d)\n",
5974+ wh_dentry, err);
1facf9fc 5975+ err = -EIO;
5976+ }
5977+ au_dtime_revert(&dt);
5527c038 5978+ au_set_hi_wh(d_inode(dentry), bdst, wh_dentry);
1facf9fc 5979+
4f0767ce 5980+out_wh:
1facf9fc 5981+ dput(wh_dentry);
4f0767ce 5982+out:
1facf9fc 5983+ dput(parent);
5984+ return err;
5985+}
5986+
5987+struct au_cpup_wh_args {
5988+ int *errp;
c2b27bf2 5989+ struct au_cp_generic *cpg;
1facf9fc 5990+ struct file *file;
5991+};
5992+
5993+static void au_call_cpup_wh(void *args)
5994+{
5995+ struct au_cpup_wh_args *a = args;
86dc4139 5996+
c2b27bf2
AM
5997+ au_pin_hdir_acquire_nest(a->cpg->pin);
5998+ *a->errp = au_cpup_wh(a->cpg, a->file);
5999+ au_pin_hdir_release(a->cpg->pin);
1facf9fc 6000+}
6001+
c2b27bf2 6002+int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file)
1facf9fc 6003+{
6004+ int err, wkq_err;
c2b27bf2 6005+ aufs_bindex_t bdst;
c1595e42 6006+ struct dentry *dentry, *parent, *h_orph, *h_parent;
86dc4139 6007+ struct inode *dir, *h_dir, *h_tmpdir;
1facf9fc 6008+ struct au_wbr *wbr;
c2b27bf2 6009+ struct au_pin wh_pin, *pin_orig;
0b2a12c6 6010+ struct user_namespace *h_userns;
1facf9fc 6011+
c2b27bf2
AM
6012+ dentry = cpg->dentry;
6013+ bdst = cpg->bdst;
1facf9fc 6014+ parent = dget_parent(dentry);
5527c038 6015+ dir = d_inode(parent);
1facf9fc 6016+ h_orph = NULL;
6017+ h_parent = NULL;
6018+ h_dir = au_igrab(au_h_iptr(dir, bdst));
6019+ h_tmpdir = h_dir;
c2b27bf2 6020+ pin_orig = NULL;
1facf9fc 6021+ if (!h_dir->i_nlink) {
6022+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
6023+ h_orph = wbr->wbr_orph;
6024+
6025+ h_parent = dget(au_h_dptr(parent, bdst));
1facf9fc 6026+ au_set_h_dptr(parent, bdst, dget(h_orph));
5527c038 6027+ h_tmpdir = d_inode(h_orph);
1facf9fc 6028+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
6029+
febd17d6 6030+ inode_lock_nested(h_tmpdir, AuLsc_I_PARENT3);
4a4d8108 6031+ /* todo: au_h_open_pre()? */
86dc4139 6032+
c2b27bf2 6033+ pin_orig = cpg->pin;
86dc4139 6034+ au_pin_init(&wh_pin, dentry, bdst, AuLsc_DI_PARENT,
c2b27bf2
AM
6035+ AuLsc_I_PARENT3, cpg->pin->udba, AuPin_DI_LOCKED);
6036+ cpg->pin = &wh_pin;
1facf9fc 6037+ }
6038+
0b2a12c6
JR
6039+ h_userns = au_sbr_userns(dentry->d_sb, bdst);
6040+ if (!au_test_h_perm_sio(h_userns, h_tmpdir, MAY_EXEC | MAY_WRITE)
5527c038 6041+ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode))
c2b27bf2 6042+ err = au_cpup_wh(cpg, file);
1facf9fc 6043+ else {
6044+ struct au_cpup_wh_args args = {
6045+ .errp = &err,
c2b27bf2
AM
6046+ .cpg = cpg,
6047+ .file = file
1facf9fc 6048+ };
6049+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
6050+ if (unlikely(wkq_err))
6051+ err = wkq_err;
6052+ }
6053+
6054+ if (h_orph) {
febd17d6 6055+ inode_unlock(h_tmpdir);
4a4d8108 6056+ /* todo: au_h_open_post()? */
1facf9fc 6057+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
1facf9fc 6058+ au_set_h_dptr(parent, bdst, h_parent);
c2b27bf2
AM
6059+ AuDebugOn(!pin_orig);
6060+ cpg->pin = pin_orig;
1facf9fc 6061+ }
6062+ iput(h_dir);
6063+ dput(parent);
6064+
6065+ return err;
6066+}
6067+
6068+/* ---------------------------------------------------------------------- */
6069+
6070+/*
6071+ * generic routine for both of copy-up and copy-down.
6072+ */
6073+/* cf. revalidate function in file.c */
6074+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
6075+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 6076+ struct au_pin *pin,
1facf9fc 6077+ struct dentry *h_parent, void *arg),
6078+ void *arg)
6079+{
6080+ int err;
6081+ struct au_pin pin;
5527c038 6082+ struct dentry *d, *parent, *h_parent, *real_parent, *h_dentry;
1facf9fc 6083+
6084+ err = 0;
6085+ parent = dget_parent(dentry);
6086+ if (IS_ROOT(parent))
6087+ goto out;
6088+
6089+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
6090+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
6091+
6092+ /* do not use au_dpage */
6093+ real_parent = parent;
6094+ while (1) {
6095+ dput(parent);
6096+ parent = dget_parent(dentry);
6097+ h_parent = au_h_dptr(parent, bdst);
6098+ if (h_parent)
6099+ goto out; /* success */
6100+
6101+ /* find top dir which is necessary to cpup */
6102+ do {
6103+ d = parent;
6104+ dput(parent);
6105+ parent = dget_parent(d);
6106+ di_read_lock_parent3(parent, !AuLock_IR);
6107+ h_parent = au_h_dptr(parent, bdst);
6108+ di_read_unlock(parent, !AuLock_IR);
6109+ } while (!h_parent);
6110+
6111+ if (d != real_parent)
6112+ di_write_lock_child3(d);
6113+
6114+ /* somebody else might create while we were sleeping */
5527c038
JR
6115+ h_dentry = au_h_dptr(d, bdst);
6116+ if (!h_dentry || d_is_negative(h_dentry)) {
6117+ if (h_dentry)
5afbbe0d 6118+ au_update_dbtop(d);
1facf9fc 6119+
6120+ au_pin_set_dentry(&pin, d);
6121+ err = au_do_pin(&pin);
6122+ if (!err) {
86dc4139 6123+ err = cp(d, bdst, &pin, h_parent, arg);
1facf9fc 6124+ au_unpin(&pin);
6125+ }
6126+ }
6127+
6128+ if (d != real_parent)
6129+ di_write_unlock(d);
6130+ if (unlikely(err))
6131+ break;
6132+ }
6133+
4f0767ce 6134+out:
1facf9fc 6135+ dput(parent);
6136+ return err;
6137+}
6138+
6139+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 6140+ struct au_pin *pin,
2000de60 6141+ struct dentry *h_parent __maybe_unused,
1facf9fc 6142+ void *arg __maybe_unused)
6143+{
c2b27bf2
AM
6144+ struct au_cp_generic cpg = {
6145+ .dentry = dentry,
6146+ .bdst = bdst,
6147+ .bsrc = -1,
6148+ .len = 0,
6149+ .pin = pin,
6150+ .flags = AuCpup_DTIME
6151+ };
6152+ return au_sio_cpup_simple(&cpg);
1facf9fc 6153+}
6154+
6155+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
6156+{
6157+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
6158+}
6159+
6160+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
6161+{
6162+ int err;
6163+ struct dentry *parent;
6164+ struct inode *dir;
6165+
6166+ parent = dget_parent(dentry);
5527c038 6167+ dir = d_inode(parent);
1facf9fc 6168+ err = 0;
6169+ if (au_h_iptr(dir, bdst))
6170+ goto out;
6171+
6172+ di_read_unlock(parent, AuLock_IR);
6173+ di_write_lock_parent(parent);
6174+ /* someone else might change our inode while we were sleeping */
6175+ if (!au_h_iptr(dir, bdst))
6176+ err = au_cpup_dirs(dentry, bdst);
6177+ di_downgrade_lock(parent, AuLock_IR);
6178+
4f0767ce 6179+out:
1facf9fc 6180+ dput(parent);
6181+ return err;
6182+}
7f207e10 6183diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
eca34b5c 6184--- /usr/share/empty/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
319657f6 6185+++ linux/fs/aufs/cpup.h 2021-12-03 15:38:59.933313976 +0100
062440b3
AM
6186@@ -0,0 +1,100 @@
6187+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 6188+/*
6d176551 6189+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 6190+ *
6191+ * This program, aufs is free software; you can redistribute it and/or modify
6192+ * it under the terms of the GNU General Public License as published by
6193+ * the Free Software Foundation; either version 2 of the License, or
6194+ * (at your option) any later version.
dece6358
AM
6195+ *
6196+ * This program is distributed in the hope that it will be useful,
6197+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6198+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6199+ * GNU General Public License for more details.
6200+ *
6201+ * You should have received a copy of the GNU General Public License
523b37e3 6202+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 6203+ */
6204+
6205+/*
6206+ * copy-up/down functions
6207+ */
6208+
6209+#ifndef __AUFS_CPUP_H__
6210+#define __AUFS_CPUP_H__
6211+
6212+#ifdef __KERNEL__
6213+
dece6358 6214+#include <linux/path.h>
1facf9fc 6215+
dece6358
AM
6216+struct inode;
6217+struct file;
86dc4139 6218+struct au_pin;
dece6358 6219+
86dc4139 6220+void au_cpup_attr_flags(struct inode *dst, unsigned int iflags);
1facf9fc 6221+void au_cpup_attr_timesizes(struct inode *inode);
6222+void au_cpup_attr_nlink(struct inode *inode, int force);
6223+void au_cpup_attr_changeable(struct inode *inode);
6224+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
6225+void au_cpup_attr_all(struct inode *inode, int force);
6226+
6227+/* ---------------------------------------------------------------------- */
6228+
c2b27bf2
AM
6229+struct au_cp_generic {
6230+ struct dentry *dentry;
6231+ aufs_bindex_t bdst, bsrc;
6232+ loff_t len;
6233+ struct au_pin *pin;
6234+ unsigned int flags;
6235+};
6236+
1facf9fc 6237+/* cpup flags */
392086de
AM
6238+#define AuCpup_DTIME 1 /* do dtime_store/revert */
6239+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
6240+ for link(2) */
6241+#define AuCpup_RENAME (1 << 2) /* rename after cpup */
6242+#define AuCpup_HOPEN (1 << 3) /* call h_open_pre/post() in
6243+ cpup */
6244+#define AuCpup_OVERWRITE (1 << 4) /* allow overwriting the
6245+ existing entry */
6246+#define AuCpup_RWDST (1 << 5) /* force write target even if
6247+ the branch is marked as RO */
c2b27bf2 6248+
8b6a4947
AM
6249+#ifndef CONFIG_AUFS_BR_HFSPLUS
6250+#undef AuCpup_HOPEN
6251+#define AuCpup_HOPEN 0
6252+#endif
6253+
1facf9fc 6254+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
7f207e10
AM
6255+#define au_fset_cpup(flags, name) \
6256+ do { (flags) |= AuCpup_##name; } while (0)
6257+#define au_fclr_cpup(flags, name) \
6258+ do { (flags) &= ~AuCpup_##name; } while (0)
1facf9fc 6259+
6260+int au_copy_file(struct file *dst, struct file *src, loff_t len);
c2b27bf2
AM
6261+int au_sio_cpup_simple(struct au_cp_generic *cpg);
6262+int au_sio_cpdown_simple(struct au_cp_generic *cpg);
6263+int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file);
1facf9fc 6264+
6265+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
6266+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 6267+ struct au_pin *pin,
1facf9fc 6268+ struct dentry *h_parent, void *arg),
6269+ void *arg);
6270+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
6271+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
6272+
6273+/* ---------------------------------------------------------------------- */
6274+
6275+/* keep timestamps when copyup */
6276+struct au_dtime {
6277+ struct dentry *dt_dentry;
6278+ struct path dt_h_path;
cd7a4cd9 6279+ struct timespec64 dt_atime, dt_mtime;
1facf9fc 6280+};
6281+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
6282+ struct path *h_path);
6283+void au_dtime_revert(struct au_dtime *dt);
6284+
6285+#endif /* __KERNEL__ */
6286+#endif /* __AUFS_CPUP_H__ */
7f207e10 6287diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
eca34b5c 6288--- /usr/share/empty/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
319657f6 6289+++ linux/fs/aufs/dbgaufs.c 2021-12-03 15:38:59.933313976 +0100
9f237c51 6290@@ -0,0 +1,526 @@
cd7a4cd9 6291+// SPDX-License-Identifier: GPL-2.0
1facf9fc 6292+/*
6d176551 6293+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 6294+ *
6295+ * This program, aufs is free software; you can redistribute it and/or modify
6296+ * it under the terms of the GNU General Public License as published by
6297+ * the Free Software Foundation; either version 2 of the License, or
6298+ * (at your option) any later version.
dece6358
AM
6299+ *
6300+ * This program is distributed in the hope that it will be useful,
6301+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6302+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6303+ * GNU General Public License for more details.
6304+ *
6305+ * You should have received a copy of the GNU General Public License
523b37e3 6306+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 6307+ */
6308+
6309+/*
6310+ * debugfs interface
6311+ */
6312+
6313+#include <linux/debugfs.h>
6314+#include "aufs.h"
6315+
6316+#ifndef CONFIG_SYSFS
6317+#error DEBUG_FS depends upon SYSFS
6318+#endif
6319+
6320+static struct dentry *dbgaufs;
cd7a4cd9 6321+static const mode_t dbgaufs_mode = 0444;
1facf9fc 6322+
6323+/* 20 is max digits length of ulong 64 */
6324+struct dbgaufs_arg {
6325+ int n;
6326+ char a[20 * 4];
6327+};
6328+
6329+/*
6330+ * common function for all XINO files
6331+ */
6332+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
6333+ struct file *file)
6334+{
9f237c51
AM
6335+ void *p;
6336+
6337+ p = file->private_data;
6338+ if (p) {
6339+ /* this is struct dbgaufs_arg */
6340+ AuDebugOn(!au_kfree_sz_test(p));
6341+ au_kfree_do_rcu(p);
6342+ }
1facf9fc 6343+ return 0;
6344+}
6345+
062440b3
AM
6346+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt,
6347+ int cnt)
1facf9fc 6348+{
6349+ int err;
6350+ struct kstat st;
6351+ struct dbgaufs_arg *p;
6352+
6353+ err = -ENOMEM;
6354+ p = kmalloc(sizeof(*p), GFP_NOFS);
6355+ if (unlikely(!p))
6356+ goto out;
6357+
6358+ err = 0;
6359+ p->n = 0;
6360+ file->private_data = p;
6361+ if (!xf)
6362+ goto out;
6363+
521ced18 6364+ err = vfsub_getattr(&xf->f_path, &st);
1facf9fc 6365+ if (!err) {
6366+ if (do_fcnt)
6367+ p->n = snprintf
062440b3
AM
6368+ (p->a, sizeof(p->a), "%d, %llux%u %lld\n",
6369+ cnt, st.blocks, st.blksize,
1facf9fc 6370+ (long long)st.size);
6371+ else
521ced18 6372+ p->n = snprintf(p->a, sizeof(p->a), "%llux%u %lld\n",
1facf9fc 6373+ st.blocks, st.blksize,
6374+ (long long)st.size);
6375+ AuDebugOn(p->n >= sizeof(p->a));
6376+ } else {
6377+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
6378+ err = 0;
6379+ }
6380+
4f0767ce 6381+out:
1facf9fc 6382+ return err;
1facf9fc 6383+}
6384+
6385+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
6386+ size_t count, loff_t *ppos)
6387+{
6388+ struct dbgaufs_arg *p;
6389+
6390+ p = file->private_data;
6391+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
6392+}
6393+
6394+/* ---------------------------------------------------------------------- */
6395+
86dc4139
AM
6396+struct dbgaufs_plink_arg {
6397+ int n;
6398+ char a[];
6399+};
6400+
6401+static int dbgaufs_plink_release(struct inode *inode __maybe_unused,
6402+ struct file *file)
6403+{
1c60b727 6404+ free_page((unsigned long)file->private_data);
86dc4139
AM
6405+ return 0;
6406+}
6407+
6408+static int dbgaufs_plink_open(struct inode *inode, struct file *file)
6409+{
6410+ int err, i, limit;
6411+ unsigned long n, sum;
6412+ struct dbgaufs_plink_arg *p;
6413+ struct au_sbinfo *sbinfo;
6414+ struct super_block *sb;
8b6a4947 6415+ struct hlist_bl_head *hbl;
86dc4139
AM
6416+
6417+ err = -ENOMEM;
6418+ p = (void *)get_zeroed_page(GFP_NOFS);
6419+ if (unlikely(!p))
6420+ goto out;
6421+
6422+ err = -EFBIG;
6423+ sbinfo = inode->i_private;
6424+ sb = sbinfo->si_sb;
6425+ si_noflush_read_lock(sb);
6426+ if (au_opt_test(au_mntflags(sb), PLINK)) {
6427+ limit = PAGE_SIZE - sizeof(p->n);
6428+
6429+ /* the number of buckets */
6430+ n = snprintf(p->a + p->n, limit, "%d\n", AuPlink_NHASH);
6431+ p->n += n;
6432+ limit -= n;
6433+
6434+ sum = 0;
8b6a4947
AM
6435+ for (i = 0, hbl = sbinfo->si_plink; i < AuPlink_NHASH;
6436+ i++, hbl++) {
6437+ n = au_hbl_count(hbl);
86dc4139
AM
6438+ sum += n;
6439+
6440+ n = snprintf(p->a + p->n, limit, "%lu ", n);
6441+ p->n += n;
6442+ limit -= n;
6443+ if (unlikely(limit <= 0))
6444+ goto out_free;
6445+ }
6446+ p->a[p->n - 1] = '\n';
6447+
6448+ /* the sum of plinks */
6449+ n = snprintf(p->a + p->n, limit, "%lu\n", sum);
6450+ p->n += n;
6451+ limit -= n;
6452+ if (unlikely(limit <= 0))
6453+ goto out_free;
6454+ } else {
6455+#define str "1\n0\n0\n"
6456+ p->n = sizeof(str) - 1;
6457+ strcpy(p->a, str);
6458+#undef str
6459+ }
6460+ si_read_unlock(sb);
6461+
6462+ err = 0;
6463+ file->private_data = p;
6464+ goto out; /* success */
6465+
6466+out_free:
1c60b727 6467+ free_page((unsigned long)p);
86dc4139
AM
6468+out:
6469+ return err;
6470+}
6471+
6472+static ssize_t dbgaufs_plink_read(struct file *file, char __user *buf,
6473+ size_t count, loff_t *ppos)
6474+{
6475+ struct dbgaufs_plink_arg *p;
6476+
6477+ p = file->private_data;
6478+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
6479+}
6480+
6481+static const struct file_operations dbgaufs_plink_fop = {
6482+ .owner = THIS_MODULE,
6483+ .open = dbgaufs_plink_open,
6484+ .release = dbgaufs_plink_release,
6485+ .read = dbgaufs_plink_read
6486+};
6487+
6488+/* ---------------------------------------------------------------------- */
6489+
1facf9fc 6490+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
6491+{
6492+ int err;
6493+ struct au_sbinfo *sbinfo;
6494+ struct super_block *sb;
6495+
6496+ sbinfo = inode->i_private;
6497+ sb = sbinfo->si_sb;
6498+ si_noflush_read_lock(sb);
062440b3 6499+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0, /*cnt*/0);
1facf9fc 6500+ si_read_unlock(sb);
6501+ return err;
6502+}
6503+
6504+static const struct file_operations dbgaufs_xib_fop = {
4a4d8108 6505+ .owner = THIS_MODULE,
1facf9fc 6506+ .open = dbgaufs_xib_open,
6507+ .release = dbgaufs_xi_release,
6508+ .read = dbgaufs_xi_read
6509+};
6510+
6511+/* ---------------------------------------------------------------------- */
6512+
6513+#define DbgaufsXi_PREFIX "xi"
6514+
6515+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
6516+{
acd2b654 6517+ int err, idx;
1facf9fc 6518+ long l;
acd2b654
AM
6519+ aufs_bindex_t bindex;
6520+ char *p, a[sizeof(DbgaufsXi_PREFIX) + 8];
1facf9fc 6521+ struct au_sbinfo *sbinfo;
6522+ struct super_block *sb;
acd2b654 6523+ struct au_xino *xi;
1facf9fc 6524+ struct file *xf;
6525+ struct qstr *name;
062440b3 6526+ struct au_branch *br;
1facf9fc 6527+
6528+ err = -ENOENT;
2000de60 6529+ name = &file->f_path.dentry->d_name;
1facf9fc 6530+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
6531+ || memcmp(name->name, DbgaufsXi_PREFIX,
6532+ sizeof(DbgaufsXi_PREFIX) - 1)))
6533+ goto out;
acd2b654
AM
6534+
6535+ AuDebugOn(name->len >= sizeof(a));
6536+ memcpy(a, name->name, name->len);
6537+ a[name->len] = '\0';
6538+ p = strchr(a, '-');
6539+ if (p)
6540+ *p = '\0';
6541+ err = kstrtol(a + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
1facf9fc 6542+ if (unlikely(err))
6543+ goto out;
acd2b654
AM
6544+ bindex = l;
6545+ idx = 0;
6546+ if (p) {
6547+ err = kstrtol(p + 1, 10, &l);
6548+ if (unlikely(err))
6549+ goto out;
6550+ idx = l;
6551+ }
1facf9fc 6552+
acd2b654 6553+ err = -ENOENT;
1facf9fc 6554+ sbinfo = inode->i_private;
6555+ sb = sbinfo->si_sb;
6556+ si_noflush_read_lock(sb);
acd2b654
AM
6557+ if (unlikely(bindex < 0 || bindex > au_sbbot(sb)))
6558+ goto out_si;
6559+ br = au_sbr(sb, bindex);
6560+ xi = br->br_xino;
6561+ if (unlikely(idx >= xi->xi_nfile))
6562+ goto out_si;
6563+ xf = au_xino_file(xi, idx);
6564+ if (xf)
062440b3
AM
6565+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1,
6566+ au_xino_count(br));
1facf9fc 6567+
acd2b654
AM
6568+out_si:
6569+ si_read_unlock(sb);
4f0767ce 6570+out:
acd2b654 6571+ AuTraceErr(err);
1facf9fc 6572+ return err;
6573+}
6574+
6575+static const struct file_operations dbgaufs_xino_fop = {
4a4d8108 6576+ .owner = THIS_MODULE,
1facf9fc 6577+ .open = dbgaufs_xino_open,
6578+ .release = dbgaufs_xi_release,
6579+ .read = dbgaufs_xi_read
6580+};
6581+
062440b3
AM
6582+void dbgaufs_xino_del(struct au_branch *br)
6583+{
6584+ struct dentry *dbgaufs;
6585+
6586+ dbgaufs = br->br_dbgaufs;
6587+ if (!dbgaufs)
6588+ return;
6589+
6590+ br->br_dbgaufs = NULL;
6591+ /* debugfs acquires the parent i_mutex */
6592+ lockdep_off();
6593+ debugfs_remove(dbgaufs);
6594+ lockdep_on();
6595+}
6596+
1facf9fc 6597+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
6598+{
5afbbe0d 6599+ aufs_bindex_t bbot;
1facf9fc 6600+ struct au_branch *br;
1facf9fc 6601+
6602+ if (!au_sbi(sb)->si_dbgaufs)
6603+ return;
6604+
5afbbe0d
AM
6605+ bbot = au_sbbot(sb);
6606+ for (; bindex <= bbot; bindex++) {
1facf9fc 6607+ br = au_sbr(sb, bindex);
062440b3
AM
6608+ dbgaufs_xino_del(br);
6609+ }
6610+}
6611+
acd2b654
AM
6612+static void dbgaufs_br_do_add(struct super_block *sb, aufs_bindex_t bindex,
6613+ unsigned int idx, struct dentry *parent,
6614+ struct au_sbinfo *sbinfo)
062440b3
AM
6615+{
6616+ struct au_branch *br;
6617+ struct dentry *d;
acd2b654
AM
6618+ /* "xi" bindex(5) "-" idx(2) NULL */
6619+ char name[sizeof(DbgaufsXi_PREFIX) + 8];
062440b3 6620+
acd2b654
AM
6621+ if (!idx)
6622+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
6623+ else
6624+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d-%u",
6625+ bindex, idx);
062440b3
AM
6626+ br = au_sbr(sb, bindex);
6627+ if (br->br_dbgaufs) {
6628+ struct qstr qstr = QSTR_INIT(name, strlen(name));
6629+
6630+ if (!au_qstreq(&br->br_dbgaufs->d_name, &qstr)) {
6631+ /* debugfs acquires the parent i_mutex */
6632+ lockdep_off();
6633+ d = debugfs_rename(parent, br->br_dbgaufs, parent,
6634+ name);
6635+ lockdep_on();
6636+ if (unlikely(!d))
6637+ pr_warn("failed renaming %pd/%s, ignored.\n",
6638+ parent, name);
6639+ }
6640+ } else {
e2f27e51 6641+ lockdep_off();
062440b3
AM
6642+ br->br_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
6643+ sbinfo, &dbgaufs_xino_fop);
e2f27e51 6644+ lockdep_on();
062440b3 6645+ if (unlikely(!br->br_dbgaufs))
acd2b654 6646+ pr_warn("failed creating %pd/%s, ignored.\n",
062440b3 6647+ parent, name);
1facf9fc 6648+ }
6649+}
6650+
acd2b654
AM
6651+static void dbgaufs_br_add(struct super_block *sb, aufs_bindex_t bindex,
6652+ struct dentry *parent, struct au_sbinfo *sbinfo)
6653+{
6654+ struct au_branch *br;
6655+ struct au_xino *xi;
6656+ unsigned int u;
6657+
6658+ br = au_sbr(sb, bindex);
6659+ xi = br->br_xino;
6660+ for (u = 0; u < xi->xi_nfile; u++)
6661+ dbgaufs_br_do_add(sb, bindex, u, parent, sbinfo);
6662+}
6663+
062440b3 6664+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex, int topdown)
1facf9fc 6665+{
6666+ struct au_sbinfo *sbinfo;
6667+ struct dentry *parent;
5afbbe0d 6668+ aufs_bindex_t bbot;
062440b3
AM
6669+
6670+ if (!au_opt_test(au_mntflags(sb), XINO))
6671+ return;
1facf9fc 6672+
6673+ sbinfo = au_sbi(sb);
6674+ parent = sbinfo->si_dbgaufs;
6675+ if (!parent)
6676+ return;
6677+
5afbbe0d 6678+ bbot = au_sbbot(sb);
062440b3
AM
6679+ if (topdown)
6680+ for (; bindex <= bbot; bindex++)
6681+ dbgaufs_br_add(sb, bindex, parent, sbinfo);
6682+ else
6683+ for (; bbot >= bindex; bbot--)
6684+ dbgaufs_br_add(sb, bbot, parent, sbinfo);
1facf9fc 6685+}
6686+
6687+/* ---------------------------------------------------------------------- */
6688+
6689+#ifdef CONFIG_AUFS_EXPORT
6690+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
6691+{
6692+ int err;
6693+ struct au_sbinfo *sbinfo;
6694+ struct super_block *sb;
6695+
6696+ sbinfo = inode->i_private;
6697+ sb = sbinfo->si_sb;
6698+ si_noflush_read_lock(sb);
062440b3 6699+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0, /*cnt*/0);
1facf9fc 6700+ si_read_unlock(sb);
6701+ return err;
6702+}
6703+
6704+static const struct file_operations dbgaufs_xigen_fop = {
4a4d8108 6705+ .owner = THIS_MODULE,
1facf9fc 6706+ .open = dbgaufs_xigen_open,
6707+ .release = dbgaufs_xi_release,
6708+ .read = dbgaufs_xi_read
6709+};
6710+
6711+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
6712+{
6713+ int err;
6714+
dece6358 6715+ /*
c1595e42 6716+ * This function is a dynamic '__init' function actually,
dece6358
AM
6717+ * so the tiny check for si_rwsem is unnecessary.
6718+ */
6719+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
6720+
1facf9fc 6721+ err = -EIO;
6722+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
6723+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
6724+ &dbgaufs_xigen_fop);
6725+ if (sbinfo->si_dbgaufs_xigen)
6726+ err = 0;
6727+
6728+ return err;
6729+}
6730+#else
6731+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
6732+{
6733+ return 0;
6734+}
6735+#endif /* CONFIG_AUFS_EXPORT */
6736+
6737+/* ---------------------------------------------------------------------- */
6738+
6739+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
6740+{
dece6358 6741+ /*
7e9cd9fe 6742+ * This function is a dynamic '__fin' function actually,
dece6358
AM
6743+ * so the tiny check for si_rwsem is unnecessary.
6744+ */
6745+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
6746+
1facf9fc 6747+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
6748+ sbinfo->si_dbgaufs = NULL;
1facf9fc 6749+}
6750+
6751+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
6752+{
6753+ int err;
6754+ char name[SysaufsSiNameLen];
6755+
dece6358 6756+ /*
c1595e42 6757+ * This function is a dynamic '__init' function actually,
dece6358
AM
6758+ * so the tiny check for si_rwsem is unnecessary.
6759+ */
6760+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
6761+
1facf9fc 6762+ err = -ENOENT;
6763+ if (!dbgaufs) {
6764+ AuErr1("/debug/aufs is uninitialized\n");
6765+ goto out;
6766+ }
6767+
6768+ err = -EIO;
6769+ sysaufs_name(sbinfo, name);
6770+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
6771+ if (unlikely(!sbinfo->si_dbgaufs))
6772+ goto out;
1facf9fc 6773+
062440b3 6774+ /* regardless plink/noplink option */
86dc4139
AM
6775+ sbinfo->si_dbgaufs_plink = debugfs_create_file
6776+ ("plink", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
6777+ &dbgaufs_plink_fop);
6778+ if (unlikely(!sbinfo->si_dbgaufs_plink))
6779+ goto out_dir;
6780+
062440b3
AM
6781+ /* regardless xino/noxino option */
6782+ sbinfo->si_dbgaufs_xib = debugfs_create_file
6783+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
6784+ &dbgaufs_xib_fop);
6785+ if (unlikely(!sbinfo->si_dbgaufs_xib))
6786+ goto out_dir;
6787+
1facf9fc 6788+ err = dbgaufs_xigen_init(sbinfo);
6789+ if (!err)
6790+ goto out; /* success */
6791+
4f0767ce 6792+out_dir:
1facf9fc 6793+ dbgaufs_si_fin(sbinfo);
4f0767ce 6794+out:
062440b3
AM
6795+ if (unlikely(err))
6796+ pr_err("debugfs/aufs failed\n");
1facf9fc 6797+ return err;
6798+}
6799+
6800+/* ---------------------------------------------------------------------- */
6801+
6802+void dbgaufs_fin(void)
6803+{
6804+ debugfs_remove(dbgaufs);
6805+}
6806+
6807+int __init dbgaufs_init(void)
6808+{
6809+ int err;
6810+
6811+ err = -EIO;
6812+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
6813+ if (dbgaufs)
6814+ err = 0;
6815+ return err;
6816+}
7f207e10 6817diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
eca34b5c 6818--- /usr/share/empty/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100
319657f6 6819+++ linux/fs/aufs/dbgaufs.h 2021-12-03 15:38:59.933313976 +0100
062440b3
AM
6820@@ -0,0 +1,53 @@
6821+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 6822+/*
6d176551 6823+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 6824+ *
6825+ * This program, aufs is free software; you can redistribute it and/or modify
6826+ * it under the terms of the GNU General Public License as published by
6827+ * the Free Software Foundation; either version 2 of the License, or
6828+ * (at your option) any later version.
dece6358
AM
6829+ *
6830+ * This program is distributed in the hope that it will be useful,
6831+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6832+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6833+ * GNU General Public License for more details.
6834+ *
6835+ * You should have received a copy of the GNU General Public License
523b37e3 6836+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 6837+ */
6838+
6839+/*
6840+ * debugfs interface
6841+ */
6842+
6843+#ifndef __DBGAUFS_H__
6844+#define __DBGAUFS_H__
6845+
6846+#ifdef __KERNEL__
6847+
dece6358 6848+struct super_block;
1facf9fc 6849+struct au_sbinfo;
062440b3 6850+struct au_branch;
dece6358 6851+
1facf9fc 6852+#ifdef CONFIG_DEBUG_FS
6853+/* dbgaufs.c */
062440b3 6854+void dbgaufs_xino_del(struct au_branch *br);
1facf9fc 6855+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
062440b3 6856+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex, int topdown);
1facf9fc 6857+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
6858+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
6859+void dbgaufs_fin(void);
6860+int __init dbgaufs_init(void);
1facf9fc 6861+#else
062440b3 6862+AuStubVoid(dbgaufs_xino_del, struct au_branch *br)
4a4d8108 6863+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
062440b3
AM
6864+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex,
6865+ int topdown)
4a4d8108
AM
6866+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
6867+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
6868+AuStubVoid(dbgaufs_fin, void)
6869+AuStubInt0(__init dbgaufs_init, void)
1facf9fc 6870+#endif /* CONFIG_DEBUG_FS */
6871+
6872+#endif /* __KERNEL__ */
6873+#endif /* __DBGAUFS_H__ */
7f207e10 6874diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
eca34b5c 6875--- /usr/share/empty/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
319657f6 6876+++ linux/fs/aufs/dcsub.c 2021-12-03 15:38:59.933313976 +0100
cd7a4cd9
AM
6877@@ -0,0 +1,225 @@
6878+// SPDX-License-Identifier: GPL-2.0
1facf9fc 6879+/*
6d176551 6880+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 6881+ *
6882+ * This program, aufs is free software; you can redistribute it and/or modify
6883+ * it under the terms of the GNU General Public License as published by
6884+ * the Free Software Foundation; either version 2 of the License, or
6885+ * (at your option) any later version.
dece6358
AM
6886+ *
6887+ * This program is distributed in the hope that it will be useful,
6888+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6889+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6890+ * GNU General Public License for more details.
6891+ *
6892+ * You should have received a copy of the GNU General Public License
523b37e3 6893+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 6894+ */
6895+
6896+/*
6897+ * sub-routines for dentry cache
6898+ */
6899+
6900+#include "aufs.h"
6901+
6902+static void au_dpage_free(struct au_dpage *dpage)
6903+{
6904+ int i;
6905+ struct dentry **p;
6906+
6907+ p = dpage->dentries;
6908+ for (i = 0; i < dpage->ndentry; i++)
6909+ dput(*p++);
1c60b727 6910+ free_page((unsigned long)dpage->dentries);
1facf9fc 6911+}
6912+
6913+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
6914+{
6915+ int err;
6916+ void *p;
6917+
6918+ err = -ENOMEM;
6919+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
6920+ if (unlikely(!dpages->dpages))
6921+ goto out;
6922+
6923+ p = (void *)__get_free_page(gfp);
6924+ if (unlikely(!p))
6925+ goto out_dpages;
6926+
6927+ dpages->dpages[0].ndentry = 0;
6928+ dpages->dpages[0].dentries = p;
6929+ dpages->ndpage = 1;
6930+ return 0; /* success */
6931+
4f0767ce 6932+out_dpages:
9f237c51 6933+ au_kfree_try_rcu(dpages->dpages);
4f0767ce 6934+out:
1facf9fc 6935+ return err;
6936+}
6937+
6938+void au_dpages_free(struct au_dcsub_pages *dpages)
6939+{
6940+ int i;
6941+ struct au_dpage *p;
6942+
6943+ p = dpages->dpages;
6944+ for (i = 0; i < dpages->ndpage; i++)
6945+ au_dpage_free(p++);
9f237c51 6946+ au_kfree_try_rcu(dpages->dpages);
1facf9fc 6947+}
6948+
6949+static int au_dpages_append(struct au_dcsub_pages *dpages,
6950+ struct dentry *dentry, gfp_t gfp)
6951+{
6952+ int err, sz;
6953+ struct au_dpage *dpage;
6954+ void *p;
6955+
6956+ dpage = dpages->dpages + dpages->ndpage - 1;
6957+ sz = PAGE_SIZE / sizeof(dentry);
6958+ if (unlikely(dpage->ndentry >= sz)) {
6959+ AuLabel(new dpage);
6960+ err = -ENOMEM;
6961+ sz = dpages->ndpage * sizeof(*dpages->dpages);
6962+ p = au_kzrealloc(dpages->dpages, sz,
e2f27e51
AM
6963+ sz + sizeof(*dpages->dpages), gfp,
6964+ /*may_shrink*/0);
1facf9fc 6965+ if (unlikely(!p))
6966+ goto out;
6967+
6968+ dpages->dpages = p;
6969+ dpage = dpages->dpages + dpages->ndpage;
6970+ p = (void *)__get_free_page(gfp);
6971+ if (unlikely(!p))
6972+ goto out;
6973+
6974+ dpage->ndentry = 0;
6975+ dpage->dentries = p;
6976+ dpages->ndpage++;
6977+ }
6978+
c1595e42 6979+ AuDebugOn(au_dcount(dentry) <= 0);
027c5e7a 6980+ dpage->dentries[dpage->ndentry++] = dget_dlock(dentry);
1facf9fc 6981+ return 0; /* success */
6982+
4f0767ce 6983+out:
1facf9fc 6984+ return err;
6985+}
6986+
c1595e42
JR
6987+/* todo: BAD approach */
6988+/* copied from linux/fs/dcache.c */
6989+enum d_walk_ret {
6990+ D_WALK_CONTINUE,
6991+ D_WALK_QUIT,
6992+ D_WALK_NORETRY,
6993+ D_WALK_SKIP,
6994+};
6995+
6996+extern void d_walk(struct dentry *parent, void *data,
cd7a4cd9 6997+ enum d_walk_ret (*enter)(void *, struct dentry *));
c1595e42
JR
6998+
6999+struct ac_dpages_arg {
1facf9fc 7000+ int err;
c1595e42
JR
7001+ struct au_dcsub_pages *dpages;
7002+ struct super_block *sb;
7003+ au_dpages_test test;
7004+ void *arg;
7005+};
1facf9fc 7006+
c1595e42
JR
7007+static enum d_walk_ret au_call_dpages_append(void *_arg, struct dentry *dentry)
7008+{
7009+ enum d_walk_ret ret;
7010+ struct ac_dpages_arg *arg = _arg;
1facf9fc 7011+
c1595e42
JR
7012+ ret = D_WALK_CONTINUE;
7013+ if (dentry->d_sb == arg->sb
7014+ && !IS_ROOT(dentry)
7015+ && au_dcount(dentry) > 0
7016+ && au_di(dentry)
7017+ && (!arg->test || arg->test(dentry, arg->arg))) {
7018+ arg->err = au_dpages_append(arg->dpages, dentry, GFP_ATOMIC);
7019+ if (unlikely(arg->err))
7020+ ret = D_WALK_QUIT;
1facf9fc 7021+ }
7022+
c1595e42
JR
7023+ return ret;
7024+}
027c5e7a 7025+
c1595e42
JR
7026+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
7027+ au_dpages_test test, void *arg)
7028+{
7029+ struct ac_dpages_arg args = {
7030+ .err = 0,
7031+ .dpages = dpages,
7032+ .sb = root->d_sb,
7033+ .test = test,
7034+ .arg = arg
7035+ };
027c5e7a 7036+
cd7a4cd9 7037+ d_walk(root, &args, au_call_dpages_append);
c1595e42
JR
7038+
7039+ return args.err;
1facf9fc 7040+}
7041+
7042+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
7043+ int do_include, au_dpages_test test, void *arg)
7044+{
7045+ int err;
7046+
7047+ err = 0;
027c5e7a
AM
7048+ write_seqlock(&rename_lock);
7049+ spin_lock(&dentry->d_lock);
7050+ if (do_include
c1595e42 7051+ && au_dcount(dentry) > 0
027c5e7a 7052+ && (!test || test(dentry, arg)))
1facf9fc 7053+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
7054+ spin_unlock(&dentry->d_lock);
7055+ if (unlikely(err))
7056+ goto out;
7057+
7058+ /*
523b37e3 7059+ * RCU for vfsmount is unnecessary since this is a traverse in a single
027c5e7a
AM
7060+ * mount
7061+ */
1facf9fc 7062+ while (!IS_ROOT(dentry)) {
027c5e7a
AM
7063+ dentry = dentry->d_parent; /* rename_lock is locked */
7064+ spin_lock(&dentry->d_lock);
c1595e42 7065+ if (au_dcount(dentry) > 0
027c5e7a 7066+ && (!test || test(dentry, arg)))
1facf9fc 7067+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
7068+ spin_unlock(&dentry->d_lock);
7069+ if (unlikely(err))
7070+ break;
1facf9fc 7071+ }
7072+
4f0767ce 7073+out:
027c5e7a 7074+ write_sequnlock(&rename_lock);
1facf9fc 7075+ return err;
7076+}
7077+
027c5e7a
AM
7078+static inline int au_dcsub_dpages_aufs(struct dentry *dentry, void *arg)
7079+{
7080+ return au_di(dentry) && dentry->d_sb == arg;
7081+}
7082+
7083+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
7084+ struct dentry *dentry, int do_include)
7085+{
7086+ return au_dcsub_pages_rev(dpages, dentry, do_include,
7087+ au_dcsub_dpages_aufs, dentry->d_sb);
7088+}
7089+
4a4d8108 7090+int au_test_subdir(struct dentry *d1, struct dentry *d2)
1facf9fc 7091+{
4a4d8108
AM
7092+ struct path path[2] = {
7093+ {
7094+ .dentry = d1
7095+ },
7096+ {
7097+ .dentry = d2
7098+ }
7099+ };
1facf9fc 7100+
4a4d8108 7101+ return path_is_under(path + 0, path + 1);
1facf9fc 7102+}
7f207e10 7103diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
eca34b5c 7104--- /usr/share/empty/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
319657f6 7105+++ linux/fs/aufs/dcsub.h 2021-12-03 15:38:59.933313976 +0100
062440b3
AM
7106@@ -0,0 +1,137 @@
7107+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 7108+/*
6d176551 7109+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 7110+ *
7111+ * This program, aufs is free software; you can redistribute it and/or modify
7112+ * it under the terms of the GNU General Public License as published by
7113+ * the Free Software Foundation; either version 2 of the License, or
7114+ * (at your option) any later version.
dece6358
AM
7115+ *
7116+ * This program is distributed in the hope that it will be useful,
7117+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7118+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7119+ * GNU General Public License for more details.
7120+ *
7121+ * You should have received a copy of the GNU General Public License
523b37e3 7122+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7123+ */
7124+
7125+/*
7126+ * sub-routines for dentry cache
7127+ */
7128+
7129+#ifndef __AUFS_DCSUB_H__
7130+#define __AUFS_DCSUB_H__
7131+
7132+#ifdef __KERNEL__
7133+
7f207e10 7134+#include <linux/dcache.h>
027c5e7a 7135+#include <linux/fs.h>
dece6358 7136+
1facf9fc 7137+struct au_dpage {
7138+ int ndentry;
7139+ struct dentry **dentries;
7140+};
7141+
7142+struct au_dcsub_pages {
7143+ int ndpage;
7144+ struct au_dpage *dpages;
7145+};
7146+
7147+/* ---------------------------------------------------------------------- */
7148+
7f207e10 7149+/* dcsub.c */
1facf9fc 7150+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
7151+void au_dpages_free(struct au_dcsub_pages *dpages);
7152+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
7153+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
7154+ au_dpages_test test, void *arg);
7155+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
7156+ int do_include, au_dpages_test test, void *arg);
027c5e7a
AM
7157+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
7158+ struct dentry *dentry, int do_include);
4a4d8108 7159+int au_test_subdir(struct dentry *d1, struct dentry *d2);
1facf9fc 7160+
7f207e10
AM
7161+/* ---------------------------------------------------------------------- */
7162+
523b37e3
AM
7163+/*
7164+ * todo: in linux-3.13, several similar (but faster) helpers are added to
7165+ * include/linux/dcache.h. Try them (in the future).
7166+ */
7167+
027c5e7a
AM
7168+static inline int au_d_hashed_positive(struct dentry *d)
7169+{
7170+ int err;
5527c038 7171+ struct inode *inode = d_inode(d);
076b876e 7172+
027c5e7a 7173+ err = 0;
5527c038
JR
7174+ if (unlikely(d_unhashed(d)
7175+ || d_is_negative(d)
7176+ || !inode->i_nlink))
027c5e7a
AM
7177+ err = -ENOENT;
7178+ return err;
7179+}
7180+
38d290e6
JR
7181+static inline int au_d_linkable(struct dentry *d)
7182+{
7183+ int err;
5527c038 7184+ struct inode *inode = d_inode(d);
076b876e 7185+
38d290e6
JR
7186+ err = au_d_hashed_positive(d);
7187+ if (err
5527c038 7188+ && d_is_positive(d)
38d290e6
JR
7189+ && (inode->i_state & I_LINKABLE))
7190+ err = 0;
7191+ return err;
7192+}
7193+
027c5e7a
AM
7194+static inline int au_d_alive(struct dentry *d)
7195+{
7196+ int err;
7197+ struct inode *inode;
076b876e 7198+
027c5e7a
AM
7199+ err = 0;
7200+ if (!IS_ROOT(d))
7201+ err = au_d_hashed_positive(d);
7202+ else {
5527c038
JR
7203+ inode = d_inode(d);
7204+ if (unlikely(d_unlinked(d)
7205+ || d_is_negative(d)
7206+ || !inode->i_nlink))
027c5e7a
AM
7207+ err = -ENOENT;
7208+ }
7209+ return err;
7210+}
7211+
7212+static inline int au_alive_dir(struct dentry *d)
7f207e10 7213+{
027c5e7a 7214+ int err;
076b876e 7215+
027c5e7a 7216+ err = au_d_alive(d);
5527c038 7217+ if (unlikely(err || IS_DEADDIR(d_inode(d))))
027c5e7a
AM
7218+ err = -ENOENT;
7219+ return err;
7f207e10
AM
7220+}
7221+
38d290e6
JR
7222+static inline int au_qstreq(struct qstr *a, struct qstr *b)
7223+{
7224+ return a->len == b->len
7225+ && !memcmp(a->name, b->name, a->len);
7226+}
7227+
7e9cd9fe
AM
7228+/*
7229+ * by the commit
7230+ * 360f547 2015-01-25 dcache: let the dentry count go down to zero without
7231+ * taking d_lock
7232+ * the type of d_lockref.count became int, but the inlined function d_count()
7233+ * still returns unsigned int.
7234+ * I don't know why. Maybe it is for every d_count() users?
7235+ * Anyway au_dcount() lives on.
7236+ */
c1595e42
JR
7237+static inline int au_dcount(struct dentry *d)
7238+{
7239+ return (int)d_count(d);
7240+}
7241+
1facf9fc 7242+#endif /* __KERNEL__ */
7243+#endif /* __AUFS_DCSUB_H__ */
7f207e10 7244diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
eca34b5c 7245--- /usr/share/empty/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
319657f6 7246+++ linux/fs/aufs/debug.c 2021-12-03 15:38:59.933313976 +0100
758e9dad 7247@@ -0,0 +1,444 @@
cd7a4cd9 7248+// SPDX-License-Identifier: GPL-2.0
1facf9fc 7249+/*
6d176551 7250+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 7251+ *
7252+ * This program, aufs is free software; you can redistribute it and/or modify
7253+ * it under the terms of the GNU General Public License as published by
7254+ * the Free Software Foundation; either version 2 of the License, or
7255+ * (at your option) any later version.
dece6358
AM
7256+ *
7257+ * This program is distributed in the hope that it will be useful,
7258+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7259+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7260+ * GNU General Public License for more details.
7261+ *
7262+ * You should have received a copy of the GNU General Public License
523b37e3 7263+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7264+ */
7265+
7266+/*
7267+ * debug print functions
7268+ */
7269+
eca801bf 7270+#include <linux/iversion.h>
1facf9fc 7271+#include "aufs.h"
7272+
392086de
AM
7273+/* Returns 0, or -errno. arg is in kp->arg. */
7274+static int param_atomic_t_set(const char *val, const struct kernel_param *kp)
7275+{
7276+ int err, n;
7277+
7278+ err = kstrtoint(val, 0, &n);
7279+ if (!err) {
7280+ if (n > 0)
7281+ au_debug_on();
7282+ else
7283+ au_debug_off();
7284+ }
7285+ return err;
7286+}
7287+
7288+/* Returns length written or -errno. Buffer is 4k (ie. be short!) */
7289+static int param_atomic_t_get(char *buffer, const struct kernel_param *kp)
7290+{
7291+ atomic_t *a;
7292+
7293+ a = kp->arg;
7294+ return sprintf(buffer, "%d", atomic_read(a));
7295+}
7296+
7297+static struct kernel_param_ops param_ops_atomic_t = {
7298+ .set = param_atomic_t_set,
7299+ .get = param_atomic_t_get
7300+ /* void (*free)(void *arg) */
7301+};
7302+
7303+atomic_t aufs_debug = ATOMIC_INIT(0);
1facf9fc 7304+MODULE_PARM_DESC(debug, "debug print");
cd7a4cd9 7305+module_param_named(debug, aufs_debug, atomic_t, 0664);
1facf9fc 7306+
c1595e42 7307+DEFINE_MUTEX(au_dbg_mtx); /* just to serialize the dbg msgs */
1facf9fc 7308+char *au_plevel = KERN_DEBUG;
e49829fe
JR
7309+#define dpri(fmt, ...) do { \
7310+ if ((au_plevel \
7311+ && strcmp(au_plevel, KERN_DEBUG)) \
7312+ || au_debug_test()) \
7313+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
1facf9fc 7314+} while (0)
7315+
7316+/* ---------------------------------------------------------------------- */
7317+
7318+void au_dpri_whlist(struct au_nhash *whlist)
7319+{
7320+ unsigned long ul, n;
7321+ struct hlist_head *head;
c06a8ce3 7322+ struct au_vdir_wh *pos;
1facf9fc 7323+
7324+ n = whlist->nh_num;
7325+ head = whlist->nh_head;
7326+ for (ul = 0; ul < n; ul++) {
c06a8ce3 7327+ hlist_for_each_entry(pos, head, wh_hash)
1facf9fc 7328+ dpri("b%d, %.*s, %d\n",
c06a8ce3
AM
7329+ pos->wh_bindex,
7330+ pos->wh_str.len, pos->wh_str.name,
7331+ pos->wh_str.len);
1facf9fc 7332+ head++;
7333+ }
7334+}
7335+
7336+void au_dpri_vdir(struct au_vdir *vdir)
7337+{
7338+ unsigned long ul;
7339+ union au_vdir_deblk_p p;
7340+ unsigned char *o;
7341+
7342+ if (!vdir || IS_ERR(vdir)) {
7343+ dpri("err %ld\n", PTR_ERR(vdir));
7344+ return;
7345+ }
7346+
be118d29 7347+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %llu\n",
1facf9fc 7348+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
7349+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
7350+ for (ul = 0; ul < vdir->vd_nblk; ul++) {
7351+ p.deblk = vdir->vd_deblk[ul];
7352+ o = p.deblk;
7353+ dpri("[%lu]: %p\n", ul, o);
7354+ }
7355+}
7356+
53392da6 7357+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode, int hn,
1facf9fc 7358+ struct dentry *wh)
7359+{
7360+ char *n = NULL;
7361+ int l = 0;
7362+
7363+ if (!inode || IS_ERR(inode)) {
7364+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
7365+ return -1;
7366+ }
7367+
c2b27bf2 7368+ /* the type of i_blocks depends upon CONFIG_LBDAF */
1facf9fc 7369+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
7370+ && sizeof(inode->i_blocks) != sizeof(u64));
7371+ if (wh) {
7372+ n = (void *)wh->d_name.name;
7373+ l = wh->d_name.len;
7374+ }
7375+
53392da6
AM
7376+ dpri("i%d: %p, i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
7377+ " hn %d, ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
7378+ bindex, inode,
1facf9fc 7379+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
7380+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
7381+ i_size_read(inode), (unsigned long long)inode->i_blocks,
cd7a4cd9 7382+ hn, (long long)timespec64_to_ns(&inode->i_ctime) & 0x0ffff,
1facf9fc 7383+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
be118d29 7384+ inode->i_state, inode->i_flags, inode_peek_iversion(inode),
b752ccd1 7385+ inode->i_generation,
1facf9fc 7386+ l ? ", wh " : "", l, n);
7387+ return 0;
7388+}
7389+
7390+void au_dpri_inode(struct inode *inode)
7391+{
7392+ struct au_iinfo *iinfo;
5afbbe0d 7393+ struct au_hinode *hi;
1facf9fc 7394+ aufs_bindex_t bindex;
53392da6 7395+ int err, hn;
1facf9fc 7396+
53392da6 7397+ err = do_pri_inode(-1, inode, -1, NULL);
5afbbe0d 7398+ if (err || !au_test_aufs(inode->i_sb) || au_is_bad_inode(inode))
1facf9fc 7399+ return;
7400+
7401+ iinfo = au_ii(inode);
5afbbe0d
AM
7402+ dpri("i-1: btop %d, bbot %d, gen %d\n",
7403+ iinfo->ii_btop, iinfo->ii_bbot, au_iigen(inode, NULL));
7404+ if (iinfo->ii_btop < 0)
1facf9fc 7405+ return;
53392da6 7406+ hn = 0;
5afbbe0d
AM
7407+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; bindex++) {
7408+ hi = au_hinode(iinfo, bindex);
7409+ hn = !!au_hn(hi);
7410+ do_pri_inode(bindex, hi->hi_inode, hn, hi->hi_whdentry);
53392da6 7411+ }
1facf9fc 7412+}
7413+
2cbb1c4b
JR
7414+void au_dpri_dalias(struct inode *inode)
7415+{
7416+ struct dentry *d;
7417+
7418+ spin_lock(&inode->i_lock);
c1595e42 7419+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias)
2cbb1c4b
JR
7420+ au_dpri_dentry(d);
7421+ spin_unlock(&inode->i_lock);
7422+}
7423+
1facf9fc 7424+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
7425+{
7426+ struct dentry *wh = NULL;
53392da6 7427+ int hn;
5afbbe0d 7428+ struct inode *inode;
076b876e 7429+ struct au_iinfo *iinfo;
5afbbe0d 7430+ struct au_hinode *hi;
1facf9fc 7431+
7432+ if (!dentry || IS_ERR(dentry)) {
7433+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
7434+ return -1;
7435+ }
7436+ /* do not call dget_parent() here */
027c5e7a 7437+ /* note: access d_xxx without d_lock */
523b37e3
AM
7438+ dpri("d%d: %p, %pd2?, %s, cnt %d, flags 0x%x, %shashed\n",
7439+ bindex, dentry, dentry,
1facf9fc 7440+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
c1595e42 7441+ au_dcount(dentry), dentry->d_flags,
523b37e3 7442+ d_unhashed(dentry) ? "un" : "");
53392da6 7443+ hn = -1;
5afbbe0d
AM
7444+ inode = NULL;
7445+ if (d_is_positive(dentry))
7446+ inode = d_inode(dentry);
7447+ if (inode
7448+ && au_test_aufs(dentry->d_sb)
7449+ && bindex >= 0
7450+ && !au_is_bad_inode(inode)) {
7451+ iinfo = au_ii(inode);
7452+ hi = au_hinode(iinfo, bindex);
7453+ hn = !!au_hn(hi);
7454+ wh = hi->hi_whdentry;
7455+ }
7456+ do_pri_inode(bindex, inode, hn, wh);
1facf9fc 7457+ return 0;
7458+}
7459+
7460+void au_dpri_dentry(struct dentry *dentry)
7461+{
7462+ struct au_dinfo *dinfo;
7463+ aufs_bindex_t bindex;
7464+ int err;
7465+
7466+ err = do_pri_dentry(-1, dentry);
7467+ if (err || !au_test_aufs(dentry->d_sb))
7468+ return;
7469+
7470+ dinfo = au_di(dentry);
7471+ if (!dinfo)
7472+ return;
5afbbe0d
AM
7473+ dpri("d-1: btop %d, bbot %d, bwh %d, bdiropq %d, gen %d, tmp %d\n",
7474+ dinfo->di_btop, dinfo->di_bbot,
38d290e6
JR
7475+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry),
7476+ dinfo->di_tmpfile);
5afbbe0d 7477+ if (dinfo->di_btop < 0)
1facf9fc 7478+ return;
5afbbe0d
AM
7479+ for (bindex = dinfo->di_btop; bindex <= dinfo->di_bbot; bindex++)
7480+ do_pri_dentry(bindex, au_hdentry(dinfo, bindex)->hd_dentry);
1facf9fc 7481+}
7482+
7483+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
7484+{
7485+ char a[32];
7486+
7487+ if (!file || IS_ERR(file)) {
7488+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
7489+ return -1;
7490+ }
7491+ a[0] = 0;
7492+ if (bindex < 0
b912730e 7493+ && !IS_ERR_OR_NULL(file->f_path.dentry)
2000de60 7494+ && au_test_aufs(file->f_path.dentry->d_sb)
1facf9fc 7495+ && au_fi(file))
e49829fe 7496+ snprintf(a, sizeof(a), ", gen %d, mmapped %d",
2cbb1c4b 7497+ au_figen(file), atomic_read(&au_fi(file)->fi_mmapped));
b752ccd1 7498+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
1facf9fc 7499+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
b752ccd1 7500+ file->f_version, file->f_pos, a);
b912730e 7501+ if (!IS_ERR_OR_NULL(file->f_path.dentry))
2000de60 7502+ do_pri_dentry(bindex, file->f_path.dentry);
1facf9fc 7503+ return 0;
7504+}
7505+
7506+void au_dpri_file(struct file *file)
7507+{
7508+ struct au_finfo *finfo;
4a4d8108
AM
7509+ struct au_fidir *fidir;
7510+ struct au_hfile *hfile;
1facf9fc 7511+ aufs_bindex_t bindex;
7512+ int err;
7513+
7514+ err = do_pri_file(-1, file);
2000de60 7515+ if (err
b912730e 7516+ || IS_ERR_OR_NULL(file->f_path.dentry)
2000de60 7517+ || !au_test_aufs(file->f_path.dentry->d_sb))
1facf9fc 7518+ return;
7519+
7520+ finfo = au_fi(file);
7521+ if (!finfo)
7522+ return;
4a4d8108 7523+ if (finfo->fi_btop < 0)
1facf9fc 7524+ return;
4a4d8108
AM
7525+ fidir = finfo->fi_hdir;
7526+ if (!fidir)
7527+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
7528+ else
e49829fe
JR
7529+ for (bindex = finfo->fi_btop;
7530+ bindex >= 0 && bindex <= fidir->fd_bbot;
4a4d8108
AM
7531+ bindex++) {
7532+ hfile = fidir->fd_hfile + bindex;
7533+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
7534+ }
1facf9fc 7535+}
7536+
7537+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
7538+{
7539+ struct vfsmount *mnt;
7540+ struct super_block *sb;
7541+
7542+ if (!br || IS_ERR(br))
7543+ goto out;
86dc4139 7544+ mnt = au_br_mnt(br);
1facf9fc 7545+ if (!mnt || IS_ERR(mnt))
7546+ goto out;
7547+ sb = mnt->mnt_sb;
7548+ if (!sb || IS_ERR(sb))
7549+ goto out;
7550+
acd2b654 7551+ dpri("s%d: {perm 0x%x, id %d, wbr %p}, "
b752ccd1 7552+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, "
1facf9fc 7553+ "xino %d\n",
acd2b654
AM
7554+ bindex, br->br_perm, br->br_id, br->br_wbr,
7555+ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
b752ccd1 7556+ sb->s_flags, sb->s_count,
acd2b654
AM
7557+ atomic_read(&sb->s_active),
7558+ !!au_xino_file(br->br_xino, /*idx*/-1));
1facf9fc 7559+ return 0;
7560+
4f0767ce 7561+out:
1facf9fc 7562+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
7563+ return -1;
7564+}
7565+
7566+void au_dpri_sb(struct super_block *sb)
7567+{
7568+ struct au_sbinfo *sbinfo;
7569+ aufs_bindex_t bindex;
7570+ int err;
acd2b654 7571+ /* to reduce stack size */
1facf9fc 7572+ struct {
7573+ struct vfsmount mnt;
7574+ struct au_branch fake;
7575+ } *a;
7576+
7577+ /* this function can be called from magic sysrq */
7578+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
7579+ if (unlikely(!a)) {
7580+ dpri("no memory\n");
7581+ return;
7582+ }
7583+
7584+ a->mnt.mnt_sb = sb;
86dc4139 7585+ a->fake.br_path.mnt = &a->mnt;
1facf9fc 7586+ err = do_pri_br(-1, &a->fake);
9f237c51 7587+ au_kfree_rcu(a);
1facf9fc 7588+ dpri("dev 0x%x\n", sb->s_dev);
7589+ if (err || !au_test_aufs(sb))
7590+ return;
7591+
7592+ sbinfo = au_sbi(sb);
7593+ if (!sbinfo)
7594+ return;
f0c0a007
AM
7595+ dpri("nw %d, gen %u, kobj %d\n",
7596+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
521ced18 7597+ kref_read(&sbinfo->si_kobj.kref));
5afbbe0d 7598+ for (bindex = 0; bindex <= sbinfo->si_bbot; bindex++)
1facf9fc 7599+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
7600+}
7601+
7602+/* ---------------------------------------------------------------------- */
7603+
027c5e7a
AM
7604+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line)
7605+{
5527c038 7606+ struct inode *h_inode, *inode = d_inode(dentry);
027c5e7a 7607+ struct dentry *h_dentry;
5afbbe0d 7608+ aufs_bindex_t bindex, bbot, bi;
027c5e7a
AM
7609+
7610+ if (!inode /* || au_di(dentry)->di_lsc == AuLsc_DI_TMP */)
7611+ return;
7612+
5afbbe0d
AM
7613+ bbot = au_dbbot(dentry);
7614+ bi = au_ibbot(inode);
7615+ if (bi < bbot)
7616+ bbot = bi;
7617+ bindex = au_dbtop(dentry);
7618+ bi = au_ibtop(inode);
027c5e7a
AM
7619+ if (bi > bindex)
7620+ bindex = bi;
7621+
5afbbe0d 7622+ for (; bindex <= bbot; bindex++) {
027c5e7a
AM
7623+ h_dentry = au_h_dptr(dentry, bindex);
7624+ if (!h_dentry)
7625+ continue;
7626+ h_inode = au_h_iptr(inode, bindex);
5527c038 7627+ if (unlikely(h_inode != d_inode(h_dentry))) {
392086de 7628+ au_debug_on();
027c5e7a
AM
7629+ AuDbg("b%d, %s:%d\n", bindex, func, line);
7630+ AuDbgDentry(dentry);
7631+ AuDbgInode(inode);
392086de 7632+ au_debug_off();
758e9dad
AM
7633+ if (au_test_fuse(h_inode->i_sb))
7634+ WARN_ON_ONCE(1);
7635+ else
7636+ BUG();
027c5e7a
AM
7637+ }
7638+ }
7639+}
7640+
1facf9fc 7641+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
7642+{
7643+ int err, i, j;
7644+ struct au_dcsub_pages dpages;
7645+ struct au_dpage *dpage;
7646+ struct dentry **dentries;
7647+
7648+ err = au_dpages_init(&dpages, GFP_NOFS);
7649+ AuDebugOn(err);
027c5e7a 7650+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/1);
1facf9fc 7651+ AuDebugOn(err);
7652+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
7653+ dpage = dpages.dpages + i;
7654+ dentries = dpage->dentries;
7655+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
027c5e7a 7656+ AuDebugOn(au_digen_test(dentries[j], sigen));
1facf9fc 7657+ }
7658+ au_dpages_free(&dpages);
7659+}
7660+
1facf9fc 7661+void au_dbg_verify_kthread(void)
7662+{
53392da6 7663+ if (au_wkq_test()) {
1facf9fc 7664+ au_dbg_blocked();
1e00d052
AM
7665+ /*
7666+ * It may be recursive, but udba=notify between two aufs mounts,
7667+ * where a single ro branch is shared, is not a problem.
7668+ */
7669+ /* WARN_ON(1); */
1facf9fc 7670+ }
7671+}
7672+
7673+/* ---------------------------------------------------------------------- */
7674+
1facf9fc 7675+int __init au_debug_init(void)
7676+{
7677+ aufs_bindex_t bindex;
7678+ struct au_vdir_destr destr;
7679+
7680+ bindex = -1;
7681+ AuDebugOn(bindex >= 0);
7682+
7683+ destr.len = -1;
7684+ AuDebugOn(destr.len < NAME_MAX);
7685+
7686+#ifdef CONFIG_4KSTACKS
0c3ec466 7687+ pr_warn("CONFIG_4KSTACKS is defined.\n");
1facf9fc 7688+#endif
7689+
1facf9fc 7690+ return 0;
7691+}
7f207e10 7692diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
eca34b5c 7693--- /usr/share/empty/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
319657f6 7694+++ linux/fs/aufs/debug.h 2021-12-03 15:38:59.933313976 +0100
062440b3
AM
7695@@ -0,0 +1,226 @@
7696+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 7697+/*
6d176551 7698+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 7699+ *
7700+ * This program, aufs is free software; you can redistribute it and/or modify
7701+ * it under the terms of the GNU General Public License as published by
7702+ * the Free Software Foundation; either version 2 of the License, or
7703+ * (at your option) any later version.
dece6358
AM
7704+ *
7705+ * This program is distributed in the hope that it will be useful,
7706+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7707+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7708+ * GNU General Public License for more details.
7709+ *
7710+ * You should have received a copy of the GNU General Public License
523b37e3 7711+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7712+ */
7713+
7714+/*
7715+ * debug print functions
7716+ */
7717+
7718+#ifndef __AUFS_DEBUG_H__
7719+#define __AUFS_DEBUG_H__
7720+
7721+#ifdef __KERNEL__
7722+
392086de 7723+#include <linux/atomic.h>
4a4d8108
AM
7724+#include <linux/module.h>
7725+#include <linux/kallsyms.h>
1facf9fc 7726+#include <linux/sysrq.h>
4a4d8108 7727+
1facf9fc 7728+#ifdef CONFIG_AUFS_DEBUG
7729+#define AuDebugOn(a) BUG_ON(a)
7730+
7731+/* module parameter */
392086de
AM
7732+extern atomic_t aufs_debug;
7733+static inline void au_debug_on(void)
1facf9fc 7734+{
392086de
AM
7735+ atomic_inc(&aufs_debug);
7736+}
7737+static inline void au_debug_off(void)
7738+{
7739+ atomic_dec_if_positive(&aufs_debug);
1facf9fc 7740+}
7741+
7742+static inline int au_debug_test(void)
7743+{
392086de 7744+ return atomic_read(&aufs_debug) > 0;
1facf9fc 7745+}
7746+#else
7747+#define AuDebugOn(a) do {} while (0)
392086de
AM
7748+AuStubVoid(au_debug_on, void)
7749+AuStubVoid(au_debug_off, void)
4a4d8108 7750+AuStubInt0(au_debug_test, void)
1facf9fc 7751+#endif /* CONFIG_AUFS_DEBUG */
7752+
392086de
AM
7753+#define param_check_atomic_t(name, p) __param_check(name, p, atomic_t)
7754+
1facf9fc 7755+/* ---------------------------------------------------------------------- */
7756+
7757+/* debug print */
7758+
4a4d8108 7759+#define AuDbg(fmt, ...) do { \
1facf9fc 7760+ if (au_debug_test()) \
4a4d8108 7761+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
1facf9fc 7762+} while (0)
4a4d8108
AM
7763+#define AuLabel(l) AuDbg(#l "\n")
7764+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__)
7765+#define AuWarn1(fmt, ...) do { \
1facf9fc 7766+ static unsigned char _c; \
7767+ if (!_c++) \
0c3ec466 7768+ pr_warn(fmt, ##__VA_ARGS__); \
1facf9fc 7769+} while (0)
7770+
4a4d8108 7771+#define AuErr1(fmt, ...) do { \
1facf9fc 7772+ static unsigned char _c; \
7773+ if (!_c++) \
4a4d8108 7774+ pr_err(fmt, ##__VA_ARGS__); \
1facf9fc 7775+} while (0)
7776+
4a4d8108 7777+#define AuIOErr1(fmt, ...) do { \
1facf9fc 7778+ static unsigned char _c; \
7779+ if (!_c++) \
4a4d8108 7780+ AuIOErr(fmt, ##__VA_ARGS__); \
1facf9fc 7781+} while (0)
7782+
7783+#define AuUnsupportMsg "This operation is not supported." \
7784+ " Please report this application to aufs-users ML."
4a4d8108
AM
7785+#define AuUnsupport(fmt, ...) do { \
7786+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
1facf9fc 7787+ dump_stack(); \
7788+} while (0)
7789+
7790+#define AuTraceErr(e) do { \
7791+ if (unlikely((e) < 0)) \
7792+ AuDbg("err %d\n", (int)(e)); \
7793+} while (0)
7794+
7795+#define AuTraceErrPtr(p) do { \
7796+ if (IS_ERR(p)) \
7797+ AuDbg("err %ld\n", PTR_ERR(p)); \
7798+} while (0)
7799+
7800+/* dirty macros for debug print, use with "%.*s" and caution */
7801+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
1facf9fc 7802+
7803+/* ---------------------------------------------------------------------- */
7804+
dece6358 7805+struct dentry;
1facf9fc 7806+#ifdef CONFIG_AUFS_DEBUG
c1595e42 7807+extern struct mutex au_dbg_mtx;
1facf9fc 7808+extern char *au_plevel;
7809+struct au_nhash;
7810+void au_dpri_whlist(struct au_nhash *whlist);
7811+struct au_vdir;
7812+void au_dpri_vdir(struct au_vdir *vdir);
dece6358 7813+struct inode;
1facf9fc 7814+void au_dpri_inode(struct inode *inode);
2cbb1c4b 7815+void au_dpri_dalias(struct inode *inode);
1facf9fc 7816+void au_dpri_dentry(struct dentry *dentry);
dece6358 7817+struct file;
1facf9fc 7818+void au_dpri_file(struct file *filp);
dece6358 7819+struct super_block;
1facf9fc 7820+void au_dpri_sb(struct super_block *sb);
7821+
027c5e7a
AM
7822+#define au_dbg_verify_dinode(d) __au_dbg_verify_dinode(d, __func__, __LINE__)
7823+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line);
1facf9fc 7824+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
1facf9fc 7825+void au_dbg_verify_kthread(void);
7826+
7827+int __init au_debug_init(void);
7e9cd9fe 7828+
1facf9fc 7829+#define AuDbgWhlist(w) do { \
c1595e42 7830+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7831+ AuDbg(#w "\n"); \
7832+ au_dpri_whlist(w); \
c1595e42 7833+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7834+} while (0)
7835+
7836+#define AuDbgVdir(v) do { \
c1595e42 7837+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7838+ AuDbg(#v "\n"); \
7839+ au_dpri_vdir(v); \
c1595e42 7840+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7841+} while (0)
7842+
7843+#define AuDbgInode(i) do { \
c1595e42 7844+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7845+ AuDbg(#i "\n"); \
7846+ au_dpri_inode(i); \
c1595e42 7847+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7848+} while (0)
7849+
2cbb1c4b 7850+#define AuDbgDAlias(i) do { \
c1595e42 7851+ mutex_lock(&au_dbg_mtx); \
2cbb1c4b
JR
7852+ AuDbg(#i "\n"); \
7853+ au_dpri_dalias(i); \
c1595e42 7854+ mutex_unlock(&au_dbg_mtx); \
2cbb1c4b
JR
7855+} while (0)
7856+
1facf9fc 7857+#define AuDbgDentry(d) do { \
c1595e42 7858+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7859+ AuDbg(#d "\n"); \
7860+ au_dpri_dentry(d); \
c1595e42 7861+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7862+} while (0)
7863+
7864+#define AuDbgFile(f) do { \
c1595e42 7865+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7866+ AuDbg(#f "\n"); \
7867+ au_dpri_file(f); \
c1595e42 7868+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7869+} while (0)
7870+
7871+#define AuDbgSb(sb) do { \
c1595e42 7872+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7873+ AuDbg(#sb "\n"); \
7874+ au_dpri_sb(sb); \
c1595e42 7875+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7876+} while (0)
7877+
4a4d8108
AM
7878+#define AuDbgSym(addr) do { \
7879+ char sym[KSYM_SYMBOL_LEN]; \
7880+ sprint_symbol(sym, (unsigned long)addr); \
7881+ AuDbg("%s\n", sym); \
7882+} while (0)
1facf9fc 7883+#else
027c5e7a 7884+AuStubVoid(au_dbg_verify_dinode, struct dentry *dentry)
4a4d8108
AM
7885+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
7886+AuStubVoid(au_dbg_verify_kthread, void)
7887+AuStubInt0(__init au_debug_init, void)
1facf9fc 7888+
1facf9fc 7889+#define AuDbgWhlist(w) do {} while (0)
7890+#define AuDbgVdir(v) do {} while (0)
7891+#define AuDbgInode(i) do {} while (0)
2cbb1c4b 7892+#define AuDbgDAlias(i) do {} while (0)
1facf9fc 7893+#define AuDbgDentry(d) do {} while (0)
7894+#define AuDbgFile(f) do {} while (0)
7895+#define AuDbgSb(sb) do {} while (0)
4a4d8108 7896+#define AuDbgSym(addr) do {} while (0)
1facf9fc 7897+#endif /* CONFIG_AUFS_DEBUG */
7898+
7899+/* ---------------------------------------------------------------------- */
7900+
7901+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
7902+int __init au_sysrq_init(void);
7903+void au_sysrq_fin(void);
7904+
7905+#ifdef CONFIG_HW_CONSOLE
7906+#define au_dbg_blocked() do { \
7907+ WARN_ON(1); \
0c5527e5 7908+ handle_sysrq('w'); \
1facf9fc 7909+} while (0)
7910+#else
4a4d8108 7911+AuStubVoid(au_dbg_blocked, void)
1facf9fc 7912+#endif
7913+
7914+#else
4a4d8108
AM
7915+AuStubInt0(__init au_sysrq_init, void)
7916+AuStubVoid(au_sysrq_fin, void)
7917+AuStubVoid(au_dbg_blocked, void)
1facf9fc 7918+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
7919+
7920+#endif /* __KERNEL__ */
7921+#endif /* __AUFS_DEBUG_H__ */
7f207e10 7922diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
eca34b5c 7923--- /usr/share/empty/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
319657f6 7924+++ linux/fs/aufs/dentry.c 2021-12-03 15:40:58.233313963 +0100
758e9dad 7925@@ -0,0 +1,1169 @@
cd7a4cd9 7926+// SPDX-License-Identifier: GPL-2.0
1facf9fc 7927+/*
6d176551 7928+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 7929+ *
7930+ * This program, aufs is free software; you can redistribute it and/or modify
7931+ * it under the terms of the GNU General Public License as published by
7932+ * the Free Software Foundation; either version 2 of the License, or
7933+ * (at your option) any later version.
dece6358
AM
7934+ *
7935+ * This program is distributed in the hope that it will be useful,
7936+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7937+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7938+ * GNU General Public License for more details.
7939+ *
7940+ * You should have received a copy of the GNU General Public License
523b37e3 7941+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7942+ */
7943+
7944+/*
7945+ * lookup and dentry operations
7946+ */
7947+
eca801bf 7948+#include <linux/iversion.h>
dece6358 7949+#include <linux/namei.h>
1facf9fc 7950+#include "aufs.h"
7951+
1facf9fc 7952+/*
7953+ * returns positive/negative dentry, NULL or an error.
7954+ * NULL means whiteout-ed or not-found.
7955+ */
7956+static struct dentry*
7957+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
8b6a4947 7958+ aufs_bindex_t bindex, struct au_do_lookup_args *args)
1facf9fc 7959+{
7960+ struct dentry *h_dentry;
2000de60 7961+ struct inode *h_inode;
1facf9fc 7962+ struct au_branch *br;
0b2a12c6 7963+ struct user_namespace *h_userns;
758e9dad 7964+ struct path h_path;
1facf9fc 7965+ int wh_found, opq;
7966+ unsigned char wh_able;
7967+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
076b876e
AM
7968+ const unsigned char ignore_perm = !!au_ftest_lkup(args->flags,
7969+ IGNORE_PERM);
1facf9fc 7970+
1facf9fc 7971+ wh_found = 0;
7972+ br = au_sbr(dentry->d_sb, bindex);
758e9dad
AM
7973+ h_path.dentry = h_parent;
7974+ h_path.mnt = au_br_mnt(br);
0b2a12c6 7975+ h_userns = au_br_userns(br);
1facf9fc 7976+ wh_able = !!au_br_whable(br->br_perm);
7977+ if (wh_able)
758e9dad 7978+ wh_found = au_wh_test(h_userns, &h_path, &args->whname,
0b2a12c6 7979+ ignore_perm);
1facf9fc 7980+ h_dentry = ERR_PTR(wh_found);
7981+ if (!wh_found)
7982+ goto real_lookup;
7983+ if (unlikely(wh_found < 0))
7984+ goto out;
7985+
7986+ /* We found a whiteout */
5afbbe0d 7987+ /* au_set_dbbot(dentry, bindex); */
1facf9fc 7988+ au_set_dbwh(dentry, bindex);
7989+ if (!allow_neg)
7990+ return NULL; /* success */
7991+
4f0767ce 7992+real_lookup:
076b876e 7993+ if (!ignore_perm)
758e9dad 7994+ h_dentry = vfsub_lkup_one(args->name, &h_path);
076b876e 7995+ else
758e9dad 7996+ h_dentry = au_sio_lkup_one(h_userns, args->name, &h_path);
2000de60
JR
7997+ if (IS_ERR(h_dentry)) {
7998+ if (PTR_ERR(h_dentry) == -ENAMETOOLONG
7999+ && !allow_neg)
8000+ h_dentry = NULL;
1facf9fc 8001+ goto out;
2000de60 8002+ }
1facf9fc 8003+
5527c038
JR
8004+ h_inode = d_inode(h_dentry);
8005+ if (d_is_negative(h_dentry)) {
1facf9fc 8006+ if (!allow_neg)
8007+ goto out_neg;
8008+ } else if (wh_found
8009+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
8010+ goto out_neg;
8b6a4947
AM
8011+ else if (au_ftest_lkup(args->flags, DIRREN)
8012+ /* && h_inode */
8013+ && !au_dr_lkup_h_ino(args, bindex, h_inode->i_ino)) {
8014+ AuDbg("b%d %pd ignored hi%llu\n", bindex, h_dentry,
8015+ (unsigned long long)h_inode->i_ino);
8016+ goto out_neg;
8017+ }
1facf9fc 8018+
5afbbe0d
AM
8019+ if (au_dbbot(dentry) <= bindex)
8020+ au_set_dbbot(dentry, bindex);
8021+ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry))
8022+ au_set_dbtop(dentry, bindex);
1facf9fc 8023+ au_set_h_dptr(dentry, bindex, h_dentry);
8024+
2000de60
JR
8025+ if (!d_is_dir(h_dentry)
8026+ || !wh_able
5527c038 8027+ || (d_really_is_positive(dentry) && !d_is_dir(dentry)))
1facf9fc 8028+ goto out; /* success */
8029+
758e9dad 8030+ h_path.dentry = h_dentry;
be118d29 8031+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD);
758e9dad 8032+ opq = au_diropq_test(h_userns, &h_path);
3c1bdaff 8033+ inode_unlock_shared(h_inode);
1facf9fc 8034+ if (opq > 0)
8035+ au_set_dbdiropq(dentry, bindex);
8036+ else if (unlikely(opq < 0)) {
8037+ au_set_h_dptr(dentry, bindex, NULL);
8038+ h_dentry = ERR_PTR(opq);
8039+ }
8040+ goto out;
8041+
4f0767ce 8042+out_neg:
1facf9fc 8043+ dput(h_dentry);
8044+ h_dentry = NULL;
4f0767ce 8045+out:
1facf9fc 8046+ return h_dentry;
8047+}
8048+
dece6358
AM
8049+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
8050+{
8051+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
8052+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
8053+ return -EPERM;
8054+ return 0;
8055+}
8056+
1facf9fc 8057+/*
8058+ * returns the number of lower positive dentries,
8059+ * otherwise an error.
8060+ * can be called at unlinking with @type is zero.
8061+ */
5afbbe0d
AM
8062+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop,
8063+ unsigned int flags)
1facf9fc 8064+{
8065+ int npositive, err;
8066+ aufs_bindex_t bindex, btail, bdiropq;
8b6a4947 8067+ unsigned char isdir, dirperm1, dirren;
1facf9fc 8068+ struct au_do_lookup_args args = {
8b6a4947
AM
8069+ .flags = flags,
8070+ .name = &dentry->d_name
1facf9fc 8071+ };
1facf9fc 8072+ struct dentry *parent;
076b876e 8073+ struct super_block *sb;
1facf9fc 8074+
076b876e 8075+ sb = dentry->d_sb;
8b6a4947 8076+ err = au_test_shwh(sb, args.name);
dece6358 8077+ if (unlikely(err))
1facf9fc 8078+ goto out;
8079+
8b6a4947 8080+ err = au_wh_name_alloc(&args.whname, args.name);
1facf9fc 8081+ if (unlikely(err))
8082+ goto out;
8083+
2000de60 8084+ isdir = !!d_is_dir(dentry);
076b876e 8085+ dirperm1 = !!au_opt_test(au_mntflags(sb), DIRPERM1);
8b6a4947
AM
8086+ dirren = !!au_opt_test(au_mntflags(sb), DIRREN);
8087+ if (dirren)
8088+ au_fset_lkup(args.flags, DIRREN);
1facf9fc 8089+
8090+ npositive = 0;
4a4d8108 8091+ parent = dget_parent(dentry);
1facf9fc 8092+ btail = au_dbtaildir(parent);
5afbbe0d 8093+ for (bindex = btop; bindex <= btail; bindex++) {
1facf9fc 8094+ struct dentry *h_parent, *h_dentry;
8095+ struct inode *h_inode, *h_dir;
8b6a4947 8096+ struct au_branch *br;
1facf9fc 8097+
8098+ h_dentry = au_h_dptr(dentry, bindex);
8099+ if (h_dentry) {
5527c038 8100+ if (d_is_positive(h_dentry))
1facf9fc 8101+ npositive++;
5afbbe0d 8102+ break;
1facf9fc 8103+ }
8104+ h_parent = au_h_dptr(parent, bindex);
2000de60 8105+ if (!h_parent || !d_is_dir(h_parent))
1facf9fc 8106+ continue;
8107+
8b6a4947
AM
8108+ if (dirren) {
8109+ /* if the inum matches, then use the prepared name */
8110+ err = au_dr_lkup_name(&args, bindex);
8111+ if (unlikely(err))
8112+ goto out_parent;
8113+ }
8114+
5527c038 8115+ h_dir = d_inode(h_parent);
be118d29 8116+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
8b6a4947 8117+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &args);
3c1bdaff 8118+ inode_unlock_shared(h_dir);
1facf9fc 8119+ err = PTR_ERR(h_dentry);
8120+ if (IS_ERR(h_dentry))
4a4d8108 8121+ goto out_parent;
2000de60
JR
8122+ if (h_dentry)
8123+ au_fclr_lkup(args.flags, ALLOW_NEG);
076b876e
AM
8124+ if (dirperm1)
8125+ au_fset_lkup(args.flags, IGNORE_PERM);
1facf9fc 8126+
79b8bda9 8127+ if (au_dbwh(dentry) == bindex)
1facf9fc 8128+ break;
8129+ if (!h_dentry)
8130+ continue;
5527c038 8131+ if (d_is_negative(h_dentry))
1facf9fc 8132+ continue;
5527c038 8133+ h_inode = d_inode(h_dentry);
1facf9fc 8134+ npositive++;
8135+ if (!args.type)
8136+ args.type = h_inode->i_mode & S_IFMT;
8137+ if (args.type != S_IFDIR)
8138+ break;
8139+ else if (isdir) {
8140+ /* the type of lower may be different */
8141+ bdiropq = au_dbdiropq(dentry);
8142+ if (bdiropq >= 0 && bdiropq <= bindex)
8143+ break;
8144+ }
8b6a4947
AM
8145+ br = au_sbr(sb, bindex);
8146+ if (dirren
8147+ && au_dr_hino_test_add(&br->br_dirren, h_inode->i_ino,
8148+ /*add_ent*/NULL)) {
8149+ /* prepare next name to lookup */
8150+ err = au_dr_lkup(&args, dentry, bindex);
8151+ if (unlikely(err))
8152+ goto out_parent;
8153+ }
1facf9fc 8154+ }
8155+
8156+ if (npositive) {
8157+ AuLabel(positive);
5afbbe0d 8158+ au_update_dbtop(dentry);
1facf9fc 8159+ }
8160+ err = npositive;
076b876e 8161+ if (unlikely(!au_opt_test(au_mntflags(sb), UDBA_NONE)
5afbbe0d 8162+ && au_dbtop(dentry) < 0)) {
1facf9fc 8163+ err = -EIO;
523b37e3
AM
8164+ AuIOErr("both of real entry and whiteout found, %pd, err %d\n",
8165+ dentry, err);
027c5e7a 8166+ }
1facf9fc 8167+
4f0767ce 8168+out_parent:
4a4d8108 8169+ dput(parent);
9f237c51 8170+ au_kfree_try_rcu(args.whname.name);
8b6a4947
AM
8171+ if (dirren)
8172+ au_dr_lkup_fin(&args);
4f0767ce 8173+out:
1facf9fc 8174+ return err;
8175+}
8176+
0b2a12c6 8177+struct dentry *au_sio_lkup_one(struct user_namespace *userns, struct qstr *name,
758e9dad 8178+ struct path *ppath)
1facf9fc 8179+{
8180+ struct dentry *dentry;
8181+ int wkq_err;
8182+
758e9dad
AM
8183+ if (!au_test_h_perm_sio(userns, d_inode(ppath->dentry), MAY_EXEC))
8184+ dentry = vfsub_lkup_one(name, ppath);
1facf9fc 8185+ else {
b4510431
AM
8186+ struct vfsub_lkup_one_args args = {
8187+ .errp = &dentry,
8188+ .name = name,
758e9dad 8189+ .ppath = ppath
1facf9fc 8190+ };
8191+
b4510431 8192+ wkq_err = au_wkq_wait(vfsub_call_lkup_one, &args);
1facf9fc 8193+ if (unlikely(wkq_err))
8194+ dentry = ERR_PTR(wkq_err);
8195+ }
8196+
8197+ return dentry;
8198+}
8199+
8200+/*
8201+ * lookup @dentry on @bindex which should be negative.
8202+ */
86dc4139 8203+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh)
1facf9fc 8204+{
8205+ int err;
758e9dad 8206+ struct dentry *parent, *h_dentry;
86dc4139 8207+ struct au_branch *br;
0b2a12c6 8208+ struct user_namespace *h_userns;
758e9dad 8209+ struct path h_ppath;
1facf9fc 8210+
1facf9fc 8211+ parent = dget_parent(dentry);
86dc4139 8212+ br = au_sbr(dentry->d_sb, bindex);
758e9dad
AM
8213+ h_ppath.dentry = au_h_dptr(parent, bindex);
8214+ h_ppath.mnt = au_br_mnt(br);
0b2a12c6 8215+ h_userns = au_br_userns(br);
86dc4139 8216+ if (wh)
758e9dad 8217+ h_dentry = au_whtmp_lkup(h_ppath.dentry, br, &dentry->d_name);
86dc4139 8218+ else
758e9dad 8219+ h_dentry = au_sio_lkup_one(h_userns, &dentry->d_name, &h_ppath);
1facf9fc 8220+ err = PTR_ERR(h_dentry);
8221+ if (IS_ERR(h_dentry))
8222+ goto out;
5527c038 8223+ if (unlikely(d_is_positive(h_dentry))) {
1facf9fc 8224+ err = -EIO;
523b37e3 8225+ AuIOErr("%pd should be negative on b%d.\n", h_dentry, bindex);
1facf9fc 8226+ dput(h_dentry);
8227+ goto out;
8228+ }
8229+
4a4d8108 8230+ err = 0;
5afbbe0d
AM
8231+ if (bindex < au_dbtop(dentry))
8232+ au_set_dbtop(dentry, bindex);
8233+ if (au_dbbot(dentry) < bindex)
8234+ au_set_dbbot(dentry, bindex);
1facf9fc 8235+ au_set_h_dptr(dentry, bindex, h_dentry);
1facf9fc 8236+
4f0767ce 8237+out:
1facf9fc 8238+ dput(parent);
8239+ return err;
8240+}
8241+
8242+/* ---------------------------------------------------------------------- */
8243+
8244+/* subset of struct inode */
8245+struct au_iattr {
8246+ unsigned long i_ino;
8247+ /* unsigned int i_nlink; */
0c3ec466
AM
8248+ kuid_t i_uid;
8249+ kgid_t i_gid;
1facf9fc 8250+ u64 i_version;
8251+/*
8252+ loff_t i_size;
8253+ blkcnt_t i_blocks;
8254+*/
8255+ umode_t i_mode;
8256+};
8257+
8258+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
8259+{
8260+ ia->i_ino = h_inode->i_ino;
8261+ /* ia->i_nlink = h_inode->i_nlink; */
8262+ ia->i_uid = h_inode->i_uid;
8263+ ia->i_gid = h_inode->i_gid;
be118d29 8264+ ia->i_version = inode_query_iversion(h_inode);
1facf9fc 8265+/*
8266+ ia->i_size = h_inode->i_size;
8267+ ia->i_blocks = h_inode->i_blocks;
8268+*/
8269+ ia->i_mode = (h_inode->i_mode & S_IFMT);
8270+}
8271+
8272+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
8273+{
8274+ return ia->i_ino != h_inode->i_ino
8275+ /* || ia->i_nlink != h_inode->i_nlink */
0c3ec466 8276+ || !uid_eq(ia->i_uid, h_inode->i_uid)
2dfbb274 8277+ || !gid_eq(ia->i_gid, h_inode->i_gid)
be118d29 8278+ || !inode_eq_iversion(h_inode, ia->i_version)
1facf9fc 8279+/*
8280+ || ia->i_size != h_inode->i_size
8281+ || ia->i_blocks != h_inode->i_blocks
8282+*/
8283+ || ia->i_mode != (h_inode->i_mode & S_IFMT);
8284+}
8285+
8286+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
8287+ struct au_branch *br)
8288+{
8289+ int err;
8290+ struct au_iattr ia;
8291+ struct inode *h_inode;
8292+ struct dentry *h_d;
8293+ struct super_block *h_sb;
758e9dad 8294+ struct path h_ppath;
1facf9fc 8295+
8296+ err = 0;
8297+ memset(&ia, -1, sizeof(ia));
8298+ h_sb = h_dentry->d_sb;
5527c038
JR
8299+ h_inode = NULL;
8300+ if (d_is_positive(h_dentry)) {
8301+ h_inode = d_inode(h_dentry);
1facf9fc 8302+ au_iattr_save(&ia, h_inode);
5527c038 8303+ } else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
1facf9fc 8304+ /* nfs d_revalidate may return 0 for negative dentry */
8305+ /* fuse d_revalidate always return 0 for negative dentry */
8306+ goto out;
8307+
8308+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
758e9dad
AM
8309+ h_ppath.dentry = h_parent;
8310+ h_ppath.mnt = au_br_mnt(br);
8311+ h_d = vfsub_lkup_one(&h_dentry->d_name, &h_ppath);
1facf9fc 8312+ err = PTR_ERR(h_d);
8313+ if (IS_ERR(h_d))
8314+ goto out;
8315+
8316+ err = 0;
8317+ if (unlikely(h_d != h_dentry
5527c038 8318+ || d_inode(h_d) != h_inode
1facf9fc 8319+ || (h_inode && au_iattr_test(&ia, h_inode))))
8320+ err = au_busy_or_stale();
8321+ dput(h_d);
8322+
4f0767ce 8323+out:
1facf9fc 8324+ AuTraceErr(err);
8325+ return err;
8326+}
8327+
8328+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
8329+ struct dentry *h_parent, struct au_branch *br)
8330+{
8331+ int err;
8332+
8333+ err = 0;
027c5e7a
AM
8334+ if (udba == AuOpt_UDBA_REVAL
8335+ && !au_test_fs_remote(h_dentry->d_sb)) {
1facf9fc 8336+ IMustLock(h_dir);
5527c038 8337+ err = (d_inode(h_dentry->d_parent) != h_dir);
027c5e7a 8338+ } else if (udba != AuOpt_UDBA_NONE)
1facf9fc 8339+ err = au_h_verify_dentry(h_dentry, h_parent, br);
8340+
8341+ return err;
8342+}
8343+
8344+/* ---------------------------------------------------------------------- */
8345+
027c5e7a 8346+static int au_do_refresh_hdentry(struct dentry *dentry, struct dentry *parent)
1facf9fc 8347+{
027c5e7a 8348+ int err;
5afbbe0d 8349+ aufs_bindex_t new_bindex, bindex, bbot, bwh, bdiropq;
027c5e7a
AM
8350+ struct au_hdentry tmp, *p, *q;
8351+ struct au_dinfo *dinfo;
8352+ struct super_block *sb;
1facf9fc 8353+
027c5e7a 8354+ DiMustWriteLock(dentry);
1308ab2a 8355+
027c5e7a
AM
8356+ sb = dentry->d_sb;
8357+ dinfo = au_di(dentry);
5afbbe0d 8358+ bbot = dinfo->di_bbot;
1facf9fc 8359+ bwh = dinfo->di_bwh;
8360+ bdiropq = dinfo->di_bdiropq;
5afbbe0d
AM
8361+ bindex = dinfo->di_btop;
8362+ p = au_hdentry(dinfo, bindex);
8363+ for (; bindex <= bbot; bindex++, p++) {
027c5e7a 8364+ if (!p->hd_dentry)
1facf9fc 8365+ continue;
8366+
027c5e7a
AM
8367+ new_bindex = au_br_index(sb, p->hd_id);
8368+ if (new_bindex == bindex)
1facf9fc 8369+ continue;
1facf9fc 8370+
1facf9fc 8371+ if (dinfo->di_bwh == bindex)
8372+ bwh = new_bindex;
8373+ if (dinfo->di_bdiropq == bindex)
8374+ bdiropq = new_bindex;
8375+ if (new_bindex < 0) {
8376+ au_hdput(p);
8377+ p->hd_dentry = NULL;
8378+ continue;
8379+ }
8380+
8381+ /* swap two lower dentries, and loop again */
5afbbe0d 8382+ q = au_hdentry(dinfo, new_bindex);
1facf9fc 8383+ tmp = *q;
8384+ *q = *p;
8385+ *p = tmp;
8386+ if (tmp.hd_dentry) {
8387+ bindex--;
8388+ p--;
8389+ }
8390+ }
8391+
1facf9fc 8392+ dinfo->di_bwh = -1;
5afbbe0d 8393+ if (bwh >= 0 && bwh <= au_sbbot(sb) && au_sbr_whable(sb, bwh))
1facf9fc 8394+ dinfo->di_bwh = bwh;
8395+
8396+ dinfo->di_bdiropq = -1;
8397+ if (bdiropq >= 0
5afbbe0d 8398+ && bdiropq <= au_sbbot(sb)
1facf9fc 8399+ && au_sbr_whable(sb, bdiropq))
8400+ dinfo->di_bdiropq = bdiropq;
8401+
027c5e7a 8402+ err = -EIO;
5afbbe0d
AM
8403+ dinfo->di_btop = -1;
8404+ dinfo->di_bbot = -1;
8405+ bbot = au_dbbot(parent);
8406+ bindex = 0;
8407+ p = au_hdentry(dinfo, bindex);
8408+ for (; bindex <= bbot; bindex++, p++)
1facf9fc 8409+ if (p->hd_dentry) {
5afbbe0d 8410+ dinfo->di_btop = bindex;
1facf9fc 8411+ break;
8412+ }
8413+
5afbbe0d
AM
8414+ if (dinfo->di_btop >= 0) {
8415+ bindex = bbot;
8416+ p = au_hdentry(dinfo, bindex);
8417+ for (; bindex >= 0; bindex--, p--)
027c5e7a 8418+ if (p->hd_dentry) {
5afbbe0d 8419+ dinfo->di_bbot = bindex;
027c5e7a
AM
8420+ err = 0;
8421+ break;
8422+ }
8423+ }
8424+
8425+ return err;
1facf9fc 8426+}
8427+
027c5e7a 8428+static void au_do_hide(struct dentry *dentry)
1facf9fc 8429+{
027c5e7a 8430+ struct inode *inode;
1facf9fc 8431+
5527c038
JR
8432+ if (d_really_is_positive(dentry)) {
8433+ inode = d_inode(dentry);
8434+ if (!d_is_dir(dentry)) {
027c5e7a
AM
8435+ if (inode->i_nlink && !d_unhashed(dentry))
8436+ drop_nlink(inode);
8437+ } else {
8438+ clear_nlink(inode);
8439+ /* stop next lookup */
8440+ inode->i_flags |= S_DEAD;
8441+ }
8442+ smp_mb(); /* necessary? */
8443+ }
8444+ d_drop(dentry);
8445+}
1308ab2a 8446+
027c5e7a
AM
8447+static int au_hide_children(struct dentry *parent)
8448+{
8449+ int err, i, j, ndentry;
8450+ struct au_dcsub_pages dpages;
8451+ struct au_dpage *dpage;
8452+ struct dentry *dentry;
1facf9fc 8453+
027c5e7a 8454+ err = au_dpages_init(&dpages, GFP_NOFS);
1facf9fc 8455+ if (unlikely(err))
8456+ goto out;
027c5e7a
AM
8457+ err = au_dcsub_pages(&dpages, parent, NULL, NULL);
8458+ if (unlikely(err))
8459+ goto out_dpages;
1facf9fc 8460+
027c5e7a
AM
8461+ /* in reverse order */
8462+ for (i = dpages.ndpage - 1; i >= 0; i--) {
8463+ dpage = dpages.dpages + i;
8464+ ndentry = dpage->ndentry;
8465+ for (j = ndentry - 1; j >= 0; j--) {
8466+ dentry = dpage->dentries[j];
8467+ if (dentry != parent)
8468+ au_do_hide(dentry);
8469+ }
8470+ }
1facf9fc 8471+
027c5e7a
AM
8472+out_dpages:
8473+ au_dpages_free(&dpages);
4f0767ce 8474+out:
027c5e7a 8475+ return err;
1facf9fc 8476+}
8477+
027c5e7a 8478+static void au_hide(struct dentry *dentry)
1facf9fc 8479+{
027c5e7a 8480+ int err;
1facf9fc 8481+
027c5e7a 8482+ AuDbgDentry(dentry);
2000de60 8483+ if (d_is_dir(dentry)) {
027c5e7a
AM
8484+ /* shrink_dcache_parent(dentry); */
8485+ err = au_hide_children(dentry);
8486+ if (unlikely(err))
523b37e3
AM
8487+ AuIOErr("%pd, failed hiding children, ignored %d\n",
8488+ dentry, err);
027c5e7a
AM
8489+ }
8490+ au_do_hide(dentry);
8491+}
1facf9fc 8492+
027c5e7a
AM
8493+/*
8494+ * By adding a dirty branch, a cached dentry may be affected in various ways.
8495+ *
8496+ * a dirty branch is added
8497+ * - on the top of layers
8498+ * - in the middle of layers
8499+ * - to the bottom of layers
8500+ *
8501+ * on the added branch there exists
8502+ * - a whiteout
8503+ * - a diropq
8504+ * - a same named entry
8505+ * + exist
8506+ * * negative --> positive
8507+ * * positive --> positive
8508+ * - type is unchanged
8509+ * - type is changed
8510+ * + doesn't exist
8511+ * * negative --> negative
8512+ * * positive --> negative (rejected by au_br_del() for non-dir case)
8513+ * - none
8514+ */
8515+static int au_refresh_by_dinfo(struct dentry *dentry, struct au_dinfo *dinfo,
8516+ struct au_dinfo *tmp)
8517+{
8518+ int err;
5afbbe0d 8519+ aufs_bindex_t bindex, bbot;
027c5e7a
AM
8520+ struct {
8521+ struct dentry *dentry;
8522+ struct inode *inode;
8523+ mode_t mode;
be52b249
AM
8524+ } orig_h, tmp_h = {
8525+ .dentry = NULL
8526+ };
027c5e7a
AM
8527+ struct au_hdentry *hd;
8528+ struct inode *inode, *h_inode;
8529+ struct dentry *h_dentry;
8530+
8531+ err = 0;
5afbbe0d 8532+ AuDebugOn(dinfo->di_btop < 0);
027c5e7a 8533+ orig_h.mode = 0;
5afbbe0d 8534+ orig_h.dentry = au_hdentry(dinfo, dinfo->di_btop)->hd_dentry;
5527c038
JR
8535+ orig_h.inode = NULL;
8536+ if (d_is_positive(orig_h.dentry)) {
8537+ orig_h.inode = d_inode(orig_h.dentry);
027c5e7a 8538+ orig_h.mode = orig_h.inode->i_mode & S_IFMT;
5527c038 8539+ }
5afbbe0d
AM
8540+ if (tmp->di_btop >= 0) {
8541+ tmp_h.dentry = au_hdentry(tmp, tmp->di_btop)->hd_dentry;
5527c038
JR
8542+ if (d_is_positive(tmp_h.dentry)) {
8543+ tmp_h.inode = d_inode(tmp_h.dentry);
027c5e7a 8544+ tmp_h.mode = tmp_h.inode->i_mode & S_IFMT;
5527c038 8545+ }
027c5e7a
AM
8546+ }
8547+
5527c038
JR
8548+ inode = NULL;
8549+ if (d_really_is_positive(dentry))
8550+ inode = d_inode(dentry);
027c5e7a 8551+ if (!orig_h.inode) {
acd2b654 8552+ AuDbg("negative originally\n");
027c5e7a
AM
8553+ if (inode) {
8554+ au_hide(dentry);
8555+ goto out;
8556+ }
8557+ AuDebugOn(inode);
5afbbe0d 8558+ AuDebugOn(dinfo->di_btop != dinfo->di_bbot);
027c5e7a
AM
8559+ AuDebugOn(dinfo->di_bdiropq != -1);
8560+
8561+ if (!tmp_h.inode) {
8562+ AuDbg("negative --> negative\n");
8563+ /* should have only one negative lower */
5afbbe0d
AM
8564+ if (tmp->di_btop >= 0
8565+ && tmp->di_btop < dinfo->di_btop) {
8566+ AuDebugOn(tmp->di_btop != tmp->di_bbot);
8567+ AuDebugOn(dinfo->di_btop != dinfo->di_bbot);
8568+ au_set_h_dptr(dentry, dinfo->di_btop, NULL);
027c5e7a 8569+ au_di_cp(dinfo, tmp);
5afbbe0d
AM
8570+ hd = au_hdentry(tmp, tmp->di_btop);
8571+ au_set_h_dptr(dentry, tmp->di_btop,
027c5e7a
AM
8572+ dget(hd->hd_dentry));
8573+ }
8574+ au_dbg_verify_dinode(dentry);
8575+ } else {
8576+ AuDbg("negative --> positive\n");
8577+ /*
8578+ * similar to the behaviour of creating with bypassing
8579+ * aufs.
8580+ * unhash it in order to force an error in the
8581+ * succeeding create operation.
8582+ * we should not set S_DEAD here.
8583+ */
8584+ d_drop(dentry);
8585+ /* au_di_swap(tmp, dinfo); */
8586+ au_dbg_verify_dinode(dentry);
8587+ }
8588+ } else {
8589+ AuDbg("positive originally\n");
8590+ /* inode may be NULL */
8591+ AuDebugOn(inode && (inode->i_mode & S_IFMT) != orig_h.mode);
8592+ if (!tmp_h.inode) {
8593+ AuDbg("positive --> negative\n");
8594+ /* or bypassing aufs */
8595+ au_hide(dentry);
5afbbe0d 8596+ if (tmp->di_bwh >= 0 && tmp->di_bwh <= dinfo->di_btop)
027c5e7a
AM
8597+ dinfo->di_bwh = tmp->di_bwh;
8598+ if (inode)
8599+ err = au_refresh_hinode_self(inode);
8600+ au_dbg_verify_dinode(dentry);
8601+ } else if (orig_h.mode == tmp_h.mode) {
8602+ AuDbg("positive --> positive, same type\n");
8603+ if (!S_ISDIR(orig_h.mode)
5afbbe0d 8604+ && dinfo->di_btop > tmp->di_btop) {
027c5e7a
AM
8605+ /*
8606+ * similar to the behaviour of removing and
8607+ * creating.
8608+ */
8609+ au_hide(dentry);
8610+ if (inode)
8611+ err = au_refresh_hinode_self(inode);
8612+ au_dbg_verify_dinode(dentry);
8613+ } else {
8614+ /* fill empty slots */
5afbbe0d
AM
8615+ if (dinfo->di_btop > tmp->di_btop)
8616+ dinfo->di_btop = tmp->di_btop;
8617+ if (dinfo->di_bbot < tmp->di_bbot)
8618+ dinfo->di_bbot = tmp->di_bbot;
027c5e7a
AM
8619+ dinfo->di_bwh = tmp->di_bwh;
8620+ dinfo->di_bdiropq = tmp->di_bdiropq;
5afbbe0d
AM
8621+ bbot = dinfo->di_bbot;
8622+ bindex = tmp->di_btop;
8623+ hd = au_hdentry(tmp, bindex);
8624+ for (; bindex <= bbot; bindex++, hd++) {
027c5e7a
AM
8625+ if (au_h_dptr(dentry, bindex))
8626+ continue;
5afbbe0d 8627+ h_dentry = hd->hd_dentry;
027c5e7a
AM
8628+ if (!h_dentry)
8629+ continue;
5527c038
JR
8630+ AuDebugOn(d_is_negative(h_dentry));
8631+ h_inode = d_inode(h_dentry);
027c5e7a
AM
8632+ AuDebugOn(orig_h.mode
8633+ != (h_inode->i_mode
8634+ & S_IFMT));
8635+ au_set_h_dptr(dentry, bindex,
8636+ dget(h_dentry));
8637+ }
5afbbe0d
AM
8638+ if (inode)
8639+ err = au_refresh_hinode(inode, dentry);
027c5e7a
AM
8640+ au_dbg_verify_dinode(dentry);
8641+ }
8642+ } else {
8643+ AuDbg("positive --> positive, different type\n");
8644+ /* similar to the behaviour of removing and creating */
8645+ au_hide(dentry);
8646+ if (inode)
8647+ err = au_refresh_hinode_self(inode);
8648+ au_dbg_verify_dinode(dentry);
8649+ }
8650+ }
8651+
8652+out:
8653+ return err;
8654+}
8655+
79b8bda9
AM
8656+void au_refresh_dop(struct dentry *dentry, int force_reval)
8657+{
8658+ const struct dentry_operations *dop
8659+ = force_reval ? &aufs_dop : dentry->d_sb->s_d_op;
8660+ static const unsigned int mask
8661+ = DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE;
8662+
8663+ BUILD_BUG_ON(sizeof(mask) != sizeof(dentry->d_flags));
8664+
8665+ if (dentry->d_op == dop)
8666+ return;
8667+
8668+ AuDbg("%pd\n", dentry);
8669+ spin_lock(&dentry->d_lock);
8670+ if (dop == &aufs_dop)
8671+ dentry->d_flags |= mask;
8672+ else
8673+ dentry->d_flags &= ~mask;
8674+ dentry->d_op = dop;
8675+ spin_unlock(&dentry->d_lock);
8676+}
8677+
027c5e7a
AM
8678+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent)
8679+{
e2f27e51 8680+ int err, ebrange, nbr;
027c5e7a
AM
8681+ unsigned int sigen;
8682+ struct au_dinfo *dinfo, *tmp;
8683+ struct super_block *sb;
8684+ struct inode *inode;
8685+
8686+ DiMustWriteLock(dentry);
8687+ AuDebugOn(IS_ROOT(dentry));
5527c038 8688+ AuDebugOn(d_really_is_negative(parent));
027c5e7a
AM
8689+
8690+ sb = dentry->d_sb;
027c5e7a
AM
8691+ sigen = au_sigen(sb);
8692+ err = au_digen_test(parent, sigen);
8693+ if (unlikely(err))
8694+ goto out;
8695+
e2f27e51 8696+ nbr = au_sbbot(sb) + 1;
027c5e7a 8697+ dinfo = au_di(dentry);
e2f27e51 8698+ err = au_di_realloc(dinfo, nbr, /*may_shrink*/0);
027c5e7a
AM
8699+ if (unlikely(err))
8700+ goto out;
8701+ ebrange = au_dbrange_test(dentry);
8702+ if (!ebrange)
8703+ ebrange = au_do_refresh_hdentry(dentry, parent);
8704+
38d290e6 8705+ if (d_unhashed(dentry) || ebrange /* || dinfo->di_tmpfile */) {
5afbbe0d 8706+ AuDebugOn(au_dbtop(dentry) < 0 && au_dbbot(dentry) >= 0);
5527c038
JR
8707+ if (d_really_is_positive(dentry)) {
8708+ inode = d_inode(dentry);
027c5e7a 8709+ err = au_refresh_hinode_self(inode);
5527c038 8710+ }
027c5e7a
AM
8711+ au_dbg_verify_dinode(dentry);
8712+ if (!err)
8713+ goto out_dgen; /* success */
8714+ goto out;
8715+ }
8716+
8717+ /* temporary dinfo */
8718+ AuDbgDentry(dentry);
8719+ err = -ENOMEM;
8720+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
8721+ if (unlikely(!tmp))
8722+ goto out;
8723+ au_di_swap(tmp, dinfo);
8724+ /* returns the number of positive dentries */
8725+ /*
8726+ * if current working dir is removed, it returns an error.
8727+ * but the dentry is legal.
8728+ */
5afbbe0d 8729+ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG);
027c5e7a
AM
8730+ AuDbgDentry(dentry);
8731+ au_di_swap(tmp, dinfo);
8732+ if (err == -ENOENT)
8733+ err = 0;
8734+ if (err >= 0) {
8735+ /* compare/refresh by dinfo */
8736+ AuDbgDentry(dentry);
8737+ err = au_refresh_by_dinfo(dentry, dinfo, tmp);
8738+ au_dbg_verify_dinode(dentry);
8739+ AuTraceErr(err);
8740+ }
e2f27e51 8741+ au_di_realloc(dinfo, nbr, /*may_shrink*/1); /* harmless if err */
027c5e7a
AM
8742+ au_rw_write_unlock(&tmp->di_rwsem);
8743+ au_di_free(tmp);
8744+ if (unlikely(err))
8745+ goto out;
8746+
8747+out_dgen:
8748+ au_update_digen(dentry);
8749+out:
8750+ if (unlikely(err && !(dentry->d_flags & DCACHE_NFSFS_RENAMED))) {
523b37e3 8751+ AuIOErr("failed refreshing %pd, %d\n", dentry, err);
027c5e7a
AM
8752+ AuDbgDentry(dentry);
8753+ }
8754+ AuTraceErr(err);
8755+ return err;
8756+}
8757+
b4510431
AM
8758+static int au_do_h_d_reval(struct dentry *h_dentry, unsigned int flags,
8759+ struct dentry *dentry, aufs_bindex_t bindex)
027c5e7a
AM
8760+{
8761+ int err, valid;
027c5e7a
AM
8762+
8763+ err = 0;
8764+ if (!(h_dentry->d_flags & DCACHE_OP_REVALIDATE))
8765+ goto out;
027c5e7a
AM
8766+
8767+ AuDbg("b%d\n", bindex);
b4510431
AM
8768+ /*
8769+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
8770+ * due to whiteout and branch permission.
8771+ */
8772+ flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
8773+ | LOOKUP_FOLLOW | LOOKUP_EXCL);
8774+ /* it may return tri-state */
8775+ valid = h_dentry->d_op->d_revalidate(h_dentry, flags);
1facf9fc 8776+
8777+ if (unlikely(valid < 0))
8778+ err = valid;
8779+ else if (!valid)
8780+ err = -EINVAL;
8781+
4f0767ce 8782+out:
1facf9fc 8783+ AuTraceErr(err);
8784+ return err;
8785+}
8786+
8787+/* todo: remove this */
8788+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
8b6a4947 8789+ unsigned int flags, int do_udba, int dirren)
1facf9fc 8790+{
8791+ int err;
8792+ umode_t mode, h_mode;
5afbbe0d 8793+ aufs_bindex_t bindex, btail, btop, ibs, ibe;
38d290e6 8794+ unsigned char plus, unhashed, is_root, h_plus, h_nfs, tmpfile;
4a4d8108 8795+ struct inode *h_inode, *h_cached_inode;
1facf9fc 8796+ struct dentry *h_dentry;
8797+ struct qstr *name, *h_name;
8798+
8799+ err = 0;
8800+ plus = 0;
8801+ mode = 0;
1facf9fc 8802+ ibs = -1;
8803+ ibe = -1;
8804+ unhashed = !!d_unhashed(dentry);
8805+ is_root = !!IS_ROOT(dentry);
8806+ name = &dentry->d_name;
38d290e6 8807+ tmpfile = au_di(dentry)->di_tmpfile;
1facf9fc 8808+
8809+ /*
7f207e10
AM
8810+ * Theoretically, REVAL test should be unnecessary in case of
8811+ * {FS,I}NOTIFY.
8812+ * But {fs,i}notify doesn't fire some necessary events,
1facf9fc 8813+ * IN_ATTRIB for atime/nlink/pageio
1facf9fc 8814+ * Let's do REVAL test too.
8815+ */
8816+ if (do_udba && inode) {
8817+ mode = (inode->i_mode & S_IFMT);
8818+ plus = (inode->i_nlink > 0);
5afbbe0d
AM
8819+ ibs = au_ibtop(inode);
8820+ ibe = au_ibbot(inode);
1facf9fc 8821+ }
8822+
5afbbe0d
AM
8823+ btop = au_dbtop(dentry);
8824+ btail = btop;
1facf9fc 8825+ if (inode && S_ISDIR(inode->i_mode))
8826+ btail = au_dbtaildir(dentry);
5afbbe0d 8827+ for (bindex = btop; bindex <= btail; bindex++) {
1facf9fc 8828+ h_dentry = au_h_dptr(dentry, bindex);
8829+ if (!h_dentry)
8830+ continue;
8831+
523b37e3
AM
8832+ AuDbg("b%d, %pd\n", bindex, h_dentry);
8833+ h_nfs = !!au_test_nfs(h_dentry->d_sb);
027c5e7a 8834+ spin_lock(&h_dentry->d_lock);
1facf9fc 8835+ h_name = &h_dentry->d_name;
8836+ if (unlikely(do_udba
8837+ && !is_root
523b37e3
AM
8838+ && ((!h_nfs
8839+ && (unhashed != !!d_unhashed(h_dentry)
8b6a4947 8840+ || (!tmpfile && !dirren
38d290e6
JR
8841+ && !au_qstreq(name, h_name))
8842+ ))
523b37e3
AM
8843+ || (h_nfs
8844+ && !(flags & LOOKUP_OPEN)
8845+ && (h_dentry->d_flags
8846+ & DCACHE_NFSFS_RENAMED)))
1facf9fc 8847+ )) {
38d290e6
JR
8848+ int h_unhashed;
8849+
8850+ h_unhashed = d_unhashed(h_dentry);
027c5e7a 8851+ spin_unlock(&h_dentry->d_lock);
38d290e6
JR
8852+ AuDbg("unhash 0x%x 0x%x, %pd %pd\n",
8853+ unhashed, h_unhashed, dentry, h_dentry);
1facf9fc 8854+ goto err;
8855+ }
027c5e7a 8856+ spin_unlock(&h_dentry->d_lock);
1facf9fc 8857+
b4510431 8858+ err = au_do_h_d_reval(h_dentry, flags, dentry, bindex);
1facf9fc 8859+ if (unlikely(err))
8860+ /* do not goto err, to keep the errno */
8861+ break;
8862+
8863+ /* todo: plink too? */
8864+ if (!do_udba)
8865+ continue;
8866+
8867+ /* UDBA tests */
5527c038 8868+ if (unlikely(!!inode != d_is_positive(h_dentry)))
1facf9fc 8869+ goto err;
8870+
5527c038
JR
8871+ h_inode = NULL;
8872+ if (d_is_positive(h_dentry))
8873+ h_inode = d_inode(h_dentry);
1facf9fc 8874+ h_plus = plus;
8875+ h_mode = mode;
8876+ h_cached_inode = h_inode;
8877+ if (h_inode) {
8878+ h_mode = (h_inode->i_mode & S_IFMT);
8879+ h_plus = (h_inode->i_nlink > 0);
8880+ }
8881+ if (inode && ibs <= bindex && bindex <= ibe)
8882+ h_cached_inode = au_h_iptr(inode, bindex);
8883+
523b37e3 8884+ if (!h_nfs) {
38d290e6 8885+ if (unlikely(plus != h_plus && !tmpfile))
523b37e3
AM
8886+ goto err;
8887+ } else {
8888+ if (unlikely(!(h_dentry->d_flags & DCACHE_NFSFS_RENAMED)
8889+ && !is_root
8890+ && !IS_ROOT(h_dentry)
8891+ && unhashed != d_unhashed(h_dentry)))
8892+ goto err;
8893+ }
8894+ if (unlikely(mode != h_mode
1facf9fc 8895+ || h_cached_inode != h_inode))
8896+ goto err;
8897+ continue;
8898+
f6b6e03d 8899+err:
1facf9fc 8900+ err = -EINVAL;
8901+ break;
8902+ }
8903+
523b37e3 8904+ AuTraceErr(err);
1facf9fc 8905+ return err;
8906+}
8907+
027c5e7a 8908+/* todo: consolidate with do_refresh() and au_reval_for_attr() */
1facf9fc 8909+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
8910+{
8911+ int err;
8912+ struct dentry *parent;
1facf9fc 8913+
027c5e7a 8914+ if (!au_digen_test(dentry, sigen))
1facf9fc 8915+ return 0;
8916+
8917+ parent = dget_parent(dentry);
8918+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 8919+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 8920+ au_dbg_verify_gen(parent, sigen);
027c5e7a 8921+ err = au_refresh_dentry(dentry, parent);
1facf9fc 8922+ di_read_unlock(parent, AuLock_IR);
8923+ dput(parent);
027c5e7a 8924+ AuTraceErr(err);
1facf9fc 8925+ return err;
8926+}
8927+
8928+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
8929+{
8930+ int err;
8931+ struct dentry *d, *parent;
1facf9fc 8932+
027c5e7a 8933+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR))
1facf9fc 8934+ return simple_reval_dpath(dentry, sigen);
8935+
8936+ /* slow loop, keep it simple and stupid */
8937+ /* cf: au_cpup_dirs() */
8938+ err = 0;
8939+ parent = NULL;
027c5e7a 8940+ while (au_digen_test(dentry, sigen)) {
1facf9fc 8941+ d = dentry;
8942+ while (1) {
8943+ dput(parent);
8944+ parent = dget_parent(d);
027c5e7a 8945+ if (!au_digen_test(parent, sigen))
1facf9fc 8946+ break;
8947+ d = parent;
8948+ }
8949+
1facf9fc 8950+ if (d != dentry)
027c5e7a 8951+ di_write_lock_child2(d);
1facf9fc 8952+
8953+ /* someone might update our dentry while we were sleeping */
027c5e7a
AM
8954+ if (au_digen_test(d, sigen)) {
8955+ /*
8956+ * todo: consolidate with simple_reval_dpath(),
8957+ * do_refresh() and au_reval_for_attr().
8958+ */
1facf9fc 8959+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 8960+ err = au_refresh_dentry(d, parent);
1facf9fc 8961+ di_read_unlock(parent, AuLock_IR);
8962+ }
8963+
8964+ if (d != dentry)
8965+ di_write_unlock(d);
8966+ dput(parent);
8967+ if (unlikely(err))
8968+ break;
8969+ }
8970+
8971+ return err;
8972+}
8973+
8974+/*
8975+ * if valid returns 1, otherwise 0.
8976+ */
b4510431 8977+static int aufs_d_revalidate(struct dentry *dentry, unsigned int flags)
1facf9fc 8978+{
8979+ int valid, err;
8980+ unsigned int sigen;
8b6a4947 8981+ unsigned char do_udba, dirren;
1facf9fc 8982+ struct super_block *sb;
8983+ struct inode *inode;
8984+
027c5e7a 8985+ /* todo: support rcu-walk? */
b4510431 8986+ if (flags & LOOKUP_RCU)
027c5e7a
AM
8987+ return -ECHILD;
8988+
8989+ valid = 0;
8990+ if (unlikely(!au_di(dentry)))
8991+ goto out;
8992+
e49829fe 8993+ valid = 1;
1facf9fc 8994+ sb = dentry->d_sb;
e49829fe
JR
8995+ /*
8996+ * todo: very ugly
8997+ * i_mutex of parent dir may be held,
8998+ * but we should not return 'invalid' due to busy.
8999+ */
9000+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM);
9001+ if (unlikely(err)) {
9002+ valid = err;
027c5e7a 9003+ AuTraceErr(err);
e49829fe
JR
9004+ goto out;
9005+ }
5527c038
JR
9006+ inode = NULL;
9007+ if (d_really_is_positive(dentry))
9008+ inode = d_inode(dentry);
5afbbe0d 9009+ if (unlikely(inode && au_is_bad_inode(inode))) {
c1595e42
JR
9010+ err = -EINVAL;
9011+ AuTraceErr(err);
9012+ goto out_dgrade;
9013+ }
027c5e7a
AM
9014+ if (unlikely(au_dbrange_test(dentry))) {
9015+ err = -EINVAL;
9016+ AuTraceErr(err);
9017+ goto out_dgrade;
1facf9fc 9018+ }
027c5e7a
AM
9019+
9020+ sigen = au_sigen(sb);
9021+ if (au_digen_test(dentry, sigen)) {
1facf9fc 9022+ AuDebugOn(IS_ROOT(dentry));
027c5e7a
AM
9023+ err = au_reval_dpath(dentry, sigen);
9024+ if (unlikely(err)) {
9025+ AuTraceErr(err);
1facf9fc 9026+ goto out_dgrade;
027c5e7a 9027+ }
1facf9fc 9028+ }
9029+ di_downgrade_lock(dentry, AuLock_IR);
9030+
1facf9fc 9031+ err = -EINVAL;
c1595e42 9032+ if (!(flags & (LOOKUP_OPEN | LOOKUP_EMPTY))
523b37e3 9033+ && inode
38d290e6 9034+ && !(inode->i_state && I_LINKABLE)
79b8bda9
AM
9035+ && (IS_DEADDIR(inode) || !inode->i_nlink)) {
9036+ AuTraceErr(err);
027c5e7a 9037+ goto out_inval;
79b8bda9 9038+ }
027c5e7a 9039+
1facf9fc 9040+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
9041+ if (do_udba && inode) {
5afbbe0d 9042+ aufs_bindex_t btop = au_ibtop(inode);
027c5e7a 9043+ struct inode *h_inode;
1facf9fc 9044+
5afbbe0d
AM
9045+ if (btop >= 0) {
9046+ h_inode = au_h_iptr(inode, btop);
79b8bda9
AM
9047+ if (h_inode && au_test_higen(inode, h_inode)) {
9048+ AuTraceErr(err);
027c5e7a 9049+ goto out_inval;
79b8bda9 9050+ }
027c5e7a 9051+ }
1facf9fc 9052+ }
9053+
8b6a4947
AM
9054+ dirren = !!au_opt_test(au_mntflags(sb), DIRREN);
9055+ err = h_d_revalidate(dentry, inode, flags, do_udba, dirren);
5afbbe0d 9056+ if (unlikely(!err && do_udba && au_dbtop(dentry) < 0)) {
1facf9fc 9057+ err = -EIO;
523b37e3
AM
9058+ AuDbg("both of real entry and whiteout found, %p, err %d\n",
9059+ dentry, err);
027c5e7a 9060+ }
e49829fe 9061+ goto out_inval;
1facf9fc 9062+
4f0767ce 9063+out_dgrade:
1facf9fc 9064+ di_downgrade_lock(dentry, AuLock_IR);
e49829fe 9065+out_inval:
1facf9fc 9066+ aufs_read_unlock(dentry, AuLock_IR);
9067+ AuTraceErr(err);
9068+ valid = !err;
e49829fe 9069+out:
027c5e7a 9070+ if (!valid) {
523b37e3 9071+ AuDbg("%pd invalid, %d\n", dentry, valid);
027c5e7a
AM
9072+ d_drop(dentry);
9073+ }
1facf9fc 9074+ return valid;
9075+}
9076+
9077+static void aufs_d_release(struct dentry *dentry)
9078+{
027c5e7a 9079+ if (au_di(dentry)) {
4a4d8108
AM
9080+ au_di_fin(dentry);
9081+ au_hn_di_reinit(dentry);
1facf9fc 9082+ }
1facf9fc 9083+}
9084+
4a4d8108 9085+const struct dentry_operations aufs_dop = {
c06a8ce3
AM
9086+ .d_revalidate = aufs_d_revalidate,
9087+ .d_weak_revalidate = aufs_d_revalidate,
9088+ .d_release = aufs_d_release
1facf9fc 9089+};
79b8bda9
AM
9090+
9091+/* aufs_dop without d_revalidate */
9092+const struct dentry_operations aufs_dop_noreval = {
9093+ .d_release = aufs_d_release
9094+};
7f207e10 9095diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
eca34b5c 9096--- /usr/share/empty/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
319657f6 9097+++ linux/fs/aufs/dentry.h 2021-12-03 15:40:58.233313963 +0100
0b2a12c6 9098@@ -0,0 +1,269 @@
062440b3 9099+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 9100+/*
6d176551 9101+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 9102+ *
9103+ * This program, aufs is free software; you can redistribute it and/or modify
9104+ * it under the terms of the GNU General Public License as published by
9105+ * the Free Software Foundation; either version 2 of the License, or
9106+ * (at your option) any later version.
dece6358
AM
9107+ *
9108+ * This program is distributed in the hope that it will be useful,
9109+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9110+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9111+ * GNU General Public License for more details.
9112+ *
9113+ * You should have received a copy of the GNU General Public License
523b37e3 9114+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 9115+ */
9116+
9117+/*
9118+ * lookup and dentry operations
9119+ */
9120+
9121+#ifndef __AUFS_DENTRY_H__
9122+#define __AUFS_DENTRY_H__
9123+
9124+#ifdef __KERNEL__
9125+
dece6358 9126+#include <linux/dcache.h>
8b6a4947 9127+#include "dirren.h"
1facf9fc 9128+#include "rwsem.h"
9129+
1facf9fc 9130+struct au_hdentry {
9131+ struct dentry *hd_dentry;
027c5e7a 9132+ aufs_bindex_t hd_id;
1facf9fc 9133+};
9134+
9135+struct au_dinfo {
9136+ atomic_t di_generation;
9137+
dece6358 9138+ struct au_rwsem di_rwsem;
5afbbe0d 9139+ aufs_bindex_t di_btop, di_bbot, di_bwh, di_bdiropq;
38d290e6 9140+ unsigned char di_tmpfile; /* to allow the different name */
1c60b727 9141+ struct au_hdentry *di_hdentry;
9f237c51 9142+ struct rcu_head rcu;
4a4d8108 9143+} ____cacheline_aligned_in_smp;
1facf9fc 9144+
9145+/* ---------------------------------------------------------------------- */
9146+
5afbbe0d
AM
9147+/* flags for au_lkup_dentry() */
9148+#define AuLkup_ALLOW_NEG 1
9149+#define AuLkup_IGNORE_PERM (1 << 1)
8b6a4947 9150+#define AuLkup_DIRREN (1 << 2)
5afbbe0d
AM
9151+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
9152+#define au_fset_lkup(flags, name) \
9153+ do { (flags) |= AuLkup_##name; } while (0)
9154+#define au_fclr_lkup(flags, name) \
9155+ do { (flags) &= ~AuLkup_##name; } while (0)
9156+
8b6a4947
AM
9157+#ifndef CONFIG_AUFS_DIRREN
9158+#undef AuLkup_DIRREN
9159+#define AuLkup_DIRREN 0
9160+#endif
9161+
9162+struct au_do_lookup_args {
9163+ unsigned int flags;
9164+ mode_t type;
9165+ struct qstr whname, *name;
9166+ struct au_dr_lookup dirren;
9167+};
9168+
5afbbe0d
AM
9169+/* ---------------------------------------------------------------------- */
9170+
1facf9fc 9171+/* dentry.c */
79b8bda9 9172+extern const struct dentry_operations aufs_dop, aufs_dop_noreval;
1facf9fc 9173+struct au_branch;
0b2a12c6 9174+struct dentry *au_sio_lkup_one(struct user_namespace *userns, struct qstr *name,
758e9dad 9175+ struct path *ppath);
1facf9fc 9176+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
9177+ struct dentry *h_parent, struct au_branch *br);
9178+
5afbbe0d
AM
9179+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop,
9180+ unsigned int flags);
86dc4139 9181+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh);
027c5e7a 9182+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent);
1facf9fc 9183+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
79b8bda9 9184+void au_refresh_dop(struct dentry *dentry, int force_reval);
1facf9fc 9185+
9186+/* dinfo.c */
4a4d8108 9187+void au_di_init_once(void *_di);
027c5e7a
AM
9188+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc);
9189+void au_di_free(struct au_dinfo *dinfo);
9190+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b);
9191+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src);
4a4d8108
AM
9192+int au_di_init(struct dentry *dentry);
9193+void au_di_fin(struct dentry *dentry);
e2f27e51 9194+int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink);
1facf9fc 9195+
9196+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
9197+void di_read_unlock(struct dentry *d, int flags);
9198+void di_downgrade_lock(struct dentry *d, int flags);
9199+void di_write_lock(struct dentry *d, unsigned int lsc);
9200+void di_write_unlock(struct dentry *d);
9201+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
9202+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
9203+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
9204+
9205+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
2cbb1c4b 9206+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex);
1facf9fc 9207+aufs_bindex_t au_dbtail(struct dentry *dentry);
9208+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
9209+
9210+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
9211+ struct dentry *h_dentry);
027c5e7a
AM
9212+int au_digen_test(struct dentry *dentry, unsigned int sigen);
9213+int au_dbrange_test(struct dentry *dentry);
1facf9fc 9214+void au_update_digen(struct dentry *dentry);
9215+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
5afbbe0d
AM
9216+void au_update_dbtop(struct dentry *dentry);
9217+void au_update_dbbot(struct dentry *dentry);
1facf9fc 9218+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
9219+
9220+/* ---------------------------------------------------------------------- */
9221+
9222+static inline struct au_dinfo *au_di(struct dentry *dentry)
9223+{
9224+ return dentry->d_fsdata;
9225+}
9226+
9227+/* ---------------------------------------------------------------------- */
9228+
9229+/* lock subclass for dinfo */
9230+enum {
9231+ AuLsc_DI_CHILD, /* child first */
4a4d8108 9232+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */
1facf9fc 9233+ AuLsc_DI_CHILD3, /* copyup dirs */
9234+ AuLsc_DI_PARENT,
9235+ AuLsc_DI_PARENT2,
027c5e7a
AM
9236+ AuLsc_DI_PARENT3,
9237+ AuLsc_DI_TMP /* temp for replacing dinfo */
1facf9fc 9238+};
9239+
9240+/*
9241+ * di_read_lock_child, di_write_lock_child,
9242+ * di_read_lock_child2, di_write_lock_child2,
9243+ * di_read_lock_child3, di_write_lock_child3,
9244+ * di_read_lock_parent, di_write_lock_parent,
9245+ * di_read_lock_parent2, di_write_lock_parent2,
9246+ * di_read_lock_parent3, di_write_lock_parent3,
9247+ */
9248+#define AuReadLockFunc(name, lsc) \
9249+static inline void di_read_lock_##name(struct dentry *d, int flags) \
9250+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
9251+
9252+#define AuWriteLockFunc(name, lsc) \
9253+static inline void di_write_lock_##name(struct dentry *d) \
9254+{ di_write_lock(d, AuLsc_DI_##lsc); }
9255+
9256+#define AuRWLockFuncs(name, lsc) \
9257+ AuReadLockFunc(name, lsc) \
9258+ AuWriteLockFunc(name, lsc)
9259+
9260+AuRWLockFuncs(child, CHILD);
9261+AuRWLockFuncs(child2, CHILD2);
9262+AuRWLockFuncs(child3, CHILD3);
9263+AuRWLockFuncs(parent, PARENT);
9264+AuRWLockFuncs(parent2, PARENT2);
9265+AuRWLockFuncs(parent3, PARENT3);
9266+
9267+#undef AuReadLockFunc
9268+#undef AuWriteLockFunc
9269+#undef AuRWLockFuncs
9270+
9271+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
dece6358
AM
9272+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
9273+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
1facf9fc 9274+
9275+/* ---------------------------------------------------------------------- */
9276+
9277+/* todo: memory barrier? */
9278+static inline unsigned int au_digen(struct dentry *d)
9279+{
9280+ return atomic_read(&au_di(d)->di_generation);
9281+}
9282+
9283+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
9284+{
9285+ hdentry->hd_dentry = NULL;
9286+}
9287+
5afbbe0d
AM
9288+static inline struct au_hdentry *au_hdentry(struct au_dinfo *di,
9289+ aufs_bindex_t bindex)
9290+{
9291+ return di->di_hdentry + bindex;
9292+}
9293+
1facf9fc 9294+static inline void au_hdput(struct au_hdentry *hd)
9295+{
4a4d8108
AM
9296+ if (hd)
9297+ dput(hd->hd_dentry);
1facf9fc 9298+}
9299+
5afbbe0d 9300+static inline aufs_bindex_t au_dbtop(struct dentry *dentry)
1facf9fc 9301+{
1308ab2a 9302+ DiMustAnyLock(dentry);
5afbbe0d 9303+ return au_di(dentry)->di_btop;
1facf9fc 9304+}
9305+
5afbbe0d 9306+static inline aufs_bindex_t au_dbbot(struct dentry *dentry)
1facf9fc 9307+{
1308ab2a 9308+ DiMustAnyLock(dentry);
5afbbe0d 9309+ return au_di(dentry)->di_bbot;
1facf9fc 9310+}
9311+
9312+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
9313+{
1308ab2a 9314+ DiMustAnyLock(dentry);
1facf9fc 9315+ return au_di(dentry)->di_bwh;
9316+}
9317+
9318+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
9319+{
1308ab2a 9320+ DiMustAnyLock(dentry);
1facf9fc 9321+ return au_di(dentry)->di_bdiropq;
9322+}
9323+
9324+/* todo: hard/soft set? */
5afbbe0d 9325+static inline void au_set_dbtop(struct dentry *dentry, aufs_bindex_t bindex)
1facf9fc 9326+{
1308ab2a 9327+ DiMustWriteLock(dentry);
5afbbe0d 9328+ au_di(dentry)->di_btop = bindex;
1facf9fc 9329+}
9330+
5afbbe0d 9331+static inline void au_set_dbbot(struct dentry *dentry, aufs_bindex_t bindex)
1facf9fc 9332+{
1308ab2a 9333+ DiMustWriteLock(dentry);
5afbbe0d 9334+ au_di(dentry)->di_bbot = bindex;
1facf9fc 9335+}
9336+
9337+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
9338+{
1308ab2a 9339+ DiMustWriteLock(dentry);
5afbbe0d 9340+ /* dbwh can be outside of btop - bbot range */
1facf9fc 9341+ au_di(dentry)->di_bwh = bindex;
9342+}
9343+
9344+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
9345+{
1308ab2a 9346+ DiMustWriteLock(dentry);
1facf9fc 9347+ au_di(dentry)->di_bdiropq = bindex;
9348+}
9349+
9350+/* ---------------------------------------------------------------------- */
9351+
4a4d8108 9352+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 9353+static inline void au_digen_dec(struct dentry *d)
9354+{
e49829fe 9355+ atomic_dec(&au_di(d)->di_generation);
1facf9fc 9356+}
9357+
4a4d8108 9358+static inline void au_hn_di_reinit(struct dentry *dentry)
1facf9fc 9359+{
9360+ dentry->d_fsdata = NULL;
9361+}
9362+#else
4a4d8108
AM
9363+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
9364+#endif /* CONFIG_AUFS_HNOTIFY */
1facf9fc 9365+
9366+#endif /* __KERNEL__ */
9367+#endif /* __AUFS_DENTRY_H__ */
7f207e10 9368diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
eca34b5c 9369--- /usr/share/empty/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
319657f6 9370+++ linux/fs/aufs/dinfo.c 2021-12-03 15:38:59.933313976 +0100
062440b3 9371@@ -0,0 +1,554 @@
cd7a4cd9 9372+// SPDX-License-Identifier: GPL-2.0
1facf9fc 9373+/*
6d176551 9374+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 9375+ *
9376+ * This program, aufs is free software; you can redistribute it and/or modify
9377+ * it under the terms of the GNU General Public License as published by
9378+ * the Free Software Foundation; either version 2 of the License, or
9379+ * (at your option) any later version.
dece6358
AM
9380+ *
9381+ * This program is distributed in the hope that it will be useful,
9382+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9383+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9384+ * GNU General Public License for more details.
9385+ *
9386+ * You should have received a copy of the GNU General Public License
523b37e3 9387+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 9388+ */
9389+
9390+/*
9391+ * dentry private data
9392+ */
9393+
9394+#include "aufs.h"
9395+
e49829fe 9396+void au_di_init_once(void *_dinfo)
4a4d8108 9397+{
e49829fe 9398+ struct au_dinfo *dinfo = _dinfo;
4a4d8108 9399+
e49829fe 9400+ au_rw_init(&dinfo->di_rwsem);
4a4d8108
AM
9401+}
9402+
027c5e7a 9403+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc)
1facf9fc 9404+{
9405+ struct au_dinfo *dinfo;
027c5e7a 9406+ int nbr, i;
1facf9fc 9407+
9408+ dinfo = au_cache_alloc_dinfo();
9409+ if (unlikely(!dinfo))
9410+ goto out;
9411+
5afbbe0d 9412+ nbr = au_sbbot(sb) + 1;
1facf9fc 9413+ if (nbr <= 0)
9414+ nbr = 1;
9415+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
027c5e7a
AM
9416+ if (dinfo->di_hdentry) {
9417+ au_rw_write_lock_nested(&dinfo->di_rwsem, lsc);
5afbbe0d
AM
9418+ dinfo->di_btop = -1;
9419+ dinfo->di_bbot = -1;
027c5e7a
AM
9420+ dinfo->di_bwh = -1;
9421+ dinfo->di_bdiropq = -1;
38d290e6 9422+ dinfo->di_tmpfile = 0;
027c5e7a
AM
9423+ for (i = 0; i < nbr; i++)
9424+ dinfo->di_hdentry[i].hd_id = -1;
9425+ goto out;
9426+ }
1facf9fc 9427+
1c60b727 9428+ au_cache_free_dinfo(dinfo);
027c5e7a
AM
9429+ dinfo = NULL;
9430+
4f0767ce 9431+out:
027c5e7a 9432+ return dinfo;
1facf9fc 9433+}
9434+
027c5e7a 9435+void au_di_free(struct au_dinfo *dinfo)
4a4d8108 9436+{
4a4d8108 9437+ struct au_hdentry *p;
5afbbe0d 9438+ aufs_bindex_t bbot, bindex;
4a4d8108
AM
9439+
9440+ /* dentry may not be revalidated */
5afbbe0d 9441+ bindex = dinfo->di_btop;
4a4d8108 9442+ if (bindex >= 0) {
5afbbe0d
AM
9443+ bbot = dinfo->di_bbot;
9444+ p = au_hdentry(dinfo, bindex);
9445+ while (bindex++ <= bbot)
4a4d8108
AM
9446+ au_hdput(p++);
9447+ }
9f237c51 9448+ au_kfree_try_rcu(dinfo->di_hdentry);
1c60b727 9449+ au_cache_free_dinfo(dinfo);
027c5e7a
AM
9450+}
9451+
9452+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b)
9453+{
9454+ struct au_hdentry *p;
9455+ aufs_bindex_t bi;
9456+
9457+ AuRwMustWriteLock(&a->di_rwsem);
9458+ AuRwMustWriteLock(&b->di_rwsem);
9459+
9460+#define DiSwap(v, name) \
9461+ do { \
9462+ v = a->di_##name; \
9463+ a->di_##name = b->di_##name; \
9464+ b->di_##name = v; \
9465+ } while (0)
9466+
9467+ DiSwap(p, hdentry);
5afbbe0d
AM
9468+ DiSwap(bi, btop);
9469+ DiSwap(bi, bbot);
027c5e7a
AM
9470+ DiSwap(bi, bwh);
9471+ DiSwap(bi, bdiropq);
9472+ /* smp_mb(); */
9473+
9474+#undef DiSwap
9475+}
9476+
9477+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src)
9478+{
9479+ AuRwMustWriteLock(&dst->di_rwsem);
9480+ AuRwMustWriteLock(&src->di_rwsem);
9481+
5afbbe0d
AM
9482+ dst->di_btop = src->di_btop;
9483+ dst->di_bbot = src->di_bbot;
027c5e7a
AM
9484+ dst->di_bwh = src->di_bwh;
9485+ dst->di_bdiropq = src->di_bdiropq;
9486+ /* smp_mb(); */
9487+}
9488+
9489+int au_di_init(struct dentry *dentry)
9490+{
9491+ int err;
9492+ struct super_block *sb;
9493+ struct au_dinfo *dinfo;
9494+
9495+ err = 0;
9496+ sb = dentry->d_sb;
9497+ dinfo = au_di_alloc(sb, AuLsc_DI_CHILD);
9498+ if (dinfo) {
9499+ atomic_set(&dinfo->di_generation, au_sigen(sb));
9500+ /* smp_mb(); */ /* atomic_set */
9501+ dentry->d_fsdata = dinfo;
9502+ } else
9503+ err = -ENOMEM;
9504+
9505+ return err;
9506+}
9507+
9508+void au_di_fin(struct dentry *dentry)
9509+{
9510+ struct au_dinfo *dinfo;
9511+
9512+ dinfo = au_di(dentry);
9513+ AuRwDestroy(&dinfo->di_rwsem);
9514+ au_di_free(dinfo);
4a4d8108
AM
9515+}
9516+
e2f27e51 9517+int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink)
1facf9fc 9518+{
9519+ int err, sz;
9520+ struct au_hdentry *hdp;
9521+
1308ab2a 9522+ AuRwMustWriteLock(&dinfo->di_rwsem);
9523+
1facf9fc 9524+ err = -ENOMEM;
5afbbe0d 9525+ sz = sizeof(*hdp) * (dinfo->di_bbot + 1);
1facf9fc 9526+ if (!sz)
9527+ sz = sizeof(*hdp);
e2f27e51
AM
9528+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS,
9529+ may_shrink);
1facf9fc 9530+ if (hdp) {
9531+ dinfo->di_hdentry = hdp;
9532+ err = 0;
9533+ }
9534+
9535+ return err;
9536+}
9537+
9538+/* ---------------------------------------------------------------------- */
9539+
9540+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
9541+{
9542+ switch (lsc) {
9543+ case AuLsc_DI_CHILD:
9544+ ii_write_lock_child(inode);
9545+ break;
9546+ case AuLsc_DI_CHILD2:
9547+ ii_write_lock_child2(inode);
9548+ break;
9549+ case AuLsc_DI_CHILD3:
9550+ ii_write_lock_child3(inode);
9551+ break;
9552+ case AuLsc_DI_PARENT:
9553+ ii_write_lock_parent(inode);
9554+ break;
9555+ case AuLsc_DI_PARENT2:
9556+ ii_write_lock_parent2(inode);
9557+ break;
9558+ case AuLsc_DI_PARENT3:
9559+ ii_write_lock_parent3(inode);
9560+ break;
9561+ default:
9562+ BUG();
9563+ }
9564+}
9565+
9566+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
9567+{
9568+ switch (lsc) {
9569+ case AuLsc_DI_CHILD:
9570+ ii_read_lock_child(inode);
9571+ break;
9572+ case AuLsc_DI_CHILD2:
9573+ ii_read_lock_child2(inode);
9574+ break;
9575+ case AuLsc_DI_CHILD3:
9576+ ii_read_lock_child3(inode);
9577+ break;
9578+ case AuLsc_DI_PARENT:
9579+ ii_read_lock_parent(inode);
9580+ break;
9581+ case AuLsc_DI_PARENT2:
9582+ ii_read_lock_parent2(inode);
9583+ break;
9584+ case AuLsc_DI_PARENT3:
9585+ ii_read_lock_parent3(inode);
9586+ break;
9587+ default:
9588+ BUG();
9589+ }
9590+}
9591+
9592+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
9593+{
5527c038
JR
9594+ struct inode *inode;
9595+
dece6358 9596+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
5527c038
JR
9597+ if (d_really_is_positive(d)) {
9598+ inode = d_inode(d);
1facf9fc 9599+ if (au_ftest_lock(flags, IW))
5527c038 9600+ do_ii_write_lock(inode, lsc);
1facf9fc 9601+ else if (au_ftest_lock(flags, IR))
5527c038 9602+ do_ii_read_lock(inode, lsc);
1facf9fc 9603+ }
9604+}
9605+
9606+void di_read_unlock(struct dentry *d, int flags)
9607+{
5527c038
JR
9608+ struct inode *inode;
9609+
9610+ if (d_really_is_positive(d)) {
9611+ inode = d_inode(d);
027c5e7a
AM
9612+ if (au_ftest_lock(flags, IW)) {
9613+ au_dbg_verify_dinode(d);
5527c038 9614+ ii_write_unlock(inode);
027c5e7a
AM
9615+ } else if (au_ftest_lock(flags, IR)) {
9616+ au_dbg_verify_dinode(d);
5527c038 9617+ ii_read_unlock(inode);
027c5e7a 9618+ }
1facf9fc 9619+ }
dece6358 9620+ au_rw_read_unlock(&au_di(d)->di_rwsem);
1facf9fc 9621+}
9622+
9623+void di_downgrade_lock(struct dentry *d, int flags)
9624+{
5527c038
JR
9625+ if (d_really_is_positive(d) && au_ftest_lock(flags, IR))
9626+ ii_downgrade_lock(d_inode(d));
dece6358 9627+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
1facf9fc 9628+}
9629+
9630+void di_write_lock(struct dentry *d, unsigned int lsc)
9631+{
dece6358 9632+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
5527c038
JR
9633+ if (d_really_is_positive(d))
9634+ do_ii_write_lock(d_inode(d), lsc);
1facf9fc 9635+}
9636+
9637+void di_write_unlock(struct dentry *d)
9638+{
027c5e7a 9639+ au_dbg_verify_dinode(d);
5527c038
JR
9640+ if (d_really_is_positive(d))
9641+ ii_write_unlock(d_inode(d));
dece6358 9642+ au_rw_write_unlock(&au_di(d)->di_rwsem);
1facf9fc 9643+}
9644+
9645+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
9646+{
9647+ AuDebugOn(d1 == d2
5527c038 9648+ || d_inode(d1) == d_inode(d2)
1facf9fc 9649+ || d1->d_sb != d2->d_sb);
9650+
521ced18
JR
9651+ if ((isdir && au_test_subdir(d1, d2))
9652+ || d1 < d2) {
1facf9fc 9653+ di_write_lock_child(d1);
9654+ di_write_lock_child2(d2);
9655+ } else {
1facf9fc 9656+ di_write_lock_child(d2);
9657+ di_write_lock_child2(d1);
9658+ }
9659+}
9660+
9661+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
9662+{
9663+ AuDebugOn(d1 == d2
5527c038 9664+ || d_inode(d1) == d_inode(d2)
1facf9fc 9665+ || d1->d_sb != d2->d_sb);
9666+
521ced18
JR
9667+ if ((isdir && au_test_subdir(d1, d2))
9668+ || d1 < d2) {
1facf9fc 9669+ di_write_lock_parent(d1);
9670+ di_write_lock_parent2(d2);
9671+ } else {
1facf9fc 9672+ di_write_lock_parent(d2);
9673+ di_write_lock_parent2(d1);
9674+ }
9675+}
9676+
9677+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
9678+{
9679+ di_write_unlock(d1);
5527c038 9680+ if (d_inode(d1) == d_inode(d2))
dece6358 9681+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
1facf9fc 9682+ else
9683+ di_write_unlock(d2);
9684+}
9685+
9686+/* ---------------------------------------------------------------------- */
9687+
9688+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
9689+{
9690+ struct dentry *d;
9691+
1308ab2a 9692+ DiMustAnyLock(dentry);
9693+
5afbbe0d 9694+ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry))
1facf9fc 9695+ return NULL;
9696+ AuDebugOn(bindex < 0);
5afbbe0d 9697+ d = au_hdentry(au_di(dentry), bindex)->hd_dentry;
c1595e42 9698+ AuDebugOn(d && au_dcount(d) <= 0);
1facf9fc 9699+ return d;
9700+}
9701+
2cbb1c4b
JR
9702+/*
9703+ * extended version of au_h_dptr().
38d290e6
JR
9704+ * returns a hashed and positive (or linkable) h_dentry in bindex, NULL, or
9705+ * error.
2cbb1c4b
JR
9706+ */
9707+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex)
9708+{
9709+ struct dentry *h_dentry;
9710+ struct inode *inode, *h_inode;
9711+
5527c038 9712+ AuDebugOn(d_really_is_negative(dentry));
2cbb1c4b
JR
9713+
9714+ h_dentry = NULL;
5afbbe0d
AM
9715+ if (au_dbtop(dentry) <= bindex
9716+ && bindex <= au_dbbot(dentry))
2cbb1c4b 9717+ h_dentry = au_h_dptr(dentry, bindex);
38d290e6 9718+ if (h_dentry && !au_d_linkable(h_dentry)) {
2cbb1c4b
JR
9719+ dget(h_dentry);
9720+ goto out; /* success */
9721+ }
9722+
5527c038 9723+ inode = d_inode(dentry);
5afbbe0d
AM
9724+ AuDebugOn(bindex < au_ibtop(inode));
9725+ AuDebugOn(au_ibbot(inode) < bindex);
2cbb1c4b
JR
9726+ h_inode = au_h_iptr(inode, bindex);
9727+ h_dentry = d_find_alias(h_inode);
9728+ if (h_dentry) {
9729+ if (!IS_ERR(h_dentry)) {
38d290e6 9730+ if (!au_d_linkable(h_dentry))
2cbb1c4b
JR
9731+ goto out; /* success */
9732+ dput(h_dentry);
9733+ } else
9734+ goto out;
9735+ }
9736+
9737+ if (au_opt_test(au_mntflags(dentry->d_sb), PLINK)) {
9738+ h_dentry = au_plink_lkup(inode, bindex);
9739+ AuDebugOn(!h_dentry);
9740+ if (!IS_ERR(h_dentry)) {
9741+ if (!au_d_hashed_positive(h_dentry))
9742+ goto out; /* success */
9743+ dput(h_dentry);
9744+ h_dentry = NULL;
9745+ }
9746+ }
9747+
9748+out:
9749+ AuDbgDentry(h_dentry);
9750+ return h_dentry;
9751+}
9752+
1facf9fc 9753+aufs_bindex_t au_dbtail(struct dentry *dentry)
9754+{
5afbbe0d 9755+ aufs_bindex_t bbot, bwh;
1facf9fc 9756+
5afbbe0d
AM
9757+ bbot = au_dbbot(dentry);
9758+ if (0 <= bbot) {
1facf9fc 9759+ bwh = au_dbwh(dentry);
9760+ if (!bwh)
9761+ return bwh;
5afbbe0d 9762+ if (0 < bwh && bwh < bbot)
1facf9fc 9763+ return bwh - 1;
9764+ }
5afbbe0d 9765+ return bbot;
1facf9fc 9766+}
9767+
9768+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
9769+{
5afbbe0d 9770+ aufs_bindex_t bbot, bopq;
1facf9fc 9771+
5afbbe0d
AM
9772+ bbot = au_dbtail(dentry);
9773+ if (0 <= bbot) {
1facf9fc 9774+ bopq = au_dbdiropq(dentry);
5afbbe0d
AM
9775+ if (0 <= bopq && bopq < bbot)
9776+ bbot = bopq;
1facf9fc 9777+ }
5afbbe0d 9778+ return bbot;
1facf9fc 9779+}
9780+
9781+/* ---------------------------------------------------------------------- */
9782+
9783+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
9784+ struct dentry *h_dentry)
9785+{
5afbbe0d
AM
9786+ struct au_dinfo *dinfo;
9787+ struct au_hdentry *hd;
027c5e7a 9788+ struct au_branch *br;
1facf9fc 9789+
1308ab2a 9790+ DiMustWriteLock(dentry);
9791+
5afbbe0d
AM
9792+ dinfo = au_di(dentry);
9793+ hd = au_hdentry(dinfo, bindex);
4a4d8108 9794+ au_hdput(hd);
1facf9fc 9795+ hd->hd_dentry = h_dentry;
027c5e7a
AM
9796+ if (h_dentry) {
9797+ br = au_sbr(dentry->d_sb, bindex);
9798+ hd->hd_id = br->br_id;
9799+ }
9800+}
9801+
9802+int au_dbrange_test(struct dentry *dentry)
9803+{
9804+ int err;
5afbbe0d 9805+ aufs_bindex_t btop, bbot;
027c5e7a
AM
9806+
9807+ err = 0;
5afbbe0d
AM
9808+ btop = au_dbtop(dentry);
9809+ bbot = au_dbbot(dentry);
9810+ if (btop >= 0)
9811+ AuDebugOn(bbot < 0 && btop > bbot);
027c5e7a
AM
9812+ else {
9813+ err = -EIO;
5afbbe0d 9814+ AuDebugOn(bbot >= 0);
027c5e7a
AM
9815+ }
9816+
9817+ return err;
9818+}
9819+
9820+int au_digen_test(struct dentry *dentry, unsigned int sigen)
9821+{
9822+ int err;
9823+
9824+ err = 0;
9825+ if (unlikely(au_digen(dentry) != sigen
5527c038 9826+ || au_iigen_test(d_inode(dentry), sigen)))
027c5e7a
AM
9827+ err = -EIO;
9828+
9829+ return err;
1facf9fc 9830+}
9831+
9832+void au_update_digen(struct dentry *dentry)
9833+{
9834+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
9835+ /* smp_mb(); */ /* atomic_set */
9836+}
9837+
9838+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
9839+{
9840+ struct au_dinfo *dinfo;
9841+ struct dentry *h_d;
4a4d8108 9842+ struct au_hdentry *hdp;
5afbbe0d 9843+ aufs_bindex_t bindex, bbot;
1facf9fc 9844+
1308ab2a 9845+ DiMustWriteLock(dentry);
9846+
1facf9fc 9847+ dinfo = au_di(dentry);
5afbbe0d 9848+ if (!dinfo || dinfo->di_btop < 0)
1facf9fc 9849+ return;
9850+
9851+ if (do_put_zero) {
5afbbe0d
AM
9852+ bbot = dinfo->di_bbot;
9853+ bindex = dinfo->di_btop;
9854+ hdp = au_hdentry(dinfo, bindex);
9855+ for (; bindex <= bbot; bindex++, hdp++) {
9856+ h_d = hdp->hd_dentry;
5527c038 9857+ if (h_d && d_is_negative(h_d))
1facf9fc 9858+ au_set_h_dptr(dentry, bindex, NULL);
9859+ }
9860+ }
9861+
5afbbe0d
AM
9862+ dinfo->di_btop = 0;
9863+ hdp = au_hdentry(dinfo, dinfo->di_btop);
9864+ for (; dinfo->di_btop <= dinfo->di_bbot; dinfo->di_btop++, hdp++)
9865+ if (hdp->hd_dentry)
1facf9fc 9866+ break;
5afbbe0d
AM
9867+ if (dinfo->di_btop > dinfo->di_bbot) {
9868+ dinfo->di_btop = -1;
9869+ dinfo->di_bbot = -1;
1facf9fc 9870+ return;
9871+ }
9872+
5afbbe0d
AM
9873+ hdp = au_hdentry(dinfo, dinfo->di_bbot);
9874+ for (; dinfo->di_bbot >= 0; dinfo->di_bbot--, hdp--)
9875+ if (hdp->hd_dentry)
1facf9fc 9876+ break;
5afbbe0d 9877+ AuDebugOn(dinfo->di_btop > dinfo->di_bbot || dinfo->di_bbot < 0);
1facf9fc 9878+}
9879+
5afbbe0d 9880+void au_update_dbtop(struct dentry *dentry)
1facf9fc 9881+{
5afbbe0d 9882+ aufs_bindex_t bindex, bbot;
1facf9fc 9883+ struct dentry *h_dentry;
9884+
5afbbe0d
AM
9885+ bbot = au_dbbot(dentry);
9886+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) {
1facf9fc 9887+ h_dentry = au_h_dptr(dentry, bindex);
9888+ if (!h_dentry)
9889+ continue;
5527c038 9890+ if (d_is_positive(h_dentry)) {
5afbbe0d 9891+ au_set_dbtop(dentry, bindex);
1facf9fc 9892+ return;
9893+ }
9894+ au_set_h_dptr(dentry, bindex, NULL);
9895+ }
9896+}
9897+
5afbbe0d 9898+void au_update_dbbot(struct dentry *dentry)
1facf9fc 9899+{
5afbbe0d 9900+ aufs_bindex_t bindex, btop;
1facf9fc 9901+ struct dentry *h_dentry;
9902+
5afbbe0d
AM
9903+ btop = au_dbtop(dentry);
9904+ for (bindex = au_dbbot(dentry); bindex >= btop; bindex--) {
1facf9fc 9905+ h_dentry = au_h_dptr(dentry, bindex);
9906+ if (!h_dentry)
9907+ continue;
5527c038 9908+ if (d_is_positive(h_dentry)) {
5afbbe0d 9909+ au_set_dbbot(dentry, bindex);
1facf9fc 9910+ return;
9911+ }
9912+ au_set_h_dptr(dentry, bindex, NULL);
9913+ }
9914+}
9915+
9916+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
9917+{
5afbbe0d 9918+ aufs_bindex_t bindex, bbot;
1facf9fc 9919+
5afbbe0d
AM
9920+ bbot = au_dbbot(dentry);
9921+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++)
1facf9fc 9922+ if (au_h_dptr(dentry, bindex) == h_dentry)
9923+ return bindex;
9924+ return -1;
9925+}
7f207e10 9926diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
eca34b5c 9927--- /usr/share/empty/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
319657f6 9928+++ linux/fs/aufs/dir.c 2021-12-03 15:40:58.233313963 +0100
0b2a12c6 9929@@ -0,0 +1,765 @@
cd7a4cd9 9930+// SPDX-License-Identifier: GPL-2.0
1facf9fc 9931+/*
6d176551 9932+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 9933+ *
9934+ * This program, aufs is free software; you can redistribute it and/or modify
9935+ * it under the terms of the GNU General Public License as published by
9936+ * the Free Software Foundation; either version 2 of the License, or
9937+ * (at your option) any later version.
dece6358
AM
9938+ *
9939+ * This program is distributed in the hope that it will be useful,
9940+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9941+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9942+ * GNU General Public License for more details.
9943+ *
9944+ * You should have received a copy of the GNU General Public License
523b37e3 9945+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 9946+ */
9947+
9948+/*
9949+ * directory operations
9950+ */
9951+
9952+#include <linux/fs_stack.h>
eca801bf 9953+#include <linux/iversion.h>
1facf9fc 9954+#include "aufs.h"
9955+
9956+void au_add_nlink(struct inode *dir, struct inode *h_dir)
9957+{
9dbd164d
AM
9958+ unsigned int nlink;
9959+
1facf9fc 9960+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
9961+
9dbd164d
AM
9962+ nlink = dir->i_nlink;
9963+ nlink += h_dir->i_nlink - 2;
1facf9fc 9964+ if (h_dir->i_nlink < 2)
9dbd164d 9965+ nlink += 2;
f6b6e03d 9966+ smp_mb(); /* for i_nlink */
7eafdf33 9967+ /* 0 can happen in revaliding */
92d182d2 9968+ set_nlink(dir, nlink);
1facf9fc 9969+}
9970+
9971+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
9972+{
9dbd164d
AM
9973+ unsigned int nlink;
9974+
1facf9fc 9975+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
9976+
9dbd164d
AM
9977+ nlink = dir->i_nlink;
9978+ nlink -= h_dir->i_nlink - 2;
1facf9fc 9979+ if (h_dir->i_nlink < 2)
9dbd164d 9980+ nlink -= 2;
f6b6e03d 9981+ smp_mb(); /* for i_nlink */
92d182d2 9982+ /* nlink == 0 means the branch-fs is broken */
9dbd164d 9983+ set_nlink(dir, nlink);
1facf9fc 9984+}
9985+
1308ab2a 9986+loff_t au_dir_size(struct file *file, struct dentry *dentry)
9987+{
9988+ loff_t sz;
5afbbe0d 9989+ aufs_bindex_t bindex, bbot;
1308ab2a 9990+ struct file *h_file;
9991+ struct dentry *h_dentry;
9992+
9993+ sz = 0;
9994+ if (file) {
2000de60 9995+ AuDebugOn(!d_is_dir(file->f_path.dentry));
1308ab2a 9996+
5afbbe0d
AM
9997+ bbot = au_fbbot_dir(file);
9998+ for (bindex = au_fbtop(file);
9999+ bindex <= bbot && sz < KMALLOC_MAX_SIZE;
1308ab2a 10000+ bindex++) {
4a4d8108 10001+ h_file = au_hf_dir(file, bindex);
c06a8ce3
AM
10002+ if (h_file && file_inode(h_file))
10003+ sz += vfsub_f_size_read(h_file);
1308ab2a 10004+ }
10005+ } else {
10006+ AuDebugOn(!dentry);
2000de60 10007+ AuDebugOn(!d_is_dir(dentry));
1308ab2a 10008+
5afbbe0d
AM
10009+ bbot = au_dbtaildir(dentry);
10010+ for (bindex = au_dbtop(dentry);
10011+ bindex <= bbot && sz < KMALLOC_MAX_SIZE;
1308ab2a 10012+ bindex++) {
10013+ h_dentry = au_h_dptr(dentry, bindex);
5527c038
JR
10014+ if (h_dentry && d_is_positive(h_dentry))
10015+ sz += i_size_read(d_inode(h_dentry));
1308ab2a 10016+ }
10017+ }
10018+ if (sz < KMALLOC_MAX_SIZE)
10019+ sz = roundup_pow_of_two(sz);
10020+ if (sz > KMALLOC_MAX_SIZE)
10021+ sz = KMALLOC_MAX_SIZE;
10022+ else if (sz < NAME_MAX) {
10023+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
10024+ sz = AUFS_RDBLK_DEF;
10025+ }
10026+ return sz;
10027+}
10028+
b912730e
AM
10029+struct au_dir_ts_arg {
10030+ struct dentry *dentry;
10031+ aufs_bindex_t brid;
10032+};
10033+
10034+static void au_do_dir_ts(void *arg)
10035+{
10036+ struct au_dir_ts_arg *a = arg;
10037+ struct au_dtime dt;
10038+ struct path h_path;
10039+ struct inode *dir, *h_dir;
10040+ struct super_block *sb;
10041+ struct au_branch *br;
10042+ struct au_hinode *hdir;
10043+ int err;
5afbbe0d 10044+ aufs_bindex_t btop, bindex;
b912730e
AM
10045+
10046+ sb = a->dentry->d_sb;
5527c038 10047+ if (d_really_is_negative(a->dentry))
b912730e 10048+ goto out;
5527c038 10049+ /* no dir->i_mutex lock */
b95c5147
AM
10050+ aufs_read_lock(a->dentry, AuLock_DW); /* noflush */
10051+
5527c038 10052+ dir = d_inode(a->dentry);
5afbbe0d 10053+ btop = au_ibtop(dir);
b912730e 10054+ bindex = au_br_index(sb, a->brid);
5afbbe0d 10055+ if (bindex < btop)
b912730e
AM
10056+ goto out_unlock;
10057+
10058+ br = au_sbr(sb, bindex);
10059+ h_path.dentry = au_h_dptr(a->dentry, bindex);
10060+ if (!h_path.dentry)
10061+ goto out_unlock;
10062+ h_path.mnt = au_br_mnt(br);
10063+ au_dtime_store(&dt, a->dentry, &h_path);
10064+
5afbbe0d 10065+ br = au_sbr(sb, btop);
b912730e
AM
10066+ if (!au_br_writable(br->br_perm))
10067+ goto out_unlock;
5afbbe0d 10068+ h_path.dentry = au_h_dptr(a->dentry, btop);
b912730e
AM
10069+ h_path.mnt = au_br_mnt(br);
10070+ err = vfsub_mnt_want_write(h_path.mnt);
10071+ if (err)
10072+ goto out_unlock;
5afbbe0d
AM
10073+ hdir = au_hi(dir, btop);
10074+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
10075+ h_dir = au_h_iptr(dir, btop);
b912730e 10076+ if (h_dir->i_nlink
cd7a4cd9 10077+ && timespec64_compare(&h_dir->i_mtime, &dt.dt_mtime) < 0) {
b912730e
AM
10078+ dt.dt_h_path = h_path;
10079+ au_dtime_revert(&dt);
10080+ }
5afbbe0d 10081+ au_hn_inode_unlock(hdir);
b912730e
AM
10082+ vfsub_mnt_drop_write(h_path.mnt);
10083+ au_cpup_attr_timesizes(dir);
10084+
10085+out_unlock:
10086+ aufs_read_unlock(a->dentry, AuLock_DW);
10087+out:
10088+ dput(a->dentry);
10089+ au_nwt_done(&au_sbi(sb)->si_nowait);
9f237c51 10090+ au_kfree_try_rcu(arg);
b912730e
AM
10091+}
10092+
10093+void au_dir_ts(struct inode *dir, aufs_bindex_t bindex)
10094+{
10095+ int perm, wkq_err;
5afbbe0d 10096+ aufs_bindex_t btop;
b912730e
AM
10097+ struct au_dir_ts_arg *arg;
10098+ struct dentry *dentry;
10099+ struct super_block *sb;
10100+
10101+ IMustLock(dir);
10102+
10103+ dentry = d_find_any_alias(dir);
10104+ AuDebugOn(!dentry);
10105+ sb = dentry->d_sb;
5afbbe0d
AM
10106+ btop = au_ibtop(dir);
10107+ if (btop == bindex) {
b912730e
AM
10108+ au_cpup_attr_timesizes(dir);
10109+ goto out;
10110+ }
10111+
5afbbe0d 10112+ perm = au_sbr_perm(sb, btop);
b912730e
AM
10113+ if (!au_br_writable(perm))
10114+ goto out;
10115+
10116+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
10117+ if (!arg)
10118+ goto out;
10119+
10120+ arg->dentry = dget(dentry); /* will be dput-ted by au_do_dir_ts() */
10121+ arg->brid = au_sbr_id(sb, bindex);
10122+ wkq_err = au_wkq_nowait(au_do_dir_ts, arg, sb, /*flags*/0);
10123+ if (unlikely(wkq_err)) {
10124+ pr_err("wkq %d\n", wkq_err);
10125+ dput(dentry);
9f237c51 10126+ au_kfree_try_rcu(arg);
b912730e
AM
10127+ }
10128+
10129+out:
10130+ dput(dentry);
10131+}
10132+
1facf9fc 10133+/* ---------------------------------------------------------------------- */
10134+
10135+static int reopen_dir(struct file *file)
10136+{
10137+ int err;
10138+ unsigned int flags;
5afbbe0d 10139+ aufs_bindex_t bindex, btail, btop;
1facf9fc 10140+ struct dentry *dentry, *h_dentry;
10141+ struct file *h_file;
10142+
10143+ /* open all lower dirs */
2000de60 10144+ dentry = file->f_path.dentry;
5afbbe0d
AM
10145+ btop = au_dbtop(dentry);
10146+ for (bindex = au_fbtop(file); bindex < btop; bindex++)
1facf9fc 10147+ au_set_h_fptr(file, bindex, NULL);
5afbbe0d 10148+ au_set_fbtop(file, btop);
1facf9fc 10149+
10150+ btail = au_dbtaildir(dentry);
5afbbe0d 10151+ for (bindex = au_fbbot_dir(file); btail < bindex; bindex--)
1facf9fc 10152+ au_set_h_fptr(file, bindex, NULL);
5afbbe0d 10153+ au_set_fbbot_dir(file, btail);
1facf9fc 10154+
4a4d8108 10155+ flags = vfsub_file_flags(file);
5afbbe0d 10156+ for (bindex = btop; bindex <= btail; bindex++) {
1facf9fc 10157+ h_dentry = au_h_dptr(dentry, bindex);
10158+ if (!h_dentry)
10159+ continue;
4a4d8108 10160+ h_file = au_hf_dir(file, bindex);
1facf9fc 10161+ if (h_file)
10162+ continue;
10163+
392086de 10164+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0);
1facf9fc 10165+ err = PTR_ERR(h_file);
10166+ if (IS_ERR(h_file))
10167+ goto out; /* close all? */
10168+ au_set_h_fptr(file, bindex, h_file);
10169+ }
10170+ au_update_figen(file);
10171+ /* todo: necessary? */
10172+ /* file->f_ra = h_file->f_ra; */
10173+ err = 0;
10174+
4f0767ce 10175+out:
1facf9fc 10176+ return err;
10177+}
10178+
b912730e 10179+static int do_open_dir(struct file *file, int flags, struct file *h_file)
1facf9fc 10180+{
10181+ int err;
10182+ aufs_bindex_t bindex, btail;
10183+ struct dentry *dentry, *h_dentry;
8cdd5066 10184+ struct vfsmount *mnt;
1facf9fc 10185+
1308ab2a 10186+ FiMustWriteLock(file);
b912730e 10187+ AuDebugOn(h_file);
1308ab2a 10188+
523b37e3 10189+ err = 0;
8cdd5066 10190+ mnt = file->f_path.mnt;
2000de60 10191+ dentry = file->f_path.dentry;
be118d29 10192+ file->f_version = inode_query_iversion(d_inode(dentry));
5afbbe0d
AM
10193+ bindex = au_dbtop(dentry);
10194+ au_set_fbtop(file, bindex);
1facf9fc 10195+ btail = au_dbtaildir(dentry);
5afbbe0d 10196+ au_set_fbbot_dir(file, btail);
1facf9fc 10197+ for (; !err && bindex <= btail; bindex++) {
10198+ h_dentry = au_h_dptr(dentry, bindex);
10199+ if (!h_dentry)
10200+ continue;
10201+
8cdd5066
JR
10202+ err = vfsub_test_mntns(mnt, h_dentry->d_sb);
10203+ if (unlikely(err))
10204+ break;
392086de 10205+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0);
1facf9fc 10206+ if (IS_ERR(h_file)) {
10207+ err = PTR_ERR(h_file);
10208+ break;
10209+ }
10210+ au_set_h_fptr(file, bindex, h_file);
10211+ }
10212+ au_update_figen(file);
10213+ /* todo: necessary? */
10214+ /* file->f_ra = h_file->f_ra; */
10215+ if (!err)
10216+ return 0; /* success */
10217+
10218+ /* close all */
5afbbe0d 10219+ for (bindex = au_fbtop(file); bindex <= btail; bindex++)
1facf9fc 10220+ au_set_h_fptr(file, bindex, NULL);
5afbbe0d
AM
10221+ au_set_fbtop(file, -1);
10222+ au_set_fbbot_dir(file, -1);
4a4d8108 10223+
1facf9fc 10224+ return err;
10225+}
10226+
10227+static int aufs_open_dir(struct inode *inode __maybe_unused,
10228+ struct file *file)
10229+{
4a4d8108
AM
10230+ int err;
10231+ struct super_block *sb;
10232+ struct au_fidir *fidir;
10233+
10234+ err = -ENOMEM;
2000de60 10235+ sb = file->f_path.dentry->d_sb;
4a4d8108 10236+ si_read_lock(sb, AuLock_FLUSH);
e49829fe 10237+ fidir = au_fidir_alloc(sb);
4a4d8108 10238+ if (fidir) {
b912730e
AM
10239+ struct au_do_open_args args = {
10240+ .open = do_open_dir,
10241+ .fidir = fidir
10242+ };
10243+ err = au_do_open(file, &args);
4a4d8108 10244+ if (unlikely(err))
9f237c51 10245+ au_kfree_rcu(fidir);
4a4d8108
AM
10246+ }
10247+ si_read_unlock(sb);
10248+ return err;
1facf9fc 10249+}
10250+
10251+static int aufs_release_dir(struct inode *inode __maybe_unused,
10252+ struct file *file)
10253+{
10254+ struct au_vdir *vdir_cache;
4a4d8108
AM
10255+ struct au_finfo *finfo;
10256+ struct au_fidir *fidir;
f0c0a007 10257+ struct au_hfile *hf;
5afbbe0d 10258+ aufs_bindex_t bindex, bbot;
1facf9fc 10259+
4a4d8108
AM
10260+ finfo = au_fi(file);
10261+ fidir = finfo->fi_hdir;
10262+ if (fidir) {
8b6a4947
AM
10263+ au_hbl_del(&finfo->fi_hlist,
10264+ &au_sbi(file->f_path.dentry->d_sb)->si_files);
4a4d8108
AM
10265+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */
10266+ if (vdir_cache)
1c60b727 10267+ au_vdir_free(vdir_cache);
4a4d8108
AM
10268+
10269+ bindex = finfo->fi_btop;
10270+ if (bindex >= 0) {
f0c0a007 10271+ hf = fidir->fd_hfile + bindex;
4a4d8108
AM
10272+ /*
10273+ * calls fput() instead of filp_close(),
10274+ * since no dnotify or lock for the lower file.
10275+ */
5afbbe0d 10276+ bbot = fidir->fd_bbot;
f0c0a007
AM
10277+ for (; bindex <= bbot; bindex++, hf++)
10278+ if (hf->hf_file)
1c60b727 10279+ au_hfput(hf, /*execed*/0);
4a4d8108 10280+ }
9f237c51 10281+ au_kfree_rcu(fidir);
4a4d8108 10282+ finfo->fi_hdir = NULL;
1facf9fc 10283+ }
1c60b727 10284+ au_finfo_fin(file);
1facf9fc 10285+ return 0;
10286+}
10287+
10288+/* ---------------------------------------------------------------------- */
10289+
4a4d8108
AM
10290+static int au_do_flush_dir(struct file *file, fl_owner_t id)
10291+{
10292+ int err;
5afbbe0d 10293+ aufs_bindex_t bindex, bbot;
4a4d8108
AM
10294+ struct file *h_file;
10295+
10296+ err = 0;
5afbbe0d
AM
10297+ bbot = au_fbbot_dir(file);
10298+ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) {
4a4d8108
AM
10299+ h_file = au_hf_dir(file, bindex);
10300+ if (h_file)
10301+ err = vfsub_flush(h_file, id);
10302+ }
10303+ return err;
10304+}
10305+
10306+static int aufs_flush_dir(struct file *file, fl_owner_t id)
10307+{
10308+ return au_do_flush(file, id, au_do_flush_dir);
10309+}
10310+
10311+/* ---------------------------------------------------------------------- */
10312+
1facf9fc 10313+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
10314+{
10315+ int err;
5afbbe0d 10316+ aufs_bindex_t bbot, bindex;
1facf9fc 10317+ struct inode *inode;
10318+ struct super_block *sb;
10319+
10320+ err = 0;
10321+ sb = dentry->d_sb;
5527c038 10322+ inode = d_inode(dentry);
1facf9fc 10323+ IMustLock(inode);
5afbbe0d
AM
10324+ bbot = au_dbbot(dentry);
10325+ for (bindex = au_dbtop(dentry); !err && bindex <= bbot; bindex++) {
1facf9fc 10326+ struct path h_path;
1facf9fc 10327+
10328+ if (au_test_ro(sb, bindex, inode))
10329+ continue;
10330+ h_path.dentry = au_h_dptr(dentry, bindex);
10331+ if (!h_path.dentry)
10332+ continue;
1facf9fc 10333+
1facf9fc 10334+ h_path.mnt = au_sbr_mnt(sb, bindex);
53392da6 10335+ err = vfsub_fsync(NULL, &h_path, datasync);
1facf9fc 10336+ }
10337+
10338+ return err;
10339+}
10340+
10341+static int au_do_fsync_dir(struct file *file, int datasync)
10342+{
10343+ int err;
5afbbe0d 10344+ aufs_bindex_t bbot, bindex;
1facf9fc 10345+ struct file *h_file;
10346+ struct super_block *sb;
10347+ struct inode *inode;
1facf9fc 10348+
521ced18 10349+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0);
1facf9fc 10350+ if (unlikely(err))
10351+ goto out;
10352+
c06a8ce3 10353+ inode = file_inode(file);
b912730e 10354+ sb = inode->i_sb;
5afbbe0d
AM
10355+ bbot = au_fbbot_dir(file);
10356+ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) {
4a4d8108 10357+ h_file = au_hf_dir(file, bindex);
1facf9fc 10358+ if (!h_file || au_test_ro(sb, bindex, inode))
10359+ continue;
10360+
53392da6 10361+ err = vfsub_fsync(h_file, &h_file->f_path, datasync);
1facf9fc 10362+ }
10363+
4f0767ce 10364+out:
1facf9fc 10365+ return err;
10366+}
10367+
10368+/*
10369+ * @file may be NULL
10370+ */
1e00d052
AM
10371+static int aufs_fsync_dir(struct file *file, loff_t start, loff_t end,
10372+ int datasync)
1facf9fc 10373+{
10374+ int err;
b752ccd1 10375+ struct dentry *dentry;
5527c038 10376+ struct inode *inode;
1facf9fc 10377+ struct super_block *sb;
1facf9fc 10378+
10379+ err = 0;
2000de60 10380+ dentry = file->f_path.dentry;
5527c038 10381+ inode = d_inode(dentry);
febd17d6 10382+ inode_lock(inode);
1facf9fc 10383+ sb = dentry->d_sb;
10384+ si_noflush_read_lock(sb);
10385+ if (file)
10386+ err = au_do_fsync_dir(file, datasync);
10387+ else {
10388+ di_write_lock_child(dentry);
10389+ err = au_do_fsync_dir_no_file(dentry, datasync);
10390+ }
5527c038 10391+ au_cpup_attr_timesizes(inode);
1facf9fc 10392+ di_write_unlock(dentry);
10393+ if (file)
10394+ fi_write_unlock(file);
10395+
10396+ si_read_unlock(sb);
febd17d6 10397+ inode_unlock(inode);
1facf9fc 10398+ return err;
10399+}
10400+
10401+/* ---------------------------------------------------------------------- */
10402+
5afbbe0d 10403+static int aufs_iterate_shared(struct file *file, struct dir_context *ctx)
1facf9fc 10404+{
10405+ int err;
10406+ struct dentry *dentry;
9dbd164d 10407+ struct inode *inode, *h_inode;
1facf9fc 10408+ struct super_block *sb;
10409+
062440b3 10410+ AuDbg("%pD, ctx{%ps, %llu}\n", file, ctx->actor, ctx->pos);
392086de 10411+
2000de60 10412+ dentry = file->f_path.dentry;
5527c038 10413+ inode = d_inode(dentry);
1facf9fc 10414+ IMustLock(inode);
10415+
10416+ sb = dentry->d_sb;
10417+ si_read_lock(sb, AuLock_FLUSH);
521ced18 10418+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0);
1facf9fc 10419+ if (unlikely(err))
10420+ goto out;
027c5e7a
AM
10421+ err = au_alive_dir(dentry);
10422+ if (!err)
10423+ err = au_vdir_init(file);
1facf9fc 10424+ di_downgrade_lock(dentry, AuLock_IR);
10425+ if (unlikely(err))
10426+ goto out_unlock;
10427+
5afbbe0d 10428+ h_inode = au_h_iptr(inode, au_ibtop(inode));
b752ccd1 10429+ if (!au_test_nfsd()) {
392086de 10430+ err = au_vdir_fill_de(file, ctx);
9dbd164d 10431+ fsstack_copy_attr_atime(inode, h_inode);
1facf9fc 10432+ } else {
10433+ /*
10434+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
10435+ * encode_fh() and others.
10436+ */
9dbd164d 10437+ atomic_inc(&h_inode->i_count);
1facf9fc 10438+ di_read_unlock(dentry, AuLock_IR);
10439+ si_read_unlock(sb);
392086de 10440+ err = au_vdir_fill_de(file, ctx);
1facf9fc 10441+ fsstack_copy_attr_atime(inode, h_inode);
10442+ fi_write_unlock(file);
9dbd164d 10443+ iput(h_inode);
1facf9fc 10444+
10445+ AuTraceErr(err);
10446+ return err;
10447+ }
10448+
4f0767ce 10449+out_unlock:
1facf9fc 10450+ di_read_unlock(dentry, AuLock_IR);
10451+ fi_write_unlock(file);
4f0767ce 10452+out:
1facf9fc 10453+ si_read_unlock(sb);
10454+ return err;
10455+}
10456+
10457+/* ---------------------------------------------------------------------- */
10458+
10459+#define AuTestEmpty_WHONLY 1
dece6358
AM
10460+#define AuTestEmpty_CALLED (1 << 1)
10461+#define AuTestEmpty_SHWH (1 << 2)
1facf9fc 10462+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
7f207e10
AM
10463+#define au_fset_testempty(flags, name) \
10464+ do { (flags) |= AuTestEmpty_##name; } while (0)
10465+#define au_fclr_testempty(flags, name) \
10466+ do { (flags) &= ~AuTestEmpty_##name; } while (0)
1facf9fc 10467+
dece6358
AM
10468+#ifndef CONFIG_AUFS_SHWH
10469+#undef AuTestEmpty_SHWH
10470+#define AuTestEmpty_SHWH 0
10471+#endif
10472+
1facf9fc 10473+struct test_empty_arg {
392086de 10474+ struct dir_context ctx;
1308ab2a 10475+ struct au_nhash *whlist;
1facf9fc 10476+ unsigned int flags;
10477+ int err;
10478+ aufs_bindex_t bindex;
10479+};
10480+
392086de
AM
10481+static int test_empty_cb(struct dir_context *ctx, const char *__name,
10482+ int namelen, loff_t offset __maybe_unused, u64 ino,
dece6358 10483+ unsigned int d_type)
1facf9fc 10484+{
392086de
AM
10485+ struct test_empty_arg *arg = container_of(ctx, struct test_empty_arg,
10486+ ctx);
1facf9fc 10487+ char *name = (void *)__name;
10488+
10489+ arg->err = 0;
10490+ au_fset_testempty(arg->flags, CALLED);
10491+ /* smp_mb(); */
10492+ if (name[0] == '.'
10493+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
10494+ goto out; /* success */
10495+
10496+ if (namelen <= AUFS_WH_PFX_LEN
10497+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
10498+ if (au_ftest_testempty(arg->flags, WHONLY)
1308ab2a 10499+ && !au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 10500+ arg->err = -ENOTEMPTY;
10501+ goto out;
10502+ }
10503+
10504+ name += AUFS_WH_PFX_LEN;
10505+ namelen -= AUFS_WH_PFX_LEN;
1308ab2a 10506+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 10507+ arg->err = au_nhash_append_wh
1308ab2a 10508+ (arg->whlist, name, namelen, ino, d_type, arg->bindex,
dece6358 10509+ au_ftest_testempty(arg->flags, SHWH));
1facf9fc 10510+
4f0767ce 10511+out:
1facf9fc 10512+ /* smp_mb(); */
10513+ AuTraceErr(arg->err);
10514+ return arg->err;
10515+}
10516+
10517+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
10518+{
10519+ int err;
10520+ struct file *h_file;
acd2b654 10521+ struct au_branch *br;
1facf9fc 10522+
10523+ h_file = au_h_open(dentry, arg->bindex,
10524+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
392086de 10525+ /*file*/NULL, /*force_wr*/0);
1facf9fc 10526+ err = PTR_ERR(h_file);
10527+ if (IS_ERR(h_file))
10528+ goto out;
10529+
10530+ err = 0;
10531+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
c06a8ce3 10532+ && !file_inode(h_file)->i_nlink)
1facf9fc 10533+ goto out_put;
10534+
10535+ do {
10536+ arg->err = 0;
10537+ au_fclr_testempty(arg->flags, CALLED);
10538+ /* smp_mb(); */
392086de 10539+ err = vfsub_iterate_dir(h_file, &arg->ctx);
1facf9fc 10540+ if (err >= 0)
10541+ err = arg->err;
10542+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
10543+
4f0767ce 10544+out_put:
1facf9fc 10545+ fput(h_file);
acd2b654
AM
10546+ br = au_sbr(dentry->d_sb, arg->bindex);
10547+ au_lcnt_dec(&br->br_nfiles);
4f0767ce 10548+out:
1facf9fc 10549+ return err;
10550+}
10551+
10552+struct do_test_empty_args {
10553+ int *errp;
10554+ struct dentry *dentry;
10555+ struct test_empty_arg *arg;
10556+};
10557+
10558+static void call_do_test_empty(void *args)
10559+{
10560+ struct do_test_empty_args *a = args;
10561+ *a->errp = do_test_empty(a->dentry, a->arg);
10562+}
10563+
10564+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
10565+{
10566+ int err, wkq_err;
10567+ struct dentry *h_dentry;
10568+ struct inode *h_inode;
0b2a12c6 10569+ struct user_namespace *h_userns;
1facf9fc 10570+
0b2a12c6 10571+ h_userns = au_sbr_userns(dentry->d_sb, arg->bindex);
1facf9fc 10572+ h_dentry = au_h_dptr(dentry, arg->bindex);
5527c038 10573+ h_inode = d_inode(h_dentry);
53392da6 10574+ /* todo: i_mode changes anytime? */
be118d29 10575+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD);
0b2a12c6 10576+ err = au_test_h_perm_sio(h_userns, h_inode, MAY_EXEC | MAY_READ);
3c1bdaff 10577+ inode_unlock_shared(h_inode);
1facf9fc 10578+ if (!err)
10579+ err = do_test_empty(dentry, arg);
10580+ else {
10581+ struct do_test_empty_args args = {
10582+ .errp = &err,
10583+ .dentry = dentry,
10584+ .arg = arg
10585+ };
10586+ unsigned int flags = arg->flags;
10587+
10588+ wkq_err = au_wkq_wait(call_do_test_empty, &args);
10589+ if (unlikely(wkq_err))
10590+ err = wkq_err;
10591+ arg->flags = flags;
10592+ }
10593+
10594+ return err;
10595+}
10596+
10597+int au_test_empty_lower(struct dentry *dentry)
10598+{
10599+ int err;
1308ab2a 10600+ unsigned int rdhash;
5afbbe0d 10601+ aufs_bindex_t bindex, btop, btail;
1308ab2a 10602+ struct au_nhash whlist;
392086de
AM
10603+ struct test_empty_arg arg = {
10604+ .ctx = {
2000de60 10605+ .actor = test_empty_cb
392086de
AM
10606+ }
10607+ };
076b876e 10608+ int (*test_empty)(struct dentry *dentry, struct test_empty_arg *arg);
1facf9fc 10609+
dece6358
AM
10610+ SiMustAnyLock(dentry->d_sb);
10611+
1308ab2a 10612+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
10613+ if (!rdhash)
10614+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
10615+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
dece6358 10616+ if (unlikely(err))
1facf9fc 10617+ goto out;
10618+
1facf9fc 10619+ arg.flags = 0;
1308ab2a 10620+ arg.whlist = &whlist;
5afbbe0d 10621+ btop = au_dbtop(dentry);
dece6358
AM
10622+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
10623+ au_fset_testempty(arg.flags, SHWH);
076b876e
AM
10624+ test_empty = do_test_empty;
10625+ if (au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1))
10626+ test_empty = sio_test_empty;
5afbbe0d 10627+ arg.bindex = btop;
076b876e 10628+ err = test_empty(dentry, &arg);
1facf9fc 10629+ if (unlikely(err))
10630+ goto out_whlist;
10631+
10632+ au_fset_testempty(arg.flags, WHONLY);
10633+ btail = au_dbtaildir(dentry);
5afbbe0d 10634+ for (bindex = btop + 1; !err && bindex <= btail; bindex++) {
1facf9fc 10635+ struct dentry *h_dentry;
10636+
10637+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 10638+ if (h_dentry && d_is_positive(h_dentry)) {
1facf9fc 10639+ arg.bindex = bindex;
076b876e 10640+ err = test_empty(dentry, &arg);
1facf9fc 10641+ }
10642+ }
10643+
4f0767ce 10644+out_whlist:
1308ab2a 10645+ au_nhash_wh_free(&whlist);
4f0767ce 10646+out:
1facf9fc 10647+ return err;
10648+}
10649+
10650+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
10651+{
10652+ int err;
392086de
AM
10653+ struct test_empty_arg arg = {
10654+ .ctx = {
2000de60 10655+ .actor = test_empty_cb
392086de
AM
10656+ }
10657+ };
1facf9fc 10658+ aufs_bindex_t bindex, btail;
10659+
10660+ err = 0;
1308ab2a 10661+ arg.whlist = whlist;
1facf9fc 10662+ arg.flags = AuTestEmpty_WHONLY;
dece6358
AM
10663+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
10664+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 10665+ btail = au_dbtaildir(dentry);
5afbbe0d 10666+ for (bindex = au_dbtop(dentry); !err && bindex <= btail; bindex++) {
1facf9fc 10667+ struct dentry *h_dentry;
10668+
10669+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 10670+ if (h_dentry && d_is_positive(h_dentry)) {
1facf9fc 10671+ arg.bindex = bindex;
10672+ err = sio_test_empty(dentry, &arg);
10673+ }
10674+ }
10675+
10676+ return err;
10677+}
10678+
10679+/* ---------------------------------------------------------------------- */
10680+
10681+const struct file_operations aufs_dir_fop = {
4a4d8108 10682+ .owner = THIS_MODULE,
027c5e7a 10683+ .llseek = default_llseek,
1facf9fc 10684+ .read = generic_read_dir,
5afbbe0d 10685+ .iterate_shared = aufs_iterate_shared,
1facf9fc 10686+ .unlocked_ioctl = aufs_ioctl_dir,
b752ccd1
AM
10687+#ifdef CONFIG_COMPAT
10688+ .compat_ioctl = aufs_compat_ioctl_dir,
10689+#endif
1facf9fc 10690+ .open = aufs_open_dir,
10691+ .release = aufs_release_dir,
4a4d8108 10692+ .flush = aufs_flush_dir,
1facf9fc 10693+ .fsync = aufs_fsync_dir
10694+};
7f207e10 10695diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
eca34b5c 10696--- /usr/share/empty/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
319657f6 10697+++ linux/fs/aufs/dir.h 2021-12-03 15:38:59.933313976 +0100
9f237c51 10698@@ -0,0 +1,134 @@
062440b3 10699+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 10700+/*
6d176551 10701+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 10702+ *
10703+ * This program, aufs is free software; you can redistribute it and/or modify
10704+ * it under the terms of the GNU General Public License as published by
10705+ * the Free Software Foundation; either version 2 of the License, or
10706+ * (at your option) any later version.
dece6358
AM
10707+ *
10708+ * This program is distributed in the hope that it will be useful,
10709+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10710+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10711+ * GNU General Public License for more details.
10712+ *
10713+ * You should have received a copy of the GNU General Public License
523b37e3 10714+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 10715+ */
10716+
10717+/*
10718+ * directory operations
10719+ */
10720+
10721+#ifndef __AUFS_DIR_H__
10722+#define __AUFS_DIR_H__
10723+
10724+#ifdef __KERNEL__
10725+
10726+#include <linux/fs.h>
1facf9fc 10727+
10728+/* ---------------------------------------------------------------------- */
10729+
10730+/* need to be faster and smaller */
10731+
10732+struct au_nhash {
dece6358
AM
10733+ unsigned int nh_num;
10734+ struct hlist_head *nh_head;
1facf9fc 10735+};
10736+
10737+struct au_vdir_destr {
10738+ unsigned char len;
42b5c33a 10739+ unsigned char name[];
1facf9fc 10740+} __packed;
10741+
10742+struct au_vdir_dehstr {
10743+ struct hlist_node hash;
1c60b727 10744+ struct au_vdir_destr *str;
9f237c51 10745+ struct rcu_head rcu;
4a4d8108 10746+} ____cacheline_aligned_in_smp;
1facf9fc 10747+
10748+struct au_vdir_de {
10749+ ino_t de_ino;
10750+ unsigned char de_type;
10751+ /* caution: packed */
10752+ struct au_vdir_destr de_str;
10753+} __packed;
10754+
10755+struct au_vdir_wh {
10756+ struct hlist_node wh_hash;
dece6358
AM
10757+#ifdef CONFIG_AUFS_SHWH
10758+ ino_t wh_ino;
1facf9fc 10759+ aufs_bindex_t wh_bindex;
dece6358
AM
10760+ unsigned char wh_type;
10761+#else
10762+ aufs_bindex_t wh_bindex;
10763+#endif
10764+ /* caution: packed */
1facf9fc 10765+ struct au_vdir_destr wh_str;
10766+} __packed;
10767+
10768+union au_vdir_deblk_p {
10769+ unsigned char *deblk;
10770+ struct au_vdir_de *de;
10771+};
10772+
10773+struct au_vdir {
10774+ unsigned char **vd_deblk;
10775+ unsigned long vd_nblk;
1facf9fc 10776+ struct {
10777+ unsigned long ul;
10778+ union au_vdir_deblk_p p;
10779+ } vd_last;
10780+
be118d29 10781+ u64 vd_version;
dece6358 10782+ unsigned int vd_deblk_sz;
9f237c51
AM
10783+ unsigned long vd_jiffy;
10784+ struct rcu_head rcu;
4a4d8108 10785+} ____cacheline_aligned_in_smp;
1facf9fc 10786+
10787+/* ---------------------------------------------------------------------- */
10788+
10789+/* dir.c */
10790+extern const struct file_operations aufs_dir_fop;
10791+void au_add_nlink(struct inode *dir, struct inode *h_dir);
10792+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
1308ab2a 10793+loff_t au_dir_size(struct file *file, struct dentry *dentry);
b912730e 10794+void au_dir_ts(struct inode *dir, aufs_bindex_t bsrc);
1facf9fc 10795+int au_test_empty_lower(struct dentry *dentry);
10796+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
10797+
10798+/* vdir.c */
1308ab2a 10799+unsigned int au_rdhash_est(loff_t sz);
dece6358
AM
10800+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
10801+void au_nhash_wh_free(struct au_nhash *whlist);
1facf9fc 10802+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
10803+ int limit);
dece6358
AM
10804+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
10805+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
10806+ unsigned int d_type, aufs_bindex_t bindex,
10807+ unsigned char shwh);
1c60b727 10808+void au_vdir_free(struct au_vdir *vdir);
1facf9fc 10809+int au_vdir_init(struct file *file);
392086de 10810+int au_vdir_fill_de(struct file *file, struct dir_context *ctx);
1facf9fc 10811+
10812+/* ioctl.c */
10813+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
10814+
1308ab2a 10815+#ifdef CONFIG_AUFS_RDU
10816+/* rdu.c */
10817+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
10818+#ifdef CONFIG_COMPAT
10819+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
10820+ unsigned long arg);
10821+#endif
1308ab2a 10822+#else
c1595e42
JR
10823+AuStub(long, au_rdu_ioctl, return -EINVAL, struct file *file,
10824+ unsigned int cmd, unsigned long arg)
b752ccd1 10825+#ifdef CONFIG_COMPAT
c1595e42
JR
10826+AuStub(long, au_rdu_compat_ioctl, return -EINVAL, struct file *file,
10827+ unsigned int cmd, unsigned long arg)
b752ccd1 10828+#endif
1308ab2a 10829+#endif
10830+
1facf9fc 10831+#endif /* __KERNEL__ */
10832+#endif /* __AUFS_DIR_H__ */
8b6a4947 10833diff -urN /usr/share/empty/fs/aufs/dirren.c linux/fs/aufs/dirren.c
eca34b5c 10834--- /usr/share/empty/fs/aufs/dirren.c 1970-01-01 01:00:00.000000000 +0100
319657f6 10835+++ linux/fs/aufs/dirren.c 2021-12-03 15:38:59.933313976 +0100
758e9dad 10836@@ -0,0 +1,1315 @@
cd7a4cd9 10837+// SPDX-License-Identifier: GPL-2.0
8b6a4947 10838+/*
6d176551 10839+ * Copyright (C) 2017-2021 Junjiro R. Okajima
8b6a4947
AM
10840+ *
10841+ * This program, aufs is free software; you can redistribute it and/or modify
10842+ * it under the terms of the GNU General Public License as published by
10843+ * the Free Software Foundation; either version 2 of the License, or
10844+ * (at your option) any later version.
10845+ *
10846+ * This program is distributed in the hope that it will be useful,
10847+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10848+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10849+ * GNU General Public License for more details.
10850+ *
10851+ * You should have received a copy of the GNU General Public License
10852+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
10853+ */
10854+
10855+/*
acd2b654 10856+ * special handling in renaming a directory
8b6a4947
AM
10857+ * in order to support looking-up the before-renamed name on the lower readonly
10858+ * branches
10859+ */
10860+
10861+#include <linux/byteorder/generic.h>
10862+#include "aufs.h"
10863+
10864+static void au_dr_hino_del(struct au_dr_br *dr, struct au_dr_hino *ent)
10865+{
10866+ int idx;
10867+
10868+ idx = au_dr_ihash(ent->dr_h_ino);
10869+ au_hbl_del(&ent->dr_hnode, dr->dr_h_ino + idx);
10870+}
10871+
10872+static int au_dr_hino_test_empty(struct au_dr_br *dr)
10873+{
10874+ int ret, i;
10875+ struct hlist_bl_head *hbl;
10876+
10877+ ret = 1;
10878+ for (i = 0; ret && i < AuDirren_NHASH; i++) {
10879+ hbl = dr->dr_h_ino + i;
10880+ hlist_bl_lock(hbl);
10881+ ret &= hlist_bl_empty(hbl);
10882+ hlist_bl_unlock(hbl);
10883+ }
10884+
10885+ return ret;
10886+}
10887+
10888+static struct au_dr_hino *au_dr_hino_find(struct au_dr_br *dr, ino_t ino)
10889+{
10890+ struct au_dr_hino *found, *ent;
10891+ struct hlist_bl_head *hbl;
10892+ struct hlist_bl_node *pos;
10893+ int idx;
10894+
10895+ found = NULL;
10896+ idx = au_dr_ihash(ino);
10897+ hbl = dr->dr_h_ino + idx;
10898+ hlist_bl_lock(hbl);
10899+ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode)
10900+ if (ent->dr_h_ino == ino) {
10901+ found = ent;
10902+ break;
10903+ }
10904+ hlist_bl_unlock(hbl);
10905+
10906+ return found;
10907+}
10908+
10909+int au_dr_hino_test_add(struct au_dr_br *dr, ino_t ino,
10910+ struct au_dr_hino *add_ent)
10911+{
10912+ int found, idx;
10913+ struct hlist_bl_head *hbl;
10914+ struct hlist_bl_node *pos;
10915+ struct au_dr_hino *ent;
10916+
10917+ found = 0;
10918+ idx = au_dr_ihash(ino);
10919+ hbl = dr->dr_h_ino + idx;
43982f53 10920+#if 0 /* debug print */
8b6a4947
AM
10921+ {
10922+ struct hlist_bl_node *tmp;
10923+
10924+ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode)
10925+ AuDbg("hi%llu\n", (unsigned long long)ent->dr_h_ino);
10926+ }
10927+#endif
10928+ hlist_bl_lock(hbl);
10929+ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode)
10930+ if (ent->dr_h_ino == ino) {
10931+ found = 1;
10932+ break;
10933+ }
10934+ if (!found && add_ent)
10935+ hlist_bl_add_head(&add_ent->dr_hnode, hbl);
10936+ hlist_bl_unlock(hbl);
10937+
10938+ if (!found && add_ent)
10939+ AuDbg("i%llu added\n", (unsigned long long)add_ent->dr_h_ino);
10940+
10941+ return found;
10942+}
10943+
10944+void au_dr_hino_free(struct au_dr_br *dr)
10945+{
10946+ int i;
10947+ struct hlist_bl_head *hbl;
10948+ struct hlist_bl_node *pos, *tmp;
10949+ struct au_dr_hino *ent;
10950+
10951+ /* SiMustWriteLock(sb); */
10952+
10953+ for (i = 0; i < AuDirren_NHASH; i++) {
10954+ hbl = dr->dr_h_ino + i;
10955+ /* no spinlock since sbinfo must be write-locked */
10956+ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode)
9f237c51 10957+ au_kfree_rcu(ent);
8b6a4947
AM
10958+ INIT_HLIST_BL_HEAD(hbl);
10959+ }
10960+}
10961+
10962+/* returns the number of inodes or an error */
10963+static int au_dr_hino_store(struct super_block *sb, struct au_branch *br,
10964+ struct file *hinofile)
10965+{
10966+ int err, i;
10967+ ssize_t ssz;
10968+ loff_t pos, oldsize;
10969+ __be64 u64;
10970+ struct inode *hinoinode;
10971+ struct hlist_bl_head *hbl;
10972+ struct hlist_bl_node *n1, *n2;
10973+ struct au_dr_hino *ent;
10974+
10975+ SiMustWriteLock(sb);
10976+ AuDebugOn(!au_br_writable(br->br_perm));
10977+
10978+ hinoinode = file_inode(hinofile);
10979+ oldsize = i_size_read(hinoinode);
10980+
10981+ err = 0;
10982+ pos = 0;
10983+ hbl = br->br_dirren.dr_h_ino;
10984+ for (i = 0; !err && i < AuDirren_NHASH; i++, hbl++) {
10985+ /* no bit-lock since sbinfo must be write-locked */
10986+ hlist_bl_for_each_entry_safe(ent, n1, n2, hbl, dr_hnode) {
10987+ AuDbg("hi%llu, %pD2\n",
10988+ (unsigned long long)ent->dr_h_ino, hinofile);
10989+ u64 = cpu_to_be64(ent->dr_h_ino);
10990+ ssz = vfsub_write_k(hinofile, &u64, sizeof(u64), &pos);
10991+ if (ssz == sizeof(u64))
10992+ continue;
10993+
10994+ /* write error */
10995+ pr_err("ssz %zd, %pD2\n", ssz, hinofile);
10996+ err = -ENOSPC;
10997+ if (ssz < 0)
10998+ err = ssz;
10999+ break;
11000+ }
11001+ }
11002+ /* regardless the error */
11003+ if (pos < oldsize) {
11004+ err = vfsub_trunc(&hinofile->f_path, pos, /*attr*/0, hinofile);
11005+ AuTraceErr(err);
11006+ }
11007+
11008+ AuTraceErr(err);
11009+ return err;
11010+}
11011+
11012+static int au_dr_hino_load(struct au_dr_br *dr, struct file *hinofile)
11013+{
11014+ int err, hidx;
11015+ ssize_t ssz;
11016+ size_t sz, n;
11017+ loff_t pos;
11018+ uint64_t u64;
11019+ struct au_dr_hino *ent;
11020+ struct inode *hinoinode;
11021+ struct hlist_bl_head *hbl;
11022+
11023+ err = 0;
11024+ pos = 0;
11025+ hbl = dr->dr_h_ino;
11026+ hinoinode = file_inode(hinofile);
11027+ sz = i_size_read(hinoinode);
11028+ AuDebugOn(sz % sizeof(u64));
11029+ n = sz / sizeof(u64);
11030+ while (n--) {
11031+ ssz = vfsub_read_k(hinofile, &u64, sizeof(u64), &pos);
11032+ if (unlikely(ssz != sizeof(u64))) {
11033+ pr_err("ssz %zd, %pD2\n", ssz, hinofile);
11034+ err = -EINVAL;
11035+ if (ssz < 0)
11036+ err = ssz;
11037+ goto out_free;
11038+ }
11039+
11040+ ent = kmalloc(sizeof(*ent), GFP_NOFS);
11041+ if (!ent) {
11042+ err = -ENOMEM;
11043+ AuTraceErr(err);
11044+ goto out_free;
11045+ }
11046+ ent->dr_h_ino = be64_to_cpu((__force __be64)u64);
11047+ AuDbg("hi%llu, %pD2\n",
11048+ (unsigned long long)ent->dr_h_ino, hinofile);
11049+ hidx = au_dr_ihash(ent->dr_h_ino);
11050+ au_hbl_add(&ent->dr_hnode, hbl + hidx);
11051+ }
11052+ goto out; /* success */
11053+
11054+out_free:
11055+ au_dr_hino_free(dr);
11056+out:
11057+ AuTraceErr(err);
11058+ return err;
11059+}
11060+
11061+/*
11062+ * @bindex/@br is a switch to distinguish whether suspending hnotify or not.
11063+ * @path is a switch to distinguish load and store.
11064+ */
11065+static int au_dr_hino(struct super_block *sb, aufs_bindex_t bindex,
11066+ struct au_branch *br, const struct path *path)
11067+{
11068+ int err, flags;
11069+ unsigned char load, suspend;
11070+ struct file *hinofile;
11071+ struct au_hinode *hdir;
11072+ struct inode *dir, *delegated;
11073+ struct path hinopath;
11074+ struct qstr hinoname = QSTR_INIT(AUFS_WH_DR_BRHINO,
11075+ sizeof(AUFS_WH_DR_BRHINO) - 1);
11076+
11077+ AuDebugOn(bindex < 0 && !br);
11078+ AuDebugOn(bindex >= 0 && br);
11079+
11080+ err = -EINVAL;
11081+ suspend = !br;
11082+ if (suspend)
11083+ br = au_sbr(sb, bindex);
11084+ load = !!path;
11085+ if (!load) {
11086+ path = &br->br_path;
11087+ AuDebugOn(!au_br_writable(br->br_perm));
11088+ if (unlikely(!au_br_writable(br->br_perm)))
11089+ goto out;
11090+ }
11091+
11092+ hdir = NULL;
11093+ if (suspend) {
11094+ dir = d_inode(sb->s_root);
11095+ hdir = au_hinode(au_ii(dir), bindex);
11096+ dir = hdir->hi_inode;
11097+ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD);
11098+ } else {
11099+ dir = d_inode(path->dentry);
11100+ inode_lock_nested(dir, AuLsc_I_CHILD);
11101+ }
758e9dad
AM
11102+ hinopath.mnt = path->mnt;
11103+ hinopath.dentry = vfsub_lkup_one(&hinoname, (struct path *)path);
8b6a4947
AM
11104+ err = PTR_ERR(hinopath.dentry);
11105+ if (IS_ERR(hinopath.dentry))
11106+ goto out_unlock;
11107+
11108+ err = 0;
11109+ flags = O_RDONLY;
11110+ if (load) {
11111+ if (d_is_negative(hinopath.dentry))
11112+ goto out_dput; /* success */
11113+ } else {
11114+ if (au_dr_hino_test_empty(&br->br_dirren)) {
11115+ if (d_is_positive(hinopath.dentry)) {
11116+ delegated = NULL;
11117+ err = vfsub_unlink(dir, &hinopath, &delegated,
11118+ /*force*/0);
11119+ AuTraceErr(err);
11120+ if (unlikely(err))
11121+ pr_err("ignored err %d, %pd2\n",
11122+ err, hinopath.dentry);
11123+ if (unlikely(err == -EWOULDBLOCK))
11124+ iput(delegated);
11125+ err = 0;
11126+ }
11127+ goto out_dput;
11128+ } else if (!d_is_positive(hinopath.dentry)) {
11129+ err = vfsub_create(dir, &hinopath, 0600,
11130+ /*want_excl*/false);
11131+ AuTraceErr(err);
11132+ if (unlikely(err))
11133+ goto out_dput;
11134+ }
11135+ flags = O_WRONLY;
11136+ }
8b6a4947
AM
11137+ hinofile = vfsub_dentry_open(&hinopath, flags);
11138+ if (suspend)
11139+ au_hn_inode_unlock(hdir);
11140+ else
11141+ inode_unlock(dir);
11142+ dput(hinopath.dentry);
11143+ AuTraceErrPtr(hinofile);
11144+ if (IS_ERR(hinofile)) {
11145+ err = PTR_ERR(hinofile);
11146+ goto out;
11147+ }
11148+
11149+ if (load)
11150+ err = au_dr_hino_load(&br->br_dirren, hinofile);
11151+ else
11152+ err = au_dr_hino_store(sb, br, hinofile);
11153+ fput(hinofile);
11154+ goto out;
11155+
11156+out_dput:
11157+ dput(hinopath.dentry);
11158+out_unlock:
11159+ if (suspend)
11160+ au_hn_inode_unlock(hdir);
11161+ else
11162+ inode_unlock(dir);
11163+out:
11164+ AuTraceErr(err);
11165+ return err;
11166+}
11167+
11168+/* ---------------------------------------------------------------------- */
11169+
11170+static int au_dr_brid_init(struct au_dr_brid *brid, const struct path *path)
11171+{
11172+ int err;
11173+ struct kstatfs kstfs;
11174+ dev_t dev;
11175+ struct dentry *dentry;
11176+ struct super_block *sb;
11177+
11178+ err = vfs_statfs((void *)path, &kstfs);
11179+ AuTraceErr(err);
11180+ if (unlikely(err))
11181+ goto out;
11182+
11183+ /* todo: support for UUID */
11184+
11185+ if (kstfs.f_fsid.val[0] || kstfs.f_fsid.val[1]) {
11186+ brid->type = AuBrid_FSID;
11187+ brid->fsid = kstfs.f_fsid;
11188+ } else {
11189+ dentry = path->dentry;
11190+ sb = dentry->d_sb;
11191+ dev = sb->s_dev;
11192+ if (dev) {
11193+ brid->type = AuBrid_DEV;
11194+ brid->dev = dev;
11195+ }
11196+ }
11197+
11198+out:
11199+ return err;
11200+}
11201+
11202+int au_dr_br_init(struct super_block *sb, struct au_branch *br,
11203+ const struct path *path)
11204+{
11205+ int err, i;
11206+ struct au_dr_br *dr;
11207+ struct hlist_bl_head *hbl;
11208+
11209+ dr = &br->br_dirren;
11210+ hbl = dr->dr_h_ino;
11211+ for (i = 0; i < AuDirren_NHASH; i++, hbl++)
11212+ INIT_HLIST_BL_HEAD(hbl);
11213+
11214+ err = au_dr_brid_init(&dr->dr_brid, path);
11215+ if (unlikely(err))
11216+ goto out;
11217+
11218+ if (au_opt_test(au_mntflags(sb), DIRREN))
11219+ err = au_dr_hino(sb, /*bindex*/-1, br, path);
11220+
11221+out:
11222+ AuTraceErr(err);
11223+ return err;
11224+}
11225+
11226+int au_dr_br_fin(struct super_block *sb, struct au_branch *br)
11227+{
11228+ int err;
11229+
11230+ err = 0;
11231+ if (au_br_writable(br->br_perm))
11232+ err = au_dr_hino(sb, /*bindex*/-1, br, /*path*/NULL);
11233+ if (!err)
11234+ au_dr_hino_free(&br->br_dirren);
11235+
11236+ return err;
11237+}
11238+
11239+/* ---------------------------------------------------------------------- */
11240+
11241+static int au_brid_str(struct au_dr_brid *brid, struct inode *h_inode,
11242+ char *buf, size_t sz)
11243+{
11244+ int err;
11245+ unsigned int major, minor;
11246+ char *p;
11247+
11248+ p = buf;
11249+ err = snprintf(p, sz, "%d_", brid->type);
11250+ AuDebugOn(err > sz);
11251+ p += err;
11252+ sz -= err;
11253+ switch (brid->type) {
11254+ case AuBrid_Unset:
11255+ return -EINVAL;
11256+ case AuBrid_UUID:
11257+ err = snprintf(p, sz, "%pU", brid->uuid.b);
11258+ break;
11259+ case AuBrid_FSID:
11260+ err = snprintf(p, sz, "%08x-%08x",
11261+ brid->fsid.val[0], brid->fsid.val[1]);
11262+ break;
11263+ case AuBrid_DEV:
11264+ major = MAJOR(brid->dev);
11265+ minor = MINOR(brid->dev);
11266+ if (major <= 0xff && minor <= 0xff)
11267+ err = snprintf(p, sz, "%02x%02x", major, minor);
11268+ else
11269+ err = snprintf(p, sz, "%03x:%05x", major, minor);
11270+ break;
11271+ }
11272+ AuDebugOn(err > sz);
11273+ p += err;
11274+ sz -= err;
11275+ err = snprintf(p, sz, "_%llu", (unsigned long long)h_inode->i_ino);
11276+ AuDebugOn(err > sz);
11277+ p += err;
11278+ sz -= err;
11279+
11280+ return p - buf;
11281+}
11282+
11283+static int au_drinfo_name(struct au_branch *br, char *name, int len)
11284+{
11285+ int rlen;
11286+ struct dentry *br_dentry;
11287+ struct inode *br_inode;
11288+
11289+ br_dentry = au_br_dentry(br);
11290+ br_inode = d_inode(br_dentry);
11291+ rlen = au_brid_str(&br->br_dirren.dr_brid, br_inode, name, len);
11292+ AuDebugOn(rlen >= AUFS_DIRREN_ENV_VAL_SZ);
11293+ AuDebugOn(rlen > len);
11294+
11295+ return rlen;
11296+}
11297+
11298+/* ---------------------------------------------------------------------- */
11299+
11300+/*
11301+ * from the given @h_dentry, construct drinfo at @*fdata.
11302+ * when the size of @*fdata is not enough, reallocate and return new @fdata and
11303+ * @allocated.
11304+ */
11305+static int au_drinfo_construct(struct au_drinfo_fdata **fdata,
11306+ struct dentry *h_dentry,
11307+ unsigned char *allocated)
11308+{
11309+ int err, v;
11310+ struct au_drinfo_fdata *f, *p;
11311+ struct au_drinfo *drinfo;
11312+ struct inode *h_inode;
11313+ struct qstr *qname;
11314+
11315+ err = 0;
11316+ f = *fdata;
11317+ h_inode = d_inode(h_dentry);
11318+ qname = &h_dentry->d_name;
11319+ drinfo = &f->drinfo;
11320+ drinfo->ino = (__force uint64_t)cpu_to_be64(h_inode->i_ino);
11321+ drinfo->oldnamelen = qname->len;
11322+ if (*allocated < sizeof(*f) + qname->len) {
11323+ v = roundup_pow_of_two(*allocated + qname->len);
11324+ p = au_krealloc(f, v, GFP_NOFS, /*may_shrink*/0);
11325+ if (unlikely(!p)) {
11326+ err = -ENOMEM;
11327+ AuTraceErr(err);
11328+ goto out;
11329+ }
11330+ f = p;
11331+ *fdata = f;
11332+ *allocated = v;
11333+ drinfo = &f->drinfo;
11334+ }
11335+ memcpy(drinfo->oldname, qname->name, qname->len);
11336+ AuDbg("i%llu, %.*s\n",
11337+ be64_to_cpu((__force __be64)drinfo->ino), drinfo->oldnamelen,
11338+ drinfo->oldname);
11339+
11340+out:
11341+ AuTraceErr(err);
11342+ return err;
11343+}
11344+
11345+/* callers have to free the return value */
11346+static struct au_drinfo *au_drinfo_read_k(struct file *file, ino_t h_ino)
11347+{
11348+ struct au_drinfo *ret, *drinfo;
11349+ struct au_drinfo_fdata fdata;
11350+ int len;
11351+ loff_t pos;
11352+ ssize_t ssz;
11353+
11354+ ret = ERR_PTR(-EIO);
11355+ pos = 0;
11356+ ssz = vfsub_read_k(file, &fdata, sizeof(fdata), &pos);
11357+ if (unlikely(ssz != sizeof(fdata))) {
11358+ AuIOErr("ssz %zd, %u, %pD2\n",
11359+ ssz, (unsigned int)sizeof(fdata), file);
11360+ goto out;
11361+ }
11362+
11363+ fdata.magic = ntohl((__force __be32)fdata.magic);
11364+ switch (fdata.magic) {
11365+ case AUFS_DRINFO_MAGIC_V1:
11366+ break;
11367+ default:
11368+ AuIOErr("magic-num 0x%x, 0x%x, %pD2\n",
11369+ fdata.magic, AUFS_DRINFO_MAGIC_V1, file);
11370+ goto out;
11371+ }
11372+
11373+ drinfo = &fdata.drinfo;
11374+ len = drinfo->oldnamelen;
11375+ if (!len) {
11376+ AuIOErr("broken drinfo %pD2\n", file);
11377+ goto out;
11378+ }
11379+
11380+ ret = NULL;
11381+ drinfo->ino = be64_to_cpu((__force __be64)drinfo->ino);
11382+ if (unlikely(h_ino && drinfo->ino != h_ino)) {
11383+ AuDbg("ignored i%llu, i%llu, %pD2\n",
11384+ (unsigned long long)drinfo->ino,
11385+ (unsigned long long)h_ino, file);
11386+ goto out; /* success */
11387+ }
11388+
11389+ ret = kmalloc(sizeof(*ret) + len, GFP_NOFS);
11390+ if (unlikely(!ret)) {
11391+ ret = ERR_PTR(-ENOMEM);
11392+ AuTraceErrPtr(ret);
11393+ goto out;
11394+ }
11395+
11396+ *ret = *drinfo;
11397+ ssz = vfsub_read_k(file, (void *)ret->oldname, len, &pos);
11398+ if (unlikely(ssz != len)) {
9f237c51 11399+ au_kfree_rcu(ret);
8b6a4947
AM
11400+ ret = ERR_PTR(-EIO);
11401+ AuIOErr("ssz %zd, %u, %pD2\n", ssz, len, file);
11402+ goto out;
11403+ }
11404+
11405+ AuDbg("oldname %.*s\n", ret->oldnamelen, ret->oldname);
11406+
11407+out:
11408+ return ret;
11409+}
11410+
11411+/* ---------------------------------------------------------------------- */
11412+
11413+/* in order to be revertible */
11414+struct au_drinfo_rev_elm {
11415+ int created;
11416+ struct dentry *info_dentry;
11417+ struct au_drinfo *info_last;
11418+};
11419+
11420+struct au_drinfo_rev {
11421+ unsigned char already;
11422+ aufs_bindex_t nelm;
42b5c33a 11423+ struct au_drinfo_rev_elm elm[];
8b6a4947
AM
11424+};
11425+
11426+/* todo: isn't it too large? */
11427+struct au_drinfo_store {
11428+ struct path h_ppath;
11429+ struct dentry *h_dentry;
11430+ struct au_drinfo_fdata *fdata;
11431+ char *infoname; /* inside of whname, just after PFX */
11432+ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ];
11433+ aufs_bindex_t btgt, btail;
11434+ unsigned char no_sio,
11435+ allocated, /* current size of *fdata */
11436+ infonamelen, /* room size for p */
acd2b654 11437+ whnamelen, /* length of the generated name */
8b6a4947
AM
11438+ renameback; /* renamed back */
11439+};
11440+
11441+/* on rename(2) error, the caller should revert it using @elm */
11442+static int au_drinfo_do_store(struct au_drinfo_store *w,
11443+ struct au_drinfo_rev_elm *elm)
11444+{
11445+ int err, len;
11446+ ssize_t ssz;
11447+ loff_t pos;
11448+ struct path infopath = {
11449+ .mnt = w->h_ppath.mnt
11450+ };
11451+ struct inode *h_dir, *h_inode, *delegated;
11452+ struct file *infofile;
11453+ struct qstr *qname;
11454+
11455+ AuDebugOn(elm
11456+ && memcmp(elm, page_address(ZERO_PAGE(0)), sizeof(*elm)));
11457+
758e9dad 11458+ infopath.dentry = vfsub_lookup_one_len(w->whname, &w->h_ppath,
8b6a4947
AM
11459+ w->whnamelen);
11460+ AuTraceErrPtr(infopath.dentry);
11461+ if (IS_ERR(infopath.dentry)) {
11462+ err = PTR_ERR(infopath.dentry);
11463+ goto out;
11464+ }
11465+
11466+ err = 0;
11467+ h_dir = d_inode(w->h_ppath.dentry);
11468+ if (elm && d_is_negative(infopath.dentry)) {
11469+ err = vfsub_create(h_dir, &infopath, 0600, /*want_excl*/true);
11470+ AuTraceErr(err);
11471+ if (unlikely(err))
11472+ goto out_dput;
11473+ elm->created = 1;
11474+ elm->info_dentry = dget(infopath.dentry);
11475+ }
11476+
11477+ infofile = vfsub_dentry_open(&infopath, O_RDWR);
11478+ AuTraceErrPtr(infofile);
11479+ if (IS_ERR(infofile)) {
11480+ err = PTR_ERR(infofile);
11481+ goto out_dput;
11482+ }
11483+
11484+ h_inode = d_inode(infopath.dentry);
11485+ if (elm && i_size_read(h_inode)) {
11486+ h_inode = d_inode(w->h_dentry);
11487+ elm->info_last = au_drinfo_read_k(infofile, h_inode->i_ino);
11488+ AuTraceErrPtr(elm->info_last);
11489+ if (IS_ERR(elm->info_last)) {
11490+ err = PTR_ERR(elm->info_last);
11491+ elm->info_last = NULL;
11492+ AuDebugOn(elm->info_dentry);
11493+ goto out_fput;
11494+ }
11495+ }
11496+
11497+ if (elm && w->renameback) {
11498+ delegated = NULL;
11499+ err = vfsub_unlink(h_dir, &infopath, &delegated, /*force*/0);
11500+ AuTraceErr(err);
11501+ if (unlikely(err == -EWOULDBLOCK))
11502+ iput(delegated);
11503+ goto out_fput;
11504+ }
11505+
11506+ pos = 0;
11507+ qname = &w->h_dentry->d_name;
11508+ len = sizeof(*w->fdata) + qname->len;
11509+ if (!elm)
11510+ len = sizeof(*w->fdata) + w->fdata->drinfo.oldnamelen;
11511+ ssz = vfsub_write_k(infofile, w->fdata, len, &pos);
11512+ if (ssz == len) {
11513+ AuDbg("hi%llu, %.*s\n", w->fdata->drinfo.ino,
11514+ w->fdata->drinfo.oldnamelen, w->fdata->drinfo.oldname);
11515+ goto out_fput; /* success */
11516+ } else {
11517+ err = -EIO;
11518+ if (ssz < 0)
11519+ err = ssz;
11520+ /* the caller should revert it using @elm */
11521+ }
11522+
11523+out_fput:
11524+ fput(infofile);
11525+out_dput:
11526+ dput(infopath.dentry);
11527+out:
11528+ AuTraceErr(err);
11529+ return err;
11530+}
11531+
11532+struct au_call_drinfo_do_store_args {
11533+ int *errp;
11534+ struct au_drinfo_store *w;
11535+ struct au_drinfo_rev_elm *elm;
11536+};
11537+
11538+static void au_call_drinfo_do_store(void *args)
11539+{
11540+ struct au_call_drinfo_do_store_args *a = args;
11541+
11542+ *a->errp = au_drinfo_do_store(a->w, a->elm);
11543+}
11544+
11545+static int au_drinfo_store_sio(struct au_drinfo_store *w,
11546+ struct au_drinfo_rev_elm *elm)
11547+{
11548+ int err, wkq_err;
11549+
11550+ if (w->no_sio)
11551+ err = au_drinfo_do_store(w, elm);
11552+ else {
11553+ struct au_call_drinfo_do_store_args a = {
11554+ .errp = &err,
11555+ .w = w,
11556+ .elm = elm
11557+ };
11558+ wkq_err = au_wkq_wait(au_call_drinfo_do_store, &a);
11559+ if (unlikely(wkq_err))
11560+ err = wkq_err;
11561+ }
11562+ AuTraceErr(err);
11563+
11564+ return err;
11565+}
11566+
11567+static int au_drinfo_store_work_init(struct au_drinfo_store *w,
11568+ aufs_bindex_t btgt)
11569+{
11570+ int err;
11571+
11572+ memset(w, 0, sizeof(*w));
11573+ w->allocated = roundup_pow_of_two(sizeof(*w->fdata) + 40);
11574+ strcpy(w->whname, AUFS_WH_DR_INFO_PFX);
11575+ w->infoname = w->whname + sizeof(AUFS_WH_DR_INFO_PFX) - 1;
11576+ w->infonamelen = sizeof(w->whname) - sizeof(AUFS_WH_DR_INFO_PFX);
11577+ w->btgt = btgt;
11578+ w->no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID);
11579+
11580+ err = -ENOMEM;
11581+ w->fdata = kcalloc(1, w->allocated, GFP_NOFS);
11582+ if (unlikely(!w->fdata)) {
11583+ AuTraceErr(err);
11584+ goto out;
11585+ }
11586+ w->fdata->magic = (__force uint32_t)htonl(AUFS_DRINFO_MAGIC_V1);
11587+ err = 0;
11588+
11589+out:
11590+ return err;
11591+}
11592+
11593+static void au_drinfo_store_work_fin(struct au_drinfo_store *w)
11594+{
9f237c51 11595+ au_kfree_rcu(w->fdata);
8b6a4947
AM
11596+}
11597+
11598+static void au_drinfo_store_rev(struct au_drinfo_rev *rev,
11599+ struct au_drinfo_store *w)
11600+{
11601+ struct au_drinfo_rev_elm *elm;
11602+ struct inode *h_dir, *delegated;
11603+ int err, nelm;
11604+ struct path infopath = {
11605+ .mnt = w->h_ppath.mnt
11606+ };
11607+
11608+ h_dir = d_inode(w->h_ppath.dentry);
11609+ IMustLock(h_dir);
11610+
11611+ err = 0;
11612+ elm = rev->elm;
11613+ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) {
11614+ AuDebugOn(elm->created && elm->info_last);
11615+ if (elm->created) {
11616+ AuDbg("here\n");
11617+ delegated = NULL;
11618+ infopath.dentry = elm->info_dentry;
11619+ err = vfsub_unlink(h_dir, &infopath, &delegated,
11620+ !w->no_sio);
11621+ AuTraceErr(err);
11622+ if (unlikely(err == -EWOULDBLOCK))
11623+ iput(delegated);
11624+ dput(elm->info_dentry);
11625+ } else if (elm->info_last) {
11626+ AuDbg("here\n");
11627+ w->fdata->drinfo = *elm->info_last;
11628+ memcpy(w->fdata->drinfo.oldname,
11629+ elm->info_last->oldname,
11630+ elm->info_last->oldnamelen);
11631+ err = au_drinfo_store_sio(w, /*elm*/NULL);
9f237c51 11632+ au_kfree_rcu(elm->info_last);
8b6a4947
AM
11633+ }
11634+ if (unlikely(err))
11635+ AuIOErr("%d, %s\n", err, w->whname);
11636+ /* go on even if err */
11637+ }
11638+}
11639+
11640+/* caller has to call au_dr_rename_fin() later */
11641+static int au_drinfo_store(struct dentry *dentry, aufs_bindex_t btgt,
11642+ struct qstr *dst_name, void *_rev)
11643+{
11644+ int err, sz, nelm;
11645+ aufs_bindex_t bindex, btail;
11646+ struct au_drinfo_store work;
11647+ struct au_drinfo_rev *rev, **p;
11648+ struct au_drinfo_rev_elm *elm;
11649+ struct super_block *sb;
11650+ struct au_branch *br;
11651+ struct au_hinode *hdir;
11652+
11653+ err = au_drinfo_store_work_init(&work, btgt);
11654+ AuTraceErr(err);
11655+ if (unlikely(err))
11656+ goto out;
11657+
11658+ err = -ENOMEM;
11659+ btail = au_dbtaildir(dentry);
11660+ nelm = btail - btgt;
11661+ sz = sizeof(*rev) + sizeof(*elm) * nelm;
11662+ rev = kcalloc(1, sz, GFP_NOFS);
11663+ if (unlikely(!rev)) {
11664+ AuTraceErr(err);
11665+ goto out_args;
11666+ }
11667+ rev->nelm = nelm;
11668+ elm = rev->elm;
11669+ p = _rev;
11670+ *p = rev;
11671+
11672+ err = 0;
11673+ sb = dentry->d_sb;
11674+ work.h_ppath.dentry = au_h_dptr(dentry, btgt);
11675+ work.h_ppath.mnt = au_sbr_mnt(sb, btgt);
11676+ hdir = au_hi(d_inode(dentry), btgt);
11677+ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD);
11678+ for (bindex = btgt + 1; bindex <= btail; bindex++, elm++) {
11679+ work.h_dentry = au_h_dptr(dentry, bindex);
11680+ if (!work.h_dentry)
11681+ continue;
11682+
11683+ err = au_drinfo_construct(&work.fdata, work.h_dentry,
11684+ &work.allocated);
11685+ AuTraceErr(err);
11686+ if (unlikely(err))
11687+ break;
11688+
11689+ work.renameback = au_qstreq(&work.h_dentry->d_name, dst_name);
11690+ br = au_sbr(sb, bindex);
11691+ work.whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1;
11692+ work.whnamelen += au_drinfo_name(br, work.infoname,
11693+ work.infonamelen);
11694+ AuDbg("whname %.*s, i%llu, %.*s\n",
11695+ work.whnamelen, work.whname,
11696+ be64_to_cpu((__force __be64)work.fdata->drinfo.ino),
11697+ work.fdata->drinfo.oldnamelen,
11698+ work.fdata->drinfo.oldname);
11699+
11700+ err = au_drinfo_store_sio(&work, elm);
11701+ AuTraceErr(err);
11702+ if (unlikely(err))
11703+ break;
11704+ }
11705+ if (unlikely(err)) {
11706+ /* revert all drinfo */
11707+ au_drinfo_store_rev(rev, &work);
9f237c51 11708+ au_kfree_try_rcu(rev);
8b6a4947
AM
11709+ *p = NULL;
11710+ }
11711+ au_hn_inode_unlock(hdir);
11712+
11713+out_args:
11714+ au_drinfo_store_work_fin(&work);
11715+out:
11716+ return err;
11717+}
11718+
11719+/* ---------------------------------------------------------------------- */
11720+
11721+int au_dr_rename(struct dentry *src, aufs_bindex_t bindex,
11722+ struct qstr *dst_name, void *_rev)
11723+{
11724+ int err, already;
11725+ ino_t ino;
11726+ struct super_block *sb;
11727+ struct au_branch *br;
11728+ struct au_dr_br *dr;
11729+ struct dentry *h_dentry;
11730+ struct inode *h_inode;
11731+ struct au_dr_hino *ent;
11732+ struct au_drinfo_rev *rev, **p;
11733+
11734+ AuDbg("bindex %d\n", bindex);
11735+
11736+ err = -ENOMEM;
11737+ ent = kmalloc(sizeof(*ent), GFP_NOFS);
11738+ if (unlikely(!ent))
11739+ goto out;
11740+
11741+ sb = src->d_sb;
11742+ br = au_sbr(sb, bindex);
11743+ dr = &br->br_dirren;
11744+ h_dentry = au_h_dptr(src, bindex);
11745+ h_inode = d_inode(h_dentry);
11746+ ino = h_inode->i_ino;
11747+ ent->dr_h_ino = ino;
11748+ already = au_dr_hino_test_add(dr, ino, ent);
11749+ AuDbg("b%d, hi%llu, already %d\n",
11750+ bindex, (unsigned long long)ino, already);
11751+
11752+ err = au_drinfo_store(src, bindex, dst_name, _rev);
11753+ AuTraceErr(err);
11754+ if (!err) {
11755+ p = _rev;
11756+ rev = *p;
11757+ rev->already = already;
11758+ goto out; /* success */
11759+ }
11760+
11761+ /* revert */
11762+ if (!already)
11763+ au_dr_hino_del(dr, ent);
9f237c51 11764+ au_kfree_rcu(ent);
8b6a4947
AM
11765+
11766+out:
11767+ AuTraceErr(err);
11768+ return err;
11769+}
11770+
11771+void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *_rev)
11772+{
11773+ struct au_drinfo_rev *rev;
11774+ struct au_drinfo_rev_elm *elm;
11775+ int nelm;
11776+
11777+ rev = _rev;
11778+ elm = rev->elm;
11779+ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) {
11780+ dput(elm->info_dentry);
9f237c51 11781+ au_kfree_rcu(elm->info_last);
8b6a4947 11782+ }
9f237c51 11783+ au_kfree_try_rcu(rev);
8b6a4947
AM
11784+}
11785+
11786+void au_dr_rename_rev(struct dentry *src, aufs_bindex_t btgt, void *_rev)
11787+{
11788+ int err;
11789+ struct au_drinfo_store work;
11790+ struct au_drinfo_rev *rev = _rev;
11791+ struct super_block *sb;
11792+ struct au_branch *br;
11793+ struct inode *h_inode;
11794+ struct au_dr_br *dr;
11795+ struct au_dr_hino *ent;
11796+
11797+ err = au_drinfo_store_work_init(&work, btgt);
11798+ if (unlikely(err))
11799+ goto out;
11800+
11801+ sb = src->d_sb;
11802+ br = au_sbr(sb, btgt);
11803+ work.h_ppath.dentry = au_h_dptr(src, btgt);
11804+ work.h_ppath.mnt = au_br_mnt(br);
11805+ au_drinfo_store_rev(rev, &work);
11806+ au_drinfo_store_work_fin(&work);
11807+ if (rev->already)
11808+ goto out;
11809+
11810+ dr = &br->br_dirren;
11811+ h_inode = d_inode(work.h_ppath.dentry);
11812+ ent = au_dr_hino_find(dr, h_inode->i_ino);
11813+ BUG_ON(!ent);
11814+ au_dr_hino_del(dr, ent);
9f237c51 11815+ au_kfree_rcu(ent);
8b6a4947
AM
11816+
11817+out:
9f237c51 11818+ au_kfree_try_rcu(rev);
8b6a4947
AM
11819+ if (unlikely(err))
11820+ pr_err("failed to remove dirren info\n");
11821+}
11822+
11823+/* ---------------------------------------------------------------------- */
11824+
11825+static struct au_drinfo *au_drinfo_do_load(struct path *h_ppath,
11826+ char *whname, int whnamelen,
11827+ struct dentry **info_dentry)
11828+{
11829+ struct au_drinfo *drinfo;
11830+ struct file *f;
11831+ struct inode *h_dir;
11832+ struct path infopath;
11833+ int unlocked;
11834+
11835+ AuDbg("%pd/%.*s\n", h_ppath->dentry, whnamelen, whname);
11836+
11837+ *info_dentry = NULL;
11838+ drinfo = NULL;
11839+ unlocked = 0;
11840+ h_dir = d_inode(h_ppath->dentry);
be118d29 11841+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
758e9dad 11842+ infopath.dentry = vfsub_lookup_one_len(whname, h_ppath, whnamelen);
8b6a4947
AM
11843+ if (IS_ERR(infopath.dentry)) {
11844+ drinfo = (void *)infopath.dentry;
11845+ goto out;
11846+ }
11847+
11848+ if (d_is_negative(infopath.dentry))
11849+ goto out_dput; /* success */
11850+
11851+ infopath.mnt = h_ppath->mnt;
11852+ f = vfsub_dentry_open(&infopath, O_RDONLY);
11853+ inode_unlock_shared(h_dir);
11854+ unlocked = 1;
11855+ if (IS_ERR(f)) {
11856+ drinfo = (void *)f;
11857+ goto out_dput;
11858+ }
11859+
11860+ drinfo = au_drinfo_read_k(f, /*h_ino*/0);
11861+ if (IS_ERR_OR_NULL(drinfo))
11862+ goto out_fput;
11863+
11864+ AuDbg("oldname %.*s\n", drinfo->oldnamelen, drinfo->oldname);
11865+ *info_dentry = dget(infopath.dentry); /* keep it alive */
11866+
11867+out_fput:
11868+ fput(f);
11869+out_dput:
11870+ dput(infopath.dentry);
11871+out:
11872+ if (!unlocked)
11873+ inode_unlock_shared(h_dir);
11874+ AuTraceErrPtr(drinfo);
11875+ return drinfo;
11876+}
11877+
11878+struct au_drinfo_do_load_args {
11879+ struct au_drinfo **drinfop;
11880+ struct path *h_ppath;
11881+ char *whname;
11882+ int whnamelen;
11883+ struct dentry **info_dentry;
11884+};
11885+
11886+static void au_call_drinfo_do_load(void *args)
11887+{
11888+ struct au_drinfo_do_load_args *a = args;
11889+
11890+ *a->drinfop = au_drinfo_do_load(a->h_ppath, a->whname, a->whnamelen,
11891+ a->info_dentry);
11892+}
11893+
11894+struct au_drinfo_load {
11895+ struct path h_ppath;
11896+ struct qstr *qname;
11897+ unsigned char no_sio;
11898+
11899+ aufs_bindex_t ninfo;
11900+ struct au_drinfo **drinfo;
11901+};
11902+
11903+static int au_drinfo_load(struct au_drinfo_load *w, aufs_bindex_t bindex,
11904+ struct au_branch *br)
11905+{
11906+ int err, wkq_err, whnamelen, e;
11907+ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ]
11908+ = AUFS_WH_DR_INFO_PFX;
11909+ struct au_drinfo *drinfo;
11910+ struct qstr oldname;
11911+ struct inode *h_dir, *delegated;
11912+ struct dentry *info_dentry;
11913+ struct path infopath;
11914+
11915+ whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1;
11916+ whnamelen += au_drinfo_name(br, whname + whnamelen,
11917+ sizeof(whname) - whnamelen);
11918+ if (w->no_sio)
11919+ drinfo = au_drinfo_do_load(&w->h_ppath, whname, whnamelen,
11920+ &info_dentry);
11921+ else {
11922+ struct au_drinfo_do_load_args args = {
11923+ .drinfop = &drinfo,
11924+ .h_ppath = &w->h_ppath,
11925+ .whname = whname,
11926+ .whnamelen = whnamelen,
11927+ .info_dentry = &info_dentry
11928+ };
11929+ wkq_err = au_wkq_wait(au_call_drinfo_do_load, &args);
11930+ if (unlikely(wkq_err))
11931+ drinfo = ERR_PTR(wkq_err);
11932+ }
11933+ err = PTR_ERR(drinfo);
11934+ if (IS_ERR_OR_NULL(drinfo))
11935+ goto out;
11936+
11937+ err = 0;
11938+ oldname.len = drinfo->oldnamelen;
11939+ oldname.name = drinfo->oldname;
11940+ if (au_qstreq(w->qname, &oldname)) {
11941+ /* the name is renamed back */
9f237c51 11942+ au_kfree_rcu(drinfo);
8b6a4947
AM
11943+ drinfo = NULL;
11944+
11945+ infopath.dentry = info_dentry;
11946+ infopath.mnt = w->h_ppath.mnt;
11947+ h_dir = d_inode(w->h_ppath.dentry);
11948+ delegated = NULL;
11949+ inode_lock_nested(h_dir, AuLsc_I_PARENT);
11950+ e = vfsub_unlink(h_dir, &infopath, &delegated, !w->no_sio);
11951+ inode_unlock(h_dir);
11952+ if (unlikely(e))
11953+ AuIOErr("ignored %d, %pd2\n", e, &infopath.dentry);
11954+ if (unlikely(e == -EWOULDBLOCK))
11955+ iput(delegated);
11956+ }
9f237c51 11957+ au_kfree_rcu(w->drinfo[bindex]);
8b6a4947
AM
11958+ w->drinfo[bindex] = drinfo;
11959+ dput(info_dentry);
11960+
11961+out:
11962+ AuTraceErr(err);
11963+ return err;
11964+}
11965+
11966+/* ---------------------------------------------------------------------- */
11967+
11968+static void au_dr_lkup_free(struct au_drinfo **drinfo, int n)
11969+{
11970+ struct au_drinfo **p = drinfo;
11971+
11972+ while (n-- > 0)
9f237c51
AM
11973+ au_kfree_rcu(*drinfo++);
11974+ au_kfree_try_rcu(p);
8b6a4947
AM
11975+}
11976+
11977+int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry,
11978+ aufs_bindex_t btgt)
11979+{
11980+ int err, ninfo;
11981+ struct au_drinfo_load w;
11982+ aufs_bindex_t bindex, bbot;
11983+ struct au_branch *br;
11984+ struct inode *h_dir;
11985+ struct au_dr_hino *ent;
11986+ struct super_block *sb;
11987+
11988+ AuDbg("%.*s, name %.*s, whname %.*s, b%d\n",
11989+ AuLNPair(&dentry->d_name), AuLNPair(&lkup->dirren.dr_name),
11990+ AuLNPair(&lkup->whname), btgt);
11991+
11992+ sb = dentry->d_sb;
11993+ bbot = au_sbbot(sb);
11994+ w.ninfo = bbot + 1;
11995+ if (!lkup->dirren.drinfo) {
11996+ lkup->dirren.drinfo = kcalloc(w.ninfo,
11997+ sizeof(*lkup->dirren.drinfo),
11998+ GFP_NOFS);
11999+ if (unlikely(!lkup->dirren.drinfo)) {
12000+ err = -ENOMEM;
12001+ goto out;
12002+ }
12003+ lkup->dirren.ninfo = w.ninfo;
12004+ }
12005+ w.drinfo = lkup->dirren.drinfo;
12006+ w.no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID);
12007+ w.h_ppath.dentry = au_h_dptr(dentry, btgt);
12008+ AuDebugOn(!w.h_ppath.dentry);
12009+ w.h_ppath.mnt = au_sbr_mnt(sb, btgt);
12010+ w.qname = &dentry->d_name;
12011+
12012+ ninfo = 0;
12013+ for (bindex = btgt + 1; bindex <= bbot; bindex++) {
12014+ br = au_sbr(sb, bindex);
12015+ err = au_drinfo_load(&w, bindex, br);
12016+ if (unlikely(err))
12017+ goto out_free;
12018+ if (w.drinfo[bindex])
12019+ ninfo++;
12020+ }
12021+ if (!ninfo) {
12022+ br = au_sbr(sb, btgt);
12023+ h_dir = d_inode(w.h_ppath.dentry);
12024+ ent = au_dr_hino_find(&br->br_dirren, h_dir->i_ino);
12025+ AuDebugOn(!ent);
12026+ au_dr_hino_del(&br->br_dirren, ent);
9f237c51 12027+ au_kfree_rcu(ent);
8b6a4947
AM
12028+ }
12029+ goto out; /* success */
12030+
12031+out_free:
12032+ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo);
12033+ lkup->dirren.ninfo = 0;
12034+ lkup->dirren.drinfo = NULL;
12035+out:
12036+ AuTraceErr(err);
12037+ return err;
12038+}
12039+
12040+void au_dr_lkup_fin(struct au_do_lookup_args *lkup)
12041+{
12042+ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo);
12043+}
12044+
12045+int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt)
12046+{
12047+ int err;
12048+ struct au_drinfo *drinfo;
12049+
12050+ err = 0;
12051+ if (!lkup->dirren.drinfo)
12052+ goto out;
43982f53
AM
12053+ AuDebugOn(lkup->dirren.ninfo <= btgt);
12054+ drinfo = lkup->dirren.drinfo[btgt];
8b6a4947
AM
12055+ if (!drinfo)
12056+ goto out;
12057+
9f237c51 12058+ au_kfree_try_rcu(lkup->whname.name);
8b6a4947
AM
12059+ lkup->whname.name = NULL;
12060+ lkup->dirren.dr_name.len = drinfo->oldnamelen;
12061+ lkup->dirren.dr_name.name = drinfo->oldname;
12062+ lkup->name = &lkup->dirren.dr_name;
12063+ err = au_wh_name_alloc(&lkup->whname, lkup->name);
12064+ if (!err)
12065+ AuDbg("name %.*s, whname %.*s, b%d\n",
12066+ AuLNPair(lkup->name), AuLNPair(&lkup->whname),
12067+ btgt);
12068+
12069+out:
12070+ AuTraceErr(err);
12071+ return err;
12072+}
12073+
12074+int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex,
12075+ ino_t h_ino)
12076+{
12077+ int match;
12078+ struct au_drinfo *drinfo;
12079+
12080+ match = 1;
12081+ if (!lkup->dirren.drinfo)
12082+ goto out;
43982f53
AM
12083+ AuDebugOn(lkup->dirren.ninfo <= bindex);
12084+ drinfo = lkup->dirren.drinfo[bindex];
8b6a4947
AM
12085+ if (!drinfo)
12086+ goto out;
12087+
12088+ match = (drinfo->ino == h_ino);
12089+ AuDbg("match %d\n", match);
12090+
12091+out:
12092+ return match;
12093+}
12094+
12095+/* ---------------------------------------------------------------------- */
12096+
12097+int au_dr_opt_set(struct super_block *sb)
12098+{
12099+ int err;
12100+ aufs_bindex_t bindex, bbot;
12101+ struct au_branch *br;
12102+
12103+ err = 0;
12104+ bbot = au_sbbot(sb);
12105+ for (bindex = 0; !err && bindex <= bbot; bindex++) {
12106+ br = au_sbr(sb, bindex);
12107+ err = au_dr_hino(sb, bindex, /*br*/NULL, &br->br_path);
12108+ }
12109+
12110+ return err;
12111+}
12112+
12113+int au_dr_opt_flush(struct super_block *sb)
12114+{
12115+ int err;
12116+ aufs_bindex_t bindex, bbot;
12117+ struct au_branch *br;
12118+
12119+ err = 0;
12120+ bbot = au_sbbot(sb);
12121+ for (bindex = 0; !err && bindex <= bbot; bindex++) {
12122+ br = au_sbr(sb, bindex);
12123+ if (au_br_writable(br->br_perm))
12124+ err = au_dr_hino(sb, bindex, /*br*/NULL, /*path*/NULL);
12125+ }
12126+
12127+ return err;
12128+}
12129+
12130+int au_dr_opt_clr(struct super_block *sb, int no_flush)
12131+{
12132+ int err;
12133+ aufs_bindex_t bindex, bbot;
12134+ struct au_branch *br;
12135+
12136+ err = 0;
12137+ if (!no_flush) {
12138+ err = au_dr_opt_flush(sb);
12139+ if (unlikely(err))
12140+ goto out;
12141+ }
12142+
12143+ bbot = au_sbbot(sb);
12144+ for (bindex = 0; bindex <= bbot; bindex++) {
12145+ br = au_sbr(sb, bindex);
12146+ au_dr_hino_free(&br->br_dirren);
12147+ }
12148+
12149+out:
12150+ return err;
12151+}
12152diff -urN /usr/share/empty/fs/aufs/dirren.h linux/fs/aufs/dirren.h
eca34b5c 12153--- /usr/share/empty/fs/aufs/dirren.h 1970-01-01 01:00:00.000000000 +0100
319657f6 12154+++ linux/fs/aufs/dirren.h 2021-12-03 15:38:59.933313976 +0100
062440b3
AM
12155@@ -0,0 +1,140 @@
12156+/* SPDX-License-Identifier: GPL-2.0 */
8b6a4947 12157+/*
6d176551 12158+ * Copyright (C) 2017-2021 Junjiro R. Okajima
8b6a4947
AM
12159+ *
12160+ * This program, aufs is free software; you can redistribute it and/or modify
12161+ * it under the terms of the GNU General Public License as published by
12162+ * the Free Software Foundation; either version 2 of the License, or
12163+ * (at your option) any later version.
12164+ *
12165+ * This program is distributed in the hope that it will be useful,
12166+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12167+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12168+ * GNU General Public License for more details.
12169+ *
12170+ * You should have received a copy of the GNU General Public License
12171+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
12172+ */
12173+
12174+/*
12175+ * renamed dir info
12176+ */
12177+
12178+#ifndef __AUFS_DIRREN_H__
12179+#define __AUFS_DIRREN_H__
12180+
12181+#ifdef __KERNEL__
12182+
12183+#include <linux/dcache.h>
12184+#include <linux/statfs.h>
12185+#include <linux/uuid.h>
12186+#include "hbl.h"
12187+
12188+#define AuDirren_NHASH 100
12189+
12190+#ifdef CONFIG_AUFS_DIRREN
12191+enum au_brid_type {
12192+ AuBrid_Unset,
12193+ AuBrid_UUID,
12194+ AuBrid_FSID,
12195+ AuBrid_DEV
12196+};
12197+
12198+struct au_dr_brid {
12199+ enum au_brid_type type;
12200+ union {
12201+ uuid_t uuid; /* unimplemented yet */
12202+ fsid_t fsid;
12203+ dev_t dev;
12204+ };
12205+};
12206+
12207+/* 20 is the max digits length of ulong 64 */
12208+/* brid-type "_" uuid "_" inum */
12209+#define AUFS_DIRREN_FNAME_SZ (1 + 1 + UUID_STRING_LEN + 20)
12210+#define AUFS_DIRREN_ENV_VAL_SZ (AUFS_DIRREN_FNAME_SZ + 1 + 20)
12211+
12212+struct au_dr_hino {
12213+ struct hlist_bl_node dr_hnode;
12214+ ino_t dr_h_ino;
12215+};
12216+
12217+struct au_dr_br {
12218+ struct hlist_bl_head dr_h_ino[AuDirren_NHASH];
12219+ struct au_dr_brid dr_brid;
12220+};
12221+
12222+struct au_dr_lookup {
12223+ /* dr_name is pointed by struct au_do_lookup_args.name */
12224+ struct qstr dr_name; /* subset of dr_info */
12225+ aufs_bindex_t ninfo;
12226+ struct au_drinfo **drinfo;
12227+};
12228+#else
12229+struct au_dr_hino;
12230+/* empty */
12231+struct au_dr_br { };
12232+struct au_dr_lookup { };
12233+#endif
12234+
12235+/* ---------------------------------------------------------------------- */
12236+
12237+struct au_branch;
12238+struct au_do_lookup_args;
12239+struct au_hinode;
12240+#ifdef CONFIG_AUFS_DIRREN
12241+int au_dr_hino_test_add(struct au_dr_br *dr, ino_t h_ino,
12242+ struct au_dr_hino *add_ent);
12243+void au_dr_hino_free(struct au_dr_br *dr);
12244+int au_dr_br_init(struct super_block *sb, struct au_branch *br,
12245+ const struct path *path);
12246+int au_dr_br_fin(struct super_block *sb, struct au_branch *br);
12247+int au_dr_rename(struct dentry *src, aufs_bindex_t bindex,
12248+ struct qstr *dst_name, void *_rev);
12249+void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *rev);
12250+void au_dr_rename_rev(struct dentry *src, aufs_bindex_t bindex, void *rev);
12251+int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry,
12252+ aufs_bindex_t bindex);
12253+int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt);
12254+int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex,
12255+ ino_t h_ino);
12256+void au_dr_lkup_fin(struct au_do_lookup_args *lkup);
12257+int au_dr_opt_set(struct super_block *sb);
12258+int au_dr_opt_flush(struct super_block *sb);
12259+int au_dr_opt_clr(struct super_block *sb, int no_flush);
12260+#else
12261+AuStubInt0(au_dr_hino_test_add, struct au_dr_br *dr, ino_t h_ino,
12262+ struct au_dr_hino *add_ent);
12263+AuStubVoid(au_dr_hino_free, struct au_dr_br *dr);
12264+AuStubInt0(au_dr_br_init, struct super_block *sb, struct au_branch *br,
12265+ const struct path *path);
12266+AuStubInt0(au_dr_br_fin, struct super_block *sb, struct au_branch *br);
12267+AuStubInt0(au_dr_rename, struct dentry *src, aufs_bindex_t bindex,
12268+ struct qstr *dst_name, void *_rev);
12269+AuStubVoid(au_dr_rename_fin, struct dentry *src, aufs_bindex_t btgt, void *rev);
12270+AuStubVoid(au_dr_rename_rev, struct dentry *src, aufs_bindex_t bindex,
12271+ void *rev);
12272+AuStubInt0(au_dr_lkup, struct au_do_lookup_args *lkup, struct dentry *dentry,
12273+ aufs_bindex_t bindex);
12274+AuStubInt0(au_dr_lkup_name, struct au_do_lookup_args *lkup, aufs_bindex_t btgt);
12275+AuStubInt0(au_dr_lkup_h_ino, struct au_do_lookup_args *lkup,
12276+ aufs_bindex_t bindex, ino_t h_ino);
12277+AuStubVoid(au_dr_lkup_fin, struct au_do_lookup_args *lkup);
12278+AuStubInt0(au_dr_opt_set, struct super_block *sb);
12279+AuStubInt0(au_dr_opt_flush, struct super_block *sb);
12280+AuStubInt0(au_dr_opt_clr, struct super_block *sb, int no_flush);
12281+#endif
12282+
12283+/* ---------------------------------------------------------------------- */
12284+
12285+#ifdef CONFIG_AUFS_DIRREN
12286+static inline int au_dr_ihash(ino_t h_ino)
12287+{
12288+ return h_ino % AuDirren_NHASH;
12289+}
12290+#else
12291+AuStubInt0(au_dr_ihash, ino_t h_ino);
12292+#endif
12293+
12294+#endif /* __KERNEL__ */
12295+#endif /* __AUFS_DIRREN_H__ */
7f207e10 12296diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
eca34b5c 12297--- /usr/share/empty/fs/aufs/dynop.c 1970-01-01 01:00:00.000000000 +0100
319657f6 12298+++ linux/fs/aufs/dynop.c 2021-12-03 15:38:59.933313976 +0100
e37dd06a 12299@@ -0,0 +1,368 @@
cd7a4cd9 12300+// SPDX-License-Identifier: GPL-2.0
1facf9fc 12301+/*
6d176551 12302+ * Copyright (C) 2010-2021 Junjiro R. Okajima
1facf9fc 12303+ *
12304+ * This program, aufs is free software; you can redistribute it and/or modify
12305+ * it under the terms of the GNU General Public License as published by
12306+ * the Free Software Foundation; either version 2 of the License, or
12307+ * (at your option) any later version.
dece6358
AM
12308+ *
12309+ * This program is distributed in the hope that it will be useful,
12310+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12311+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12312+ * GNU General Public License for more details.
12313+ *
12314+ * You should have received a copy of the GNU General Public License
523b37e3 12315+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 12316+ */
12317+
12318+/*
4a4d8108 12319+ * dynamically customizable operations for regular files
1facf9fc 12320+ */
12321+
1facf9fc 12322+#include "aufs.h"
12323+
4a4d8108 12324+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop)
1facf9fc 12325+
4a4d8108
AM
12326+/*
12327+ * How large will these lists be?
12328+ * Usually just a few elements, 20-30 at most for each, I guess.
12329+ */
8b6a4947 12330+static struct hlist_bl_head dynop[AuDyLast];
4a4d8108 12331+
8b6a4947
AM
12332+static struct au_dykey *dy_gfind_get(struct hlist_bl_head *hbl,
12333+ const void *h_op)
1facf9fc 12334+{
4a4d8108 12335+ struct au_dykey *key, *tmp;
8b6a4947 12336+ struct hlist_bl_node *pos;
1facf9fc 12337+
4a4d8108 12338+ key = NULL;
8b6a4947
AM
12339+ hlist_bl_lock(hbl);
12340+ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode)
4a4d8108 12341+ if (tmp->dk_op.dy_hop == h_op) {
83b672a5
AM
12342+ if (kref_get_unless_zero(&tmp->dk_kref))
12343+ key = tmp;
4a4d8108
AM
12344+ break;
12345+ }
8b6a4947 12346+ hlist_bl_unlock(hbl);
4a4d8108
AM
12347+
12348+ return key;
1facf9fc 12349+}
12350+
4a4d8108 12351+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key)
1facf9fc 12352+{
4a4d8108
AM
12353+ struct au_dykey **k, *found;
12354+ const void *h_op = key->dk_op.dy_hop;
12355+ int i;
1facf9fc 12356+
4a4d8108
AM
12357+ found = NULL;
12358+ k = br->br_dykey;
12359+ for (i = 0; i < AuBrDynOp; i++)
12360+ if (k[i]) {
12361+ if (k[i]->dk_op.dy_hop == h_op) {
12362+ found = k[i];
12363+ break;
12364+ }
12365+ } else
12366+ break;
12367+ if (!found) {
12368+ spin_lock(&br->br_dykey_lock);
12369+ for (; i < AuBrDynOp; i++)
12370+ if (k[i]) {
12371+ if (k[i]->dk_op.dy_hop == h_op) {
12372+ found = k[i];
12373+ break;
12374+ }
12375+ } else {
12376+ k[i] = key;
12377+ break;
12378+ }
12379+ spin_unlock(&br->br_dykey_lock);
12380+ BUG_ON(i == AuBrDynOp); /* expand the array */
12381+ }
12382+
12383+ return found;
1facf9fc 12384+}
12385+
4a4d8108 12386+/* kref_get() if @key is already added */
8b6a4947 12387+static struct au_dykey *dy_gadd(struct hlist_bl_head *hbl, struct au_dykey *key)
4a4d8108
AM
12388+{
12389+ struct au_dykey *tmp, *found;
8b6a4947 12390+ struct hlist_bl_node *pos;
4a4d8108 12391+ const void *h_op = key->dk_op.dy_hop;
1facf9fc 12392+
4a4d8108 12393+ found = NULL;
8b6a4947
AM
12394+ hlist_bl_lock(hbl);
12395+ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode)
4a4d8108 12396+ if (tmp->dk_op.dy_hop == h_op) {
83b672a5
AM
12397+ if (kref_get_unless_zero(&tmp->dk_kref))
12398+ found = tmp;
4a4d8108
AM
12399+ break;
12400+ }
12401+ if (!found)
8b6a4947
AM
12402+ hlist_bl_add_head(&key->dk_hnode, hbl);
12403+ hlist_bl_unlock(hbl);
1facf9fc 12404+
4a4d8108
AM
12405+ if (!found)
12406+ DyPrSym(key);
12407+ return found;
12408+}
12409+
12410+static void dy_free_rcu(struct rcu_head *rcu)
1facf9fc 12411+{
4a4d8108
AM
12412+ struct au_dykey *key;
12413+
12414+ key = container_of(rcu, struct au_dykey, dk_rcu);
12415+ DyPrSym(key);
83b672a5 12416+ kfree(key);
1facf9fc 12417+}
12418+
4a4d8108
AM
12419+static void dy_free(struct kref *kref)
12420+{
12421+ struct au_dykey *key;
8b6a4947 12422+ struct hlist_bl_head *hbl;
1facf9fc 12423+
4a4d8108 12424+ key = container_of(kref, struct au_dykey, dk_kref);
8b6a4947
AM
12425+ hbl = dynop + key->dk_op.dy_type;
12426+ au_hbl_del(&key->dk_hnode, hbl);
4a4d8108
AM
12427+ call_rcu(&key->dk_rcu, dy_free_rcu);
12428+}
12429+
12430+void au_dy_put(struct au_dykey *key)
1facf9fc 12431+{
4a4d8108
AM
12432+ kref_put(&key->dk_kref, dy_free);
12433+}
1facf9fc 12434+
4a4d8108
AM
12435+/* ---------------------------------------------------------------------- */
12436+
12437+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *))
12438+
12439+#ifdef CONFIG_AUFS_DEBUG
12440+#define DyDbgDeclare(cnt) unsigned int cnt = 0
4f0767ce 12441+#define DyDbgInc(cnt) do { cnt++; } while (0)
4a4d8108
AM
12442+#else
12443+#define DyDbgDeclare(cnt) do {} while (0)
12444+#define DyDbgInc(cnt) do {} while (0)
12445+#endif
12446+
12447+#define DySet(func, dst, src, h_op, h_sb) do { \
12448+ DyDbgInc(cnt); \
12449+ if (h_op->func) { \
12450+ if (src.func) \
12451+ dst.func = src.func; \
12452+ else \
12453+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \
12454+ } \
12455+} while (0)
12456+
12457+#define DySetForce(func, dst, src) do { \
12458+ AuDebugOn(!src.func); \
12459+ DyDbgInc(cnt); \
12460+ dst.func = src.func; \
12461+} while (0)
12462+
12463+#define DySetAop(func) \
12464+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
12465+#define DySetAopForce(func) \
12466+ DySetForce(func, dyaop->da_op, aufs_aop)
12467+
12468+static void dy_aop(struct au_dykey *key, const void *h_op,
12469+ struct super_block *h_sb __maybe_unused)
12470+{
12471+ struct au_dyaop *dyaop = (void *)key;
12472+ const struct address_space_operations *h_aop = h_op;
12473+ DyDbgDeclare(cnt);
12474+
12475+ AuDbg("%s\n", au_sbtype(h_sb));
12476+
12477+ DySetAop(writepage);
12478+ DySetAopForce(readpage); /* force */
4a4d8108
AM
12479+ DySetAop(writepages);
12480+ DySetAop(set_page_dirty);
12481+ DySetAop(readpages);
e37dd06a 12482+ DySetAop(readahead);
4a4d8108
AM
12483+ DySetAop(write_begin);
12484+ DySetAop(write_end);
12485+ DySetAop(bmap);
12486+ DySetAop(invalidatepage);
12487+ DySetAop(releasepage);
027c5e7a 12488+ DySetAop(freepage);
7e9cd9fe 12489+ /* this one will be changed according to an aufs mount option */
4a4d8108 12490+ DySetAop(direct_IO);
4a4d8108 12491+ DySetAop(migratepage);
e2f27e51
AM
12492+ DySetAop(isolate_page);
12493+ DySetAop(putback_page);
4a4d8108
AM
12494+ DySetAop(launder_page);
12495+ DySetAop(is_partially_uptodate);
392086de 12496+ DySetAop(is_dirty_writeback);
4a4d8108 12497+ DySetAop(error_remove_page);
b4510431
AM
12498+ DySetAop(swap_activate);
12499+ DySetAop(swap_deactivate);
4a4d8108
AM
12500+
12501+ DyDbgSize(cnt, *h_aop);
4a4d8108
AM
12502+}
12503+
4a4d8108
AM
12504+/* ---------------------------------------------------------------------- */
12505+
12506+static void dy_bug(struct kref *kref)
12507+{
12508+ BUG();
12509+}
12510+
12511+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
12512+{
12513+ struct au_dykey *key, *old;
8b6a4947 12514+ struct hlist_bl_head *hbl;
b752ccd1 12515+ struct op {
4a4d8108 12516+ unsigned int sz;
b752ccd1
AM
12517+ void (*set)(struct au_dykey *key, const void *h_op,
12518+ struct super_block *h_sb __maybe_unused);
12519+ };
12520+ static const struct op a[] = {
4a4d8108
AM
12521+ [AuDy_AOP] = {
12522+ .sz = sizeof(struct au_dyaop),
b752ccd1 12523+ .set = dy_aop
4a4d8108 12524+ }
b752ccd1
AM
12525+ };
12526+ const struct op *p;
4a4d8108 12527+
8b6a4947
AM
12528+ hbl = dynop + op->dy_type;
12529+ key = dy_gfind_get(hbl, op->dy_hop);
4a4d8108
AM
12530+ if (key)
12531+ goto out_add; /* success */
12532+
12533+ p = a + op->dy_type;
12534+ key = kzalloc(p->sz, GFP_NOFS);
12535+ if (unlikely(!key)) {
12536+ key = ERR_PTR(-ENOMEM);
12537+ goto out;
12538+ }
12539+
12540+ key->dk_op.dy_hop = op->dy_hop;
12541+ kref_init(&key->dk_kref);
86dc4139 12542+ p->set(key, op->dy_hop, au_br_sb(br));
8b6a4947 12543+ old = dy_gadd(hbl, key);
4a4d8108 12544+ if (old) {
9f237c51 12545+ au_kfree_rcu(key);
4a4d8108
AM
12546+ key = old;
12547+ }
12548+
12549+out_add:
12550+ old = dy_bradd(br, key);
12551+ if (old)
12552+ /* its ref-count should never be zero here */
12553+ kref_put(&key->dk_kref, dy_bug);
12554+out:
12555+ return key;
12556+}
12557+
12558+/* ---------------------------------------------------------------------- */
12559+/*
acd2b654 12560+ * Aufs prohibits O_DIRECT by default even if the branch supports it.
c1595e42 12561+ * This behaviour is necessary to return an error from open(O_DIRECT) instead
4a4d8108
AM
12562+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
12563+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
12564+ * See the aufs manual in detail.
4a4d8108
AM
12565+ */
12566+static void dy_adx(struct au_dyaop *dyaop, int do_dx)
12567+{
7e9cd9fe 12568+ if (!do_dx)
4a4d8108 12569+ dyaop->da_op.direct_IO = NULL;
7e9cd9fe 12570+ else
4a4d8108 12571+ dyaop->da_op.direct_IO = aufs_aop.direct_IO;
4a4d8108
AM
12572+}
12573+
12574+static struct au_dyaop *dy_aget(struct au_branch *br,
12575+ const struct address_space_operations *h_aop,
12576+ int do_dx)
12577+{
12578+ struct au_dyaop *dyaop;
12579+ struct au_dynop op;
12580+
12581+ op.dy_type = AuDy_AOP;
12582+ op.dy_haop = h_aop;
12583+ dyaop = (void *)dy_get(&op, br);
12584+ if (IS_ERR(dyaop))
12585+ goto out;
12586+ dy_adx(dyaop, do_dx);
12587+
12588+out:
12589+ return dyaop;
12590+}
12591+
12592+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
12593+ struct inode *h_inode)
12594+{
12595+ int err, do_dx;
12596+ struct super_block *sb;
12597+ struct au_branch *br;
12598+ struct au_dyaop *dyaop;
12599+
12600+ AuDebugOn(!S_ISREG(h_inode->i_mode));
12601+ IiMustWriteLock(inode);
12602+
12603+ sb = inode->i_sb;
12604+ br = au_sbr(sb, bindex);
12605+ do_dx = !!au_opt_test(au_mntflags(sb), DIO);
12606+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx);
12607+ err = PTR_ERR(dyaop);
12608+ if (IS_ERR(dyaop))
12609+ /* unnecessary to call dy_fput() */
12610+ goto out;
12611+
12612+ err = 0;
12613+ inode->i_mapping->a_ops = &dyaop->da_op;
12614+
12615+out:
12616+ return err;
12617+}
12618+
b752ccd1
AM
12619+/*
12620+ * Is it safe to replace a_ops during the inode/file is in operation?
12621+ * Yes, I hope so.
12622+ */
12623+int au_dy_irefresh(struct inode *inode)
12624+{
12625+ int err;
5afbbe0d 12626+ aufs_bindex_t btop;
b752ccd1
AM
12627+ struct inode *h_inode;
12628+
12629+ err = 0;
12630+ if (S_ISREG(inode->i_mode)) {
5afbbe0d
AM
12631+ btop = au_ibtop(inode);
12632+ h_inode = au_h_iptr(inode, btop);
12633+ err = au_dy_iaop(inode, btop, h_inode);
b752ccd1
AM
12634+ }
12635+ return err;
12636+}
12637+
4a4d8108
AM
12638+void au_dy_arefresh(int do_dx)
12639+{
8b6a4947
AM
12640+ struct hlist_bl_head *hbl;
12641+ struct hlist_bl_node *pos;
4a4d8108
AM
12642+ struct au_dykey *key;
12643+
8b6a4947
AM
12644+ hbl = dynop + AuDy_AOP;
12645+ hlist_bl_lock(hbl);
12646+ hlist_bl_for_each_entry(key, pos, hbl, dk_hnode)
4a4d8108 12647+ dy_adx((void *)key, do_dx);
8b6a4947 12648+ hlist_bl_unlock(hbl);
4a4d8108
AM
12649+}
12650+
4a4d8108
AM
12651+/* ---------------------------------------------------------------------- */
12652+
12653+void __init au_dy_init(void)
12654+{
12655+ int i;
12656+
4a4d8108 12657+ for (i = 0; i < AuDyLast; i++)
8b6a4947 12658+ INIT_HLIST_BL_HEAD(dynop + i);
4a4d8108
AM
12659+}
12660+
12661+void au_dy_fin(void)
12662+{
12663+ int i;
12664+
12665+ for (i = 0; i < AuDyLast; i++)
8b6a4947 12666+ WARN_ON(!hlist_bl_empty(dynop + i));
4a4d8108 12667+}
7f207e10 12668diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
eca34b5c 12669--- /usr/share/empty/fs/aufs/dynop.h 1970-01-01 01:00:00.000000000 +0100
319657f6 12670+++ linux/fs/aufs/dynop.h 2021-12-03 15:38:59.933313976 +0100
fbc438ed 12671@@ -0,0 +1,77 @@
062440b3 12672+/* SPDX-License-Identifier: GPL-2.0 */
4a4d8108 12673+/*
6d176551 12674+ * Copyright (C) 2010-2021 Junjiro R. Okajima
4a4d8108
AM
12675+ *
12676+ * This program, aufs is free software; you can redistribute it and/or modify
12677+ * it under the terms of the GNU General Public License as published by
12678+ * the Free Software Foundation; either version 2 of the License, or
12679+ * (at your option) any later version.
12680+ *
12681+ * This program is distributed in the hope that it will be useful,
12682+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12683+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12684+ * GNU General Public License for more details.
12685+ *
12686+ * You should have received a copy of the GNU General Public License
523b37e3 12687+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
12688+ */
12689+
12690+/*
12691+ * dynamically customizable operations (for regular files only)
12692+ */
12693+
12694+#ifndef __AUFS_DYNOP_H__
12695+#define __AUFS_DYNOP_H__
12696+
12697+#ifdef __KERNEL__
12698+
7e9cd9fe
AM
12699+#include <linux/fs.h>
12700+#include <linux/kref.h>
4a4d8108 12701+
2cbb1c4b 12702+enum {AuDy_AOP, AuDyLast};
4a4d8108
AM
12703+
12704+struct au_dynop {
12705+ int dy_type;
12706+ union {
12707+ const void *dy_hop;
12708+ const struct address_space_operations *dy_haop;
4a4d8108
AM
12709+ };
12710+};
12711+
12712+struct au_dykey {
12713+ union {
8b6a4947 12714+ struct hlist_bl_node dk_hnode;
4a4d8108
AM
12715+ struct rcu_head dk_rcu;
12716+ };
12717+ struct au_dynop dk_op;
12718+
12719+ /*
12720+ * during I am in the branch local array, kref is gotten. when the
12721+ * branch is removed, kref is put.
12722+ */
12723+ struct kref dk_kref;
12724+};
12725+
12726+/* stop unioning since their sizes are very different from each other */
12727+struct au_dyaop {
12728+ struct au_dykey da_key;
12729+ struct address_space_operations da_op; /* not const */
4a4d8108 12730+};
fbc438ed
JR
12731+/* make sure that 'struct au_dykey *' can be any type */
12732+static_assert(!offsetof(struct au_dyaop, da_key));
4a4d8108 12733+
4a4d8108
AM
12734+/* ---------------------------------------------------------------------- */
12735+
12736+/* dynop.c */
12737+struct au_branch;
12738+void au_dy_put(struct au_dykey *key);
12739+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
12740+ struct inode *h_inode);
b752ccd1 12741+int au_dy_irefresh(struct inode *inode);
4a4d8108 12742+void au_dy_arefresh(int do_dio);
4a4d8108
AM
12743+
12744+void __init au_dy_init(void);
12745+void au_dy_fin(void);
12746+
4a4d8108
AM
12747+#endif /* __KERNEL__ */
12748+#endif /* __AUFS_DYNOP_H__ */
7f207e10 12749diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
eca34b5c 12750--- /usr/share/empty/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
319657f6 12751+++ linux/fs/aufs/export.c 2021-12-03 15:40:58.233313963 +0100
758e9dad 12752@@ -0,0 +1,831 @@
cd7a4cd9 12753+// SPDX-License-Identifier: GPL-2.0
4a4d8108 12754+/*
6d176551 12755+ * Copyright (C) 2005-2021 Junjiro R. Okajima
4a4d8108
AM
12756+ *
12757+ * This program, aufs is free software; you can redistribute it and/or modify
12758+ * it under the terms of the GNU General Public License as published by
12759+ * the Free Software Foundation; either version 2 of the License, or
12760+ * (at your option) any later version.
12761+ *
12762+ * This program is distributed in the hope that it will be useful,
12763+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12764+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12765+ * GNU General Public License for more details.
12766+ *
12767+ * You should have received a copy of the GNU General Public License
523b37e3 12768+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
12769+ */
12770+
12771+/*
12772+ * export via nfs
12773+ */
12774+
12775+#include <linux/exportfs.h>
7eafdf33 12776+#include <linux/fs_struct.h>
4a4d8108
AM
12777+#include <linux/namei.h>
12778+#include <linux/nsproxy.h>
12779+#include <linux/random.h>
12780+#include <linux/writeback.h>
12781+#include "aufs.h"
12782+
12783+union conv {
12784+#ifdef CONFIG_AUFS_INO_T_64
12785+ __u32 a[2];
12786+#else
12787+ __u32 a[1];
12788+#endif
12789+ ino_t ino;
12790+};
12791+
12792+static ino_t decode_ino(__u32 *a)
12793+{
12794+ union conv u;
12795+
12796+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
12797+ u.a[0] = a[0];
12798+#ifdef CONFIG_AUFS_INO_T_64
12799+ u.a[1] = a[1];
12800+#endif
12801+ return u.ino;
12802+}
12803+
12804+static void encode_ino(__u32 *a, ino_t ino)
12805+{
12806+ union conv u;
12807+
12808+ u.ino = ino;
12809+ a[0] = u.a[0];
12810+#ifdef CONFIG_AUFS_INO_T_64
12811+ a[1] = u.a[1];
12812+#endif
12813+}
12814+
12815+/* NFS file handle */
12816+enum {
12817+ Fh_br_id,
12818+ Fh_sigen,
12819+#ifdef CONFIG_AUFS_INO_T_64
12820+ /* support 64bit inode number */
12821+ Fh_ino1,
12822+ Fh_ino2,
12823+ Fh_dir_ino1,
12824+ Fh_dir_ino2,
12825+#else
12826+ Fh_ino1,
12827+ Fh_dir_ino1,
12828+#endif
12829+ Fh_igen,
12830+ Fh_h_type,
12831+ Fh_tail,
12832+
12833+ Fh_ino = Fh_ino1,
12834+ Fh_dir_ino = Fh_dir_ino1
12835+};
12836+
12837+static int au_test_anon(struct dentry *dentry)
12838+{
027c5e7a 12839+ /* note: read d_flags without d_lock */
4a4d8108
AM
12840+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
12841+}
12842+
a2a7ad62
AM
12843+int au_test_nfsd(void)
12844+{
12845+ int ret;
12846+ struct task_struct *tsk = current;
12847+ char comm[sizeof(tsk->comm)];
12848+
12849+ ret = 0;
12850+ if (tsk->flags & PF_KTHREAD) {
12851+ get_task_comm(comm, tsk);
12852+ ret = !strcmp(comm, "nfsd");
12853+ }
12854+
12855+ return ret;
12856+}
12857+
4a4d8108
AM
12858+/* ---------------------------------------------------------------------- */
12859+/* inode generation external table */
12860+
b752ccd1 12861+void au_xigen_inc(struct inode *inode)
4a4d8108 12862+{
4a4d8108
AM
12863+ loff_t pos;
12864+ ssize_t sz;
12865+ __u32 igen;
12866+ struct super_block *sb;
12867+ struct au_sbinfo *sbinfo;
12868+
4a4d8108 12869+ sb = inode->i_sb;
b752ccd1 12870+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
1facf9fc 12871+
b752ccd1 12872+ sbinfo = au_sbi(sb);
1facf9fc 12873+ pos = inode->i_ino;
12874+ pos *= sizeof(igen);
12875+ igen = inode->i_generation + 1;
e37dd06a 12876+ sz = xino_fwrite(sbinfo->si_xigen, &igen, sizeof(igen), &pos);
1facf9fc 12877+ if (sz == sizeof(igen))
b752ccd1 12878+ return; /* success */
1facf9fc 12879+
b752ccd1 12880+ if (unlikely(sz >= 0))
1facf9fc 12881+ AuIOErr("xigen error (%zd)\n", sz);
1facf9fc 12882+}
12883+
12884+int au_xigen_new(struct inode *inode)
12885+{
12886+ int err;
12887+ loff_t pos;
12888+ ssize_t sz;
12889+ struct super_block *sb;
12890+ struct au_sbinfo *sbinfo;
12891+ struct file *file;
12892+
12893+ err = 0;
12894+ /* todo: dirty, at mount time */
12895+ if (inode->i_ino == AUFS_ROOT_INO)
12896+ goto out;
12897+ sb = inode->i_sb;
dece6358 12898+ SiMustAnyLock(sb);
1facf9fc 12899+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
12900+ goto out;
12901+
12902+ err = -EFBIG;
12903+ pos = inode->i_ino;
12904+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
12905+ AuIOErr1("too large i%lld\n", pos);
12906+ goto out;
12907+ }
12908+ pos *= sizeof(inode->i_generation);
12909+
12910+ err = 0;
12911+ sbinfo = au_sbi(sb);
12912+ file = sbinfo->si_xigen;
12913+ BUG_ON(!file);
12914+
c06a8ce3 12915+ if (vfsub_f_size_read(file)
1facf9fc 12916+ < pos + sizeof(inode->i_generation)) {
12917+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
e37dd06a 12918+ sz = xino_fwrite(file, &inode->i_generation,
1facf9fc 12919+ sizeof(inode->i_generation), &pos);
12920+ } else
e37dd06a 12921+ sz = xino_fread(file, &inode->i_generation,
1facf9fc 12922+ sizeof(inode->i_generation), &pos);
12923+ if (sz == sizeof(inode->i_generation))
12924+ goto out; /* success */
12925+
12926+ err = sz;
12927+ if (unlikely(sz >= 0)) {
12928+ err = -EIO;
12929+ AuIOErr("xigen error (%zd)\n", sz);
12930+ }
12931+
4f0767ce 12932+out:
1facf9fc 12933+ return err;
12934+}
12935+
062440b3 12936+int au_xigen_set(struct super_block *sb, struct path *path)
1facf9fc 12937+{
12938+ int err;
12939+ struct au_sbinfo *sbinfo;
12940+ struct file *file;
12941+
dece6358
AM
12942+ SiMustWriteLock(sb);
12943+
1facf9fc 12944+ sbinfo = au_sbi(sb);
062440b3 12945+ file = au_xino_create2(sb, path, sbinfo->si_xigen);
1facf9fc 12946+ err = PTR_ERR(file);
12947+ if (IS_ERR(file))
12948+ goto out;
12949+ err = 0;
12950+ if (sbinfo->si_xigen)
12951+ fput(sbinfo->si_xigen);
12952+ sbinfo->si_xigen = file;
12953+
4f0767ce 12954+out:
062440b3 12955+ AuTraceErr(err);
1facf9fc 12956+ return err;
12957+}
12958+
12959+void au_xigen_clr(struct super_block *sb)
12960+{
12961+ struct au_sbinfo *sbinfo;
12962+
dece6358
AM
12963+ SiMustWriteLock(sb);
12964+
1facf9fc 12965+ sbinfo = au_sbi(sb);
12966+ if (sbinfo->si_xigen) {
12967+ fput(sbinfo->si_xigen);
12968+ sbinfo->si_xigen = NULL;
12969+ }
12970+}
12971+
12972+/* ---------------------------------------------------------------------- */
12973+
12974+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
12975+ ino_t dir_ino)
12976+{
12977+ struct dentry *dentry, *d;
12978+ struct inode *inode;
12979+ unsigned int sigen;
12980+
12981+ dentry = NULL;
12982+ inode = ilookup(sb, ino);
12983+ if (!inode)
12984+ goto out;
12985+
12986+ dentry = ERR_PTR(-ESTALE);
12987+ sigen = au_sigen(sb);
5afbbe0d 12988+ if (unlikely(au_is_bad_inode(inode)
1facf9fc 12989+ || IS_DEADDIR(inode)
537831f9 12990+ || sigen != au_iigen(inode, NULL)))
1facf9fc 12991+ goto out_iput;
12992+
12993+ dentry = NULL;
12994+ if (!dir_ino || S_ISDIR(inode->i_mode))
12995+ dentry = d_find_alias(inode);
12996+ else {
027c5e7a 12997+ spin_lock(&inode->i_lock);
c1595e42 12998+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) {
027c5e7a 12999+ spin_lock(&d->d_lock);
1facf9fc 13000+ if (!au_test_anon(d)
5527c038 13001+ && d_inode(d->d_parent)->i_ino == dir_ino) {
027c5e7a
AM
13002+ dentry = dget_dlock(d);
13003+ spin_unlock(&d->d_lock);
1facf9fc 13004+ break;
13005+ }
027c5e7a
AM
13006+ spin_unlock(&d->d_lock);
13007+ }
13008+ spin_unlock(&inode->i_lock);
1facf9fc 13009+ }
027c5e7a 13010+ if (unlikely(dentry && au_digen_test(dentry, sigen))) {
2cbb1c4b 13011+ /* need to refresh */
1facf9fc 13012+ dput(dentry);
2cbb1c4b 13013+ dentry = NULL;
1facf9fc 13014+ }
13015+
4f0767ce 13016+out_iput:
1facf9fc 13017+ iput(inode);
4f0767ce 13018+out:
2cbb1c4b 13019+ AuTraceErrPtr(dentry);
1facf9fc 13020+ return dentry;
13021+}
13022+
13023+/* ---------------------------------------------------------------------- */
13024+
13025+/* todo: dirty? */
13026+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
4a4d8108
AM
13027+
13028+struct au_compare_mnt_args {
13029+ /* input */
13030+ struct super_block *sb;
13031+
13032+ /* output */
13033+ struct vfsmount *mnt;
13034+};
13035+
13036+static int au_compare_mnt(struct vfsmount *mnt, void *arg)
13037+{
13038+ struct au_compare_mnt_args *a = arg;
13039+
13040+ if (mnt->mnt_sb != a->sb)
13041+ return 0;
13042+ a->mnt = mntget(mnt);
13043+ return 1;
13044+}
13045+
1facf9fc 13046+static struct vfsmount *au_mnt_get(struct super_block *sb)
13047+{
4a4d8108 13048+ int err;
7eafdf33 13049+ struct path root;
4a4d8108
AM
13050+ struct au_compare_mnt_args args = {
13051+ .sb = sb
13052+ };
1facf9fc 13053+
7eafdf33 13054+ get_fs_root(current->fs, &root);
523b37e3 13055+ rcu_read_lock();
7eafdf33 13056+ err = iterate_mounts(au_compare_mnt, &args, root.mnt);
523b37e3 13057+ rcu_read_unlock();
7eafdf33 13058+ path_put(&root);
4a4d8108
AM
13059+ AuDebugOn(!err);
13060+ AuDebugOn(!args.mnt);
13061+ return args.mnt;
1facf9fc 13062+}
13063+
13064+struct au_nfsd_si_lock {
4a4d8108 13065+ unsigned int sigen;
027c5e7a 13066+ aufs_bindex_t bindex, br_id;
1facf9fc 13067+ unsigned char force_lock;
13068+};
13069+
027c5e7a
AM
13070+static int si_nfsd_read_lock(struct super_block *sb,
13071+ struct au_nfsd_si_lock *nsi_lock)
1facf9fc 13072+{
027c5e7a 13073+ int err;
1facf9fc 13074+ aufs_bindex_t bindex;
13075+
13076+ si_read_lock(sb, AuLock_FLUSH);
13077+
13078+ /* branch id may be wrapped around */
027c5e7a 13079+ err = 0;
1facf9fc 13080+ bindex = au_br_index(sb, nsi_lock->br_id);
13081+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
13082+ goto out; /* success */
13083+
027c5e7a
AM
13084+ err = -ESTALE;
13085+ bindex = -1;
1facf9fc 13086+ if (!nsi_lock->force_lock)
13087+ si_read_unlock(sb);
1facf9fc 13088+
4f0767ce 13089+out:
027c5e7a
AM
13090+ nsi_lock->bindex = bindex;
13091+ return err;
1facf9fc 13092+}
13093+
13094+struct find_name_by_ino {
392086de 13095+ struct dir_context ctx;
1facf9fc 13096+ int called, found;
13097+ ino_t ino;
13098+ char *name;
13099+ int namelen;
13100+};
13101+
13102+static int
392086de
AM
13103+find_name_by_ino(struct dir_context *ctx, const char *name, int namelen,
13104+ loff_t offset, u64 ino, unsigned int d_type)
1facf9fc 13105+{
392086de
AM
13106+ struct find_name_by_ino *a = container_of(ctx, struct find_name_by_ino,
13107+ ctx);
1facf9fc 13108+
13109+ a->called++;
13110+ if (a->ino != ino)
13111+ return 0;
13112+
13113+ memcpy(a->name, name, namelen);
13114+ a->namelen = namelen;
13115+ a->found = 1;
13116+ return 1;
13117+}
13118+
13119+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
13120+ struct au_nfsd_si_lock *nsi_lock)
13121+{
13122+ struct dentry *dentry, *parent;
13123+ struct file *file;
13124+ struct inode *dir;
392086de
AM
13125+ struct find_name_by_ino arg = {
13126+ .ctx = {
2000de60 13127+ .actor = find_name_by_ino
392086de
AM
13128+ }
13129+ };
1facf9fc 13130+ int err;
13131+
13132+ parent = path->dentry;
13133+ if (nsi_lock)
13134+ si_read_unlock(parent->d_sb);
4a4d8108 13135+ file = vfsub_dentry_open(path, au_dir_roflags);
1facf9fc 13136+ dentry = (void *)file;
13137+ if (IS_ERR(file))
13138+ goto out;
13139+
13140+ dentry = ERR_PTR(-ENOMEM);
537831f9 13141+ arg.name = (void *)__get_free_page(GFP_NOFS);
1facf9fc 13142+ if (unlikely(!arg.name))
13143+ goto out_file;
13144+ arg.ino = ino;
13145+ arg.found = 0;
13146+ do {
13147+ arg.called = 0;
13148+ /* smp_mb(); */
392086de 13149+ err = vfsub_iterate_dir(file, &arg.ctx);
1facf9fc 13150+ } while (!err && !arg.found && arg.called);
13151+ dentry = ERR_PTR(err);
13152+ if (unlikely(err))
13153+ goto out_name;
1716fcea
AM
13154+ /* instead of ENOENT */
13155+ dentry = ERR_PTR(-ESTALE);
1facf9fc 13156+ if (!arg.found)
13157+ goto out_name;
13158+
b4510431 13159+ /* do not call vfsub_lkup_one() */
5527c038 13160+ dir = d_inode(parent);
758e9dad 13161+ dentry = vfsub_lookup_one_len_unlocked(arg.name, path, arg.namelen);
1facf9fc 13162+ AuTraceErrPtr(dentry);
13163+ if (IS_ERR(dentry))
13164+ goto out_name;
13165+ AuDebugOn(au_test_anon(dentry));
5527c038 13166+ if (unlikely(d_really_is_negative(dentry))) {
1facf9fc 13167+ dput(dentry);
13168+ dentry = ERR_PTR(-ENOENT);
13169+ }
13170+
4f0767ce 13171+out_name:
1c60b727 13172+ free_page((unsigned long)arg.name);
4f0767ce 13173+out_file:
1facf9fc 13174+ fput(file);
4f0767ce 13175+out:
1facf9fc 13176+ if (unlikely(nsi_lock
13177+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
13178+ if (!IS_ERR(dentry)) {
13179+ dput(dentry);
13180+ dentry = ERR_PTR(-ESTALE);
13181+ }
13182+ AuTraceErrPtr(dentry);
13183+ return dentry;
13184+}
13185+
13186+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
13187+ ino_t dir_ino,
13188+ struct au_nfsd_si_lock *nsi_lock)
13189+{
13190+ struct dentry *dentry;
13191+ struct path path;
13192+
13193+ if (dir_ino != AUFS_ROOT_INO) {
13194+ path.dentry = decode_by_ino(sb, dir_ino, 0);
13195+ dentry = path.dentry;
13196+ if (!path.dentry || IS_ERR(path.dentry))
13197+ goto out;
13198+ AuDebugOn(au_test_anon(path.dentry));
13199+ } else
13200+ path.dentry = dget(sb->s_root);
13201+
13202+ path.mnt = au_mnt_get(sb);
13203+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
13204+ path_put(&path);
13205+
4f0767ce 13206+out:
1facf9fc 13207+ AuTraceErrPtr(dentry);
13208+ return dentry;
13209+}
13210+
13211+/* ---------------------------------------------------------------------- */
13212+
13213+static int h_acceptable(void *expv, struct dentry *dentry)
13214+{
13215+ return 1;
13216+}
13217+
13218+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
13219+ char *buf, int len, struct super_block *sb)
13220+{
13221+ char *p;
13222+ int n;
13223+ struct path path;
13224+
13225+ p = d_path(h_rootpath, buf, len);
13226+ if (IS_ERR(p))
13227+ goto out;
13228+ n = strlen(p);
13229+
13230+ path.mnt = h_rootpath->mnt;
13231+ path.dentry = h_parent;
13232+ p = d_path(&path, buf, len);
13233+ if (IS_ERR(p))
13234+ goto out;
13235+ if (n != 1)
13236+ p += n;
13237+
13238+ path.mnt = au_mnt_get(sb);
13239+ path.dentry = sb->s_root;
13240+ p = d_path(&path, buf, len - strlen(p));
13241+ mntput(path.mnt);
13242+ if (IS_ERR(p))
13243+ goto out;
13244+ if (n != 1)
13245+ p[strlen(p)] = '/';
13246+
4f0767ce 13247+out:
1facf9fc 13248+ AuTraceErrPtr(p);
13249+ return p;
13250+}
13251+
13252+static
027c5e7a
AM
13253+struct dentry *decode_by_path(struct super_block *sb, ino_t ino, __u32 *fh,
13254+ int fh_len, struct au_nfsd_si_lock *nsi_lock)
1facf9fc 13255+{
13256+ struct dentry *dentry, *h_parent, *root;
13257+ struct super_block *h_sb;
13258+ char *pathname, *p;
13259+ struct vfsmount *h_mnt;
13260+ struct au_branch *br;
13261+ int err;
13262+ struct path path;
13263+
027c5e7a 13264+ br = au_sbr(sb, nsi_lock->bindex);
86dc4139 13265+ h_mnt = au_br_mnt(br);
1facf9fc 13266+ h_sb = h_mnt->mnt_sb;
13267+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
5afbbe0d 13268+ lockdep_off();
1facf9fc 13269+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
13270+ fh_len - Fh_tail, fh[Fh_h_type],
13271+ h_acceptable, /*context*/NULL);
5afbbe0d 13272+ lockdep_on();
1facf9fc 13273+ dentry = h_parent;
13274+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
13275+ AuWarn1("%s decode_fh failed, %ld\n",
13276+ au_sbtype(h_sb), PTR_ERR(h_parent));
13277+ goto out;
13278+ }
13279+ dentry = NULL;
13280+ if (unlikely(au_test_anon(h_parent))) {
13281+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
13282+ au_sbtype(h_sb));
13283+ goto out_h_parent;
13284+ }
13285+
13286+ dentry = ERR_PTR(-ENOMEM);
13287+ pathname = (void *)__get_free_page(GFP_NOFS);
13288+ if (unlikely(!pathname))
13289+ goto out_h_parent;
13290+
13291+ root = sb->s_root;
13292+ path.mnt = h_mnt;
13293+ di_read_lock_parent(root, !AuLock_IR);
027c5e7a 13294+ path.dentry = au_h_dptr(root, nsi_lock->bindex);
1facf9fc 13295+ di_read_unlock(root, !AuLock_IR);
13296+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
13297+ dentry = (void *)p;
13298+ if (IS_ERR(p))
13299+ goto out_pathname;
13300+
13301+ si_read_unlock(sb);
13302+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
13303+ dentry = ERR_PTR(err);
13304+ if (unlikely(err))
13305+ goto out_relock;
13306+
13307+ dentry = ERR_PTR(-ENOENT);
13308+ AuDebugOn(au_test_anon(path.dentry));
5527c038 13309+ if (unlikely(d_really_is_negative(path.dentry)))
1facf9fc 13310+ goto out_path;
13311+
5527c038 13312+ if (ino != d_inode(path.dentry)->i_ino)
1facf9fc 13313+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
13314+ else
13315+ dentry = dget(path.dentry);
13316+
4f0767ce 13317+out_path:
1facf9fc 13318+ path_put(&path);
4f0767ce 13319+out_relock:
1facf9fc 13320+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
13321+ if (!IS_ERR(dentry)) {
13322+ dput(dentry);
13323+ dentry = ERR_PTR(-ESTALE);
13324+ }
4f0767ce 13325+out_pathname:
1c60b727 13326+ free_page((unsigned long)pathname);
4f0767ce 13327+out_h_parent:
1facf9fc 13328+ dput(h_parent);
4f0767ce 13329+out:
1facf9fc 13330+ AuTraceErrPtr(dentry);
13331+ return dentry;
13332+}
13333+
13334+/* ---------------------------------------------------------------------- */
13335+
13336+static struct dentry *
13337+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
13338+ int fh_type)
13339+{
13340+ struct dentry *dentry;
13341+ __u32 *fh = fid->raw;
027c5e7a 13342+ struct au_branch *br;
1facf9fc 13343+ ino_t ino, dir_ino;
1facf9fc 13344+ struct au_nfsd_si_lock nsi_lock = {
1facf9fc 13345+ .force_lock = 0
13346+ };
13347+
1facf9fc 13348+ dentry = ERR_PTR(-ESTALE);
4a4d8108
AM
13349+ /* it should never happen, but the file handle is unreliable */
13350+ if (unlikely(fh_len < Fh_tail))
13351+ goto out;
13352+ nsi_lock.sigen = fh[Fh_sigen];
13353+ nsi_lock.br_id = fh[Fh_br_id];
13354+
1facf9fc 13355+ /* branch id may be wrapped around */
027c5e7a
AM
13356+ br = NULL;
13357+ if (unlikely(si_nfsd_read_lock(sb, &nsi_lock)))
1facf9fc 13358+ goto out;
13359+ nsi_lock.force_lock = 1;
13360+
13361+ /* is this inode still cached? */
13362+ ino = decode_ino(fh + Fh_ino);
4a4d8108
AM
13363+ /* it should never happen */
13364+ if (unlikely(ino == AUFS_ROOT_INO))
8cdd5066 13365+ goto out_unlock;
4a4d8108 13366+
1facf9fc 13367+ dir_ino = decode_ino(fh + Fh_dir_ino);
13368+ dentry = decode_by_ino(sb, ino, dir_ino);
13369+ if (IS_ERR(dentry))
13370+ goto out_unlock;
13371+ if (dentry)
13372+ goto accept;
13373+
13374+ /* is the parent dir cached? */
027c5e7a 13375+ br = au_sbr(sb, nsi_lock.bindex);
acd2b654 13376+ au_lcnt_inc(&br->br_nfiles);
1facf9fc 13377+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
13378+ if (IS_ERR(dentry))
13379+ goto out_unlock;
13380+ if (dentry)
13381+ goto accept;
13382+
13383+ /* lookup path */
027c5e7a 13384+ dentry = decode_by_path(sb, ino, fh, fh_len, &nsi_lock);
1facf9fc 13385+ if (IS_ERR(dentry))
13386+ goto out_unlock;
13387+ if (unlikely(!dentry))
13388+ /* todo?: make it ESTALE */
13389+ goto out_unlock;
13390+
4f0767ce 13391+accept:
027c5e7a 13392+ if (!au_digen_test(dentry, au_sigen(sb))
5527c038 13393+ && d_inode(dentry)->i_generation == fh[Fh_igen])
1facf9fc 13394+ goto out_unlock; /* success */
13395+
13396+ dput(dentry);
13397+ dentry = ERR_PTR(-ESTALE);
4f0767ce 13398+out_unlock:
027c5e7a 13399+ if (br)
acd2b654 13400+ au_lcnt_dec(&br->br_nfiles);
1facf9fc 13401+ si_read_unlock(sb);
4f0767ce 13402+out:
1facf9fc 13403+ AuTraceErrPtr(dentry);
13404+ return dentry;
13405+}
13406+
13407+#if 0 /* reserved for future use */
13408+/* support subtreecheck option */
13409+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
13410+ int fh_len, int fh_type)
13411+{
13412+ struct dentry *parent;
13413+ __u32 *fh = fid->raw;
13414+ ino_t dir_ino;
13415+
13416+ dir_ino = decode_ino(fh + Fh_dir_ino);
13417+ parent = decode_by_ino(sb, dir_ino, 0);
13418+ if (IS_ERR(parent))
13419+ goto out;
13420+ if (!parent)
13421+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
13422+ dir_ino, fh, fh_len);
13423+
4f0767ce 13424+out:
1facf9fc 13425+ AuTraceErrPtr(parent);
13426+ return parent;
13427+}
13428+#endif
13429+
13430+/* ---------------------------------------------------------------------- */
13431+
0c3ec466
AM
13432+static int aufs_encode_fh(struct inode *inode, __u32 *fh, int *max_len,
13433+ struct inode *dir)
1facf9fc 13434+{
13435+ int err;
0c3ec466 13436+ aufs_bindex_t bindex;
1facf9fc 13437+ struct super_block *sb, *h_sb;
0c3ec466
AM
13438+ struct dentry *dentry, *parent, *h_parent;
13439+ struct inode *h_dir;
1facf9fc 13440+ struct au_branch *br;
13441+
1facf9fc 13442+ err = -ENOSPC;
13443+ if (unlikely(*max_len <= Fh_tail)) {
13444+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
13445+ goto out;
13446+ }
13447+
13448+ err = FILEID_ROOT;
0c3ec466
AM
13449+ if (inode->i_ino == AUFS_ROOT_INO) {
13450+ AuDebugOn(inode->i_ino != AUFS_ROOT_INO);
1facf9fc 13451+ goto out;
13452+ }
13453+
1facf9fc 13454+ h_parent = NULL;
0c3ec466
AM
13455+ sb = inode->i_sb;
13456+ err = si_read_lock(sb, AuLock_FLUSH);
027c5e7a
AM
13457+ if (unlikely(err))
13458+ goto out;
13459+
1facf9fc 13460+#ifdef CONFIG_AUFS_DEBUG
13461+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
13462+ AuWarn1("NFS-exporting requires xino\n");
13463+#endif
027c5e7a 13464+ err = -EIO;
0c3ec466
AM
13465+ parent = NULL;
13466+ ii_read_lock_child(inode);
5afbbe0d 13467+ bindex = au_ibtop(inode);
0c3ec466 13468+ if (!dir) {
c1595e42 13469+ dentry = d_find_any_alias(inode);
0c3ec466
AM
13470+ if (unlikely(!dentry))
13471+ goto out_unlock;
13472+ AuDebugOn(au_test_anon(dentry));
13473+ parent = dget_parent(dentry);
13474+ dput(dentry);
13475+ if (unlikely(!parent))
13476+ goto out_unlock;
5527c038
JR
13477+ if (d_really_is_positive(parent))
13478+ dir = d_inode(parent);
1facf9fc 13479+ }
0c3ec466
AM
13480+
13481+ ii_read_lock_parent(dir);
13482+ h_dir = au_h_iptr(dir, bindex);
13483+ ii_read_unlock(dir);
13484+ if (unlikely(!h_dir))
13485+ goto out_parent;
c1595e42 13486+ h_parent = d_find_any_alias(h_dir);
1facf9fc 13487+ if (unlikely(!h_parent))
0c3ec466 13488+ goto out_hparent;
1facf9fc 13489+
13490+ err = -EPERM;
13491+ br = au_sbr(sb, bindex);
86dc4139 13492+ h_sb = au_br_sb(br);
1facf9fc 13493+ if (unlikely(!h_sb->s_export_op)) {
13494+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
0c3ec466 13495+ goto out_hparent;
1facf9fc 13496+ }
13497+
13498+ fh[Fh_br_id] = br->br_id;
13499+ fh[Fh_sigen] = au_sigen(sb);
13500+ encode_ino(fh + Fh_ino, inode->i_ino);
0c3ec466 13501+ encode_ino(fh + Fh_dir_ino, dir->i_ino);
1facf9fc 13502+ fh[Fh_igen] = inode->i_generation;
13503+
13504+ *max_len -= Fh_tail;
13505+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
13506+ max_len,
13507+ /*connectable or subtreecheck*/0);
13508+ err = fh[Fh_h_type];
13509+ *max_len += Fh_tail;
13510+ /* todo: macros? */
1716fcea 13511+ if (err != FILEID_INVALID)
1facf9fc 13512+ err = 99;
13513+ else
13514+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
13515+
0c3ec466 13516+out_hparent:
1facf9fc 13517+ dput(h_parent);
0c3ec466 13518+out_parent:
1facf9fc 13519+ dput(parent);
0c3ec466
AM
13520+out_unlock:
13521+ ii_read_unlock(inode);
13522+ si_read_unlock(sb);
4f0767ce 13523+out:
1facf9fc 13524+ if (unlikely(err < 0))
1716fcea 13525+ err = FILEID_INVALID;
1facf9fc 13526+ return err;
13527+}
13528+
13529+/* ---------------------------------------------------------------------- */
13530+
4a4d8108
AM
13531+static int aufs_commit_metadata(struct inode *inode)
13532+{
13533+ int err;
13534+ aufs_bindex_t bindex;
13535+ struct super_block *sb;
13536+ struct inode *h_inode;
13537+ int (*f)(struct inode *inode);
13538+
13539+ sb = inode->i_sb;
e49829fe 13540+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 13541+ ii_write_lock_child(inode);
5afbbe0d 13542+ bindex = au_ibtop(inode);
4a4d8108
AM
13543+ AuDebugOn(bindex < 0);
13544+ h_inode = au_h_iptr(inode, bindex);
13545+
13546+ f = h_inode->i_sb->s_export_op->commit_metadata;
13547+ if (f)
13548+ err = f(h_inode);
758e9dad
AM
13549+ else
13550+ err = sync_inode_metadata(h_inode, /*wait*/1);
4a4d8108
AM
13551+
13552+ au_cpup_attr_timesizes(inode);
13553+ ii_write_unlock(inode);
13554+ si_read_unlock(sb);
13555+ return err;
13556+}
13557+
13558+/* ---------------------------------------------------------------------- */
13559+
1facf9fc 13560+static struct export_operations aufs_export_op = {
4a4d8108 13561+ .fh_to_dentry = aufs_fh_to_dentry,
1facf9fc 13562+ /* .fh_to_parent = aufs_fh_to_parent, */
4a4d8108
AM
13563+ .encode_fh = aufs_encode_fh,
13564+ .commit_metadata = aufs_commit_metadata
1facf9fc 13565+};
13566+
13567+void au_export_init(struct super_block *sb)
13568+{
13569+ struct au_sbinfo *sbinfo;
13570+ __u32 u;
13571+
5afbbe0d
AM
13572+ BUILD_BUG_ON_MSG(IS_BUILTIN(CONFIG_AUFS_FS)
13573+ && IS_MODULE(CONFIG_EXPORTFS),
13574+ AUFS_NAME ": unsupported configuration "
13575+ "CONFIG_EXPORTFS=m and CONFIG_AUFS_FS=y");
13576+
1facf9fc 13577+ sb->s_export_op = &aufs_export_op;
13578+ sbinfo = au_sbi(sb);
13579+ sbinfo->si_xigen = NULL;
13580+ get_random_bytes(&u, sizeof(u));
13581+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
13582+ atomic_set(&sbinfo->si_xigen_next, u);
13583+}
076b876e 13584diff -urN /usr/share/empty/fs/aufs/fhsm.c linux/fs/aufs/fhsm.c
eca34b5c 13585--- /usr/share/empty/fs/aufs/fhsm.c 1970-01-01 01:00:00.000000000 +0100
319657f6 13586+++ linux/fs/aufs/fhsm.c 2021-12-03 15:38:59.933313976 +0100
062440b3 13587@@ -0,0 +1,427 @@
cd7a4cd9 13588+// SPDX-License-Identifier: GPL-2.0
076b876e 13589+/*
6d176551 13590+ * Copyright (C) 2011-2021 Junjiro R. Okajima
076b876e
AM
13591+ *
13592+ * This program, aufs is free software; you can redistribute it and/or modify
13593+ * it under the terms of the GNU General Public License as published by
13594+ * the Free Software Foundation; either version 2 of the License, or
13595+ * (at your option) any later version.
13596+ *
13597+ * This program is distributed in the hope that it will be useful,
13598+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13599+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13600+ * GNU General Public License for more details.
13601+ *
13602+ * You should have received a copy of the GNU General Public License
13603+ * along with this program; if not, write to the Free Software
13604+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13605+ */
13606+
13607+/*
13608+ * File-based Hierarchy Storage Management
13609+ */
13610+
13611+#include <linux/anon_inodes.h>
13612+#include <linux/poll.h>
13613+#include <linux/seq_file.h>
13614+#include <linux/statfs.h>
13615+#include "aufs.h"
13616+
c1595e42
JR
13617+static aufs_bindex_t au_fhsm_bottom(struct super_block *sb)
13618+{
13619+ struct au_sbinfo *sbinfo;
13620+ struct au_fhsm *fhsm;
13621+
13622+ SiMustAnyLock(sb);
13623+
13624+ sbinfo = au_sbi(sb);
13625+ fhsm = &sbinfo->si_fhsm;
13626+ AuDebugOn(!fhsm);
13627+ return fhsm->fhsm_bottom;
13628+}
13629+
13630+void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex)
13631+{
13632+ struct au_sbinfo *sbinfo;
13633+ struct au_fhsm *fhsm;
13634+
13635+ SiMustWriteLock(sb);
13636+
13637+ sbinfo = au_sbi(sb);
13638+ fhsm = &sbinfo->si_fhsm;
13639+ AuDebugOn(!fhsm);
13640+ fhsm->fhsm_bottom = bindex;
13641+}
13642+
13643+/* ---------------------------------------------------------------------- */
13644+
076b876e
AM
13645+static int au_fhsm_test_jiffy(struct au_sbinfo *sbinfo, struct au_branch *br)
13646+{
13647+ struct au_br_fhsm *bf;
13648+
13649+ bf = br->br_fhsm;
13650+ MtxMustLock(&bf->bf_lock);
13651+
13652+ return !bf->bf_readable
13653+ || time_after(jiffies,
13654+ bf->bf_jiffy + sbinfo->si_fhsm.fhsm_expire);
13655+}
13656+
13657+/* ---------------------------------------------------------------------- */
13658+
13659+static void au_fhsm_notify(struct super_block *sb, int val)
13660+{
13661+ struct au_sbinfo *sbinfo;
13662+ struct au_fhsm *fhsm;
13663+
13664+ SiMustAnyLock(sb);
13665+
13666+ sbinfo = au_sbi(sb);
13667+ fhsm = &sbinfo->si_fhsm;
13668+ if (au_fhsm_pid(fhsm)
13669+ && atomic_read(&fhsm->fhsm_readable) != -1) {
13670+ atomic_set(&fhsm->fhsm_readable, val);
13671+ if (val)
13672+ wake_up(&fhsm->fhsm_wqh);
13673+ }
13674+}
13675+
13676+static int au_fhsm_stfs(struct super_block *sb, aufs_bindex_t bindex,
13677+ struct aufs_stfs *rstfs, int do_lock, int do_notify)
13678+{
13679+ int err;
13680+ struct au_branch *br;
13681+ struct au_br_fhsm *bf;
13682+
13683+ br = au_sbr(sb, bindex);
13684+ AuDebugOn(au_br_rdonly(br));
13685+ bf = br->br_fhsm;
13686+ AuDebugOn(!bf);
13687+
13688+ if (do_lock)
13689+ mutex_lock(&bf->bf_lock);
13690+ else
13691+ MtxMustLock(&bf->bf_lock);
13692+
13693+ /* sb->s_root for NFS is unreliable */
13694+ err = au_br_stfs(br, &bf->bf_stfs);
13695+ if (unlikely(err)) {
13696+ AuErr1("FHSM failed (%d), b%d, ignored.\n", bindex, err);
13697+ goto out;
13698+ }
13699+
13700+ bf->bf_jiffy = jiffies;
13701+ bf->bf_readable = 1;
13702+ if (do_notify)
13703+ au_fhsm_notify(sb, /*val*/1);
13704+ if (rstfs)
13705+ *rstfs = bf->bf_stfs;
13706+
13707+out:
13708+ if (do_lock)
13709+ mutex_unlock(&bf->bf_lock);
13710+ au_fhsm_notify(sb, /*val*/1);
13711+
13712+ return err;
13713+}
13714+
13715+void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force)
13716+{
13717+ int err;
076b876e
AM
13718+ struct au_sbinfo *sbinfo;
13719+ struct au_fhsm *fhsm;
13720+ struct au_branch *br;
13721+ struct au_br_fhsm *bf;
13722+
13723+ AuDbg("b%d, force %d\n", bindex, force);
13724+ SiMustAnyLock(sb);
13725+
13726+ sbinfo = au_sbi(sb);
13727+ fhsm = &sbinfo->si_fhsm;
c1595e42
JR
13728+ if (!au_ftest_si(sbinfo, FHSM)
13729+ || fhsm->fhsm_bottom == bindex)
076b876e
AM
13730+ return;
13731+
13732+ br = au_sbr(sb, bindex);
13733+ bf = br->br_fhsm;
13734+ AuDebugOn(!bf);
13735+ mutex_lock(&bf->bf_lock);
13736+ if (force
13737+ || au_fhsm_pid(fhsm)
13738+ || au_fhsm_test_jiffy(sbinfo, br))
13739+ err = au_fhsm_stfs(sb, bindex, /*rstfs*/NULL, /*do_lock*/0,
13740+ /*do_notify*/1);
13741+ mutex_unlock(&bf->bf_lock);
13742+}
13743+
13744+void au_fhsm_wrote_all(struct super_block *sb, int force)
13745+{
5afbbe0d 13746+ aufs_bindex_t bindex, bbot;
076b876e
AM
13747+ struct au_branch *br;
13748+
13749+ /* exclude the bottom */
5afbbe0d
AM
13750+ bbot = au_fhsm_bottom(sb);
13751+ for (bindex = 0; bindex < bbot; bindex++) {
076b876e
AM
13752+ br = au_sbr(sb, bindex);
13753+ if (au_br_fhsm(br->br_perm))
13754+ au_fhsm_wrote(sb, bindex, force);
13755+ }
13756+}
13757+
13758+/* ---------------------------------------------------------------------- */
13759+
be118d29 13760+static __poll_t au_fhsm_poll(struct file *file, struct poll_table_struct *wait)
076b876e 13761+{
be118d29 13762+ __poll_t mask;
076b876e
AM
13763+ struct au_sbinfo *sbinfo;
13764+ struct au_fhsm *fhsm;
13765+
13766+ mask = 0;
13767+ sbinfo = file->private_data;
13768+ fhsm = &sbinfo->si_fhsm;
13769+ poll_wait(file, &fhsm->fhsm_wqh, wait);
13770+ if (atomic_read(&fhsm->fhsm_readable))
be118d29 13771+ mask = EPOLLIN /* | EPOLLRDNORM */;
076b876e 13772+
b00004a5
AM
13773+ if (!mask)
13774+ AuDbg("mask 0x%x\n", mask);
076b876e
AM
13775+ return mask;
13776+}
13777+
13778+static int au_fhsm_do_read_one(struct aufs_stbr __user *stbr,
13779+ struct aufs_stfs *stfs, __s16 brid)
13780+{
13781+ int err;
13782+
13783+ err = copy_to_user(&stbr->stfs, stfs, sizeof(*stfs));
13784+ if (!err)
13785+ err = __put_user(brid, &stbr->brid);
13786+ if (unlikely(err))
13787+ err = -EFAULT;
13788+
13789+ return err;
13790+}
13791+
13792+static ssize_t au_fhsm_do_read(struct super_block *sb,
13793+ struct aufs_stbr __user *stbr, size_t count)
13794+{
13795+ ssize_t err;
13796+ int nstbr;
5afbbe0d 13797+ aufs_bindex_t bindex, bbot;
076b876e
AM
13798+ struct au_branch *br;
13799+ struct au_br_fhsm *bf;
13800+
13801+ /* except the bottom branch */
13802+ err = 0;
13803+ nstbr = 0;
5afbbe0d
AM
13804+ bbot = au_fhsm_bottom(sb);
13805+ for (bindex = 0; !err && bindex < bbot; bindex++) {
076b876e
AM
13806+ br = au_sbr(sb, bindex);
13807+ if (!au_br_fhsm(br->br_perm))
13808+ continue;
13809+
13810+ bf = br->br_fhsm;
13811+ mutex_lock(&bf->bf_lock);
13812+ if (bf->bf_readable) {
13813+ err = -EFAULT;
13814+ if (count >= sizeof(*stbr))
13815+ err = au_fhsm_do_read_one(stbr++, &bf->bf_stfs,
13816+ br->br_id);
13817+ if (!err) {
13818+ bf->bf_readable = 0;
13819+ count -= sizeof(*stbr);
13820+ nstbr++;
13821+ }
13822+ }
13823+ mutex_unlock(&bf->bf_lock);
13824+ }
13825+ if (!err)
13826+ err = sizeof(*stbr) * nstbr;
13827+
13828+ return err;
13829+}
13830+
13831+static ssize_t au_fhsm_read(struct file *file, char __user *buf, size_t count,
13832+ loff_t *pos)
13833+{
13834+ ssize_t err;
13835+ int readable;
5afbbe0d 13836+ aufs_bindex_t nfhsm, bindex, bbot;
076b876e
AM
13837+ struct au_sbinfo *sbinfo;
13838+ struct au_fhsm *fhsm;
13839+ struct au_branch *br;
13840+ struct super_block *sb;
13841+
13842+ err = 0;
13843+ sbinfo = file->private_data;
13844+ fhsm = &sbinfo->si_fhsm;
13845+need_data:
13846+ spin_lock_irq(&fhsm->fhsm_wqh.lock);
13847+ if (!atomic_read(&fhsm->fhsm_readable)) {
13848+ if (vfsub_file_flags(file) & O_NONBLOCK)
13849+ err = -EAGAIN;
13850+ else
13851+ err = wait_event_interruptible_locked_irq
13852+ (fhsm->fhsm_wqh,
13853+ atomic_read(&fhsm->fhsm_readable));
13854+ }
13855+ spin_unlock_irq(&fhsm->fhsm_wqh.lock);
13856+ if (unlikely(err))
13857+ goto out;
13858+
13859+ /* sb may already be dead */
13860+ au_rw_read_lock(&sbinfo->si_rwsem);
13861+ readable = atomic_read(&fhsm->fhsm_readable);
13862+ if (readable > 0) {
13863+ sb = sbinfo->si_sb;
13864+ AuDebugOn(!sb);
13865+ /* exclude the bottom branch */
13866+ nfhsm = 0;
5afbbe0d
AM
13867+ bbot = au_fhsm_bottom(sb);
13868+ for (bindex = 0; bindex < bbot; bindex++) {
076b876e
AM
13869+ br = au_sbr(sb, bindex);
13870+ if (au_br_fhsm(br->br_perm))
13871+ nfhsm++;
13872+ }
13873+ err = -EMSGSIZE;
13874+ if (nfhsm * sizeof(struct aufs_stbr) <= count) {
13875+ atomic_set(&fhsm->fhsm_readable, 0);
13876+ err = au_fhsm_do_read(sbinfo->si_sb, (void __user *)buf,
13877+ count);
13878+ }
13879+ }
13880+ au_rw_read_unlock(&sbinfo->si_rwsem);
13881+ if (!readable)
13882+ goto need_data;
13883+
13884+out:
13885+ return err;
13886+}
13887+
13888+static int au_fhsm_release(struct inode *inode, struct file *file)
13889+{
13890+ struct au_sbinfo *sbinfo;
13891+ struct au_fhsm *fhsm;
13892+
13893+ /* sb may already be dead */
13894+ sbinfo = file->private_data;
13895+ fhsm = &sbinfo->si_fhsm;
13896+ spin_lock(&fhsm->fhsm_spin);
13897+ fhsm->fhsm_pid = 0;
13898+ spin_unlock(&fhsm->fhsm_spin);
13899+ kobject_put(&sbinfo->si_kobj);
13900+
13901+ return 0;
13902+}
13903+
13904+static const struct file_operations au_fhsm_fops = {
13905+ .owner = THIS_MODULE,
13906+ .llseek = noop_llseek,
13907+ .read = au_fhsm_read,
13908+ .poll = au_fhsm_poll,
13909+ .release = au_fhsm_release
13910+};
13911+
13912+int au_fhsm_fd(struct super_block *sb, int oflags)
13913+{
13914+ int err, fd;
13915+ struct au_sbinfo *sbinfo;
13916+ struct au_fhsm *fhsm;
13917+
13918+ err = -EPERM;
13919+ if (unlikely(!capable(CAP_SYS_ADMIN)))
13920+ goto out;
13921+
13922+ err = -EINVAL;
13923+ if (unlikely(oflags & ~(O_CLOEXEC | O_NONBLOCK)))
13924+ goto out;
13925+
13926+ err = 0;
13927+ sbinfo = au_sbi(sb);
13928+ fhsm = &sbinfo->si_fhsm;
13929+ spin_lock(&fhsm->fhsm_spin);
13930+ if (!fhsm->fhsm_pid)
13931+ fhsm->fhsm_pid = current->pid;
13932+ else
13933+ err = -EBUSY;
13934+ spin_unlock(&fhsm->fhsm_spin);
13935+ if (unlikely(err))
13936+ goto out;
13937+
13938+ oflags |= O_RDONLY;
13939+ /* oflags |= FMODE_NONOTIFY; */
13940+ fd = anon_inode_getfd("[aufs_fhsm]", &au_fhsm_fops, sbinfo, oflags);
13941+ err = fd;
13942+ if (unlikely(fd < 0))
13943+ goto out_pid;
13944+
acd2b654 13945+ /* succeed regardless 'fhsm' status */
076b876e
AM
13946+ kobject_get(&sbinfo->si_kobj);
13947+ si_noflush_read_lock(sb);
13948+ if (au_ftest_si(sbinfo, FHSM))
13949+ au_fhsm_wrote_all(sb, /*force*/0);
13950+ si_read_unlock(sb);
13951+ goto out; /* success */
13952+
13953+out_pid:
13954+ spin_lock(&fhsm->fhsm_spin);
13955+ fhsm->fhsm_pid = 0;
13956+ spin_unlock(&fhsm->fhsm_spin);
13957+out:
13958+ AuTraceErr(err);
13959+ return err;
13960+}
13961+
13962+/* ---------------------------------------------------------------------- */
13963+
13964+int au_fhsm_br_alloc(struct au_branch *br)
13965+{
13966+ int err;
13967+
13968+ err = 0;
13969+ br->br_fhsm = kmalloc(sizeof(*br->br_fhsm), GFP_NOFS);
13970+ if (br->br_fhsm)
13971+ au_br_fhsm_init(br->br_fhsm);
13972+ else
13973+ err = -ENOMEM;
13974+
13975+ return err;
13976+}
13977+
13978+/* ---------------------------------------------------------------------- */
13979+
13980+void au_fhsm_fin(struct super_block *sb)
13981+{
13982+ au_fhsm_notify(sb, /*val*/-1);
13983+}
13984+
13985+void au_fhsm_init(struct au_sbinfo *sbinfo)
13986+{
13987+ struct au_fhsm *fhsm;
13988+
13989+ fhsm = &sbinfo->si_fhsm;
13990+ spin_lock_init(&fhsm->fhsm_spin);
13991+ init_waitqueue_head(&fhsm->fhsm_wqh);
13992+ atomic_set(&fhsm->fhsm_readable, 0);
13993+ fhsm->fhsm_expire
13994+ = msecs_to_jiffies(AUFS_FHSM_CACHE_DEF_SEC * MSEC_PER_SEC);
c1595e42 13995+ fhsm->fhsm_bottom = -1;
076b876e
AM
13996+}
13997+
13998+void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec)
13999+{
14000+ sbinfo->si_fhsm.fhsm_expire
14001+ = msecs_to_jiffies(sec * MSEC_PER_SEC);
14002+}
14003+
14004+void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo)
14005+{
14006+ unsigned int u;
14007+
14008+ if (!au_ftest_si(sbinfo, FHSM))
14009+ return;
14010+
14011+ u = jiffies_to_msecs(sbinfo->si_fhsm.fhsm_expire) / MSEC_PER_SEC;
14012+ if (u != AUFS_FHSM_CACHE_DEF_SEC)
14013+ seq_printf(seq, ",fhsm_sec=%u", u);
14014+}
7f207e10 14015diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
eca34b5c 14016--- /usr/share/empty/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
319657f6 14017+++ linux/fs/aufs/file.c 2021-12-03 15:38:59.936647310 +0100
42a736d3 14018@@ -0,0 +1,863 @@
cd7a4cd9 14019+// SPDX-License-Identifier: GPL-2.0
1facf9fc 14020+/*
6d176551 14021+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 14022+ *
14023+ * This program, aufs is free software; you can redistribute it and/or modify
14024+ * it under the terms of the GNU General Public License as published by
14025+ * the Free Software Foundation; either version 2 of the License, or
14026+ * (at your option) any later version.
dece6358
AM
14027+ *
14028+ * This program is distributed in the hope that it will be useful,
14029+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14030+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14031+ * GNU General Public License for more details.
14032+ *
14033+ * You should have received a copy of the GNU General Public License
523b37e3 14034+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 14035+ */
14036+
14037+/*
4a4d8108 14038+ * handling file/dir, and address_space operation
1facf9fc 14039+ */
14040+
7eafdf33
AM
14041+#ifdef CONFIG_AUFS_DEBUG
14042+#include <linux/migrate.h>
14043+#endif
4a4d8108 14044+#include <linux/pagemap.h>
1facf9fc 14045+#include "aufs.h"
14046+
4a4d8108
AM
14047+/* drop flags for writing */
14048+unsigned int au_file_roflags(unsigned int flags)
14049+{
14050+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
14051+ flags |= O_RDONLY | O_NOATIME;
14052+ return flags;
14053+}
14054+
14055+/* common functions to regular file and dir */
14056+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
392086de 14057+ struct file *file, int force_wr)
1facf9fc 14058+{
1308ab2a 14059+ struct file *h_file;
4a4d8108
AM
14060+ struct dentry *h_dentry;
14061+ struct inode *h_inode;
14062+ struct super_block *sb;
14063+ struct au_branch *br;
14064+ struct path h_path;
b912730e 14065+ int err;
1facf9fc 14066+
4a4d8108
AM
14067+ /* a race condition can happen between open and unlink/rmdir */
14068+ h_file = ERR_PTR(-ENOENT);
14069+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 14070+ if (au_test_nfsd() && (!h_dentry || d_is_negative(h_dentry)))
4a4d8108 14071+ goto out;
5527c038 14072+ h_inode = d_inode(h_dentry);
027c5e7a
AM
14073+ spin_lock(&h_dentry->d_lock);
14074+ err = (!d_unhashed(dentry) && d_unlinked(h_dentry))
5527c038 14075+ /* || !d_inode(dentry)->i_nlink */
027c5e7a
AM
14076+ ;
14077+ spin_unlock(&h_dentry->d_lock);
14078+ if (unlikely(err))
4a4d8108 14079+ goto out;
1facf9fc 14080+
4a4d8108
AM
14081+ sb = dentry->d_sb;
14082+ br = au_sbr(sb, bindex);
b912730e
AM
14083+ err = au_br_test_oflag(flags, br);
14084+ h_file = ERR_PTR(err);
14085+ if (unlikely(err))
027c5e7a 14086+ goto out;
1facf9fc 14087+
4a4d8108 14088+ /* drop flags for writing */
5527c038 14089+ if (au_test_ro(sb, bindex, d_inode(dentry))) {
392086de
AM
14090+ if (force_wr && !(flags & O_WRONLY))
14091+ force_wr = 0;
4a4d8108 14092+ flags = au_file_roflags(flags);
392086de
AM
14093+ if (force_wr) {
14094+ h_file = ERR_PTR(-EROFS);
14095+ flags = au_file_roflags(flags);
14096+ if (unlikely(vfsub_native_ro(h_inode)
14097+ || IS_APPEND(h_inode)))
14098+ goto out;
14099+ flags &= ~O_ACCMODE;
14100+ flags |= O_WRONLY;
14101+ }
14102+ }
4a4d8108 14103+ flags &= ~O_CREAT;
acd2b654 14104+ au_lcnt_inc(&br->br_nfiles);
4a4d8108 14105+ h_path.dentry = h_dentry;
86dc4139 14106+ h_path.mnt = au_br_mnt(br);
38d290e6 14107+ h_file = vfsub_dentry_open(&h_path, flags);
4a4d8108
AM
14108+ if (IS_ERR(h_file))
14109+ goto out_br;
dece6358 14110+
b912730e 14111+ if (flags & __FMODE_EXEC) {
4a4d8108
AM
14112+ err = deny_write_access(h_file);
14113+ if (unlikely(err)) {
14114+ fput(h_file);
14115+ h_file = ERR_PTR(err);
14116+ goto out_br;
14117+ }
14118+ }
953406b4 14119+ fsnotify_open(h_file);
4a4d8108 14120+ goto out; /* success */
1facf9fc 14121+
4f0767ce 14122+out_br:
acd2b654 14123+ au_lcnt_dec(&br->br_nfiles);
4f0767ce 14124+out:
4a4d8108
AM
14125+ return h_file;
14126+}
1308ab2a 14127+
076b876e
AM
14128+static int au_cmoo(struct dentry *dentry)
14129+{
8b6a4947 14130+ int err, cmoo, matched;
076b876e
AM
14131+ unsigned int udba;
14132+ struct path h_path;
14133+ struct au_pin pin;
14134+ struct au_cp_generic cpg = {
14135+ .dentry = dentry,
14136+ .bdst = -1,
14137+ .bsrc = -1,
14138+ .len = -1,
14139+ .pin = &pin,
14140+ .flags = AuCpup_DTIME | AuCpup_HOPEN
14141+ };
7e9cd9fe 14142+ struct inode *delegated;
076b876e
AM
14143+ struct super_block *sb;
14144+ struct au_sbinfo *sbinfo;
14145+ struct au_fhsm *fhsm;
14146+ pid_t pid;
14147+ struct au_branch *br;
14148+ struct dentry *parent;
14149+ struct au_hinode *hdir;
14150+
14151+ DiMustWriteLock(dentry);
5527c038 14152+ IiMustWriteLock(d_inode(dentry));
076b876e
AM
14153+
14154+ err = 0;
14155+ if (IS_ROOT(dentry))
14156+ goto out;
5afbbe0d 14157+ cpg.bsrc = au_dbtop(dentry);
076b876e
AM
14158+ if (!cpg.bsrc)
14159+ goto out;
14160+
14161+ sb = dentry->d_sb;
14162+ sbinfo = au_sbi(sb);
14163+ fhsm = &sbinfo->si_fhsm;
14164+ pid = au_fhsm_pid(fhsm);
8b6a4947
AM
14165+ rcu_read_lock();
14166+ matched = (pid
14167+ && (current->pid == pid
14168+ || rcu_dereference(current->real_parent)->pid == pid));
14169+ rcu_read_unlock();
14170+ if (matched)
076b876e
AM
14171+ goto out;
14172+
14173+ br = au_sbr(sb, cpg.bsrc);
14174+ cmoo = au_br_cmoo(br->br_perm);
14175+ if (!cmoo)
14176+ goto out;
7e9cd9fe 14177+ if (!d_is_reg(dentry))
076b876e
AM
14178+ cmoo &= AuBrAttr_COO_ALL;
14179+ if (!cmoo)
14180+ goto out;
14181+
14182+ parent = dget_parent(dentry);
14183+ di_write_lock_parent(parent);
14184+ err = au_wbr_do_copyup_bu(dentry, cpg.bsrc - 1);
14185+ cpg.bdst = err;
14186+ if (unlikely(err < 0)) {
14187+ err = 0; /* there is no upper writable branch */
14188+ goto out_dgrade;
14189+ }
14190+ AuDbg("bsrc %d, bdst %d\n", cpg.bsrc, cpg.bdst);
14191+
14192+ /* do not respect the coo attrib for the target branch */
14193+ err = au_cpup_dirs(dentry, cpg.bdst);
14194+ if (unlikely(err))
14195+ goto out_dgrade;
14196+
14197+ di_downgrade_lock(parent, AuLock_IR);
14198+ udba = au_opt_udba(sb);
14199+ err = au_pin(&pin, dentry, cpg.bdst, udba,
14200+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14201+ if (unlikely(err))
14202+ goto out_parent;
14203+
14204+ err = au_sio_cpup_simple(&cpg);
14205+ au_unpin(&pin);
14206+ if (unlikely(err))
14207+ goto out_parent;
14208+ if (!(cmoo & AuBrWAttr_MOO))
14209+ goto out_parent; /* success */
14210+
14211+ err = au_pin(&pin, dentry, cpg.bsrc, udba,
14212+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14213+ if (unlikely(err))
14214+ goto out_parent;
14215+
14216+ h_path.mnt = au_br_mnt(br);
14217+ h_path.dentry = au_h_dptr(dentry, cpg.bsrc);
5527c038 14218+ hdir = au_hi(d_inode(parent), cpg.bsrc);
076b876e
AM
14219+ delegated = NULL;
14220+ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated, /*force*/1);
14221+ au_unpin(&pin);
14222+ /* todo: keep h_dentry or not? */
14223+ if (unlikely(err == -EWOULDBLOCK)) {
14224+ pr_warn("cannot retry for NFSv4 delegation"
14225+ " for an internal unlink\n");
14226+ iput(delegated);
14227+ }
14228+ if (unlikely(err)) {
14229+ pr_err("unlink %pd after coo failed (%d), ignored\n",
14230+ dentry, err);
14231+ err = 0;
14232+ }
14233+ goto out_parent; /* success */
14234+
14235+out_dgrade:
14236+ di_downgrade_lock(parent, AuLock_IR);
14237+out_parent:
14238+ di_read_unlock(parent, AuLock_IR);
14239+ dput(parent);
14240+out:
14241+ AuTraceErr(err);
14242+ return err;
14243+}
14244+
b912730e 14245+int au_do_open(struct file *file, struct au_do_open_args *args)
1facf9fc 14246+{
8b6a4947 14247+ int err, aopen = args->aopen;
1facf9fc 14248+ struct dentry *dentry;
076b876e 14249+ struct au_finfo *finfo;
1308ab2a 14250+
8b6a4947 14251+ if (!aopen)
b912730e
AM
14252+ err = au_finfo_init(file, args->fidir);
14253+ else {
14254+ lockdep_off();
14255+ err = au_finfo_init(file, args->fidir);
14256+ lockdep_on();
14257+ }
4a4d8108
AM
14258+ if (unlikely(err))
14259+ goto out;
1facf9fc 14260+
2000de60 14261+ dentry = file->f_path.dentry;
b912730e 14262+ AuDebugOn(IS_ERR_OR_NULL(dentry));
8b6a4947
AM
14263+ di_write_lock_child(dentry);
14264+ err = au_cmoo(dentry);
14265+ di_downgrade_lock(dentry, AuLock_IR);
14266+ if (!err) {
14267+ if (!aopen)
b912730e 14268+ err = args->open(file, vfsub_file_flags(file), NULL);
8b6a4947
AM
14269+ else {
14270+ lockdep_off();
acd2b654
AM
14271+ err = args->open(file, vfsub_file_flags(file),
14272+ args->h_file);
8b6a4947
AM
14273+ lockdep_on();
14274+ }
b912730e 14275+ }
8b6a4947 14276+ di_read_unlock(dentry, AuLock_IR);
1facf9fc 14277+
076b876e
AM
14278+ finfo = au_fi(file);
14279+ if (!err) {
14280+ finfo->fi_file = file;
8b6a4947
AM
14281+ au_hbl_add(&finfo->fi_hlist,
14282+ &au_sbi(file->f_path.dentry->d_sb)->si_files);
076b876e 14283+ }
8b6a4947 14284+ if (!aopen)
b912730e
AM
14285+ fi_write_unlock(file);
14286+ else {
14287+ lockdep_off();
14288+ fi_write_unlock(file);
14289+ lockdep_on();
14290+ }
4a4d8108 14291+ if (unlikely(err)) {
076b876e 14292+ finfo->fi_hdir = NULL;
1c60b727 14293+ au_finfo_fin(file);
1308ab2a 14294+ }
4a4d8108 14295+
4f0767ce 14296+out:
8b6a4947 14297+ AuTraceErr(err);
1308ab2a 14298+ return err;
14299+}
dece6358 14300+
4a4d8108 14301+int au_reopen_nondir(struct file *file)
1308ab2a 14302+{
4a4d8108 14303+ int err;
5afbbe0d 14304+ aufs_bindex_t btop;
4a4d8108 14305+ struct dentry *dentry;
acd2b654 14306+ struct au_branch *br;
4a4d8108 14307+ struct file *h_file, *h_file_tmp;
1308ab2a 14308+
2000de60 14309+ dentry = file->f_path.dentry;
5afbbe0d 14310+ btop = au_dbtop(dentry);
acd2b654 14311+ br = au_sbr(dentry->d_sb, btop);
4a4d8108 14312+ h_file_tmp = NULL;
5afbbe0d 14313+ if (au_fbtop(file) == btop) {
4a4d8108
AM
14314+ h_file = au_hf_top(file);
14315+ if (file->f_mode == h_file->f_mode)
14316+ return 0; /* success */
14317+ h_file_tmp = h_file;
14318+ get_file(h_file_tmp);
acd2b654 14319+ au_lcnt_inc(&br->br_nfiles);
5afbbe0d 14320+ au_set_h_fptr(file, btop, NULL);
4a4d8108
AM
14321+ }
14322+ AuDebugOn(au_fi(file)->fi_hdir);
86dc4139
AM
14323+ /*
14324+ * it can happen
14325+ * file exists on both of rw and ro
5afbbe0d 14326+ * open --> dbtop and fbtop are both 0
86dc4139
AM
14327+ * prepend a branch as rw, "rw" become ro
14328+ * remove rw/file
14329+ * delete the top branch, "rw" becomes rw again
5afbbe0d
AM
14330+ * --> dbtop is 1, fbtop is still 0
14331+ * write --> fbtop is 0 but dbtop is 1
86dc4139 14332+ */
5afbbe0d 14333+ /* AuDebugOn(au_fbtop(file) < btop); */
1308ab2a 14334+
5afbbe0d 14335+ h_file = au_h_open(dentry, btop, vfsub_file_flags(file) & ~O_TRUNC,
392086de 14336+ file, /*force_wr*/0);
4a4d8108 14337+ err = PTR_ERR(h_file);
86dc4139
AM
14338+ if (IS_ERR(h_file)) {
14339+ if (h_file_tmp) {
acd2b654 14340+ /* revert */
5afbbe0d 14341+ au_set_h_fptr(file, btop, h_file_tmp);
86dc4139
AM
14342+ h_file_tmp = NULL;
14343+ }
4a4d8108 14344+ goto out; /* todo: close all? */
86dc4139 14345+ }
4a4d8108
AM
14346+
14347+ err = 0;
5afbbe0d
AM
14348+ au_set_fbtop(file, btop);
14349+ au_set_h_fptr(file, btop, h_file);
4a4d8108
AM
14350+ au_update_figen(file);
14351+ /* todo: necessary? */
14352+ /* file->f_ra = h_file->f_ra; */
14353+
4f0767ce 14354+out:
acd2b654 14355+ if (h_file_tmp) {
4a4d8108 14356+ fput(h_file_tmp);
acd2b654
AM
14357+ au_lcnt_dec(&br->br_nfiles);
14358+ }
4a4d8108 14359+ return err;
1facf9fc 14360+}
14361+
1308ab2a 14362+/* ---------------------------------------------------------------------- */
14363+
4a4d8108
AM
14364+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
14365+ struct dentry *hi_wh)
1facf9fc 14366+{
4a4d8108 14367+ int err;
5afbbe0d 14368+ aufs_bindex_t btop;
4a4d8108
AM
14369+ struct au_dinfo *dinfo;
14370+ struct dentry *h_dentry;
14371+ struct au_hdentry *hdp;
1facf9fc 14372+
2000de60 14373+ dinfo = au_di(file->f_path.dentry);
4a4d8108 14374+ AuRwMustWriteLock(&dinfo->di_rwsem);
dece6358 14375+
5afbbe0d
AM
14376+ btop = dinfo->di_btop;
14377+ dinfo->di_btop = btgt;
14378+ hdp = au_hdentry(dinfo, btgt);
14379+ h_dentry = hdp->hd_dentry;
14380+ hdp->hd_dentry = hi_wh;
4a4d8108 14381+ err = au_reopen_nondir(file);
5afbbe0d
AM
14382+ hdp->hd_dentry = h_dentry;
14383+ dinfo->di_btop = btop;
1facf9fc 14384+
1facf9fc 14385+ return err;
14386+}
14387+
4a4d8108 14388+static int au_ready_to_write_wh(struct file *file, loff_t len,
86dc4139 14389+ aufs_bindex_t bcpup, struct au_pin *pin)
1facf9fc 14390+{
4a4d8108 14391+ int err;
027c5e7a 14392+ struct inode *inode, *h_inode;
c2b27bf2
AM
14393+ struct dentry *h_dentry, *hi_wh;
14394+ struct au_cp_generic cpg = {
2000de60 14395+ .dentry = file->f_path.dentry,
c2b27bf2
AM
14396+ .bdst = bcpup,
14397+ .bsrc = -1,
14398+ .len = len,
14399+ .pin = pin
14400+ };
1facf9fc 14401+
5afbbe0d 14402+ au_update_dbtop(cpg.dentry);
5527c038 14403+ inode = d_inode(cpg.dentry);
027c5e7a 14404+ h_inode = NULL;
5afbbe0d
AM
14405+ if (au_dbtop(cpg.dentry) <= bcpup
14406+ && au_dbbot(cpg.dentry) >= bcpup) {
c2b27bf2 14407+ h_dentry = au_h_dptr(cpg.dentry, bcpup);
5527c038
JR
14408+ if (h_dentry && d_is_positive(h_dentry))
14409+ h_inode = d_inode(h_dentry);
027c5e7a 14410+ }
4a4d8108 14411+ hi_wh = au_hi_wh(inode, bcpup);
027c5e7a 14412+ if (!hi_wh && !h_inode)
c2b27bf2 14413+ err = au_sio_cpup_wh(&cpg, file);
4a4d8108
AM
14414+ else
14415+ /* already copied-up after unlink */
14416+ err = au_reopen_wh(file, bcpup, hi_wh);
1facf9fc 14417+
4a4d8108 14418+ if (!err
38d290e6
JR
14419+ && (inode->i_nlink > 1
14420+ || (inode->i_state & I_LINKABLE))
c2b27bf2
AM
14421+ && au_opt_test(au_mntflags(cpg.dentry->d_sb), PLINK))
14422+ au_plink_append(inode, bcpup, au_h_dptr(cpg.dentry, bcpup));
1308ab2a 14423+
dece6358 14424+ return err;
1facf9fc 14425+}
14426+
4a4d8108
AM
14427+/*
14428+ * prepare the @file for writing.
14429+ */
14430+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
1facf9fc 14431+{
4a4d8108 14432+ int err;
5afbbe0d 14433+ aufs_bindex_t dbtop;
c1595e42 14434+ struct dentry *parent;
86dc4139 14435+ struct inode *inode;
1facf9fc 14436+ struct super_block *sb;
4a4d8108 14437+ struct file *h_file;
c2b27bf2 14438+ struct au_cp_generic cpg = {
2000de60 14439+ .dentry = file->f_path.dentry,
c2b27bf2
AM
14440+ .bdst = -1,
14441+ .bsrc = -1,
14442+ .len = len,
14443+ .pin = pin,
14444+ .flags = AuCpup_DTIME
14445+ };
1facf9fc 14446+
c2b27bf2 14447+ sb = cpg.dentry->d_sb;
5527c038 14448+ inode = d_inode(cpg.dentry);
5afbbe0d 14449+ cpg.bsrc = au_fbtop(file);
c2b27bf2 14450+ err = au_test_ro(sb, cpg.bsrc, inode);
4a4d8108 14451+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
c2b27bf2
AM
14452+ err = au_pin(pin, cpg.dentry, cpg.bsrc, AuOpt_UDBA_NONE,
14453+ /*flags*/0);
1facf9fc 14454+ goto out;
4a4d8108 14455+ }
1facf9fc 14456+
027c5e7a 14457+ /* need to cpup or reopen */
c2b27bf2 14458+ parent = dget_parent(cpg.dentry);
4a4d8108 14459+ di_write_lock_parent(parent);
c2b27bf2
AM
14460+ err = AuWbrCopyup(au_sbi(sb), cpg.dentry);
14461+ cpg.bdst = err;
4a4d8108
AM
14462+ if (unlikely(err < 0))
14463+ goto out_dgrade;
14464+ err = 0;
14465+
c2b27bf2
AM
14466+ if (!d_unhashed(cpg.dentry) && !au_h_dptr(parent, cpg.bdst)) {
14467+ err = au_cpup_dirs(cpg.dentry, cpg.bdst);
1facf9fc 14468+ if (unlikely(err))
4a4d8108
AM
14469+ goto out_dgrade;
14470+ }
14471+
c2b27bf2 14472+ err = au_pin(pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE,
4a4d8108
AM
14473+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14474+ if (unlikely(err))
14475+ goto out_dgrade;
14476+
5afbbe0d
AM
14477+ dbtop = au_dbtop(cpg.dentry);
14478+ if (dbtop <= cpg.bdst)
c2b27bf2 14479+ cpg.bsrc = cpg.bdst;
027c5e7a 14480+
5afbbe0d 14481+ if (dbtop <= cpg.bdst /* just reopen */
c2b27bf2 14482+ || !d_unhashed(cpg.dentry) /* copyup and reopen */
027c5e7a 14483+ ) {
392086de 14484+ h_file = au_h_open_pre(cpg.dentry, cpg.bsrc, /*force_wr*/0);
86dc4139 14485+ if (IS_ERR(h_file))
027c5e7a 14486+ err = PTR_ERR(h_file);
86dc4139 14487+ else {
027c5e7a 14488+ di_downgrade_lock(parent, AuLock_IR);
5afbbe0d 14489+ if (dbtop > cpg.bdst)
c2b27bf2 14490+ err = au_sio_cpup_simple(&cpg);
027c5e7a
AM
14491+ if (!err)
14492+ err = au_reopen_nondir(file);
c2b27bf2 14493+ au_h_open_post(cpg.dentry, cpg.bsrc, h_file);
027c5e7a 14494+ }
027c5e7a
AM
14495+ } else { /* copyup as wh and reopen */
14496+ /*
14497+ * since writable hfsplus branch is not supported,
14498+ * h_open_pre/post() are unnecessary.
14499+ */
c2b27bf2 14500+ err = au_ready_to_write_wh(file, len, cpg.bdst, pin);
4a4d8108 14501+ di_downgrade_lock(parent, AuLock_IR);
4a4d8108 14502+ }
4a4d8108
AM
14503+
14504+ if (!err) {
14505+ au_pin_set_parent_lflag(pin, /*lflag*/0);
14506+ goto out_dput; /* success */
14507+ }
14508+ au_unpin(pin);
14509+ goto out_unlock;
1facf9fc 14510+
4f0767ce 14511+out_dgrade:
4a4d8108 14512+ di_downgrade_lock(parent, AuLock_IR);
4f0767ce 14513+out_unlock:
4a4d8108 14514+ di_read_unlock(parent, AuLock_IR);
4f0767ce 14515+out_dput:
4a4d8108 14516+ dput(parent);
4f0767ce 14517+out:
1facf9fc 14518+ return err;
14519+}
14520+
4a4d8108
AM
14521+/* ---------------------------------------------------------------------- */
14522+
14523+int au_do_flush(struct file *file, fl_owner_t id,
14524+ int (*flush)(struct file *file, fl_owner_t id))
1facf9fc 14525+{
4a4d8108 14526+ int err;
1facf9fc 14527+ struct super_block *sb;
4a4d8108 14528+ struct inode *inode;
1facf9fc 14529+
c06a8ce3
AM
14530+ inode = file_inode(file);
14531+ sb = inode->i_sb;
4a4d8108
AM
14532+ si_noflush_read_lock(sb);
14533+ fi_read_lock(file);
b752ccd1 14534+ ii_read_lock_child(inode);
1facf9fc 14535+
4a4d8108
AM
14536+ err = flush(file, id);
14537+ au_cpup_attr_timesizes(inode);
1facf9fc 14538+
b752ccd1 14539+ ii_read_unlock(inode);
4a4d8108 14540+ fi_read_unlock(file);
1308ab2a 14541+ si_read_unlock(sb);
dece6358 14542+ return err;
1facf9fc 14543+}
14544+
4a4d8108
AM
14545+/* ---------------------------------------------------------------------- */
14546+
14547+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
1facf9fc 14548+{
4a4d8108 14549+ int err;
4a4d8108
AM
14550+ struct au_pin pin;
14551+ struct au_finfo *finfo;
c2b27bf2 14552+ struct dentry *parent, *hi_wh;
4a4d8108 14553+ struct inode *inode;
1facf9fc 14554+ struct super_block *sb;
c2b27bf2 14555+ struct au_cp_generic cpg = {
2000de60 14556+ .dentry = file->f_path.dentry,
c2b27bf2
AM
14557+ .bdst = -1,
14558+ .bsrc = -1,
14559+ .len = -1,
14560+ .pin = &pin,
14561+ .flags = AuCpup_DTIME
14562+ };
1facf9fc 14563+
4a4d8108
AM
14564+ FiMustWriteLock(file);
14565+
14566+ err = 0;
14567+ finfo = au_fi(file);
c2b27bf2 14568+ sb = cpg.dentry->d_sb;
5527c038 14569+ inode = d_inode(cpg.dentry);
5afbbe0d 14570+ cpg.bdst = au_ibtop(inode);
c2b27bf2 14571+ if (cpg.bdst == finfo->fi_btop || IS_ROOT(cpg.dentry))
1308ab2a 14572+ goto out;
dece6358 14573+
c2b27bf2
AM
14574+ parent = dget_parent(cpg.dentry);
14575+ if (au_test_ro(sb, cpg.bdst, inode)) {
4a4d8108 14576+ di_read_lock_parent(parent, !AuLock_IR);
c2b27bf2
AM
14577+ err = AuWbrCopyup(au_sbi(sb), cpg.dentry);
14578+ cpg.bdst = err;
4a4d8108
AM
14579+ di_read_unlock(parent, !AuLock_IR);
14580+ if (unlikely(err < 0))
14581+ goto out_parent;
14582+ err = 0;
1facf9fc 14583+ }
1facf9fc 14584+
4a4d8108 14585+ di_read_lock_parent(parent, AuLock_IR);
c2b27bf2 14586+ hi_wh = au_hi_wh(inode, cpg.bdst);
7f207e10
AM
14587+ if (!S_ISDIR(inode->i_mode)
14588+ && au_opt_test(au_mntflags(sb), PLINK)
4a4d8108 14589+ && au_plink_test(inode)
c2b27bf2 14590+ && !d_unhashed(cpg.dentry)
5afbbe0d 14591+ && cpg.bdst < au_dbtop(cpg.dentry)) {
c2b27bf2 14592+ err = au_test_and_cpup_dirs(cpg.dentry, cpg.bdst);
4a4d8108
AM
14593+ if (unlikely(err))
14594+ goto out_unlock;
14595+
14596+ /* always superio. */
c2b27bf2 14597+ err = au_pin(&pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE,
4a4d8108 14598+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
367653fa 14599+ if (!err) {
c2b27bf2 14600+ err = au_sio_cpup_simple(&cpg);
367653fa
AM
14601+ au_unpin(&pin);
14602+ }
4a4d8108
AM
14603+ } else if (hi_wh) {
14604+ /* already copied-up after unlink */
c2b27bf2 14605+ err = au_reopen_wh(file, cpg.bdst, hi_wh);
4a4d8108
AM
14606+ *need_reopen = 0;
14607+ }
1facf9fc 14608+
4f0767ce 14609+out_unlock:
4a4d8108 14610+ di_read_unlock(parent, AuLock_IR);
4f0767ce 14611+out_parent:
4a4d8108 14612+ dput(parent);
4f0767ce 14613+out:
1308ab2a 14614+ return err;
dece6358 14615+}
1facf9fc 14616+
4a4d8108 14617+static void au_do_refresh_dir(struct file *file)
dece6358 14618+{
5afbbe0d 14619+ aufs_bindex_t bindex, bbot, new_bindex, brid;
4a4d8108
AM
14620+ struct au_hfile *p, tmp, *q;
14621+ struct au_finfo *finfo;
1308ab2a 14622+ struct super_block *sb;
4a4d8108 14623+ struct au_fidir *fidir;
1facf9fc 14624+
4a4d8108 14625+ FiMustWriteLock(file);
1facf9fc 14626+
2000de60 14627+ sb = file->f_path.dentry->d_sb;
4a4d8108
AM
14628+ finfo = au_fi(file);
14629+ fidir = finfo->fi_hdir;
14630+ AuDebugOn(!fidir);
14631+ p = fidir->fd_hfile + finfo->fi_btop;
14632+ brid = p->hf_br->br_id;
5afbbe0d
AM
14633+ bbot = fidir->fd_bbot;
14634+ for (bindex = finfo->fi_btop; bindex <= bbot; bindex++, p++) {
4a4d8108
AM
14635+ if (!p->hf_file)
14636+ continue;
1308ab2a 14637+
4a4d8108
AM
14638+ new_bindex = au_br_index(sb, p->hf_br->br_id);
14639+ if (new_bindex == bindex)
14640+ continue;
14641+ if (new_bindex < 0) {
14642+ au_set_h_fptr(file, bindex, NULL);
14643+ continue;
14644+ }
1308ab2a 14645+
4a4d8108
AM
14646+ /* swap two lower inode, and loop again */
14647+ q = fidir->fd_hfile + new_bindex;
14648+ tmp = *q;
14649+ *q = *p;
14650+ *p = tmp;
14651+ if (tmp.hf_file) {
14652+ bindex--;
14653+ p--;
14654+ }
14655+ }
1308ab2a 14656+
4a4d8108 14657+ p = fidir->fd_hfile;
2000de60 14658+ if (!au_test_mmapped(file) && !d_unlinked(file->f_path.dentry)) {
5afbbe0d
AM
14659+ bbot = au_sbbot(sb);
14660+ for (finfo->fi_btop = 0; finfo->fi_btop <= bbot;
4a4d8108
AM
14661+ finfo->fi_btop++, p++)
14662+ if (p->hf_file) {
c06a8ce3 14663+ if (file_inode(p->hf_file))
4a4d8108 14664+ break;
1c60b727 14665+ au_hfput(p, /*execed*/0);
4a4d8108
AM
14666+ }
14667+ } else {
5afbbe0d
AM
14668+ bbot = au_br_index(sb, brid);
14669+ for (finfo->fi_btop = 0; finfo->fi_btop < bbot;
4a4d8108
AM
14670+ finfo->fi_btop++, p++)
14671+ if (p->hf_file)
1c60b727 14672+ au_hfput(p, /*execed*/0);
5afbbe0d 14673+ bbot = au_sbbot(sb);
4a4d8108 14674+ }
1308ab2a 14675+
5afbbe0d
AM
14676+ p = fidir->fd_hfile + bbot;
14677+ for (fidir->fd_bbot = bbot; fidir->fd_bbot >= finfo->fi_btop;
4a4d8108
AM
14678+ fidir->fd_bbot--, p--)
14679+ if (p->hf_file) {
c06a8ce3 14680+ if (file_inode(p->hf_file))
4a4d8108 14681+ break;
1c60b727 14682+ au_hfput(p, /*execed*/0);
4a4d8108
AM
14683+ }
14684+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
1308ab2a 14685+}
14686+
4a4d8108
AM
14687+/*
14688+ * after branch manipulating, refresh the file.
14689+ */
14690+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
1facf9fc 14691+{
e2f27e51 14692+ int err, need_reopen, nbr;
5afbbe0d 14693+ aufs_bindex_t bbot, bindex;
4a4d8108 14694+ struct dentry *dentry;
e2f27e51 14695+ struct super_block *sb;
1308ab2a 14696+ struct au_finfo *finfo;
4a4d8108 14697+ struct au_hfile *hfile;
1facf9fc 14698+
2000de60 14699+ dentry = file->f_path.dentry;
e2f27e51
AM
14700+ sb = dentry->d_sb;
14701+ nbr = au_sbbot(sb) + 1;
1308ab2a 14702+ finfo = au_fi(file);
4a4d8108
AM
14703+ if (!finfo->fi_hdir) {
14704+ hfile = &finfo->fi_htop;
14705+ AuDebugOn(!hfile->hf_file);
e2f27e51 14706+ bindex = au_br_index(sb, hfile->hf_br->br_id);
4a4d8108
AM
14707+ AuDebugOn(bindex < 0);
14708+ if (bindex != finfo->fi_btop)
5afbbe0d 14709+ au_set_fbtop(file, bindex);
4a4d8108 14710+ } else {
e2f27e51 14711+ err = au_fidir_realloc(finfo, nbr, /*may_shrink*/0);
4a4d8108
AM
14712+ if (unlikely(err))
14713+ goto out;
14714+ au_do_refresh_dir(file);
14715+ }
1facf9fc 14716+
4a4d8108
AM
14717+ err = 0;
14718+ need_reopen = 1;
14719+ if (!au_test_mmapped(file))
14720+ err = au_file_refresh_by_inode(file, &need_reopen);
e2f27e51
AM
14721+ if (finfo->fi_hdir)
14722+ /* harmless if err */
14723+ au_fidir_realloc(finfo, nbr, /*may_shrink*/1);
027c5e7a 14724+ if (!err && need_reopen && !d_unlinked(dentry))
4a4d8108
AM
14725+ err = reopen(file);
14726+ if (!err) {
14727+ au_update_figen(file);
14728+ goto out; /* success */
14729+ }
14730+
14731+ /* error, close all lower files */
14732+ if (finfo->fi_hdir) {
5afbbe0d
AM
14733+ bbot = au_fbbot_dir(file);
14734+ for (bindex = au_fbtop(file); bindex <= bbot; bindex++)
4a4d8108
AM
14735+ au_set_h_fptr(file, bindex, NULL);
14736+ }
1facf9fc 14737+
4f0767ce 14738+out:
1facf9fc 14739+ return err;
14740+}
14741+
4a4d8108
AM
14742+/* common function to regular file and dir */
14743+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
521ced18 14744+ int wlock, unsigned int fi_lsc)
dece6358 14745+{
1308ab2a 14746+ int err;
4a4d8108 14747+ unsigned int sigen, figen;
5afbbe0d 14748+ aufs_bindex_t btop;
4a4d8108
AM
14749+ unsigned char pseudo_link;
14750+ struct dentry *dentry;
14751+ struct inode *inode;
1facf9fc 14752+
4a4d8108 14753+ err = 0;
2000de60 14754+ dentry = file->f_path.dentry;
5527c038 14755+ inode = d_inode(dentry);
4a4d8108 14756+ sigen = au_sigen(dentry->d_sb);
521ced18 14757+ fi_write_lock_nested(file, fi_lsc);
4a4d8108 14758+ figen = au_figen(file);
521ced18
JR
14759+ if (!fi_lsc)
14760+ di_write_lock_child(dentry);
14761+ else
14762+ di_write_lock_child2(dentry);
5afbbe0d
AM
14763+ btop = au_dbtop(dentry);
14764+ pseudo_link = (btop != au_ibtop(inode));
14765+ if (sigen == figen && !pseudo_link && au_fbtop(file) == btop) {
4a4d8108
AM
14766+ if (!wlock) {
14767+ di_downgrade_lock(dentry, AuLock_IR);
14768+ fi_downgrade_lock(file);
14769+ }
14770+ goto out; /* success */
14771+ }
dece6358 14772+
4a4d8108 14773+ AuDbg("sigen %d, figen %d\n", sigen, figen);
027c5e7a 14774+ if (au_digen_test(dentry, sigen)) {
4a4d8108 14775+ err = au_reval_dpath(dentry, sigen);
027c5e7a 14776+ AuDebugOn(!err && au_digen_test(dentry, sigen));
4a4d8108 14777+ }
dece6358 14778+
027c5e7a
AM
14779+ if (!err)
14780+ err = refresh_file(file, reopen);
4a4d8108
AM
14781+ if (!err) {
14782+ if (!wlock) {
14783+ di_downgrade_lock(dentry, AuLock_IR);
14784+ fi_downgrade_lock(file);
14785+ }
14786+ } else {
14787+ di_write_unlock(dentry);
14788+ fi_write_unlock(file);
14789+ }
1facf9fc 14790+
4f0767ce 14791+out:
1308ab2a 14792+ return err;
14793+}
1facf9fc 14794+
4a4d8108
AM
14795+/* ---------------------------------------------------------------------- */
14796+
14797+/* cf. aufs_nopage() */
14798+/* for madvise(2) */
14799+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
1308ab2a 14800+{
4a4d8108
AM
14801+ unlock_page(page);
14802+ return 0;
14803+}
1facf9fc 14804+
4a4d8108 14805+/* it will never be called, but necessary to support O_DIRECT */
5afbbe0d 14806+static ssize_t aufs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
4a4d8108 14807+{ BUG(); return 0; }
1facf9fc 14808+
4a4d8108
AM
14809+/* they will never be called. */
14810+#ifdef CONFIG_AUFS_DEBUG
14811+static int aufs_write_begin(struct file *file, struct address_space *mapping,
14812+ loff_t pos, unsigned len, unsigned flags,
14813+ struct page **pagep, void **fsdata)
14814+{ AuUnsupport(); return 0; }
14815+static int aufs_write_end(struct file *file, struct address_space *mapping,
14816+ loff_t pos, unsigned len, unsigned copied,
14817+ struct page *page, void *fsdata)
14818+{ AuUnsupport(); return 0; }
14819+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
14820+{ AuUnsupport(); return 0; }
1308ab2a 14821+
4a4d8108
AM
14822+static int aufs_set_page_dirty(struct page *page)
14823+{ AuUnsupport(); return 0; }
392086de
AM
14824+static void aufs_invalidatepage(struct page *page, unsigned int offset,
14825+ unsigned int length)
4a4d8108
AM
14826+{ AuUnsupport(); }
14827+static int aufs_releasepage(struct page *page, gfp_t gfp)
14828+{ AuUnsupport(); return 0; }
79b8bda9 14829+#if 0 /* called by memory compaction regardless file */
4a4d8108 14830+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
7eafdf33 14831+ struct page *page, enum migrate_mode mode)
4a4d8108 14832+{ AuUnsupport(); return 0; }
79b8bda9 14833+#endif
e2f27e51
AM
14834+static bool aufs_isolate_page(struct page *page, isolate_mode_t mode)
14835+{ AuUnsupport(); return true; }
14836+static void aufs_putback_page(struct page *page)
14837+{ AuUnsupport(); }
4a4d8108
AM
14838+static int aufs_launder_page(struct page *page)
14839+{ AuUnsupport(); return 0; }
14840+static int aufs_is_partially_uptodate(struct page *page,
38d290e6
JR
14841+ unsigned long from,
14842+ unsigned long count)
4a4d8108 14843+{ AuUnsupport(); return 0; }
392086de
AM
14844+static void aufs_is_dirty_writeback(struct page *page, bool *dirty,
14845+ bool *writeback)
14846+{ AuUnsupport(); }
4a4d8108
AM
14847+static int aufs_error_remove_page(struct address_space *mapping,
14848+ struct page *page)
14849+{ AuUnsupport(); return 0; }
b4510431
AM
14850+static int aufs_swap_activate(struct swap_info_struct *sis, struct file *file,
14851+ sector_t *span)
14852+{ AuUnsupport(); return 0; }
14853+static void aufs_swap_deactivate(struct file *file)
14854+{ AuUnsupport(); }
4a4d8108
AM
14855+#endif /* CONFIG_AUFS_DEBUG */
14856+
14857+const struct address_space_operations aufs_aop = {
14858+ .readpage = aufs_readpage,
14859+ .direct_IO = aufs_direct_IO,
4a4d8108
AM
14860+#ifdef CONFIG_AUFS_DEBUG
14861+ .writepage = aufs_writepage,
4a4d8108
AM
14862+ /* no writepages, because of writepage */
14863+ .set_page_dirty = aufs_set_page_dirty,
14864+ /* no readpages, because of readpage */
14865+ .write_begin = aufs_write_begin,
14866+ .write_end = aufs_write_end,
14867+ /* no bmap, no block device */
14868+ .invalidatepage = aufs_invalidatepage,
14869+ .releasepage = aufs_releasepage,
79b8bda9
AM
14870+ /* is fallback_migrate_page ok? */
14871+ /* .migratepage = aufs_migratepage, */
e2f27e51
AM
14872+ .isolate_page = aufs_isolate_page,
14873+ .putback_page = aufs_putback_page,
4a4d8108
AM
14874+ .launder_page = aufs_launder_page,
14875+ .is_partially_uptodate = aufs_is_partially_uptodate,
392086de 14876+ .is_dirty_writeback = aufs_is_dirty_writeback,
b4510431
AM
14877+ .error_remove_page = aufs_error_remove_page,
14878+ .swap_activate = aufs_swap_activate,
14879+ .swap_deactivate = aufs_swap_deactivate
4a4d8108 14880+#endif /* CONFIG_AUFS_DEBUG */
dece6358 14881+};
7f207e10 14882diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
eca34b5c 14883--- /usr/share/empty/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
319657f6 14884+++ linux/fs/aufs/file.h 2021-12-03 15:38:59.936647310 +0100
9f237c51 14885@@ -0,0 +1,342 @@
062440b3 14886+/* SPDX-License-Identifier: GPL-2.0 */
4a4d8108 14887+/*
6d176551 14888+ * Copyright (C) 2005-2021 Junjiro R. Okajima
4a4d8108
AM
14889+ *
14890+ * This program, aufs is free software; you can redistribute it and/or modify
14891+ * it under the terms of the GNU General Public License as published by
14892+ * the Free Software Foundation; either version 2 of the License, or
14893+ * (at your option) any later version.
14894+ *
14895+ * This program is distributed in the hope that it will be useful,
14896+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14897+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14898+ * GNU General Public License for more details.
14899+ *
14900+ * You should have received a copy of the GNU General Public License
523b37e3 14901+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 14902+ */
1facf9fc 14903+
4a4d8108
AM
14904+/*
14905+ * file operations
14906+ */
1facf9fc 14907+
4a4d8108
AM
14908+#ifndef __AUFS_FILE_H__
14909+#define __AUFS_FILE_H__
1facf9fc 14910+
4a4d8108 14911+#ifdef __KERNEL__
1facf9fc 14912+
2cbb1c4b 14913+#include <linux/file.h>
4a4d8108 14914+#include <linux/fs.h>
3c1bdaff 14915+#include <linux/mm_types.h>
4a4d8108 14916+#include <linux/poll.h>
4a4d8108 14917+#include "rwsem.h"
1facf9fc 14918+
4a4d8108
AM
14919+struct au_branch;
14920+struct au_hfile {
14921+ struct file *hf_file;
14922+ struct au_branch *hf_br;
14923+};
1facf9fc 14924+
4a4d8108
AM
14925+struct au_vdir;
14926+struct au_fidir {
14927+ aufs_bindex_t fd_bbot;
14928+ aufs_bindex_t fd_nent;
14929+ struct au_vdir *fd_vdir_cache;
14930+ struct au_hfile fd_hfile[];
14931+};
1facf9fc 14932+
4a4d8108 14933+static inline int au_fidir_sz(int nent)
dece6358 14934+{
4f0767ce
JR
14935+ AuDebugOn(nent < 0);
14936+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
4a4d8108 14937+}
1facf9fc 14938+
4a4d8108
AM
14939+struct au_finfo {
14940+ atomic_t fi_generation;
dece6358 14941+
4a4d8108
AM
14942+ struct au_rwsem fi_rwsem;
14943+ aufs_bindex_t fi_btop;
14944+
14945+ /* do not union them */
14946+ struct { /* for non-dir */
14947+ struct au_hfile fi_htop;
2cbb1c4b 14948+ atomic_t fi_mmapped;
4a4d8108
AM
14949+ };
14950+ struct au_fidir *fi_hdir; /* for dir only */
523b37e3 14951+
8b6a4947 14952+ struct hlist_bl_node fi_hlist;
1c60b727 14953+ struct file *fi_file; /* very ugly */
9f237c51 14954+ struct rcu_head rcu;
4a4d8108 14955+} ____cacheline_aligned_in_smp;
1facf9fc 14956+
4a4d8108 14957+/* ---------------------------------------------------------------------- */
1facf9fc 14958+
4a4d8108
AM
14959+/* file.c */
14960+extern const struct address_space_operations aufs_aop;
14961+unsigned int au_file_roflags(unsigned int flags);
14962+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
392086de 14963+ struct file *file, int force_wr);
b912730e 14964+struct au_do_open_args {
8b6a4947 14965+ int aopen;
b912730e
AM
14966+ int (*open)(struct file *file, int flags,
14967+ struct file *h_file);
14968+ struct au_fidir *fidir;
14969+ struct file *h_file;
14970+};
14971+int au_do_open(struct file *file, struct au_do_open_args *args);
4a4d8108
AM
14972+int au_reopen_nondir(struct file *file);
14973+struct au_pin;
14974+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
14975+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
521ced18 14976+ int wlock, unsigned int fi_lsc);
4a4d8108
AM
14977+int au_do_flush(struct file *file, fl_owner_t id,
14978+ int (*flush)(struct file *file, fl_owner_t id));
1facf9fc 14979+
4a4d8108
AM
14980+/* poll.c */
14981+#ifdef CONFIG_AUFS_POLL
cd7a4cd9 14982+__poll_t aufs_poll(struct file *file, struct poll_table_struct *pt);
4a4d8108 14983+#endif
1facf9fc 14984+
4a4d8108
AM
14985+#ifdef CONFIG_AUFS_BR_HFSPLUS
14986+/* hfsplus.c */
392086de
AM
14987+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex,
14988+ int force_wr);
4a4d8108
AM
14989+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
14990+ struct file *h_file);
14991+#else
c1595e42
JR
14992+AuStub(struct file *, au_h_open_pre, return NULL, struct dentry *dentry,
14993+ aufs_bindex_t bindex, int force_wr)
4a4d8108
AM
14994+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
14995+ struct file *h_file);
14996+#endif
1facf9fc 14997+
4a4d8108
AM
14998+/* f_op.c */
14999+extern const struct file_operations aufs_file_fop;
b912730e 15000+int au_do_open_nondir(struct file *file, int flags, struct file *h_file);
4a4d8108 15001+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
521ced18 15002+struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc);
4a4d8108 15003+
4a4d8108 15004+/* finfo.c */
f0c0a007 15005+void au_hfput(struct au_hfile *hf, int execed);
4a4d8108
AM
15006+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
15007+ struct file *h_file);
1facf9fc 15008+
4a4d8108 15009+void au_update_figen(struct file *file);
4a4d8108 15010+struct au_fidir *au_fidir_alloc(struct super_block *sb);
e2f27e51 15011+int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink);
1facf9fc 15012+
4a4d8108 15013+void au_fi_init_once(void *_fi);
1c60b727 15014+void au_finfo_fin(struct file *file);
4a4d8108 15015+int au_finfo_init(struct file *file, struct au_fidir *fidir);
1facf9fc 15016+
4a4d8108
AM
15017+/* ioctl.c */
15018+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
15019+#ifdef CONFIG_COMPAT
15020+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
15021+ unsigned long arg);
c2b27bf2
AM
15022+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
15023+ unsigned long arg);
b752ccd1 15024+#endif
1facf9fc 15025+
4a4d8108 15026+/* ---------------------------------------------------------------------- */
1facf9fc 15027+
4a4d8108
AM
15028+static inline struct au_finfo *au_fi(struct file *file)
15029+{
38d290e6 15030+ return file->private_data;
4a4d8108 15031+}
1facf9fc 15032+
4a4d8108 15033+/* ---------------------------------------------------------------------- */
1facf9fc 15034+
8b6a4947
AM
15035+#define fi_read_lock(f) au_rw_read_lock(&au_fi(f)->fi_rwsem)
15036+#define fi_write_lock(f) au_rw_write_lock(&au_fi(f)->fi_rwsem)
15037+#define fi_read_trylock(f) au_rw_read_trylock(&au_fi(f)->fi_rwsem)
15038+#define fi_write_trylock(f) au_rw_write_trylock(&au_fi(f)->fi_rwsem)
4a4d8108 15039+/*
8b6a4947
AM
15040+#define fi_read_trylock_nested(f) \
15041+ au_rw_read_trylock_nested(&au_fi(f)->fi_rwsem)
15042+#define fi_write_trylock_nested(f) \
15043+ au_rw_write_trylock_nested(&au_fi(f)->fi_rwsem)
15044+*/
15045+
15046+#define fi_read_unlock(f) au_rw_read_unlock(&au_fi(f)->fi_rwsem)
15047+#define fi_write_unlock(f) au_rw_write_unlock(&au_fi(f)->fi_rwsem)
15048+#define fi_downgrade_lock(f) au_rw_dgrade_lock(&au_fi(f)->fi_rwsem)
1308ab2a 15049+
521ced18
JR
15050+/* lock subclass for finfo */
15051+enum {
15052+ AuLsc_FI_1,
15053+ AuLsc_FI_2
15054+};
15055+
15056+static inline void fi_read_lock_nested(struct file *f, unsigned int lsc)
15057+{
15058+ au_rw_read_lock_nested(&au_fi(f)->fi_rwsem, lsc);
15059+}
15060+
15061+static inline void fi_write_lock_nested(struct file *f, unsigned int lsc)
15062+{
15063+ au_rw_write_lock_nested(&au_fi(f)->fi_rwsem, lsc);
15064+}
15065+
15066+/*
15067+ * fi_read_lock_1, fi_write_lock_1,
15068+ * fi_read_lock_2, fi_write_lock_2
15069+ */
15070+#define AuReadLockFunc(name) \
15071+static inline void fi_read_lock_##name(struct file *f) \
15072+{ fi_read_lock_nested(f, AuLsc_FI_##name); }
15073+
15074+#define AuWriteLockFunc(name) \
15075+static inline void fi_write_lock_##name(struct file *f) \
15076+{ fi_write_lock_nested(f, AuLsc_FI_##name); }
15077+
15078+#define AuRWLockFuncs(name) \
15079+ AuReadLockFunc(name) \
15080+ AuWriteLockFunc(name)
15081+
15082+AuRWLockFuncs(1);
15083+AuRWLockFuncs(2);
15084+
15085+#undef AuReadLockFunc
15086+#undef AuWriteLockFunc
15087+#undef AuRWLockFuncs
15088+
4a4d8108
AM
15089+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
15090+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
15091+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 15092+
1308ab2a 15093+/* ---------------------------------------------------------------------- */
15094+
4a4d8108 15095+/* todo: hard/soft set? */
5afbbe0d 15096+static inline aufs_bindex_t au_fbtop(struct file *file)
dece6358 15097+{
4a4d8108
AM
15098+ FiMustAnyLock(file);
15099+ return au_fi(file)->fi_btop;
15100+}
dece6358 15101+
5afbbe0d 15102+static inline aufs_bindex_t au_fbbot_dir(struct file *file)
4a4d8108
AM
15103+{
15104+ FiMustAnyLock(file);
15105+ AuDebugOn(!au_fi(file)->fi_hdir);
15106+ return au_fi(file)->fi_hdir->fd_bbot;
15107+}
1facf9fc 15108+
4a4d8108
AM
15109+static inline struct au_vdir *au_fvdir_cache(struct file *file)
15110+{
15111+ FiMustAnyLock(file);
15112+ AuDebugOn(!au_fi(file)->fi_hdir);
15113+ return au_fi(file)->fi_hdir->fd_vdir_cache;
15114+}
1facf9fc 15115+
5afbbe0d 15116+static inline void au_set_fbtop(struct file *file, aufs_bindex_t bindex)
4a4d8108
AM
15117+{
15118+ FiMustWriteLock(file);
15119+ au_fi(file)->fi_btop = bindex;
15120+}
1facf9fc 15121+
5afbbe0d 15122+static inline void au_set_fbbot_dir(struct file *file, aufs_bindex_t bindex)
4a4d8108
AM
15123+{
15124+ FiMustWriteLock(file);
15125+ AuDebugOn(!au_fi(file)->fi_hdir);
15126+ au_fi(file)->fi_hdir->fd_bbot = bindex;
15127+}
1308ab2a 15128+
4a4d8108
AM
15129+static inline void au_set_fvdir_cache(struct file *file,
15130+ struct au_vdir *vdir_cache)
15131+{
15132+ FiMustWriteLock(file);
15133+ AuDebugOn(!au_fi(file)->fi_hdir);
15134+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
15135+}
dece6358 15136+
4a4d8108
AM
15137+static inline struct file *au_hf_top(struct file *file)
15138+{
15139+ FiMustAnyLock(file);
15140+ AuDebugOn(au_fi(file)->fi_hdir);
15141+ return au_fi(file)->fi_htop.hf_file;
15142+}
1facf9fc 15143+
4a4d8108
AM
15144+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
15145+{
15146+ FiMustAnyLock(file);
15147+ AuDebugOn(!au_fi(file)->fi_hdir);
15148+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
dece6358
AM
15149+}
15150+
4a4d8108
AM
15151+/* todo: memory barrier? */
15152+static inline unsigned int au_figen(struct file *f)
dece6358 15153+{
4a4d8108
AM
15154+ return atomic_read(&au_fi(f)->fi_generation);
15155+}
dece6358 15156+
2cbb1c4b
JR
15157+static inline void au_set_mmapped(struct file *f)
15158+{
15159+ if (atomic_inc_return(&au_fi(f)->fi_mmapped))
15160+ return;
0c3ec466 15161+ pr_warn("fi_mmapped wrapped around\n");
2cbb1c4b
JR
15162+ while (!atomic_inc_return(&au_fi(f)->fi_mmapped))
15163+ ;
15164+}
15165+
15166+static inline void au_unset_mmapped(struct file *f)
15167+{
15168+ atomic_dec(&au_fi(f)->fi_mmapped);
15169+}
15170+
4a4d8108
AM
15171+static inline int au_test_mmapped(struct file *f)
15172+{
2cbb1c4b
JR
15173+ return atomic_read(&au_fi(f)->fi_mmapped);
15174+}
15175+
15176+/* customize vma->vm_file */
15177+
15178+static inline void au_do_vm_file_reset(struct vm_area_struct *vma,
15179+ struct file *file)
15180+{
53392da6
AM
15181+ struct file *f;
15182+
15183+ f = vma->vm_file;
2cbb1c4b
JR
15184+ get_file(file);
15185+ vma->vm_file = file;
53392da6 15186+ fput(f);
2cbb1c4b
JR
15187+}
15188+
15189+#ifdef CONFIG_MMU
15190+#define AuDbgVmRegion(file, vma) do {} while (0)
15191+
15192+static inline void au_vm_file_reset(struct vm_area_struct *vma,
15193+ struct file *file)
15194+{
15195+ au_do_vm_file_reset(vma, file);
15196+}
15197+#else
15198+#define AuDbgVmRegion(file, vma) \
15199+ AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file))
15200+
15201+static inline void au_vm_file_reset(struct vm_area_struct *vma,
15202+ struct file *file)
15203+{
53392da6
AM
15204+ struct file *f;
15205+
2cbb1c4b 15206+ au_do_vm_file_reset(vma, file);
53392da6 15207+ f = vma->vm_region->vm_file;
2cbb1c4b
JR
15208+ get_file(file);
15209+ vma->vm_region->vm_file = file;
53392da6 15210+ fput(f);
2cbb1c4b
JR
15211+}
15212+#endif /* CONFIG_MMU */
15213+
15214+/* handle vma->vm_prfile */
fb47a38f 15215+static inline void au_vm_prfile_set(struct vm_area_struct *vma,
2cbb1c4b
JR
15216+ struct file *file)
15217+{
2cbb1c4b
JR
15218+ get_file(file);
15219+ vma->vm_prfile = file;
15220+#ifndef CONFIG_MMU
15221+ get_file(file);
15222+ vma->vm_region->vm_prfile = file;
15223+#endif
fb47a38f 15224+}
1308ab2a 15225+
4a4d8108
AM
15226+#endif /* __KERNEL__ */
15227+#endif /* __AUFS_FILE_H__ */
7f207e10 15228diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
eca34b5c 15229--- /usr/share/empty/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
319657f6 15230+++ linux/fs/aufs/finfo.c 2021-12-03 15:38:59.936647310 +0100
062440b3 15231@@ -0,0 +1,149 @@
cd7a4cd9 15232+// SPDX-License-Identifier: GPL-2.0
4a4d8108 15233+/*
6d176551 15234+ * Copyright (C) 2005-2021 Junjiro R. Okajima
4a4d8108
AM
15235+ *
15236+ * This program, aufs is free software; you can redistribute it and/or modify
15237+ * it under the terms of the GNU General Public License as published by
15238+ * the Free Software Foundation; either version 2 of the License, or
15239+ * (at your option) any later version.
15240+ *
15241+ * This program is distributed in the hope that it will be useful,
15242+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15243+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15244+ * GNU General Public License for more details.
15245+ *
15246+ * You should have received a copy of the GNU General Public License
523b37e3 15247+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 15248+ */
1308ab2a 15249+
4a4d8108
AM
15250+/*
15251+ * file private data
15252+ */
1facf9fc 15253+
4a4d8108 15254+#include "aufs.h"
1facf9fc 15255+
f0c0a007 15256+void au_hfput(struct au_hfile *hf, int execed)
4a4d8108 15257+{
f0c0a007 15258+ if (execed)
4a4d8108
AM
15259+ allow_write_access(hf->hf_file);
15260+ fput(hf->hf_file);
15261+ hf->hf_file = NULL;
acd2b654 15262+ au_lcnt_dec(&hf->hf_br->br_nfiles);
4a4d8108
AM
15263+ hf->hf_br = NULL;
15264+}
1facf9fc 15265+
4a4d8108
AM
15266+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
15267+{
15268+ struct au_finfo *finfo = au_fi(file);
15269+ struct au_hfile *hf;
15270+ struct au_fidir *fidir;
15271+
15272+ fidir = finfo->fi_hdir;
15273+ if (!fidir) {
15274+ AuDebugOn(finfo->fi_btop != bindex);
15275+ hf = &finfo->fi_htop;
15276+ } else
15277+ hf = fidir->fd_hfile + bindex;
15278+
15279+ if (hf && hf->hf_file)
f0c0a007 15280+ au_hfput(hf, vfsub_file_execed(file));
4a4d8108
AM
15281+ if (val) {
15282+ FiMustWriteLock(file);
b912730e 15283+ AuDebugOn(IS_ERR_OR_NULL(file->f_path.dentry));
4a4d8108 15284+ hf->hf_file = val;
2000de60 15285+ hf->hf_br = au_sbr(file->f_path.dentry->d_sb, bindex);
1308ab2a 15286+ }
4a4d8108 15287+}
1facf9fc 15288+
4a4d8108
AM
15289+void au_update_figen(struct file *file)
15290+{
2000de60 15291+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_path.dentry));
4a4d8108 15292+ /* smp_mb(); */ /* atomic_set */
1facf9fc 15293+}
15294+
4a4d8108
AM
15295+/* ---------------------------------------------------------------------- */
15296+
4a4d8108
AM
15297+struct au_fidir *au_fidir_alloc(struct super_block *sb)
15298+{
15299+ struct au_fidir *fidir;
15300+ int nbr;
15301+
5afbbe0d 15302+ nbr = au_sbbot(sb) + 1;
4a4d8108
AM
15303+ if (nbr < 2)
15304+ nbr = 2; /* initial allocate for 2 branches */
15305+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
15306+ if (fidir) {
15307+ fidir->fd_bbot = -1;
15308+ fidir->fd_nent = nbr;
4a4d8108
AM
15309+ }
15310+
15311+ return fidir;
15312+}
15313+
e2f27e51 15314+int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink)
4a4d8108
AM
15315+{
15316+ int err;
15317+ struct au_fidir *fidir, *p;
15318+
15319+ AuRwMustWriteLock(&finfo->fi_rwsem);
15320+ fidir = finfo->fi_hdir;
15321+ AuDebugOn(!fidir);
15322+
15323+ err = -ENOMEM;
15324+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
e2f27e51 15325+ GFP_NOFS, may_shrink);
4a4d8108
AM
15326+ if (p) {
15327+ p->fd_nent = nbr;
15328+ finfo->fi_hdir = p;
15329+ err = 0;
15330+ }
1facf9fc 15331+
dece6358 15332+ return err;
1facf9fc 15333+}
1308ab2a 15334+
15335+/* ---------------------------------------------------------------------- */
15336+
1c60b727 15337+void au_finfo_fin(struct file *file)
1308ab2a 15338+{
4a4d8108
AM
15339+ struct au_finfo *finfo;
15340+
acd2b654 15341+ au_lcnt_dec(&au_sbi(file->f_path.dentry->d_sb)->si_nfiles);
7f207e10 15342+
4a4d8108
AM
15343+ finfo = au_fi(file);
15344+ AuDebugOn(finfo->fi_hdir);
15345+ AuRwDestroy(&finfo->fi_rwsem);
1c60b727 15346+ au_cache_free_finfo(finfo);
1308ab2a 15347+}
1308ab2a 15348+
e49829fe 15349+void au_fi_init_once(void *_finfo)
4a4d8108 15350+{
e49829fe 15351+ struct au_finfo *finfo = _finfo;
1308ab2a 15352+
e49829fe 15353+ au_rw_init(&finfo->fi_rwsem);
4a4d8108 15354+}
1308ab2a 15355+
4a4d8108
AM
15356+int au_finfo_init(struct file *file, struct au_fidir *fidir)
15357+{
1716fcea 15358+ int err;
4a4d8108
AM
15359+ struct au_finfo *finfo;
15360+ struct dentry *dentry;
15361+
15362+ err = -ENOMEM;
2000de60 15363+ dentry = file->f_path.dentry;
4a4d8108
AM
15364+ finfo = au_cache_alloc_finfo();
15365+ if (unlikely(!finfo))
15366+ goto out;
15367+
15368+ err = 0;
acd2b654 15369+ au_lcnt_inc(&au_sbi(dentry->d_sb)->si_nfiles);
4a4d8108
AM
15370+ au_rw_write_lock(&finfo->fi_rwsem);
15371+ finfo->fi_btop = -1;
15372+ finfo->fi_hdir = fidir;
15373+ atomic_set(&finfo->fi_generation, au_digen(dentry));
15374+ /* smp_mb(); */ /* atomic_set */
15375+
15376+ file->private_data = finfo;
15377+
15378+out:
15379+ return err;
15380+}
7f207e10 15381diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
eca34b5c 15382--- /usr/share/empty/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
319657f6 15383+++ linux/fs/aufs/f_op.c 2021-12-03 15:38:59.933313976 +0100
0b2a12c6 15384@@ -0,0 +1,771 @@
cd7a4cd9 15385+// SPDX-License-Identifier: GPL-2.0
dece6358 15386+/*
6d176551 15387+ * Copyright (C) 2005-2021 Junjiro R. Okajima
dece6358
AM
15388+ *
15389+ * This program, aufs is free software; you can redistribute it and/or modify
15390+ * it under the terms of the GNU General Public License as published by
15391+ * the Free Software Foundation; either version 2 of the License, or
15392+ * (at your option) any later version.
15393+ *
15394+ * This program is distributed in the hope that it will be useful,
15395+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15396+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15397+ * GNU General Public License for more details.
15398+ *
15399+ * You should have received a copy of the GNU General Public License
523b37e3 15400+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
dece6358 15401+ */
1facf9fc 15402+
15403+/*
4a4d8108 15404+ * file and vm operations
1facf9fc 15405+ */
dece6358 15406+
86dc4139 15407+#include <linux/aio.h>
4a4d8108
AM
15408+#include <linux/fs_stack.h>
15409+#include <linux/mman.h>
4a4d8108 15410+#include <linux/security.h>
dece6358
AM
15411+#include "aufs.h"
15412+
b912730e 15413+int au_do_open_nondir(struct file *file, int flags, struct file *h_file)
1facf9fc 15414+{
4a4d8108
AM
15415+ int err;
15416+ aufs_bindex_t bindex;
8cdd5066 15417+ struct dentry *dentry, *h_dentry;
4a4d8108 15418+ struct au_finfo *finfo;
38d290e6 15419+ struct inode *h_inode;
4a4d8108
AM
15420+
15421+ FiMustWriteLock(file);
15422+
523b37e3 15423+ err = 0;
2000de60 15424+ dentry = file->f_path.dentry;
b912730e 15425+ AuDebugOn(IS_ERR_OR_NULL(dentry));
4a4d8108
AM
15426+ finfo = au_fi(file);
15427+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
2cbb1c4b 15428+ atomic_set(&finfo->fi_mmapped, 0);
5afbbe0d 15429+ bindex = au_dbtop(dentry);
8cdd5066
JR
15430+ if (!h_file) {
15431+ h_dentry = au_h_dptr(dentry, bindex);
15432+ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb);
15433+ if (unlikely(err))
15434+ goto out;
b912730e 15435+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0);
acd2b654
AM
15436+ if (IS_ERR(h_file)) {
15437+ err = PTR_ERR(h_file);
15438+ goto out;
15439+ }
8cdd5066
JR
15440+ } else {
15441+ h_dentry = h_file->f_path.dentry;
15442+ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb);
15443+ if (unlikely(err))
15444+ goto out;
acd2b654 15445+ /* br ref is already inc-ed */
8cdd5066 15446+ }
acd2b654
AM
15447+
15448+ if ((flags & __O_TMPFILE)
15449+ && !(flags & O_EXCL)) {
15450+ h_inode = file_inode(h_file);
15451+ spin_lock(&h_inode->i_lock);
15452+ h_inode->i_state |= I_LINKABLE;
15453+ spin_unlock(&h_inode->i_lock);
4a4d8108 15454+ }
acd2b654
AM
15455+ au_set_fbtop(file, bindex);
15456+ au_set_h_fptr(file, bindex, h_file);
15457+ au_update_figen(file);
15458+ /* todo: necessary? */
15459+ /* file->f_ra = h_file->f_ra; */
027c5e7a 15460+
8cdd5066 15461+out:
4a4d8108 15462+ return err;
1facf9fc 15463+}
15464+
4a4d8108
AM
15465+static int aufs_open_nondir(struct inode *inode __maybe_unused,
15466+ struct file *file)
1facf9fc 15467+{
4a4d8108 15468+ int err;
1308ab2a 15469+ struct super_block *sb;
b912730e
AM
15470+ struct au_do_open_args args = {
15471+ .open = au_do_open_nondir
15472+ };
1facf9fc 15473+
523b37e3
AM
15474+ AuDbg("%pD, f_flags 0x%x, f_mode 0x%x\n",
15475+ file, vfsub_file_flags(file), file->f_mode);
1facf9fc 15476+
2000de60 15477+ sb = file->f_path.dentry->d_sb;
4a4d8108 15478+ si_read_lock(sb, AuLock_FLUSH);
b912730e 15479+ err = au_do_open(file, &args);
4a4d8108
AM
15480+ si_read_unlock(sb);
15481+ return err;
15482+}
1facf9fc 15483+
4a4d8108
AM
15484+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
15485+{
15486+ struct au_finfo *finfo;
15487+ aufs_bindex_t bindex;
1facf9fc 15488+
4a4d8108 15489+ finfo = au_fi(file);
8b6a4947
AM
15490+ au_hbl_del(&finfo->fi_hlist,
15491+ &au_sbi(file->f_path.dentry->d_sb)->si_files);
4a4d8108 15492+ bindex = finfo->fi_btop;
b4510431 15493+ if (bindex >= 0)
4a4d8108 15494+ au_set_h_fptr(file, bindex, NULL);
7f207e10 15495+
1c60b727 15496+ au_finfo_fin(file);
4a4d8108 15497+ return 0;
1facf9fc 15498+}
15499+
4a4d8108
AM
15500+/* ---------------------------------------------------------------------- */
15501+
15502+static int au_do_flush_nondir(struct file *file, fl_owner_t id)
dece6358 15503+{
1308ab2a 15504+ int err;
4a4d8108
AM
15505+ struct file *h_file;
15506+
15507+ err = 0;
15508+ h_file = au_hf_top(file);
15509+ if (h_file)
15510+ err = vfsub_flush(h_file, id);
15511+ return err;
15512+}
15513+
15514+static int aufs_flush_nondir(struct file *file, fl_owner_t id)
15515+{
15516+ return au_do_flush(file, id, au_do_flush_nondir);
15517+}
15518+
15519+/* ---------------------------------------------------------------------- */
9dbd164d
AM
15520+/*
15521+ * read and write functions acquire [fdi]_rwsem once, but release before
15522+ * mmap_sem. This is because to stop a race condition between mmap(2).
acd2b654 15523+ * Releasing these aufs-rwsem should be safe, no branch-management (by keeping
9dbd164d
AM
15524+ * si_rwsem), no harmful copy-up should happen. Actually copy-up may happen in
15525+ * read functions after [fdi]_rwsem are released, but it should be harmless.
15526+ */
4a4d8108 15527+
b912730e 15528+/* Callers should call au_read_post() or fput() in the end */
521ced18 15529+struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc)
4a4d8108 15530+{
4a4d8108 15531+ struct file *h_file;
b912730e 15532+ int err;
1facf9fc 15533+
521ced18 15534+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0, lsc);
b912730e
AM
15535+ if (!err) {
15536+ di_read_unlock(file->f_path.dentry, AuLock_IR);
15537+ h_file = au_hf_top(file);
15538+ get_file(h_file);
15539+ if (!keep_fi)
15540+ fi_read_unlock(file);
15541+ } else
15542+ h_file = ERR_PTR(err);
15543+
15544+ return h_file;
15545+}
15546+
15547+static void au_read_post(struct inode *inode, struct file *h_file)
15548+{
15549+ /* update without lock, I don't think it a problem */
15550+ fsstack_copy_attr_atime(inode, file_inode(h_file));
15551+ fput(h_file);
15552+}
15553+
15554+struct au_write_pre {
521ced18
JR
15555+ /* input */
15556+ unsigned int lsc;
15557+
15558+ /* output */
b912730e 15559+ blkcnt_t blks;
5afbbe0d 15560+ aufs_bindex_t btop;
b912730e
AM
15561+};
15562+
15563+/*
15564+ * return with iinfo is write-locked
15565+ * callers should call au_write_post() or iinfo_write_unlock() + fput() in the
15566+ * end
15567+ */
15568+static struct file *au_write_pre(struct file *file, int do_ready,
15569+ struct au_write_pre *wpre)
15570+{
15571+ struct file *h_file;
15572+ struct dentry *dentry;
15573+ int err;
521ced18 15574+ unsigned int lsc;
b912730e
AM
15575+ struct au_pin pin;
15576+
521ced18
JR
15577+ lsc = 0;
15578+ if (wpre)
15579+ lsc = wpre->lsc;
15580+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, lsc);
b912730e 15581+ h_file = ERR_PTR(err);
dece6358
AM
15582+ if (unlikely(err))
15583+ goto out;
1facf9fc 15584+
b912730e
AM
15585+ dentry = file->f_path.dentry;
15586+ if (do_ready) {
15587+ err = au_ready_to_write(file, -1, &pin);
15588+ if (unlikely(err)) {
15589+ h_file = ERR_PTR(err);
15590+ di_write_unlock(dentry);
15591+ goto out_fi;
15592+ }
15593+ }
15594+
15595+ di_downgrade_lock(dentry, /*flags*/0);
15596+ if (wpre)
5afbbe0d 15597+ wpre->btop = au_fbtop(file);
4a4d8108 15598+ h_file = au_hf_top(file);
9dbd164d 15599+ get_file(h_file);
b912730e
AM
15600+ if (wpre)
15601+ wpre->blks = file_inode(h_file)->i_blocks;
15602+ if (do_ready)
15603+ au_unpin(&pin);
15604+ di_read_unlock(dentry, /*flags*/0);
15605+
15606+out_fi:
15607+ fi_write_unlock(file);
15608+out:
15609+ return h_file;
15610+}
15611+
15612+static void au_write_post(struct inode *inode, struct file *h_file,
15613+ struct au_write_pre *wpre, ssize_t written)
15614+{
15615+ struct inode *h_inode;
15616+
15617+ au_cpup_attr_timesizes(inode);
5afbbe0d 15618+ AuDebugOn(au_ibtop(inode) != wpre->btop);
b912730e
AM
15619+ h_inode = file_inode(h_file);
15620+ inode->i_mode = h_inode->i_mode;
15621+ ii_write_unlock(inode);
b912730e
AM
15622+ /* AuDbg("blks %llu, %llu\n", (u64)blks, (u64)h_inode->i_blocks); */
15623+ if (written > 0)
5afbbe0d 15624+ au_fhsm_wrote(inode->i_sb, wpre->btop,
b912730e 15625+ /*force*/h_inode->i_blocks > wpre->blks);
1c60b727 15626+ fput(h_file);
b912730e
AM
15627+}
15628+
e49829fe
JR
15629+/*
15630+ * todo: very ugly
15631+ * it locks both of i_mutex and si_rwsem for read in safe.
15632+ * if the plink maintenance mode continues forever (that is the problem),
15633+ * may loop forever.
15634+ */
15635+static void au_mtx_and_read_lock(struct inode *inode)
15636+{
15637+ int err;
15638+ struct super_block *sb = inode->i_sb;
15639+
15640+ while (1) {
febd17d6 15641+ inode_lock(inode);
e49829fe
JR
15642+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
15643+ if (!err)
15644+ break;
febd17d6 15645+ inode_unlock(inode);
e49829fe
JR
15646+ si_read_lock(sb, AuLock_NOPLMW);
15647+ si_read_unlock(sb);
15648+ }
15649+}
15650+
076b876e
AM
15651+static ssize_t au_do_iter(struct file *h_file, int rw, struct kiocb *kio,
15652+ struct iov_iter *iov_iter)
dece6358 15653+{
4a4d8108
AM
15654+ ssize_t err;
15655+ struct file *file;
076b876e 15656+ ssize_t (*iter)(struct kiocb *, struct iov_iter *);
1facf9fc 15657+
4a4d8108
AM
15658+ err = security_file_permission(h_file, rw);
15659+ if (unlikely(err))
15660+ goto out;
1facf9fc 15661+
43982f53 15662+ err = -ENOSYS; /* the branch doesn't have its ->(read|write)_iter() */
076b876e 15663+ iter = NULL;
5527c038 15664+ if (rw == MAY_READ)
076b876e 15665+ iter = h_file->f_op->read_iter;
5527c038 15666+ else if (rw == MAY_WRITE)
076b876e 15667+ iter = h_file->f_op->write_iter;
076b876e
AM
15668+
15669+ file = kio->ki_filp;
15670+ kio->ki_filp = h_file;
15671+ if (iter) {
2cbb1c4b 15672+ lockdep_off();
076b876e
AM
15673+ err = iter(kio, iov_iter);
15674+ lockdep_on();
4a4d8108
AM
15675+ } else
15676+ /* currently there is no such fs */
15677+ WARN_ON_ONCE(1);
076b876e 15678+ kio->ki_filp = file;
1facf9fc 15679+
4f0767ce 15680+out:
dece6358
AM
15681+ return err;
15682+}
1facf9fc 15683+
076b876e 15684+static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter)
1facf9fc 15685+{
4a4d8108
AM
15686+ ssize_t err;
15687+ struct file *file, *h_file;
b912730e 15688+ struct inode *inode;
dece6358 15689+ struct super_block *sb;
1facf9fc 15690+
4a4d8108 15691+ file = kio->ki_filp;
b912730e
AM
15692+ inode = file_inode(file);
15693+ sb = inode->i_sb;
e49829fe 15694+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 15695+
521ced18 15696+ h_file = au_read_pre(file, /*keep_fi*/1, /*lsc*/0);
b912730e
AM
15697+ err = PTR_ERR(h_file);
15698+ if (IS_ERR(h_file))
15699+ goto out;
9dbd164d 15700+
5afbbe0d
AM
15701+ if (au_test_loopback_kthread()) {
15702+ au_warn_loopback(h_file->f_path.dentry->d_sb);
15703+ if (file->f_mapping != h_file->f_mapping) {
15704+ file->f_mapping = h_file->f_mapping;
15705+ smp_mb(); /* unnecessary? */
15706+ }
15707+ }
15708+ fi_read_unlock(file);
15709+
076b876e 15710+ err = au_do_iter(h_file, MAY_READ, kio, iov_iter);
4a4d8108
AM
15711+ /* todo: necessary? */
15712+ /* file->f_ra = h_file->f_ra; */
b912730e 15713+ au_read_post(inode, h_file);
1facf9fc 15714+
4f0767ce 15715+out:
4a4d8108 15716+ si_read_unlock(sb);
1308ab2a 15717+ return err;
15718+}
1facf9fc 15719+
076b876e 15720+static ssize_t aufs_write_iter(struct kiocb *kio, struct iov_iter *iov_iter)
1308ab2a 15721+{
4a4d8108 15722+ ssize_t err;
b912730e
AM
15723+ struct au_write_pre wpre;
15724+ struct inode *inode;
4a4d8108 15725+ struct file *file, *h_file;
1308ab2a 15726+
4a4d8108 15727+ file = kio->ki_filp;
b912730e 15728+ inode = file_inode(file);
e49829fe
JR
15729+ au_mtx_and_read_lock(inode);
15730+
521ced18 15731+ wpre.lsc = 0;
b912730e
AM
15732+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
15733+ err = PTR_ERR(h_file);
15734+ if (IS_ERR(h_file))
9dbd164d 15735+ goto out;
9dbd164d 15736+
076b876e 15737+ err = au_do_iter(h_file, MAY_WRITE, kio, iov_iter);
b912730e 15738+ au_write_post(inode, h_file, &wpre, err);
1facf9fc 15739+
4f0767ce 15740+out:
b912730e 15741+ si_read_unlock(inode->i_sb);
febd17d6 15742+ inode_unlock(inode);
dece6358 15743+ return err;
1facf9fc 15744+}
15745+
0b2a12c6
JR
15746+/*
15747+ * We may be able to remove aufs_splice_{read,write}() since almost all FSes
15748+ * don't have their own .splice_{read,write} implimentations, and they use
15749+ * generic_file_splice_read() and iter_file_splice_write() who can act like the
15750+ * simple converters to f_op->iter_read() and ->iter_write().
15751+ * But we keep our own implementations because some non-mainlined FSes may have
15752+ * their own .splice_{read,write} implimentations and aufs doesn't want to take
15753+ * away an opportunity to co-work with aufs from them.
15754+ */
4a4d8108
AM
15755+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
15756+ struct pipe_inode_info *pipe, size_t len,
15757+ unsigned int flags)
1facf9fc 15758+{
4a4d8108
AM
15759+ ssize_t err;
15760+ struct file *h_file;
b912730e 15761+ struct inode *inode;
dece6358 15762+ struct super_block *sb;
1facf9fc 15763+
b912730e
AM
15764+ inode = file_inode(file);
15765+ sb = inode->i_sb;
e49829fe 15766+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
b912730e 15767+
521ced18 15768+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
b912730e
AM
15769+ err = PTR_ERR(h_file);
15770+ if (IS_ERR(h_file))
dece6358 15771+ goto out;
1facf9fc 15772+
4a4d8108 15773+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
acd2b654 15774+ /* todo: necessary? */
4a4d8108 15775+ /* file->f_ra = h_file->f_ra; */
b912730e 15776+ au_read_post(inode, h_file);
1facf9fc 15777+
4f0767ce 15778+out:
4a4d8108 15779+ si_read_unlock(sb);
dece6358 15780+ return err;
1facf9fc 15781+}
15782+
4a4d8108
AM
15783+static ssize_t
15784+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
15785+ size_t len, unsigned int flags)
1facf9fc 15786+{
4a4d8108 15787+ ssize_t err;
b912730e
AM
15788+ struct au_write_pre wpre;
15789+ struct inode *inode;
076b876e 15790+ struct file *h_file;
1facf9fc 15791+
b912730e 15792+ inode = file_inode(file);
e49829fe 15793+ au_mtx_and_read_lock(inode);
9dbd164d 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+
4a4d8108 15801+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
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);
4a4d8108
AM
15807+ return err;
15808+}
1facf9fc 15809+
38d290e6
JR
15810+static long aufs_fallocate(struct file *file, int mode, loff_t offset,
15811+ loff_t len)
15812+{
15813+ long err;
b912730e 15814+ struct au_write_pre wpre;
38d290e6
JR
15815+ struct inode *inode;
15816+ struct file *h_file;
15817+
b912730e 15818+ inode = file_inode(file);
38d290e6
JR
15819+ au_mtx_and_read_lock(inode);
15820+
521ced18 15821+ wpre.lsc = 0;
b912730e
AM
15822+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
15823+ err = PTR_ERR(h_file);
15824+ if (IS_ERR(h_file))
38d290e6 15825+ goto out;
38d290e6
JR
15826+
15827+ lockdep_off();
03673fb0 15828+ err = vfs_fallocate(h_file, mode, offset, len);
38d290e6 15829+ lockdep_on();
b912730e 15830+ au_write_post(inode, h_file, &wpre, /*written*/1);
38d290e6
JR
15831+
15832+out:
b912730e 15833+ si_read_unlock(inode->i_sb);
febd17d6 15834+ inode_unlock(inode);
38d290e6
JR
15835+ return err;
15836+}
15837+
521ced18
JR
15838+static ssize_t aufs_copy_file_range(struct file *src, loff_t src_pos,
15839+ struct file *dst, loff_t dst_pos,
15840+ size_t len, unsigned int flags)
15841+{
15842+ ssize_t err;
15843+ struct au_write_pre wpre;
15844+ enum { SRC, DST };
15845+ struct {
15846+ struct inode *inode;
15847+ struct file *h_file;
15848+ struct super_block *h_sb;
15849+ } a[2];
15850+#define a_src a[SRC]
15851+#define a_dst a[DST]
15852+
15853+ err = -EINVAL;
15854+ a_src.inode = file_inode(src);
15855+ if (unlikely(!S_ISREG(a_src.inode->i_mode)))
15856+ goto out;
15857+ a_dst.inode = file_inode(dst);
15858+ if (unlikely(!S_ISREG(a_dst.inode->i_mode)))
15859+ goto out;
15860+
15861+ au_mtx_and_read_lock(a_dst.inode);
15862+ /*
15863+ * in order to match the order in di_write_lock2_{child,parent}(),
acd2b654 15864+ * use f_path.dentry for this comparison.
521ced18
JR
15865+ */
15866+ if (src->f_path.dentry < dst->f_path.dentry) {
15867+ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_1);
15868+ err = PTR_ERR(a_src.h_file);
15869+ if (IS_ERR(a_src.h_file))
15870+ goto out_si;
15871+
15872+ wpre.lsc = AuLsc_FI_2;
15873+ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre);
15874+ err = PTR_ERR(a_dst.h_file);
15875+ if (IS_ERR(a_dst.h_file)) {
15876+ au_read_post(a_src.inode, a_src.h_file);
15877+ goto out_si;
15878+ }
15879+ } else {
15880+ wpre.lsc = AuLsc_FI_1;
15881+ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre);
15882+ err = PTR_ERR(a_dst.h_file);
15883+ if (IS_ERR(a_dst.h_file))
15884+ goto out_si;
15885+
15886+ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_2);
15887+ err = PTR_ERR(a_src.h_file);
15888+ if (IS_ERR(a_src.h_file)) {
15889+ au_write_post(a_dst.inode, a_dst.h_file, &wpre,
15890+ /*written*/0);
15891+ goto out_si;
15892+ }
15893+ }
15894+
15895+ err = -EXDEV;
15896+ a_src.h_sb = file_inode(a_src.h_file)->i_sb;
15897+ a_dst.h_sb = file_inode(a_dst.h_file)->i_sb;
15898+ if (unlikely(a_src.h_sb != a_dst.h_sb)) {
15899+ AuDbgFile(src);
15900+ AuDbgFile(dst);
15901+ goto out_file;
15902+ }
15903+
15904+ err = vfsub_copy_file_range(a_src.h_file, src_pos, a_dst.h_file,
15905+ dst_pos, len, flags);
15906+
15907+out_file:
15908+ au_write_post(a_dst.inode, a_dst.h_file, &wpre, err);
15909+ fi_read_unlock(src);
15910+ au_read_post(a_src.inode, a_src.h_file);
15911+out_si:
15912+ si_read_unlock(a_dst.inode->i_sb);
15913+ inode_unlock(a_dst.inode);
15914+out:
15915+ return err;
15916+#undef a_src
15917+#undef a_dst
15918+}
15919+
4a4d8108
AM
15920+/* ---------------------------------------------------------------------- */
15921+
9dbd164d
AM
15922+/*
15923+ * The locking order around current->mmap_sem.
15924+ * - in most and regular cases
15925+ * file I/O syscall -- aufs_read() or something
15926+ * -- si_rwsem for read -- mmap_sem
15927+ * (Note that [fdi]i_rwsem are released before mmap_sem).
15928+ * - in mmap case
15929+ * mmap(2) -- mmap_sem -- aufs_mmap() -- si_rwsem for read -- [fdi]i_rwsem
acd2b654
AM
15930+ * This AB-BA order is definitely bad, but is not a problem since "si_rwsem for
15931+ * read" allows multiple processes to acquire it and [fdi]i_rwsem are not held
15932+ * in file I/O. Aufs needs to stop lockdep in aufs_mmap() though.
9dbd164d
AM
15933+ * It means that when aufs acquires si_rwsem for write, the process should never
15934+ * acquire mmap_sem.
15935+ *
392086de 15936+ * Actually aufs_iterate() holds [fdi]i_rwsem before mmap_sem, but this is not a
9dbd164d
AM
15937+ * problem either since any directory is not able to be mmap-ed.
15938+ * The similar scenario is applied to aufs_readlink() too.
15939+ */
15940+
38d290e6 15941+#if 0 /* stop calling security_file_mmap() */
2dfbb274
AM
15942+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
15943+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b)
15944+
15945+static unsigned long au_arch_prot_conv(unsigned long flags)
15946+{
15947+ /* currently ppc64 only */
15948+#ifdef CONFIG_PPC64
15949+ /* cf. linux/arch/powerpc/include/asm/mman.h */
15950+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
15951+ return AuConv_VM_PROT(flags, SAO);
15952+#else
15953+ AuDebugOn(arch_calc_vm_prot_bits(-1));
15954+ return 0;
15955+#endif
15956+}
15957+
15958+static unsigned long au_prot_conv(unsigned long flags)
15959+{
15960+ return AuConv_VM_PROT(flags, READ)
15961+ | AuConv_VM_PROT(flags, WRITE)
15962+ | AuConv_VM_PROT(flags, EXEC)
15963+ | au_arch_prot_conv(flags);
15964+}
15965+
15966+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
15967+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b)
15968+
15969+static unsigned long au_flag_conv(unsigned long flags)
15970+{
15971+ return AuConv_VM_MAP(flags, GROWSDOWN)
15972+ | AuConv_VM_MAP(flags, DENYWRITE)
2dfbb274
AM
15973+ | AuConv_VM_MAP(flags, LOCKED);
15974+}
38d290e6 15975+#endif
2dfbb274 15976+
9dbd164d 15977+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
dece6358 15978+{
4a4d8108 15979+ int err;
4a4d8108 15980+ const unsigned char wlock
9dbd164d 15981+ = (file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
4a4d8108 15982+ struct super_block *sb;
9dbd164d 15983+ struct file *h_file;
b912730e 15984+ struct inode *inode;
9dbd164d
AM
15985+
15986+ AuDbgVmRegion(file, vma);
1308ab2a 15987+
b912730e
AM
15988+ inode = file_inode(file);
15989+ sb = inode->i_sb;
9dbd164d 15990+ lockdep_off();
e49829fe 15991+ si_read_lock(sb, AuLock_NOPLMW);
4a4d8108 15992+
b912730e 15993+ h_file = au_write_pre(file, wlock, /*wpre*/NULL);
9dbd164d 15994+ lockdep_on();
b912730e
AM
15995+ err = PTR_ERR(h_file);
15996+ if (IS_ERR(h_file))
15997+ goto out;
1308ab2a 15998+
b912730e
AM
15999+ err = 0;
16000+ au_set_mmapped(file);
9dbd164d 16001+ au_vm_file_reset(vma, h_file);
38d290e6
JR
16002+ /*
16003+ * we cannot call security_mmap_file() here since it may acquire
16004+ * mmap_sem or i_mutex.
16005+ *
16006+ * err = security_mmap_file(h_file, au_prot_conv(vma->vm_flags),
16007+ * au_flag_conv(vma->vm_flags));
16008+ */
9dbd164d 16009+ if (!err)
521ced18 16010+ err = call_mmap(h_file, vma);
b912730e
AM
16011+ if (!err) {
16012+ au_vm_prfile_set(vma, file);
16013+ fsstack_copy_attr_atime(inode, file_inode(h_file));
16014+ goto out_fput; /* success */
16015+ }
2cbb1c4b
JR
16016+ au_unset_mmapped(file);
16017+ au_vm_file_reset(vma, file);
b912730e 16018+
2cbb1c4b 16019+out_fput:
9dbd164d 16020+ lockdep_off();
b912730e
AM
16021+ ii_write_unlock(inode);
16022+ lockdep_on();
16023+ fput(h_file);
4f0767ce 16024+out:
b912730e 16025+ lockdep_off();
9dbd164d
AM
16026+ si_read_unlock(sb);
16027+ lockdep_on();
16028+ AuTraceErr(err);
4a4d8108
AM
16029+ return err;
16030+}
16031+
16032+/* ---------------------------------------------------------------------- */
16033+
1e00d052
AM
16034+static int aufs_fsync_nondir(struct file *file, loff_t start, loff_t end,
16035+ int datasync)
4a4d8108
AM
16036+{
16037+ int err;
b912730e 16038+ struct au_write_pre wpre;
4a4d8108
AM
16039+ struct inode *inode;
16040+ struct file *h_file;
4a4d8108
AM
16041+
16042+ err = 0; /* -EBADF; */ /* posix? */
16043+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
b912730e 16044+ goto out;
4a4d8108 16045+
b912730e
AM
16046+ inode = file_inode(file);
16047+ au_mtx_and_read_lock(inode);
16048+
521ced18 16049+ wpre.lsc = 0;
b912730e
AM
16050+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
16051+ err = PTR_ERR(h_file);
16052+ if (IS_ERR(h_file))
4a4d8108 16053+ goto out_unlock;
4a4d8108 16054+
53392da6 16055+ err = vfsub_fsync(h_file, &h_file->f_path, datasync);
b912730e 16056+ au_write_post(inode, h_file, &wpre, /*written*/0);
4a4d8108 16057+
4f0767ce 16058+out_unlock:
b912730e 16059+ si_read_unlock(inode->i_sb);
febd17d6 16060+ inode_unlock(inode);
b912730e 16061+out:
4a4d8108 16062+ return err;
dece6358
AM
16063+}
16064+
4a4d8108 16065+static int aufs_fasync(int fd, struct file *file, int flag)
dece6358 16066+{
4a4d8108
AM
16067+ int err;
16068+ struct file *h_file;
4a4d8108 16069+ struct super_block *sb;
1308ab2a 16070+
b912730e 16071+ sb = file->f_path.dentry->d_sb;
e49829fe 16072+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
b912730e 16073+
521ced18 16074+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
b912730e
AM
16075+ err = PTR_ERR(h_file);
16076+ if (IS_ERR(h_file))
4a4d8108
AM
16077+ goto out;
16078+
523b37e3 16079+ if (h_file->f_op->fasync)
4a4d8108 16080+ err = h_file->f_op->fasync(fd, h_file, flag);
b912730e 16081+ fput(h_file); /* instead of au_read_post() */
1308ab2a 16082+
4f0767ce 16083+out:
4a4d8108 16084+ si_read_unlock(sb);
1308ab2a 16085+ return err;
dece6358 16086+}
4a4d8108 16087+
febd17d6
JR
16088+static int aufs_setfl(struct file *file, unsigned long arg)
16089+{
16090+ int err;
16091+ struct file *h_file;
16092+ struct super_block *sb;
16093+
16094+ sb = file->f_path.dentry->d_sb;
16095+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
16096+
521ced18 16097+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
febd17d6
JR
16098+ err = PTR_ERR(h_file);
16099+ if (IS_ERR(h_file))
16100+ goto out;
16101+
1c60b727
AM
16102+ /* stop calling h_file->fasync */
16103+ arg |= vfsub_file_flags(file) & FASYNC;
febd17d6
JR
16104+ err = setfl(/*unused fd*/-1, h_file, arg);
16105+ fput(h_file); /* instead of au_read_post() */
16106+
16107+out:
16108+ si_read_unlock(sb);
16109+ return err;
16110+}
16111+
4a4d8108
AM
16112+/* ---------------------------------------------------------------------- */
16113+
16114+/* no one supports this operation, currently */
43982f53 16115+#if 0 /* reserved for future use */
4a4d8108 16116+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
2000de60 16117+ size_t len, loff_t *pos, int more)
4a4d8108
AM
16118+{
16119+}
16120+#endif
16121+
16122+/* ---------------------------------------------------------------------- */
16123+
16124+const struct file_operations aufs_file_fop = {
16125+ .owner = THIS_MODULE,
2cbb1c4b 16126+
027c5e7a 16127+ .llseek = default_llseek,
4a4d8108 16128+
076b876e
AM
16129+ .read_iter = aufs_read_iter,
16130+ .write_iter = aufs_write_iter,
16131+
4a4d8108
AM
16132+#ifdef CONFIG_AUFS_POLL
16133+ .poll = aufs_poll,
16134+#endif
16135+ .unlocked_ioctl = aufs_ioctl_nondir,
b752ccd1 16136+#ifdef CONFIG_COMPAT
c2b27bf2 16137+ .compat_ioctl = aufs_compat_ioctl_nondir,
b752ccd1 16138+#endif
4a4d8108
AM
16139+ .mmap = aufs_mmap,
16140+ .open = aufs_open_nondir,
16141+ .flush = aufs_flush_nondir,
16142+ .release = aufs_release_nondir,
16143+ .fsync = aufs_fsync_nondir,
4a4d8108
AM
16144+ .fasync = aufs_fasync,
16145+ /* .sendpage = aufs_sendpage, */
febd17d6 16146+ .setfl = aufs_setfl,
4a4d8108
AM
16147+ .splice_write = aufs_splice_write,
16148+ .splice_read = aufs_splice_read,
43982f53 16149+#if 0 /* reserved for future use */
4a4d8108 16150+ .aio_splice_write = aufs_aio_splice_write,
38d290e6 16151+ .aio_splice_read = aufs_aio_splice_read,
4a4d8108 16152+#endif
521ced18
JR
16153+ .fallocate = aufs_fallocate,
16154+ .copy_file_range = aufs_copy_file_range
4a4d8108 16155+};
7f207e10 16156diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
eca34b5c 16157--- /usr/share/empty/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100
319657f6 16158+++ linux/fs/aufs/fstype.h 2021-12-03 15:38:59.936647310 +0100
062440b3
AM
16159@@ -0,0 +1,401 @@
16160+/* SPDX-License-Identifier: GPL-2.0 */
4a4d8108 16161+/*
6d176551 16162+ * Copyright (C) 2005-2021 Junjiro R. Okajima
4a4d8108
AM
16163+ *
16164+ * This program, aufs is free software; you can redistribute it and/or modify
16165+ * it under the terms of the GNU General Public License as published by
16166+ * the Free Software Foundation; either version 2 of the License, or
16167+ * (at your option) any later version.
16168+ *
16169+ * This program is distributed in the hope that it will be useful,
16170+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16171+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16172+ * GNU General Public License for more details.
16173+ *
16174+ * You should have received a copy of the GNU General Public License
523b37e3 16175+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
16176+ */
16177+
16178+/*
16179+ * judging filesystem type
16180+ */
16181+
16182+#ifndef __AUFS_FSTYPE_H__
16183+#define __AUFS_FSTYPE_H__
16184+
16185+#ifdef __KERNEL__
16186+
16187+#include <linux/fs.h>
16188+#include <linux/magic.h>
b912730e 16189+#include <linux/nfs_fs.h>
b95c5147 16190+#include <linux/romfs_fs.h>
4a4d8108
AM
16191+
16192+static inline int au_test_aufs(struct super_block *sb)
16193+{
16194+ return sb->s_magic == AUFS_SUPER_MAGIC;
16195+}
16196+
16197+static inline const char *au_sbtype(struct super_block *sb)
16198+{
16199+ return sb->s_type->name;
16200+}
1308ab2a 16201+
16202+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
16203+{
f0c0a007 16204+#if IS_ENABLED(CONFIG_ISO9660_FS)
2000de60 16205+ return sb->s_magic == ISOFS_SUPER_MAGIC;
dece6358
AM
16206+#else
16207+ return 0;
16208+#endif
16209+}
16210+
1308ab2a 16211+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
dece6358 16212+{
f0c0a007 16213+#if IS_ENABLED(CONFIG_ROMFS_FS)
2000de60 16214+ return sb->s_magic == ROMFS_MAGIC;
dece6358
AM
16215+#else
16216+ return 0;
16217+#endif
16218+}
16219+
1308ab2a 16220+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
dece6358 16221+{
f0c0a007 16222+#if IS_ENABLED(CONFIG_CRAMFS)
1308ab2a 16223+ return sb->s_magic == CRAMFS_MAGIC;
16224+#endif
16225+ return 0;
16226+}
16227+
16228+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
16229+{
f0c0a007 16230+#if IS_ENABLED(CONFIG_NFS_FS)
1308ab2a 16231+ return sb->s_magic == NFS_SUPER_MAGIC;
dece6358
AM
16232+#else
16233+ return 0;
16234+#endif
16235+}
16236+
1308ab2a 16237+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
dece6358 16238+{
f0c0a007 16239+#if IS_ENABLED(CONFIG_FUSE_FS)
1308ab2a 16240+ return sb->s_magic == FUSE_SUPER_MAGIC;
dece6358
AM
16241+#else
16242+ return 0;
16243+#endif
16244+}
16245+
1308ab2a 16246+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
dece6358 16247+{
f0c0a007 16248+#if IS_ENABLED(CONFIG_XFS_FS)
1308ab2a 16249+ return sb->s_magic == XFS_SB_MAGIC;
dece6358
AM
16250+#else
16251+ return 0;
16252+#endif
16253+}
16254+
1308ab2a 16255+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
dece6358 16256+{
1308ab2a 16257+#ifdef CONFIG_TMPFS
16258+ return sb->s_magic == TMPFS_MAGIC;
16259+#else
16260+ return 0;
dece6358 16261+#endif
dece6358
AM
16262+}
16263+
1308ab2a 16264+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
1facf9fc 16265+{
f0c0a007 16266+#if IS_ENABLED(CONFIG_ECRYPT_FS)
1308ab2a 16267+ return !strcmp(au_sbtype(sb), "ecryptfs");
16268+#else
16269+ return 0;
16270+#endif
1facf9fc 16271+}
16272+
1308ab2a 16273+static inline int au_test_ramfs(struct super_block *sb)
16274+{
16275+ return sb->s_magic == RAMFS_MAGIC;
16276+}
16277+
16278+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
16279+{
f0c0a007 16280+#if IS_ENABLED(CONFIG_UBIFS_FS)
1308ab2a 16281+ return sb->s_magic == UBIFS_SUPER_MAGIC;
16282+#else
16283+ return 0;
16284+#endif
16285+}
16286+
16287+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
16288+{
16289+#ifdef CONFIG_PROC_FS
16290+ return sb->s_magic == PROC_SUPER_MAGIC;
16291+#else
16292+ return 0;
16293+#endif
16294+}
16295+
16296+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
16297+{
16298+#ifdef CONFIG_SYSFS
16299+ return sb->s_magic == SYSFS_MAGIC;
16300+#else
16301+ return 0;
16302+#endif
16303+}
16304+
16305+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
16306+{
f0c0a007 16307+#if IS_ENABLED(CONFIG_CONFIGFS_FS)
1308ab2a 16308+ return sb->s_magic == CONFIGFS_MAGIC;
16309+#else
16310+ return 0;
16311+#endif
16312+}
16313+
16314+static inline int au_test_minix(struct super_block *sb __maybe_unused)
16315+{
f0c0a007 16316+#if IS_ENABLED(CONFIG_MINIX_FS)
1308ab2a 16317+ return sb->s_magic == MINIX3_SUPER_MAGIC
16318+ || sb->s_magic == MINIX2_SUPER_MAGIC
16319+ || sb->s_magic == MINIX2_SUPER_MAGIC2
16320+ || sb->s_magic == MINIX_SUPER_MAGIC
16321+ || sb->s_magic == MINIX_SUPER_MAGIC2;
16322+#else
16323+ return 0;
16324+#endif
16325+}
16326+
1308ab2a 16327+static inline int au_test_fat(struct super_block *sb __maybe_unused)
16328+{
f0c0a007 16329+#if IS_ENABLED(CONFIG_FAT_FS)
1308ab2a 16330+ return sb->s_magic == MSDOS_SUPER_MAGIC;
16331+#else
16332+ return 0;
16333+#endif
16334+}
16335+
16336+static inline int au_test_msdos(struct super_block *sb)
16337+{
16338+ return au_test_fat(sb);
16339+}
16340+
16341+static inline int au_test_vfat(struct super_block *sb)
16342+{
16343+ return au_test_fat(sb);
16344+}
16345+
16346+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
16347+{
16348+#ifdef CONFIG_SECURITYFS
16349+ return sb->s_magic == SECURITYFS_MAGIC;
16350+#else
16351+ return 0;
16352+#endif
16353+}
16354+
16355+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
16356+{
f0c0a007 16357+#if IS_ENABLED(CONFIG_SQUASHFS)
1308ab2a 16358+ return sb->s_magic == SQUASHFS_MAGIC;
16359+#else
16360+ return 0;
16361+#endif
16362+}
16363+
16364+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
16365+{
f0c0a007 16366+#if IS_ENABLED(CONFIG_BTRFS_FS)
1308ab2a 16367+ return sb->s_magic == BTRFS_SUPER_MAGIC;
16368+#else
16369+ return 0;
16370+#endif
16371+}
16372+
16373+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
16374+{
f0c0a007 16375+#if IS_ENABLED(CONFIG_XENFS)
1308ab2a 16376+ return sb->s_magic == XENFS_SUPER_MAGIC;
16377+#else
16378+ return 0;
16379+#endif
16380+}
16381+
16382+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
16383+{
16384+#ifdef CONFIG_DEBUG_FS
16385+ return sb->s_magic == DEBUGFS_MAGIC;
16386+#else
16387+ return 0;
16388+#endif
16389+}
16390+
16391+static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
16392+{
f0c0a007 16393+#if IS_ENABLED(CONFIG_NILFS)
1308ab2a 16394+ return sb->s_magic == NILFS_SUPER_MAGIC;
16395+#else
16396+ return 0;
16397+#endif
16398+}
16399+
4a4d8108
AM
16400+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
16401+{
f0c0a007 16402+#if IS_ENABLED(CONFIG_HFSPLUS_FS)
4a4d8108
AM
16403+ return sb->s_magic == HFSPLUS_SUPER_MAGIC;
16404+#else
16405+ return 0;
16406+#endif
16407+}
16408+
1308ab2a 16409+/* ---------------------------------------------------------------------- */
16410+/*
16411+ * they can't be an aufs branch.
16412+ */
16413+static inline int au_test_fs_unsuppoted(struct super_block *sb)
16414+{
16415+ return
16416+#ifndef CONFIG_AUFS_BR_RAMFS
16417+ au_test_ramfs(sb) ||
16418+#endif
16419+ au_test_procfs(sb)
16420+ || au_test_sysfs(sb)
16421+ || au_test_configfs(sb)
16422+ || au_test_debugfs(sb)
16423+ || au_test_securityfs(sb)
16424+ || au_test_xenfs(sb)
16425+ || au_test_ecryptfs(sb)
16426+ /* || !strcmp(au_sbtype(sb), "unionfs") */
16427+ || au_test_aufs(sb); /* will be supported in next version */
16428+}
16429+
1308ab2a 16430+static inline int au_test_fs_remote(struct super_block *sb)
16431+{
16432+ return !au_test_tmpfs(sb)
16433+#ifdef CONFIG_AUFS_BR_RAMFS
16434+ && !au_test_ramfs(sb)
16435+#endif
16436+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
16437+}
16438+
16439+/* ---------------------------------------------------------------------- */
16440+
16441+/*
16442+ * Note: these functions (below) are created after reading ->getattr() in all
16443+ * filesystems under linux/fs. it means we have to do so in every update...
16444+ */
16445+
16446+/*
16447+ * some filesystems require getattr to refresh the inode attributes before
16448+ * referencing.
16449+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
16450+ * and leave the work for d_revalidate()
16451+ */
16452+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
16453+{
16454+ return au_test_nfs(sb)
16455+ || au_test_fuse(sb)
1308ab2a 16456+ /* || au_test_btrfs(sb) */ /* untested */
1308ab2a 16457+ ;
16458+}
16459+
16460+/*
16461+ * filesystems which don't maintain i_size or i_blocks.
16462+ */
16463+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
16464+{
16465+ return au_test_xfs(sb)
4a4d8108
AM
16466+ || au_test_btrfs(sb)
16467+ || au_test_ubifs(sb)
16468+ || au_test_hfsplus(sb) /* maintained, but incorrect */
1308ab2a 16469+ /* || au_test_minix(sb) */ /* untested */
16470+ ;
16471+}
16472+
16473+/*
16474+ * filesystems which don't store the correct value in some of their inode
16475+ * attributes.
16476+ */
16477+static inline int au_test_fs_bad_iattr(struct super_block *sb)
16478+{
16479+ return au_test_fs_bad_iattr_size(sb)
1308ab2a 16480+ || au_test_fat(sb)
16481+ || au_test_msdos(sb)
16482+ || au_test_vfat(sb);
1facf9fc 16483+}
16484+
16485+/* they don't check i_nlink in link(2) */
16486+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
16487+{
16488+ return au_test_tmpfs(sb)
16489+#ifdef CONFIG_AUFS_BR_RAMFS
16490+ || au_test_ramfs(sb)
16491+#endif
4a4d8108 16492+ || au_test_ubifs(sb)
4a4d8108 16493+ || au_test_hfsplus(sb);
1facf9fc 16494+}
16495+
16496+/*
16497+ * filesystems which sets S_NOATIME and S_NOCMTIME.
16498+ */
16499+static inline int au_test_fs_notime(struct super_block *sb)
16500+{
16501+ return au_test_nfs(sb)
16502+ || au_test_fuse(sb)
dece6358 16503+ || au_test_ubifs(sb)
1facf9fc 16504+ ;
16505+}
16506+
1facf9fc 16507+/* temporary support for i#1 in cramfs */
16508+static inline int au_test_fs_unique_ino(struct inode *inode)
16509+{
16510+ if (au_test_cramfs(inode->i_sb))
16511+ return inode->i_ino != 1;
16512+ return 1;
16513+}
16514+
16515+/* ---------------------------------------------------------------------- */
16516+
16517+/*
16518+ * the filesystem where the xino files placed must support i/o after unlink and
16519+ * maintain i_size and i_blocks.
16520+ */
16521+static inline int au_test_fs_bad_xino(struct super_block *sb)
16522+{
16523+ return au_test_fs_remote(sb)
16524+ || au_test_fs_bad_iattr_size(sb)
1facf9fc 16525+ /* don't want unnecessary work for xino */
16526+ || au_test_aufs(sb)
1308ab2a 16527+ || au_test_ecryptfs(sb)
16528+ || au_test_nilfs(sb);
1facf9fc 16529+}
16530+
16531+static inline int au_test_fs_trunc_xino(struct super_block *sb)
16532+{
16533+ return au_test_tmpfs(sb)
16534+ || au_test_ramfs(sb);
16535+}
16536+
16537+/*
16538+ * test if the @sb is real-readonly.
16539+ */
16540+static inline int au_test_fs_rr(struct super_block *sb)
16541+{
16542+ return au_test_squashfs(sb)
16543+ || au_test_iso9660(sb)
16544+ || au_test_cramfs(sb)
16545+ || au_test_romfs(sb);
16546+}
16547+
b912730e
AM
16548+/*
16549+ * test if the @inode is nfs with 'noacl' option
2121bcd9 16550+ * NFS always sets SB_POSIXACL regardless its mount option 'noacl.'
b912730e
AM
16551+ */
16552+static inline int au_test_nfs_noacl(struct inode *inode)
16553+{
16554+ return au_test_nfs(inode->i_sb)
16555+ /* && IS_POSIXACL(inode) */
16556+ && !nfs_server_capable(inode, NFS_CAP_ACLS);
16557+}
16558+
1facf9fc 16559+#endif /* __KERNEL__ */
16560+#endif /* __AUFS_FSTYPE_H__ */
8b6a4947 16561diff -urN /usr/share/empty/fs/aufs/hbl.h linux/fs/aufs/hbl.h
eca34b5c 16562--- /usr/share/empty/fs/aufs/hbl.h 1970-01-01 01:00:00.000000000 +0100
319657f6 16563+++ linux/fs/aufs/hbl.h 2021-12-03 15:38:59.936647310 +0100
062440b3
AM
16564@@ -0,0 +1,65 @@
16565+/* SPDX-License-Identifier: GPL-2.0 */
8b6a4947 16566+/*
6d176551 16567+ * Copyright (C) 2017-2021 Junjiro R. Okajima
8b6a4947
AM
16568+ *
16569+ * This program, aufs is free software; you can redistribute it and/or modify
16570+ * it under the terms of the GNU General Public License as published by
16571+ * the Free Software Foundation; either version 2 of the License, or
16572+ * (at your option) any later version.
16573+ *
16574+ * This program is distributed in the hope that it will be useful,
16575+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16576+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16577+ * GNU General Public License for more details.
16578+ *
16579+ * You should have received a copy of the GNU General Public License
16580+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
16581+ */
16582+
16583+/*
16584+ * helpers for hlist_bl.h
16585+ */
16586+
16587+#ifndef __AUFS_HBL_H__
16588+#define __AUFS_HBL_H__
16589+
16590+#ifdef __KERNEL__
16591+
16592+#include <linux/list_bl.h>
16593+
16594+static inline void au_hbl_add(struct hlist_bl_node *node,
16595+ struct hlist_bl_head *hbl)
16596+{
16597+ hlist_bl_lock(hbl);
16598+ hlist_bl_add_head(node, hbl);
16599+ hlist_bl_unlock(hbl);
16600+}
16601+
16602+static inline void au_hbl_del(struct hlist_bl_node *node,
16603+ struct hlist_bl_head *hbl)
16604+{
16605+ hlist_bl_lock(hbl);
16606+ hlist_bl_del(node);
16607+ hlist_bl_unlock(hbl);
16608+}
16609+
16610+#define au_hbl_for_each(pos, head) \
16611+ for (pos = hlist_bl_first(head); \
16612+ pos; \
16613+ pos = pos->next)
16614+
16615+static inline unsigned long au_hbl_count(struct hlist_bl_head *hbl)
16616+{
16617+ unsigned long cnt;
16618+ struct hlist_bl_node *pos;
16619+
16620+ cnt = 0;
16621+ hlist_bl_lock(hbl);
16622+ au_hbl_for_each(pos, hbl)
16623+ cnt++;
16624+ hlist_bl_unlock(hbl);
16625+ return cnt;
16626+}
16627+
16628+#endif /* __KERNEL__ */
16629+#endif /* __AUFS_HBL_H__ */
7f207e10 16630diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
eca34b5c 16631--- /usr/share/empty/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100
319657f6 16632+++ linux/fs/aufs/hfsnotify.c 2021-12-03 15:38:59.936647310 +0100
fbc438ed 16633@@ -0,0 +1,288 @@
cd7a4cd9 16634+// SPDX-License-Identifier: GPL-2.0
1facf9fc 16635+/*
6d176551 16636+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 16637+ *
16638+ * This program, aufs is free software; you can redistribute it and/or modify
16639+ * it under the terms of the GNU General Public License as published by
16640+ * the Free Software Foundation; either version 2 of the License, or
16641+ * (at your option) any later version.
dece6358
AM
16642+ *
16643+ * This program is distributed in the hope that it will be useful,
16644+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16645+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16646+ * GNU General Public License for more details.
16647+ *
16648+ * You should have received a copy of the GNU General Public License
523b37e3 16649+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 16650+ */
16651+
16652+/*
4a4d8108 16653+ * fsnotify for the lower directories
1facf9fc 16654+ */
16655+
16656+#include "aufs.h"
16657+
4a4d8108
AM
16658+/* FS_IN_IGNORED is unnecessary */
16659+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
16660+ | FS_CREATE | FS_EVENT_ON_CHILD);
7f207e10 16661+static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq);
7eafdf33 16662+static __cacheline_aligned_in_smp atomic64_t au_hfsn_ifree = ATOMIC64_INIT(0);
1facf9fc 16663+
0c5527e5 16664+static void au_hfsn_free_mark(struct fsnotify_mark *mark)
1facf9fc 16665+{
0c5527e5
AM
16666+ struct au_hnotify *hn = container_of(mark, struct au_hnotify,
16667+ hn_mark);
5afbbe0d 16668+ /* AuDbg("here\n"); */
1c60b727 16669+ au_cache_free_hnotify(hn);
8b6a4947 16670+ smp_mb__before_atomic(); /* for atomic64_dec */
1716fcea
AM
16671+ if (atomic64_dec_and_test(&au_hfsn_ifree))
16672+ wake_up(&au_hfsn_wq);
4a4d8108 16673+}
1facf9fc 16674+
027c5e7a 16675+static int au_hfsn_alloc(struct au_hinode *hinode)
4a4d8108 16676+{
1716fcea 16677+ int err;
027c5e7a
AM
16678+ struct au_hnotify *hn;
16679+ struct super_block *sb;
16680+ struct au_branch *br;
0c5527e5 16681+ struct fsnotify_mark *mark;
027c5e7a 16682+ aufs_bindex_t bindex;
1facf9fc 16683+
027c5e7a
AM
16684+ hn = hinode->hi_notify;
16685+ sb = hn->hn_aufs_inode->i_sb;
16686+ bindex = au_br_index(sb, hinode->hi_id);
16687+ br = au_sbr(sb, bindex);
1716fcea
AM
16688+ AuDebugOn(!br->br_hfsn);
16689+
0c5527e5 16690+ mark = &hn->hn_mark;
ffa93bbd 16691+ fsnotify_init_mark(mark, br->br_hfsn->hfsn_group);
0c5527e5 16692+ mark->mask = AuHfsnMask;
7f207e10
AM
16693+ /*
16694+ * by udba rename or rmdir, aufs assign a new inode to the known
16695+ * h_inode, so specify 1 to allow dups.
16696+ */
c1595e42 16697+ lockdep_off();
acd2b654 16698+ err = fsnotify_add_inode_mark(mark, hinode->hi_inode, /*allow_dups*/1);
c1595e42 16699+ lockdep_on();
1716fcea
AM
16700+
16701+ return err;
1facf9fc 16702+}
16703+
7eafdf33 16704+static int au_hfsn_free(struct au_hinode *hinode, struct au_hnotify *hn)
1facf9fc 16705+{
0c5527e5 16706+ struct fsnotify_mark *mark;
7eafdf33 16707+ unsigned long long ull;
1716fcea 16708+ struct fsnotify_group *group;
7eafdf33
AM
16709+
16710+ ull = atomic64_inc_return(&au_hfsn_ifree);
16711+ BUG_ON(!ull);
953406b4 16712+
0c5527e5 16713+ mark = &hn->hn_mark;
1716fcea
AM
16714+ spin_lock(&mark->lock);
16715+ group = mark->group;
16716+ fsnotify_get_group(group);
16717+ spin_unlock(&mark->lock);
c1595e42 16718+ lockdep_off();
1716fcea 16719+ fsnotify_destroy_mark(mark, group);
5afbbe0d 16720+ fsnotify_put_mark(mark);
1716fcea 16721+ fsnotify_put_group(group);
c1595e42 16722+ lockdep_on();
7f207e10 16723+
7eafdf33
AM
16724+ /* free hn by myself */
16725+ return 0;
1facf9fc 16726+}
16727+
16728+/* ---------------------------------------------------------------------- */
16729+
4a4d8108 16730+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 16731+{
0c5527e5 16732+ struct fsnotify_mark *mark;
1facf9fc 16733+
0c5527e5
AM
16734+ mark = &hinode->hi_notify->hn_mark;
16735+ spin_lock(&mark->lock);
1facf9fc 16736+ if (do_set) {
0c5527e5
AM
16737+ AuDebugOn(mark->mask & AuHfsnMask);
16738+ mark->mask |= AuHfsnMask;
1facf9fc 16739+ } else {
0c5527e5
AM
16740+ AuDebugOn(!(mark->mask & AuHfsnMask));
16741+ mark->mask &= ~AuHfsnMask;
1facf9fc 16742+ }
0c5527e5 16743+ spin_unlock(&mark->lock);
4a4d8108 16744+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
1facf9fc 16745+}
16746+
4a4d8108 16747+/* ---------------------------------------------------------------------- */
1facf9fc 16748+
4a4d8108
AM
16749+/* #define AuDbgHnotify */
16750+#ifdef AuDbgHnotify
16751+static char *au_hfsn_name(u32 mask)
16752+{
16753+#ifdef CONFIG_AUFS_DEBUG
c06a8ce3
AM
16754+#define test_ret(flag) \
16755+ do { \
16756+ if (mask & flag) \
16757+ return #flag; \
16758+ } while (0)
4a4d8108
AM
16759+ test_ret(FS_ACCESS);
16760+ test_ret(FS_MODIFY);
16761+ test_ret(FS_ATTRIB);
16762+ test_ret(FS_CLOSE_WRITE);
16763+ test_ret(FS_CLOSE_NOWRITE);
16764+ test_ret(FS_OPEN);
16765+ test_ret(FS_MOVED_FROM);
16766+ test_ret(FS_MOVED_TO);
16767+ test_ret(FS_CREATE);
16768+ test_ret(FS_DELETE);
16769+ test_ret(FS_DELETE_SELF);
16770+ test_ret(FS_MOVE_SELF);
16771+ test_ret(FS_UNMOUNT);
16772+ test_ret(FS_Q_OVERFLOW);
16773+ test_ret(FS_IN_IGNORED);
b912730e 16774+ test_ret(FS_ISDIR);
4a4d8108
AM
16775+ test_ret(FS_IN_ONESHOT);
16776+ test_ret(FS_EVENT_ON_CHILD);
16777+ return "";
16778+#undef test_ret
16779+#else
16780+ return "??";
16781+#endif
1facf9fc 16782+}
4a4d8108 16783+#endif
1facf9fc 16784+
16785+/* ---------------------------------------------------------------------- */
16786+
1716fcea
AM
16787+static void au_hfsn_free_group(struct fsnotify_group *group)
16788+{
16789+ struct au_br_hfsnotify *hfsn = group->private;
16790+
5afbbe0d 16791+ /* AuDbg("here\n"); */
9f237c51 16792+ au_kfree_try_rcu(hfsn);
1716fcea
AM
16793+}
16794+
4a4d8108 16795+static int au_hfsn_handle_event(struct fsnotify_group *group,
a2654f78 16796+ u32 mask, const void *data, int data_type,
e37dd06a 16797+ struct inode *dir,
83b672a5 16798+ const struct qstr *file_name, u32 cookie,
ffa93bbd 16799+ struct fsnotify_iter_info *iter_info)
1facf9fc 16800+{
16801+ int err;
4a4d8108
AM
16802+ struct au_hnotify *hnotify;
16803+ struct inode *h_dir, *h_inode;
cd7a4cd9 16804+ struct fsnotify_mark *inode_mark;
4a4d8108 16805+
fb47a38f 16806+ AuDebugOn(data_type != FSNOTIFY_EVENT_INODE);
1facf9fc 16807+
16808+ err = 0;
0c5527e5 16809+ /* if FS_UNMOUNT happens, there must be another bug */
4a4d8108 16810+ AuDebugOn(mask & FS_UNMOUNT);
0c5527e5 16811+ if (mask & (FS_IN_IGNORED | FS_UNMOUNT))
1facf9fc 16812+ goto out;
1facf9fc 16813+
e37dd06a 16814+ h_dir = dir;
fb47a38f 16815+ h_inode = NULL;
4a4d8108 16816+#ifdef AuDbgHnotify
392086de 16817+ au_debug_on();
fbc438ed
JR
16818+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
16819+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
4a4d8108
AM
16820+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
16821+ h_dir->i_ino, mask, au_hfsn_name(mask),
fbc438ed 16822+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
4a4d8108 16823+ /* WARN_ON(1); */
1facf9fc 16824+ }
392086de 16825+ au_debug_off();
1facf9fc 16826+#endif
4a4d8108 16827+
cd7a4cd9 16828+ inode_mark = fsnotify_iter_inode_mark(iter_info);
0c5527e5
AM
16829+ AuDebugOn(!inode_mark);
16830+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
b62f1e65 16831+ err = au_hnotify(h_dir, hnotify, mask, file_name, h_inode);
1facf9fc 16832+
4a4d8108
AM
16833+out:
16834+ return err;
16835+}
1facf9fc 16836+
4a4d8108 16837+static struct fsnotify_ops au_hfsn_ops = {
1716fcea 16838+ .handle_event = au_hfsn_handle_event,
ffa93bbd
AM
16839+ .free_group_priv = au_hfsn_free_group,
16840+ .free_mark = au_hfsn_free_mark
4a4d8108
AM
16841+};
16842+
16843+/* ---------------------------------------------------------------------- */
16844+
027c5e7a
AM
16845+static void au_hfsn_fin_br(struct au_branch *br)
16846+{
1716fcea 16847+ struct au_br_hfsnotify *hfsn;
027c5e7a 16848+
1716fcea 16849+ hfsn = br->br_hfsn;
c1595e42
JR
16850+ if (hfsn) {
16851+ lockdep_off();
1716fcea 16852+ fsnotify_put_group(hfsn->hfsn_group);
c1595e42
JR
16853+ lockdep_on();
16854+ }
027c5e7a
AM
16855+}
16856+
1716fcea 16857+static int au_hfsn_init_br(struct au_branch *br, int perm)
4a4d8108
AM
16858+{
16859+ int err;
1716fcea
AM
16860+ struct fsnotify_group *group;
16861+ struct au_br_hfsnotify *hfsn;
1facf9fc 16862+
4a4d8108 16863+ err = 0;
1716fcea
AM
16864+ br->br_hfsn = NULL;
16865+ if (!au_br_hnotifyable(perm))
027c5e7a 16866+ goto out;
027c5e7a 16867+
1716fcea
AM
16868+ err = -ENOMEM;
16869+ hfsn = kmalloc(sizeof(*hfsn), GFP_NOFS);
16870+ if (unlikely(!hfsn))
027c5e7a
AM
16871+ goto out;
16872+
1716fcea
AM
16873+ err = 0;
16874+ group = fsnotify_alloc_group(&au_hfsn_ops);
16875+ if (IS_ERR(group)) {
16876+ err = PTR_ERR(group);
0c5527e5 16877+ pr_err("fsnotify_alloc_group() failed, %d\n", err);
1716fcea 16878+ goto out_hfsn;
4a4d8108 16879+ }
1facf9fc 16880+
1716fcea
AM
16881+ group->private = hfsn;
16882+ hfsn->hfsn_group = group;
16883+ br->br_hfsn = hfsn;
16884+ goto out; /* success */
16885+
16886+out_hfsn:
9f237c51 16887+ au_kfree_try_rcu(hfsn);
027c5e7a 16888+out:
1716fcea
AM
16889+ return err;
16890+}
16891+
16892+static int au_hfsn_reset_br(unsigned int udba, struct au_branch *br, int perm)
16893+{
16894+ int err;
16895+
16896+ err = 0;
16897+ if (!br->br_hfsn)
16898+ err = au_hfsn_init_br(br, perm);
16899+
1facf9fc 16900+ return err;
16901+}
16902+
7eafdf33
AM
16903+/* ---------------------------------------------------------------------- */
16904+
16905+static void au_hfsn_fin(void)
16906+{
16907+ AuDbg("au_hfsn_ifree %lld\n", (long long)atomic64_read(&au_hfsn_ifree));
16908+ wait_event(au_hfsn_wq, !atomic64_read(&au_hfsn_ifree));
16909+}
16910+
4a4d8108
AM
16911+const struct au_hnotify_op au_hnotify_op = {
16912+ .ctl = au_hfsn_ctl,
16913+ .alloc = au_hfsn_alloc,
16914+ .free = au_hfsn_free,
1facf9fc 16915+
7eafdf33
AM
16916+ .fin = au_hfsn_fin,
16917+
027c5e7a
AM
16918+ .reset_br = au_hfsn_reset_br,
16919+ .fin_br = au_hfsn_fin_br,
16920+ .init_br = au_hfsn_init_br
4a4d8108 16921+};
7f207e10 16922diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
eca34b5c 16923--- /usr/share/empty/fs/aufs/hfsplus.c 1970-01-01 01:00:00.000000000 +0100
319657f6 16924+++ linux/fs/aufs/hfsplus.c 2021-12-03 15:38:59.936647310 +0100
acd2b654 16925@@ -0,0 +1,60 @@
cd7a4cd9 16926+// SPDX-License-Identifier: GPL-2.0
4a4d8108 16927+/*
6d176551 16928+ * Copyright (C) 2010-2021 Junjiro R. Okajima
4a4d8108
AM
16929+ *
16930+ * This program, aufs is free software; you can redistribute it and/or modify
16931+ * it under the terms of the GNU General Public License as published by
16932+ * the Free Software Foundation; either version 2 of the License, or
16933+ * (at your option) any later version.
16934+ *
16935+ * This program is distributed in the hope that it will be useful,
16936+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16937+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16938+ * GNU General Public License for more details.
16939+ *
16940+ * You should have received a copy of the GNU General Public License
523b37e3 16941+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 16942+ */
1facf9fc 16943+
4a4d8108 16944+/*
acd2b654 16945+ * special support for filesystems which acquires an inode mutex
4a4d8108
AM
16946+ * at final closing a file, eg, hfsplus.
16947+ *
16948+ * This trick is very simple and stupid, just to open the file before really
acd2b654 16949+ * necessary open to tell hfsplus that this is not the final closing.
4a4d8108
AM
16950+ * The caller should call au_h_open_pre() after acquiring the inode mutex,
16951+ * and au_h_open_post() after releasing it.
16952+ */
1facf9fc 16953+
4a4d8108 16954+#include "aufs.h"
1facf9fc 16955+
392086de
AM
16956+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex,
16957+ int force_wr)
4a4d8108
AM
16958+{
16959+ struct file *h_file;
16960+ struct dentry *h_dentry;
1facf9fc 16961+
4a4d8108
AM
16962+ h_dentry = au_h_dptr(dentry, bindex);
16963+ AuDebugOn(!h_dentry);
5527c038 16964+ AuDebugOn(d_is_negative(h_dentry));
4a4d8108
AM
16965+
16966+ h_file = NULL;
16967+ if (au_test_hfsplus(h_dentry->d_sb)
7e9cd9fe 16968+ && d_is_reg(h_dentry))
4a4d8108
AM
16969+ h_file = au_h_open(dentry, bindex,
16970+ O_RDONLY | O_NOATIME | O_LARGEFILE,
392086de 16971+ /*file*/NULL, force_wr);
4a4d8108 16972+ return h_file;
1facf9fc 16973+}
16974+
4a4d8108
AM
16975+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
16976+ struct file *h_file)
16977+{
acd2b654
AM
16978+ struct au_branch *br;
16979+
4a4d8108
AM
16980+ if (h_file) {
16981+ fput(h_file);
acd2b654
AM
16982+ br = au_sbr(dentry->d_sb, bindex);
16983+ au_lcnt_dec(&br->br_nfiles);
4a4d8108
AM
16984+ }
16985+}
7f207e10 16986diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
eca34b5c 16987--- /usr/share/empty/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100
319657f6 16988+++ linux/fs/aufs/hnotify.c 2021-12-03 15:38:59.936647310 +0100
43982f53 16989@@ -0,0 +1,715 @@
cd7a4cd9 16990+// SPDX-License-Identifier: GPL-2.0
e49829fe 16991+/*
6d176551 16992+ * Copyright (C) 2005-2021 Junjiro R. Okajima
e49829fe
JR
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/>.
e49829fe
JR
17006+ */
17007+
17008+/*
7f207e10 17009+ * abstraction to notify the direct changes on lower directories
e49829fe
JR
17010+ */
17011+
eca801bf 17012+/* #include <linux/iversion.h> */
e49829fe
JR
17013+#include "aufs.h"
17014+
027c5e7a 17015+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode)
e49829fe
JR
17016+{
17017+ int err;
7f207e10 17018+ struct au_hnotify *hn;
1facf9fc 17019+
4a4d8108
AM
17020+ err = -ENOMEM;
17021+ hn = au_cache_alloc_hnotify();
17022+ if (hn) {
17023+ hn->hn_aufs_inode = inode;
027c5e7a
AM
17024+ hinode->hi_notify = hn;
17025+ err = au_hnotify_op.alloc(hinode);
17026+ AuTraceErr(err);
17027+ if (unlikely(err)) {
17028+ hinode->hi_notify = NULL;
1c60b727 17029+ au_cache_free_hnotify(hn);
4a4d8108
AM
17030+ /*
17031+ * The upper dir was removed by udba, but the same named
acd2b654 17032+ * dir left. In this case, aufs assigns a new inode
4a4d8108 17033+ * number and set the monitor again.
acd2b654 17034+ * For the lower dir, the old monitor is still left.
4a4d8108
AM
17035+ */
17036+ if (err == -EEXIST)
17037+ err = 0;
17038+ }
1308ab2a 17039+ }
1308ab2a 17040+
027c5e7a 17041+ AuTraceErr(err);
1308ab2a 17042+ return err;
dece6358 17043+}
1facf9fc 17044+
4a4d8108 17045+void au_hn_free(struct au_hinode *hinode)
dece6358 17046+{
4a4d8108 17047+ struct au_hnotify *hn;
1facf9fc 17048+
4a4d8108
AM
17049+ hn = hinode->hi_notify;
17050+ if (hn) {
4a4d8108 17051+ hinode->hi_notify = NULL;
7eafdf33 17052+ if (au_hnotify_op.free(hinode, hn))
1c60b727 17053+ au_cache_free_hnotify(hn);
4a4d8108
AM
17054+ }
17055+}
dece6358 17056+
4a4d8108 17057+/* ---------------------------------------------------------------------- */
dece6358 17058+
4a4d8108
AM
17059+void au_hn_ctl(struct au_hinode *hinode, int do_set)
17060+{
17061+ if (hinode->hi_notify)
17062+ au_hnotify_op.ctl(hinode, do_set);
17063+}
17064+
17065+void au_hn_reset(struct inode *inode, unsigned int flags)
17066+{
5afbbe0d 17067+ aufs_bindex_t bindex, bbot;
4a4d8108
AM
17068+ struct inode *hi;
17069+ struct dentry *iwhdentry;
1facf9fc 17070+
5afbbe0d
AM
17071+ bbot = au_ibbot(inode);
17072+ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) {
4a4d8108
AM
17073+ hi = au_h_iptr(inode, bindex);
17074+ if (!hi)
17075+ continue;
1308ab2a 17076+
febd17d6 17077+ /* inode_lock_nested(hi, AuLsc_I_CHILD); */
4a4d8108
AM
17078+ iwhdentry = au_hi_wh(inode, bindex);
17079+ if (iwhdentry)
17080+ dget(iwhdentry);
17081+ au_igrab(hi);
17082+ au_set_h_iptr(inode, bindex, NULL, 0);
17083+ au_set_h_iptr(inode, bindex, au_igrab(hi),
17084+ flags & ~AuHi_XINO);
17085+ iput(hi);
17086+ dput(iwhdentry);
febd17d6 17087+ /* inode_unlock(hi); */
1facf9fc 17088+ }
1facf9fc 17089+}
17090+
1308ab2a 17091+/* ---------------------------------------------------------------------- */
1facf9fc 17092+
4a4d8108 17093+static int hn_xino(struct inode *inode, struct inode *h_inode)
1facf9fc 17094+{
4a4d8108 17095+ int err;
5afbbe0d 17096+ aufs_bindex_t bindex, bbot, bfound, btop;
4a4d8108 17097+ struct inode *h_i;
1facf9fc 17098+
4a4d8108
AM
17099+ err = 0;
17100+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 17101+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
17102+ goto out;
17103+ }
1facf9fc 17104+
4a4d8108 17105+ bfound = -1;
5afbbe0d
AM
17106+ bbot = au_ibbot(inode);
17107+ btop = au_ibtop(inode);
4a4d8108 17108+#if 0 /* reserved for future use */
5afbbe0d 17109+ if (bindex == bbot) {
4a4d8108
AM
17110+ /* keep this ino in rename case */
17111+ goto out;
17112+ }
17113+#endif
5afbbe0d 17114+ for (bindex = btop; bindex <= bbot; bindex++)
4a4d8108
AM
17115+ if (au_h_iptr(inode, bindex) == h_inode) {
17116+ bfound = bindex;
17117+ break;
17118+ }
17119+ if (bfound < 0)
1308ab2a 17120+ goto out;
1facf9fc 17121+
5afbbe0d 17122+ for (bindex = btop; bindex <= bbot; bindex++) {
4a4d8108
AM
17123+ h_i = au_h_iptr(inode, bindex);
17124+ if (!h_i)
17125+ continue;
1facf9fc 17126+
4a4d8108
AM
17127+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
17128+ /* ignore this error */
17129+ /* bad action? */
1facf9fc 17130+ }
1facf9fc 17131+
4a4d8108 17132+ /* children inode number will be broken */
1facf9fc 17133+
4f0767ce 17134+out:
4a4d8108
AM
17135+ AuTraceErr(err);
17136+ return err;
1facf9fc 17137+}
17138+
4a4d8108 17139+static int hn_gen_tree(struct dentry *dentry)
1facf9fc 17140+{
4a4d8108
AM
17141+ int err, i, j, ndentry;
17142+ struct au_dcsub_pages dpages;
17143+ struct au_dpage *dpage;
17144+ struct dentry **dentries;
1facf9fc 17145+
4a4d8108
AM
17146+ err = au_dpages_init(&dpages, GFP_NOFS);
17147+ if (unlikely(err))
17148+ goto out;
17149+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
17150+ if (unlikely(err))
17151+ goto out_dpages;
1facf9fc 17152+
4a4d8108
AM
17153+ for (i = 0; i < dpages.ndpage; i++) {
17154+ dpage = dpages.dpages + i;
17155+ dentries = dpage->dentries;
17156+ ndentry = dpage->ndentry;
17157+ for (j = 0; j < ndentry; j++) {
17158+ struct dentry *d;
17159+
17160+ d = dentries[j];
17161+ if (IS_ROOT(d))
17162+ continue;
17163+
4a4d8108 17164+ au_digen_dec(d);
5527c038 17165+ if (d_really_is_positive(d))
4a4d8108
AM
17166+ /* todo: reset children xino?
17167+ cached children only? */
5527c038 17168+ au_iigen_dec(d_inode(d));
1308ab2a 17169+ }
dece6358 17170+ }
1facf9fc 17171+
4f0767ce 17172+out_dpages:
4a4d8108 17173+ au_dpages_free(&dpages);
4f0767ce 17174+out:
dece6358
AM
17175+ return err;
17176+}
17177+
1308ab2a 17178+/*
4a4d8108 17179+ * return 0 if processed.
1308ab2a 17180+ */
4a4d8108
AM
17181+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
17182+ const unsigned int isdir)
dece6358 17183+{
1308ab2a 17184+ int err;
4a4d8108
AM
17185+ struct dentry *d;
17186+ struct qstr *dname;
1facf9fc 17187+
4a4d8108
AM
17188+ err = 1;
17189+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 17190+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
17191+ err = 0;
17192+ goto out;
17193+ }
dece6358 17194+
4a4d8108
AM
17195+ if (!isdir) {
17196+ AuDebugOn(!name);
17197+ au_iigen_dec(inode);
027c5e7a 17198+ spin_lock(&inode->i_lock);
c1595e42 17199+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) {
027c5e7a 17200+ spin_lock(&d->d_lock);
4a4d8108
AM
17201+ dname = &d->d_name;
17202+ if (dname->len != nlen
027c5e7a
AM
17203+ && memcmp(dname->name, name, nlen)) {
17204+ spin_unlock(&d->d_lock);
4a4d8108 17205+ continue;
027c5e7a 17206+ }
4a4d8108 17207+ err = 0;
4a4d8108
AM
17208+ au_digen_dec(d);
17209+ spin_unlock(&d->d_lock);
17210+ break;
1facf9fc 17211+ }
027c5e7a 17212+ spin_unlock(&inode->i_lock);
1308ab2a 17213+ } else {
027c5e7a 17214+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIR);
c1595e42 17215+ d = d_find_any_alias(inode);
4a4d8108
AM
17216+ if (!d) {
17217+ au_iigen_dec(inode);
17218+ goto out;
17219+ }
1facf9fc 17220+
027c5e7a 17221+ spin_lock(&d->d_lock);
4a4d8108 17222+ dname = &d->d_name;
027c5e7a
AM
17223+ if (dname->len == nlen && !memcmp(dname->name, name, nlen)) {
17224+ spin_unlock(&d->d_lock);
4a4d8108 17225+ err = hn_gen_tree(d);
027c5e7a
AM
17226+ spin_lock(&d->d_lock);
17227+ }
17228+ spin_unlock(&d->d_lock);
4a4d8108
AM
17229+ dput(d);
17230+ }
1facf9fc 17231+
4f0767ce 17232+out:
4a4d8108 17233+ AuTraceErr(err);
1308ab2a 17234+ return err;
17235+}
dece6358 17236+
4a4d8108 17237+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
1facf9fc 17238+{
4a4d8108 17239+ int err;
1facf9fc 17240+
5527c038 17241+ if (IS_ROOT(dentry)) {
0c3ec466 17242+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
17243+ return 0;
17244+ }
1308ab2a 17245+
4a4d8108
AM
17246+ err = 0;
17247+ if (!isdir) {
4a4d8108 17248+ au_digen_dec(dentry);
5527c038
JR
17249+ if (d_really_is_positive(dentry))
17250+ au_iigen_dec(d_inode(dentry));
4a4d8108 17251+ } else {
027c5e7a 17252+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR);
5527c038 17253+ if (d_really_is_positive(dentry))
4a4d8108
AM
17254+ err = hn_gen_tree(dentry);
17255+ }
17256+
17257+ AuTraceErr(err);
17258+ return err;
1facf9fc 17259+}
17260+
4a4d8108 17261+/* ---------------------------------------------------------------------- */
1facf9fc 17262+
4a4d8108
AM
17263+/* hnotify job flags */
17264+#define AuHnJob_XINO0 1
17265+#define AuHnJob_GEN (1 << 1)
17266+#define AuHnJob_DIRENT (1 << 2)
17267+#define AuHnJob_ISDIR (1 << 3)
17268+#define AuHnJob_TRYXINO0 (1 << 4)
17269+#define AuHnJob_MNTPNT (1 << 5)
17270+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name)
7f207e10
AM
17271+#define au_fset_hnjob(flags, name) \
17272+ do { (flags) |= AuHnJob_##name; } while (0)
17273+#define au_fclr_hnjob(flags, name) \
17274+ do { (flags) &= ~AuHnJob_##name; } while (0)
1facf9fc 17275+
4a4d8108
AM
17276+enum {
17277+ AuHn_CHILD,
17278+ AuHn_PARENT,
17279+ AuHnLast
17280+};
1facf9fc 17281+
4a4d8108
AM
17282+struct au_hnotify_args {
17283+ struct inode *h_dir, *dir, *h_child_inode;
17284+ u32 mask;
17285+ unsigned int flags[AuHnLast];
17286+ unsigned int h_child_nlen;
17287+ char h_child_name[];
17288+};
1facf9fc 17289+
4a4d8108
AM
17290+struct hn_job_args {
17291+ unsigned int flags;
17292+ struct inode *inode, *h_inode, *dir, *h_dir;
17293+ struct dentry *dentry;
17294+ char *h_name;
17295+ int h_nlen;
17296+};
1308ab2a 17297+
4a4d8108
AM
17298+static int hn_job(struct hn_job_args *a)
17299+{
17300+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
076b876e 17301+ int e;
1308ab2a 17302+
4a4d8108
AM
17303+ /* reset xino */
17304+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
17305+ hn_xino(a->inode, a->h_inode); /* ignore this error */
1308ab2a 17306+
4a4d8108
AM
17307+ if (au_ftest_hnjob(a->flags, TRYXINO0)
17308+ && a->inode
17309+ && a->h_inode) {
be118d29 17310+ inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD);
38d290e6
JR
17311+ if (!a->h_inode->i_nlink
17312+ && !(a->h_inode->i_state & I_LINKABLE))
4a4d8108 17313+ hn_xino(a->inode, a->h_inode); /* ignore this error */
3c1bdaff 17314+ inode_unlock_shared(a->h_inode);
1308ab2a 17315+ }
1facf9fc 17316+
4a4d8108
AM
17317+ /* make the generation obsolete */
17318+ if (au_ftest_hnjob(a->flags, GEN)) {
076b876e 17319+ e = -1;
4a4d8108 17320+ if (a->inode)
076b876e 17321+ e = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
4a4d8108 17322+ isdir);
076b876e 17323+ if (e && a->dentry)
4a4d8108
AM
17324+ hn_gen_by_name(a->dentry, isdir);
17325+ /* ignore this error */
1facf9fc 17326+ }
1facf9fc 17327+
4a4d8108
AM
17328+ /* make dir entries obsolete */
17329+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
17330+ struct au_vdir *vdir;
1facf9fc 17331+
4a4d8108
AM
17332+ vdir = au_ivdir(a->inode);
17333+ if (vdir)
17334+ vdir->vd_jiffy = 0;
17335+ /* IMustLock(a->inode); */
be118d29 17336+ /* inode_inc_iversion(a->inode); */
4a4d8108 17337+ }
1facf9fc 17338+
4a4d8108
AM
17339+ /* can do nothing but warn */
17340+ if (au_ftest_hnjob(a->flags, MNTPNT)
17341+ && a->dentry
17342+ && d_mountpoint(a->dentry))
523b37e3 17343+ pr_warn("mount-point %pd is removed or renamed\n", a->dentry);
1facf9fc 17344+
4a4d8108 17345+ return 0;
1308ab2a 17346+}
1facf9fc 17347+
1308ab2a 17348+/* ---------------------------------------------------------------------- */
1facf9fc 17349+
4a4d8108
AM
17350+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
17351+ struct inode *dir)
1308ab2a 17352+{
4a4d8108
AM
17353+ struct dentry *dentry, *d, *parent;
17354+ struct qstr *dname;
1308ab2a 17355+
c1595e42 17356+ parent = d_find_any_alias(dir);
4a4d8108
AM
17357+ if (!parent)
17358+ return NULL;
1308ab2a 17359+
4a4d8108 17360+ dentry = NULL;
027c5e7a 17361+ spin_lock(&parent->d_lock);
c1595e42 17362+ list_for_each_entry(d, &parent->d_subdirs, d_child) {
523b37e3 17363+ /* AuDbg("%pd\n", d); */
027c5e7a 17364+ spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
4a4d8108
AM
17365+ dname = &d->d_name;
17366+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
027c5e7a
AM
17367+ goto cont_unlock;
17368+ if (au_di(d))
17369+ au_digen_dec(d);
17370+ else
17371+ goto cont_unlock;
c1595e42 17372+ if (au_dcount(d) > 0) {
027c5e7a 17373+ dentry = dget_dlock(d);
4a4d8108 17374+ spin_unlock(&d->d_lock);
027c5e7a 17375+ break;
dece6358 17376+ }
1facf9fc 17377+
f6b6e03d 17378+cont_unlock:
027c5e7a 17379+ spin_unlock(&d->d_lock);
1308ab2a 17380+ }
027c5e7a 17381+ spin_unlock(&parent->d_lock);
4a4d8108 17382+ dput(parent);
1facf9fc 17383+
4a4d8108
AM
17384+ if (dentry)
17385+ di_write_lock_child(dentry);
1308ab2a 17386+
4a4d8108
AM
17387+ return dentry;
17388+}
dece6358 17389+
4a4d8108
AM
17390+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
17391+ aufs_bindex_t bindex, ino_t h_ino)
17392+{
17393+ struct inode *inode;
17394+ ino_t ino;
17395+ int err;
17396+
17397+ inode = NULL;
17398+ err = au_xino_read(sb, bindex, h_ino, &ino);
17399+ if (!err && ino)
17400+ inode = ilookup(sb, ino);
17401+ if (!inode)
17402+ goto out;
17403+
17404+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 17405+ pr_warn("wrong root branch\n");
4a4d8108
AM
17406+ iput(inode);
17407+ inode = NULL;
17408+ goto out;
1308ab2a 17409+ }
17410+
4a4d8108 17411+ ii_write_lock_child(inode);
1308ab2a 17412+
4f0767ce 17413+out:
4a4d8108 17414+ return inode;
dece6358
AM
17415+}
17416+
4a4d8108 17417+static void au_hn_bh(void *_args)
1facf9fc 17418+{
4a4d8108
AM
17419+ struct au_hnotify_args *a = _args;
17420+ struct super_block *sb;
5afbbe0d 17421+ aufs_bindex_t bindex, bbot, bfound;
4a4d8108 17422+ unsigned char xino, try_iput;
1facf9fc 17423+ int err;
1308ab2a 17424+ struct inode *inode;
4a4d8108
AM
17425+ ino_t h_ino;
17426+ struct hn_job_args args;
17427+ struct dentry *dentry;
17428+ struct au_sbinfo *sbinfo;
1facf9fc 17429+
4a4d8108
AM
17430+ AuDebugOn(!_args);
17431+ AuDebugOn(!a->h_dir);
17432+ AuDebugOn(!a->dir);
17433+ AuDebugOn(!a->mask);
17434+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
17435+ a->mask, a->dir->i_ino, a->h_dir->i_ino,
17436+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
1facf9fc 17437+
4a4d8108
AM
17438+ inode = NULL;
17439+ dentry = NULL;
17440+ /*
17441+ * do not lock a->dir->i_mutex here
17442+ * because of d_revalidate() may cause a deadlock.
17443+ */
17444+ sb = a->dir->i_sb;
17445+ AuDebugOn(!sb);
17446+ sbinfo = au_sbi(sb);
17447+ AuDebugOn(!sbinfo);
7f207e10 17448+ si_write_lock(sb, AuLock_NOPLMW);
1facf9fc 17449+
8b6a4947
AM
17450+ if (au_opt_test(sbinfo->si_mntflags, DIRREN))
17451+ switch (a->mask & FS_EVENTS_POSS_ON_CHILD) {
17452+ case FS_MOVED_FROM:
17453+ case FS_MOVED_TO:
17454+ AuWarn1("DIRREN with UDBA may not work correctly "
17455+ "for the direct rename(2)\n");
17456+ }
17457+
4a4d8108
AM
17458+ ii_read_lock_parent(a->dir);
17459+ bfound = -1;
5afbbe0d
AM
17460+ bbot = au_ibbot(a->dir);
17461+ for (bindex = au_ibtop(a->dir); bindex <= bbot; bindex++)
4a4d8108
AM
17462+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
17463+ bfound = bindex;
17464+ break;
17465+ }
17466+ ii_read_unlock(a->dir);
17467+ if (unlikely(bfound < 0))
17468+ goto out;
1facf9fc 17469+
4a4d8108
AM
17470+ xino = !!au_opt_test(au_mntflags(sb), XINO);
17471+ h_ino = 0;
17472+ if (a->h_child_inode)
17473+ h_ino = a->h_child_inode->i_ino;
1facf9fc 17474+
4a4d8108
AM
17475+ if (a->h_child_nlen
17476+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
17477+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
17478+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
17479+ a->dir);
17480+ try_iput = 0;
5527c038
JR
17481+ if (dentry && d_really_is_positive(dentry))
17482+ inode = d_inode(dentry);
4a4d8108
AM
17483+ if (xino && !inode && h_ino
17484+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
17485+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
17486+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
17487+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
17488+ try_iput = 1;
f0c0a007 17489+ }
1facf9fc 17490+
4a4d8108
AM
17491+ args.flags = a->flags[AuHn_CHILD];
17492+ args.dentry = dentry;
17493+ args.inode = inode;
17494+ args.h_inode = a->h_child_inode;
17495+ args.dir = a->dir;
17496+ args.h_dir = a->h_dir;
17497+ args.h_name = a->h_child_name;
17498+ args.h_nlen = a->h_child_nlen;
17499+ err = hn_job(&args);
17500+ if (dentry) {
027c5e7a 17501+ if (au_di(dentry))
4a4d8108
AM
17502+ di_write_unlock(dentry);
17503+ dput(dentry);
17504+ }
17505+ if (inode && try_iput) {
17506+ ii_write_unlock(inode);
17507+ iput(inode);
17508+ }
1facf9fc 17509+
4a4d8108
AM
17510+ ii_write_lock_parent(a->dir);
17511+ args.flags = a->flags[AuHn_PARENT];
17512+ args.dentry = NULL;
17513+ args.inode = a->dir;
17514+ args.h_inode = a->h_dir;
17515+ args.dir = NULL;
17516+ args.h_dir = NULL;
17517+ args.h_name = NULL;
17518+ args.h_nlen = 0;
17519+ err = hn_job(&args);
17520+ ii_write_unlock(a->dir);
1facf9fc 17521+
4f0767ce 17522+out:
4a4d8108
AM
17523+ iput(a->h_child_inode);
17524+ iput(a->h_dir);
17525+ iput(a->dir);
027c5e7a
AM
17526+ si_write_unlock(sb);
17527+ au_nwt_done(&sbinfo->si_nowait);
9f237c51 17528+ au_kfree_rcu(a);
dece6358 17529+}
1facf9fc 17530+
4a4d8108
AM
17531+/* ---------------------------------------------------------------------- */
17532+
17533+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
b62f1e65 17534+ const struct qstr *h_child_qstr, struct inode *h_child_inode)
dece6358 17535+{
4a4d8108 17536+ int err, len;
53392da6 17537+ unsigned int flags[AuHnLast], f;
4a4d8108
AM
17538+ unsigned char isdir, isroot, wh;
17539+ struct inode *dir;
17540+ struct au_hnotify_args *args;
17541+ char *p, *h_child_name;
dece6358 17542+
1308ab2a 17543+ err = 0;
4a4d8108
AM
17544+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
17545+ dir = igrab(hnotify->hn_aufs_inode);
17546+ if (!dir)
17547+ goto out;
1facf9fc 17548+
4a4d8108
AM
17549+ isroot = (dir->i_ino == AUFS_ROOT_INO);
17550+ wh = 0;
17551+ h_child_name = (void *)h_child_qstr->name;
17552+ len = h_child_qstr->len;
17553+ if (h_child_name) {
17554+ if (len > AUFS_WH_PFX_LEN
17555+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
17556+ h_child_name += AUFS_WH_PFX_LEN;
17557+ len -= AUFS_WH_PFX_LEN;
17558+ wh = 1;
17559+ }
1facf9fc 17560+ }
dece6358 17561+
4a4d8108
AM
17562+ isdir = 0;
17563+ if (h_child_inode)
17564+ isdir = !!S_ISDIR(h_child_inode->i_mode);
17565+ flags[AuHn_PARENT] = AuHnJob_ISDIR;
17566+ flags[AuHn_CHILD] = 0;
17567+ if (isdir)
17568+ flags[AuHn_CHILD] = AuHnJob_ISDIR;
17569+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
17570+ au_fset_hnjob(flags[AuHn_CHILD], GEN);
fbc438ed 17571+ switch (mask & ALL_FSNOTIFY_DIRENT_EVENTS) {
4a4d8108
AM
17572+ case FS_MOVED_FROM:
17573+ case FS_MOVED_TO:
17574+ au_fset_hnjob(flags[AuHn_CHILD], XINO0);
17575+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
42a736d3 17576+ fallthrough;
4a4d8108 17577+ case FS_CREATE:
fb47a38f 17578+ AuDebugOn(!h_child_name);
4a4d8108 17579+ break;
1facf9fc 17580+
4a4d8108
AM
17581+ case FS_DELETE:
17582+ /*
17583+ * aufs never be able to get this child inode.
17584+ * revalidation should be in d_revalidate()
17585+ * by checking i_nlink, i_generation or d_unhashed().
17586+ */
17587+ AuDebugOn(!h_child_name);
17588+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
17589+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
17590+ break;
dece6358 17591+
4a4d8108
AM
17592+ default:
17593+ AuDebugOn(1);
17594+ }
1308ab2a 17595+
4a4d8108
AM
17596+ if (wh)
17597+ h_child_inode = NULL;
1308ab2a 17598+
4a4d8108
AM
17599+ err = -ENOMEM;
17600+ /* iput() and kfree() will be called in au_hnotify() */
4a4d8108 17601+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
4a4d8108
AM
17602+ if (unlikely(!args)) {
17603+ AuErr1("no memory\n");
17604+ iput(dir);
17605+ goto out;
17606+ }
17607+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
17608+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
17609+ args->mask = mask;
17610+ args->dir = dir;
17611+ args->h_dir = igrab(h_dir);
17612+ if (h_child_inode)
17613+ h_child_inode = igrab(h_child_inode); /* can be NULL */
17614+ args->h_child_inode = h_child_inode;
17615+ args->h_child_nlen = len;
17616+ if (len) {
17617+ p = (void *)args;
17618+ p += sizeof(*args);
17619+ memcpy(p, h_child_name, len);
17620+ p[len] = 0;
1308ab2a 17621+ }
1308ab2a 17622+
38d290e6 17623+ /* NFS fires the event for silly-renamed one from kworker */
53392da6 17624+ f = 0;
38d290e6
JR
17625+ if (!dir->i_nlink
17626+ || (au_test_nfs(h_dir->i_sb) && (mask & FS_DELETE)))
53392da6
AM
17627+ f = AuWkq_NEST;
17628+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb, f);
4a4d8108
AM
17629+ if (unlikely(err)) {
17630+ pr_err("wkq %d\n", err);
17631+ iput(args->h_child_inode);
17632+ iput(args->h_dir);
17633+ iput(args->dir);
9f237c51 17634+ au_kfree_rcu(args);
1facf9fc 17635+ }
1facf9fc 17636+
4a4d8108 17637+out:
1facf9fc 17638+ return err;
17639+}
17640+
027c5e7a
AM
17641+/* ---------------------------------------------------------------------- */
17642+
17643+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm)
17644+{
17645+ int err;
17646+
17647+ AuDebugOn(!(udba & AuOptMask_UDBA));
17648+
17649+ err = 0;
17650+ if (au_hnotify_op.reset_br)
17651+ err = au_hnotify_op.reset_br(udba, br, perm);
17652+
17653+ return err;
17654+}
17655+
17656+int au_hnotify_init_br(struct au_branch *br, int perm)
17657+{
17658+ int err;
17659+
17660+ err = 0;
17661+ if (au_hnotify_op.init_br)
17662+ err = au_hnotify_op.init_br(br, perm);
17663+
17664+ return err;
17665+}
17666+
17667+void au_hnotify_fin_br(struct au_branch *br)
17668+{
17669+ if (au_hnotify_op.fin_br)
17670+ au_hnotify_op.fin_br(br);
17671+}
17672+
4a4d8108
AM
17673+static void au_hn_destroy_cache(void)
17674+{
1c60b727
AM
17675+ kmem_cache_destroy(au_cache[AuCache_HNOTIFY]);
17676+ au_cache[AuCache_HNOTIFY] = NULL;
4a4d8108 17677+}
1308ab2a 17678+
4a4d8108 17679+int __init au_hnotify_init(void)
1facf9fc 17680+{
1308ab2a 17681+ int err;
1308ab2a 17682+
4a4d8108 17683+ err = -ENOMEM;
1c60b727
AM
17684+ au_cache[AuCache_HNOTIFY] = AuCache(au_hnotify);
17685+ if (au_cache[AuCache_HNOTIFY]) {
027c5e7a
AM
17686+ err = 0;
17687+ if (au_hnotify_op.init)
17688+ err = au_hnotify_op.init();
4a4d8108
AM
17689+ if (unlikely(err))
17690+ au_hn_destroy_cache();
1308ab2a 17691+ }
1308ab2a 17692+ AuTraceErr(err);
4a4d8108 17693+ return err;
1308ab2a 17694+}
17695+
4a4d8108 17696+void au_hnotify_fin(void)
1308ab2a 17697+{
027c5e7a
AM
17698+ if (au_hnotify_op.fin)
17699+ au_hnotify_op.fin();
f0c0a007 17700+
4a4d8108 17701+ /* cf. au_cache_fin() */
1c60b727 17702+ if (au_cache[AuCache_HNOTIFY])
4a4d8108 17703+ au_hn_destroy_cache();
dece6358 17704+}
7f207e10 17705diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
eca34b5c 17706--- /usr/share/empty/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
319657f6 17707+++ linux/fs/aufs/iinfo.c 2021-12-03 15:38:59.936647310 +0100
062440b3 17708@@ -0,0 +1,286 @@
cd7a4cd9 17709+// SPDX-License-Identifier: GPL-2.0
dece6358 17710+/*
6d176551 17711+ * Copyright (C) 2005-2021 Junjiro R. Okajima
dece6358
AM
17712+ *
17713+ * This program, aufs is free software; you can redistribute it and/or modify
17714+ * it under the terms of the GNU General Public License as published by
17715+ * the Free Software Foundation; either version 2 of the License, or
17716+ * (at your option) any later version.
17717+ *
17718+ * This program is distributed in the hope that it will be useful,
17719+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17720+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17721+ * GNU General Public License for more details.
17722+ *
17723+ * You should have received a copy of the GNU General Public License
523b37e3 17724+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
dece6358 17725+ */
1facf9fc 17726+
dece6358 17727+/*
4a4d8108 17728+ * inode private data
dece6358 17729+ */
1facf9fc 17730+
1308ab2a 17731+#include "aufs.h"
1facf9fc 17732+
4a4d8108 17733+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 17734+{
4a4d8108 17735+ struct inode *h_inode;
5afbbe0d 17736+ struct au_hinode *hinode;
1facf9fc 17737+
4a4d8108 17738+ IiMustAnyLock(inode);
1facf9fc 17739+
5afbbe0d
AM
17740+ hinode = au_hinode(au_ii(inode), bindex);
17741+ h_inode = hinode->hi_inode;
4a4d8108
AM
17742+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
17743+ return h_inode;
17744+}
1facf9fc 17745+
4a4d8108
AM
17746+/* todo: hard/soft set? */
17747+void au_hiput(struct au_hinode *hinode)
17748+{
17749+ au_hn_free(hinode);
17750+ dput(hinode->hi_whdentry);
17751+ iput(hinode->hi_inode);
17752+}
1facf9fc 17753+
4a4d8108
AM
17754+unsigned int au_hi_flags(struct inode *inode, int isdir)
17755+{
17756+ unsigned int flags;
17757+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
1facf9fc 17758+
4a4d8108
AM
17759+ flags = 0;
17760+ if (au_opt_test(mnt_flags, XINO))
17761+ au_fset_hi(flags, XINO);
17762+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
17763+ au_fset_hi(flags, HNOTIFY);
17764+ return flags;
1facf9fc 17765+}
17766+
4a4d8108
AM
17767+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
17768+ struct inode *h_inode, unsigned int flags)
1308ab2a 17769+{
4a4d8108
AM
17770+ struct au_hinode *hinode;
17771+ struct inode *hi;
17772+ struct au_iinfo *iinfo = au_ii(inode);
1facf9fc 17773+
4a4d8108 17774+ IiMustWriteLock(inode);
dece6358 17775+
5afbbe0d 17776+ hinode = au_hinode(iinfo, bindex);
4a4d8108
AM
17777+ hi = hinode->hi_inode;
17778+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
17779+
17780+ if (hi)
17781+ au_hiput(hinode);
17782+ hinode->hi_inode = h_inode;
17783+ if (h_inode) {
17784+ int err;
17785+ struct super_block *sb = inode->i_sb;
17786+ struct au_branch *br;
17787+
027c5e7a
AM
17788+ AuDebugOn(inode->i_mode
17789+ && (h_inode->i_mode & S_IFMT)
17790+ != (inode->i_mode & S_IFMT));
5afbbe0d 17791+ if (bindex == iinfo->ii_btop)
4a4d8108
AM
17792+ au_cpup_igen(inode, h_inode);
17793+ br = au_sbr(sb, bindex);
17794+ hinode->hi_id = br->br_id;
17795+ if (au_ftest_hi(flags, XINO)) {
17796+ err = au_xino_write(sb, bindex, h_inode->i_ino,
17797+ inode->i_ino);
17798+ if (unlikely(err))
17799+ AuIOErr1("failed au_xino_write() %d\n", err);
17800+ }
17801+
17802+ if (au_ftest_hi(flags, HNOTIFY)
17803+ && au_br_hnotifyable(br->br_perm)) {
027c5e7a 17804+ err = au_hn_alloc(hinode, inode);
4a4d8108
AM
17805+ if (unlikely(err))
17806+ AuIOErr1("au_hn_alloc() %d\n", err);
1308ab2a 17807+ }
17808+ }
4a4d8108 17809+}
dece6358 17810+
4a4d8108
AM
17811+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
17812+ struct dentry *h_wh)
17813+{
17814+ struct au_hinode *hinode;
dece6358 17815+
4a4d8108
AM
17816+ IiMustWriteLock(inode);
17817+
5afbbe0d 17818+ hinode = au_hinode(au_ii(inode), bindex);
4a4d8108
AM
17819+ AuDebugOn(hinode->hi_whdentry);
17820+ hinode->hi_whdentry = h_wh;
1facf9fc 17821+}
17822+
537831f9 17823+void au_update_iigen(struct inode *inode, int half)
1308ab2a 17824+{
537831f9
AM
17825+ struct au_iinfo *iinfo;
17826+ struct au_iigen *iigen;
17827+ unsigned int sigen;
17828+
17829+ sigen = au_sigen(inode->i_sb);
17830+ iinfo = au_ii(inode);
17831+ iigen = &iinfo->ii_generation;
be52b249 17832+ spin_lock(&iigen->ig_spin);
537831f9
AM
17833+ iigen->ig_generation = sigen;
17834+ if (half)
17835+ au_ig_fset(iigen->ig_flags, HALF_REFRESHED);
17836+ else
17837+ au_ig_fclr(iigen->ig_flags, HALF_REFRESHED);
be52b249 17838+ spin_unlock(&iigen->ig_spin);
4a4d8108 17839+}
1facf9fc 17840+
4a4d8108
AM
17841+/* it may be called at remount time, too */
17842+void au_update_ibrange(struct inode *inode, int do_put_zero)
17843+{
17844+ struct au_iinfo *iinfo;
5afbbe0d 17845+ aufs_bindex_t bindex, bbot;
1facf9fc 17846+
5afbbe0d 17847+ AuDebugOn(au_is_bad_inode(inode));
4a4d8108 17848+ IiMustWriteLock(inode);
1facf9fc 17849+
5afbbe0d
AM
17850+ iinfo = au_ii(inode);
17851+ if (do_put_zero && iinfo->ii_btop >= 0) {
17852+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot;
4a4d8108
AM
17853+ bindex++) {
17854+ struct inode *h_i;
1facf9fc 17855+
5afbbe0d 17856+ h_i = au_hinode(iinfo, bindex)->hi_inode;
38d290e6
JR
17857+ if (h_i
17858+ && !h_i->i_nlink
17859+ && !(h_i->i_state & I_LINKABLE))
027c5e7a
AM
17860+ au_set_h_iptr(inode, bindex, NULL, 0);
17861+ }
4a4d8108
AM
17862+ }
17863+
5afbbe0d
AM
17864+ iinfo->ii_btop = -1;
17865+ iinfo->ii_bbot = -1;
17866+ bbot = au_sbbot(inode->i_sb);
17867+ for (bindex = 0; bindex <= bbot; bindex++)
17868+ if (au_hinode(iinfo, bindex)->hi_inode) {
17869+ iinfo->ii_btop = bindex;
4a4d8108 17870+ break;
027c5e7a 17871+ }
5afbbe0d
AM
17872+ if (iinfo->ii_btop >= 0)
17873+ for (bindex = bbot; bindex >= iinfo->ii_btop; bindex--)
17874+ if (au_hinode(iinfo, bindex)->hi_inode) {
17875+ iinfo->ii_bbot = bindex;
027c5e7a
AM
17876+ break;
17877+ }
5afbbe0d 17878+ AuDebugOn(iinfo->ii_btop > iinfo->ii_bbot);
1308ab2a 17879+}
1facf9fc 17880+
dece6358 17881+/* ---------------------------------------------------------------------- */
1facf9fc 17882+
4a4d8108 17883+void au_icntnr_init_once(void *_c)
dece6358 17884+{
4a4d8108
AM
17885+ struct au_icntnr *c = _c;
17886+ struct au_iinfo *iinfo = &c->iinfo;
1facf9fc 17887+
be52b249 17888+ spin_lock_init(&iinfo->ii_generation.ig_spin);
4a4d8108
AM
17889+ au_rw_init(&iinfo->ii_rwsem);
17890+ inode_init_once(&c->vfs_inode);
17891+}
1facf9fc 17892+
5afbbe0d
AM
17893+void au_hinode_init(struct au_hinode *hinode)
17894+{
17895+ hinode->hi_inode = NULL;
17896+ hinode->hi_id = -1;
17897+ au_hn_init(hinode);
17898+ hinode->hi_whdentry = NULL;
17899+}
17900+
4a4d8108
AM
17901+int au_iinfo_init(struct inode *inode)
17902+{
17903+ struct au_iinfo *iinfo;
17904+ struct super_block *sb;
5afbbe0d 17905+ struct au_hinode *hi;
4a4d8108 17906+ int nbr, i;
1facf9fc 17907+
4a4d8108
AM
17908+ sb = inode->i_sb;
17909+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
5afbbe0d 17910+ nbr = au_sbbot(sb) + 1;
4a4d8108
AM
17911+ if (unlikely(nbr <= 0))
17912+ nbr = 1;
5afbbe0d
AM
17913+ hi = kmalloc_array(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
17914+ if (hi) {
acd2b654 17915+ au_lcnt_inc(&au_sbi(sb)->si_ninodes);
5afbbe0d
AM
17916+
17917+ iinfo->ii_hinode = hi;
17918+ for (i = 0; i < nbr; i++, hi++)
17919+ au_hinode_init(hi);
1facf9fc 17920+
537831f9 17921+ iinfo->ii_generation.ig_generation = au_sigen(sb);
5afbbe0d
AM
17922+ iinfo->ii_btop = -1;
17923+ iinfo->ii_bbot = -1;
4a4d8108
AM
17924+ iinfo->ii_vdir = NULL;
17925+ return 0;
1308ab2a 17926+ }
4a4d8108
AM
17927+ return -ENOMEM;
17928+}
1facf9fc 17929+
e2f27e51 17930+int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink)
4a4d8108 17931+{
5afbbe0d 17932+ int err, i;
4a4d8108 17933+ struct au_hinode *hip;
1facf9fc 17934+
4a4d8108
AM
17935+ AuRwMustWriteLock(&iinfo->ii_rwsem);
17936+
17937+ err = -ENOMEM;
e2f27e51
AM
17938+ hip = au_krealloc(iinfo->ii_hinode, sizeof(*hip) * nbr, GFP_NOFS,
17939+ may_shrink);
4a4d8108
AM
17940+ if (hip) {
17941+ iinfo->ii_hinode = hip;
5afbbe0d
AM
17942+ i = iinfo->ii_bbot + 1;
17943+ hip += i;
17944+ for (; i < nbr; i++, hip++)
17945+ au_hinode_init(hip);
4a4d8108 17946+ err = 0;
1308ab2a 17947+ }
4a4d8108 17948+
1308ab2a 17949+ return err;
1facf9fc 17950+}
17951+
4a4d8108 17952+void au_iinfo_fin(struct inode *inode)
1facf9fc 17953+{
4a4d8108
AM
17954+ struct au_iinfo *iinfo;
17955+ struct au_hinode *hi;
17956+ struct super_block *sb;
5afbbe0d 17957+ aufs_bindex_t bindex, bbot;
b752ccd1 17958+ const unsigned char unlinked = !inode->i_nlink;
1308ab2a 17959+
5afbbe0d 17960+ AuDebugOn(au_is_bad_inode(inode));
1308ab2a 17961+
b752ccd1 17962+ sb = inode->i_sb;
acd2b654 17963+ au_lcnt_dec(&au_sbi(sb)->si_ninodes);
b752ccd1
AM
17964+ if (si_pid_test(sb))
17965+ au_xino_delete_inode(inode, unlinked);
17966+ else {
17967+ /*
17968+ * it is safe to hide the dependency between sbinfo and
17969+ * sb->s_umount.
17970+ */
17971+ lockdep_off();
17972+ si_noflush_read_lock(sb);
17973+ au_xino_delete_inode(inode, unlinked);
17974+ si_read_unlock(sb);
17975+ lockdep_on();
17976+ }
17977+
5afbbe0d 17978+ iinfo = au_ii(inode);
4a4d8108 17979+ if (iinfo->ii_vdir)
1c60b727 17980+ au_vdir_free(iinfo->ii_vdir);
1308ab2a 17981+
5afbbe0d 17982+ bindex = iinfo->ii_btop;
b752ccd1 17983+ if (bindex >= 0) {
5afbbe0d
AM
17984+ hi = au_hinode(iinfo, bindex);
17985+ bbot = iinfo->ii_bbot;
17986+ while (bindex++ <= bbot) {
b752ccd1 17987+ if (hi->hi_inode)
4a4d8108 17988+ au_hiput(hi);
4a4d8108
AM
17989+ hi++;
17990+ }
17991+ }
9f237c51 17992+ au_kfree_rcu(iinfo->ii_hinode);
4a4d8108 17993+ AuRwDestroy(&iinfo->ii_rwsem);
dece6358 17994+}
7f207e10 17995diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
eca34b5c 17996--- /usr/share/empty/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
319657f6 17997+++ linux/fs/aufs/inode.c 2021-12-03 15:40:58.236647297 +0100
0b2a12c6 17998@@ -0,0 +1,531 @@
cd7a4cd9 17999+// SPDX-License-Identifier: GPL-2.0
4a4d8108 18000+/*
6d176551 18001+ * Copyright (C) 2005-2021 Junjiro R. Okajima
4a4d8108
AM
18002+ *
18003+ * This program, aufs is free software; you can redistribute it and/or modify
18004+ * it under the terms of the GNU General Public License as published by
18005+ * the Free Software Foundation; either version 2 of the License, or
18006+ * (at your option) any later version.
18007+ *
18008+ * This program is distributed in the hope that it will be useful,
18009+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18010+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18011+ * GNU General Public License for more details.
18012+ *
18013+ * You should have received a copy of the GNU General Public License
523b37e3 18014+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 18015+ */
1facf9fc 18016+
4a4d8108
AM
18017+/*
18018+ * inode functions
18019+ */
1facf9fc 18020+
eca801bf 18021+#include <linux/iversion.h>
4a4d8108 18022+#include "aufs.h"
1308ab2a 18023+
4a4d8108
AM
18024+struct inode *au_igrab(struct inode *inode)
18025+{
18026+ if (inode) {
18027+ AuDebugOn(!atomic_read(&inode->i_count));
027c5e7a 18028+ ihold(inode);
1facf9fc 18029+ }
4a4d8108
AM
18030+ return inode;
18031+}
1facf9fc 18032+
4a4d8108
AM
18033+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
18034+{
18035+ au_cpup_attr_all(inode, /*force*/0);
537831f9 18036+ au_update_iigen(inode, /*half*/1);
4a4d8108 18037+ if (do_version)
be118d29 18038+ inode_inc_iversion(inode);
dece6358 18039+}
1facf9fc 18040+
027c5e7a 18041+static int au_ii_refresh(struct inode *inode, int *update)
dece6358 18042+{
e2f27e51 18043+ int err, e, nbr;
027c5e7a 18044+ umode_t type;
4a4d8108 18045+ aufs_bindex_t bindex, new_bindex;
1308ab2a 18046+ struct super_block *sb;
4a4d8108 18047+ struct au_iinfo *iinfo;
027c5e7a 18048+ struct au_hinode *p, *q, tmp;
1facf9fc 18049+
5afbbe0d 18050+ AuDebugOn(au_is_bad_inode(inode));
4a4d8108 18051+ IiMustWriteLock(inode);
1facf9fc 18052+
027c5e7a 18053+ *update = 0;
4a4d8108 18054+ sb = inode->i_sb;
e2f27e51 18055+ nbr = au_sbbot(sb) + 1;
027c5e7a 18056+ type = inode->i_mode & S_IFMT;
4a4d8108 18057+ iinfo = au_ii(inode);
e2f27e51 18058+ err = au_hinode_realloc(iinfo, nbr, /*may_shrink*/0);
4a4d8108 18059+ if (unlikely(err))
1308ab2a 18060+ goto out;
1facf9fc 18061+
5afbbe0d
AM
18062+ AuDebugOn(iinfo->ii_btop < 0);
18063+ p = au_hinode(iinfo, iinfo->ii_btop);
18064+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot;
4a4d8108
AM
18065+ bindex++, p++) {
18066+ if (!p->hi_inode)
18067+ continue;
1facf9fc 18068+
027c5e7a 18069+ AuDebugOn(type != (p->hi_inode->i_mode & S_IFMT));
4a4d8108
AM
18070+ new_bindex = au_br_index(sb, p->hi_id);
18071+ if (new_bindex == bindex)
18072+ continue;
1facf9fc 18073+
4a4d8108 18074+ if (new_bindex < 0) {
027c5e7a 18075+ *update = 1;
4a4d8108
AM
18076+ au_hiput(p);
18077+ p->hi_inode = NULL;
18078+ continue;
1308ab2a 18079+ }
4a4d8108 18080+
5afbbe0d
AM
18081+ if (new_bindex < iinfo->ii_btop)
18082+ iinfo->ii_btop = new_bindex;
18083+ if (iinfo->ii_bbot < new_bindex)
18084+ iinfo->ii_bbot = new_bindex;
4a4d8108 18085+ /* swap two lower inode, and loop again */
5afbbe0d 18086+ q = au_hinode(iinfo, new_bindex);
4a4d8108
AM
18087+ tmp = *q;
18088+ *q = *p;
18089+ *p = tmp;
18090+ if (tmp.hi_inode) {
18091+ bindex--;
18092+ p--;
1308ab2a 18093+ }
18094+ }
4a4d8108 18095+ au_update_ibrange(inode, /*do_put_zero*/0);
e2f27e51 18096+ au_hinode_realloc(iinfo, nbr, /*may_shrink*/1); /* harmless if err */
4a4d8108
AM
18097+ e = au_dy_irefresh(inode);
18098+ if (unlikely(e && !err))
18099+ err = e;
1facf9fc 18100+
4f0767ce 18101+out:
027c5e7a
AM
18102+ AuTraceErr(err);
18103+ return err;
18104+}
18105+
b95c5147
AM
18106+void au_refresh_iop(struct inode *inode, int force_getattr)
18107+{
18108+ int type;
18109+ struct au_sbinfo *sbi = au_sbi(inode->i_sb);
18110+ const struct inode_operations *iop
18111+ = force_getattr ? aufs_iop : sbi->si_iop_array;
18112+
18113+ if (inode->i_op == iop)
18114+ return;
18115+
18116+ switch (inode->i_mode & S_IFMT) {
18117+ case S_IFDIR:
18118+ type = AuIop_DIR;
18119+ break;
18120+ case S_IFLNK:
18121+ type = AuIop_SYMLINK;
18122+ break;
18123+ default:
18124+ type = AuIop_OTHER;
18125+ break;
18126+ }
18127+
18128+ inode->i_op = iop + type;
18129+ /* unnecessary smp_wmb() */
18130+}
18131+
027c5e7a
AM
18132+int au_refresh_hinode_self(struct inode *inode)
18133+{
18134+ int err, update;
18135+
18136+ err = au_ii_refresh(inode, &update);
18137+ if (!err)
18138+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
18139+
18140+ AuTraceErr(err);
4a4d8108
AM
18141+ return err;
18142+}
1facf9fc 18143+
4a4d8108
AM
18144+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
18145+{
027c5e7a 18146+ int err, e, update;
4a4d8108 18147+ unsigned int flags;
027c5e7a 18148+ umode_t mode;
5afbbe0d 18149+ aufs_bindex_t bindex, bbot;
027c5e7a 18150+ unsigned char isdir;
4a4d8108
AM
18151+ struct au_hinode *p;
18152+ struct au_iinfo *iinfo;
1facf9fc 18153+
027c5e7a 18154+ err = au_ii_refresh(inode, &update);
4a4d8108
AM
18155+ if (unlikely(err))
18156+ goto out;
18157+
18158+ update = 0;
18159+ iinfo = au_ii(inode);
5afbbe0d 18160+ p = au_hinode(iinfo, iinfo->ii_btop);
027c5e7a
AM
18161+ mode = (inode->i_mode & S_IFMT);
18162+ isdir = S_ISDIR(mode);
4a4d8108 18163+ flags = au_hi_flags(inode, isdir);
5afbbe0d
AM
18164+ bbot = au_dbbot(dentry);
18165+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) {
5527c038 18166+ struct inode *h_i, *h_inode;
4a4d8108
AM
18167+ struct dentry *h_d;
18168+
18169+ h_d = au_h_dptr(dentry, bindex);
5527c038 18170+ if (!h_d || d_is_negative(h_d))
4a4d8108
AM
18171+ continue;
18172+
5527c038
JR
18173+ h_inode = d_inode(h_d);
18174+ AuDebugOn(mode != (h_inode->i_mode & S_IFMT));
5afbbe0d 18175+ if (iinfo->ii_btop <= bindex && bindex <= iinfo->ii_bbot) {
4a4d8108
AM
18176+ h_i = au_h_iptr(inode, bindex);
18177+ if (h_i) {
5527c038 18178+ if (h_i == h_inode)
4a4d8108
AM
18179+ continue;
18180+ err = -EIO;
18181+ break;
18182+ }
18183+ }
5afbbe0d
AM
18184+ if (bindex < iinfo->ii_btop)
18185+ iinfo->ii_btop = bindex;
18186+ if (iinfo->ii_bbot < bindex)
18187+ iinfo->ii_bbot = bindex;
5527c038 18188+ au_set_h_iptr(inode, bindex, au_igrab(h_inode), flags);
4a4d8108 18189+ update = 1;
1308ab2a 18190+ }
4a4d8108
AM
18191+ au_update_ibrange(inode, /*do_put_zero*/0);
18192+ e = au_dy_irefresh(inode);
18193+ if (unlikely(e && !err))
18194+ err = e;
027c5e7a
AM
18195+ if (!err)
18196+ au_refresh_hinode_attr(inode, update && isdir);
4a4d8108 18197+
4f0767ce 18198+out:
4a4d8108 18199+ AuTraceErr(err);
1308ab2a 18200+ return err;
dece6358
AM
18201+}
18202+
4a4d8108 18203+static int set_inode(struct inode *inode, struct dentry *dentry)
dece6358 18204+{
4a4d8108
AM
18205+ int err;
18206+ unsigned int flags;
18207+ umode_t mode;
5afbbe0d 18208+ aufs_bindex_t bindex, btop, btail;
4a4d8108
AM
18209+ unsigned char isdir;
18210+ struct dentry *h_dentry;
18211+ struct inode *h_inode;
18212+ struct au_iinfo *iinfo;
43982f53 18213+ const struct inode_operations *iop;
dece6358 18214+
4a4d8108 18215+ IiMustWriteLock(inode);
dece6358 18216+
4a4d8108
AM
18217+ err = 0;
18218+ isdir = 0;
b95c5147 18219+ iop = au_sbi(inode->i_sb)->si_iop_array;
5afbbe0d
AM
18220+ btop = au_dbtop(dentry);
18221+ h_dentry = au_h_dptr(dentry, btop);
5527c038 18222+ h_inode = d_inode(h_dentry);
4a4d8108
AM
18223+ mode = h_inode->i_mode;
18224+ switch (mode & S_IFMT) {
18225+ case S_IFREG:
18226+ btail = au_dbtail(dentry);
b95c5147 18227+ inode->i_op = iop + AuIop_OTHER;
4a4d8108 18228+ inode->i_fop = &aufs_file_fop;
5afbbe0d 18229+ err = au_dy_iaop(inode, btop, h_inode);
4a4d8108
AM
18230+ if (unlikely(err))
18231+ goto out;
18232+ break;
18233+ case S_IFDIR:
18234+ isdir = 1;
18235+ btail = au_dbtaildir(dentry);
b95c5147 18236+ inode->i_op = iop + AuIop_DIR;
4a4d8108
AM
18237+ inode->i_fop = &aufs_dir_fop;
18238+ break;
18239+ case S_IFLNK:
18240+ btail = au_dbtail(dentry);
b95c5147 18241+ inode->i_op = iop + AuIop_SYMLINK;
4a4d8108
AM
18242+ break;
18243+ case S_IFBLK:
18244+ case S_IFCHR:
18245+ case S_IFIFO:
18246+ case S_IFSOCK:
18247+ btail = au_dbtail(dentry);
b95c5147 18248+ inode->i_op = iop + AuIop_OTHER;
38d290e6 18249+ init_special_inode(inode, mode, h_inode->i_rdev);
4a4d8108
AM
18250+ break;
18251+ default:
18252+ AuIOErr("Unknown file type 0%o\n", mode);
18253+ err = -EIO;
1308ab2a 18254+ goto out;
4a4d8108 18255+ }
dece6358 18256+
4a4d8108
AM
18257+ /* do not set hnotify for whiteouted dirs (SHWH mode) */
18258+ flags = au_hi_flags(inode, isdir);
18259+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
18260+ && au_ftest_hi(flags, HNOTIFY)
18261+ && dentry->d_name.len > AUFS_WH_PFX_LEN
18262+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
18263+ au_fclr_hi(flags, HNOTIFY);
18264+ iinfo = au_ii(inode);
5afbbe0d
AM
18265+ iinfo->ii_btop = btop;
18266+ iinfo->ii_bbot = btail;
18267+ for (bindex = btop; bindex <= btail; bindex++) {
4a4d8108
AM
18268+ h_dentry = au_h_dptr(dentry, bindex);
18269+ if (h_dentry)
18270+ au_set_h_iptr(inode, bindex,
5527c038 18271+ au_igrab(d_inode(h_dentry)), flags);
4a4d8108
AM
18272+ }
18273+ au_cpup_attr_all(inode, /*force*/1);
c1595e42
JR
18274+ /*
18275+ * to force calling aufs_get_acl() every time,
18276+ * do not call cache_no_acl() for aufs inode.
18277+ */
dece6358 18278+
4f0767ce 18279+out:
4a4d8108
AM
18280+ return err;
18281+}
dece6358 18282+
027c5e7a
AM
18283+/*
18284+ * successful returns with iinfo write_locked
18285+ * minus: errno
18286+ * zero: success, matched
18287+ * plus: no error, but unmatched
18288+ */
18289+static int reval_inode(struct inode *inode, struct dentry *dentry)
4a4d8108
AM
18290+{
18291+ int err;
cfc41e69 18292+ unsigned int gen, igflags;
5afbbe0d 18293+ aufs_bindex_t bindex, bbot;
4a4d8108 18294+ struct inode *h_inode, *h_dinode;
5527c038 18295+ struct dentry *h_dentry;
dece6358 18296+
4a4d8108
AM
18297+ /*
18298+ * before this function, if aufs got any iinfo lock, it must be only
18299+ * one, the parent dir.
18300+ * it can happen by UDBA and the obsoleted inode number.
18301+ */
18302+ err = -EIO;
18303+ if (unlikely(inode->i_ino == parent_ino(dentry)))
18304+ goto out;
18305+
027c5e7a 18306+ err = 1;
4a4d8108 18307+ ii_write_lock_new_child(inode);
5afbbe0d 18308+ h_dentry = au_h_dptr(dentry, au_dbtop(dentry));
5527c038 18309+ h_dinode = d_inode(h_dentry);
5afbbe0d
AM
18310+ bbot = au_ibbot(inode);
18311+ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) {
4a4d8108 18312+ h_inode = au_h_iptr(inode, bindex);
537831f9
AM
18313+ if (!h_inode || h_inode != h_dinode)
18314+ continue;
18315+
18316+ err = 0;
cfc41e69 18317+ gen = au_iigen(inode, &igflags);
537831f9 18318+ if (gen == au_digen(dentry)
cfc41e69 18319+ && !au_ig_ftest(igflags, HALF_REFRESHED))
4a4d8108 18320+ break;
537831f9
AM
18321+
18322+ /* fully refresh inode using dentry */
18323+ err = au_refresh_hinode(inode, dentry);
18324+ if (!err)
18325+ au_update_iigen(inode, /*half*/0);
18326+ break;
1facf9fc 18327+ }
dece6358 18328+
4a4d8108
AM
18329+ if (unlikely(err))
18330+ ii_write_unlock(inode);
4f0767ce 18331+out:
1facf9fc 18332+ return err;
18333+}
1facf9fc 18334+
4a4d8108
AM
18335+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
18336+ unsigned int d_type, ino_t *ino)
1facf9fc 18337+{
521ced18
JR
18338+ int err, idx;
18339+ const int isnondir = d_type != DT_DIR;
1facf9fc 18340+
b752ccd1 18341+ /* prevent hardlinked inode number from race condition */
521ced18
JR
18342+ if (isnondir) {
18343+ err = au_xinondir_enter(sb, bindex, h_ino, &idx);
18344+ if (unlikely(err))
18345+ goto out;
4a4d8108 18346+ }
521ced18 18347+
4a4d8108
AM
18348+ err = au_xino_read(sb, bindex, h_ino, ino);
18349+ if (unlikely(err))
521ced18 18350+ goto out_xinondir;
1308ab2a 18351+
4a4d8108
AM
18352+ if (!*ino) {
18353+ err = -EIO;
18354+ *ino = au_xino_new_ino(sb);
18355+ if (unlikely(!*ino))
521ced18 18356+ goto out_xinondir;
4a4d8108
AM
18357+ err = au_xino_write(sb, bindex, h_ino, *ino);
18358+ if (unlikely(err))
521ced18 18359+ goto out_xinondir;
1308ab2a 18360+ }
1facf9fc 18361+
521ced18
JR
18362+out_xinondir:
18363+ if (isnondir && idx >= 0)
18364+ au_xinondir_leave(sb, bindex, h_ino, idx);
4f0767ce 18365+out:
1facf9fc 18366+ return err;
18367+}
18368+
4a4d8108
AM
18369+/* successful returns with iinfo write_locked */
18370+/* todo: return with unlocked? */
18371+struct inode *au_new_inode(struct dentry *dentry, int must_new)
1facf9fc 18372+{
5527c038 18373+ struct inode *inode, *h_inode;
4a4d8108
AM
18374+ struct dentry *h_dentry;
18375+ struct super_block *sb;
18376+ ino_t h_ino, ino;
521ced18 18377+ int err, idx, hlinked;
5afbbe0d 18378+ aufs_bindex_t btop;
1facf9fc 18379+
4a4d8108 18380+ sb = dentry->d_sb;
5afbbe0d
AM
18381+ btop = au_dbtop(dentry);
18382+ h_dentry = au_h_dptr(dentry, btop);
5527c038
JR
18383+ h_inode = d_inode(h_dentry);
18384+ h_ino = h_inode->i_ino;
521ced18 18385+ hlinked = !d_is_dir(h_dentry) && h_inode->i_nlink > 1;
b752ccd1 18386+
521ced18 18387+new_ino:
b752ccd1
AM
18388+ /*
18389+ * stop 'race'-ing between hardlinks under different
18390+ * parents.
18391+ */
521ced18
JR
18392+ if (hlinked) {
18393+ err = au_xinondir_enter(sb, btop, h_ino, &idx);
18394+ inode = ERR_PTR(err);
18395+ if (unlikely(err))
18396+ goto out;
18397+ }
b752ccd1 18398+
5afbbe0d 18399+ err = au_xino_read(sb, btop, h_ino, &ino);
4a4d8108
AM
18400+ inode = ERR_PTR(err);
18401+ if (unlikely(err))
521ced18 18402+ goto out_xinondir;
b752ccd1 18403+
4a4d8108
AM
18404+ if (!ino) {
18405+ ino = au_xino_new_ino(sb);
18406+ if (unlikely(!ino)) {
18407+ inode = ERR_PTR(-EIO);
521ced18 18408+ goto out_xinondir;
dece6358
AM
18409+ }
18410+ }
1facf9fc 18411+
4a4d8108
AM
18412+ AuDbg("i%lu\n", (unsigned long)ino);
18413+ inode = au_iget_locked(sb, ino);
18414+ err = PTR_ERR(inode);
18415+ if (IS_ERR(inode))
521ced18 18416+ goto out_xinondir;
1facf9fc 18417+
4a4d8108
AM
18418+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
18419+ if (inode->i_state & I_NEW) {
18420+ ii_write_lock_new_child(inode);
18421+ err = set_inode(inode, dentry);
18422+ if (!err) {
18423+ unlock_new_inode(inode);
521ced18 18424+ goto out_xinondir; /* success */
4a4d8108 18425+ }
1308ab2a 18426+
027c5e7a
AM
18427+ /*
18428+ * iget_failed() calls iput(), but we need to call
18429+ * ii_write_unlock() after iget_failed(). so dirty hack for
18430+ * i_count.
18431+ */
18432+ atomic_inc(&inode->i_count);
4a4d8108 18433+ iget_failed(inode);
027c5e7a 18434+ ii_write_unlock(inode);
5afbbe0d 18435+ au_xino_write(sb, btop, h_ino, /*ino*/0);
027c5e7a
AM
18436+ /* ignore this error */
18437+ goto out_iput;
18438+ } else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) {
b752ccd1
AM
18439+ /*
18440+ * horrible race condition between lookup, readdir and copyup
18441+ * (or something).
18442+ */
521ced18
JR
18443+ if (hlinked && idx >= 0)
18444+ au_xinondir_leave(sb, btop, h_ino, idx);
027c5e7a
AM
18445+ err = reval_inode(inode, dentry);
18446+ if (unlikely(err < 0)) {
521ced18 18447+ hlinked = 0;
027c5e7a
AM
18448+ goto out_iput;
18449+ }
521ced18 18450+ if (!err)
4a4d8108 18451+ goto out; /* success */
521ced18
JR
18452+ else if (hlinked && idx >= 0) {
18453+ err = au_xinondir_enter(sb, btop, h_ino, &idx);
18454+ if (unlikely(err)) {
18455+ iput(inode);
18456+ inode = ERR_PTR(err);
18457+ goto out;
18458+ }
18459+ }
4a4d8108
AM
18460+ }
18461+
5527c038 18462+ if (unlikely(au_test_fs_unique_ino(h_inode)))
4a4d8108 18463+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
523b37e3 18464+ " b%d, %s, %pd, hi%lu, i%lu.\n",
5afbbe0d 18465+ btop, au_sbtype(h_dentry->d_sb), dentry,
4a4d8108
AM
18466+ (unsigned long)h_ino, (unsigned long)ino);
18467+ ino = 0;
5afbbe0d 18468+ err = au_xino_write(sb, btop, h_ino, /*ino*/0);
4a4d8108
AM
18469+ if (!err) {
18470+ iput(inode);
521ced18
JR
18471+ if (hlinked && idx >= 0)
18472+ au_xinondir_leave(sb, btop, h_ino, idx);
4a4d8108
AM
18473+ goto new_ino;
18474+ }
1308ab2a 18475+
4f0767ce 18476+out_iput:
4a4d8108 18477+ iput(inode);
4a4d8108 18478+ inode = ERR_PTR(err);
521ced18
JR
18479+out_xinondir:
18480+ if (hlinked && idx >= 0)
18481+ au_xinondir_leave(sb, btop, h_ino, idx);
4f0767ce 18482+out:
4a4d8108 18483+ return inode;
1facf9fc 18484+}
18485+
4a4d8108 18486+/* ---------------------------------------------------------------------- */
1facf9fc 18487+
4a4d8108
AM
18488+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
18489+ struct inode *inode)
18490+{
18491+ int err;
076b876e 18492+ struct inode *hi;
1facf9fc 18493+
4a4d8108 18494+ err = au_br_rdonly(au_sbr(sb, bindex));
1facf9fc 18495+
4a4d8108
AM
18496+ /* pseudo-link after flushed may happen out of bounds */
18497+ if (!err
18498+ && inode
5afbbe0d
AM
18499+ && au_ibtop(inode) <= bindex
18500+ && bindex <= au_ibbot(inode)) {
4a4d8108
AM
18501+ /*
18502+ * permission check is unnecessary since vfsub routine
18503+ * will be called later
18504+ */
076b876e 18505+ hi = au_h_iptr(inode, bindex);
4a4d8108
AM
18506+ if (hi)
18507+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
1facf9fc 18508+ }
18509+
4a4d8108
AM
18510+ return err;
18511+}
dece6358 18512+
0b2a12c6
JR
18513+int au_test_h_perm(struct user_namespace *h_userns, struct inode *h_inode,
18514+ int mask)
4a4d8108 18515+{
2dfbb274 18516+ if (uid_eq(current_fsuid(), GLOBAL_ROOT_UID))
4a4d8108 18517+ return 0;
0b2a12c6 18518+ return inode_permission(h_userns, h_inode, mask);
4a4d8108 18519+}
1facf9fc 18520+
0b2a12c6
JR
18521+int au_test_h_perm_sio(struct user_namespace *h_userns, struct inode *h_inode,
18522+ int mask)
4a4d8108
AM
18523+{
18524+ if (au_test_nfs(h_inode->i_sb)
18525+ && (mask & MAY_WRITE)
18526+ && S_ISDIR(h_inode->i_mode))
18527+ mask |= MAY_READ; /* force permission check */
0b2a12c6 18528+ return au_test_h_perm(h_userns, h_inode, mask);
1facf9fc 18529+}
7f207e10 18530diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
eca34b5c 18531--- /usr/share/empty/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
319657f6 18532+++ linux/fs/aufs/inode.h 2021-12-03 15:40:58.236647297 +0100
0b2a12c6 18533@@ -0,0 +1,705 @@
062440b3 18534+/* SPDX-License-Identifier: GPL-2.0 */
4a4d8108 18535+/*
6d176551 18536+ * Copyright (C) 2005-2021 Junjiro R. Okajima
4a4d8108
AM
18537+ *
18538+ * This program, aufs is free software; you can redistribute it and/or modify
18539+ * it under the terms of the GNU General Public License as published by
18540+ * the Free Software Foundation; either version 2 of the License, or
18541+ * (at your option) any later version.
18542+ *
18543+ * This program is distributed in the hope that it will be useful,
18544+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18545+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18546+ * GNU General Public License for more details.
18547+ *
18548+ * You should have received a copy of the GNU General Public License
523b37e3 18549+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 18550+ */
1facf9fc 18551+
1308ab2a 18552+/*
4a4d8108 18553+ * inode operations
1308ab2a 18554+ */
dece6358 18555+
4a4d8108
AM
18556+#ifndef __AUFS_INODE_H__
18557+#define __AUFS_INODE_H__
dece6358 18558+
4a4d8108 18559+#ifdef __KERNEL__
1308ab2a 18560+
4a4d8108 18561+#include <linux/fsnotify.h>
4a4d8108 18562+#include "rwsem.h"
1308ab2a 18563+
4a4d8108 18564+struct vfsmount;
1facf9fc 18565+
4a4d8108
AM
18566+struct au_hnotify {
18567+#ifdef CONFIG_AUFS_HNOTIFY
18568+#ifdef CONFIG_AUFS_HFSNOTIFY
7f207e10 18569+ /* never use fsnotify_add_vfsmount_mark() */
0c5527e5 18570+ struct fsnotify_mark hn_mark;
4a4d8108 18571+#endif
1c60b727 18572+ struct inode *hn_aufs_inode; /* no get/put */
9f237c51 18573+ struct rcu_head rcu;
4a4d8108
AM
18574+#endif
18575+} ____cacheline_aligned_in_smp;
1facf9fc 18576+
4a4d8108
AM
18577+struct au_hinode {
18578+ struct inode *hi_inode;
18579+ aufs_bindex_t hi_id;
18580+#ifdef CONFIG_AUFS_HNOTIFY
18581+ struct au_hnotify *hi_notify;
18582+#endif
dece6358 18583+
4a4d8108
AM
18584+ /* reference to the copied-up whiteout with get/put */
18585+ struct dentry *hi_whdentry;
18586+};
dece6358 18587+
537831f9
AM
18588+/* ig_flags */
18589+#define AuIG_HALF_REFRESHED 1
18590+#define au_ig_ftest(flags, name) ((flags) & AuIG_##name)
18591+#define au_ig_fset(flags, name) \
18592+ do { (flags) |= AuIG_##name; } while (0)
18593+#define au_ig_fclr(flags, name) \
18594+ do { (flags) &= ~AuIG_##name; } while (0)
18595+
18596+struct au_iigen {
be52b249 18597+ spinlock_t ig_spin;
537831f9
AM
18598+ __u32 ig_generation, ig_flags;
18599+};
18600+
4a4d8108
AM
18601+struct au_vdir;
18602+struct au_iinfo {
7a9e40b8 18603+ struct au_iigen ii_generation;
4a4d8108 18604+ struct super_block *ii_hsb1; /* no get/put */
1facf9fc 18605+
4a4d8108 18606+ struct au_rwsem ii_rwsem;
5afbbe0d 18607+ aufs_bindex_t ii_btop, ii_bbot;
4a4d8108
AM
18608+ __u32 ii_higen;
18609+ struct au_hinode *ii_hinode;
18610+ struct au_vdir *ii_vdir;
18611+};
1facf9fc 18612+
4a4d8108 18613+struct au_icntnr {
9f237c51
AM
18614+ struct au_iinfo iinfo;
18615+ struct inode vfs_inode;
18616+ struct hlist_bl_node plink;
18617+ struct rcu_head rcu;
4a4d8108 18618+} ____cacheline_aligned_in_smp;
1308ab2a 18619+
4a4d8108
AM
18620+/* au_pin flags */
18621+#define AuPin_DI_LOCKED 1
18622+#define AuPin_MNT_WRITE (1 << 1)
18623+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
7f207e10
AM
18624+#define au_fset_pin(flags, name) \
18625+ do { (flags) |= AuPin_##name; } while (0)
18626+#define au_fclr_pin(flags, name) \
18627+ do { (flags) &= ~AuPin_##name; } while (0)
4a4d8108
AM
18628+
18629+struct au_pin {
18630+ /* input */
18631+ struct dentry *dentry;
18632+ unsigned int udba;
18633+ unsigned char lsc_di, lsc_hi, flags;
18634+ aufs_bindex_t bindex;
18635+
18636+ /* output */
18637+ struct dentry *parent;
18638+ struct au_hinode *hdir;
18639+ struct vfsmount *h_mnt;
86dc4139
AM
18640+
18641+ /* temporary unlock/relock for copyup */
18642+ struct dentry *h_dentry, *h_parent;
18643+ struct au_branch *br;
18644+ struct task_struct *task;
4a4d8108 18645+};
1facf9fc 18646+
86dc4139 18647+void au_pin_hdir_unlock(struct au_pin *p);
c1595e42 18648+int au_pin_hdir_lock(struct au_pin *p);
86dc4139 18649+int au_pin_hdir_relock(struct au_pin *p);
86dc4139
AM
18650+void au_pin_hdir_acquire_nest(struct au_pin *p);
18651+void au_pin_hdir_release(struct au_pin *p);
18652+
1308ab2a 18653+/* ---------------------------------------------------------------------- */
18654+
4a4d8108 18655+static inline struct au_iinfo *au_ii(struct inode *inode)
1facf9fc 18656+{
5afbbe0d
AM
18657+ BUG_ON(is_bad_inode(inode));
18658+ return &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
4a4d8108 18659+}
1facf9fc 18660+
4a4d8108 18661+/* ---------------------------------------------------------------------- */
1facf9fc 18662+
4a4d8108
AM
18663+/* inode.c */
18664+struct inode *au_igrab(struct inode *inode);
b95c5147 18665+void au_refresh_iop(struct inode *inode, int force_getattr);
027c5e7a 18666+int au_refresh_hinode_self(struct inode *inode);
4a4d8108
AM
18667+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
18668+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
18669+ unsigned int d_type, ino_t *ino);
18670+struct inode *au_new_inode(struct dentry *dentry, int must_new);
18671+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
18672+ struct inode *inode);
0b2a12c6
JR
18673+int au_test_h_perm(struct user_namespace *h_userns, struct inode *h_inode,
18674+ int mask);
18675+int au_test_h_perm_sio(struct user_namespace *h_userns, struct inode *h_inode,
18676+ int mask);
1facf9fc 18677+
4a4d8108
AM
18678+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
18679+ ino_t h_ino, unsigned int d_type, ino_t *ino)
18680+{
18681+#ifdef CONFIG_AUFS_SHWH
18682+ return au_ino(sb, bindex, h_ino, d_type, ino);
18683+#else
18684+ return 0;
18685+#endif
18686+}
1facf9fc 18687+
4a4d8108 18688+/* i_op.c */
b95c5147
AM
18689+enum {
18690+ AuIop_SYMLINK,
18691+ AuIop_DIR,
18692+ AuIop_OTHER,
18693+ AuIop_Last
18694+};
43982f53 18695+extern struct inode_operations aufs_iop[AuIop_Last], /* not const */
b95c5147 18696+ aufs_iop_nogetattr[AuIop_Last];
1308ab2a 18697+
4a4d8108
AM
18698+/* au_wr_dir flags */
18699+#define AuWrDir_ADD_ENTRY 1
7e9cd9fe
AM
18700+#define AuWrDir_ISDIR (1 << 1)
18701+#define AuWrDir_TMPFILE (1 << 2)
4a4d8108 18702+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
7f207e10
AM
18703+#define au_fset_wrdir(flags, name) \
18704+ do { (flags) |= AuWrDir_##name; } while (0)
18705+#define au_fclr_wrdir(flags, name) \
18706+ do { (flags) &= ~AuWrDir_##name; } while (0)
1facf9fc 18707+
4a4d8108
AM
18708+struct au_wr_dir_args {
18709+ aufs_bindex_t force_btgt;
18710+ unsigned char flags;
18711+};
18712+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
18713+ struct au_wr_dir_args *args);
dece6358 18714+
4a4d8108
AM
18715+struct dentry *au_pinned_h_parent(struct au_pin *pin);
18716+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
18717+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
18718+ unsigned int udba, unsigned char flags);
18719+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
18720+ unsigned int udba, unsigned char flags) __must_check;
18721+int au_do_pin(struct au_pin *pin) __must_check;
18722+void au_unpin(struct au_pin *pin);
c1595e42
JR
18723+int au_reval_for_attr(struct dentry *dentry, unsigned int sigen);
18724+
18725+#define AuIcpup_DID_CPUP 1
18726+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
18727+#define au_fset_icpup(flags, name) \
18728+ do { (flags) |= AuIcpup_##name; } while (0)
18729+#define au_fclr_icpup(flags, name) \
18730+ do { (flags) &= ~AuIcpup_##name; } while (0)
18731+
18732+struct au_icpup_args {
18733+ unsigned char flags;
18734+ unsigned char pin_flags;
18735+ aufs_bindex_t btgt;
18736+ unsigned int udba;
18737+ struct au_pin pin;
18738+ struct path h_path;
18739+ struct inode *h_inode;
18740+};
18741+
18742+int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
18743+ struct au_icpup_args *a);
18744+
42b5c33a
AM
18745+int au_h_path_getattr(struct dentry *dentry, struct inode *inode, int force,
18746+ struct path *h_path, int locked);
1facf9fc 18747+
4a4d8108
AM
18748+/* i_op_add.c */
18749+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
18750+ struct dentry *h_parent, int isdir);
0b2a12c6
JR
18751+int aufs_mknod(struct user_namespace *userns, struct inode *dir,
18752+ struct dentry *dentry, umode_t mode, dev_t dev);
18753+int aufs_symlink(struct user_namespace *userns, struct inode *dir,
18754+ struct dentry *dentry, const char *symname);
18755+int aufs_create(struct user_namespace *userns, struct inode *dir,
18756+ struct dentry *dentry, umode_t mode, bool want_excl);
b912730e
AM
18757+struct vfsub_aopen_args;
18758+int au_aopen_or_create(struct inode *dir, struct dentry *dentry,
18759+ struct vfsub_aopen_args *args);
0b2a12c6
JR
18760+int aufs_tmpfile(struct user_namespace *userns, struct inode *dir,
18761+ struct dentry *dentry, umode_t mode);
4a4d8108
AM
18762+int aufs_link(struct dentry *src_dentry, struct inode *dir,
18763+ struct dentry *dentry);
0b2a12c6
JR
18764+int aufs_mkdir(struct user_namespace *userns, struct inode *dir,
18765+ struct dentry *dentry, umode_t mode);
1facf9fc 18766+
4a4d8108
AM
18767+/* i_op_del.c */
18768+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
18769+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
18770+ struct dentry *h_parent, int isdir);
18771+int aufs_unlink(struct inode *dir, struct dentry *dentry);
18772+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1308ab2a 18773+
4a4d8108
AM
18774+/* i_op_ren.c */
18775+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
0b2a12c6
JR
18776+int aufs_rename(struct user_namespace *userns,
18777+ struct inode *_src_dir, struct dentry *_src_dentry,
18778+ struct inode *_dst_dir, struct dentry *_dst_dentry,
18779+ unsigned int _flags);
1facf9fc 18780+
4a4d8108
AM
18781+/* iinfo.c */
18782+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
18783+void au_hiput(struct au_hinode *hinode);
18784+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
18785+ struct dentry *h_wh);
18786+unsigned int au_hi_flags(struct inode *inode, int isdir);
1308ab2a 18787+
4a4d8108
AM
18788+/* hinode flags */
18789+#define AuHi_XINO 1
18790+#define AuHi_HNOTIFY (1 << 1)
18791+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
7f207e10
AM
18792+#define au_fset_hi(flags, name) \
18793+ do { (flags) |= AuHi_##name; } while (0)
18794+#define au_fclr_hi(flags, name) \
18795+ do { (flags) &= ~AuHi_##name; } while (0)
1facf9fc 18796+
4a4d8108
AM
18797+#ifndef CONFIG_AUFS_HNOTIFY
18798+#undef AuHi_HNOTIFY
18799+#define AuHi_HNOTIFY 0
18800+#endif
1facf9fc 18801+
4a4d8108
AM
18802+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
18803+ struct inode *h_inode, unsigned int flags);
1facf9fc 18804+
537831f9 18805+void au_update_iigen(struct inode *inode, int half);
4a4d8108 18806+void au_update_ibrange(struct inode *inode, int do_put_zero);
1facf9fc 18807+
4a4d8108 18808+void au_icntnr_init_once(void *_c);
5afbbe0d 18809+void au_hinode_init(struct au_hinode *hinode);
4a4d8108
AM
18810+int au_iinfo_init(struct inode *inode);
18811+void au_iinfo_fin(struct inode *inode);
e2f27e51 18812+int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink);
1308ab2a 18813+
e49829fe 18814+#ifdef CONFIG_PROC_FS
4a4d8108 18815+/* plink.c */
e49829fe 18816+int au_plink_maint(struct super_block *sb, int flags);
7e9cd9fe 18817+struct au_sbinfo;
e49829fe
JR
18818+void au_plink_maint_leave(struct au_sbinfo *sbinfo);
18819+int au_plink_maint_enter(struct super_block *sb);
4a4d8108
AM
18820+#ifdef CONFIG_AUFS_DEBUG
18821+void au_plink_list(struct super_block *sb);
18822+#else
18823+AuStubVoid(au_plink_list, struct super_block *sb)
18824+#endif
18825+int au_plink_test(struct inode *inode);
18826+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
18827+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
18828+ struct dentry *h_dentry);
e49829fe
JR
18829+void au_plink_put(struct super_block *sb, int verbose);
18830+void au_plink_clean(struct super_block *sb, int verbose);
4a4d8108 18831+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
e49829fe
JR
18832+#else
18833+AuStubInt0(au_plink_maint, struct super_block *sb, int flags);
18834+AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo);
18835+AuStubInt0(au_plink_maint_enter, struct super_block *sb);
18836+AuStubVoid(au_plink_list, struct super_block *sb);
18837+AuStubInt0(au_plink_test, struct inode *inode);
18838+AuStub(struct dentry *, au_plink_lkup, return NULL,
18839+ struct inode *inode, aufs_bindex_t bindex);
18840+AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex,
18841+ struct dentry *h_dentry);
18842+AuStubVoid(au_plink_put, struct super_block *sb, int verbose);
18843+AuStubVoid(au_plink_clean, struct super_block *sb, int verbose);
18844+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id);
18845+#endif /* CONFIG_PROC_FS */
1facf9fc 18846+
c1595e42
JR
18847+#ifdef CONFIG_AUFS_XATTR
18848+/* xattr.c */
0b2a12c6 18849+int au_cpup_xattr(struct path *h_dst, struct path *h_src, int ignore_flags,
7e9cd9fe 18850+ unsigned int verbose);
c1595e42 18851+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size);
f2c43d5f 18852+void au_xattr_init(struct super_block *sb);
c1595e42 18853+#else
0b2a12c6 18854+AuStubInt0(au_cpup_xattr, struct path *h_dst, struct path *h_src,
7e9cd9fe 18855+ int ignore_flags, unsigned int verbose);
f2c43d5f 18856+AuStubVoid(au_xattr_init, struct super_block *sb);
c1595e42
JR
18857+#endif
18858+
18859+#ifdef CONFIG_FS_POSIX_ACL
758e9dad 18860+struct posix_acl *aufs_get_acl(struct inode *inode, int type, bool rcu);
0b2a12c6
JR
18861+int aufs_set_acl(struct user_namespace *userns, struct inode *inode,
18862+ struct posix_acl *acl, int type);
c1595e42
JR
18863+#endif
18864+
18865+#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL)
18866+enum {
18867+ AU_XATTR_SET,
c1595e42
JR
18868+ AU_ACL_SET
18869+};
18870+
f2c43d5f 18871+struct au_sxattr {
c1595e42
JR
18872+ int type;
18873+ union {
18874+ struct {
18875+ const char *name;
18876+ const void *value;
18877+ size_t size;
18878+ int flags;
18879+ } set;
18880+ struct {
c1595e42
JR
18881+ struct posix_acl *acl;
18882+ int type;
18883+ } acl_set;
18884+ } u;
18885+};
f2c43d5f
AM
18886+ssize_t au_sxattr(struct dentry *dentry, struct inode *inode,
18887+ struct au_sxattr *arg);
c1595e42
JR
18888+#endif
18889+
4a4d8108 18890+/* ---------------------------------------------------------------------- */
1308ab2a 18891+
4a4d8108
AM
18892+/* lock subclass for iinfo */
18893+enum {
18894+ AuLsc_II_CHILD, /* child first */
18895+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */
18896+ AuLsc_II_CHILD3, /* copyup dirs */
18897+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
18898+ AuLsc_II_PARENT2,
18899+ AuLsc_II_PARENT3, /* copyup dirs */
18900+ AuLsc_II_NEW_CHILD
18901+};
1308ab2a 18902+
1facf9fc 18903+/*
4a4d8108
AM
18904+ * ii_read_lock_child, ii_write_lock_child,
18905+ * ii_read_lock_child2, ii_write_lock_child2,
18906+ * ii_read_lock_child3, ii_write_lock_child3,
18907+ * ii_read_lock_parent, ii_write_lock_parent,
18908+ * ii_read_lock_parent2, ii_write_lock_parent2,
18909+ * ii_read_lock_parent3, ii_write_lock_parent3,
18910+ * ii_read_lock_new_child, ii_write_lock_new_child,
1facf9fc 18911+ */
4a4d8108
AM
18912+#define AuReadLockFunc(name, lsc) \
18913+static inline void ii_read_lock_##name(struct inode *i) \
18914+{ \
18915+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
18916+}
18917+
18918+#define AuWriteLockFunc(name, lsc) \
18919+static inline void ii_write_lock_##name(struct inode *i) \
18920+{ \
18921+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
18922+}
18923+
18924+#define AuRWLockFuncs(name, lsc) \
18925+ AuReadLockFunc(name, lsc) \
18926+ AuWriteLockFunc(name, lsc)
18927+
18928+AuRWLockFuncs(child, CHILD);
18929+AuRWLockFuncs(child2, CHILD2);
18930+AuRWLockFuncs(child3, CHILD3);
18931+AuRWLockFuncs(parent, PARENT);
18932+AuRWLockFuncs(parent2, PARENT2);
18933+AuRWLockFuncs(parent3, PARENT3);
18934+AuRWLockFuncs(new_child, NEW_CHILD);
18935+
18936+#undef AuReadLockFunc
18937+#undef AuWriteLockFunc
18938+#undef AuRWLockFuncs
1facf9fc 18939+
8b6a4947
AM
18940+#define ii_read_unlock(i) au_rw_read_unlock(&au_ii(i)->ii_rwsem)
18941+#define ii_write_unlock(i) au_rw_write_unlock(&au_ii(i)->ii_rwsem)
18942+#define ii_downgrade_lock(i) au_rw_dgrade_lock(&au_ii(i)->ii_rwsem)
1facf9fc 18943+
4a4d8108
AM
18944+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
18945+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
18946+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
1facf9fc 18947+
4a4d8108 18948+/* ---------------------------------------------------------------------- */
1308ab2a 18949+
027c5e7a
AM
18950+static inline void au_icntnr_init(struct au_icntnr *c)
18951+{
18952+#ifdef CONFIG_AUFS_DEBUG
18953+ c->vfs_inode.i_mode = 0;
18954+#endif
18955+}
18956+
cfc41e69 18957+static inline unsigned int au_iigen(struct inode *inode, unsigned int *igflags)
4a4d8108 18958+{
537831f9
AM
18959+ unsigned int gen;
18960+ struct au_iinfo *iinfo;
be52b249 18961+ struct au_iigen *iigen;
537831f9
AM
18962+
18963+ iinfo = au_ii(inode);
be52b249
AM
18964+ iigen = &iinfo->ii_generation;
18965+ spin_lock(&iigen->ig_spin);
cfc41e69
AM
18966+ if (igflags)
18967+ *igflags = iigen->ig_flags;
be52b249
AM
18968+ gen = iigen->ig_generation;
18969+ spin_unlock(&iigen->ig_spin);
537831f9
AM
18970+
18971+ return gen;
4a4d8108 18972+}
1308ab2a 18973+
4a4d8108
AM
18974+/* tiny test for inode number */
18975+/* tmpfs generation is too rough */
18976+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
18977+{
18978+ struct au_iinfo *iinfo;
1308ab2a 18979+
4a4d8108
AM
18980+ iinfo = au_ii(inode);
18981+ AuRwMustAnyLock(&iinfo->ii_rwsem);
18982+ return !(iinfo->ii_hsb1 == h_inode->i_sb
18983+ && iinfo->ii_higen == h_inode->i_generation);
18984+}
1308ab2a 18985+
4a4d8108
AM
18986+static inline void au_iigen_dec(struct inode *inode)
18987+{
537831f9 18988+ struct au_iinfo *iinfo;
be52b249 18989+ struct au_iigen *iigen;
537831f9
AM
18990+
18991+ iinfo = au_ii(inode);
be52b249
AM
18992+ iigen = &iinfo->ii_generation;
18993+ spin_lock(&iigen->ig_spin);
18994+ iigen->ig_generation--;
18995+ spin_unlock(&iigen->ig_spin);
027c5e7a
AM
18996+}
18997+
18998+static inline int au_iigen_test(struct inode *inode, unsigned int sigen)
18999+{
19000+ int err;
19001+
19002+ err = 0;
537831f9 19003+ if (unlikely(inode && au_iigen(inode, NULL) != sigen))
027c5e7a
AM
19004+ err = -EIO;
19005+
19006+ return err;
4a4d8108 19007+}
1308ab2a 19008+
4a4d8108 19009+/* ---------------------------------------------------------------------- */
1308ab2a 19010+
5afbbe0d
AM
19011+static inline struct au_hinode *au_hinode(struct au_iinfo *iinfo,
19012+ aufs_bindex_t bindex)
19013+{
19014+ return iinfo->ii_hinode + bindex;
19015+}
19016+
19017+static inline int au_is_bad_inode(struct inode *inode)
19018+{
19019+ return !!(is_bad_inode(inode) || !au_hinode(au_ii(inode), 0));
19020+}
19021+
4a4d8108
AM
19022+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
19023+ aufs_bindex_t bindex)
19024+{
19025+ IiMustAnyLock(inode);
5afbbe0d 19026+ return au_hinode(au_ii(inode), bindex)->hi_id;
4a4d8108 19027+}
1308ab2a 19028+
5afbbe0d 19029+static inline aufs_bindex_t au_ibtop(struct inode *inode)
4a4d8108
AM
19030+{
19031+ IiMustAnyLock(inode);
5afbbe0d 19032+ return au_ii(inode)->ii_btop;
4a4d8108 19033+}
1308ab2a 19034+
5afbbe0d 19035+static inline aufs_bindex_t au_ibbot(struct inode *inode)
4a4d8108
AM
19036+{
19037+ IiMustAnyLock(inode);
5afbbe0d 19038+ return au_ii(inode)->ii_bbot;
4a4d8108 19039+}
1308ab2a 19040+
4a4d8108
AM
19041+static inline struct au_vdir *au_ivdir(struct inode *inode)
19042+{
19043+ IiMustAnyLock(inode);
19044+ return au_ii(inode)->ii_vdir;
19045+}
1308ab2a 19046+
4a4d8108
AM
19047+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
19048+{
19049+ IiMustAnyLock(inode);
5afbbe0d 19050+ return au_hinode(au_ii(inode), bindex)->hi_whdentry;
4a4d8108 19051+}
1308ab2a 19052+
5afbbe0d 19053+static inline void au_set_ibtop(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 19054+{
4a4d8108 19055+ IiMustWriteLock(inode);
5afbbe0d 19056+ au_ii(inode)->ii_btop = bindex;
4a4d8108 19057+}
1308ab2a 19058+
5afbbe0d 19059+static inline void au_set_ibbot(struct inode *inode, aufs_bindex_t bindex)
4a4d8108
AM
19060+{
19061+ IiMustWriteLock(inode);
5afbbe0d 19062+ au_ii(inode)->ii_bbot = bindex;
1308ab2a 19063+}
19064+
4a4d8108
AM
19065+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
19066+{
19067+ IiMustWriteLock(inode);
19068+ au_ii(inode)->ii_vdir = vdir;
19069+}
1facf9fc 19070+
4a4d8108 19071+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 19072+{
4a4d8108 19073+ IiMustAnyLock(inode);
5afbbe0d 19074+ return au_hinode(au_ii(inode), bindex);
4a4d8108 19075+}
dece6358 19076+
4a4d8108 19077+/* ---------------------------------------------------------------------- */
1facf9fc 19078+
4a4d8108
AM
19079+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
19080+{
19081+ if (pin)
19082+ return pin->parent;
19083+ return NULL;
1facf9fc 19084+}
19085+
4a4d8108 19086+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
1facf9fc 19087+{
4a4d8108
AM
19088+ if (pin && pin->hdir)
19089+ return pin->hdir->hi_inode;
19090+ return NULL;
1308ab2a 19091+}
1facf9fc 19092+
4a4d8108
AM
19093+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
19094+{
19095+ if (pin)
19096+ return pin->hdir;
19097+ return NULL;
19098+}
1facf9fc 19099+
4a4d8108 19100+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
1308ab2a 19101+{
4a4d8108
AM
19102+ if (pin)
19103+ pin->dentry = dentry;
19104+}
1308ab2a 19105+
4a4d8108
AM
19106+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
19107+ unsigned char lflag)
19108+{
19109+ if (pin) {
7f207e10 19110+ if (lflag)
4a4d8108 19111+ au_fset_pin(pin->flags, DI_LOCKED);
7f207e10 19112+ else
4a4d8108 19113+ au_fclr_pin(pin->flags, DI_LOCKED);
1308ab2a 19114+ }
4a4d8108
AM
19115+}
19116+
7e9cd9fe 19117+#if 0 /* reserved */
4a4d8108
AM
19118+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
19119+{
19120+ if (pin) {
19121+ dput(pin->parent);
19122+ pin->parent = dget(parent);
1facf9fc 19123+ }
4a4d8108 19124+}
7e9cd9fe 19125+#endif
1facf9fc 19126+
4a4d8108
AM
19127+/* ---------------------------------------------------------------------- */
19128+
027c5e7a 19129+struct au_branch;
4a4d8108
AM
19130+#ifdef CONFIG_AUFS_HNOTIFY
19131+struct au_hnotify_op {
19132+ void (*ctl)(struct au_hinode *hinode, int do_set);
027c5e7a 19133+ int (*alloc)(struct au_hinode *hinode);
7eafdf33
AM
19134+
19135+ /*
42a736d3 19136+ * if it returns true, the caller should free hinode->hi_notify,
7eafdf33
AM
19137+ * otherwise ->free() frees it.
19138+ */
19139+ int (*free)(struct au_hinode *hinode,
19140+ struct au_hnotify *hn) __must_check;
4a4d8108
AM
19141+
19142+ void (*fin)(void);
19143+ int (*init)(void);
027c5e7a
AM
19144+
19145+ int (*reset_br)(unsigned int udba, struct au_branch *br, int perm);
19146+ void (*fin_br)(struct au_branch *br);
19147+ int (*init_br)(struct au_branch *br, int perm);
4a4d8108
AM
19148+};
19149+
19150+/* hnotify.c */
027c5e7a 19151+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode);
4a4d8108
AM
19152+void au_hn_free(struct au_hinode *hinode);
19153+void au_hn_ctl(struct au_hinode *hinode, int do_set);
19154+void au_hn_reset(struct inode *inode, unsigned int flags);
19155+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
fbc438ed 19156+ const struct qstr *h_child_qstr, struct inode *h_child_inode);
027c5e7a
AM
19157+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm);
19158+int au_hnotify_init_br(struct au_branch *br, int perm);
19159+void au_hnotify_fin_br(struct au_branch *br);
4a4d8108
AM
19160+int __init au_hnotify_init(void);
19161+void au_hnotify_fin(void);
19162+
7f207e10 19163+/* hfsnotify.c */
4a4d8108
AM
19164+extern const struct au_hnotify_op au_hnotify_op;
19165+
19166+static inline
19167+void au_hn_init(struct au_hinode *hinode)
19168+{
19169+ hinode->hi_notify = NULL;
1308ab2a 19170+}
19171+
53392da6
AM
19172+static inline struct au_hnotify *au_hn(struct au_hinode *hinode)
19173+{
19174+ return hinode->hi_notify;
19175+}
19176+
4a4d8108 19177+#else
c1595e42
JR
19178+AuStub(int, au_hn_alloc, return -EOPNOTSUPP,
19179+ struct au_hinode *hinode __maybe_unused,
19180+ struct inode *inode __maybe_unused)
19181+AuStub(struct au_hnotify *, au_hn, return NULL, struct au_hinode *hinode)
4a4d8108
AM
19182+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
19183+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
19184+ int do_set __maybe_unused)
19185+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
19186+ unsigned int flags __maybe_unused)
027c5e7a
AM
19187+AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused,
19188+ struct au_branch *br __maybe_unused,
19189+ int perm __maybe_unused)
19190+AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused,
19191+ int perm __maybe_unused)
19192+AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused)
4a4d8108
AM
19193+AuStubInt0(__init au_hnotify_init, void)
19194+AuStubVoid(au_hnotify_fin, void)
19195+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
19196+#endif /* CONFIG_AUFS_HNOTIFY */
19197+
19198+static inline void au_hn_suspend(struct au_hinode *hdir)
19199+{
19200+ au_hn_ctl(hdir, /*do_set*/0);
1308ab2a 19201+}
19202+
4a4d8108 19203+static inline void au_hn_resume(struct au_hinode *hdir)
1308ab2a 19204+{
4a4d8108
AM
19205+ au_hn_ctl(hdir, /*do_set*/1);
19206+}
1308ab2a 19207+
5afbbe0d 19208+static inline void au_hn_inode_lock(struct au_hinode *hdir)
4a4d8108 19209+{
febd17d6 19210+ inode_lock(hdir->hi_inode);
4a4d8108
AM
19211+ au_hn_suspend(hdir);
19212+}
dece6358 19213+
5afbbe0d 19214+static inline void au_hn_inode_lock_nested(struct au_hinode *hdir,
4a4d8108
AM
19215+ unsigned int sc __maybe_unused)
19216+{
febd17d6 19217+ inode_lock_nested(hdir->hi_inode, sc);
4a4d8108 19218+ au_hn_suspend(hdir);
1facf9fc 19219+}
1facf9fc 19220+
8b6a4947
AM
19221+#if 0 /* unused */
19222+#include "vfsub.h"
3c1bdaff
AM
19223+static inline void au_hn_inode_lock_shared_nested(struct au_hinode *hdir,
19224+ unsigned int sc)
19225+{
be118d29 19226+ inode_lock_shared_nested(hdir->hi_inode, sc);
3c1bdaff
AM
19227+ au_hn_suspend(hdir);
19228+}
8b6a4947 19229+#endif
3c1bdaff 19230+
5afbbe0d 19231+static inline void au_hn_inode_unlock(struct au_hinode *hdir)
4a4d8108
AM
19232+{
19233+ au_hn_resume(hdir);
febd17d6 19234+ inode_unlock(hdir->hi_inode);
4a4d8108
AM
19235+}
19236+
19237+#endif /* __KERNEL__ */
19238+#endif /* __AUFS_INODE_H__ */
7f207e10 19239diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
eca34b5c 19240--- /usr/share/empty/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
319657f6 19241+++ linux/fs/aufs/ioctl.c 2021-12-03 15:38:59.936647310 +0100
062440b3 19242@@ -0,0 +1,220 @@
cd7a4cd9 19243+// SPDX-License-Identifier: GPL-2.0
4a4d8108 19244+/*
6d176551 19245+ * Copyright (C) 2005-2021 Junjiro R. Okajima
4a4d8108
AM
19246+ *
19247+ * This program, aufs is free software; you can redistribute it and/or modify
19248+ * it under the terms of the GNU General Public License as published by
19249+ * the Free Software Foundation; either version 2 of the License, or
19250+ * (at your option) any later version.
19251+ *
19252+ * This program is distributed in the hope that it will be useful,
19253+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19254+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19255+ * GNU General Public License for more details.
19256+ *
19257+ * You should have received a copy of the GNU General Public License
523b37e3 19258+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
19259+ */
19260+
19261+/*
19262+ * ioctl
19263+ * plink-management and readdir in userspace.
19264+ * assist the pathconf(3) wrapper library.
c2b27bf2 19265+ * move-down
076b876e 19266+ * File-based Hierarchical Storage Management.
4a4d8108
AM
19267+ */
19268+
c2b27bf2
AM
19269+#include <linux/compat.h>
19270+#include <linux/file.h>
4a4d8108
AM
19271+#include "aufs.h"
19272+
1e00d052 19273+static int au_wbr_fd(struct path *path, struct aufs_wbr_fd __user *arg)
4a4d8108
AM
19274+{
19275+ int err, fd;
5afbbe0d 19276+ aufs_bindex_t wbi, bindex, bbot;
4a4d8108
AM
19277+ struct file *h_file;
19278+ struct super_block *sb;
19279+ struct dentry *root;
1e00d052
AM
19280+ struct au_branch *br;
19281+ struct aufs_wbr_fd wbrfd = {
19282+ .oflags = au_dir_roflags,
19283+ .brid = -1
19284+ };
19285+ const int valid = O_RDONLY | O_NONBLOCK | O_LARGEFILE | O_DIRECTORY
19286+ | O_NOATIME | O_CLOEXEC;
4a4d8108 19287+
1e00d052
AM
19288+ AuDebugOn(wbrfd.oflags & ~valid);
19289+
19290+ if (arg) {
19291+ err = copy_from_user(&wbrfd, arg, sizeof(wbrfd));
19292+ if (unlikely(err)) {
19293+ err = -EFAULT;
19294+ goto out;
19295+ }
19296+
19297+ err = -EINVAL;
19298+ AuDbg("wbrfd{0%o, %d}\n", wbrfd.oflags, wbrfd.brid);
19299+ wbrfd.oflags |= au_dir_roflags;
19300+ AuDbg("0%o\n", wbrfd.oflags);
19301+ if (unlikely(wbrfd.oflags & ~valid))
19302+ goto out;
19303+ }
19304+
2000de60 19305+ fd = get_unused_fd_flags(0);
1e00d052
AM
19306+ err = fd;
19307+ if (unlikely(fd < 0))
4a4d8108 19308+ goto out;
4a4d8108 19309+
1e00d052 19310+ h_file = ERR_PTR(-EINVAL);
4a4d8108 19311+ wbi = 0;
1e00d052 19312+ br = NULL;
4a4d8108
AM
19313+ sb = path->dentry->d_sb;
19314+ root = sb->s_root;
19315+ aufs_read_lock(root, AuLock_IR);
5afbbe0d 19316+ bbot = au_sbbot(sb);
1e00d052
AM
19317+ if (wbrfd.brid >= 0) {
19318+ wbi = au_br_index(sb, wbrfd.brid);
5afbbe0d 19319+ if (unlikely(wbi < 0 || wbi > bbot))
1e00d052
AM
19320+ goto out_unlock;
19321+ }
19322+
19323+ h_file = ERR_PTR(-ENOENT);
19324+ br = au_sbr(sb, wbi);
19325+ if (!au_br_writable(br->br_perm)) {
19326+ if (arg)
19327+ goto out_unlock;
19328+
19329+ bindex = wbi + 1;
19330+ wbi = -1;
5afbbe0d 19331+ for (; bindex <= bbot; bindex++) {
1e00d052
AM
19332+ br = au_sbr(sb, bindex);
19333+ if (au_br_writable(br->br_perm)) {
4a4d8108 19334+ wbi = bindex;
1e00d052 19335+ br = au_sbr(sb, wbi);
4a4d8108
AM
19336+ break;
19337+ }
19338+ }
4a4d8108
AM
19339+ }
19340+ AuDbg("wbi %d\n", wbi);
1e00d052 19341+ if (wbi >= 0)
392086de
AM
19342+ h_file = au_h_open(root, wbi, wbrfd.oflags, NULL,
19343+ /*force_wr*/0);
1e00d052
AM
19344+
19345+out_unlock:
4a4d8108
AM
19346+ aufs_read_unlock(root, AuLock_IR);
19347+ err = PTR_ERR(h_file);
19348+ if (IS_ERR(h_file))
19349+ goto out_fd;
19350+
acd2b654 19351+ au_lcnt_dec(&br->br_nfiles); /* cf. au_h_open() */
4a4d8108
AM
19352+ fd_install(fd, h_file);
19353+ err = fd;
19354+ goto out; /* success */
19355+
4f0767ce 19356+out_fd:
4a4d8108 19357+ put_unused_fd(fd);
4f0767ce 19358+out:
1e00d052 19359+ AuTraceErr(err);
4a4d8108
AM
19360+ return err;
19361+}
19362+
19363+/* ---------------------------------------------------------------------- */
19364+
19365+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
19366+{
19367+ long err;
c1595e42 19368+ struct dentry *dentry;
4a4d8108
AM
19369+
19370+ switch (cmd) {
4a4d8108
AM
19371+ case AUFS_CTL_RDU:
19372+ case AUFS_CTL_RDU_INO:
19373+ err = au_rdu_ioctl(file, cmd, arg);
19374+ break;
19375+
19376+ case AUFS_CTL_WBR_FD:
1e00d052 19377+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
4a4d8108
AM
19378+ break;
19379+
027c5e7a
AM
19380+ case AUFS_CTL_IBUSY:
19381+ err = au_ibusy_ioctl(file, arg);
19382+ break;
19383+
076b876e
AM
19384+ case AUFS_CTL_BRINFO:
19385+ err = au_brinfo_ioctl(file, arg);
19386+ break;
19387+
19388+ case AUFS_CTL_FHSM_FD:
2000de60 19389+ dentry = file->f_path.dentry;
c1595e42
JR
19390+ if (IS_ROOT(dentry))
19391+ err = au_fhsm_fd(dentry->d_sb, arg);
19392+ else
19393+ err = -ENOTTY;
076b876e
AM
19394+ break;
19395+
4a4d8108
AM
19396+ default:
19397+ /* do not call the lower */
19398+ AuDbg("0x%x\n", cmd);
19399+ err = -ENOTTY;
19400+ }
19401+
19402+ AuTraceErr(err);
19403+ return err;
19404+}
19405+
19406+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
19407+{
19408+ long err;
19409+
19410+ switch (cmd) {
c2b27bf2 19411+ case AUFS_CTL_MVDOWN:
2000de60 19412+ err = au_mvdown(file->f_path.dentry, (void __user *)arg);
c2b27bf2
AM
19413+ break;
19414+
4a4d8108 19415+ case AUFS_CTL_WBR_FD:
1e00d052 19416+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
4a4d8108
AM
19417+ break;
19418+
19419+ default:
19420+ /* do not call the lower */
19421+ AuDbg("0x%x\n", cmd);
19422+ err = -ENOTTY;
19423+ }
19424+
19425+ AuTraceErr(err);
19426+ return err;
19427+}
b752ccd1
AM
19428+
19429+#ifdef CONFIG_COMPAT
19430+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
19431+ unsigned long arg)
19432+{
19433+ long err;
19434+
19435+ switch (cmd) {
19436+ case AUFS_CTL_RDU:
19437+ case AUFS_CTL_RDU_INO:
19438+ err = au_rdu_compat_ioctl(file, cmd, arg);
19439+ break;
19440+
027c5e7a
AM
19441+ case AUFS_CTL_IBUSY:
19442+ err = au_ibusy_compat_ioctl(file, arg);
19443+ break;
19444+
076b876e
AM
19445+ case AUFS_CTL_BRINFO:
19446+ err = au_brinfo_compat_ioctl(file, arg);
19447+ break;
19448+
b752ccd1
AM
19449+ default:
19450+ err = aufs_ioctl_dir(file, cmd, arg);
19451+ }
19452+
19453+ AuTraceErr(err);
19454+ return err;
19455+}
19456+
b752ccd1
AM
19457+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
19458+ unsigned long arg)
19459+{
19460+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
19461+}
19462+#endif
7f207e10 19463diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
eca34b5c 19464--- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
319657f6 19465+++ linux/fs/aufs/i_op_add.c 2021-12-03 15:40:58.236647297 +0100
0b2a12c6 19466@@ -0,0 +1,941 @@
cd7a4cd9 19467+// SPDX-License-Identifier: GPL-2.0
4a4d8108 19468+/*
6d176551 19469+ * Copyright (C) 2005-2021 Junjiro R. Okajima
4a4d8108
AM
19470+ *
19471+ * This program, aufs is free software; you can redistribute it and/or modify
19472+ * it under the terms of the GNU General Public License as published by
19473+ * the Free Software Foundation; either version 2 of the License, or
19474+ * (at your option) any later version.
19475+ *
19476+ * This program is distributed in the hope that it will be useful,
19477+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19478+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19479+ * GNU General Public License for more details.
19480+ *
19481+ * You should have received a copy of the GNU General Public License
523b37e3 19482+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
19483+ */
19484+
19485+/*
19486+ * inode operations (add entry)
19487+ */
19488+
eca801bf 19489+#include <linux/iversion.h>
4a4d8108
AM
19490+#include "aufs.h"
19491+
19492+/*
19493+ * final procedure of adding a new entry, except link(2).
19494+ * remove whiteout, instantiate, copyup the parent dir's times and size
19495+ * and update version.
19496+ * if it failed, re-create the removed whiteout.
19497+ */
19498+static int epilog(struct inode *dir, aufs_bindex_t bindex,
19499+ struct dentry *wh_dentry, struct dentry *dentry)
19500+{
19501+ int err, rerr;
19502+ aufs_bindex_t bwh;
19503+ struct path h_path;
076b876e 19504+ struct super_block *sb;
4a4d8108
AM
19505+ struct inode *inode, *h_dir;
19506+ struct dentry *wh;
19507+
19508+ bwh = -1;
076b876e 19509+ sb = dir->i_sb;
4a4d8108 19510+ if (wh_dentry) {
5527c038 19511+ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */
4a4d8108
AM
19512+ IMustLock(h_dir);
19513+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
19514+ bwh = au_dbwh(dentry);
19515+ h_path.dentry = wh_dentry;
076b876e 19516+ h_path.mnt = au_sbr_mnt(sb, bindex);
4a4d8108
AM
19517+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
19518+ dentry);
19519+ if (unlikely(err))
19520+ goto out;
19521+ }
19522+
19523+ inode = au_new_inode(dentry, /*must_new*/1);
19524+ if (!IS_ERR(inode)) {
19525+ d_instantiate(dentry, inode);
5527c038 19526+ dir = d_inode(dentry->d_parent); /* dir inode is locked */
4a4d8108 19527+ IMustLock(dir);
b912730e 19528+ au_dir_ts(dir, bindex);
be118d29 19529+ inode_inc_iversion(dir);
076b876e 19530+ au_fhsm_wrote(sb, bindex, /*force*/0);
4a4d8108
AM
19531+ return 0; /* success */
19532+ }
19533+
19534+ err = PTR_ERR(inode);
19535+ if (!wh_dentry)
19536+ goto out;
19537+
19538+ /* revert */
19539+ /* dir inode is locked */
19540+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
19541+ rerr = PTR_ERR(wh);
19542+ if (IS_ERR(wh)) {
523b37e3
AM
19543+ AuIOErr("%pd reverting whiteout failed(%d, %d)\n",
19544+ dentry, err, rerr);
4a4d8108
AM
19545+ err = -EIO;
19546+ } else
19547+ dput(wh);
19548+
4f0767ce 19549+out:
4a4d8108
AM
19550+ return err;
19551+}
19552+
027c5e7a
AM
19553+static int au_d_may_add(struct dentry *dentry)
19554+{
19555+ int err;
19556+
19557+ err = 0;
19558+ if (unlikely(d_unhashed(dentry)))
19559+ err = -ENOENT;
5527c038 19560+ if (unlikely(d_really_is_positive(dentry)))
027c5e7a
AM
19561+ err = -EEXIST;
19562+ return err;
19563+}
19564+
4a4d8108
AM
19565+/*
19566+ * simple tests for the adding inode operations.
19567+ * following the checks in vfs, plus the parent-child relationship.
19568+ */
19569+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
19570+ struct dentry *h_parent, int isdir)
19571+{
19572+ int err;
19573+ umode_t h_mode;
19574+ struct dentry *h_dentry;
19575+ struct inode *h_inode;
19576+
19577+ err = -ENAMETOOLONG;
19578+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
19579+ goto out;
19580+
19581+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 19582+ if (d_really_is_negative(dentry)) {
4a4d8108 19583+ err = -EEXIST;
5527c038 19584+ if (unlikely(d_is_positive(h_dentry)))
4a4d8108
AM
19585+ goto out;
19586+ } else {
19587+ /* rename(2) case */
19588+ err = -EIO;
5527c038
JR
19589+ if (unlikely(d_is_negative(h_dentry)))
19590+ goto out;
19591+ h_inode = d_inode(h_dentry);
19592+ if (unlikely(!h_inode->i_nlink))
4a4d8108
AM
19593+ goto out;
19594+
19595+ h_mode = h_inode->i_mode;
19596+ if (!isdir) {
19597+ err = -EISDIR;
19598+ if (unlikely(S_ISDIR(h_mode)))
19599+ goto out;
19600+ } else if (unlikely(!S_ISDIR(h_mode))) {
19601+ err = -ENOTDIR;
19602+ goto out;
19603+ }
19604+ }
19605+
19606+ err = 0;
19607+ /* expected parent dir is locked */
19608+ if (unlikely(h_parent != h_dentry->d_parent))
19609+ err = -EIO;
19610+
4f0767ce 19611+out:
4a4d8108
AM
19612+ AuTraceErr(err);
19613+ return err;
19614+}
19615+
19616+/*
19617+ * initial procedure of adding a new entry.
19618+ * prepare writable branch and the parent dir, lock it,
19619+ * and lookup whiteout for the new entry.
19620+ */
19621+static struct dentry*
19622+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
19623+ struct dentry *src_dentry, struct au_pin *pin,
19624+ struct au_wr_dir_args *wr_dir_args)
19625+{
19626+ struct dentry *wh_dentry, *h_parent;
19627+ struct super_block *sb;
19628+ struct au_branch *br;
19629+ int err;
19630+ unsigned int udba;
19631+ aufs_bindex_t bcpup;
19632+
523b37e3 19633+ AuDbg("%pd\n", dentry);
4a4d8108
AM
19634+
19635+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
19636+ bcpup = err;
19637+ wh_dentry = ERR_PTR(err);
19638+ if (unlikely(err < 0))
19639+ goto out;
19640+
19641+ sb = dentry->d_sb;
19642+ udba = au_opt_udba(sb);
19643+ err = au_pin(pin, dentry, bcpup, udba,
19644+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
19645+ wh_dentry = ERR_PTR(err);
19646+ if (unlikely(err))
19647+ goto out;
19648+
19649+ h_parent = au_pinned_h_parent(pin);
19650+ if (udba != AuOpt_UDBA_NONE
5afbbe0d 19651+ && au_dbtop(dentry) == bcpup)
4a4d8108
AM
19652+ err = au_may_add(dentry, bcpup, h_parent,
19653+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
19654+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
19655+ err = -ENAMETOOLONG;
19656+ wh_dentry = ERR_PTR(err);
19657+ if (unlikely(err))
19658+ goto out_unpin;
19659+
19660+ br = au_sbr(sb, bcpup);
19661+ if (dt) {
19662+ struct path tmp = {
19663+ .dentry = h_parent,
86dc4139 19664+ .mnt = au_br_mnt(br)
4a4d8108
AM
19665+ };
19666+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
19667+ }
19668+
19669+ wh_dentry = NULL;
19670+ if (bcpup != au_dbwh(dentry))
19671+ goto out; /* success */
19672+
2000de60
JR
19673+ /*
19674+ * ENAMETOOLONG here means that if we allowed create such name, then it
19675+ * would not be able to removed in the future. So we don't allow such
19676+ * name here and we don't handle ENAMETOOLONG differently here.
19677+ */
4a4d8108
AM
19678+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
19679+
4f0767ce 19680+out_unpin:
4a4d8108
AM
19681+ if (IS_ERR(wh_dentry))
19682+ au_unpin(pin);
4f0767ce 19683+out:
4a4d8108
AM
19684+ return wh_dentry;
19685+}
19686+
19687+/* ---------------------------------------------------------------------- */
19688+
19689+enum { Mknod, Symlink, Creat };
19690+struct simple_arg {
19691+ int type;
19692+ union {
19693+ struct {
b912730e
AM
19694+ umode_t mode;
19695+ bool want_excl;
19696+ bool try_aopen;
19697+ struct vfsub_aopen_args *aopen;
4a4d8108
AM
19698+ } c;
19699+ struct {
19700+ const char *symname;
19701+ } s;
19702+ struct {
7eafdf33 19703+ umode_t mode;
4a4d8108
AM
19704+ dev_t dev;
19705+ } m;
19706+ } u;
19707+};
19708+
19709+static int add_simple(struct inode *dir, struct dentry *dentry,
19710+ struct simple_arg *arg)
19711+{
076b876e 19712+ int err, rerr;
5afbbe0d 19713+ aufs_bindex_t btop;
4a4d8108 19714+ unsigned char created;
b912730e
AM
19715+ const unsigned char try_aopen
19716+ = (arg->type == Creat && arg->u.c.try_aopen);
acd2b654 19717+ struct vfsub_aopen_args *aopen = arg->u.c.aopen;
4a4d8108
AM
19718+ struct dentry *wh_dentry, *parent;
19719+ struct inode *h_dir;
b912730e
AM
19720+ struct super_block *sb;
19721+ struct au_branch *br;
acd2b654 19722+ /* to reduce stack size */
c2b27bf2
AM
19723+ struct {
19724+ struct au_dtime dt;
19725+ struct au_pin pin;
19726+ struct path h_path;
19727+ struct au_wr_dir_args wr_dir_args;
19728+ } *a;
4a4d8108 19729+
523b37e3 19730+ AuDbg("%pd\n", dentry);
4a4d8108
AM
19731+ IMustLock(dir);
19732+
c2b27bf2
AM
19733+ err = -ENOMEM;
19734+ a = kmalloc(sizeof(*a), GFP_NOFS);
19735+ if (unlikely(!a))
19736+ goto out;
19737+ a->wr_dir_args.force_btgt = -1;
19738+ a->wr_dir_args.flags = AuWrDir_ADD_ENTRY;
19739+
4a4d8108 19740+ parent = dentry->d_parent; /* dir inode is locked */
b912730e
AM
19741+ if (!try_aopen) {
19742+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
19743+ if (unlikely(err))
19744+ goto out_free;
19745+ }
027c5e7a
AM
19746+ err = au_d_may_add(dentry);
19747+ if (unlikely(err))
19748+ goto out_unlock;
b912730e
AM
19749+ if (!try_aopen)
19750+ di_write_lock_parent(parent);
c2b27bf2
AM
19751+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
19752+ &a->pin, &a->wr_dir_args);
4a4d8108
AM
19753+ err = PTR_ERR(wh_dentry);
19754+ if (IS_ERR(wh_dentry))
027c5e7a 19755+ goto out_parent;
4a4d8108 19756+
5afbbe0d 19757+ btop = au_dbtop(dentry);
b912730e 19758+ sb = dentry->d_sb;
5afbbe0d
AM
19759+ br = au_sbr(sb, btop);
19760+ a->h_path.dentry = au_h_dptr(dentry, btop);
b912730e 19761+ a->h_path.mnt = au_br_mnt(br);
c2b27bf2 19762+ h_dir = au_pinned_h_dir(&a->pin);
4a4d8108
AM
19763+ switch (arg->type) {
19764+ case Creat:
acd2b654 19765+ if (!try_aopen || !h_dir->i_op->atomic_open) {
b912730e
AM
19766+ err = vfsub_create(h_dir, &a->h_path, arg->u.c.mode,
19767+ arg->u.c.want_excl);
acd2b654
AM
19768+ created = !err;
19769+ if (!err && try_aopen)
19770+ aopen->file->f_mode |= FMODE_CREATED;
19771+ } else {
19772+ aopen->br = br;
19773+ err = vfsub_atomic_open(h_dir, a->h_path.dentry, aopen);
19774+ AuDbg("err %d\n", err);
19775+ AuDbgFile(aopen->file);
19776+ created = err >= 0
19777+ && !!(aopen->file->f_mode & FMODE_CREATED);
19778+ }
4a4d8108
AM
19779+ break;
19780+ case Symlink:
c2b27bf2 19781+ err = vfsub_symlink(h_dir, &a->h_path, arg->u.s.symname);
acd2b654 19782+ created = !err;
4a4d8108
AM
19783+ break;
19784+ case Mknod:
c2b27bf2
AM
19785+ err = vfsub_mknod(h_dir, &a->h_path, arg->u.m.mode,
19786+ arg->u.m.dev);
acd2b654 19787+ created = !err;
4a4d8108
AM
19788+ break;
19789+ default:
19790+ BUG();
19791+ }
acd2b654
AM
19792+ if (unlikely(err < 0))
19793+ goto out_unpin;
19794+
19795+ err = epilog(dir, btop, wh_dentry, dentry);
4a4d8108 19796+ if (!err)
acd2b654 19797+ goto out_unpin; /* success */
4a4d8108
AM
19798+
19799+ /* revert */
acd2b654 19800+ if (created /* && d_is_positive(a->h_path.dentry) */) {
523b37e3
AM
19801+ /* no delegation since it is just created */
19802+ rerr = vfsub_unlink(h_dir, &a->h_path, /*delegated*/NULL,
19803+ /*force*/0);
4a4d8108 19804+ if (rerr) {
523b37e3
AM
19805+ AuIOErr("%pd revert failure(%d, %d)\n",
19806+ dentry, err, rerr);
4a4d8108
AM
19807+ err = -EIO;
19808+ }
c2b27bf2 19809+ au_dtime_revert(&a->dt);
4a4d8108 19810+ }
acd2b654
AM
19811+ if (try_aopen && h_dir->i_op->atomic_open
19812+ && (aopen->file->f_mode & FMODE_OPENED))
19813+ /* aopen->file is still opened */
19814+ au_lcnt_dec(&aopen->br->br_nfiles);
4a4d8108 19815+
acd2b654 19816+out_unpin:
c2b27bf2 19817+ au_unpin(&a->pin);
4a4d8108 19818+ dput(wh_dentry);
027c5e7a 19819+out_parent:
b912730e
AM
19820+ if (!try_aopen)
19821+ di_write_unlock(parent);
027c5e7a 19822+out_unlock:
4a4d8108 19823+ if (unlikely(err)) {
5afbbe0d 19824+ au_update_dbtop(dentry);
4a4d8108
AM
19825+ d_drop(dentry);
19826+ }
b912730e
AM
19827+ if (!try_aopen)
19828+ aufs_read_unlock(dentry, AuLock_DW);
c2b27bf2 19829+out_free:
9f237c51 19830+ au_kfree_rcu(a);
027c5e7a 19831+out:
4a4d8108
AM
19832+ return err;
19833+}
19834+
0b2a12c6
JR
19835+int aufs_mknod(struct user_namespace *userns, struct inode *dir,
19836+ struct dentry *dentry, umode_t mode, dev_t dev)
4a4d8108
AM
19837+{
19838+ struct simple_arg arg = {
19839+ .type = Mknod,
19840+ .u.m = {
19841+ .mode = mode,
19842+ .dev = dev
19843+ }
19844+ };
19845+ return add_simple(dir, dentry, &arg);
19846+}
19847+
0b2a12c6
JR
19848+int aufs_symlink(struct user_namespace *userns, struct inode *dir,
19849+ struct dentry *dentry, const char *symname)
4a4d8108
AM
19850+{
19851+ struct simple_arg arg = {
19852+ .type = Symlink,
19853+ .u.s.symname = symname
19854+ };
19855+ return add_simple(dir, dentry, &arg);
19856+}
19857+
0b2a12c6
JR
19858+int aufs_create(struct user_namespace *userns, struct inode *dir,
19859+ struct dentry *dentry, umode_t mode, bool want_excl)
4a4d8108
AM
19860+{
19861+ struct simple_arg arg = {
19862+ .type = Creat,
19863+ .u.c = {
b4510431
AM
19864+ .mode = mode,
19865+ .want_excl = want_excl
4a4d8108
AM
19866+ }
19867+ };
19868+ return add_simple(dir, dentry, &arg);
19869+}
19870+
b912730e
AM
19871+int au_aopen_or_create(struct inode *dir, struct dentry *dentry,
19872+ struct vfsub_aopen_args *aopen_args)
19873+{
19874+ struct simple_arg arg = {
19875+ .type = Creat,
19876+ .u.c = {
19877+ .mode = aopen_args->create_mode,
19878+ .want_excl = aopen_args->open_flag & O_EXCL,
19879+ .try_aopen = true,
19880+ .aopen = aopen_args
19881+ }
19882+ };
19883+ return add_simple(dir, dentry, &arg);
19884+}
19885+
0b2a12c6
JR
19886+int aufs_tmpfile(struct user_namespace *userns, struct inode *dir,
19887+ struct dentry *dentry, umode_t mode)
38d290e6
JR
19888+{
19889+ int err;
19890+ aufs_bindex_t bindex;
19891+ struct super_block *sb;
19892+ struct dentry *parent, *h_parent, *h_dentry;
19893+ struct inode *h_dir, *inode;
19894+ struct vfsmount *h_mnt;
0b2a12c6 19895+ struct user_namespace *h_userns;
38d290e6
JR
19896+ struct au_wr_dir_args wr_dir_args = {
19897+ .force_btgt = -1,
19898+ .flags = AuWrDir_TMPFILE
19899+ };
19900+
19901+ /* copy-up may happen */
febd17d6 19902+ inode_lock(dir);
38d290e6
JR
19903+
19904+ sb = dir->i_sb;
19905+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
19906+ if (unlikely(err))
19907+ goto out;
19908+
19909+ err = au_di_init(dentry);
19910+ if (unlikely(err))
19911+ goto out_si;
19912+
19913+ err = -EBUSY;
19914+ parent = d_find_any_alias(dir);
19915+ AuDebugOn(!parent);
19916+ di_write_lock_parent(parent);
5527c038 19917+ if (unlikely(d_inode(parent) != dir))
38d290e6
JR
19918+ goto out_parent;
19919+
19920+ err = au_digen_test(parent, au_sigen(sb));
19921+ if (unlikely(err))
19922+ goto out_parent;
19923+
5afbbe0d
AM
19924+ bindex = au_dbtop(parent);
19925+ au_set_dbtop(dentry, bindex);
19926+ au_set_dbbot(dentry, bindex);
38d290e6
JR
19927+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
19928+ bindex = err;
19929+ if (unlikely(err < 0))
19930+ goto out_parent;
19931+
19932+ err = -EOPNOTSUPP;
19933+ h_dir = au_h_iptr(dir, bindex);
19934+ if (unlikely(!h_dir->i_op->tmpfile))
19935+ goto out_parent;
19936+
19937+ h_mnt = au_sbr_mnt(sb, bindex);
19938+ err = vfsub_mnt_want_write(h_mnt);
19939+ if (unlikely(err))
19940+ goto out_parent;
19941+
0b2a12c6 19942+ h_userns = mnt_user_ns(h_mnt);
38d290e6 19943+ h_parent = au_h_dptr(parent, bindex);
0b2a12c6 19944+ h_dentry = vfs_tmpfile(h_userns, h_parent, mode, /*open_flag*/0);
521ced18
JR
19945+ if (IS_ERR(h_dentry)) {
19946+ err = PTR_ERR(h_dentry);
38d290e6 19947+ goto out_mnt;
521ced18 19948+ }
38d290e6 19949+
5afbbe0d
AM
19950+ au_set_dbtop(dentry, bindex);
19951+ au_set_dbbot(dentry, bindex);
38d290e6
JR
19952+ au_set_h_dptr(dentry, bindex, dget(h_dentry));
19953+ inode = au_new_inode(dentry, /*must_new*/1);
19954+ if (IS_ERR(inode)) {
19955+ err = PTR_ERR(inode);
19956+ au_set_h_dptr(dentry, bindex, NULL);
5afbbe0d
AM
19957+ au_set_dbtop(dentry, -1);
19958+ au_set_dbbot(dentry, -1);
38d290e6
JR
19959+ } else {
19960+ if (!inode->i_nlink)
19961+ set_nlink(inode, 1);
19962+ d_tmpfile(dentry, inode);
19963+ au_di(dentry)->di_tmpfile = 1;
19964+
19965+ /* update without i_mutex */
5afbbe0d 19966+ if (au_ibtop(dir) == au_dbtop(dentry))
38d290e6
JR
19967+ au_cpup_attr_timesizes(dir);
19968+ }
38d290e6 19969+ dput(h_dentry);
521ced18 19970+
38d290e6
JR
19971+out_mnt:
19972+ vfsub_mnt_drop_write(h_mnt);
19973+out_parent:
19974+ di_write_unlock(parent);
19975+ dput(parent);
19976+ di_write_unlock(dentry);
5afbbe0d 19977+ if (unlikely(err)) {
38d290e6
JR
19978+ au_di_fin(dentry);
19979+ dentry->d_fsdata = NULL;
19980+ }
19981+out_si:
19982+ si_read_unlock(sb);
19983+out:
febd17d6 19984+ inode_unlock(dir);
38d290e6
JR
19985+ return err;
19986+}
19987+
4a4d8108
AM
19988+/* ---------------------------------------------------------------------- */
19989+
19990+struct au_link_args {
19991+ aufs_bindex_t bdst, bsrc;
19992+ struct au_pin pin;
19993+ struct path h_path;
19994+ struct dentry *src_parent, *parent;
19995+};
19996+
19997+static int au_cpup_before_link(struct dentry *src_dentry,
19998+ struct au_link_args *a)
19999+{
20000+ int err;
20001+ struct dentry *h_src_dentry;
c2b27bf2
AM
20002+ struct au_cp_generic cpg = {
20003+ .dentry = src_dentry,
20004+ .bdst = a->bdst,
20005+ .bsrc = a->bsrc,
20006+ .len = -1,
20007+ .pin = &a->pin,
20008+ .flags = AuCpup_DTIME | AuCpup_HOPEN /* | AuCpup_KEEPLINO */
20009+ };
4a4d8108
AM
20010+
20011+ di_read_lock_parent(a->src_parent, AuLock_IR);
20012+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
20013+ if (unlikely(err))
20014+ goto out;
20015+
20016+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
4a4d8108
AM
20017+ err = au_pin(&a->pin, src_dentry, a->bdst,
20018+ au_opt_udba(src_dentry->d_sb),
20019+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
20020+ if (unlikely(err))
20021+ goto out;
367653fa 20022+
c2b27bf2 20023+ err = au_sio_cpup_simple(&cpg);
4a4d8108
AM
20024+ au_unpin(&a->pin);
20025+
4f0767ce 20026+out:
4a4d8108
AM
20027+ di_read_unlock(a->src_parent, AuLock_IR);
20028+ return err;
20029+}
20030+
86dc4139
AM
20031+static int au_cpup_or_link(struct dentry *src_dentry, struct dentry *dentry,
20032+ struct au_link_args *a)
4a4d8108
AM
20033+{
20034+ int err;
20035+ unsigned char plink;
5afbbe0d 20036+ aufs_bindex_t bbot;
4a4d8108 20037+ struct dentry *h_src_dentry;
523b37e3 20038+ struct inode *h_inode, *inode, *delegated;
4a4d8108
AM
20039+ struct super_block *sb;
20040+ struct file *h_file;
20041+
20042+ plink = 0;
20043+ h_inode = NULL;
20044+ sb = src_dentry->d_sb;
5527c038 20045+ inode = d_inode(src_dentry);
5afbbe0d 20046+ if (au_ibtop(inode) <= a->bdst)
4a4d8108
AM
20047+ h_inode = au_h_iptr(inode, a->bdst);
20048+ if (!h_inode || !h_inode->i_nlink) {
20049+ /* copyup src_dentry as the name of dentry. */
5afbbe0d
AM
20050+ bbot = au_dbbot(dentry);
20051+ if (bbot < a->bsrc)
20052+ au_set_dbbot(dentry, a->bsrc);
86dc4139
AM
20053+ au_set_h_dptr(dentry, a->bsrc,
20054+ dget(au_h_dptr(src_dentry, a->bsrc)));
20055+ dget(a->h_path.dentry);
20056+ au_set_h_dptr(dentry, a->bdst, NULL);
c1595e42
JR
20057+ AuDbg("temporary d_inode...\n");
20058+ spin_lock(&dentry->d_lock);
5527c038 20059+ dentry->d_inode = d_inode(src_dentry); /* tmp */
c1595e42 20060+ spin_unlock(&dentry->d_lock);
392086de 20061+ h_file = au_h_open_pre(dentry, a->bsrc, /*force_wr*/0);
86dc4139 20062+ if (IS_ERR(h_file))
4a4d8108 20063+ err = PTR_ERR(h_file);
86dc4139 20064+ else {
c2b27bf2
AM
20065+ struct au_cp_generic cpg = {
20066+ .dentry = dentry,
20067+ .bdst = a->bdst,
20068+ .bsrc = -1,
20069+ .len = -1,
20070+ .pin = &a->pin,
20071+ .flags = AuCpup_KEEPLINO
20072+ };
20073+ err = au_sio_cpup_simple(&cpg);
86dc4139
AM
20074+ au_h_open_post(dentry, a->bsrc, h_file);
20075+ if (!err) {
20076+ dput(a->h_path.dentry);
20077+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
20078+ } else
20079+ au_set_h_dptr(dentry, a->bdst,
20080+ a->h_path.dentry);
20081+ }
c1595e42 20082+ spin_lock(&dentry->d_lock);
86dc4139 20083+ dentry->d_inode = NULL; /* restore */
c1595e42
JR
20084+ spin_unlock(&dentry->d_lock);
20085+ AuDbg("temporary d_inode...done\n");
86dc4139 20086+ au_set_h_dptr(dentry, a->bsrc, NULL);
5afbbe0d 20087+ au_set_dbbot(dentry, bbot);
4a4d8108
AM
20088+ } else {
20089+ /* the inode of src_dentry already exists on a.bdst branch */
20090+ h_src_dentry = d_find_alias(h_inode);
20091+ if (!h_src_dentry && au_plink_test(inode)) {
20092+ plink = 1;
20093+ h_src_dentry = au_plink_lkup(inode, a->bdst);
20094+ err = PTR_ERR(h_src_dentry);
20095+ if (IS_ERR(h_src_dentry))
20096+ goto out;
20097+
5527c038 20098+ if (unlikely(d_is_negative(h_src_dentry))) {
4a4d8108
AM
20099+ dput(h_src_dentry);
20100+ h_src_dentry = NULL;
20101+ }
20102+
20103+ }
20104+ if (h_src_dentry) {
523b37e3 20105+ delegated = NULL;
4a4d8108 20106+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
523b37e3
AM
20107+ &a->h_path, &delegated);
20108+ if (unlikely(err == -EWOULDBLOCK)) {
20109+ pr_warn("cannot retry for NFSv4 delegation"
20110+ " for an internal link\n");
20111+ iput(delegated);
20112+ }
4a4d8108
AM
20113+ dput(h_src_dentry);
20114+ } else {
20115+ AuIOErr("no dentry found for hi%lu on b%d\n",
20116+ h_inode->i_ino, a->bdst);
20117+ err = -EIO;
20118+ }
20119+ }
20120+
20121+ if (!err && !plink)
20122+ au_plink_append(inode, a->bdst, a->h_path.dentry);
20123+
20124+out:
2cbb1c4b 20125+ AuTraceErr(err);
4a4d8108
AM
20126+ return err;
20127+}
20128+
20129+int aufs_link(struct dentry *src_dentry, struct inode *dir,
20130+ struct dentry *dentry)
20131+{
20132+ int err, rerr;
20133+ struct au_dtime dt;
20134+ struct au_link_args *a;
20135+ struct dentry *wh_dentry, *h_src_dentry;
523b37e3 20136+ struct inode *inode, *delegated;
4a4d8108
AM
20137+ struct super_block *sb;
20138+ struct au_wr_dir_args wr_dir_args = {
20139+ /* .force_btgt = -1, */
20140+ .flags = AuWrDir_ADD_ENTRY
20141+ };
20142+
20143+ IMustLock(dir);
5527c038 20144+ inode = d_inode(src_dentry);
4a4d8108
AM
20145+ IMustLock(inode);
20146+
4a4d8108
AM
20147+ err = -ENOMEM;
20148+ a = kzalloc(sizeof(*a), GFP_NOFS);
20149+ if (unlikely(!a))
20150+ goto out;
20151+
20152+ a->parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
20153+ err = aufs_read_and_write_lock2(dentry, src_dentry,
20154+ AuLock_NOPLM | AuLock_GEN);
e49829fe
JR
20155+ if (unlikely(err))
20156+ goto out_kfree;
38d290e6 20157+ err = au_d_linkable(src_dentry);
027c5e7a
AM
20158+ if (unlikely(err))
20159+ goto out_unlock;
20160+ err = au_d_may_add(dentry);
20161+ if (unlikely(err))
20162+ goto out_unlock;
e49829fe 20163+
4a4d8108 20164+ a->src_parent = dget_parent(src_dentry);
5afbbe0d 20165+ wr_dir_args.force_btgt = au_ibtop(inode);
4a4d8108
AM
20166+
20167+ di_write_lock_parent(a->parent);
20168+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
20169+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
20170+ &wr_dir_args);
20171+ err = PTR_ERR(wh_dentry);
20172+ if (IS_ERR(wh_dentry))
027c5e7a 20173+ goto out_parent;
4a4d8108
AM
20174+
20175+ err = 0;
20176+ sb = dentry->d_sb;
5afbbe0d 20177+ a->bdst = au_dbtop(dentry);
4a4d8108
AM
20178+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
20179+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
5afbbe0d 20180+ a->bsrc = au_ibtop(inode);
2cbb1c4b 20181+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
38d290e6
JR
20182+ if (!h_src_dentry && au_di(src_dentry)->di_tmpfile)
20183+ h_src_dentry = dget(au_hi_wh(inode, a->bsrc));
2cbb1c4b 20184+ if (!h_src_dentry) {
5afbbe0d 20185+ a->bsrc = au_dbtop(src_dentry);
2cbb1c4b
JR
20186+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
20187+ AuDebugOn(!h_src_dentry);
38d290e6
JR
20188+ } else if (IS_ERR(h_src_dentry)) {
20189+ err = PTR_ERR(h_src_dentry);
2cbb1c4b 20190+ goto out_parent;
38d290e6 20191+ }
2cbb1c4b 20192+
f2c43d5f
AM
20193+ /*
20194+ * aufs doesn't touch the credential so
acd2b654 20195+ * security_dentry_create_files_as() is unnecessary.
f2c43d5f 20196+ */
4a4d8108
AM
20197+ if (au_opt_test(au_mntflags(sb), PLINK)) {
20198+ if (a->bdst < a->bsrc
20199+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
86dc4139 20200+ err = au_cpup_or_link(src_dentry, dentry, a);
523b37e3
AM
20201+ else {
20202+ delegated = NULL;
4a4d8108 20203+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
523b37e3
AM
20204+ &a->h_path, &delegated);
20205+ if (unlikely(err == -EWOULDBLOCK)) {
20206+ pr_warn("cannot retry for NFSv4 delegation"
20207+ " for an internal link\n");
20208+ iput(delegated);
20209+ }
20210+ }
2cbb1c4b 20211+ dput(h_src_dentry);
4a4d8108
AM
20212+ } else {
20213+ /*
20214+ * copyup src_dentry to the branch we process,
20215+ * and then link(2) to it.
20216+ */
2cbb1c4b 20217+ dput(h_src_dentry);
4a4d8108
AM
20218+ if (a->bdst < a->bsrc
20219+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
20220+ au_unpin(&a->pin);
20221+ di_write_unlock(a->parent);
20222+ err = au_cpup_before_link(src_dentry, a);
20223+ di_write_lock_parent(a->parent);
20224+ if (!err)
20225+ err = au_pin(&a->pin, dentry, a->bdst,
20226+ au_opt_udba(sb),
20227+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
20228+ if (unlikely(err))
20229+ goto out_wh;
20230+ }
20231+ if (!err) {
20232+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
20233+ err = -ENOENT;
5527c038 20234+ if (h_src_dentry && d_is_positive(h_src_dentry)) {
523b37e3 20235+ delegated = NULL;
4a4d8108
AM
20236+ err = vfsub_link(h_src_dentry,
20237+ au_pinned_h_dir(&a->pin),
523b37e3
AM
20238+ &a->h_path, &delegated);
20239+ if (unlikely(err == -EWOULDBLOCK)) {
20240+ pr_warn("cannot retry"
20241+ " for NFSv4 delegation"
20242+ " for an internal link\n");
20243+ iput(delegated);
20244+ }
20245+ }
4a4d8108
AM
20246+ }
20247+ }
20248+ if (unlikely(err))
20249+ goto out_unpin;
20250+
20251+ if (wh_dentry) {
20252+ a->h_path.dentry = wh_dentry;
20253+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
20254+ dentry);
20255+ if (unlikely(err))
20256+ goto out_revert;
20257+ }
20258+
b912730e 20259+ au_dir_ts(dir, a->bdst);
be118d29 20260+ inode_inc_iversion(dir);
4a4d8108
AM
20261+ inc_nlink(inode);
20262+ inode->i_ctime = dir->i_ctime;
027c5e7a
AM
20263+ d_instantiate(dentry, au_igrab(inode));
20264+ if (d_unhashed(a->h_path.dentry))
4a4d8108
AM
20265+ /* some filesystem calls d_drop() */
20266+ d_drop(dentry);
076b876e
AM
20267+ /* some filesystems consume an inode even hardlink */
20268+ au_fhsm_wrote(sb, a->bdst, /*force*/0);
4a4d8108
AM
20269+ goto out_unpin; /* success */
20270+
4f0767ce 20271+out_revert:
523b37e3
AM
20272+ /* no delegation since it is just created */
20273+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path,
20274+ /*delegated*/NULL, /*force*/0);
027c5e7a 20275+ if (unlikely(rerr)) {
523b37e3 20276+ AuIOErr("%pd reverting failed(%d, %d)\n", dentry, err, rerr);
027c5e7a
AM
20277+ err = -EIO;
20278+ }
4a4d8108 20279+ au_dtime_revert(&dt);
4f0767ce 20280+out_unpin:
4a4d8108 20281+ au_unpin(&a->pin);
4f0767ce 20282+out_wh:
4a4d8108 20283+ dput(wh_dentry);
027c5e7a
AM
20284+out_parent:
20285+ di_write_unlock(a->parent);
20286+ dput(a->src_parent);
4f0767ce 20287+out_unlock:
4a4d8108 20288+ if (unlikely(err)) {
5afbbe0d 20289+ au_update_dbtop(dentry);
4a4d8108
AM
20290+ d_drop(dentry);
20291+ }
4a4d8108 20292+ aufs_read_and_write_unlock2(dentry, src_dentry);
e49829fe 20293+out_kfree:
9f237c51 20294+ au_kfree_rcu(a);
4f0767ce 20295+out:
86dc4139 20296+ AuTraceErr(err);
4a4d8108
AM
20297+ return err;
20298+}
20299+
0b2a12c6
JR
20300+int aufs_mkdir(struct user_namespace *userns, struct inode *dir,
20301+ struct dentry *dentry, umode_t mode)
4a4d8108
AM
20302+{
20303+ int err, rerr;
20304+ aufs_bindex_t bindex;
20305+ unsigned char diropq;
20306+ struct path h_path;
20307+ struct dentry *wh_dentry, *parent, *opq_dentry;
febd17d6 20308+ struct inode *h_inode;
4a4d8108
AM
20309+ struct super_block *sb;
20310+ struct {
20311+ struct au_pin pin;
20312+ struct au_dtime dt;
20313+ } *a; /* reduce the stack usage */
20314+ struct au_wr_dir_args wr_dir_args = {
20315+ .force_btgt = -1,
20316+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
20317+ };
20318+
20319+ IMustLock(dir);
20320+
20321+ err = -ENOMEM;
20322+ a = kmalloc(sizeof(*a), GFP_NOFS);
20323+ if (unlikely(!a))
20324+ goto out;
20325+
027c5e7a
AM
20326+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
20327+ if (unlikely(err))
20328+ goto out_free;
20329+ err = au_d_may_add(dentry);
20330+ if (unlikely(err))
20331+ goto out_unlock;
20332+
4a4d8108
AM
20333+ parent = dentry->d_parent; /* dir inode is locked */
20334+ di_write_lock_parent(parent);
20335+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
20336+ &a->pin, &wr_dir_args);
20337+ err = PTR_ERR(wh_dentry);
20338+ if (IS_ERR(wh_dentry))
027c5e7a 20339+ goto out_parent;
4a4d8108
AM
20340+
20341+ sb = dentry->d_sb;
5afbbe0d 20342+ bindex = au_dbtop(dentry);
4a4d8108
AM
20343+ h_path.dentry = au_h_dptr(dentry, bindex);
20344+ h_path.mnt = au_sbr_mnt(sb, bindex);
20345+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
20346+ if (unlikely(err))
027c5e7a 20347+ goto out_unpin;
4a4d8108
AM
20348+
20349+ /* make the dir opaque */
20350+ diropq = 0;
febd17d6 20351+ h_inode = d_inode(h_path.dentry);
4a4d8108
AM
20352+ if (wh_dentry
20353+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
febd17d6 20354+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 20355+ opq_dentry = au_diropq_create(dentry, bindex);
febd17d6 20356+ inode_unlock(h_inode);
4a4d8108
AM
20357+ err = PTR_ERR(opq_dentry);
20358+ if (IS_ERR(opq_dentry))
20359+ goto out_dir;
20360+ dput(opq_dentry);
20361+ diropq = 1;
20362+ }
20363+
20364+ err = epilog(dir, bindex, wh_dentry, dentry);
20365+ if (!err) {
20366+ inc_nlink(dir);
027c5e7a 20367+ goto out_unpin; /* success */
4a4d8108
AM
20368+ }
20369+
20370+ /* revert */
20371+ if (diropq) {
20372+ AuLabel(revert opq);
febd17d6 20373+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 20374+ rerr = au_diropq_remove(dentry, bindex);
febd17d6 20375+ inode_unlock(h_inode);
4a4d8108 20376+ if (rerr) {
523b37e3
AM
20377+ AuIOErr("%pd reverting diropq failed(%d, %d)\n",
20378+ dentry, err, rerr);
4a4d8108
AM
20379+ err = -EIO;
20380+ }
20381+ }
20382+
4f0767ce 20383+out_dir:
4a4d8108
AM
20384+ AuLabel(revert dir);
20385+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
20386+ if (rerr) {
523b37e3
AM
20387+ AuIOErr("%pd reverting dir failed(%d, %d)\n",
20388+ dentry, err, rerr);
4a4d8108
AM
20389+ err = -EIO;
20390+ }
4a4d8108 20391+ au_dtime_revert(&a->dt);
027c5e7a 20392+out_unpin:
4a4d8108
AM
20393+ au_unpin(&a->pin);
20394+ dput(wh_dentry);
027c5e7a
AM
20395+out_parent:
20396+ di_write_unlock(parent);
20397+out_unlock:
4a4d8108 20398+ if (unlikely(err)) {
5afbbe0d 20399+ au_update_dbtop(dentry);
4a4d8108
AM
20400+ d_drop(dentry);
20401+ }
4a4d8108 20402+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 20403+out_free:
9f237c51 20404+ au_kfree_rcu(a);
4f0767ce 20405+out:
4a4d8108
AM
20406+ return err;
20407+}
7f207e10 20408diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
eca34b5c 20409--- /usr/share/empty/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
319657f6 20410+++ linux/fs/aufs/i_op.c 2021-12-03 15:40:58.236647297 +0100
0b2a12c6 20411@@ -0,0 +1,1513 @@
cd7a4cd9 20412+// SPDX-License-Identifier: GPL-2.0
4a4d8108 20413+/*
6d176551 20414+ * Copyright (C) 2005-2021 Junjiro R. Okajima
4a4d8108
AM
20415+ *
20416+ * This program, aufs is free software; you can redistribute it and/or modify
20417+ * it under the terms of the GNU General Public License as published by
20418+ * the Free Software Foundation; either version 2 of the License, or
20419+ * (at your option) any later version.
20420+ *
20421+ * This program is distributed in the hope that it will be useful,
20422+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20423+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20424+ * GNU General Public License for more details.
20425+ *
20426+ * You should have received a copy of the GNU General Public License
523b37e3 20427+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 20428+ */
1facf9fc 20429+
1308ab2a 20430+/*
4a4d8108 20431+ * inode operations (except add/del/rename)
1308ab2a 20432+ */
4a4d8108
AM
20433+
20434+#include <linux/device_cgroup.h>
20435+#include <linux/fs_stack.h>
eca801bf 20436+#include <linux/iversion.h>
4a4d8108
AM
20437+#include <linux/namei.h>
20438+#include <linux/security.h>
4a4d8108
AM
20439+#include "aufs.h"
20440+
1e00d052 20441+static int h_permission(struct inode *h_inode, int mask,
79b8bda9 20442+ struct path *h_path, int brperm)
1facf9fc 20443+{
1308ab2a 20444+ int err;
4a4d8108 20445+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
0b2a12c6 20446+ struct user_namespace *h_userns;
1facf9fc 20447+
e2f27e51
AM
20448+ err = -EPERM;
20449+ if (write_mask && IS_IMMUTABLE(h_inode))
20450+ goto out;
20451+
4a4d8108 20452+ err = -EACCES;
e2f27e51
AM
20453+ if (((mask & MAY_EXEC)
20454+ && S_ISREG(h_inode->i_mode)
20455+ && (path_noexec(h_path)
cd7a4cd9 20456+ || !(h_inode->i_mode & 0111))))
4a4d8108
AM
20457+ goto out;
20458+
20459+ /*
20460+ * - skip the lower fs test in the case of write to ro branch.
20461+ * - nfs dir permission write check is optimized, but a policy for
20462+ * link/rename requires a real check.
2121bcd9 20463+ * - nfs always sets SB_POSIXACL regardless its mount option 'noacl.'
b912730e 20464+ * in this case, generic_permission() returns -EOPNOTSUPP.
4a4d8108 20465+ */
0b2a12c6 20466+ h_userns = mnt_user_ns(h_path->mnt);
4a4d8108
AM
20467+ if ((write_mask && !au_br_writable(brperm))
20468+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
20469+ && write_mask && !(mask & MAY_READ))
20470+ || !h_inode->i_op->permission) {
20471+ /* AuLabel(generic_permission); */
062440b3 20472+ /* AuDbg("get_acl %ps\n", h_inode->i_op->get_acl); */
0b2a12c6 20473+ err = generic_permission(h_userns, h_inode, mask);
b912730e 20474+ if (err == -EOPNOTSUPP && au_test_nfs_noacl(h_inode))
0b2a12c6
JR
20475+ err = h_inode->i_op->permission(h_userns, h_inode,
20476+ mask);
b912730e 20477+ AuTraceErr(err);
1308ab2a 20478+ } else {
4a4d8108 20479+ /* AuLabel(h_inode->permission); */
0b2a12c6 20480+ err = h_inode->i_op->permission(h_userns, h_inode, mask);
4a4d8108
AM
20481+ AuTraceErr(err);
20482+ }
1facf9fc 20483+
4a4d8108
AM
20484+ if (!err)
20485+ err = devcgroup_inode_permission(h_inode, mask);
7f207e10 20486+ if (!err)
4a4d8108 20487+ err = security_inode_permission(h_inode, mask);
4a4d8108 20488+
4f0767ce 20489+out:
1308ab2a 20490+ return err;
20491+}
dece6358 20492+
0b2a12c6
JR
20493+static int aufs_permission(struct user_namespace *userns, struct inode *inode,
20494+ int mask)
1308ab2a 20495+{
20496+ int err;
5afbbe0d 20497+ aufs_bindex_t bindex, bbot;
4a4d8108
AM
20498+ const unsigned char isdir = !!S_ISDIR(inode->i_mode),
20499+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
20500+ struct inode *h_inode;
20501+ struct super_block *sb;
20502+ struct au_branch *br;
1facf9fc 20503+
027c5e7a 20504+ /* todo: support rcu-walk? */
1e00d052 20505+ if (mask & MAY_NOT_BLOCK)
027c5e7a
AM
20506+ return -ECHILD;
20507+
4a4d8108
AM
20508+ sb = inode->i_sb;
20509+ si_read_lock(sb, AuLock_FLUSH);
20510+ ii_read_lock_child(inode);
43982f53
AM
20511+#if 0 /* reserved for future use */
20512+ /*
20513+ * This test may be rather 'too much' since the test is essentially done
20514+ * in the aufs_lookup(). Theoretically it is possible that the inode
20515+ * generation doesn't match to the superblock's here. But it isn't a
20516+ * big deal I suppose.
20517+ */
027c5e7a
AM
20518+ err = au_iigen_test(inode, au_sigen(sb));
20519+ if (unlikely(err))
20520+ goto out;
20521+#endif
dece6358 20522+
076b876e
AM
20523+ if (!isdir
20524+ || write_mask
20525+ || au_opt_test(au_mntflags(sb), DIRPERM1)) {
4a4d8108 20526+ err = au_busy_or_stale();
5afbbe0d 20527+ h_inode = au_h_iptr(inode, au_ibtop(inode));
4a4d8108
AM
20528+ if (unlikely(!h_inode
20529+ || (h_inode->i_mode & S_IFMT)
20530+ != (inode->i_mode & S_IFMT)))
20531+ goto out;
1facf9fc 20532+
4a4d8108 20533+ err = 0;
5afbbe0d 20534+ bindex = au_ibtop(inode);
4a4d8108 20535+ br = au_sbr(sb, bindex);
79b8bda9 20536+ err = h_permission(h_inode, mask, &br->br_path, br->br_perm);
4a4d8108
AM
20537+ if (write_mask
20538+ && !err
20539+ && !special_file(h_inode->i_mode)) {
20540+ /* test whether the upper writable branch exists */
20541+ err = -EROFS;
20542+ for (; bindex >= 0; bindex--)
20543+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
20544+ err = 0;
20545+ break;
20546+ }
20547+ }
20548+ goto out;
20549+ }
dece6358 20550+
4a4d8108 20551+ /* non-write to dir */
1308ab2a 20552+ err = 0;
5afbbe0d
AM
20553+ bbot = au_ibbot(inode);
20554+ for (bindex = au_ibtop(inode); !err && bindex <= bbot; bindex++) {
4a4d8108
AM
20555+ h_inode = au_h_iptr(inode, bindex);
20556+ if (h_inode) {
20557+ err = au_busy_or_stale();
20558+ if (unlikely(!S_ISDIR(h_inode->i_mode)))
20559+ break;
20560+
20561+ br = au_sbr(sb, bindex);
79b8bda9 20562+ err = h_permission(h_inode, mask, &br->br_path,
4a4d8108
AM
20563+ br->br_perm);
20564+ }
20565+ }
1308ab2a 20566+
4f0767ce 20567+out:
4a4d8108
AM
20568+ ii_read_unlock(inode);
20569+ si_read_unlock(sb);
1308ab2a 20570+ return err;
20571+}
20572+
4a4d8108 20573+/* ---------------------------------------------------------------------- */
1facf9fc 20574+
4a4d8108 20575+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
b4510431 20576+ unsigned int flags)
4a4d8108
AM
20577+{
20578+ struct dentry *ret, *parent;
b752ccd1 20579+ struct inode *inode;
4a4d8108 20580+ struct super_block *sb;
1716fcea 20581+ int err, npositive;
dece6358 20582+
4a4d8108 20583+ IMustLock(dir);
1308ab2a 20584+
537831f9
AM
20585+ /* todo: support rcu-walk? */
20586+ ret = ERR_PTR(-ECHILD);
20587+ if (flags & LOOKUP_RCU)
20588+ goto out;
20589+
20590+ ret = ERR_PTR(-ENAMETOOLONG);
20591+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
20592+ goto out;
20593+
4a4d8108 20594+ sb = dir->i_sb;
7f207e10
AM
20595+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
20596+ ret = ERR_PTR(err);
20597+ if (unlikely(err))
20598+ goto out;
20599+
4a4d8108
AM
20600+ err = au_di_init(dentry);
20601+ ret = ERR_PTR(err);
20602+ if (unlikely(err))
7f207e10 20603+ goto out_si;
1308ab2a 20604+
9dbd164d 20605+ inode = NULL;
027c5e7a 20606+ npositive = 0; /* suppress a warning */
4a4d8108
AM
20607+ parent = dentry->d_parent; /* dir inode is locked */
20608+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
20609+ err = au_alive_dir(parent);
20610+ if (!err)
20611+ err = au_digen_test(parent, au_sigen(sb));
20612+ if (!err) {
5afbbe0d
AM
20613+ /* regardless LOOKUP_CREATE, always ALLOW_NEG */
20614+ npositive = au_lkup_dentry(dentry, au_dbtop(parent),
20615+ AuLkup_ALLOW_NEG);
027c5e7a
AM
20616+ err = npositive;
20617+ }
4a4d8108 20618+ di_read_unlock(parent, AuLock_IR);
4a4d8108
AM
20619+ ret = ERR_PTR(err);
20620+ if (unlikely(err < 0))
20621+ goto out_unlock;
1308ab2a 20622+
4a4d8108 20623+ if (npositive) {
b752ccd1 20624+ inode = au_new_inode(dentry, /*must_new*/0);
c1595e42
JR
20625+ if (IS_ERR(inode)) {
20626+ ret = (void *)inode;
20627+ inode = NULL;
20628+ goto out_unlock;
20629+ }
9dbd164d 20630+ }
4a4d8108 20631+
c1595e42
JR
20632+ if (inode)
20633+ atomic_inc(&inode->i_count);
4a4d8108 20634+ ret = d_splice_alias(inode, dentry);
43982f53 20635+#if 0 /* reserved for future use */
537831f9
AM
20636+ if (unlikely(d_need_lookup(dentry))) {
20637+ spin_lock(&dentry->d_lock);
20638+ dentry->d_flags &= ~DCACHE_NEED_LOOKUP;
20639+ spin_unlock(&dentry->d_lock);
20640+ } else
20641+#endif
c1595e42 20642+ if (inode) {
2000de60 20643+ if (!IS_ERR(ret)) {
c1595e42 20644+ iput(inode);
2000de60
JR
20645+ if (ret && ret != dentry)
20646+ ii_write_unlock(inode);
20647+ } else {
c1595e42
JR
20648+ ii_write_unlock(inode);
20649+ iput(inode);
20650+ inode = NULL;
20651+ }
7f207e10 20652+ }
1facf9fc 20653+
4f0767ce 20654+out_unlock:
4a4d8108 20655+ di_write_unlock(dentry);
7f207e10 20656+out_si:
4a4d8108 20657+ si_read_unlock(sb);
7f207e10 20658+out:
4a4d8108
AM
20659+ return ret;
20660+}
1facf9fc 20661+
4a4d8108 20662+/* ---------------------------------------------------------------------- */
1facf9fc 20663+
acd2b654
AM
20664+/*
20665+ * very dirty and complicated aufs ->atomic_open().
20666+ * aufs_atomic_open()
20667+ * + au_aopen_or_create()
20668+ * + add_simple()
20669+ * + vfsub_atomic_open()
20670+ * + branch fs ->atomic_open()
20671+ * may call the actual 'open' for h_file
20672+ * + inc br_nfiles only if opened
20673+ * + au_aopen_no_open() or au_aopen_do_open()
20674+ *
20675+ * au_aopen_do_open()
20676+ * + finish_open()
20677+ * + au_do_aopen()
20678+ * + au_do_open() the body of all 'open'
20679+ * + au_do_open_nondir()
20680+ * set the passed h_file
20681+ *
20682+ * au_aopen_no_open()
20683+ * + finish_no_open()
20684+ */
20685+
b912730e 20686+struct aopen_node {
8b6a4947 20687+ struct hlist_bl_node hblist;
b912730e
AM
20688+ struct file *file, *h_file;
20689+};
20690+
20691+static int au_do_aopen(struct inode *inode, struct file *file)
20692+{
8b6a4947
AM
20693+ struct hlist_bl_head *aopen;
20694+ struct hlist_bl_node *pos;
b912730e
AM
20695+ struct aopen_node *node;
20696+ struct au_do_open_args args = {
8b6a4947
AM
20697+ .aopen = 1,
20698+ .open = au_do_open_nondir
b912730e
AM
20699+ };
20700+
20701+ aopen = &au_sbi(inode->i_sb)->si_aopen;
8b6a4947
AM
20702+ hlist_bl_lock(aopen);
20703+ hlist_bl_for_each_entry(node, pos, aopen, hblist)
b912730e
AM
20704+ if (node->file == file) {
20705+ args.h_file = node->h_file;
20706+ break;
20707+ }
8b6a4947 20708+ hlist_bl_unlock(aopen);
b912730e
AM
20709+ /* AuDebugOn(!args.h_file); */
20710+
20711+ return au_do_open(file, &args);
20712+}
20713+
acd2b654
AM
20714+static int au_aopen_do_open(struct file *file, struct dentry *dentry,
20715+ struct aopen_node *aopen_node)
20716+{
20717+ int err;
20718+ struct hlist_bl_head *aopen;
20719+
20720+ AuLabel(here);
20721+ aopen = &au_sbi(dentry->d_sb)->si_aopen;
20722+ au_hbl_add(&aopen_node->hblist, aopen);
20723+ err = finish_open(file, dentry, au_do_aopen);
20724+ au_hbl_del(&aopen_node->hblist, aopen);
20725+ /* AuDbgFile(file); */
20726+ AuDbg("%pd%s%s\n", dentry,
20727+ (file->f_mode & FMODE_CREATED) ? " created" : "",
20728+ (file->f_mode & FMODE_OPENED) ? " opened" : "");
20729+
20730+ AuTraceErr(err);
20731+ return err;
20732+}
20733+
20734+static int au_aopen_no_open(struct file *file, struct dentry *dentry)
20735+{
20736+ int err;
20737+
20738+ AuLabel(here);
20739+ dget(dentry);
20740+ err = finish_no_open(file, dentry);
20741+
20742+ AuTraceErr(err);
20743+ return err;
20744+}
20745+
b912730e
AM
20746+static int aufs_atomic_open(struct inode *dir, struct dentry *dentry,
20747+ struct file *file, unsigned int open_flag,
acd2b654 20748+ umode_t create_mode)
b912730e 20749+{
acd2b654 20750+ int err, did_open;
5afbbe0d 20751+ unsigned int lkup_flags;
acd2b654
AM
20752+ aufs_bindex_t bindex;
20753+ struct super_block *sb;
f0c0a007 20754+ struct dentry *parent, *d;
b912730e
AM
20755+ struct vfsub_aopen_args args = {
20756+ .open_flag = open_flag,
acd2b654 20757+ .create_mode = create_mode
b912730e
AM
20758+ };
20759+ struct aopen_node aopen_node = {
20760+ .file = file
20761+ };
20762+
20763+ IMustLock(dir);
5afbbe0d 20764+ AuDbg("open_flag 0%o\n", open_flag);
b912730e
AM
20765+ AuDbgDentry(dentry);
20766+
20767+ err = 0;
20768+ if (!au_di(dentry)) {
5afbbe0d
AM
20769+ lkup_flags = LOOKUP_OPEN;
20770+ if (open_flag & O_CREAT)
20771+ lkup_flags |= LOOKUP_CREATE;
20772+ d = aufs_lookup(dir, dentry, lkup_flags);
b912730e
AM
20773+ if (IS_ERR(d)) {
20774+ err = PTR_ERR(d);
5afbbe0d 20775+ AuTraceErr(err);
b912730e
AM
20776+ goto out;
20777+ } else if (d) {
20778+ /*
20779+ * obsoleted dentry found.
20780+ * another error will be returned later.
20781+ */
20782+ d_drop(d);
b912730e 20783+ AuDbgDentry(d);
5afbbe0d 20784+ dput(d);
b912730e
AM
20785+ }
20786+ AuDbgDentry(dentry);
20787+ }
20788+
20789+ if (d_is_positive(dentry)
20790+ || d_unhashed(dentry)
20791+ || d_unlinked(dentry)
acd2b654
AM
20792+ || !(open_flag & O_CREAT)) {
20793+ err = au_aopen_no_open(file, dentry);
20794+ goto out; /* success */
20795+ }
b912730e
AM
20796+
20797+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
20798+ if (unlikely(err))
20799+ goto out;
20800+
acd2b654 20801+ sb = dentry->d_sb;
b912730e
AM
20802+ parent = dentry->d_parent; /* dir is locked */
20803+ di_write_lock_parent(parent);
5afbbe0d 20804+ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG);
acd2b654
AM
20805+ if (unlikely(err < 0))
20806+ goto out_parent;
b912730e
AM
20807+
20808+ AuDbgDentry(dentry);
acd2b654
AM
20809+ if (d_is_positive(dentry)) {
20810+ err = au_aopen_no_open(file, dentry);
20811+ goto out_parent; /* success */
20812+ }
b912730e 20813+
acd2b654 20814+ args.file = alloc_empty_file(file->f_flags, current_cred());
b912730e
AM
20815+ err = PTR_ERR(args.file);
20816+ if (IS_ERR(args.file))
acd2b654 20817+ goto out_parent;
b912730e 20818+
acd2b654 20819+ bindex = au_dbtop(dentry);
b912730e
AM
20820+ err = au_aopen_or_create(dir, dentry, &args);
20821+ AuTraceErr(err);
20822+ AuDbgFile(args.file);
acd2b654
AM
20823+ file->f_mode = args.file->f_mode & ~FMODE_OPENED;
20824+ did_open = !!(args.file->f_mode & FMODE_OPENED);
20825+ if (!did_open) {
20826+ fput(args.file);
20827+ args.file = NULL;
b912730e 20828+ }
8b6a4947
AM
20829+ di_write_unlock(parent);
20830+ di_write_unlock(dentry);
acd2b654
AM
20831+ if (unlikely(err < 0)) {
20832+ if (args.file)
20833+ fput(args.file);
20834+ goto out_sb;
b912730e 20835+ }
b912730e 20836+
acd2b654
AM
20837+ if (!did_open)
20838+ err = au_aopen_no_open(file, dentry);
8b6a4947 20839+ else {
acd2b654
AM
20840+ aopen_node.h_file = args.file;
20841+ err = au_aopen_do_open(file, dentry, &aopen_node);
8b6a4947 20842+ }
acd2b654
AM
20843+ if (unlikely(err < 0)) {
20844+ if (args.file)
20845+ fput(args.file);
20846+ if (did_open)
20847+ au_lcnt_dec(&args.br->br_nfiles);
b912730e 20848+ }
acd2b654
AM
20849+ goto out_sb; /* success */
20850+
20851+out_parent:
20852+ di_write_unlock(parent);
20853+ di_write_unlock(dentry);
20854+out_sb:
20855+ si_read_unlock(sb);
b912730e 20856+out:
b912730e 20857+ AuTraceErr(err);
acd2b654 20858+ AuDbgFile(file);
b912730e
AM
20859+ return err;
20860+}
20861+
20862+
20863+/* ---------------------------------------------------------------------- */
20864+
4a4d8108
AM
20865+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
20866+ const unsigned char add_entry, aufs_bindex_t bcpup,
5afbbe0d 20867+ aufs_bindex_t btop)
4a4d8108
AM
20868+{
20869+ int err;
20870+ struct dentry *h_parent;
20871+ struct inode *h_dir;
1facf9fc 20872+
027c5e7a 20873+ if (add_entry)
5527c038 20874+ IMustLock(d_inode(parent));
027c5e7a 20875+ else
4a4d8108
AM
20876+ di_write_lock_parent(parent);
20877+
20878+ err = 0;
20879+ if (!au_h_dptr(parent, bcpup)) {
5afbbe0d 20880+ if (btop > bcpup)
c2b27bf2 20881+ err = au_cpup_dirs(dentry, bcpup);
5afbbe0d 20882+ else if (btop < bcpup)
4a4d8108
AM
20883+ err = au_cpdown_dirs(dentry, bcpup);
20884+ else
c2b27bf2 20885+ BUG();
4a4d8108 20886+ }
38d290e6 20887+ if (!err && add_entry && !au_ftest_wrdir(add_entry, TMPFILE)) {
4a4d8108 20888+ h_parent = au_h_dptr(parent, bcpup);
5527c038 20889+ h_dir = d_inode(h_parent);
be118d29 20890+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
7e9cd9fe 20891+ err = au_lkup_neg(dentry, bcpup, /*wh*/0);
4a4d8108 20892+ /* todo: no unlock here */
3c1bdaff 20893+ inode_unlock_shared(h_dir);
027c5e7a
AM
20894+
20895+ AuDbg("bcpup %d\n", bcpup);
20896+ if (!err) {
5527c038 20897+ if (d_really_is_negative(dentry))
5afbbe0d 20898+ au_set_h_dptr(dentry, btop, NULL);
4a4d8108
AM
20899+ au_update_dbrange(dentry, /*do_put_zero*/0);
20900+ }
1308ab2a 20901+ }
1facf9fc 20902+
4a4d8108
AM
20903+ if (!add_entry)
20904+ di_write_unlock(parent);
20905+ if (!err)
20906+ err = bcpup; /* success */
1308ab2a 20907+
027c5e7a 20908+ AuTraceErr(err);
4a4d8108
AM
20909+ return err;
20910+}
1facf9fc 20911+
4a4d8108
AM
20912+/*
20913+ * decide the branch and the parent dir where we will create a new entry.
20914+ * returns new bindex or an error.
20915+ * copyup the parent dir if needed.
20916+ */
20917+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
20918+ struct au_wr_dir_args *args)
20919+{
20920+ int err;
392086de 20921+ unsigned int flags;
5afbbe0d 20922+ aufs_bindex_t bcpup, btop, src_btop;
86dc4139
AM
20923+ const unsigned char add_entry
20924+ = au_ftest_wrdir(args->flags, ADD_ENTRY)
38d290e6 20925+ | au_ftest_wrdir(args->flags, TMPFILE);
4a4d8108
AM
20926+ struct super_block *sb;
20927+ struct dentry *parent;
20928+ struct au_sbinfo *sbinfo;
1facf9fc 20929+
4a4d8108
AM
20930+ sb = dentry->d_sb;
20931+ sbinfo = au_sbi(sb);
20932+ parent = dget_parent(dentry);
5afbbe0d
AM
20933+ btop = au_dbtop(dentry);
20934+ bcpup = btop;
4a4d8108
AM
20935+ if (args->force_btgt < 0) {
20936+ if (src_dentry) {
5afbbe0d
AM
20937+ src_btop = au_dbtop(src_dentry);
20938+ if (src_btop < btop)
20939+ bcpup = src_btop;
4a4d8108 20940+ } else if (add_entry) {
392086de
AM
20941+ flags = 0;
20942+ if (au_ftest_wrdir(args->flags, ISDIR))
20943+ au_fset_wbr(flags, DIR);
20944+ err = AuWbrCreate(sbinfo, dentry, flags);
4a4d8108
AM
20945+ bcpup = err;
20946+ }
1facf9fc 20947+
5527c038 20948+ if (bcpup < 0 || au_test_ro(sb, bcpup, d_inode(dentry))) {
4a4d8108
AM
20949+ if (add_entry)
20950+ err = AuWbrCopyup(sbinfo, dentry);
20951+ else {
20952+ if (!IS_ROOT(dentry)) {
20953+ di_read_lock_parent(parent, !AuLock_IR);
20954+ err = AuWbrCopyup(sbinfo, dentry);
20955+ di_read_unlock(parent, !AuLock_IR);
20956+ } else
20957+ err = AuWbrCopyup(sbinfo, dentry);
20958+ }
20959+ bcpup = err;
20960+ if (unlikely(err < 0))
20961+ goto out;
20962+ }
20963+ } else {
20964+ bcpup = args->force_btgt;
5527c038 20965+ AuDebugOn(au_test_ro(sb, bcpup, d_inode(dentry)));
1308ab2a 20966+ }
027c5e7a 20967+
5afbbe0d 20968+ AuDbg("btop %d, bcpup %d\n", btop, bcpup);
4a4d8108 20969+ err = bcpup;
5afbbe0d 20970+ if (bcpup == btop)
4a4d8108 20971+ goto out; /* success */
4a4d8108
AM
20972+
20973+ /* copyup the new parent into the branch we process */
5afbbe0d 20974+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, btop);
027c5e7a 20975+ if (err >= 0) {
5527c038 20976+ if (d_really_is_negative(dentry)) {
5afbbe0d
AM
20977+ au_set_h_dptr(dentry, btop, NULL);
20978+ au_set_dbtop(dentry, bcpup);
20979+ au_set_dbbot(dentry, bcpup);
027c5e7a 20980+ }
38d290e6
JR
20981+ AuDebugOn(add_entry
20982+ && !au_ftest_wrdir(args->flags, TMPFILE)
20983+ && !au_h_dptr(dentry, bcpup));
027c5e7a 20984+ }
86dc4139
AM
20985+
20986+out:
20987+ dput(parent);
20988+ return err;
20989+}
20990+
20991+/* ---------------------------------------------------------------------- */
20992+
20993+void au_pin_hdir_unlock(struct au_pin *p)
20994+{
20995+ if (p->hdir)
5afbbe0d 20996+ au_hn_inode_unlock(p->hdir);
86dc4139
AM
20997+}
20998+
c1595e42 20999+int au_pin_hdir_lock(struct au_pin *p)
86dc4139
AM
21000+{
21001+ int err;
21002+
21003+ err = 0;
21004+ if (!p->hdir)
21005+ goto out;
21006+
21007+ /* even if an error happens later, keep this lock */
5afbbe0d 21008+ au_hn_inode_lock_nested(p->hdir, p->lsc_hi);
86dc4139
AM
21009+
21010+ err = -EBUSY;
5527c038 21011+ if (unlikely(p->hdir->hi_inode != d_inode(p->h_parent)))
86dc4139
AM
21012+ goto out;
21013+
21014+ err = 0;
21015+ if (p->h_dentry)
21016+ err = au_h_verify(p->h_dentry, p->udba, p->hdir->hi_inode,
21017+ p->h_parent, p->br);
21018+
21019+out:
21020+ return err;
21021+}
21022+
21023+int au_pin_hdir_relock(struct au_pin *p)
21024+{
21025+ int err, i;
21026+ struct inode *h_i;
21027+ struct dentry *h_d[] = {
21028+ p->h_dentry,
21029+ p->h_parent
21030+ };
21031+
21032+ err = au_pin_hdir_lock(p);
21033+ if (unlikely(err))
21034+ goto out;
21035+
21036+ for (i = 0; !err && i < sizeof(h_d)/sizeof(*h_d); i++) {
21037+ if (!h_d[i])
21038+ continue;
5527c038
JR
21039+ if (d_is_positive(h_d[i])) {
21040+ h_i = d_inode(h_d[i]);
86dc4139 21041+ err = !h_i->i_nlink;
5527c038 21042+ }
86dc4139
AM
21043+ }
21044+
21045+out:
21046+ return err;
21047+}
21048+
5afbbe0d 21049+static void au_pin_hdir_set_owner(struct au_pin *p, struct task_struct *task)
86dc4139 21050+{
eca34b5c 21051+ atomic_long_set(&p->hdir->hi_inode->i_rwsem.owner, (long)task);
86dc4139
AM
21052+}
21053+
21054+void au_pin_hdir_acquire_nest(struct au_pin *p)
21055+{
21056+ if (p->hdir) {
5afbbe0d 21057+ rwsem_acquire_nest(&p->hdir->hi_inode->i_rwsem.dep_map,
86dc4139
AM
21058+ p->lsc_hi, 0, NULL, _RET_IP_);
21059+ au_pin_hdir_set_owner(p, current);
21060+ }
dece6358 21061+}
1facf9fc 21062+
86dc4139
AM
21063+void au_pin_hdir_release(struct au_pin *p)
21064+{
21065+ if (p->hdir) {
21066+ au_pin_hdir_set_owner(p, p->task);
d58c55f2 21067+ rwsem_release(&p->hdir->hi_inode->i_rwsem.dep_map, _RET_IP_);
86dc4139
AM
21068+ }
21069+}
1308ab2a 21070+
4a4d8108 21071+struct dentry *au_pinned_h_parent(struct au_pin *pin)
1308ab2a 21072+{
4a4d8108
AM
21073+ if (pin && pin->parent)
21074+ return au_h_dptr(pin->parent, pin->bindex);
21075+ return NULL;
dece6358 21076+}
1facf9fc 21077+
4a4d8108 21078+void au_unpin(struct au_pin *p)
dece6358 21079+{
86dc4139
AM
21080+ if (p->hdir)
21081+ au_pin_hdir_unlock(p);
e49829fe 21082+ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE))
b4510431 21083+ vfsub_mnt_drop_write(p->h_mnt);
4a4d8108
AM
21084+ if (!p->hdir)
21085+ return;
1facf9fc 21086+
4a4d8108
AM
21087+ if (!au_ftest_pin(p->flags, DI_LOCKED))
21088+ di_read_unlock(p->parent, AuLock_IR);
21089+ iput(p->hdir->hi_inode);
21090+ dput(p->parent);
21091+ p->parent = NULL;
21092+ p->hdir = NULL;
21093+ p->h_mnt = NULL;
86dc4139 21094+ /* do not clear p->task */
4a4d8108 21095+}
1308ab2a 21096+
4a4d8108
AM
21097+int au_do_pin(struct au_pin *p)
21098+{
21099+ int err;
21100+ struct super_block *sb;
4a4d8108
AM
21101+ struct inode *h_dir;
21102+
21103+ err = 0;
21104+ sb = p->dentry->d_sb;
86dc4139 21105+ p->br = au_sbr(sb, p->bindex);
4a4d8108
AM
21106+ if (IS_ROOT(p->dentry)) {
21107+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
86dc4139 21108+ p->h_mnt = au_br_mnt(p->br);
b4510431 21109+ err = vfsub_mnt_want_write(p->h_mnt);
4a4d8108
AM
21110+ if (unlikely(err)) {
21111+ au_fclr_pin(p->flags, MNT_WRITE);
21112+ goto out_err;
21113+ }
21114+ }
dece6358 21115+ goto out;
1facf9fc 21116+ }
21117+
86dc4139 21118+ p->h_dentry = NULL;
5afbbe0d 21119+ if (p->bindex <= au_dbbot(p->dentry))
86dc4139 21120+ p->h_dentry = au_h_dptr(p->dentry, p->bindex);
dece6358 21121+
4a4d8108
AM
21122+ p->parent = dget_parent(p->dentry);
21123+ if (!au_ftest_pin(p->flags, DI_LOCKED))
21124+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
dece6358 21125+
4a4d8108 21126+ h_dir = NULL;
86dc4139 21127+ p->h_parent = au_h_dptr(p->parent, p->bindex);
5527c038 21128+ p->hdir = au_hi(d_inode(p->parent), p->bindex);
4a4d8108
AM
21129+ if (p->hdir)
21130+ h_dir = p->hdir->hi_inode;
dece6358 21131+
b752ccd1
AM
21132+ /*
21133+ * udba case, or
21134+ * if DI_LOCKED is not set, then p->parent may be different
21135+ * and h_parent can be NULL.
21136+ */
86dc4139 21137+ if (unlikely(!p->hdir || !h_dir || !p->h_parent)) {
e49829fe 21138+ err = -EBUSY;
4a4d8108
AM
21139+ if (!au_ftest_pin(p->flags, DI_LOCKED))
21140+ di_read_unlock(p->parent, AuLock_IR);
21141+ dput(p->parent);
21142+ p->parent = NULL;
21143+ goto out_err;
21144+ }
1308ab2a 21145+
4a4d8108 21146+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
86dc4139 21147+ p->h_mnt = au_br_mnt(p->br);
b4510431 21148+ err = vfsub_mnt_want_write(p->h_mnt);
dece6358 21149+ if (unlikely(err)) {
4a4d8108 21150+ au_fclr_pin(p->flags, MNT_WRITE);
86dc4139
AM
21151+ if (!au_ftest_pin(p->flags, DI_LOCKED))
21152+ di_read_unlock(p->parent, AuLock_IR);
21153+ dput(p->parent);
21154+ p->parent = NULL;
21155+ goto out_err;
dece6358
AM
21156+ }
21157+ }
4a4d8108 21158+
86dc4139
AM
21159+ au_igrab(h_dir);
21160+ err = au_pin_hdir_lock(p);
21161+ if (!err)
21162+ goto out; /* success */
21163+
076b876e
AM
21164+ au_unpin(p);
21165+
4f0767ce 21166+out_err:
4a4d8108
AM
21167+ pr_err("err %d\n", err);
21168+ err = au_busy_or_stale();
4f0767ce 21169+out:
1facf9fc 21170+ return err;
21171+}
21172+
4a4d8108
AM
21173+void au_pin_init(struct au_pin *p, struct dentry *dentry,
21174+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
21175+ unsigned int udba, unsigned char flags)
21176+{
21177+ p->dentry = dentry;
21178+ p->udba = udba;
21179+ p->lsc_di = lsc_di;
21180+ p->lsc_hi = lsc_hi;
21181+ p->flags = flags;
21182+ p->bindex = bindex;
21183+
21184+ p->parent = NULL;
21185+ p->hdir = NULL;
21186+ p->h_mnt = NULL;
86dc4139
AM
21187+
21188+ p->h_dentry = NULL;
21189+ p->h_parent = NULL;
21190+ p->br = NULL;
21191+ p->task = current;
4a4d8108
AM
21192+}
21193+
21194+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
21195+ unsigned int udba, unsigned char flags)
21196+{
21197+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
21198+ udba, flags);
21199+ return au_do_pin(pin);
21200+}
21201+
dece6358
AM
21202+/* ---------------------------------------------------------------------- */
21203+
1308ab2a 21204+/*
4a4d8108
AM
21205+ * ->setattr() and ->getattr() are called in various cases.
21206+ * chmod, stat: dentry is revalidated.
21207+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be
21208+ * unhashed.
21209+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
1308ab2a 21210+ */
027c5e7a 21211+/* todo: consolidate with do_refresh() and simple_reval_dpath() */
c1595e42 21212+int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
1facf9fc 21213+{
4a4d8108 21214+ int err;
4a4d8108 21215+ struct dentry *parent;
1facf9fc 21216+
1308ab2a 21217+ err = 0;
027c5e7a 21218+ if (au_digen_test(dentry, sigen)) {
4a4d8108
AM
21219+ parent = dget_parent(dentry);
21220+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 21221+ err = au_refresh_dentry(dentry, parent);
4a4d8108
AM
21222+ di_read_unlock(parent, AuLock_IR);
21223+ dput(parent);
dece6358 21224+ }
1facf9fc 21225+
4a4d8108 21226+ AuTraceErr(err);
1308ab2a 21227+ return err;
21228+}
dece6358 21229+
c1595e42
JR
21230+int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
21231+ struct au_icpup_args *a)
1308ab2a 21232+{
21233+ int err;
4a4d8108 21234+ loff_t sz;
5afbbe0d 21235+ aufs_bindex_t btop, ibtop;
4a4d8108
AM
21236+ struct dentry *hi_wh, *parent;
21237+ struct inode *inode;
4a4d8108
AM
21238+ struct au_wr_dir_args wr_dir_args = {
21239+ .force_btgt = -1,
21240+ .flags = 0
21241+ };
21242+
2000de60 21243+ if (d_is_dir(dentry))
4a4d8108
AM
21244+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
21245+ /* plink or hi_wh() case */
5afbbe0d 21246+ btop = au_dbtop(dentry);
5527c038 21247+ inode = d_inode(dentry);
5afbbe0d
AM
21248+ ibtop = au_ibtop(inode);
21249+ if (btop != ibtop && !au_test_ro(inode->i_sb, ibtop, inode))
21250+ wr_dir_args.force_btgt = ibtop;
4a4d8108
AM
21251+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
21252+ if (unlikely(err < 0))
21253+ goto out;
21254+ a->btgt = err;
5afbbe0d 21255+ if (err != btop)
4a4d8108
AM
21256+ au_fset_icpup(a->flags, DID_CPUP);
21257+
21258+ err = 0;
21259+ a->pin_flags = AuPin_MNT_WRITE;
21260+ parent = NULL;
21261+ if (!IS_ROOT(dentry)) {
21262+ au_fset_pin(a->pin_flags, DI_LOCKED);
21263+ parent = dget_parent(dentry);
21264+ di_write_lock_parent(parent);
21265+ }
21266+
21267+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
21268+ if (unlikely(err))
21269+ goto out_parent;
21270+
4a4d8108 21271+ sz = -1;
5afbbe0d 21272+ a->h_path.dentry = au_h_dptr(dentry, btop);
5527c038 21273+ a->h_inode = d_inode(a->h_path.dentry);
c1595e42 21274+ if (ia && (ia->ia_valid & ATTR_SIZE)) {
be118d29 21275+ inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD);
c1595e42
JR
21276+ if (ia->ia_size < i_size_read(a->h_inode))
21277+ sz = ia->ia_size;
3c1bdaff 21278+ inode_unlock_shared(a->h_inode);
c1595e42 21279+ }
4a4d8108 21280+
4a4d8108 21281+ hi_wh = NULL;
027c5e7a 21282+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) {
4a4d8108
AM
21283+ hi_wh = au_hi_wh(inode, a->btgt);
21284+ if (!hi_wh) {
c2b27bf2
AM
21285+ struct au_cp_generic cpg = {
21286+ .dentry = dentry,
21287+ .bdst = a->btgt,
21288+ .bsrc = -1,
21289+ .len = sz,
21290+ .pin = &a->pin
21291+ };
21292+ err = au_sio_cpup_wh(&cpg, /*file*/NULL);
4a4d8108
AM
21293+ if (unlikely(err))
21294+ goto out_unlock;
21295+ hi_wh = au_hi_wh(inode, a->btgt);
21296+ /* todo: revalidate hi_wh? */
21297+ }
21298+ }
21299+
21300+ if (parent) {
21301+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
21302+ di_downgrade_lock(parent, AuLock_IR);
21303+ dput(parent);
21304+ parent = NULL;
21305+ }
21306+ if (!au_ftest_icpup(a->flags, DID_CPUP))
21307+ goto out; /* success */
21308+
21309+ if (!d_unhashed(dentry)) {
c2b27bf2
AM
21310+ struct au_cp_generic cpg = {
21311+ .dentry = dentry,
21312+ .bdst = a->btgt,
5afbbe0d 21313+ .bsrc = btop,
c2b27bf2
AM
21314+ .len = sz,
21315+ .pin = &a->pin,
21316+ .flags = AuCpup_DTIME | AuCpup_HOPEN
21317+ };
21318+ err = au_sio_cpup_simple(&cpg);
4a4d8108
AM
21319+ if (!err)
21320+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
21321+ } else if (!hi_wh)
21322+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
21323+ else
21324+ a->h_path.dentry = hi_wh; /* do not dget here */
1308ab2a 21325+
4f0767ce 21326+out_unlock:
5527c038 21327+ a->h_inode = d_inode(a->h_path.dentry);
86dc4139 21328+ if (!err)
dece6358 21329+ goto out; /* success */
4a4d8108 21330+ au_unpin(&a->pin);
4f0767ce 21331+out_parent:
4a4d8108
AM
21332+ if (parent) {
21333+ di_write_unlock(parent);
21334+ dput(parent);
21335+ }
4f0767ce 21336+out:
86dc4139 21337+ if (!err)
febd17d6 21338+ inode_lock_nested(a->h_inode, AuLsc_I_CHILD);
1facf9fc 21339+ return err;
21340+}
21341+
0b2a12c6
JR
21342+static int aufs_setattr(struct user_namespace *userns, struct dentry *dentry,
21343+ struct iattr *ia)
1facf9fc 21344+{
4a4d8108 21345+ int err;
523b37e3 21346+ struct inode *inode, *delegated;
4a4d8108
AM
21347+ struct super_block *sb;
21348+ struct file *file;
21349+ struct au_icpup_args *a;
0b2a12c6 21350+ struct user_namespace *h_userns;
1facf9fc 21351+
5527c038 21352+ inode = d_inode(dentry);
4a4d8108 21353+ IMustLock(inode);
dece6358 21354+
0b2a12c6 21355+ err = setattr_prepare(userns, dentry, ia);
f2c43d5f
AM
21356+ if (unlikely(err))
21357+ goto out;
21358+
4a4d8108
AM
21359+ err = -ENOMEM;
21360+ a = kzalloc(sizeof(*a), GFP_NOFS);
21361+ if (unlikely(!a))
21362+ goto out;
1facf9fc 21363+
4a4d8108
AM
21364+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
21365+ ia->ia_valid &= ~ATTR_MODE;
dece6358 21366+
4a4d8108
AM
21367+ file = NULL;
21368+ sb = dentry->d_sb;
e49829fe
JR
21369+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21370+ if (unlikely(err))
21371+ goto out_kfree;
21372+
4a4d8108
AM
21373+ if (ia->ia_valid & ATTR_FILE) {
21374+ /* currently ftruncate(2) only */
7e9cd9fe 21375+ AuDebugOn(!d_is_reg(dentry));
4a4d8108 21376+ file = ia->ia_file;
521ced18
JR
21377+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1,
21378+ /*fi_lsc*/0);
4a4d8108
AM
21379+ if (unlikely(err))
21380+ goto out_si;
21381+ ia->ia_file = au_hf_top(file);
21382+ a->udba = AuOpt_UDBA_NONE;
21383+ } else {
21384+ /* fchmod() doesn't pass ia_file */
21385+ a->udba = au_opt_udba(sb);
027c5e7a
AM
21386+ di_write_lock_child(dentry);
21387+ /* no d_unlinked(), to set UDBA_NONE for root */
4a4d8108
AM
21388+ if (d_unhashed(dentry))
21389+ a->udba = AuOpt_UDBA_NONE;
4a4d8108
AM
21390+ if (a->udba != AuOpt_UDBA_NONE) {
21391+ AuDebugOn(IS_ROOT(dentry));
21392+ err = au_reval_for_attr(dentry, au_sigen(sb));
21393+ if (unlikely(err))
21394+ goto out_dentry;
21395+ }
dece6358 21396+ }
dece6358 21397+
4a4d8108
AM
21398+ err = au_pin_and_icpup(dentry, ia, a);
21399+ if (unlikely(err < 0))
21400+ goto out_dentry;
21401+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
21402+ ia->ia_file = NULL;
21403+ ia->ia_valid &= ~ATTR_FILE;
1308ab2a 21404+ }
dece6358 21405+
4a4d8108
AM
21406+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
21407+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
21408+ == (ATTR_MODE | ATTR_CTIME)) {
7eafdf33 21409+ err = security_path_chmod(&a->h_path, ia->ia_mode);
4a4d8108
AM
21410+ if (unlikely(err))
21411+ goto out_unlock;
21412+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
21413+ && (ia->ia_valid & ATTR_CTIME)) {
86dc4139 21414+ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid);
4a4d8108
AM
21415+ if (unlikely(err))
21416+ goto out_unlock;
21417+ }
dece6358 21418+
4a4d8108
AM
21419+ if (ia->ia_valid & ATTR_SIZE) {
21420+ struct file *f;
1308ab2a 21421+
953406b4 21422+ if (ia->ia_size < i_size_read(inode))
4a4d8108 21423+ /* unmap only */
953406b4 21424+ truncate_setsize(inode, ia->ia_size);
1308ab2a 21425+
4a4d8108
AM
21426+ f = NULL;
21427+ if (ia->ia_valid & ATTR_FILE)
21428+ f = ia->ia_file;
febd17d6 21429+ inode_unlock(a->h_inode);
4a4d8108 21430+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
febd17d6 21431+ inode_lock_nested(a->h_inode, AuLsc_I_CHILD);
523b37e3
AM
21432+ } else {
21433+ delegated = NULL;
21434+ while (1) {
21435+ err = vfsub_notify_change(&a->h_path, ia, &delegated);
21436+ if (delegated) {
21437+ err = break_deleg_wait(&delegated);
21438+ if (!err)
21439+ continue;
21440+ }
21441+ break;
21442+ }
21443+ }
8cdd5066
JR
21444+ /*
21445+ * regardless aufs 'acl' option setting.
21446+ * why don't all acl-aware fs call this func from their ->setattr()?
21447+ */
0b2a12c6
JR
21448+ if (!err && (ia->ia_valid & ATTR_MODE)) {
21449+ h_userns = mnt_user_ns(a->h_path.mnt);
21450+ err = vfsub_acl_chmod(h_userns, a->h_inode, ia->ia_mode);
21451+ }
4a4d8108
AM
21452+ if (!err)
21453+ au_cpup_attr_changeable(inode);
1308ab2a 21454+
4f0767ce 21455+out_unlock:
febd17d6 21456+ inode_unlock(a->h_inode);
4a4d8108 21457+ au_unpin(&a->pin);
027c5e7a 21458+ if (unlikely(err))
5afbbe0d 21459+ au_update_dbtop(dentry);
4f0767ce 21460+out_dentry:
4a4d8108
AM
21461+ di_write_unlock(dentry);
21462+ if (file) {
21463+ fi_write_unlock(file);
21464+ ia->ia_file = file;
21465+ ia->ia_valid |= ATTR_FILE;
21466+ }
4f0767ce 21467+out_si:
4a4d8108 21468+ si_read_unlock(sb);
e49829fe 21469+out_kfree:
9f237c51 21470+ au_kfree_rcu(a);
4f0767ce 21471+out:
4a4d8108
AM
21472+ AuTraceErr(err);
21473+ return err;
1facf9fc 21474+}
21475+
c1595e42
JR
21476+#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL)
21477+static int au_h_path_to_set_attr(struct dentry *dentry,
21478+ struct au_icpup_args *a, struct path *h_path)
21479+{
21480+ int err;
21481+ struct super_block *sb;
21482+
21483+ sb = dentry->d_sb;
21484+ a->udba = au_opt_udba(sb);
21485+ /* no d_unlinked(), to set UDBA_NONE for root */
21486+ if (d_unhashed(dentry))
21487+ a->udba = AuOpt_UDBA_NONE;
21488+ if (a->udba != AuOpt_UDBA_NONE) {
21489+ AuDebugOn(IS_ROOT(dentry));
21490+ err = au_reval_for_attr(dentry, au_sigen(sb));
21491+ if (unlikely(err))
21492+ goto out;
21493+ }
21494+ err = au_pin_and_icpup(dentry, /*ia*/NULL, a);
21495+ if (unlikely(err < 0))
21496+ goto out;
21497+
21498+ h_path->dentry = a->h_path.dentry;
21499+ h_path->mnt = au_sbr_mnt(sb, a->btgt);
21500+
21501+out:
21502+ return err;
21503+}
21504+
f2c43d5f
AM
21505+ssize_t au_sxattr(struct dentry *dentry, struct inode *inode,
21506+ struct au_sxattr *arg)
c1595e42
JR
21507+{
21508+ int err;
21509+ struct path h_path;
21510+ struct super_block *sb;
21511+ struct au_icpup_args *a;
5afbbe0d 21512+ struct inode *h_inode;
0b2a12c6 21513+ struct user_namespace *h_userns;
c1595e42 21514+
c1595e42
JR
21515+ IMustLock(inode);
21516+
21517+ err = -ENOMEM;
21518+ a = kzalloc(sizeof(*a), GFP_NOFS);
21519+ if (unlikely(!a))
21520+ goto out;
21521+
21522+ sb = dentry->d_sb;
21523+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21524+ if (unlikely(err))
21525+ goto out_kfree;
21526+
21527+ h_path.dentry = NULL; /* silence gcc */
21528+ di_write_lock_child(dentry);
21529+ err = au_h_path_to_set_attr(dentry, a, &h_path);
21530+ if (unlikely(err))
21531+ goto out_di;
0b2a12c6 21532+ h_userns = mnt_user_ns(h_path.mnt);
c1595e42 21533+
febd17d6 21534+ inode_unlock(a->h_inode);
c1595e42
JR
21535+ switch (arg->type) {
21536+ case AU_XATTR_SET:
5afbbe0d 21537+ AuDebugOn(d_is_negative(h_path.dentry));
0b2a12c6 21538+ err = vfsub_setxattr(h_userns, h_path.dentry,
c1595e42
JR
21539+ arg->u.set.name, arg->u.set.value,
21540+ arg->u.set.size, arg->u.set.flags);
21541+ break;
c1595e42
JR
21542+ case AU_ACL_SET:
21543+ err = -EOPNOTSUPP;
5527c038 21544+ h_inode = d_inode(h_path.dentry);
0b2a12c6 21545+ if (h_inode->i_op->set_acl) {
f2c43d5f 21546+ /* this will call posix_acl_update_mode */
0b2a12c6 21547+ err = h_inode->i_op->set_acl(h_userns, h_inode,
c1595e42
JR
21548+ arg->u.acl_set.acl,
21549+ arg->u.acl_set.type);
0b2a12c6 21550+ }
c1595e42
JR
21551+ break;
21552+ }
21553+ if (!err)
21554+ au_cpup_attr_timesizes(inode);
21555+
21556+ au_unpin(&a->pin);
21557+ if (unlikely(err))
5afbbe0d 21558+ au_update_dbtop(dentry);
c1595e42
JR
21559+
21560+out_di:
21561+ di_write_unlock(dentry);
21562+ si_read_unlock(sb);
21563+out_kfree:
9f237c51 21564+ au_kfree_rcu(a);
c1595e42
JR
21565+out:
21566+ AuTraceErr(err);
21567+ return err;
21568+}
21569+#endif
21570+
4a4d8108
AM
21571+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
21572+ unsigned int nlink)
1facf9fc 21573+{
9dbd164d
AM
21574+ unsigned int n;
21575+
4a4d8108 21576+ inode->i_mode = st->mode;
86dc4139
AM
21577+ /* don't i_[ug]id_write() here */
21578+ inode->i_uid = st->uid;
21579+ inode->i_gid = st->gid;
4a4d8108
AM
21580+ inode->i_atime = st->atime;
21581+ inode->i_mtime = st->mtime;
21582+ inode->i_ctime = st->ctime;
1facf9fc 21583+
4a4d8108
AM
21584+ au_cpup_attr_nlink(inode, /*force*/0);
21585+ if (S_ISDIR(inode->i_mode)) {
9dbd164d
AM
21586+ n = inode->i_nlink;
21587+ n -= nlink;
21588+ n += st->nlink;
f6b6e03d 21589+ smp_mb(); /* for i_nlink */
7eafdf33 21590+ /* 0 can happen */
92d182d2 21591+ set_nlink(inode, n);
4a4d8108 21592+ }
1facf9fc 21593+
4a4d8108
AM
21594+ spin_lock(&inode->i_lock);
21595+ inode->i_blocks = st->blocks;
21596+ i_size_write(inode, st->size);
21597+ spin_unlock(&inode->i_lock);
1facf9fc 21598+}
21599+
c1595e42 21600+/*
f2c43d5f 21601+ * common routine for aufs_getattr() and au_getxattr().
c1595e42
JR
21602+ * returns zero or negative (an error).
21603+ * @dentry will be read-locked in success.
21604+ */
42b5c33a
AM
21605+int au_h_path_getattr(struct dentry *dentry, struct inode *inode, int force,
21606+ struct path *h_path, int locked)
1facf9fc 21607+{
4a4d8108 21608+ int err;
076b876e 21609+ unsigned int mnt_flags, sigen;
c1595e42 21610+ unsigned char udba_none;
4a4d8108 21611+ aufs_bindex_t bindex;
4a4d8108 21612+ struct super_block *sb, *h_sb;
1facf9fc 21613+
c1595e42
JR
21614+ h_path->mnt = NULL;
21615+ h_path->dentry = NULL;
21616+
21617+ err = 0;
4a4d8108 21618+ sb = dentry->d_sb;
4a4d8108
AM
21619+ mnt_flags = au_mntflags(sb);
21620+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
1facf9fc 21621+
a2654f78
AM
21622+ if (unlikely(locked))
21623+ goto body; /* skip locking dinfo */
21624+
4a4d8108 21625+ /* support fstat(2) */
027c5e7a 21626+ if (!d_unlinked(dentry) && !udba_none) {
076b876e 21627+ sigen = au_sigen(sb);
027c5e7a
AM
21628+ err = au_digen_test(dentry, sigen);
21629+ if (!err) {
4a4d8108 21630+ di_read_lock_child(dentry, AuLock_IR);
027c5e7a 21631+ err = au_dbrange_test(dentry);
c1595e42
JR
21632+ if (unlikely(err)) {
21633+ di_read_unlock(dentry, AuLock_IR);
21634+ goto out;
21635+ }
027c5e7a 21636+ } else {
4a4d8108
AM
21637+ AuDebugOn(IS_ROOT(dentry));
21638+ di_write_lock_child(dentry);
027c5e7a
AM
21639+ err = au_dbrange_test(dentry);
21640+ if (!err)
21641+ err = au_reval_for_attr(dentry, sigen);
c1595e42
JR
21642+ if (!err)
21643+ di_downgrade_lock(dentry, AuLock_IR);
21644+ else {
21645+ di_write_unlock(dentry);
21646+ goto out;
21647+ }
4a4d8108
AM
21648+ }
21649+ } else
21650+ di_read_lock_child(dentry, AuLock_IR);
1facf9fc 21651+
a2654f78 21652+body:
42b5c33a
AM
21653+ if (!inode) {
21654+ inode = d_inode(dentry);
21655+ if (unlikely(!inode))
21656+ goto out;
21657+ }
5afbbe0d 21658+ bindex = au_ibtop(inode);
c1595e42
JR
21659+ h_path->mnt = au_sbr_mnt(sb, bindex);
21660+ h_sb = h_path->mnt->mnt_sb;
21661+ if (!force
21662+ && !au_test_fs_bad_iattr(h_sb)
21663+ && udba_none)
21664+ goto out; /* success */
1facf9fc 21665+
5afbbe0d 21666+ if (au_dbtop(dentry) == bindex)
c1595e42 21667+ h_path->dentry = au_h_dptr(dentry, bindex);
4a4d8108 21668+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
c1595e42
JR
21669+ h_path->dentry = au_plink_lkup(inode, bindex);
21670+ if (IS_ERR(h_path->dentry))
21671+ /* pretending success */
21672+ h_path->dentry = NULL;
21673+ else
21674+ dput(h_path->dentry);
4a4d8108 21675+ }
c1595e42
JR
21676+
21677+out:
21678+ return err;
21679+}
21680+
0b2a12c6
JR
21681+static int aufs_getattr(struct user_namespace *userns, const struct path *path,
21682+ struct kstat *st, u32 request, unsigned int query)
c1595e42
JR
21683+{
21684+ int err;
21685+ unsigned char positive;
21686+ struct path h_path;
521ced18 21687+ struct dentry *dentry;
c1595e42
JR
21688+ struct inode *inode;
21689+ struct super_block *sb;
21690+
521ced18 21691+ dentry = path->dentry;
5527c038 21692+ inode = d_inode(dentry);
c1595e42
JR
21693+ sb = dentry->d_sb;
21694+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21695+ if (unlikely(err))
21696+ goto out;
42b5c33a
AM
21697+ err = au_h_path_getattr(dentry, /*inode*/NULL, /*force*/0, &h_path,
21698+ /*locked*/0);
c1595e42
JR
21699+ if (unlikely(err))
21700+ goto out_si;
c06a8ce3 21701+ if (unlikely(!h_path.dentry))
c1595e42 21702+ /* illegally overlapped or something */
4a4d8108
AM
21703+ goto out_fill; /* pretending success */
21704+
5527c038 21705+ positive = d_is_positive(h_path.dentry);
4a4d8108 21706+ if (positive)
521ced18
JR
21707+ /* no vfsub version */
21708+ err = vfs_getattr(&h_path, st, request, query);
4a4d8108
AM
21709+ if (!err) {
21710+ if (positive)
c06a8ce3 21711+ au_refresh_iattr(inode, st,
5527c038 21712+ d_inode(h_path.dentry)->i_nlink);
4a4d8108 21713+ goto out_fill; /* success */
1facf9fc 21714+ }
7f207e10 21715+ AuTraceErr(err);
c1595e42 21716+ goto out_di;
4a4d8108 21717+
4f0767ce 21718+out_fill:
0b2a12c6 21719+ generic_fillattr(userns, inode, st);
c1595e42 21720+out_di:
4a4d8108 21721+ di_read_unlock(dentry, AuLock_IR);
c1595e42 21722+out_si:
4a4d8108 21723+ si_read_unlock(sb);
7f207e10
AM
21724+out:
21725+ AuTraceErr(err);
4a4d8108 21726+ return err;
1facf9fc 21727+}
21728+
21729+/* ---------------------------------------------------------------------- */
21730+
febd17d6
JR
21731+static const char *aufs_get_link(struct dentry *dentry, struct inode *inode,
21732+ struct delayed_call *done)
4a4d8108 21733+{
c2c0f25c 21734+ const char *ret;
c2c0f25c 21735+ struct dentry *h_dentry;
febd17d6 21736+ struct inode *h_inode;
4a4d8108 21737+ int err;
c2c0f25c 21738+ aufs_bindex_t bindex;
1facf9fc 21739+
79b8bda9 21740+ ret = NULL; /* suppress a warning */
febd17d6
JR
21741+ err = -ECHILD;
21742+ if (!dentry)
21743+ goto out;
21744+
027c5e7a
AM
21745+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
21746+ if (unlikely(err))
c2c0f25c 21747+ goto out;
027c5e7a
AM
21748+
21749+ err = au_d_hashed_positive(dentry);
c2c0f25c
AM
21750+ if (unlikely(err))
21751+ goto out_unlock;
21752+
21753+ err = -EINVAL;
21754+ inode = d_inode(dentry);
5afbbe0d 21755+ bindex = au_ibtop(inode);
c2c0f25c 21756+ h_inode = au_h_iptr(inode, bindex);
febd17d6 21757+ if (unlikely(!h_inode->i_op->get_link))
c2c0f25c
AM
21758+ goto out_unlock;
21759+
21760+ err = -EBUSY;
21761+ h_dentry = NULL;
5afbbe0d 21762+ if (au_dbtop(dentry) <= bindex) {
c2c0f25c
AM
21763+ h_dentry = au_h_dptr(dentry, bindex);
21764+ if (h_dentry)
21765+ dget(h_dentry);
027c5e7a 21766+ }
c2c0f25c
AM
21767+ if (!h_dentry) {
21768+ h_dentry = d_find_any_alias(h_inode);
21769+ if (IS_ERR(h_dentry)) {
21770+ err = PTR_ERR(h_dentry);
febd17d6 21771+ goto out_unlock;
c2c0f25c
AM
21772+ }
21773+ }
21774+ if (unlikely(!h_dentry))
febd17d6 21775+ goto out_unlock;
1facf9fc 21776+
c2c0f25c 21777+ err = 0;
062440b3 21778+ AuDbg("%ps\n", h_inode->i_op->get_link);
c2c0f25c 21779+ AuDbgDentry(h_dentry);
f2c43d5f 21780+ ret = vfs_get_link(h_dentry, done);
c2c0f25c 21781+ dput(h_dentry);
febd17d6
JR
21782+ if (IS_ERR(ret))
21783+ err = PTR_ERR(ret);
c2c0f25c 21784+
c2c0f25c
AM
21785+out_unlock:
21786+ aufs_read_unlock(dentry, AuLock_IR);
4f0767ce 21787+out:
c2c0f25c
AM
21788+ if (unlikely(err))
21789+ ret = ERR_PTR(err);
21790+ AuTraceErrPtr(ret);
21791+ return ret;
4a4d8108 21792+}
1facf9fc 21793+
4a4d8108 21794+/* ---------------------------------------------------------------------- */
1facf9fc 21795+
e2f27e51
AM
21796+static int au_is_special(struct inode *inode)
21797+{
21798+ return (inode->i_mode & (S_IFBLK | S_IFCHR | S_IFIFO | S_IFSOCK));
21799+}
21800+
acd2b654
AM
21801+static int aufs_update_time(struct inode *inode, struct timespec64 *ts,
21802+ int flags)
4a4d8108 21803+{
0c3ec466 21804+ int err;
e2f27e51 21805+ aufs_bindex_t bindex;
0c3ec466
AM
21806+ struct super_block *sb;
21807+ struct inode *h_inode;
e2f27e51 21808+ struct vfsmount *h_mnt;
0c3ec466
AM
21809+
21810+ sb = inode->i_sb;
e2f27e51
AM
21811+ WARN_ONCE((flags & S_ATIME) && !IS_NOATIME(inode),
21812+ "unexpected s_flags 0x%lx", sb->s_flags);
21813+
0c3ec466
AM
21814+ /* mmap_sem might be acquired already, cf. aufs_mmap() */
21815+ lockdep_off();
21816+ si_read_lock(sb, AuLock_FLUSH);
21817+ ii_write_lock_child(inode);
e2f27e51
AM
21818+
21819+ err = 0;
21820+ bindex = au_ibtop(inode);
21821+ h_inode = au_h_iptr(inode, bindex);
21822+ if (!au_test_ro(sb, bindex, inode)) {
21823+ h_mnt = au_sbr_mnt(sb, bindex);
21824+ err = vfsub_mnt_want_write(h_mnt);
21825+ if (!err) {
21826+ err = vfsub_update_time(h_inode, ts, flags);
21827+ vfsub_mnt_drop_write(h_mnt);
21828+ }
21829+ } else if (au_is_special(h_inode)) {
21830+ /*
21831+ * Never copy-up here.
21832+ * These special files may already be opened and used for
21833+ * communicating. If we copied it up, then the communication
21834+ * would be corrupted.
21835+ */
21836+ AuWarn1("timestamps for i%lu are ignored "
21837+ "since it is on readonly branch (hi%lu).\n",
21838+ inode->i_ino, h_inode->i_ino);
21839+ } else if (flags & ~S_ATIME) {
21840+ err = -EIO;
21841+ AuIOErr1("unexpected flags 0x%x\n", flags);
21842+ AuDebugOn(1);
21843+ }
21844+
38d290e6
JR
21845+ if (!err)
21846+ au_cpup_attr_timesizes(inode);
0c3ec466
AM
21847+ ii_write_unlock(inode);
21848+ si_read_unlock(sb);
21849+ lockdep_on();
38d290e6
JR
21850+
21851+ if (!err && (flags & S_VERSION))
21852+ inode_inc_iversion(inode);
21853+
0c3ec466 21854+ return err;
4a4d8108 21855+}
1facf9fc 21856+
4a4d8108 21857+/* ---------------------------------------------------------------------- */
1308ab2a 21858+
b95c5147
AM
21859+/* no getattr version will be set by module.c:aufs_init() */
21860+struct inode_operations aufs_iop_nogetattr[AuIop_Last],
21861+ aufs_iop[] = {
21862+ [AuIop_SYMLINK] = {
21863+ .permission = aufs_permission,
c1595e42 21864+#ifdef CONFIG_FS_POSIX_ACL
b95c5147
AM
21865+ .get_acl = aufs_get_acl,
21866+ .set_acl = aufs_set_acl, /* unsupport for symlink? */
c1595e42
JR
21867+#endif
21868+
b95c5147
AM
21869+ .setattr = aufs_setattr,
21870+ .getattr = aufs_getattr,
0c3ec466 21871+
c1595e42 21872+#ifdef CONFIG_AUFS_XATTR
b95c5147 21873+ .listxattr = aufs_listxattr,
c1595e42
JR
21874+#endif
21875+
febd17d6 21876+ .get_link = aufs_get_link,
0c3ec466 21877+
b95c5147
AM
21878+ /* .update_time = aufs_update_time */
21879+ },
21880+ [AuIop_DIR] = {
21881+ .create = aufs_create,
21882+ .lookup = aufs_lookup,
21883+ .link = aufs_link,
21884+ .unlink = aufs_unlink,
21885+ .symlink = aufs_symlink,
21886+ .mkdir = aufs_mkdir,
21887+ .rmdir = aufs_rmdir,
21888+ .mknod = aufs_mknod,
21889+ .rename = aufs_rename,
21890+
21891+ .permission = aufs_permission,
c1595e42 21892+#ifdef CONFIG_FS_POSIX_ACL
b95c5147
AM
21893+ .get_acl = aufs_get_acl,
21894+ .set_acl = aufs_set_acl,
c1595e42
JR
21895+#endif
21896+
b95c5147
AM
21897+ .setattr = aufs_setattr,
21898+ .getattr = aufs_getattr,
0c3ec466 21899+
c1595e42 21900+#ifdef CONFIG_AUFS_XATTR
b95c5147 21901+ .listxattr = aufs_listxattr,
c1595e42
JR
21902+#endif
21903+
b95c5147
AM
21904+ .update_time = aufs_update_time,
21905+ .atomic_open = aufs_atomic_open,
21906+ .tmpfile = aufs_tmpfile
21907+ },
21908+ [AuIop_OTHER] = {
21909+ .permission = aufs_permission,
c1595e42 21910+#ifdef CONFIG_FS_POSIX_ACL
b95c5147
AM
21911+ .get_acl = aufs_get_acl,
21912+ .set_acl = aufs_set_acl,
c1595e42
JR
21913+#endif
21914+
b95c5147
AM
21915+ .setattr = aufs_setattr,
21916+ .getattr = aufs_getattr,
0c3ec466 21917+
c1595e42 21918+#ifdef CONFIG_AUFS_XATTR
b95c5147 21919+ .listxattr = aufs_listxattr,
c1595e42
JR
21920+#endif
21921+
b95c5147
AM
21922+ .update_time = aufs_update_time
21923+ }
4a4d8108 21924+};
7f207e10 21925diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
eca34b5c 21926--- /usr/share/empty/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
319657f6 21927+++ linux/fs/aufs/i_op_del.c 2021-12-03 15:40:58.236647297 +0100
758e9dad 21928@@ -0,0 +1,522 @@
cd7a4cd9 21929+// SPDX-License-Identifier: GPL-2.0
1facf9fc 21930+/*
6d176551 21931+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 21932+ *
21933+ * This program, aufs is free software; you can redistribute it and/or modify
21934+ * it under the terms of the GNU General Public License as published by
21935+ * the Free Software Foundation; either version 2 of the License, or
21936+ * (at your option) any later version.
dece6358
AM
21937+ *
21938+ * This program is distributed in the hope that it will be useful,
21939+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
21940+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21941+ * GNU General Public License for more details.
21942+ *
21943+ * You should have received a copy of the GNU General Public License
523b37e3 21944+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 21945+ */
21946+
21947+/*
4a4d8108 21948+ * inode operations (del entry)
1308ab2a 21949+ */
dece6358 21950+
eca801bf 21951+#include <linux/iversion.h>
1308ab2a 21952+#include "aufs.h"
dece6358 21953+
4a4d8108
AM
21954+/*
21955+ * decide if a new whiteout for @dentry is necessary or not.
21956+ * when it is necessary, prepare the parent dir for the upper branch whose
21957+ * branch index is @bcpup for creation. the actual creation of the whiteout will
21958+ * be done by caller.
21959+ * return value:
21960+ * 0: wh is unnecessary
21961+ * plus: wh is necessary
21962+ * minus: error
21963+ */
21964+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1308ab2a 21965+{
4a4d8108 21966+ int need_wh, err;
5afbbe0d 21967+ aufs_bindex_t btop;
4a4d8108 21968+ struct super_block *sb;
dece6358 21969+
4a4d8108 21970+ sb = dentry->d_sb;
5afbbe0d 21971+ btop = au_dbtop(dentry);
4a4d8108 21972+ if (*bcpup < 0) {
5afbbe0d
AM
21973+ *bcpup = btop;
21974+ if (au_test_ro(sb, btop, d_inode(dentry))) {
4a4d8108
AM
21975+ err = AuWbrCopyup(au_sbi(sb), dentry);
21976+ *bcpup = err;
21977+ if (unlikely(err < 0))
21978+ goto out;
21979+ }
21980+ } else
5afbbe0d 21981+ AuDebugOn(btop < *bcpup
5527c038 21982+ || au_test_ro(sb, *bcpup, d_inode(dentry)));
5afbbe0d 21983+ AuDbg("bcpup %d, btop %d\n", *bcpup, btop);
1308ab2a 21984+
5afbbe0d 21985+ if (*bcpup != btop) {
4a4d8108
AM
21986+ err = au_cpup_dirs(dentry, *bcpup);
21987+ if (unlikely(err))
21988+ goto out;
21989+ need_wh = 1;
21990+ } else {
027c5e7a 21991+ struct au_dinfo *dinfo, *tmp;
4a4d8108 21992+
027c5e7a
AM
21993+ need_wh = -ENOMEM;
21994+ dinfo = au_di(dentry);
21995+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
21996+ if (tmp) {
21997+ au_di_cp(tmp, dinfo);
21998+ au_di_swap(tmp, dinfo);
21999+ /* returns the number of positive dentries */
5afbbe0d
AM
22000+ need_wh = au_lkup_dentry(dentry, btop + 1,
22001+ /* AuLkup_IGNORE_PERM */ 0);
027c5e7a
AM
22002+ au_di_swap(tmp, dinfo);
22003+ au_rw_write_unlock(&tmp->di_rwsem);
22004+ au_di_free(tmp);
4a4d8108
AM
22005+ }
22006+ }
22007+ AuDbg("need_wh %d\n", need_wh);
22008+ err = need_wh;
22009+
4f0767ce 22010+out:
4a4d8108 22011+ return err;
1facf9fc 22012+}
22013+
4a4d8108
AM
22014+/*
22015+ * simple tests for the del-entry operations.
22016+ * following the checks in vfs, plus the parent-child relationship.
22017+ */
22018+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
22019+ struct dentry *h_parent, int isdir)
1facf9fc 22020+{
4a4d8108
AM
22021+ int err;
22022+ umode_t h_mode;
22023+ struct dentry *h_dentry, *h_latest;
1308ab2a 22024+ struct inode *h_inode;
758e9dad
AM
22025+ struct path h_ppath;
22026+ struct super_block *sb;
22027+ struct au_branch *br;
0b2a12c6 22028+ struct user_namespace *h_userns;
1facf9fc 22029+
4a4d8108 22030+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 22031+ if (d_really_is_positive(dentry)) {
4a4d8108 22032+ err = -ENOENT;
5527c038
JR
22033+ if (unlikely(d_is_negative(h_dentry)))
22034+ goto out;
22035+ h_inode = d_inode(h_dentry);
22036+ if (unlikely(!h_inode->i_nlink))
4a4d8108 22037+ goto out;
1facf9fc 22038+
4a4d8108
AM
22039+ h_mode = h_inode->i_mode;
22040+ if (!isdir) {
22041+ err = -EISDIR;
22042+ if (unlikely(S_ISDIR(h_mode)))
22043+ goto out;
22044+ } else if (unlikely(!S_ISDIR(h_mode))) {
22045+ err = -ENOTDIR;
22046+ goto out;
22047+ }
22048+ } else {
22049+ /* rename(2) case */
22050+ err = -EIO;
5527c038 22051+ if (unlikely(d_is_positive(h_dentry)))
4a4d8108
AM
22052+ goto out;
22053+ }
1facf9fc 22054+
4a4d8108
AM
22055+ err = -ENOENT;
22056+ /* expected parent dir is locked */
22057+ if (unlikely(h_parent != h_dentry->d_parent))
22058+ goto out;
22059+ err = 0;
22060+
22061+ /*
22062+ * rmdir a dir may break the consistency on some filesystem.
22063+ * let's try heavy test.
22064+ */
22065+ err = -EACCES;
758e9dad
AM
22066+ sb = dentry->d_sb;
22067+ br = au_sbr(sb, bindex);
22068+ h_userns = au_br_userns(br);
22069+ if (unlikely(!au_opt_test(au_mntflags(sb), DIRPERM1)
0b2a12c6 22070+ && au_test_h_perm(h_userns, d_inode(h_parent),
076b876e 22071+ MAY_EXEC | MAY_WRITE)))
4a4d8108
AM
22072+ goto out;
22073+
758e9dad
AM
22074+ h_ppath.dentry = h_parent;
22075+ h_ppath.mnt = au_br_mnt(br);
22076+ h_latest = au_sio_lkup_one(h_userns, &dentry->d_name, &h_ppath);
4a4d8108
AM
22077+ err = -EIO;
22078+ if (IS_ERR(h_latest))
22079+ goto out;
22080+ if (h_latest == h_dentry)
22081+ err = 0;
22082+ dput(h_latest);
22083+
4f0767ce 22084+out:
4a4d8108 22085+ return err;
1308ab2a 22086+}
1facf9fc 22087+
4a4d8108
AM
22088+/*
22089+ * decide the branch where we operate for @dentry. the branch index will be set
acd2b654 22090+ * @rbcpup. after deciding it, 'pin' it and store the timestamps of the parent
4a4d8108
AM
22091+ * dir for reverting.
22092+ * when a new whiteout is necessary, create it.
22093+ */
22094+static struct dentry*
22095+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
22096+ struct au_dtime *dt, struct au_pin *pin)
1308ab2a 22097+{
4a4d8108
AM
22098+ struct dentry *wh_dentry;
22099+ struct super_block *sb;
22100+ struct path h_path;
22101+ int err, need_wh;
22102+ unsigned int udba;
22103+ aufs_bindex_t bcpup;
dece6358 22104+
4a4d8108
AM
22105+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
22106+ wh_dentry = ERR_PTR(need_wh);
22107+ if (unlikely(need_wh < 0))
22108+ goto out;
22109+
22110+ sb = dentry->d_sb;
22111+ udba = au_opt_udba(sb);
22112+ bcpup = *rbcpup;
22113+ err = au_pin(pin, dentry, bcpup, udba,
22114+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
22115+ wh_dentry = ERR_PTR(err);
22116+ if (unlikely(err))
22117+ goto out;
22118+
22119+ h_path.dentry = au_pinned_h_parent(pin);
22120+ if (udba != AuOpt_UDBA_NONE
5afbbe0d 22121+ && au_dbtop(dentry) == bcpup) {
4a4d8108
AM
22122+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
22123+ wh_dentry = ERR_PTR(err);
22124+ if (unlikely(err))
22125+ goto out_unpin;
22126+ }
22127+
22128+ h_path.mnt = au_sbr_mnt(sb, bcpup);
22129+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
22130+ wh_dentry = NULL;
22131+ if (!need_wh)
22132+ goto out; /* success, no need to create whiteout */
22133+
22134+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
22135+ if (IS_ERR(wh_dentry))
22136+ goto out_unpin;
22137+
22138+ /* returns with the parent is locked and wh_dentry is dget-ed */
22139+ goto out; /* success */
22140+
4f0767ce 22141+out_unpin:
4a4d8108 22142+ au_unpin(pin);
4f0767ce 22143+out:
4a4d8108 22144+ return wh_dentry;
1facf9fc 22145+}
22146+
4a4d8108
AM
22147+/*
22148+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
22149+ * in order to be revertible and save time for removing many child whiteouts
22150+ * under the dir.
22151+ * returns 1 when there are too many child whiteout and caller should remove
22152+ * them asynchronously. returns 0 when the number of children is enough small to
22153+ * remove now or the branch fs is a remote fs.
22154+ * otherwise return an error.
22155+ */
22156+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
22157+ struct au_nhash *whlist, struct inode *dir)
1facf9fc 22158+{
4a4d8108
AM
22159+ int rmdir_later, err, dirwh;
22160+ struct dentry *h_dentry;
22161+ struct super_block *sb;
5527c038 22162+ struct inode *inode;
4a4d8108
AM
22163+
22164+ sb = dentry->d_sb;
22165+ SiMustAnyLock(sb);
22166+ h_dentry = au_h_dptr(dentry, bindex);
22167+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
22168+ if (unlikely(err))
22169+ goto out;
22170+
22171+ /* stop monitoring */
5527c038
JR
22172+ inode = d_inode(dentry);
22173+ au_hn_free(au_hi(inode, bindex));
4a4d8108
AM
22174+
22175+ if (!au_test_fs_remote(h_dentry->d_sb)) {
22176+ dirwh = au_sbi(sb)->si_dirwh;
22177+ rmdir_later = (dirwh <= 1);
22178+ if (!rmdir_later)
22179+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
22180+ dirwh);
22181+ if (rmdir_later)
22182+ return rmdir_later;
22183+ }
1facf9fc 22184+
4a4d8108
AM
22185+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
22186+ if (unlikely(err)) {
523b37e3
AM
22187+ AuIOErr("rmdir %pd, b%d failed, %d. ignored\n",
22188+ h_dentry, bindex, err);
4a4d8108
AM
22189+ err = 0;
22190+ }
dece6358 22191+
4f0767ce 22192+out:
4a4d8108
AM
22193+ AuTraceErr(err);
22194+ return err;
22195+}
1308ab2a 22196+
4a4d8108
AM
22197+/*
22198+ * final procedure for deleting a entry.
22199+ * maintain dentry and iattr.
22200+ */
22201+static void epilog(struct inode *dir, struct dentry *dentry,
22202+ aufs_bindex_t bindex)
22203+{
22204+ struct inode *inode;
1308ab2a 22205+
5527c038 22206+ inode = d_inode(dentry);
4a4d8108
AM
22207+ d_drop(dentry);
22208+ inode->i_ctime = dir->i_ctime;
1308ab2a 22209+
b912730e 22210+ au_dir_ts(dir, bindex);
be118d29 22211+ inode_inc_iversion(dir);
1facf9fc 22212+}
22213+
4a4d8108
AM
22214+/*
22215+ * when an error happened, remove the created whiteout and revert everything.
22216+ */
7f207e10
AM
22217+static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex,
22218+ aufs_bindex_t bwh, struct dentry *wh_dentry,
22219+ struct dentry *dentry, struct au_dtime *dt)
1facf9fc 22220+{
4a4d8108
AM
22221+ int rerr;
22222+ struct path h_path = {
22223+ .dentry = wh_dentry,
7f207e10 22224+ .mnt = au_sbr_mnt(dir->i_sb, bindex)
4a4d8108 22225+ };
dece6358 22226+
7f207e10 22227+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry);
4a4d8108
AM
22228+ if (!rerr) {
22229+ au_set_dbwh(dentry, bwh);
22230+ au_dtime_revert(dt);
22231+ return 0;
22232+ }
dece6358 22233+
523b37e3 22234+ AuIOErr("%pd reverting whiteout failed(%d, %d)\n", dentry, err, rerr);
4a4d8108 22235+ return -EIO;
1facf9fc 22236+}
22237+
4a4d8108 22238+/* ---------------------------------------------------------------------- */
1facf9fc 22239+
4a4d8108 22240+int aufs_unlink(struct inode *dir, struct dentry *dentry)
1308ab2a 22241+{
4a4d8108 22242+ int err;
5afbbe0d 22243+ aufs_bindex_t bwh, bindex, btop;
523b37e3 22244+ struct inode *inode, *h_dir, *delegated;
4a4d8108 22245+ struct dentry *parent, *wh_dentry;
acd2b654 22246+ /* to reduce stack size */
c2b27bf2
AM
22247+ struct {
22248+ struct au_dtime dt;
22249+ struct au_pin pin;
22250+ struct path h_path;
22251+ } *a;
1facf9fc 22252+
4a4d8108 22253+ IMustLock(dir);
027c5e7a 22254+
c2b27bf2
AM
22255+ err = -ENOMEM;
22256+ a = kmalloc(sizeof(*a), GFP_NOFS);
22257+ if (unlikely(!a))
22258+ goto out;
22259+
027c5e7a
AM
22260+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
22261+ if (unlikely(err))
c2b27bf2 22262+ goto out_free;
027c5e7a
AM
22263+ err = au_d_hashed_positive(dentry);
22264+ if (unlikely(err))
22265+ goto out_unlock;
5527c038 22266+ inode = d_inode(dentry);
4a4d8108 22267+ IMustLock(inode);
027c5e7a 22268+ err = -EISDIR;
2000de60 22269+ if (unlikely(d_is_dir(dentry)))
027c5e7a 22270+ goto out_unlock; /* possible? */
1facf9fc 22271+
5afbbe0d 22272+ btop = au_dbtop(dentry);
4a4d8108
AM
22273+ bwh = au_dbwh(dentry);
22274+ bindex = -1;
027c5e7a
AM
22275+ parent = dentry->d_parent; /* dir inode is locked */
22276+ di_write_lock_parent(parent);
c2b27bf2
AM
22277+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &a->dt,
22278+ &a->pin);
4a4d8108
AM
22279+ err = PTR_ERR(wh_dentry);
22280+ if (IS_ERR(wh_dentry))
027c5e7a 22281+ goto out_parent;
1facf9fc 22282+
5afbbe0d
AM
22283+ a->h_path.mnt = au_sbr_mnt(dentry->d_sb, btop);
22284+ a->h_path.dentry = au_h_dptr(dentry, btop);
c2b27bf2 22285+ dget(a->h_path.dentry);
5afbbe0d 22286+ if (bindex == btop) {
c2b27bf2 22287+ h_dir = au_pinned_h_dir(&a->pin);
523b37e3
AM
22288+ delegated = NULL;
22289+ err = vfsub_unlink(h_dir, &a->h_path, &delegated, /*force*/0);
22290+ if (unlikely(err == -EWOULDBLOCK)) {
22291+ pr_warn("cannot retry for NFSv4 delegation"
22292+ " for an internal unlink\n");
22293+ iput(delegated);
22294+ }
4a4d8108
AM
22295+ } else {
22296+ /* dir inode is locked */
5527c038 22297+ h_dir = d_inode(wh_dentry->d_parent);
4a4d8108
AM
22298+ IMustLock(h_dir);
22299+ err = 0;
22300+ }
dece6358 22301+
4a4d8108 22302+ if (!err) {
7f207e10 22303+ vfsub_drop_nlink(inode);
4a4d8108
AM
22304+ epilog(dir, dentry, bindex);
22305+
22306+ /* update target timestamps */
5afbbe0d 22307+ if (bindex == btop) {
c2b27bf2
AM
22308+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL);
22309+ /*ignore*/
5527c038 22310+ inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
4a4d8108
AM
22311+ } else
22312+ /* todo: this timestamp may be reverted later */
22313+ inode->i_ctime = h_dir->i_ctime;
027c5e7a 22314+ goto out_unpin; /* success */
1facf9fc 22315+ }
22316+
4a4d8108
AM
22317+ /* revert */
22318+ if (wh_dentry) {
22319+ int rerr;
22320+
c2b27bf2
AM
22321+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry,
22322+ &a->dt);
4a4d8108
AM
22323+ if (rerr)
22324+ err = rerr;
dece6358 22325+ }
1facf9fc 22326+
027c5e7a 22327+out_unpin:
c2b27bf2 22328+ au_unpin(&a->pin);
4a4d8108 22329+ dput(wh_dentry);
c2b27bf2 22330+ dput(a->h_path.dentry);
027c5e7a 22331+out_parent:
4a4d8108 22332+ di_write_unlock(parent);
027c5e7a 22333+out_unlock:
4a4d8108 22334+ aufs_read_unlock(dentry, AuLock_DW);
c2b27bf2 22335+out_free:
9f237c51 22336+ au_kfree_rcu(a);
027c5e7a 22337+out:
4a4d8108 22338+ return err;
dece6358
AM
22339+}
22340+
4a4d8108 22341+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
1308ab2a 22342+{
4a4d8108 22343+ int err, rmdir_later;
5afbbe0d 22344+ aufs_bindex_t bwh, bindex, btop;
4a4d8108
AM
22345+ struct inode *inode;
22346+ struct dentry *parent, *wh_dentry, *h_dentry;
22347+ struct au_whtmp_rmdir *args;
acd2b654 22348+ /* to reduce stack size */
c2b27bf2
AM
22349+ struct {
22350+ struct au_dtime dt;
22351+ struct au_pin pin;
22352+ } *a;
1facf9fc 22353+
4a4d8108 22354+ IMustLock(dir);
027c5e7a 22355+
c2b27bf2
AM
22356+ err = -ENOMEM;
22357+ a = kmalloc(sizeof(*a), GFP_NOFS);
22358+ if (unlikely(!a))
22359+ goto out;
22360+
027c5e7a
AM
22361+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
22362+ if (unlikely(err))
c2b27bf2 22363+ goto out_free;
53392da6
AM
22364+ err = au_alive_dir(dentry);
22365+ if (unlikely(err))
027c5e7a 22366+ goto out_unlock;
5527c038 22367+ inode = d_inode(dentry);
4a4d8108 22368+ IMustLock(inode);
027c5e7a 22369+ err = -ENOTDIR;
2000de60 22370+ if (unlikely(!d_is_dir(dentry)))
027c5e7a 22371+ goto out_unlock; /* possible? */
dece6358 22372+
4a4d8108
AM
22373+ err = -ENOMEM;
22374+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
22375+ if (unlikely(!args))
22376+ goto out_unlock;
dece6358 22377+
4a4d8108
AM
22378+ parent = dentry->d_parent; /* dir inode is locked */
22379+ di_write_lock_parent(parent);
22380+ err = au_test_empty(dentry, &args->whlist);
22381+ if (unlikely(err))
027c5e7a 22382+ goto out_parent;
1facf9fc 22383+
5afbbe0d 22384+ btop = au_dbtop(dentry);
4a4d8108
AM
22385+ bwh = au_dbwh(dentry);
22386+ bindex = -1;
c2b27bf2
AM
22387+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &a->dt,
22388+ &a->pin);
4a4d8108
AM
22389+ err = PTR_ERR(wh_dentry);
22390+ if (IS_ERR(wh_dentry))
027c5e7a 22391+ goto out_parent;
1facf9fc 22392+
5afbbe0d 22393+ h_dentry = au_h_dptr(dentry, btop);
4a4d8108
AM
22394+ dget(h_dentry);
22395+ rmdir_later = 0;
5afbbe0d
AM
22396+ if (bindex == btop) {
22397+ err = renwh_and_rmdir(dentry, btop, &args->whlist, dir);
4a4d8108
AM
22398+ if (err > 0) {
22399+ rmdir_later = err;
22400+ err = 0;
22401+ }
22402+ } else {
22403+ /* stop monitoring */
5afbbe0d 22404+ au_hn_free(au_hi(inode, btop));
4a4d8108
AM
22405+
22406+ /* dir inode is locked */
5527c038 22407+ IMustLock(d_inode(wh_dentry->d_parent));
1facf9fc 22408+ err = 0;
22409+ }
22410+
4a4d8108 22411+ if (!err) {
027c5e7a 22412+ vfsub_dead_dir(inode);
4a4d8108
AM
22413+ au_set_dbdiropq(dentry, -1);
22414+ epilog(dir, dentry, bindex);
1308ab2a 22415+
4a4d8108 22416+ if (rmdir_later) {
5afbbe0d 22417+ au_whtmp_kick_rmdir(dir, btop, h_dentry, args);
4a4d8108
AM
22418+ args = NULL;
22419+ }
1308ab2a 22420+
4a4d8108 22421+ goto out_unpin; /* success */
1facf9fc 22422+ }
22423+
4a4d8108
AM
22424+ /* revert */
22425+ AuLabel(revert);
22426+ if (wh_dentry) {
22427+ int rerr;
1308ab2a 22428+
c2b27bf2
AM
22429+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry,
22430+ &a->dt);
4a4d8108
AM
22431+ if (rerr)
22432+ err = rerr;
1facf9fc 22433+ }
22434+
4f0767ce 22435+out_unpin:
c2b27bf2 22436+ au_unpin(&a->pin);
4a4d8108
AM
22437+ dput(wh_dentry);
22438+ dput(h_dentry);
027c5e7a 22439+out_parent:
4a4d8108
AM
22440+ di_write_unlock(parent);
22441+ if (args)
22442+ au_whtmp_rmdir_free(args);
4f0767ce 22443+out_unlock:
4a4d8108 22444+ aufs_read_unlock(dentry, AuLock_DW);
c2b27bf2 22445+out_free:
9f237c51 22446+ au_kfree_rcu(a);
4f0767ce 22447+out:
4a4d8108
AM
22448+ AuTraceErr(err);
22449+ return err;
dece6358 22450+}
7f207e10 22451diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
eca34b5c 22452--- /usr/share/empty/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
319657f6 22453+++ linux/fs/aufs/i_op_ren.c 2021-12-03 15:40:58.236647297 +0100
758e9dad 22454@@ -0,0 +1,1257 @@
cd7a4cd9 22455+// SPDX-License-Identifier: GPL-2.0
1facf9fc 22456+/*
6d176551 22457+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 22458+ *
22459+ * This program, aufs is free software; you can redistribute it and/or modify
22460+ * it under the terms of the GNU General Public License as published by
22461+ * the Free Software Foundation; either version 2 of the License, or
22462+ * (at your option) any later version.
dece6358
AM
22463+ *
22464+ * This program is distributed in the hope that it will be useful,
22465+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22466+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22467+ * GNU General Public License for more details.
22468+ *
22469+ * You should have received a copy of the GNU General Public License
523b37e3 22470+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 22471+ */
22472+
22473+/*
4a4d8108
AM
22474+ * inode operation (rename entry)
22475+ * todo: this is crazy monster
1facf9fc 22476+ */
22477+
eca801bf 22478+#include <linux/iversion.h>
1facf9fc 22479+#include "aufs.h"
22480+
4a4d8108
AM
22481+enum { AuSRC, AuDST, AuSrcDst };
22482+enum { AuPARENT, AuCHILD, AuParentChild };
1facf9fc 22483+
f2c43d5f
AM
22484+#define AuRen_ISDIR_SRC 1
22485+#define AuRen_ISDIR_DST (1 << 1)
22486+#define AuRen_ISSAMEDIR (1 << 2)
22487+#define AuRen_WHSRC (1 << 3)
22488+#define AuRen_WHDST (1 << 4)
22489+#define AuRen_MNT_WRITE (1 << 5)
22490+#define AuRen_DT_DSTDIR (1 << 6)
22491+#define AuRen_DIROPQ_SRC (1 << 7)
22492+#define AuRen_DIROPQ_DST (1 << 8)
8b6a4947
AM
22493+#define AuRen_DIRREN (1 << 9)
22494+#define AuRen_DROPPED_SRC (1 << 10)
22495+#define AuRen_DROPPED_DST (1 << 11)
4a4d8108 22496+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
7f207e10
AM
22497+#define au_fset_ren(flags, name) \
22498+ do { (flags) |= AuRen_##name; } while (0)
22499+#define au_fclr_ren(flags, name) \
22500+ do { (flags) &= ~AuRen_##name; } while (0)
1facf9fc 22501+
8b6a4947
AM
22502+#ifndef CONFIG_AUFS_DIRREN
22503+#undef AuRen_DIRREN
22504+#define AuRen_DIRREN 0
22505+#endif
22506+
4a4d8108
AM
22507+struct au_ren_args {
22508+ struct {
22509+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
22510+ *wh_dentry;
22511+ struct inode *dir, *inode;
f2c43d5f 22512+ struct au_hinode *hdir, *hinode;
4a4d8108 22513+ struct au_dtime dt[AuParentChild];
f2c43d5f 22514+ aufs_bindex_t btop, bdiropq;
4a4d8108 22515+ } sd[AuSrcDst];
1facf9fc 22516+
4a4d8108
AM
22517+#define src_dentry sd[AuSRC].dentry
22518+#define src_dir sd[AuSRC].dir
22519+#define src_inode sd[AuSRC].inode
22520+#define src_h_dentry sd[AuSRC].h_dentry
22521+#define src_parent sd[AuSRC].parent
22522+#define src_h_parent sd[AuSRC].h_parent
22523+#define src_wh_dentry sd[AuSRC].wh_dentry
22524+#define src_hdir sd[AuSRC].hdir
f2c43d5f 22525+#define src_hinode sd[AuSRC].hinode
4a4d8108
AM
22526+#define src_h_dir sd[AuSRC].hdir->hi_inode
22527+#define src_dt sd[AuSRC].dt
5afbbe0d 22528+#define src_btop sd[AuSRC].btop
f2c43d5f 22529+#define src_bdiropq sd[AuSRC].bdiropq
1facf9fc 22530+
4a4d8108
AM
22531+#define dst_dentry sd[AuDST].dentry
22532+#define dst_dir sd[AuDST].dir
22533+#define dst_inode sd[AuDST].inode
22534+#define dst_h_dentry sd[AuDST].h_dentry
22535+#define dst_parent sd[AuDST].parent
22536+#define dst_h_parent sd[AuDST].h_parent
22537+#define dst_wh_dentry sd[AuDST].wh_dentry
22538+#define dst_hdir sd[AuDST].hdir
f2c43d5f 22539+#define dst_hinode sd[AuDST].hinode
4a4d8108
AM
22540+#define dst_h_dir sd[AuDST].hdir->hi_inode
22541+#define dst_dt sd[AuDST].dt
5afbbe0d 22542+#define dst_btop sd[AuDST].btop
f2c43d5f 22543+#define dst_bdiropq sd[AuDST].bdiropq
4a4d8108
AM
22544+
22545+ struct dentry *h_trap;
22546+ struct au_branch *br;
4a4d8108
AM
22547+ struct path h_path;
22548+ struct au_nhash whlist;
f2c43d5f 22549+ aufs_bindex_t btgt, src_bwh;
1facf9fc 22550+
f2c43d5f
AM
22551+ struct {
22552+ unsigned short auren_flags;
22553+ unsigned char flags; /* syscall parameter */
22554+ unsigned char exchange;
22555+ } __packed;
1facf9fc 22556+
4a4d8108
AM
22557+ struct au_whtmp_rmdir *thargs;
22558+ struct dentry *h_dst;
8b6a4947 22559+ struct au_hinode *h_root;
4a4d8108 22560+};
1308ab2a 22561+
4a4d8108 22562+/* ---------------------------------------------------------------------- */
1308ab2a 22563+
4a4d8108
AM
22564+/*
22565+ * functions for reverting.
22566+ * when an error happened in a single rename systemcall, we should revert
79b8bda9 22567+ * everything as if nothing happened.
4a4d8108
AM
22568+ * we don't need to revert the copied-up/down the parent dir since they are
22569+ * harmless.
22570+ */
1facf9fc 22571+
4a4d8108
AM
22572+#define RevertFailure(fmt, ...) do { \
22573+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
22574+ ##__VA_ARGS__, err, rerr); \
22575+ err = -EIO; \
22576+} while (0)
1facf9fc 22577+
f2c43d5f 22578+static void au_ren_do_rev_diropq(int err, struct au_ren_args *a, int idx)
1facf9fc 22579+{
4a4d8108 22580+ int rerr;
f2c43d5f
AM
22581+ struct dentry *d;
22582+#define src_or_dst(member) a->sd[idx].member
1facf9fc 22583+
f2c43d5f
AM
22584+ d = src_or_dst(dentry); /* {src,dst}_dentry */
22585+ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD);
22586+ rerr = au_diropq_remove(d, a->btgt);
22587+ au_hn_inode_unlock(src_or_dst(hinode));
22588+ au_set_dbdiropq(d, src_or_dst(bdiropq));
4a4d8108 22589+ if (rerr)
f2c43d5f
AM
22590+ RevertFailure("remove diropq %pd", d);
22591+
22592+#undef src_or_dst_
22593+}
22594+
22595+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
22596+{
22597+ if (au_ftest_ren(a->auren_flags, DIROPQ_SRC))
22598+ au_ren_do_rev_diropq(err, a, AuSRC);
22599+ if (au_ftest_ren(a->auren_flags, DIROPQ_DST))
22600+ au_ren_do_rev_diropq(err, a, AuDST);
4a4d8108 22601+}
1facf9fc 22602+
4a4d8108
AM
22603+static void au_ren_rev_rename(int err, struct au_ren_args *a)
22604+{
22605+ int rerr;
523b37e3 22606+ struct inode *delegated;
758e9dad
AM
22607+ struct path h_ppath = {
22608+ .dentry = a->src_h_parent,
22609+ .mnt = a->h_path.mnt
22610+ };
1facf9fc 22611+
758e9dad 22612+ a->h_path.dentry = vfsub_lkup_one(&a->src_dentry->d_name, &h_ppath);
4a4d8108
AM
22613+ rerr = PTR_ERR(a->h_path.dentry);
22614+ if (IS_ERR(a->h_path.dentry)) {
523b37e3 22615+ RevertFailure("lkup one %pd", a->src_dentry);
4a4d8108 22616+ return;
1facf9fc 22617+ }
22618+
523b37e3 22619+ delegated = NULL;
4a4d8108
AM
22620+ rerr = vfsub_rename(a->dst_h_dir,
22621+ au_h_dptr(a->src_dentry, a->btgt),
f2c43d5f 22622+ a->src_h_dir, &a->h_path, &delegated, a->flags);
523b37e3
AM
22623+ if (unlikely(rerr == -EWOULDBLOCK)) {
22624+ pr_warn("cannot retry for NFSv4 delegation"
22625+ " for an internal rename\n");
22626+ iput(delegated);
22627+ }
4a4d8108
AM
22628+ d_drop(a->h_path.dentry);
22629+ dput(a->h_path.dentry);
22630+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
22631+ if (rerr)
523b37e3 22632+ RevertFailure("rename %pd", a->src_dentry);
1facf9fc 22633+}
22634+
4a4d8108 22635+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
1facf9fc 22636+{
4a4d8108 22637+ int rerr;
523b37e3 22638+ struct inode *delegated;
758e9dad
AM
22639+ struct path h_ppath = {
22640+ .dentry = a->dst_h_parent,
22641+ .mnt = a->h_path.mnt
22642+ };
dece6358 22643+
758e9dad 22644+ a->h_path.dentry = vfsub_lkup_one(&a->dst_dentry->d_name, &h_ppath);
4a4d8108
AM
22645+ rerr = PTR_ERR(a->h_path.dentry);
22646+ if (IS_ERR(a->h_path.dentry)) {
523b37e3 22647+ RevertFailure("lkup one %pd", a->dst_dentry);
4a4d8108
AM
22648+ return;
22649+ }
5527c038 22650+ if (d_is_positive(a->h_path.dentry)) {
4a4d8108
AM
22651+ d_drop(a->h_path.dentry);
22652+ dput(a->h_path.dentry);
22653+ return;
dece6358
AM
22654+ }
22655+
523b37e3
AM
22656+ delegated = NULL;
22657+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path,
f2c43d5f 22658+ &delegated, a->flags);
523b37e3
AM
22659+ if (unlikely(rerr == -EWOULDBLOCK)) {
22660+ pr_warn("cannot retry for NFSv4 delegation"
22661+ " for an internal rename\n");
22662+ iput(delegated);
22663+ }
4a4d8108
AM
22664+ d_drop(a->h_path.dentry);
22665+ dput(a->h_path.dentry);
22666+ if (!rerr)
22667+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
22668+ else
523b37e3 22669+ RevertFailure("rename %pd", a->h_dst);
4a4d8108 22670+}
1308ab2a 22671+
4a4d8108
AM
22672+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
22673+{
22674+ int rerr;
1308ab2a 22675+
4a4d8108
AM
22676+ a->h_path.dentry = a->src_wh_dentry;
22677+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
027c5e7a 22678+ au_set_dbwh(a->src_dentry, a->src_bwh);
4a4d8108 22679+ if (rerr)
523b37e3 22680+ RevertFailure("unlink %pd", a->src_wh_dentry);
4a4d8108 22681+}
4a4d8108 22682+#undef RevertFailure
1facf9fc 22683+
1308ab2a 22684+/* ---------------------------------------------------------------------- */
22685+
4a4d8108
AM
22686+/*
22687+ * when we have to copyup the renaming entry, do it with the rename-target name
22688+ * in order to minimize the cost (the later actual rename is unnecessary).
22689+ * otherwise rename it on the target branch.
22690+ */
22691+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 22692+{
dece6358 22693+ int err;
4a4d8108 22694+ struct dentry *d;
523b37e3 22695+ struct inode *delegated;
1facf9fc 22696+
4a4d8108 22697+ d = a->src_dentry;
5afbbe0d 22698+ if (au_dbtop(d) == a->btgt) {
4a4d8108 22699+ a->h_path.dentry = a->dst_h_dentry;
5afbbe0d 22700+ AuDebugOn(au_dbtop(d) != a->btgt);
523b37e3 22701+ delegated = NULL;
4a4d8108 22702+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
f2c43d5f
AM
22703+ a->dst_h_dir, &a->h_path, &delegated,
22704+ a->flags);
523b37e3
AM
22705+ if (unlikely(err == -EWOULDBLOCK)) {
22706+ pr_warn("cannot retry for NFSv4 delegation"
22707+ " for an internal rename\n");
22708+ iput(delegated);
22709+ }
c2b27bf2 22710+ } else
86dc4139 22711+ BUG();
1308ab2a 22712+
027c5e7a
AM
22713+ if (!err && a->h_dst)
22714+ /* it will be set to dinfo later */
22715+ dget(a->h_dst);
1facf9fc 22716+
dece6358
AM
22717+ return err;
22718+}
1facf9fc 22719+
4a4d8108
AM
22720+/* cf. aufs_rmdir() */
22721+static int au_ren_del_whtmp(struct au_ren_args *a)
dece6358 22722+{
4a4d8108
AM
22723+ int err;
22724+ struct inode *dir;
1facf9fc 22725+
4a4d8108
AM
22726+ dir = a->dst_dir;
22727+ SiMustAnyLock(dir->i_sb);
22728+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
22729+ au_sbi(dir->i_sb)->si_dirwh)
22730+ || au_test_fs_remote(a->h_dst->d_sb)) {
22731+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
22732+ if (unlikely(err))
523b37e3
AM
22733+ pr_warn("failed removing whtmp dir %pd (%d), "
22734+ "ignored.\n", a->h_dst, err);
4a4d8108
AM
22735+ } else {
22736+ au_nhash_wh_free(&a->thargs->whlist);
22737+ a->thargs->whlist = a->whlist;
22738+ a->whlist.nh_num = 0;
22739+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
22740+ dput(a->h_dst);
22741+ a->thargs = NULL;
22742+ }
22743+
22744+ return 0;
1308ab2a 22745+}
1facf9fc 22746+
4a4d8108 22747+/* make it 'opaque' dir. */
f2c43d5f 22748+static int au_ren_do_diropq(struct au_ren_args *a, int idx)
4a4d8108
AM
22749+{
22750+ int err;
f2c43d5f
AM
22751+ struct dentry *d, *diropq;
22752+#define src_or_dst(member) a->sd[idx].member
1facf9fc 22753+
4a4d8108 22754+ err = 0;
f2c43d5f
AM
22755+ d = src_or_dst(dentry); /* {src,dst}_dentry */
22756+ src_or_dst(bdiropq) = au_dbdiropq(d);
22757+ src_or_dst(hinode) = au_hi(src_or_dst(inode), a->btgt);
22758+ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD);
22759+ diropq = au_diropq_create(d, a->btgt);
22760+ au_hn_inode_unlock(src_or_dst(hinode));
4a4d8108
AM
22761+ if (IS_ERR(diropq))
22762+ err = PTR_ERR(diropq);
076b876e
AM
22763+ else
22764+ dput(diropq);
1facf9fc 22765+
f2c43d5f 22766+#undef src_or_dst_
4a4d8108
AM
22767+ return err;
22768+}
1facf9fc 22769+
f2c43d5f 22770+static int au_ren_diropq(struct au_ren_args *a)
4a4d8108
AM
22771+{
22772+ int err;
f2c43d5f
AM
22773+ unsigned char always;
22774+ struct dentry *d;
1facf9fc 22775+
f2c43d5f
AM
22776+ err = 0;
22777+ d = a->dst_dentry; /* already renamed on the branch */
22778+ always = !!au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ);
22779+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)
8b6a4947 22780+ && !au_ftest_ren(a->auren_flags, DIRREN)
f2c43d5f
AM
22781+ && a->btgt != au_dbdiropq(a->src_dentry)
22782+ && (a->dst_wh_dentry
22783+ || a->btgt <= au_dbdiropq(d)
22784+ /* hide the lower to keep xino */
22785+ /* the lowers may not be a dir, but we hide them anyway */
22786+ || a->btgt < au_dbbot(d)
22787+ || always)) {
22788+ AuDbg("here\n");
22789+ err = au_ren_do_diropq(a, AuSRC);
22790+ if (unlikely(err))
4a4d8108 22791+ goto out;
f2c43d5f 22792+ au_fset_ren(a->auren_flags, DIROPQ_SRC);
4a4d8108 22793+ }
f2c43d5f
AM
22794+ if (!a->exchange)
22795+ goto out; /* success */
1facf9fc 22796+
f2c43d5f
AM
22797+ d = a->src_dentry; /* already renamed on the branch */
22798+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)
22799+ && a->btgt != au_dbdiropq(a->dst_dentry)
22800+ && (a->btgt < au_dbdiropq(d)
22801+ || a->btgt < au_dbbot(d)
22802+ || always)) {
22803+ AuDbgDentry(a->src_dentry);
22804+ AuDbgDentry(a->dst_dentry);
22805+ err = au_ren_do_diropq(a, AuDST);
4a4d8108 22806+ if (unlikely(err))
f2c43d5f
AM
22807+ goto out_rev_src;
22808+ au_fset_ren(a->auren_flags, DIROPQ_DST);
22809+ }
22810+ goto out; /* success */
dece6358 22811+
f2c43d5f
AM
22812+out_rev_src:
22813+ AuDbg("err %d, reverting src\n", err);
22814+ au_ren_rev_diropq(err, a);
22815+out:
22816+ return err;
22817+}
22818+
22819+static int do_rename(struct au_ren_args *a)
22820+{
22821+ int err;
22822+ struct dentry *d, *h_d;
22823+
22824+ if (!a->exchange) {
22825+ /* prepare workqueue args for asynchronous rmdir */
22826+ h_d = a->dst_h_dentry;
22827+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)
8b6a4947 22828+ /* && !au_ftest_ren(a->auren_flags, DIRREN) */
f2c43d5f
AM
22829+ && d_is_positive(h_d)) {
22830+ err = -ENOMEM;
22831+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb,
22832+ GFP_NOFS);
22833+ if (unlikely(!a->thargs))
22834+ goto out;
22835+ a->h_dst = dget(h_d);
22836+ }
22837+
22838+ /* create whiteout for src_dentry */
22839+ if (au_ftest_ren(a->auren_flags, WHSRC)) {
22840+ a->src_bwh = au_dbwh(a->src_dentry);
22841+ AuDebugOn(a->src_bwh >= 0);
22842+ a->src_wh_dentry = au_wh_create(a->src_dentry, a->btgt,
22843+ a->src_h_parent);
22844+ err = PTR_ERR(a->src_wh_dentry);
22845+ if (IS_ERR(a->src_wh_dentry))
22846+ goto out_thargs;
22847+ }
22848+
22849+ /* lookup whiteout for dentry */
22850+ if (au_ftest_ren(a->auren_flags, WHDST)) {
22851+ h_d = au_wh_lkup(a->dst_h_parent,
22852+ &a->dst_dentry->d_name, a->br);
22853+ err = PTR_ERR(h_d);
22854+ if (IS_ERR(h_d))
22855+ goto out_whsrc;
22856+ if (d_is_negative(h_d))
22857+ dput(h_d);
22858+ else
22859+ a->dst_wh_dentry = h_d;
22860+ }
22861+
22862+ /* rename dentry to tmpwh */
22863+ if (a->thargs) {
22864+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
22865+ if (unlikely(err))
22866+ goto out_whdst;
22867+
22868+ d = a->dst_dentry;
22869+ au_set_h_dptr(d, a->btgt, NULL);
22870+ err = au_lkup_neg(d, a->btgt, /*wh*/0);
22871+ if (unlikely(err))
22872+ goto out_whtmp;
22873+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
22874+ }
4a4d8108 22875+ }
1facf9fc 22876+
5afbbe0d 22877+ BUG_ON(d_is_positive(a->dst_h_dentry) && a->src_btop != a->btgt);
43982f53 22878+#if 0 /* debugging */
8b6a4947
AM
22879+ BUG_ON(!au_ftest_ren(a->auren_flags, DIRREN)
22880+ && d_is_positive(a->dst_h_dentry)
22881+ && a->src_btop != a->btgt);
22882+#endif
1facf9fc 22883+
4a4d8108 22884+ /* rename by vfs_rename or cpup */
4a4d8108
AM
22885+ err = au_ren_or_cpup(a);
22886+ if (unlikely(err))
22887+ /* leave the copied-up one */
22888+ goto out_whtmp;
1308ab2a 22889+
4a4d8108 22890+ /* make dir opaque */
f2c43d5f
AM
22891+ err = au_ren_diropq(a);
22892+ if (unlikely(err))
22893+ goto out_rename;
1308ab2a 22894+
4a4d8108 22895+ /* update target timestamps */
f2c43d5f
AM
22896+ if (a->exchange) {
22897+ AuDebugOn(au_dbtop(a->dst_dentry) != a->btgt);
22898+ a->h_path.dentry = au_h_dptr(a->dst_dentry, a->btgt);
22899+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
22900+ a->dst_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
22901+ }
5afbbe0d 22902+ AuDebugOn(au_dbtop(a->src_dentry) != a->btgt);
4a4d8108
AM
22903+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
22904+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
5527c038 22905+ a->src_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
1facf9fc 22906+
f2c43d5f
AM
22907+ if (!a->exchange) {
22908+ /* remove whiteout for dentry */
22909+ if (a->dst_wh_dentry) {
22910+ a->h_path.dentry = a->dst_wh_dentry;
22911+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
22912+ a->dst_dentry);
22913+ if (unlikely(err))
22914+ goto out_diropq;
22915+ }
1facf9fc 22916+
f2c43d5f
AM
22917+ /* remove whtmp */
22918+ if (a->thargs)
22919+ au_ren_del_whtmp(a); /* ignore this error */
1308ab2a 22920+
f2c43d5f
AM
22921+ au_fhsm_wrote(a->src_dentry->d_sb, a->btgt, /*force*/0);
22922+ }
4a4d8108
AM
22923+ err = 0;
22924+ goto out_success;
22925+
4f0767ce 22926+out_diropq:
f2c43d5f 22927+ au_ren_rev_diropq(err, a);
4f0767ce 22928+out_rename:
7e9cd9fe 22929+ au_ren_rev_rename(err, a);
027c5e7a 22930+ dput(a->h_dst);
4f0767ce 22931+out_whtmp:
4a4d8108
AM
22932+ if (a->thargs)
22933+ au_ren_rev_whtmp(err, a);
4f0767ce 22934+out_whdst:
4a4d8108
AM
22935+ dput(a->dst_wh_dentry);
22936+ a->dst_wh_dentry = NULL;
4f0767ce 22937+out_whsrc:
4a4d8108
AM
22938+ if (a->src_wh_dentry)
22939+ au_ren_rev_whsrc(err, a);
4f0767ce 22940+out_success:
4a4d8108
AM
22941+ dput(a->src_wh_dentry);
22942+ dput(a->dst_wh_dentry);
4f0767ce 22943+out_thargs:
4a4d8108
AM
22944+ if (a->thargs) {
22945+ dput(a->h_dst);
22946+ au_whtmp_rmdir_free(a->thargs);
22947+ a->thargs = NULL;
22948+ }
4f0767ce 22949+out:
4a4d8108 22950+ return err;
dece6358 22951+}
1facf9fc 22952+
1308ab2a 22953+/* ---------------------------------------------------------------------- */
1facf9fc 22954+
4a4d8108
AM
22955+/*
22956+ * test if @dentry dir can be rename destination or not.
22957+ * success means, it is a logically empty dir.
22958+ */
22959+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
1308ab2a 22960+{
4a4d8108 22961+ return au_test_empty(dentry, whlist);
1308ab2a 22962+}
1facf9fc 22963+
4a4d8108 22964+/*
8b6a4947
AM
22965+ * test if @a->src_dentry dir can be rename source or not.
22966+ * if it can, return 0.
4a4d8108
AM
22967+ * success means,
22968+ * - it is a logically empty dir.
22969+ * - or, it exists on writable branch and has no children including whiteouts
8b6a4947 22970+ * on the lower branch unless DIRREN is on.
4a4d8108 22971+ */
8b6a4947 22972+static int may_rename_srcdir(struct au_ren_args *a)
4a4d8108
AM
22973+{
22974+ int err;
22975+ unsigned int rdhash;
8b6a4947
AM
22976+ aufs_bindex_t btop, btgt;
22977+ struct dentry *dentry;
22978+ struct super_block *sb;
22979+ struct au_sbinfo *sbinfo;
1facf9fc 22980+
8b6a4947
AM
22981+ dentry = a->src_dentry;
22982+ sb = dentry->d_sb;
22983+ sbinfo = au_sbi(sb);
22984+ if (au_opt_test(sbinfo->si_mntflags, DIRREN))
22985+ au_fset_ren(a->auren_flags, DIRREN);
22986+
22987+ btgt = a->btgt;
5afbbe0d
AM
22988+ btop = au_dbtop(dentry);
22989+ if (btop != btgt) {
4a4d8108 22990+ struct au_nhash whlist;
dece6358 22991+
8b6a4947
AM
22992+ SiMustAnyLock(sb);
22993+ rdhash = sbinfo->si_rdhash;
4a4d8108
AM
22994+ if (!rdhash)
22995+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
22996+ dentry));
22997+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
22998+ if (unlikely(err))
22999+ goto out;
23000+ err = au_test_empty(dentry, &whlist);
23001+ au_nhash_wh_free(&whlist);
23002+ goto out;
23003+ }
dece6358 23004+
5afbbe0d 23005+ if (btop == au_dbtaildir(dentry))
4a4d8108 23006+ return 0; /* success */
dece6358 23007+
4a4d8108 23008+ err = au_test_empty_lower(dentry);
1facf9fc 23009+
4f0767ce 23010+out:
4a4d8108 23011+ if (err == -ENOTEMPTY) {
8b6a4947
AM
23012+ if (au_ftest_ren(a->auren_flags, DIRREN)) {
23013+ err = 0;
23014+ } else {
23015+ AuWarn1("renaming dir who has child(ren) on multiple "
23016+ "branches, is not supported\n");
23017+ err = -EXDEV;
23018+ }
4a4d8108
AM
23019+ }
23020+ return err;
23021+}
1308ab2a 23022+
4a4d8108
AM
23023+/* side effect: sets whlist and h_dentry */
23024+static int au_ren_may_dir(struct au_ren_args *a)
1308ab2a 23025+{
4a4d8108
AM
23026+ int err;
23027+ unsigned int rdhash;
23028+ struct dentry *d;
1facf9fc 23029+
4a4d8108
AM
23030+ d = a->dst_dentry;
23031+ SiMustAnyLock(d->d_sb);
1facf9fc 23032+
4a4d8108 23033+ err = 0;
f2c43d5f 23034+ if (au_ftest_ren(a->auren_flags, ISDIR_DST) && a->dst_inode) {
4a4d8108
AM
23035+ rdhash = au_sbi(d->d_sb)->si_rdhash;
23036+ if (!rdhash)
23037+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
23038+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
23039+ if (unlikely(err))
23040+ goto out;
1308ab2a 23041+
f2c43d5f
AM
23042+ if (!a->exchange) {
23043+ au_set_dbtop(d, a->dst_btop);
23044+ err = may_rename_dstdir(d, &a->whlist);
23045+ au_set_dbtop(d, a->btgt);
23046+ } else
8b6a4947 23047+ err = may_rename_srcdir(a);
4a4d8108 23048+ }
5afbbe0d 23049+ a->dst_h_dentry = au_h_dptr(d, au_dbtop(d));
4a4d8108
AM
23050+ if (unlikely(err))
23051+ goto out;
23052+
23053+ d = a->src_dentry;
5afbbe0d 23054+ a->src_h_dentry = au_h_dptr(d, au_dbtop(d));
f2c43d5f 23055+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) {
8b6a4947 23056+ err = may_rename_srcdir(a);
4a4d8108
AM
23057+ if (unlikely(err)) {
23058+ au_nhash_wh_free(&a->whlist);
23059+ a->whlist.nh_num = 0;
23060+ }
23061+ }
4f0767ce 23062+out:
4a4d8108 23063+ return err;
1facf9fc 23064+}
23065+
4a4d8108 23066+/* ---------------------------------------------------------------------- */
1facf9fc 23067+
4a4d8108
AM
23068+/*
23069+ * simple tests for rename.
23070+ * following the checks in vfs, plus the parent-child relationship.
23071+ */
23072+static int au_may_ren(struct au_ren_args *a)
23073+{
23074+ int err, isdir;
23075+ struct inode *h_inode;
1facf9fc 23076+
5afbbe0d 23077+ if (a->src_btop == a->btgt) {
4a4d8108 23078+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
f2c43d5f 23079+ au_ftest_ren(a->auren_flags, ISDIR_SRC));
4a4d8108
AM
23080+ if (unlikely(err))
23081+ goto out;
23082+ err = -EINVAL;
23083+ if (unlikely(a->src_h_dentry == a->h_trap))
23084+ goto out;
23085+ }
1facf9fc 23086+
4a4d8108 23087+ err = 0;
5afbbe0d 23088+ if (a->dst_btop != a->btgt)
4a4d8108 23089+ goto out;
1facf9fc 23090+
027c5e7a
AM
23091+ err = -ENOTEMPTY;
23092+ if (unlikely(a->dst_h_dentry == a->h_trap))
23093+ goto out;
23094+
4a4d8108 23095+ err = -EIO;
f2c43d5f 23096+ isdir = !!au_ftest_ren(a->auren_flags, ISDIR_DST);
5527c038
JR
23097+ if (d_really_is_negative(a->dst_dentry)) {
23098+ if (d_is_negative(a->dst_h_dentry))
23099+ err = au_may_add(a->dst_dentry, a->btgt,
23100+ a->dst_h_parent, isdir);
4a4d8108 23101+ } else {
5527c038 23102+ if (unlikely(d_is_negative(a->dst_h_dentry)))
4a4d8108 23103+ goto out;
5527c038
JR
23104+ h_inode = d_inode(a->dst_h_dentry);
23105+ if (h_inode->i_nlink)
23106+ err = au_may_del(a->dst_dentry, a->btgt,
23107+ a->dst_h_parent, isdir);
4a4d8108 23108+ }
1facf9fc 23109+
4f0767ce 23110+out:
4a4d8108
AM
23111+ if (unlikely(err == -ENOENT || err == -EEXIST))
23112+ err = -EIO;
23113+ AuTraceErr(err);
23114+ return err;
23115+}
1facf9fc 23116+
1308ab2a 23117+/* ---------------------------------------------------------------------- */
1facf9fc 23118+
4a4d8108
AM
23119+/*
23120+ * locking order
23121+ * (VFS)
23122+ * - src_dir and dir by lock_rename()
acd2b654 23123+ * - inode if exists
4a4d8108
AM
23124+ * (aufs)
23125+ * - lock all
23126+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
23127+ * + si_read_lock
23128+ * + di_write_lock2_child()
23129+ * + di_write_lock_child()
23130+ * + ii_write_lock_child()
23131+ * + di_write_lock_child2()
23132+ * + ii_write_lock_child2()
23133+ * + src_parent and parent
23134+ * + di_write_lock_parent()
23135+ * + ii_write_lock_parent()
23136+ * + di_write_lock_parent2()
23137+ * + ii_write_lock_parent2()
23138+ * + lower src_dir and dir by vfsub_lock_rename()
23139+ * + verify the every relationships between child and parent. if any
23140+ * of them failed, unlock all and return -EBUSY.
23141+ */
23142+static void au_ren_unlock(struct au_ren_args *a)
1308ab2a 23143+{
4a4d8108
AM
23144+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
23145+ a->dst_h_parent, a->dst_hdir);
8b6a4947
AM
23146+ if (au_ftest_ren(a->auren_flags, DIRREN)
23147+ && a->h_root)
23148+ au_hn_inode_unlock(a->h_root);
f2c43d5f 23149+ if (au_ftest_ren(a->auren_flags, MNT_WRITE))
86dc4139 23150+ vfsub_mnt_drop_write(au_br_mnt(a->br));
1308ab2a 23151+}
23152+
4a4d8108 23153+static int au_ren_lock(struct au_ren_args *a)
1308ab2a 23154+{
4a4d8108
AM
23155+ int err;
23156+ unsigned int udba;
1308ab2a 23157+
4a4d8108
AM
23158+ err = 0;
23159+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
23160+ a->src_hdir = au_hi(a->src_dir, a->btgt);
23161+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
23162+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
86dc4139
AM
23163+
23164+ err = vfsub_mnt_want_write(au_br_mnt(a->br));
23165+ if (unlikely(err))
23166+ goto out;
f2c43d5f 23167+ au_fset_ren(a->auren_flags, MNT_WRITE);
8b6a4947
AM
23168+ if (au_ftest_ren(a->auren_flags, DIRREN)) {
23169+ struct dentry *root;
23170+ struct inode *dir;
23171+
23172+ /*
23173+ * sbinfo is already locked, so this ii_read_lock is
23174+ * unnecessary. but our debugging feature checks it.
23175+ */
23176+ root = a->src_inode->i_sb->s_root;
23177+ if (root != a->src_parent && root != a->dst_parent) {
23178+ dir = d_inode(root);
23179+ ii_read_lock_parent3(dir);
23180+ a->h_root = au_hi(dir, a->btgt);
23181+ ii_read_unlock(dir);
23182+ au_hn_inode_lock_nested(a->h_root, AuLsc_I_PARENT3);
23183+ }
23184+ }
4a4d8108
AM
23185+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
23186+ a->dst_h_parent, a->dst_hdir);
23187+ udba = au_opt_udba(a->src_dentry->d_sb);
5527c038
JR
23188+ if (unlikely(a->src_hdir->hi_inode != d_inode(a->src_h_parent)
23189+ || a->dst_hdir->hi_inode != d_inode(a->dst_h_parent)))
4a4d8108 23190+ err = au_busy_or_stale();
5afbbe0d 23191+ if (!err && au_dbtop(a->src_dentry) == a->btgt)
4a4d8108 23192+ err = au_h_verify(a->src_h_dentry, udba,
5527c038 23193+ d_inode(a->src_h_parent), a->src_h_parent,
4a4d8108 23194+ a->br);
5afbbe0d 23195+ if (!err && au_dbtop(a->dst_dentry) == a->btgt)
4a4d8108 23196+ err = au_h_verify(a->dst_h_dentry, udba,
5527c038 23197+ d_inode(a->dst_h_parent), a->dst_h_parent,
4a4d8108 23198+ a->br);
86dc4139 23199+ if (!err)
4a4d8108 23200+ goto out; /* success */
4a4d8108
AM
23201+
23202+ err = au_busy_or_stale();
4a4d8108 23203+ au_ren_unlock(a);
86dc4139 23204+
4f0767ce 23205+out:
4a4d8108 23206+ return err;
1facf9fc 23207+}
23208+
23209+/* ---------------------------------------------------------------------- */
23210+
4a4d8108 23211+static void au_ren_refresh_dir(struct au_ren_args *a)
1facf9fc 23212+{
4a4d8108 23213+ struct inode *dir;
dece6358 23214+
4a4d8108 23215+ dir = a->dst_dir;
be118d29 23216+ inode_inc_iversion(dir);
f2c43d5f 23217+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) {
4a4d8108
AM
23218+ /* is this updating defined in POSIX? */
23219+ au_cpup_attr_timesizes(a->src_inode);
23220+ au_cpup_attr_nlink(dir, /*force*/1);
4a4d8108 23221+ }
b912730e 23222+ au_dir_ts(dir, a->btgt);
dece6358 23223+
f2c43d5f
AM
23224+ if (a->exchange) {
23225+ dir = a->src_dir;
be118d29 23226+ inode_inc_iversion(dir);
f2c43d5f
AM
23227+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)) {
23228+ /* is this updating defined in POSIX? */
23229+ au_cpup_attr_timesizes(a->dst_inode);
23230+ au_cpup_attr_nlink(dir, /*force*/1);
23231+ }
23232+ au_dir_ts(dir, a->btgt);
23233+ }
23234+
23235+ if (au_ftest_ren(a->auren_flags, ISSAMEDIR))
4a4d8108 23236+ return;
dece6358 23237+
4a4d8108 23238+ dir = a->src_dir;
be118d29 23239+ inode_inc_iversion(dir);
f2c43d5f 23240+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC))
4a4d8108 23241+ au_cpup_attr_nlink(dir, /*force*/1);
b912730e 23242+ au_dir_ts(dir, a->btgt);
1facf9fc 23243+}
23244+
4a4d8108 23245+static void au_ren_refresh(struct au_ren_args *a)
1facf9fc 23246+{
5afbbe0d 23247+ aufs_bindex_t bbot, bindex;
4a4d8108
AM
23248+ struct dentry *d, *h_d;
23249+ struct inode *i, *h_i;
23250+ struct super_block *sb;
dece6358 23251+
027c5e7a
AM
23252+ d = a->dst_dentry;
23253+ d_drop(d);
23254+ if (a->h_dst)
23255+ /* already dget-ed by au_ren_or_cpup() */
23256+ au_set_h_dptr(d, a->btgt, a->h_dst);
23257+
23258+ i = a->dst_inode;
23259+ if (i) {
f2c43d5f
AM
23260+ if (!a->exchange) {
23261+ if (!au_ftest_ren(a->auren_flags, ISDIR_DST))
23262+ vfsub_drop_nlink(i);
23263+ else {
23264+ vfsub_dead_dir(i);
23265+ au_cpup_attr_timesizes(i);
23266+ }
23267+ au_update_dbrange(d, /*do_put_zero*/1);
23268+ } else
23269+ au_cpup_attr_nlink(i, /*force*/1);
027c5e7a 23270+ } else {
5afbbe0d
AM
23271+ bbot = a->btgt;
23272+ for (bindex = au_dbtop(d); bindex < bbot; bindex++)
027c5e7a 23273+ au_set_h_dptr(d, bindex, NULL);
5afbbe0d
AM
23274+ bbot = au_dbbot(d);
23275+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++)
027c5e7a
AM
23276+ au_set_h_dptr(d, bindex, NULL);
23277+ au_update_dbrange(d, /*do_put_zero*/0);
23278+ }
23279+
8b6a4947
AM
23280+ if (a->exchange
23281+ || au_ftest_ren(a->auren_flags, DIRREN)) {
23282+ d_drop(a->src_dentry);
23283+ if (au_ftest_ren(a->auren_flags, DIRREN))
23284+ au_set_dbwh(a->src_dentry, -1);
23285+ return;
23286+ }
23287+
4a4d8108 23288+ d = a->src_dentry;
8b6a4947
AM
23289+ au_set_dbwh(d, -1);
23290+ bbot = au_dbbot(d);
23291+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) {
23292+ h_d = au_h_dptr(d, bindex);
23293+ if (h_d)
23294+ au_set_h_dptr(d, bindex, NULL);
23295+ }
23296+ au_set_dbbot(d, a->btgt);
4a4d8108 23297+
8b6a4947
AM
23298+ sb = d->d_sb;
23299+ i = a->src_inode;
23300+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
23301+ return; /* success */
4a4d8108 23302+
8b6a4947
AM
23303+ bbot = au_ibbot(i);
23304+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) {
23305+ h_i = au_h_iptr(i, bindex);
23306+ if (h_i) {
23307+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
23308+ /* ignore this error */
23309+ au_set_h_iptr(i, bindex, NULL, 0);
4a4d8108
AM
23310+ }
23311+ }
8b6a4947 23312+ au_set_ibbot(i, a->btgt);
1308ab2a 23313+}
dece6358 23314+
4a4d8108
AM
23315+/* ---------------------------------------------------------------------- */
23316+
23317+/* mainly for link(2) and rename(2) */
23318+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
1308ab2a 23319+{
4a4d8108
AM
23320+ aufs_bindex_t bdiropq, bwh;
23321+ struct dentry *parent;
23322+ struct au_branch *br;
23323+
23324+ parent = dentry->d_parent;
5527c038 23325+ IMustLock(d_inode(parent)); /* dir is locked */
4a4d8108
AM
23326+
23327+ bdiropq = au_dbdiropq(parent);
23328+ bwh = au_dbwh(dentry);
23329+ br = au_sbr(dentry->d_sb, btgt);
23330+ if (au_br_rdonly(br)
23331+ || (0 <= bdiropq && bdiropq < btgt)
23332+ || (0 <= bwh && bwh < btgt))
23333+ btgt = -1;
23334+
23335+ AuDbg("btgt %d\n", btgt);
23336+ return btgt;
1facf9fc 23337+}
23338+
5afbbe0d 23339+/* sets src_btop, dst_btop and btgt */
4a4d8108 23340+static int au_ren_wbr(struct au_ren_args *a)
1facf9fc 23341+{
4a4d8108
AM
23342+ int err;
23343+ struct au_wr_dir_args wr_dir_args = {
23344+ /* .force_btgt = -1, */
23345+ .flags = AuWrDir_ADD_ENTRY
23346+ };
dece6358 23347+
5afbbe0d
AM
23348+ a->src_btop = au_dbtop(a->src_dentry);
23349+ a->dst_btop = au_dbtop(a->dst_dentry);
f2c43d5f
AM
23350+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)
23351+ || au_ftest_ren(a->auren_flags, ISDIR_DST))
4a4d8108 23352+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
5afbbe0d
AM
23353+ wr_dir_args.force_btgt = a->src_btop;
23354+ if (a->dst_inode && a->dst_btop < a->src_btop)
23355+ wr_dir_args.force_btgt = a->dst_btop;
4a4d8108
AM
23356+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
23357+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
23358+ a->btgt = err;
f2c43d5f
AM
23359+ if (a->exchange)
23360+ au_update_dbtop(a->dst_dentry);
dece6358 23361+
4a4d8108 23362+ return err;
1facf9fc 23363+}
23364+
4a4d8108 23365+static void au_ren_dt(struct au_ren_args *a)
1facf9fc 23366+{
4a4d8108
AM
23367+ a->h_path.dentry = a->src_h_parent;
23368+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
f2c43d5f 23369+ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR)) {
4a4d8108
AM
23370+ a->h_path.dentry = a->dst_h_parent;
23371+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
23372+ }
1facf9fc 23373+
f2c43d5f
AM
23374+ au_fclr_ren(a->auren_flags, DT_DSTDIR);
23375+ if (!au_ftest_ren(a->auren_flags, ISDIR_SRC)
23376+ && !a->exchange)
4a4d8108 23377+ return;
dece6358 23378+
4a4d8108
AM
23379+ a->h_path.dentry = a->src_h_dentry;
23380+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
5527c038 23381+ if (d_is_positive(a->dst_h_dentry)) {
f2c43d5f 23382+ au_fset_ren(a->auren_flags, DT_DSTDIR);
4a4d8108
AM
23383+ a->h_path.dentry = a->dst_h_dentry;
23384+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
23385+ }
1308ab2a 23386+}
dece6358 23387+
4a4d8108 23388+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1308ab2a 23389+{
4a4d8108 23390+ struct dentry *h_d;
febd17d6 23391+ struct inode *h_inode;
4a4d8108
AM
23392+
23393+ au_dtime_revert(a->src_dt + AuPARENT);
f2c43d5f 23394+ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR))
4a4d8108
AM
23395+ au_dtime_revert(a->dst_dt + AuPARENT);
23396+
f2c43d5f 23397+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) && err != -EIO) {
4a4d8108 23398+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
febd17d6
JR
23399+ h_inode = d_inode(h_d);
23400+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 23401+ au_dtime_revert(a->src_dt + AuCHILD);
febd17d6 23402+ inode_unlock(h_inode);
4a4d8108 23403+
f2c43d5f 23404+ if (au_ftest_ren(a->auren_flags, DT_DSTDIR)) {
4a4d8108 23405+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
febd17d6
JR
23406+ h_inode = d_inode(h_d);
23407+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 23408+ au_dtime_revert(a->dst_dt + AuCHILD);
febd17d6 23409+ inode_unlock(h_inode);
1facf9fc 23410+ }
23411+ }
23412+}
23413+
4a4d8108
AM
23414+/* ---------------------------------------------------------------------- */
23415+
0b2a12c6
JR
23416+int aufs_rename(struct user_namespace *userns,
23417+ struct inode *_src_dir, struct dentry *_src_dentry,
f2c43d5f
AM
23418+ struct inode *_dst_dir, struct dentry *_dst_dentry,
23419+ unsigned int _flags)
1facf9fc 23420+{
f2c43d5f 23421+ int err, lock_flags;
8b6a4947 23422+ void *rev;
4a4d8108
AM
23423+ /* reduce stack space */
23424+ struct au_ren_args *a;
f2c43d5f 23425+ struct au_pin pin;
4a4d8108 23426+
f2c43d5f 23427+ AuDbg("%pd, %pd, 0x%x\n", _src_dentry, _dst_dentry, _flags);
4a4d8108
AM
23428+ IMustLock(_src_dir);
23429+ IMustLock(_dst_dir);
23430+
f2c43d5f
AM
23431+ err = -EINVAL;
23432+ if (unlikely(_flags & RENAME_WHITEOUT))
23433+ goto out;
23434+
4a4d8108
AM
23435+ err = -ENOMEM;
23436+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
23437+ a = kzalloc(sizeof(*a), GFP_NOFS);
23438+ if (unlikely(!a))
23439+ goto out;
23440+
f2c43d5f 23441+ a->flags = _flags;
acd2b654
AM
23442+ BUILD_BUG_ON(sizeof(a->exchange) == sizeof(u8)
23443+ && RENAME_EXCHANGE > U8_MAX);
f2c43d5f 23444+ a->exchange = _flags & RENAME_EXCHANGE;
4a4d8108
AM
23445+ a->src_dir = _src_dir;
23446+ a->src_dentry = _src_dentry;
5527c038
JR
23447+ a->src_inode = NULL;
23448+ if (d_really_is_positive(a->src_dentry))
23449+ a->src_inode = d_inode(a->src_dentry);
4a4d8108
AM
23450+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
23451+ a->dst_dir = _dst_dir;
23452+ a->dst_dentry = _dst_dentry;
5527c038
JR
23453+ a->dst_inode = NULL;
23454+ if (d_really_is_positive(a->dst_dentry))
23455+ a->dst_inode = d_inode(a->dst_dentry);
4a4d8108
AM
23456+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
23457+ if (a->dst_inode) {
f2c43d5f
AM
23458+ /*
23459+ * if EXCHANGE && src is non-dir && dst is dir,
23460+ * dst is not locked.
23461+ */
23462+ /* IMustLock(a->dst_inode); */
4a4d8108 23463+ au_igrab(a->dst_inode);
1facf9fc 23464+ }
1facf9fc 23465+
4a4d8108 23466+ err = -ENOTDIR;
f2c43d5f 23467+ lock_flags = AuLock_FLUSH | AuLock_NOPLM | AuLock_GEN;
2000de60 23468+ if (d_is_dir(a->src_dentry)) {
f2c43d5f
AM
23469+ au_fset_ren(a->auren_flags, ISDIR_SRC);
23470+ if (unlikely(!a->exchange
23471+ && d_really_is_positive(a->dst_dentry)
2000de60 23472+ && !d_is_dir(a->dst_dentry)))
4a4d8108 23473+ goto out_free;
f2c43d5f
AM
23474+ lock_flags |= AuLock_DIRS;
23475+ }
23476+ if (a->dst_inode && d_is_dir(a->dst_dentry)) {
23477+ au_fset_ren(a->auren_flags, ISDIR_DST);
23478+ if (unlikely(!a->exchange
23479+ && d_really_is_positive(a->src_dentry)
23480+ && !d_is_dir(a->src_dentry)))
23481+ goto out_free;
23482+ lock_flags |= AuLock_DIRS;
b95c5147 23483+ }
8b6a4947
AM
23484+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
23485+ lock_flags);
e49829fe
JR
23486+ if (unlikely(err))
23487+ goto out_free;
1facf9fc 23488+
027c5e7a
AM
23489+ err = au_d_hashed_positive(a->src_dentry);
23490+ if (unlikely(err))
23491+ goto out_unlock;
23492+ err = -ENOENT;
23493+ if (a->dst_inode) {
23494+ /*
f2c43d5f 23495+ * If it is a dir, VFS unhash it before this
027c5e7a
AM
23496+ * function. It means we cannot rely upon d_unhashed().
23497+ */
23498+ if (unlikely(!a->dst_inode->i_nlink))
23499+ goto out_unlock;
f2c43d5f 23500+ if (!au_ftest_ren(a->auren_flags, ISDIR_DST)) {
027c5e7a 23501+ err = au_d_hashed_positive(a->dst_dentry);
f2c43d5f 23502+ if (unlikely(err && !a->exchange))
027c5e7a
AM
23503+ goto out_unlock;
23504+ } else if (unlikely(IS_DEADDIR(a->dst_inode)))
23505+ goto out_unlock;
23506+ } else if (unlikely(d_unhashed(a->dst_dentry)))
23507+ goto out_unlock;
23508+
7eafdf33
AM
23509+ /*
23510+ * is it possible?
79b8bda9 23511+ * yes, it happened (in linux-3.3-rcN) but I don't know why.
7eafdf33
AM
23512+ * there may exist a problem somewhere else.
23513+ */
23514+ err = -EINVAL;
5527c038 23515+ if (unlikely(d_inode(a->dst_parent) == d_inode(a->src_dentry)))
7eafdf33
AM
23516+ goto out_unlock;
23517+
f2c43d5f 23518+ au_fset_ren(a->auren_flags, ISSAMEDIR); /* temporary */
4a4d8108 23519+ di_write_lock_parent(a->dst_parent);
1facf9fc 23520+
4a4d8108
AM
23521+ /* which branch we process */
23522+ err = au_ren_wbr(a);
23523+ if (unlikely(err < 0))
027c5e7a 23524+ goto out_parent;
4a4d8108 23525+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
86dc4139 23526+ a->h_path.mnt = au_br_mnt(a->br);
1facf9fc 23527+
4a4d8108
AM
23528+ /* are they available to be renamed */
23529+ err = au_ren_may_dir(a);
23530+ if (unlikely(err))
23531+ goto out_children;
1facf9fc 23532+
4a4d8108 23533+ /* prepare the writable parent dir on the same branch */
5afbbe0d 23534+ if (a->dst_btop == a->btgt) {
f2c43d5f 23535+ au_fset_ren(a->auren_flags, WHDST);
4a4d8108
AM
23536+ } else {
23537+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
23538+ if (unlikely(err))
23539+ goto out_children;
23540+ }
1facf9fc 23541+
f2c43d5f
AM
23542+ err = 0;
23543+ if (!a->exchange) {
23544+ if (a->src_dir != a->dst_dir) {
23545+ /*
23546+ * this temporary unlock is safe,
23547+ * because both dir->i_mutex are locked.
23548+ */
23549+ di_write_unlock(a->dst_parent);
23550+ di_write_lock_parent(a->src_parent);
23551+ err = au_wr_dir_need_wh(a->src_dentry,
23552+ au_ftest_ren(a->auren_flags,
23553+ ISDIR_SRC),
23554+ &a->btgt);
23555+ di_write_unlock(a->src_parent);
23556+ di_write_lock2_parent(a->src_parent, a->dst_parent,
23557+ /*isdir*/1);
23558+ au_fclr_ren(a->auren_flags, ISSAMEDIR);
23559+ } else
23560+ err = au_wr_dir_need_wh(a->src_dentry,
23561+ au_ftest_ren(a->auren_flags,
23562+ ISDIR_SRC),
23563+ &a->btgt);
23564+ }
4a4d8108
AM
23565+ if (unlikely(err < 0))
23566+ goto out_children;
23567+ if (err)
f2c43d5f 23568+ au_fset_ren(a->auren_flags, WHSRC);
1facf9fc 23569+
86dc4139 23570+ /* cpup src */
5afbbe0d 23571+ if (a->src_btop != a->btgt) {
86dc4139
AM
23572+ err = au_pin(&pin, a->src_dentry, a->btgt,
23573+ au_opt_udba(a->src_dentry->d_sb),
23574+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
367653fa 23575+ if (!err) {
c2b27bf2
AM
23576+ struct au_cp_generic cpg = {
23577+ .dentry = a->src_dentry,
23578+ .bdst = a->btgt,
5afbbe0d 23579+ .bsrc = a->src_btop,
c2b27bf2
AM
23580+ .len = -1,
23581+ .pin = &pin,
23582+ .flags = AuCpup_DTIME | AuCpup_HOPEN
23583+ };
5afbbe0d 23584+ AuDebugOn(au_dbtop(a->src_dentry) != a->src_btop);
c2b27bf2 23585+ err = au_sio_cpup_simple(&cpg);
367653fa 23586+ au_unpin(&pin);
86dc4139 23587+ }
86dc4139
AM
23588+ if (unlikely(err))
23589+ goto out_children;
5afbbe0d 23590+ a->src_btop = a->btgt;
86dc4139 23591+ a->src_h_dentry = au_h_dptr(a->src_dentry, a->btgt);
f2c43d5f
AM
23592+ if (!a->exchange)
23593+ au_fset_ren(a->auren_flags, WHSRC);
23594+ }
23595+
23596+ /* cpup dst */
23597+ if (a->exchange && a->dst_inode
23598+ && a->dst_btop != a->btgt) {
23599+ err = au_pin(&pin, a->dst_dentry, a->btgt,
23600+ au_opt_udba(a->dst_dentry->d_sb),
23601+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
23602+ if (!err) {
23603+ struct au_cp_generic cpg = {
23604+ .dentry = a->dst_dentry,
23605+ .bdst = a->btgt,
23606+ .bsrc = a->dst_btop,
23607+ .len = -1,
23608+ .pin = &pin,
23609+ .flags = AuCpup_DTIME | AuCpup_HOPEN
23610+ };
23611+ err = au_sio_cpup_simple(&cpg);
23612+ au_unpin(&pin);
23613+ }
23614+ if (unlikely(err))
23615+ goto out_children;
23616+ a->dst_btop = a->btgt;
23617+ a->dst_h_dentry = au_h_dptr(a->dst_dentry, a->btgt);
86dc4139
AM
23618+ }
23619+
4a4d8108
AM
23620+ /* lock them all */
23621+ err = au_ren_lock(a);
23622+ if (unlikely(err))
86dc4139 23623+ /* leave the copied-up one */
4a4d8108 23624+ goto out_children;
1facf9fc 23625+
f2c43d5f
AM
23626+ if (!a->exchange) {
23627+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
23628+ err = au_may_ren(a);
23629+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
23630+ err = -ENAMETOOLONG;
23631+ if (unlikely(err))
23632+ goto out_hdir;
23633+ }
1facf9fc 23634+
4a4d8108
AM
23635+ /* store timestamps to be revertible */
23636+ au_ren_dt(a);
1facf9fc 23637+
8b6a4947
AM
23638+ /* store dirren info */
23639+ if (au_ftest_ren(a->auren_flags, DIRREN)) {
23640+ err = au_dr_rename(a->src_dentry, a->btgt,
23641+ &a->dst_dentry->d_name, &rev);
23642+ AuTraceErr(err);
23643+ if (unlikely(err))
23644+ goto out_dt;
23645+ }
23646+
4a4d8108
AM
23647+ /* here we go */
23648+ err = do_rename(a);
23649+ if (unlikely(err))
8b6a4947
AM
23650+ goto out_dirren;
23651+
23652+ if (au_ftest_ren(a->auren_flags, DIRREN))
23653+ au_dr_rename_fin(a->src_dentry, a->btgt, rev);
4a4d8108
AM
23654+
23655+ /* update dir attributes */
23656+ au_ren_refresh_dir(a);
23657+
23658+ /* dput/iput all lower dentries */
23659+ au_ren_refresh(a);
23660+
23661+ goto out_hdir; /* success */
23662+
8b6a4947
AM
23663+out_dirren:
23664+ if (au_ftest_ren(a->auren_flags, DIRREN))
23665+ au_dr_rename_rev(a->src_dentry, a->btgt, rev);
4f0767ce 23666+out_dt:
4a4d8108 23667+ au_ren_rev_dt(err, a);
4f0767ce 23668+out_hdir:
4a4d8108 23669+ au_ren_unlock(a);
4f0767ce 23670+out_children:
4a4d8108 23671+ au_nhash_wh_free(&a->whlist);
5afbbe0d
AM
23672+ if (err && a->dst_inode && a->dst_btop != a->btgt) {
23673+ AuDbg("btop %d, btgt %d\n", a->dst_btop, a->btgt);
027c5e7a 23674+ au_set_h_dptr(a->dst_dentry, a->btgt, NULL);
5afbbe0d 23675+ au_set_dbtop(a->dst_dentry, a->dst_btop);
4a4d8108 23676+ }
027c5e7a 23677+out_parent:
f2c43d5f 23678+ if (!err) {
8b6a4947
AM
23679+ if (d_unhashed(a->src_dentry))
23680+ au_fset_ren(a->auren_flags, DROPPED_SRC);
23681+ if (d_unhashed(a->dst_dentry))
23682+ au_fset_ren(a->auren_flags, DROPPED_DST);
f2c43d5f
AM
23683+ if (!a->exchange)
23684+ d_move(a->src_dentry, a->dst_dentry);
8b6a4947 23685+ else {
f2c43d5f 23686+ d_exchange(a->src_dentry, a->dst_dentry);
8b6a4947
AM
23687+ if (au_ftest_ren(a->auren_flags, DROPPED_DST))
23688+ d_drop(a->dst_dentry);
23689+ }
23690+ if (au_ftest_ren(a->auren_flags, DROPPED_SRC))
23691+ d_drop(a->src_dentry);
f2c43d5f 23692+ } else {
5afbbe0d 23693+ au_update_dbtop(a->dst_dentry);
027c5e7a
AM
23694+ if (!a->dst_inode)
23695+ d_drop(a->dst_dentry);
23696+ }
f2c43d5f 23697+ if (au_ftest_ren(a->auren_flags, ISSAMEDIR))
4a4d8108
AM
23698+ di_write_unlock(a->dst_parent);
23699+ else
23700+ di_write_unlock2(a->src_parent, a->dst_parent);
027c5e7a 23701+out_unlock:
4a4d8108 23702+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
4f0767ce 23703+out_free:
4a4d8108
AM
23704+ iput(a->dst_inode);
23705+ if (a->thargs)
23706+ au_whtmp_rmdir_free(a->thargs);
9f237c51 23707+ au_kfree_rcu(a);
4f0767ce 23708+out:
4a4d8108
AM
23709+ AuTraceErr(err);
23710+ return err;
1308ab2a 23711+}
7f207e10 23712diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
eca34b5c 23713--- /usr/share/empty/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
319657f6 23714+++ linux/fs/aufs/Kconfig 2021-12-03 15:38:59.929980643 +0100
2121bcd9
AM
23715@@ -0,0 +1,199 @@
23716+# SPDX-License-Identifier: GPL-2.0
4a4d8108
AM
23717+config AUFS_FS
23718+ tristate "Aufs (Advanced multi layered unification filesystem) support"
4a4d8108
AM
23719+ help
23720+ Aufs is a stackable unification filesystem such as Unionfs,
23721+ which unifies several directories and provides a merged single
23722+ directory.
23723+ In the early days, aufs was entirely re-designed and
23724+ re-implemented Unionfs Version 1.x series. Introducing many
23725+ original ideas, approaches and improvements, it becomes totally
23726+ different from Unionfs while keeping the basic features.
1facf9fc 23727+
4a4d8108
AM
23728+if AUFS_FS
23729+choice
23730+ prompt "Maximum number of branches"
23731+ default AUFS_BRANCH_MAX_127
23732+ help
23733+ Specifies the maximum number of branches (or member directories)
23734+ in a single aufs. The larger value consumes more system
23735+ resources and has a minor impact to performance.
23736+config AUFS_BRANCH_MAX_127
23737+ bool "127"
23738+ help
23739+ Specifies the maximum number of branches (or member directories)
23740+ in a single aufs. The larger value consumes more system
23741+ resources and has a minor impact to performance.
23742+config AUFS_BRANCH_MAX_511
23743+ bool "511"
23744+ help
23745+ Specifies the maximum number of branches (or member directories)
23746+ in a single aufs. The larger value consumes more system
23747+ resources and has a minor impact to performance.
23748+config AUFS_BRANCH_MAX_1023
23749+ bool "1023"
23750+ help
23751+ Specifies the maximum number of branches (or member directories)
23752+ in a single aufs. The larger value consumes more system
23753+ resources and has a minor impact to performance.
23754+config AUFS_BRANCH_MAX_32767
23755+ bool "32767"
23756+ help
23757+ Specifies the maximum number of branches (or member directories)
23758+ in a single aufs. The larger value consumes more system
23759+ resources and has a minor impact to performance.
23760+endchoice
1facf9fc 23761+
e49829fe
JR
23762+config AUFS_SBILIST
23763+ bool
23764+ depends on AUFS_MAGIC_SYSRQ || PROC_FS
23765+ default y
23766+ help
23767+ Automatic configuration for internal use.
23768+ When aufs supports Magic SysRq or /proc, enabled automatically.
23769+
4a4d8108
AM
23770+config AUFS_HNOTIFY
23771+ bool "Detect direct branch access (bypassing aufs)"
23772+ help
23773+ If you want to modify files on branches directly, eg. bypassing aufs,
23774+ and want aufs to detect the changes of them fully, then enable this
23775+ option and use 'udba=notify' mount option.
7f207e10 23776+ Currently there is only one available configuration, "fsnotify".
4a4d8108
AM
23777+ It will have a negative impact to the performance.
23778+ See detail in aufs.5.
dece6358 23779+
4a4d8108
AM
23780+choice
23781+ prompt "method" if AUFS_HNOTIFY
23782+ default AUFS_HFSNOTIFY
23783+config AUFS_HFSNOTIFY
23784+ bool "fsnotify"
23785+ select FSNOTIFY
4a4d8108 23786+endchoice
1facf9fc 23787+
4a4d8108
AM
23788+config AUFS_EXPORT
23789+ bool "NFS-exportable aufs"
2cbb1c4b 23790+ depends on EXPORTFS
4a4d8108
AM
23791+ help
23792+ If you want to export your mounted aufs via NFS, then enable this
23793+ option. There are several requirements for this configuration.
23794+ See detail in aufs.5.
1facf9fc 23795+
4a4d8108
AM
23796+config AUFS_INO_T_64
23797+ bool
23798+ depends on AUFS_EXPORT
23799+ depends on 64BIT && !(ALPHA || S390)
23800+ default y
23801+ help
23802+ Automatic configuration for internal use.
23803+ /* typedef unsigned long/int __kernel_ino_t */
23804+ /* alpha and s390x are int */
1facf9fc 23805+
c1595e42
JR
23806+config AUFS_XATTR
23807+ bool "support for XATTR/EA (including Security Labels)"
23808+ help
23809+ If your branch fs supports XATTR/EA and you want to make them
23810+ available in aufs too, then enable this opsion and specify the
23811+ branch attributes for EA.
23812+ See detail in aufs.5.
23813+
076b876e
AM
23814+config AUFS_FHSM
23815+ bool "File-based Hierarchical Storage Management"
23816+ help
23817+ Hierarchical Storage Management (or HSM) is a well-known feature
23818+ in the storage world. Aufs provides this feature as file-based.
23819+ with multiple branches.
23820+ These multiple branches are prioritized, ie. the topmost one
23821+ should be the fastest drive and be used heavily.
23822+
4a4d8108
AM
23823+config AUFS_RDU
23824+ bool "Readdir in userspace"
23825+ help
23826+ Aufs has two methods to provide a merged view for a directory,
23827+ by a user-space library and by kernel-space natively. The latter
23828+ is always enabled but sometimes large and slow.
23829+ If you enable this option, install the library in aufs2-util
23830+ package, and set some environment variables for your readdir(3),
23831+ then the work will be handled in user-space which generally
23832+ shows better performance in most cases.
23833+ See detail in aufs.5.
1facf9fc 23834+
8b6a4947
AM
23835+config AUFS_DIRREN
23836+ bool "Workaround for rename(2)-ing a directory"
23837+ help
23838+ By default, aufs returns EXDEV error in renameing a dir who has
23839+ his child on the lower branch, since it is a bad idea to issue
23840+ rename(2) internally for every lower branch. But user may not
23841+ accept this behaviour. So here is a workaround to allow such
23842+ rename(2) and store some extra infromation on the writable
23843+ branch. Obviously this costs high (and I don't like it).
23844+ To use this feature, you need to enable this configuration AND
23845+ to specify the mount option `dirren.'
23846+ See details in aufs.5 and the design documents.
23847+
4a4d8108
AM
23848+config AUFS_SHWH
23849+ bool "Show whiteouts"
23850+ help
23851+ If you want to make the whiteouts in aufs visible, then enable
23852+ this option and specify 'shwh' mount option. Although it may
23853+ sounds like philosophy or something, but in technically it
23854+ simply shows the name of whiteout with keeping its behaviour.
1facf9fc 23855+
4a4d8108
AM
23856+config AUFS_BR_RAMFS
23857+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
23858+ help
23859+ If you want to use ramfs as an aufs branch fs, then enable this
23860+ option. Generally tmpfs is recommended.
23861+ Aufs prohibited them to be a branch fs by default, because
23862+ initramfs becomes unusable after switch_root or something
23863+ generally. If you sets initramfs as an aufs branch and boot your
23864+ system by switch_root, you will meet a problem easily since the
23865+ files in initramfs may be inaccessible.
23866+ Unless you are going to use ramfs as an aufs branch fs without
23867+ switch_root or something, leave it N.
1facf9fc 23868+
4a4d8108
AM
23869+config AUFS_BR_FUSE
23870+ bool "Fuse fs as an aufs branch"
23871+ depends on FUSE_FS
23872+ select AUFS_POLL
23873+ help
23874+ If you want to use fuse-based userspace filesystem as an aufs
23875+ branch fs, then enable this option.
23876+ It implements the internal poll(2) operation which is
23877+ implemented by fuse only (curretnly).
1facf9fc 23878+
4a4d8108
AM
23879+config AUFS_POLL
23880+ bool
23881+ help
23882+ Automatic configuration for internal use.
1facf9fc 23883+
4a4d8108
AM
23884+config AUFS_BR_HFSPLUS
23885+ bool "Hfsplus as an aufs branch"
23886+ depends on HFSPLUS_FS
23887+ default y
23888+ help
23889+ If you want to use hfsplus fs as an aufs branch fs, then enable
23890+ this option. This option introduces a small overhead at
23891+ copying-up a file on hfsplus.
1facf9fc 23892+
4a4d8108
AM
23893+config AUFS_BDEV_LOOP
23894+ bool
23895+ depends on BLK_DEV_LOOP
23896+ default y
23897+ help
23898+ Automatic configuration for internal use.
23899+ Convert =[ym] into =y.
1308ab2a 23900+
4a4d8108
AM
23901+config AUFS_DEBUG
23902+ bool "Debug aufs"
23903+ help
23904+ Enable this to compile aufs internal debug code.
23905+ It will have a negative impact to the performance.
23906+
23907+config AUFS_MAGIC_SYSRQ
23908+ bool
23909+ depends on AUFS_DEBUG && MAGIC_SYSRQ
23910+ default y
23911+ help
23912+ Automatic configuration for internal use.
23913+ When aufs supports Magic SysRq, enabled automatically.
23914+endif
acd2b654 23915diff -urN /usr/share/empty/fs/aufs/lcnt.h linux/fs/aufs/lcnt.h
eca34b5c 23916--- /usr/share/empty/fs/aufs/lcnt.h 1970-01-01 01:00:00.000000000 +0100
319657f6 23917+++ linux/fs/aufs/lcnt.h 2021-12-03 15:38:59.936647310 +0100
acd2b654
AM
23918@@ -0,0 +1,186 @@
23919+/* SPDX-License-Identifier: GPL-2.0 */
23920+/*
6d176551 23921+ * Copyright (C) 2018-2021 Junjiro R. Okajima
acd2b654
AM
23922+ *
23923+ * This program, aufs is free software; you can redistribute it and/or modify
23924+ * it under the terms of the GNU General Public License as published by
23925+ * the Free Software Foundation; either version 2 of the License, or
23926+ * (at your option) any later version.
23927+ *
23928+ * This program is distributed in the hope that it will be useful,
23929+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
23930+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23931+ * GNU General Public License for more details.
23932+ *
23933+ * You should have received a copy of the GNU General Public License
23934+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
23935+ */
23936+
23937+/*
23938+ * simple long counter wrapper
23939+ */
23940+
23941+#ifndef __AUFS_LCNT_H__
23942+#define __AUFS_LCNT_H__
23943+
23944+#ifdef __KERNEL__
23945+
23946+#include "debug.h"
23947+
23948+#define AuLCntATOMIC 1
23949+#define AuLCntPCPUCNT 2
23950+/*
23951+ * why does percpu_refcount require extra synchronize_rcu()s in
23952+ * au_br_do_free()
23953+ */
23954+#define AuLCntPCPUREF 3
23955+
23956+/* #define AuLCntChosen AuLCntATOMIC */
23957+#define AuLCntChosen AuLCntPCPUCNT
23958+/* #define AuLCntChosen AuLCntPCPUREF */
23959+
23960+#if AuLCntChosen == AuLCntATOMIC
23961+#include <linux/atomic.h>
23962+
23963+typedef atomic_long_t au_lcnt_t;
23964+
23965+static inline int au_lcnt_init(au_lcnt_t *cnt, void *release __maybe_unused)
23966+{
23967+ atomic_long_set(cnt, 0);
23968+ return 0;
23969+}
23970+
23971+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused)
23972+{
23973+ /* empty */
23974+}
23975+
23976+static inline void au_lcnt_fin(au_lcnt_t *cnt __maybe_unused,
23977+ int do_sync __maybe_unused)
23978+{
23979+ /* empty */
23980+}
23981+
23982+static inline void au_lcnt_inc(au_lcnt_t *cnt)
23983+{
23984+ atomic_long_inc(cnt);
23985+}
23986+
23987+static inline void au_lcnt_dec(au_lcnt_t *cnt)
23988+{
23989+ atomic_long_dec(cnt);
23990+}
23991+
23992+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev __maybe_unused)
23993+{
23994+ return atomic_long_read(cnt);
23995+}
23996+#endif
23997+
23998+#if AuLCntChosen == AuLCntPCPUCNT
23999+#include <linux/percpu_counter.h>
24000+
24001+typedef struct percpu_counter au_lcnt_t;
24002+
24003+static inline int au_lcnt_init(au_lcnt_t *cnt, void *release __maybe_unused)
24004+{
24005+ return percpu_counter_init(cnt, 0, GFP_NOFS);
24006+}
24007+
24008+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused)
24009+{
24010+ /* empty */
24011+}
24012+
24013+static inline void au_lcnt_fin(au_lcnt_t *cnt, int do_sync __maybe_unused)
24014+{
24015+ percpu_counter_destroy(cnt);
24016+}
24017+
24018+static inline void au_lcnt_inc(au_lcnt_t *cnt)
24019+{
24020+ percpu_counter_inc(cnt);
24021+}
24022+
24023+static inline void au_lcnt_dec(au_lcnt_t *cnt)
24024+{
24025+ percpu_counter_dec(cnt);
24026+}
24027+
24028+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev __maybe_unused)
24029+{
24030+ s64 n;
24031+
24032+ n = percpu_counter_sum(cnt);
24033+ BUG_ON(n < 0);
24034+ if (LONG_MAX != LLONG_MAX
24035+ && n > LONG_MAX)
24036+ AuWarn1("%s\n", "wrap-around");
24037+
24038+ return n;
24039+}
24040+#endif
24041+
24042+#if AuLCntChosen == AuLCntPCPUREF
24043+#include <linux/percpu-refcount.h>
24044+
24045+typedef struct percpu_ref au_lcnt_t;
24046+
24047+static inline int au_lcnt_init(au_lcnt_t *cnt, percpu_ref_func_t *release)
24048+{
24049+ if (!release)
24050+ release = percpu_ref_exit;
24051+ return percpu_ref_init(cnt, release, /*percpu mode*/0, GFP_NOFS);
24052+}
24053+
24054+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused)
24055+{
24056+ synchronize_rcu();
24057+}
24058+
24059+static inline void au_lcnt_fin(au_lcnt_t *cnt, int do_sync)
24060+{
24061+ percpu_ref_kill(cnt);
24062+ if (do_sync)
24063+ au_lcnt_wait_for_fin(cnt);
24064+}
24065+
24066+static inline void au_lcnt_inc(au_lcnt_t *cnt)
24067+{
24068+ percpu_ref_get(cnt);
24069+}
24070+
24071+static inline void au_lcnt_dec(au_lcnt_t *cnt)
24072+{
24073+ percpu_ref_put(cnt);
24074+}
24075+
24076+/*
24077+ * avoid calling this func as possible.
24078+ */
24079+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev)
24080+{
24081+ long l;
24082+
24083+ percpu_ref_switch_to_atomic_sync(cnt);
24084+ l = atomic_long_read(&cnt->count);
24085+ if (do_rev)
24086+ percpu_ref_switch_to_percpu(cnt);
24087+
24088+ /* percpu_ref is initialized by 1 instead of 0 */
24089+ return l - 1;
24090+}
24091+#endif
24092+
24093+#ifdef CONFIG_AUFS_DEBUG
24094+#define AuLCntZero(val) do { \
24095+ long l = val; \
24096+ if (l) \
24097+ AuDbg("%s = %ld\n", #val, l); \
24098+} while (0)
24099+#else
24100+#define AuLCntZero(val) do {} while (0)
24101+#endif
24102+
24103+#endif /* __KERNEL__ */
24104+#endif /* __AUFS_LCNT_H__ */
7f207e10 24105diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
eca34b5c 24106--- /usr/share/empty/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100
319657f6 24107+++ linux/fs/aufs/loop.c 2021-12-03 15:38:59.936647310 +0100
062440b3 24108@@ -0,0 +1,148 @@
cd7a4cd9 24109+// SPDX-License-Identifier: GPL-2.0
1facf9fc 24110+/*
6d176551 24111+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 24112+ *
24113+ * This program, aufs is free software; you can redistribute it and/or modify
24114+ * it under the terms of the GNU General Public License as published by
24115+ * the Free Software Foundation; either version 2 of the License, or
24116+ * (at your option) any later version.
dece6358
AM
24117+ *
24118+ * This program is distributed in the hope that it will be useful,
24119+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24120+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24121+ * GNU General Public License for more details.
24122+ *
24123+ * You should have received a copy of the GNU General Public License
523b37e3 24124+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24125+ */
24126+
24127+/*
24128+ * support for loopback block device as a branch
24129+ */
24130+
1facf9fc 24131+#include "aufs.h"
24132+
392086de
AM
24133+/* added into drivers/block/loop.c */
24134+static struct file *(*backing_file_func)(struct super_block *sb);
24135+
1facf9fc 24136+/*
24137+ * test if two lower dentries have overlapping branches.
24138+ */
b752ccd1 24139+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
1facf9fc 24140+{
b752ccd1 24141+ struct super_block *h_sb;
392086de
AM
24142+ struct file *backing_file;
24143+
24144+ if (unlikely(!backing_file_func)) {
24145+ /* don't load "loop" module here */
24146+ backing_file_func = symbol_get(loop_backing_file);
24147+ if (unlikely(!backing_file_func))
24148+ /* "loop" module is not loaded */
24149+ return 0;
24150+ }
1facf9fc 24151+
b752ccd1 24152+ h_sb = h_adding->d_sb;
392086de
AM
24153+ backing_file = backing_file_func(h_sb);
24154+ if (!backing_file)
1facf9fc 24155+ return 0;
24156+
2000de60 24157+ h_adding = backing_file->f_path.dentry;
b752ccd1
AM
24158+ /*
24159+ * h_adding can be local NFS.
24160+ * in this case aufs cannot detect the loop.
24161+ */
24162+ if (unlikely(h_adding->d_sb == sb))
1facf9fc 24163+ return 1;
b752ccd1 24164+ return !!au_test_subdir(h_adding, sb->s_root);
1facf9fc 24165+}
24166+
24167+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
24168+int au_test_loopback_kthread(void)
24169+{
b752ccd1
AM
24170+ int ret;
24171+ struct task_struct *tsk = current;
a2a7ad62 24172+ char c, comm[sizeof(tsk->comm)];
b752ccd1
AM
24173+
24174+ ret = 0;
24175+ if (tsk->flags & PF_KTHREAD) {
a2a7ad62
AM
24176+ get_task_comm(comm, tsk);
24177+ c = comm[4];
b752ccd1 24178+ ret = ('0' <= c && c <= '9'
a2a7ad62 24179+ && !strncmp(comm, "loop", 4));
b752ccd1 24180+ }
1facf9fc 24181+
b752ccd1 24182+ return ret;
1facf9fc 24183+}
87a755f4
AM
24184+
24185+/* ---------------------------------------------------------------------- */
24186+
24187+#define au_warn_loopback_step 16
24188+static int au_warn_loopback_nelem = au_warn_loopback_step;
24189+static unsigned long *au_warn_loopback_array;
24190+
24191+void au_warn_loopback(struct super_block *h_sb)
24192+{
24193+ int i, new_nelem;
24194+ unsigned long *a, magic;
24195+ static DEFINE_SPINLOCK(spin);
24196+
24197+ magic = h_sb->s_magic;
24198+ spin_lock(&spin);
24199+ a = au_warn_loopback_array;
24200+ for (i = 0; i < au_warn_loopback_nelem && *a; i++)
24201+ if (a[i] == magic) {
24202+ spin_unlock(&spin);
24203+ return;
24204+ }
24205+
24206+ /* h_sb is new to us, print it */
24207+ if (i < au_warn_loopback_nelem) {
24208+ a[i] = magic;
24209+ goto pr;
24210+ }
24211+
24212+ /* expand the array */
24213+ new_nelem = au_warn_loopback_nelem + au_warn_loopback_step;
24214+ a = au_kzrealloc(au_warn_loopback_array,
24215+ au_warn_loopback_nelem * sizeof(unsigned long),
e2f27e51
AM
24216+ new_nelem * sizeof(unsigned long), GFP_ATOMIC,
24217+ /*may_shrink*/0);
87a755f4
AM
24218+ if (a) {
24219+ au_warn_loopback_nelem = new_nelem;
24220+ au_warn_loopback_array = a;
24221+ a[i] = magic;
24222+ goto pr;
24223+ }
24224+
24225+ spin_unlock(&spin);
24226+ AuWarn1("realloc failed, ignored\n");
24227+ return;
24228+
24229+pr:
24230+ spin_unlock(&spin);
0c3ec466
AM
24231+ pr_warn("you may want to try another patch for loopback file "
24232+ "on %s(0x%lx) branch\n", au_sbtype(h_sb), magic);
87a755f4
AM
24233+}
24234+
24235+int au_loopback_init(void)
24236+{
24237+ int err;
24238+ struct super_block *sb __maybe_unused;
24239+
fbc438ed 24240+ BUILD_BUG_ON(sizeof(sb->s_magic) != sizeof(*au_warn_loopback_array));
87a755f4
AM
24241+
24242+ err = 0;
24243+ au_warn_loopback_array = kcalloc(au_warn_loopback_step,
24244+ sizeof(unsigned long), GFP_NOFS);
24245+ if (unlikely(!au_warn_loopback_array))
24246+ err = -ENOMEM;
24247+
24248+ return err;
24249+}
24250+
24251+void au_loopback_fin(void)
24252+{
79b8bda9
AM
24253+ if (backing_file_func)
24254+ symbol_put(loop_backing_file);
9f237c51 24255+ au_kfree_try_rcu(au_warn_loopback_array);
87a755f4 24256+}
7f207e10 24257diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
eca34b5c 24258--- /usr/share/empty/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100
319657f6 24259+++ linux/fs/aufs/loop.h 2021-12-03 15:38:59.936647310 +0100
eca801bf 24260@@ -0,0 +1,55 @@
062440b3 24261+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 24262+/*
6d176551 24263+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 24264+ *
24265+ * This program, aufs is free software; you can redistribute it and/or modify
24266+ * it under the terms of the GNU General Public License as published by
24267+ * the Free Software Foundation; either version 2 of the License, or
24268+ * (at your option) any later version.
dece6358
AM
24269+ *
24270+ * This program is distributed in the hope that it will be useful,
24271+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24272+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24273+ * GNU General Public License for more details.
24274+ *
24275+ * You should have received a copy of the GNU General Public License
523b37e3 24276+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24277+ */
24278+
24279+/*
24280+ * support for loopback mount as a branch
24281+ */
24282+
24283+#ifndef __AUFS_LOOP_H__
24284+#define __AUFS_LOOP_H__
24285+
24286+#ifdef __KERNEL__
24287+
dece6358
AM
24288+struct dentry;
24289+struct super_block;
1facf9fc 24290+
24291+#ifdef CONFIG_AUFS_BDEV_LOOP
392086de
AM
24292+/* drivers/block/loop.c */
24293+struct file *loop_backing_file(struct super_block *sb);
24294+
1facf9fc 24295+/* loop.c */
b752ccd1 24296+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
1facf9fc 24297+int au_test_loopback_kthread(void);
87a755f4
AM
24298+void au_warn_loopback(struct super_block *h_sb);
24299+
24300+int au_loopback_init(void);
24301+void au_loopback_fin(void);
1facf9fc 24302+#else
83b672a5 24303+AuStub(struct file *, loop_backing_file, return NULL, struct super_block *sb)
eca801bf 24304+
4a4d8108 24305+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
b752ccd1 24306+ struct dentry *h_adding)
4a4d8108 24307+AuStubInt0(au_test_loopback_kthread, void)
87a755f4
AM
24308+AuStubVoid(au_warn_loopback, struct super_block *h_sb)
24309+
24310+AuStubInt0(au_loopback_init, void)
24311+AuStubVoid(au_loopback_fin, void)
1facf9fc 24312+#endif /* BLK_DEV_LOOP */
24313+
24314+#endif /* __KERNEL__ */
24315+#endif /* __AUFS_LOOP_H__ */
7f207e10 24316diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
eca34b5c 24317--- /usr/share/empty/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100
319657f6 24318+++ linux/fs/aufs/magic.mk 2021-12-03 15:38:59.936647310 +0100
2121bcd9
AM
24319@@ -0,0 +1,31 @@
24320+# SPDX-License-Identifier: GPL-2.0
1facf9fc 24321+
24322+# defined in ${srctree}/fs/fuse/inode.c
24323+# tristate
24324+ifdef CONFIG_FUSE_FS
24325+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
24326+endif
24327+
1facf9fc 24328+# defined in ${srctree}/fs/xfs/xfs_sb.h
24329+# tristate
24330+ifdef CONFIG_XFS_FS
24331+ccflags-y += -DXFS_SB_MAGIC=0x58465342
24332+endif
24333+
24334+# defined in ${srctree}/fs/configfs/mount.c
24335+# tristate
24336+ifdef CONFIG_CONFIGFS_FS
24337+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
24338+endif
24339+
1facf9fc 24340+# defined in ${srctree}/fs/ubifs/ubifs.h
24341+# tristate
24342+ifdef CONFIG_UBIFS_FS
24343+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
24344+endif
4a4d8108
AM
24345+
24346+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
24347+# tristate
24348+ifdef CONFIG_HFSPLUS_FS
24349+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
24350+endif
7f207e10 24351diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
eca34b5c 24352--- /usr/share/empty/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
319657f6 24353+++ linux/fs/aufs/Makefile 2021-12-03 15:38:59.929980643 +0100
2121bcd9
AM
24354@@ -0,0 +1,46 @@
24355+# SPDX-License-Identifier: GPL-2.0
4a4d8108
AM
24356+
24357+include ${src}/magic.mk
24358+ifeq (${CONFIG_AUFS_FS},m)
24359+include ${src}/conf.mk
24360+endif
24361+-include ${src}/priv_def.mk
24362+
24363+# cf. include/linux/kernel.h
24364+# enable pr_debug
24365+ccflags-y += -DDEBUG
f6c5ef8b
AM
24366+# sparse requires the full pathname
24367+ifdef M
523b37e3 24368+ccflags-y += -include ${M}/../../include/uapi/linux/aufs_type.h
f6c5ef8b 24369+else
523b37e3 24370+ccflags-y += -include ${srctree}/include/uapi/linux/aufs_type.h
f6c5ef8b 24371+endif
4a4d8108
AM
24372+
24373+obj-$(CONFIG_AUFS_FS) += aufs.o
24374+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
24375+ wkq.o vfsub.o dcsub.o \
e49829fe 24376+ cpup.o whout.o wbr_policy.o \
4a4d8108
AM
24377+ dinfo.o dentry.o \
24378+ dynop.o \
24379+ finfo.o file.o f_op.o \
24380+ dir.o vdir.o \
24381+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
c2b27bf2 24382+ mvdown.o ioctl.o
4a4d8108
AM
24383+
24384+# all are boolean
e49829fe 24385+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o
4a4d8108
AM
24386+aufs-$(CONFIG_SYSFS) += sysfs.o
24387+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
24388+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
24389+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
24390+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
4a4d8108 24391+aufs-$(CONFIG_AUFS_EXPORT) += export.o
c1595e42
JR
24392+aufs-$(CONFIG_AUFS_XATTR) += xattr.o
24393+aufs-$(CONFIG_FS_POSIX_ACL) += posix_acl.o
8b6a4947 24394+aufs-$(CONFIG_AUFS_DIRREN) += dirren.o
076b876e 24395+aufs-$(CONFIG_AUFS_FHSM) += fhsm.o
4a4d8108
AM
24396+aufs-$(CONFIG_AUFS_POLL) += poll.o
24397+aufs-$(CONFIG_AUFS_RDU) += rdu.o
4a4d8108
AM
24398+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
24399+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
24400+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
7f207e10 24401diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
eca34b5c 24402--- /usr/share/empty/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
319657f6 24403+++ linux/fs/aufs/module.c 2021-12-03 15:38:59.936647310 +0100
062440b3 24404@@ -0,0 +1,273 @@
cd7a4cd9 24405+// SPDX-License-Identifier: GPL-2.0
1facf9fc 24406+/*
6d176551 24407+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 24408+ *
24409+ * This program, aufs is free software; you can redistribute it and/or modify
24410+ * it under the terms of the GNU General Public License as published by
24411+ * the Free Software Foundation; either version 2 of the License, or
24412+ * (at your option) any later version.
dece6358
AM
24413+ *
24414+ * This program is distributed in the hope that it will be useful,
24415+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24416+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24417+ * GNU General Public License for more details.
24418+ *
24419+ * You should have received a copy of the GNU General Public License
523b37e3 24420+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24421+ */
24422+
24423+/*
24424+ * module global variables and operations
24425+ */
24426+
24427+#include <linux/module.h>
24428+#include <linux/seq_file.h>
24429+#include "aufs.h"
24430+
e2f27e51
AM
24431+/* shrinkable realloc */
24432+void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink)
1facf9fc 24433+{
e2f27e51
AM
24434+ size_t sz;
24435+ int diff;
1facf9fc 24436+
e2f27e51
AM
24437+ sz = 0;
24438+ diff = -1;
24439+ if (p) {
24440+#if 0 /* unused */
24441+ if (!new_sz) {
9f237c51 24442+ au_kfree_rcu(p);
e2f27e51
AM
24443+ p = NULL;
24444+ goto out;
24445+ }
24446+#else
24447+ AuDebugOn(!new_sz);
24448+#endif
24449+ sz = ksize(p);
24450+ diff = au_kmidx_sub(sz, new_sz);
24451+ }
24452+ if (sz && !diff)
24453+ goto out;
24454+
24455+ if (sz < new_sz)
24456+ /* expand or SLOB */
24457+ p = krealloc(p, new_sz, gfp);
24458+ else if (new_sz < sz && may_shrink) {
24459+ /* shrink */
24460+ void *q;
24461+
24462+ q = kmalloc(new_sz, gfp);
24463+ if (q) {
24464+ if (p) {
24465+ memcpy(q, p, new_sz);
9f237c51 24466+ au_kfree_try_rcu(p);
e2f27e51
AM
24467+ }
24468+ p = q;
24469+ } else
24470+ p = NULL;
24471+ }
24472+
24473+out:
24474+ return p;
24475+}
24476+
24477+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp,
24478+ int may_shrink)
24479+{
24480+ p = au_krealloc(p, new_sz, gfp, may_shrink);
24481+ if (p && new_sz > nused)
1facf9fc 24482+ memset(p + nused, 0, new_sz - nused);
24483+ return p;
24484+}
24485+
24486+/* ---------------------------------------------------------------------- */
1facf9fc 24487+/*
24488+ * aufs caches
24489+ */
1c60b727 24490+struct kmem_cache *au_cache[AuCache_Last];
5afbbe0d
AM
24491+
24492+static void au_cache_fin(void)
24493+{
24494+ int i;
24495+
24496+ /*
24497+ * Make sure all delayed rcu free inodes are flushed before we
24498+ * destroy cache.
24499+ */
24500+ rcu_barrier();
24501+
24502+ /* excluding AuCache_HNOTIFY */
24503+ BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last);
24504+ for (i = 0; i < AuCache_HNOTIFY; i++) {
1c60b727
AM
24505+ kmem_cache_destroy(au_cache[i]);
24506+ au_cache[i] = NULL;
5afbbe0d
AM
24507+ }
24508+}
24509+
1facf9fc 24510+static int __init au_cache_init(void)
24511+{
1c60b727
AM
24512+ au_cache[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
24513+ if (au_cache[AuCache_DINFO])
027c5e7a 24514+ /* SLAB_DESTROY_BY_RCU */
1c60b727 24515+ au_cache[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
f0c0a007 24516+ au_icntnr_init_once);
1c60b727
AM
24517+ if (au_cache[AuCache_ICNTNR])
24518+ au_cache[AuCache_FINFO] = AuCacheCtor(au_finfo,
f0c0a007 24519+ au_fi_init_once);
1c60b727
AM
24520+ if (au_cache[AuCache_FINFO])
24521+ au_cache[AuCache_VDIR] = AuCache(au_vdir);
24522+ if (au_cache[AuCache_VDIR])
24523+ au_cache[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
24524+ if (au_cache[AuCache_DEHSTR])
1facf9fc 24525+ return 0;
24526+
5afbbe0d 24527+ au_cache_fin();
1facf9fc 24528+ return -ENOMEM;
24529+}
24530+
1facf9fc 24531+/* ---------------------------------------------------------------------- */
24532+
24533+int au_dir_roflags;
24534+
e49829fe 24535+#ifdef CONFIG_AUFS_SBILIST
1e00d052
AM
24536+/*
24537+ * iterate_supers_type() doesn't protect us from
24538+ * remounting (branch management)
24539+ */
8b6a4947 24540+struct hlist_bl_head au_sbilist;
e49829fe
JR
24541+#endif
24542+
1facf9fc 24543+/*
24544+ * functions for module interface.
24545+ */
24546+MODULE_LICENSE("GPL");
24547+/* MODULE_LICENSE("GPL v2"); */
dece6358 24548+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 24549+MODULE_DESCRIPTION(AUFS_NAME
24550+ " -- Advanced multi layered unification filesystem");
24551+MODULE_VERSION(AUFS_VERSION);
c06a8ce3 24552+MODULE_ALIAS_FS(AUFS_NAME);
1facf9fc 24553+
1facf9fc 24554+/* this module parameter has no meaning when SYSFS is disabled */
24555+int sysaufs_brs = 1;
24556+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
cd7a4cd9 24557+module_param_named(brs, sysaufs_brs, int, 0444);
1facf9fc 24558+
076b876e 24559+/* this module parameter has no meaning when USER_NS is disabled */
8cdd5066 24560+bool au_userns;
076b876e 24561+MODULE_PARM_DESC(allow_userns, "allow unprivileged to mount under userns");
cd7a4cd9 24562+module_param_named(allow_userns, au_userns, bool, 0444);
076b876e 24563+
1facf9fc 24564+/* ---------------------------------------------------------------------- */
24565+
24566+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
24567+
24568+int au_seq_path(struct seq_file *seq, struct path *path)
24569+{
79b8bda9
AM
24570+ int err;
24571+
24572+ err = seq_path(seq, path, au_esc_chars);
1c60b727 24573+ if (err >= 0)
79b8bda9 24574+ err = 0;
1c60b727 24575+ else
79b8bda9
AM
24576+ err = -ENOMEM;
24577+
24578+ return err;
1facf9fc 24579+}
24580+
24581+/* ---------------------------------------------------------------------- */
24582+
24583+static int __init aufs_init(void)
24584+{
24585+ int err, i;
24586+ char *p;
24587+
24588+ p = au_esc_chars;
24589+ for (i = 1; i <= ' '; i++)
24590+ *p++ = i;
24591+ *p++ = '\\';
24592+ *p++ = '\x7f';
24593+ *p = 0;
24594+
24595+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
24596+
b95c5147
AM
24597+ memcpy(aufs_iop_nogetattr, aufs_iop, sizeof(aufs_iop));
24598+ for (i = 0; i < AuIop_Last; i++)
24599+ aufs_iop_nogetattr[i].getattr = NULL;
24600+
1c60b727 24601+ memset(au_cache, 0, sizeof(au_cache)); /* including hnotify */
f0c0a007 24602+
e49829fe 24603+ au_sbilist_init();
1facf9fc 24604+ sysaufs_brs_init();
24605+ au_debug_init();
4a4d8108 24606+ au_dy_init();
1facf9fc 24607+ err = sysaufs_init();
24608+ if (unlikely(err))
24609+ goto out;
062440b3 24610+ err = dbgaufs_init();
4f0767ce 24611+ if (unlikely(err))
953406b4 24612+ goto out_sysaufs;
062440b3
AM
24613+ err = au_procfs_init();
24614+ if (unlikely(err))
24615+ goto out_dbgaufs;
e49829fe
JR
24616+ err = au_wkq_init();
24617+ if (unlikely(err))
24618+ goto out_procfs;
87a755f4 24619+ err = au_loopback_init();
1facf9fc 24620+ if (unlikely(err))
24621+ goto out_wkq;
87a755f4
AM
24622+ err = au_hnotify_init();
24623+ if (unlikely(err))
24624+ goto out_loopback;
1facf9fc 24625+ err = au_sysrq_init();
24626+ if (unlikely(err))
24627+ goto out_hin;
24628+ err = au_cache_init();
24629+ if (unlikely(err))
24630+ goto out_sysrq;
076b876e
AM
24631+
24632+ aufs_fs_type.fs_flags |= au_userns ? FS_USERNS_MOUNT : 0;
1facf9fc 24633+ err = register_filesystem(&aufs_fs_type);
24634+ if (unlikely(err))
24635+ goto out_cache;
076b876e 24636+
4a4d8108
AM
24637+ /* since we define pr_fmt, call printk directly */
24638+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
1facf9fc 24639+ goto out; /* success */
24640+
4f0767ce 24641+out_cache:
1facf9fc 24642+ au_cache_fin();
4f0767ce 24643+out_sysrq:
1facf9fc 24644+ au_sysrq_fin();
4f0767ce 24645+out_hin:
4a4d8108 24646+ au_hnotify_fin();
87a755f4
AM
24647+out_loopback:
24648+ au_loopback_fin();
4f0767ce 24649+out_wkq:
1facf9fc 24650+ au_wkq_fin();
e49829fe
JR
24651+out_procfs:
24652+ au_procfs_fin();
062440b3
AM
24653+out_dbgaufs:
24654+ dbgaufs_fin();
4f0767ce 24655+out_sysaufs:
1facf9fc 24656+ sysaufs_fin();
4a4d8108 24657+ au_dy_fin();
4f0767ce 24658+out:
1facf9fc 24659+ return err;
24660+}
24661+
24662+static void __exit aufs_exit(void)
24663+{
24664+ unregister_filesystem(&aufs_fs_type);
24665+ au_cache_fin();
24666+ au_sysrq_fin();
4a4d8108 24667+ au_hnotify_fin();
87a755f4 24668+ au_loopback_fin();
1facf9fc 24669+ au_wkq_fin();
e49829fe 24670+ au_procfs_fin();
062440b3 24671+ dbgaufs_fin();
1facf9fc 24672+ sysaufs_fin();
4a4d8108 24673+ au_dy_fin();
1facf9fc 24674+}
24675+
24676+module_init(aufs_init);
24677+module_exit(aufs_exit);
7f207e10 24678diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
eca34b5c 24679--- /usr/share/empty/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
319657f6 24680+++ linux/fs/aufs/module.h 2021-12-03 15:40:58.236647297 +0100
9f237c51 24681@@ -0,0 +1,166 @@
062440b3 24682+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 24683+/*
6d176551 24684+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 24685+ *
24686+ * This program, aufs is free software; you can redistribute it and/or modify
24687+ * it under the terms of the GNU General Public License as published by
24688+ * the Free Software Foundation; either version 2 of the License, or
24689+ * (at your option) any later version.
dece6358
AM
24690+ *
24691+ * This program is distributed in the hope that it will be useful,
24692+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24693+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24694+ * GNU General Public License for more details.
24695+ *
24696+ * You should have received a copy of the GNU General Public License
523b37e3 24697+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24698+ */
24699+
24700+/*
24701+ * module initialization and module-global
24702+ */
24703+
24704+#ifndef __AUFS_MODULE_H__
24705+#define __AUFS_MODULE_H__
24706+
24707+#ifdef __KERNEL__
24708+
24709+#include <linux/slab.h>
9f237c51
AM
24710+#include "debug.h"
24711+#include "dentry.h"
24712+#include "dir.h"
24713+#include "file.h"
24714+#include "inode.h"
1facf9fc 24715+
dece6358
AM
24716+struct path;
24717+struct seq_file;
24718+
1facf9fc 24719+/* module parameters */
1facf9fc 24720+extern int sysaufs_brs;
8cdd5066 24721+extern bool au_userns;
1facf9fc 24722+
24723+/* ---------------------------------------------------------------------- */
24724+
24725+extern int au_dir_roflags;
24726+
e2f27e51
AM
24727+void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink);
24728+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp,
24729+ int may_shrink);
24730+
9f237c51
AM
24731+/*
24732+ * Comparing the size of the object with sizeof(struct rcu_head)
24733+ * case 1: object is always larger
24734+ * --> au_kfree_rcu() or au_kfree_do_rcu()
24735+ * case 2: object is always smaller
24736+ * --> au_kfree_small()
24737+ * case 3: object can be any size
24738+ * --> au_kfree_try_rcu()
24739+ */
24740+
24741+static inline void au_kfree_do_rcu(const void *p)
24742+{
24743+ struct {
24744+ struct rcu_head rcu;
24745+ } *a = (void *)p;
24746+
24747+ kfree_rcu(a, rcu);
24748+}
24749+
24750+#define au_kfree_rcu(_p) do { \
24751+ typeof(_p) p = (_p); \
24752+ BUILD_BUG_ON(sizeof(*p) < sizeof(struct rcu_head)); \
24753+ if (p) \
24754+ au_kfree_do_rcu(p); \
24755+ } while (0)
24756+
24757+#define au_kfree_do_sz_test(sz) (sz >= sizeof(struct rcu_head))
24758+#define au_kfree_sz_test(p) (p && au_kfree_do_sz_test(ksize(p)))
24759+
24760+static inline void au_kfree_try_rcu(const void *p)
24761+{
24762+ if (!p)
24763+ return;
24764+ if (au_kfree_sz_test(p))
24765+ au_kfree_do_rcu(p);
24766+ else
24767+ kfree(p);
24768+}
24769+
24770+static inline void au_kfree_small(const void *p)
24771+{
24772+ if (!p)
24773+ return;
24774+ AuDebugOn(au_kfree_sz_test(p));
24775+ kfree(p);
24776+}
24777+
e2f27e51
AM
24778+static inline int au_kmidx_sub(size_t sz, size_t new_sz)
24779+{
24780+#ifndef CONFIG_SLOB
6d176551 24781+ return __kmalloc_index(sz, false) - __kmalloc_index(new_sz, false);
e2f27e51
AM
24782+#else
24783+ return -1; /* SLOB is untested */
24784+#endif
24785+}
24786+
1facf9fc 24787+int au_seq_path(struct seq_file *seq, struct path *path);
24788+
e49829fe
JR
24789+#ifdef CONFIG_PROC_FS
24790+/* procfs.c */
24791+int __init au_procfs_init(void);
24792+void au_procfs_fin(void);
24793+#else
24794+AuStubInt0(au_procfs_init, void);
24795+AuStubVoid(au_procfs_fin, void);
24796+#endif
24797+
4f0767ce
JR
24798+/* ---------------------------------------------------------------------- */
24799+
1c60b727 24800+/* kmem cache */
1facf9fc 24801+enum {
24802+ AuCache_DINFO,
24803+ AuCache_ICNTNR,
24804+ AuCache_FINFO,
24805+ AuCache_VDIR,
24806+ AuCache_DEHSTR,
7eafdf33 24807+ AuCache_HNOTIFY, /* must be last */
1facf9fc 24808+ AuCache_Last
24809+};
24810+
1c60b727 24811+extern struct kmem_cache *au_cache[AuCache_Last];
f0c0a007 24812+
4a4d8108
AM
24813+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
24814+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
24815+#define AuCacheCtor(type, ctor) \
24816+ kmem_cache_create(#type, sizeof(struct type), \
24817+ __alignof__(struct type), AuCacheFlags, ctor)
1facf9fc 24818+
9f237c51
AM
24819+#define AuCacheFuncs(name, index) \
24820+ static inline struct au_##name *au_cache_alloc_##name(void) \
24821+ { return kmem_cache_alloc(au_cache[AuCache_##index], GFP_NOFS); } \
24822+ static inline void au_cache_free_##name##_norcu(struct au_##name *p) \
24823+ { kmem_cache_free(au_cache[AuCache_##index], p); } \
24824+ \
24825+ static inline void au_cache_free_##name##_rcu_cb(struct rcu_head *rcu) \
24826+ { void *p = rcu; \
24827+ p -= offsetof(struct au_##name, rcu); \
24828+ kmem_cache_free(au_cache[AuCache_##index], p); } \
24829+ static inline void au_cache_free_##name##_rcu(struct au_##name *p) \
24830+ { BUILD_BUG_ON(sizeof(struct au_##name) < sizeof(struct rcu_head)); \
24831+ call_rcu(&p->rcu, au_cache_free_##name##_rcu_cb); } \
24832+ \
24833+ static inline void au_cache_free_##name(struct au_##name *p) \
24834+ { /* au_cache_free_##name##_norcu(p); */ \
24835+ au_cache_free_##name##_rcu(p); }
1facf9fc 24836+
24837+AuCacheFuncs(dinfo, DINFO);
24838+AuCacheFuncs(icntnr, ICNTNR);
24839+AuCacheFuncs(finfo, FINFO);
24840+AuCacheFuncs(vdir, VDIR);
4a4d8108
AM
24841+AuCacheFuncs(vdir_dehstr, DEHSTR);
24842+#ifdef CONFIG_AUFS_HNOTIFY
24843+AuCacheFuncs(hnotify, HNOTIFY);
24844+#endif
1facf9fc 24845+
4a4d8108
AM
24846+#endif /* __KERNEL__ */
24847+#endif /* __AUFS_MODULE_H__ */
c2b27bf2 24848diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
eca34b5c 24849--- /usr/share/empty/fs/aufs/mvdown.c 1970-01-01 01:00:00.000000000 +0100
319657f6 24850+++ linux/fs/aufs/mvdown.c 2021-12-03 15:38:59.939980643 +0100
ba1aed25 24851@@ -0,0 +1,706 @@
cd7a4cd9 24852+// SPDX-License-Identifier: GPL-2.0
c2b27bf2 24853+/*
6d176551 24854+ * Copyright (C) 2011-2021 Junjiro R. Okajima
c2b27bf2
AM
24855+ *
24856+ * This program, aufs is free software; you can redistribute it and/or modify
24857+ * it under the terms of the GNU General Public License as published by
24858+ * the Free Software Foundation; either version 2 of the License, or
24859+ * (at your option) any later version.
24860+ *
24861+ * This program is distributed in the hope that it will be useful,
24862+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24863+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24864+ * GNU General Public License for more details.
24865+ *
24866+ * You should have received a copy of the GNU General Public License
523b37e3
AM
24867+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
24868+ */
24869+
24870+/*
24871+ * move-down, opposite of copy-up
c2b27bf2
AM
24872+ */
24873+
24874+#include "aufs.h"
24875+
c2b27bf2
AM
24876+struct au_mvd_args {
24877+ struct {
c2b27bf2
AM
24878+ struct super_block *h_sb;
24879+ struct dentry *h_parent;
24880+ struct au_hinode *hdir;
392086de 24881+ struct inode *h_dir, *h_inode;
c1595e42 24882+ struct au_pin pin;
c2b27bf2
AM
24883+ } info[AUFS_MVDOWN_NARRAY];
24884+
24885+ struct aufs_mvdown mvdown;
24886+ struct dentry *dentry, *parent;
24887+ struct inode *inode, *dir;
24888+ struct super_block *sb;
24889+ aufs_bindex_t bopq, bwh, bfound;
24890+ unsigned char rename_lock;
c2b27bf2
AM
24891+};
24892+
392086de 24893+#define mvd_errno mvdown.au_errno
076b876e
AM
24894+#define mvd_bsrc mvdown.stbr[AUFS_MVDOWN_UPPER].bindex
24895+#define mvd_src_brid mvdown.stbr[AUFS_MVDOWN_UPPER].brid
24896+#define mvd_bdst mvdown.stbr[AUFS_MVDOWN_LOWER].bindex
24897+#define mvd_dst_brid mvdown.stbr[AUFS_MVDOWN_LOWER].brid
c2b27bf2 24898+
392086de
AM
24899+#define mvd_h_src_sb info[AUFS_MVDOWN_UPPER].h_sb
24900+#define mvd_h_src_parent info[AUFS_MVDOWN_UPPER].h_parent
24901+#define mvd_hdir_src info[AUFS_MVDOWN_UPPER].hdir
24902+#define mvd_h_src_dir info[AUFS_MVDOWN_UPPER].h_dir
24903+#define mvd_h_src_inode info[AUFS_MVDOWN_UPPER].h_inode
c1595e42 24904+#define mvd_pin_src info[AUFS_MVDOWN_UPPER].pin
392086de
AM
24905+
24906+#define mvd_h_dst_sb info[AUFS_MVDOWN_LOWER].h_sb
24907+#define mvd_h_dst_parent info[AUFS_MVDOWN_LOWER].h_parent
24908+#define mvd_hdir_dst info[AUFS_MVDOWN_LOWER].hdir
24909+#define mvd_h_dst_dir info[AUFS_MVDOWN_LOWER].h_dir
24910+#define mvd_h_dst_inode info[AUFS_MVDOWN_LOWER].h_inode
c1595e42 24911+#define mvd_pin_dst info[AUFS_MVDOWN_LOWER].pin
c2b27bf2
AM
24912+
24913+#define AU_MVD_PR(flag, ...) do { \
24914+ if (flag) \
24915+ pr_err(__VA_ARGS__); \
24916+ } while (0)
24917+
076b876e
AM
24918+static int find_lower_writable(struct au_mvd_args *a)
24919+{
24920+ struct super_block *sb;
5afbbe0d 24921+ aufs_bindex_t bindex, bbot;
076b876e
AM
24922+ struct au_branch *br;
24923+
24924+ sb = a->sb;
24925+ bindex = a->mvd_bsrc;
5afbbe0d 24926+ bbot = au_sbbot(sb);
076b876e 24927+ if (a->mvdown.flags & AUFS_MVDOWN_FHSM_LOWER)
5afbbe0d 24928+ for (bindex++; bindex <= bbot; bindex++) {
076b876e
AM
24929+ br = au_sbr(sb, bindex);
24930+ if (au_br_fhsm(br->br_perm)
8b6a4947 24931+ && !sb_rdonly(au_br_sb(br)))
076b876e
AM
24932+ return bindex;
24933+ }
24934+ else if (!(a->mvdown.flags & AUFS_MVDOWN_ROLOWER))
5afbbe0d 24935+ for (bindex++; bindex <= bbot; bindex++) {
076b876e
AM
24936+ br = au_sbr(sb, bindex);
24937+ if (!au_br_rdonly(br))
24938+ return bindex;
24939+ }
24940+ else
5afbbe0d 24941+ for (bindex++; bindex <= bbot; bindex++) {
076b876e 24942+ br = au_sbr(sb, bindex);
8b6a4947 24943+ if (!sb_rdonly(au_br_sb(br))) {
076b876e
AM
24944+ if (au_br_rdonly(br))
24945+ a->mvdown.flags
24946+ |= AUFS_MVDOWN_ROLOWER_R;
24947+ return bindex;
24948+ }
24949+ }
24950+
24951+ return -1;
24952+}
24953+
c2b27bf2 24954+/* make the parent dir on bdst */
392086de 24955+static int au_do_mkdir(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
24956+{
24957+ int err;
24958+
24959+ err = 0;
24960+ a->mvd_hdir_src = au_hi(a->dir, a->mvd_bsrc);
24961+ a->mvd_hdir_dst = au_hi(a->dir, a->mvd_bdst);
24962+ a->mvd_h_src_parent = au_h_dptr(a->parent, a->mvd_bsrc);
24963+ a->mvd_h_dst_parent = NULL;
5afbbe0d 24964+ if (au_dbbot(a->parent) >= a->mvd_bdst)
c2b27bf2
AM
24965+ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst);
24966+ if (!a->mvd_h_dst_parent) {
24967+ err = au_cpdown_dirs(a->dentry, a->mvd_bdst);
24968+ if (unlikely(err)) {
392086de 24969+ AU_MVD_PR(dmsg, "cpdown_dirs failed\n");
c2b27bf2
AM
24970+ goto out;
24971+ }
24972+ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst);
24973+ }
24974+
24975+out:
24976+ AuTraceErr(err);
24977+ return err;
24978+}
24979+
24980+/* lock them all */
392086de 24981+static int au_do_lock(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
24982+{
24983+ int err;
24984+ struct dentry *h_trap;
24985+
24986+ a->mvd_h_src_sb = au_sbr_sb(a->sb, a->mvd_bsrc);
24987+ a->mvd_h_dst_sb = au_sbr_sb(a->sb, a->mvd_bdst);
c1595e42
JR
24988+ err = au_pin(&a->mvd_pin_dst, a->dentry, a->mvd_bdst,
24989+ au_opt_udba(a->sb),
24990+ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
24991+ AuTraceErr(err);
24992+ if (unlikely(err)) {
24993+ AU_MVD_PR(dmsg, "pin_dst failed\n");
24994+ goto out;
24995+ }
24996+
c2b27bf2
AM
24997+ if (a->mvd_h_src_sb != a->mvd_h_dst_sb) {
24998+ a->rename_lock = 0;
c1595e42
JR
24999+ au_pin_init(&a->mvd_pin_src, a->dentry, a->mvd_bsrc,
25000+ AuLsc_DI_PARENT, AuLsc_I_PARENT3,
25001+ au_opt_udba(a->sb),
25002+ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
25003+ err = au_do_pin(&a->mvd_pin_src);
25004+ AuTraceErr(err);
5527c038 25005+ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent);
c1595e42
JR
25006+ if (unlikely(err)) {
25007+ AU_MVD_PR(dmsg, "pin_src failed\n");
25008+ goto out_dst;
25009+ }
25010+ goto out; /* success */
c2b27bf2
AM
25011+ }
25012+
c2b27bf2 25013+ a->rename_lock = 1;
c1595e42
JR
25014+ au_pin_hdir_unlock(&a->mvd_pin_dst);
25015+ err = au_pin(&a->mvd_pin_src, a->dentry, a->mvd_bsrc,
25016+ au_opt_udba(a->sb),
25017+ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
25018+ AuTraceErr(err);
5527c038 25019+ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent);
c1595e42
JR
25020+ if (unlikely(err)) {
25021+ AU_MVD_PR(dmsg, "pin_src failed\n");
25022+ au_pin_hdir_lock(&a->mvd_pin_dst);
25023+ goto out_dst;
25024+ }
25025+ au_pin_hdir_unlock(&a->mvd_pin_src);
c2b27bf2
AM
25026+ h_trap = vfsub_lock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
25027+ a->mvd_h_dst_parent, a->mvd_hdir_dst);
25028+ if (h_trap) {
25029+ err = (h_trap != a->mvd_h_src_parent);
25030+ if (err)
25031+ err = (h_trap != a->mvd_h_dst_parent);
25032+ }
25033+ BUG_ON(err); /* it should never happen */
c1595e42
JR
25034+ if (unlikely(a->mvd_h_src_dir != au_pinned_h_dir(&a->mvd_pin_src))) {
25035+ err = -EBUSY;
25036+ AuTraceErr(err);
25037+ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
25038+ a->mvd_h_dst_parent, a->mvd_hdir_dst);
25039+ au_pin_hdir_lock(&a->mvd_pin_src);
25040+ au_unpin(&a->mvd_pin_src);
25041+ au_pin_hdir_lock(&a->mvd_pin_dst);
25042+ goto out_dst;
25043+ }
25044+ goto out; /* success */
c2b27bf2 25045+
c1595e42
JR
25046+out_dst:
25047+ au_unpin(&a->mvd_pin_dst);
c2b27bf2
AM
25048+out:
25049+ AuTraceErr(err);
25050+ return err;
25051+}
25052+
392086de 25053+static void au_do_unlock(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2 25054+{
c1595e42
JR
25055+ if (!a->rename_lock)
25056+ au_unpin(&a->mvd_pin_src);
25057+ else {
c2b27bf2
AM
25058+ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
25059+ a->mvd_h_dst_parent, a->mvd_hdir_dst);
c1595e42
JR
25060+ au_pin_hdir_lock(&a->mvd_pin_src);
25061+ au_unpin(&a->mvd_pin_src);
25062+ au_pin_hdir_lock(&a->mvd_pin_dst);
25063+ }
25064+ au_unpin(&a->mvd_pin_dst);
c2b27bf2
AM
25065+}
25066+
25067+/* copy-down the file */
392086de 25068+static int au_do_cpdown(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25069+{
25070+ int err;
25071+ struct au_cp_generic cpg = {
25072+ .dentry = a->dentry,
25073+ .bdst = a->mvd_bdst,
25074+ .bsrc = a->mvd_bsrc,
25075+ .len = -1,
c1595e42 25076+ .pin = &a->mvd_pin_dst,
c2b27bf2
AM
25077+ .flags = AuCpup_DTIME | AuCpup_HOPEN
25078+ };
25079+
25080+ AuDbg("b%d, b%d\n", cpg.bsrc, cpg.bdst);
392086de
AM
25081+ if (a->mvdown.flags & AUFS_MVDOWN_OWLOWER)
25082+ au_fset_cpup(cpg.flags, OVERWRITE);
25083+ if (a->mvdown.flags & AUFS_MVDOWN_ROLOWER)
25084+ au_fset_cpup(cpg.flags, RWDST);
c2b27bf2
AM
25085+ err = au_sio_cpdown_simple(&cpg);
25086+ if (unlikely(err))
392086de 25087+ AU_MVD_PR(dmsg, "cpdown failed\n");
c2b27bf2
AM
25088+
25089+ AuTraceErr(err);
25090+ return err;
25091+}
25092+
25093+/*
25094+ * unlink the whiteout on bdst if exist which may be created by UDBA while we
25095+ * were sleeping
25096+ */
392086de 25097+static int au_do_unlink_wh(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25098+{
25099+ int err;
25100+ struct path h_path;
25101+ struct au_branch *br;
523b37e3 25102+ struct inode *delegated;
c2b27bf2
AM
25103+
25104+ br = au_sbr(a->sb, a->mvd_bdst);
25105+ h_path.dentry = au_wh_lkup(a->mvd_h_dst_parent, &a->dentry->d_name, br);
25106+ err = PTR_ERR(h_path.dentry);
25107+ if (IS_ERR(h_path.dentry)) {
392086de 25108+ AU_MVD_PR(dmsg, "wh_lkup failed\n");
c2b27bf2
AM
25109+ goto out;
25110+ }
25111+
25112+ err = 0;
5527c038 25113+ if (d_is_positive(h_path.dentry)) {
c2b27bf2 25114+ h_path.mnt = au_br_mnt(br);
523b37e3 25115+ delegated = NULL;
5527c038 25116+ err = vfsub_unlink(d_inode(a->mvd_h_dst_parent), &h_path,
523b37e3
AM
25117+ &delegated, /*force*/0);
25118+ if (unlikely(err == -EWOULDBLOCK)) {
25119+ pr_warn("cannot retry for NFSv4 delegation"
25120+ " for an internal unlink\n");
25121+ iput(delegated);
25122+ }
c2b27bf2 25123+ if (unlikely(err))
392086de 25124+ AU_MVD_PR(dmsg, "wh_unlink failed\n");
c2b27bf2
AM
25125+ }
25126+ dput(h_path.dentry);
25127+
25128+out:
25129+ AuTraceErr(err);
25130+ return err;
25131+}
25132+
25133+/*
25134+ * unlink the topmost h_dentry
c2b27bf2 25135+ */
392086de 25136+static int au_do_unlink(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25137+{
25138+ int err;
25139+ struct path h_path;
523b37e3 25140+ struct inode *delegated;
c2b27bf2
AM
25141+
25142+ h_path.mnt = au_sbr_mnt(a->sb, a->mvd_bsrc);
25143+ h_path.dentry = au_h_dptr(a->dentry, a->mvd_bsrc);
523b37e3
AM
25144+ delegated = NULL;
25145+ err = vfsub_unlink(a->mvd_h_src_dir, &h_path, &delegated, /*force*/0);
25146+ if (unlikely(err == -EWOULDBLOCK)) {
25147+ pr_warn("cannot retry for NFSv4 delegation"
25148+ " for an internal unlink\n");
25149+ iput(delegated);
25150+ }
c2b27bf2 25151+ if (unlikely(err))
392086de 25152+ AU_MVD_PR(dmsg, "unlink failed\n");
c2b27bf2
AM
25153+
25154+ AuTraceErr(err);
25155+ return err;
25156+}
25157+
076b876e
AM
25158+/* Since mvdown succeeded, we ignore an error of this function */
25159+static void au_do_stfs(const unsigned char dmsg, struct au_mvd_args *a)
25160+{
25161+ int err;
25162+ struct au_branch *br;
25163+
25164+ a->mvdown.flags |= AUFS_MVDOWN_STFS_FAILED;
25165+ br = au_sbr(a->sb, a->mvd_bsrc);
25166+ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_UPPER].stfs);
25167+ if (!err) {
25168+ br = au_sbr(a->sb, a->mvd_bdst);
25169+ a->mvdown.stbr[AUFS_MVDOWN_LOWER].brid = br->br_id;
25170+ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_LOWER].stfs);
25171+ }
25172+ if (!err)
25173+ a->mvdown.flags &= ~AUFS_MVDOWN_STFS_FAILED;
25174+ else
25175+ AU_MVD_PR(dmsg, "statfs failed (%d), ignored\n", err);
25176+}
25177+
c2b27bf2
AM
25178+/*
25179+ * copy-down the file and unlink the bsrc file.
25180+ * - unlink the bdst whout if exist
25181+ * - copy-down the file (with whtmp name and rename)
25182+ * - unlink the bsrc file
25183+ */
392086de 25184+static int au_do_mvdown(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25185+{
25186+ int err;
25187+
392086de 25188+ err = au_do_mkdir(dmsg, a);
c2b27bf2 25189+ if (!err)
392086de 25190+ err = au_do_lock(dmsg, a);
c2b27bf2
AM
25191+ if (unlikely(err))
25192+ goto out;
25193+
25194+ /*
25195+ * do not revert the activities we made on bdst since they should be
25196+ * harmless in aufs.
25197+ */
25198+
392086de 25199+ err = au_do_cpdown(dmsg, a);
c2b27bf2 25200+ if (!err)
392086de
AM
25201+ err = au_do_unlink_wh(dmsg, a);
25202+ if (!err && !(a->mvdown.flags & AUFS_MVDOWN_KUPPER))
25203+ err = au_do_unlink(dmsg, a);
c2b27bf2
AM
25204+ if (unlikely(err))
25205+ goto out_unlock;
25206+
c1595e42
JR
25207+ AuDbg("%pd2, 0x%x, %d --> %d\n",
25208+ a->dentry, a->mvdown.flags, a->mvd_bsrc, a->mvd_bdst);
076b876e
AM
25209+ if (find_lower_writable(a) < 0)
25210+ a->mvdown.flags |= AUFS_MVDOWN_BOTTOM;
25211+
25212+ if (a->mvdown.flags & AUFS_MVDOWN_STFS)
25213+ au_do_stfs(dmsg, a);
25214+
c2b27bf2 25215+ /* maintain internal array */
392086de
AM
25216+ if (!(a->mvdown.flags & AUFS_MVDOWN_KUPPER)) {
25217+ au_set_h_dptr(a->dentry, a->mvd_bsrc, NULL);
5afbbe0d 25218+ au_set_dbtop(a->dentry, a->mvd_bdst);
392086de 25219+ au_set_h_iptr(a->inode, a->mvd_bsrc, NULL, /*flags*/0);
5afbbe0d 25220+ au_set_ibtop(a->inode, a->mvd_bdst);
79b8bda9
AM
25221+ } else {
25222+ /* hide the lower */
25223+ au_set_h_dptr(a->dentry, a->mvd_bdst, NULL);
5afbbe0d 25224+ au_set_dbbot(a->dentry, a->mvd_bsrc);
79b8bda9 25225+ au_set_h_iptr(a->inode, a->mvd_bdst, NULL, /*flags*/0);
5afbbe0d 25226+ au_set_ibbot(a->inode, a->mvd_bsrc);
392086de 25227+ }
5afbbe0d
AM
25228+ if (au_dbbot(a->dentry) < a->mvd_bdst)
25229+ au_set_dbbot(a->dentry, a->mvd_bdst);
25230+ if (au_ibbot(a->inode) < a->mvd_bdst)
25231+ au_set_ibbot(a->inode, a->mvd_bdst);
c2b27bf2
AM
25232+
25233+out_unlock:
392086de 25234+ au_do_unlock(dmsg, a);
c2b27bf2
AM
25235+out:
25236+ AuTraceErr(err);
25237+ return err;
25238+}
25239+
25240+/* ---------------------------------------------------------------------- */
25241+
c2b27bf2 25242+/* make sure the file is idle */
392086de 25243+static int au_mvd_args_busy(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25244+{
25245+ int err, plinked;
c2b27bf2
AM
25246+
25247+ err = 0;
c2b27bf2 25248+ plinked = !!au_opt_test(au_mntflags(a->sb), PLINK);
5afbbe0d 25249+ if (au_dbtop(a->dentry) == a->mvd_bsrc
c1595e42 25250+ && au_dcount(a->dentry) == 1
c2b27bf2 25251+ && atomic_read(&a->inode->i_count) == 1
392086de 25252+ /* && a->mvd_h_src_inode->i_nlink == 1 */
c2b27bf2
AM
25253+ && (!plinked || !au_plink_test(a->inode))
25254+ && a->inode->i_nlink == 1)
25255+ goto out;
25256+
25257+ err = -EBUSY;
392086de 25258+ AU_MVD_PR(dmsg,
c1595e42 25259+ "b%d, d{b%d, c%d?}, i{c%d?, l%u}, hi{l%u}, p{%d, %d}\n",
5afbbe0d 25260+ a->mvd_bsrc, au_dbtop(a->dentry), au_dcount(a->dentry),
c2b27bf2 25261+ atomic_read(&a->inode->i_count), a->inode->i_nlink,
392086de 25262+ a->mvd_h_src_inode->i_nlink,
c2b27bf2
AM
25263+ plinked, plinked ? au_plink_test(a->inode) : 0);
25264+
25265+out:
25266+ AuTraceErr(err);
25267+ return err;
25268+}
25269+
25270+/* make sure the parent dir is fine */
392086de 25271+static int au_mvd_args_parent(const unsigned char dmsg,
c2b27bf2
AM
25272+ struct au_mvd_args *a)
25273+{
25274+ int err;
25275+ aufs_bindex_t bindex;
25276+
25277+ err = 0;
25278+ if (unlikely(au_alive_dir(a->parent))) {
25279+ err = -ENOENT;
392086de 25280+ AU_MVD_PR(dmsg, "parent dir is dead\n");
c2b27bf2
AM
25281+ goto out;
25282+ }
25283+
25284+ a->bopq = au_dbdiropq(a->parent);
25285+ bindex = au_wbr_nonopq(a->dentry, a->mvd_bdst);
25286+ AuDbg("b%d\n", bindex);
25287+ if (unlikely((bindex >= 0 && bindex < a->mvd_bdst)
25288+ || (a->bopq != -1 && a->bopq < a->mvd_bdst))) {
25289+ err = -EINVAL;
392086de
AM
25290+ a->mvd_errno = EAU_MVDOWN_OPAQUE;
25291+ AU_MVD_PR(dmsg, "ancestor is opaque b%d, b%d\n",
c2b27bf2
AM
25292+ a->bopq, a->mvd_bdst);
25293+ }
25294+
25295+out:
25296+ AuTraceErr(err);
25297+ return err;
25298+}
25299+
392086de 25300+static int au_mvd_args_intermediate(const unsigned char dmsg,
c2b27bf2
AM
25301+ struct au_mvd_args *a)
25302+{
25303+ int err;
25304+ struct au_dinfo *dinfo, *tmp;
25305+
25306+ /* lookup the next lower positive entry */
25307+ err = -ENOMEM;
25308+ tmp = au_di_alloc(a->sb, AuLsc_DI_TMP);
25309+ if (unlikely(!tmp))
25310+ goto out;
25311+
25312+ a->bfound = -1;
25313+ a->bwh = -1;
25314+ dinfo = au_di(a->dentry);
25315+ au_di_cp(tmp, dinfo);
25316+ au_di_swap(tmp, dinfo);
25317+
25318+ /* returns the number of positive dentries */
5afbbe0d
AM
25319+ err = au_lkup_dentry(a->dentry, a->mvd_bsrc + 1,
25320+ /* AuLkup_IGNORE_PERM */ 0);
c2b27bf2
AM
25321+ if (!err)
25322+ a->bwh = au_dbwh(a->dentry);
25323+ else if (err > 0)
5afbbe0d 25324+ a->bfound = au_dbtop(a->dentry);
c2b27bf2
AM
25325+
25326+ au_di_swap(tmp, dinfo);
25327+ au_rw_write_unlock(&tmp->di_rwsem);
25328+ au_di_free(tmp);
25329+ if (unlikely(err < 0))
392086de 25330+ AU_MVD_PR(dmsg, "failed look-up lower\n");
c2b27bf2
AM
25331+
25332+ /*
25333+ * here, we have these cases.
25334+ * bfound == -1
25335+ * no positive dentry under bsrc. there are more sub-cases.
25336+ * bwh < 0
25337+ * there no whiteout, we can safely move-down.
25338+ * bwh <= bsrc
25339+ * impossible
25340+ * bsrc < bwh && bwh < bdst
25341+ * there is a whiteout on RO branch. cannot proceed.
25342+ * bwh == bdst
25343+ * there is a whiteout on the RW target branch. it should
25344+ * be removed.
25345+ * bdst < bwh
25346+ * there is a whiteout somewhere unrelated branch.
25347+ * -1 < bfound && bfound <= bsrc
25348+ * impossible.
25349+ * bfound < bdst
25350+ * found, but it is on RO branch between bsrc and bdst. cannot
25351+ * proceed.
25352+ * bfound == bdst
25353+ * found, replace it if AUFS_MVDOWN_FORCE is set. otherwise return
25354+ * error.
25355+ * bdst < bfound
25356+ * found, after we create the file on bdst, it will be hidden.
25357+ */
25358+
25359+ AuDebugOn(a->bfound == -1
25360+ && a->bwh != -1
25361+ && a->bwh <= a->mvd_bsrc);
25362+ AuDebugOn(-1 < a->bfound
25363+ && a->bfound <= a->mvd_bsrc);
25364+
25365+ err = -EINVAL;
25366+ if (a->bfound == -1
25367+ && a->mvd_bsrc < a->bwh
25368+ && a->bwh != -1
25369+ && a->bwh < a->mvd_bdst) {
392086de
AM
25370+ a->mvd_errno = EAU_MVDOWN_WHITEOUT;
25371+ AU_MVD_PR(dmsg, "bsrc %d, bdst %d, bfound %d, bwh %d\n",
c2b27bf2
AM
25372+ a->mvd_bsrc, a->mvd_bdst, a->bfound, a->bwh);
25373+ goto out;
25374+ } else if (a->bfound != -1 && a->bfound < a->mvd_bdst) {
392086de
AM
25375+ a->mvd_errno = EAU_MVDOWN_UPPER;
25376+ AU_MVD_PR(dmsg, "bdst %d, bfound %d\n",
c2b27bf2
AM
25377+ a->mvd_bdst, a->bfound);
25378+ goto out;
25379+ }
25380+
25381+ err = 0; /* success */
25382+
25383+out:
25384+ AuTraceErr(err);
25385+ return err;
25386+}
25387+
392086de 25388+static int au_mvd_args_exist(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25389+{
25390+ int err;
25391+
392086de
AM
25392+ err = 0;
25393+ if (!(a->mvdown.flags & AUFS_MVDOWN_OWLOWER)
25394+ && a->bfound == a->mvd_bdst)
25395+ err = -EEXIST;
c2b27bf2
AM
25396+ AuTraceErr(err);
25397+ return err;
25398+}
25399+
392086de 25400+static int au_mvd_args(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25401+{
25402+ int err;
25403+ struct au_branch *br;
25404+
25405+ err = -EISDIR;
25406+ if (unlikely(S_ISDIR(a->inode->i_mode)))
25407+ goto out;
25408+
25409+ err = -EINVAL;
392086de 25410+ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_UPPER))
5afbbe0d 25411+ a->mvd_bsrc = au_ibtop(a->inode);
392086de
AM
25412+ else {
25413+ a->mvd_bsrc = au_br_index(a->sb, a->mvd_src_brid);
25414+ if (unlikely(a->mvd_bsrc < 0
5afbbe0d
AM
25415+ || (a->mvd_bsrc < au_dbtop(a->dentry)
25416+ || au_dbbot(a->dentry) < a->mvd_bsrc
392086de 25417+ || !au_h_dptr(a->dentry, a->mvd_bsrc))
5afbbe0d
AM
25418+ || (a->mvd_bsrc < au_ibtop(a->inode)
25419+ || au_ibbot(a->inode) < a->mvd_bsrc
392086de
AM
25420+ || !au_h_iptr(a->inode, a->mvd_bsrc)))) {
25421+ a->mvd_errno = EAU_MVDOWN_NOUPPER;
25422+ AU_MVD_PR(dmsg, "no upper\n");
25423+ goto out;
25424+ }
25425+ }
5afbbe0d 25426+ if (unlikely(a->mvd_bsrc == au_sbbot(a->sb))) {
392086de
AM
25427+ a->mvd_errno = EAU_MVDOWN_BOTTOM;
25428+ AU_MVD_PR(dmsg, "on the bottom\n");
c2b27bf2
AM
25429+ goto out;
25430+ }
392086de 25431+ a->mvd_h_src_inode = au_h_iptr(a->inode, a->mvd_bsrc);
c2b27bf2
AM
25432+ br = au_sbr(a->sb, a->mvd_bsrc);
25433+ err = au_br_rdonly(br);
392086de
AM
25434+ if (!(a->mvdown.flags & AUFS_MVDOWN_ROUPPER)) {
25435+ if (unlikely(err))
25436+ goto out;
25437+ } else if (!(vfsub_native_ro(a->mvd_h_src_inode)
25438+ || IS_APPEND(a->mvd_h_src_inode))) {
25439+ if (err)
25440+ a->mvdown.flags |= AUFS_MVDOWN_ROUPPER_R;
25441+ /* go on */
25442+ } else
c2b27bf2
AM
25443+ goto out;
25444+
25445+ err = -EINVAL;
392086de
AM
25446+ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_LOWER)) {
25447+ a->mvd_bdst = find_lower_writable(a);
25448+ if (unlikely(a->mvd_bdst < 0)) {
25449+ a->mvd_errno = EAU_MVDOWN_BOTTOM;
25450+ AU_MVD_PR(dmsg, "no writable lower branch\n");
25451+ goto out;
25452+ }
25453+ } else {
25454+ a->mvd_bdst = au_br_index(a->sb, a->mvd_dst_brid);
25455+ if (unlikely(a->mvd_bdst < 0
5afbbe0d 25456+ || au_sbbot(a->sb) < a->mvd_bdst)) {
392086de
AM
25457+ a->mvd_errno = EAU_MVDOWN_NOLOWERBR;
25458+ AU_MVD_PR(dmsg, "no lower brid\n");
25459+ goto out;
25460+ }
c2b27bf2
AM
25461+ }
25462+
392086de 25463+ err = au_mvd_args_busy(dmsg, a);
c2b27bf2 25464+ if (!err)
392086de 25465+ err = au_mvd_args_parent(dmsg, a);
c2b27bf2 25466+ if (!err)
392086de 25467+ err = au_mvd_args_intermediate(dmsg, a);
c2b27bf2 25468+ if (!err)
392086de 25469+ err = au_mvd_args_exist(dmsg, a);
c2b27bf2
AM
25470+ if (!err)
25471+ AuDbg("b%d, b%d\n", a->mvd_bsrc, a->mvd_bdst);
25472+
25473+out:
25474+ AuTraceErr(err);
25475+ return err;
25476+}
25477+
25478+int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *uarg)
25479+{
392086de
AM
25480+ int err, e;
25481+ unsigned char dmsg;
25482+ struct au_mvd_args *args;
79b8bda9 25483+ struct inode *inode;
c2b27bf2 25484+
79b8bda9 25485+ inode = d_inode(dentry);
c2b27bf2
AM
25486+ err = -EPERM;
25487+ if (unlikely(!capable(CAP_SYS_ADMIN)))
25488+ goto out;
25489+
392086de
AM
25490+ err = -ENOMEM;
25491+ args = kmalloc(sizeof(*args), GFP_NOFS);
25492+ if (unlikely(!args))
25493+ goto out;
25494+
25495+ err = copy_from_user(&args->mvdown, uarg, sizeof(args->mvdown));
25496+ if (!err)
ba1aed25
AM
25497+ /* VERIFY_WRITE */
25498+ err = !access_ok(uarg, sizeof(*uarg));
c2b27bf2
AM
25499+ if (unlikely(err)) {
25500+ err = -EFAULT;
392086de
AM
25501+ AuTraceErr(err);
25502+ goto out_free;
c2b27bf2 25503+ }
392086de
AM
25504+ AuDbg("flags 0x%x\n", args->mvdown.flags);
25505+ args->mvdown.flags &= ~(AUFS_MVDOWN_ROLOWER_R | AUFS_MVDOWN_ROUPPER_R);
25506+ args->mvdown.au_errno = 0;
25507+ args->dentry = dentry;
79b8bda9 25508+ args->inode = inode;
392086de 25509+ args->sb = dentry->d_sb;
c2b27bf2 25510+
392086de
AM
25511+ err = -ENOENT;
25512+ dmsg = !!(args->mvdown.flags & AUFS_MVDOWN_DMSG);
25513+ args->parent = dget_parent(dentry);
5527c038 25514+ args->dir = d_inode(args->parent);
febd17d6 25515+ inode_lock_nested(args->dir, I_MUTEX_PARENT);
392086de
AM
25516+ dput(args->parent);
25517+ if (unlikely(args->parent != dentry->d_parent)) {
25518+ AU_MVD_PR(dmsg, "parent dir is moved\n");
c2b27bf2
AM
25519+ goto out_dir;
25520+ }
25521+
febd17d6 25522+ inode_lock_nested(inode, I_MUTEX_CHILD);
b95c5147 25523+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_NOPLMW);
c2b27bf2
AM
25524+ if (unlikely(err))
25525+ goto out_inode;
25526+
392086de
AM
25527+ di_write_lock_parent(args->parent);
25528+ err = au_mvd_args(dmsg, args);
c2b27bf2
AM
25529+ if (unlikely(err))
25530+ goto out_parent;
25531+
392086de 25532+ err = au_do_mvdown(dmsg, args);
c2b27bf2
AM
25533+ if (unlikely(err))
25534+ goto out_parent;
c2b27bf2 25535+
392086de 25536+ au_cpup_attr_timesizes(args->dir);
79b8bda9
AM
25537+ au_cpup_attr_timesizes(inode);
25538+ if (!(args->mvdown.flags & AUFS_MVDOWN_KUPPER))
25539+ au_cpup_igen(inode, au_h_iptr(inode, args->mvd_bdst));
c2b27bf2
AM
25540+ /* au_digen_dec(dentry); */
25541+
25542+out_parent:
392086de 25543+ di_write_unlock(args->parent);
c2b27bf2
AM
25544+ aufs_read_unlock(dentry, AuLock_DW);
25545+out_inode:
febd17d6 25546+ inode_unlock(inode);
c2b27bf2 25547+out_dir:
febd17d6 25548+ inode_unlock(args->dir);
392086de
AM
25549+out_free:
25550+ e = copy_to_user(uarg, &args->mvdown, sizeof(args->mvdown));
25551+ if (unlikely(e))
25552+ err = -EFAULT;
9f237c51 25553+ au_kfree_rcu(args);
c2b27bf2
AM
25554+out:
25555+ AuTraceErr(err);
25556+ return err;
25557+}
25558diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
eca34b5c 25559--- /usr/share/empty/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
319657f6 25560+++ linux/fs/aufs/opts.c 2021-12-03 15:38:59.939980643 +0100
eca34b5c 25561@@ -0,0 +1,1880 @@
cd7a4cd9 25562+// SPDX-License-Identifier: GPL-2.0
1facf9fc 25563+/*
6d176551 25564+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 25565+ *
25566+ * This program, aufs is free software; you can redistribute it and/or modify
25567+ * it under the terms of the GNU General Public License as published by
25568+ * the Free Software Foundation; either version 2 of the License, or
25569+ * (at your option) any later version.
dece6358
AM
25570+ *
25571+ * This program is distributed in the hope that it will be useful,
25572+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25573+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25574+ * GNU General Public License for more details.
25575+ *
25576+ * You should have received a copy of the GNU General Public License
523b37e3 25577+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 25578+ */
25579+
25580+/*
25581+ * mount options/flags
25582+ */
25583+
dece6358 25584+#include <linux/namei.h>
1facf9fc 25585+#include <linux/types.h> /* a distribution requires */
25586+#include <linux/parser.h>
25587+#include "aufs.h"
25588+
25589+/* ---------------------------------------------------------------------- */
25590+
25591+enum {
25592+ Opt_br,
7e9cd9fe
AM
25593+ Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend,
25594+ Opt_idel, Opt_imod,
25595+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash,
dece6358 25596+ Opt_rdblk_def, Opt_rdhash_def,
7e9cd9fe 25597+ Opt_xino, Opt_noxino,
1facf9fc 25598+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
25599+ Opt_trunc_xino_path, Opt_itrunc_xino,
25600+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 25601+ Opt_shwh, Opt_noshwh,
1facf9fc 25602+ Opt_plink, Opt_noplink, Opt_list_plink,
25603+ Opt_udba,
4a4d8108 25604+ Opt_dio, Opt_nodio,
1facf9fc 25605+ Opt_diropq_a, Opt_diropq_w,
25606+ Opt_warn_perm, Opt_nowarn_perm,
25607+ Opt_wbr_copyup, Opt_wbr_create,
076b876e 25608+ Opt_fhsm_sec,
1facf9fc 25609+ Opt_verbose, Opt_noverbose,
25610+ Opt_sum, Opt_nosum, Opt_wsum,
076b876e 25611+ Opt_dirperm1, Opt_nodirperm1,
8b6a4947 25612+ Opt_dirren, Opt_nodirren,
c1595e42 25613+ Opt_acl, Opt_noacl,
1facf9fc 25614+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
25615+};
25616+
25617+static match_table_t options = {
25618+ {Opt_br, "br=%s"},
25619+ {Opt_br, "br:%s"},
25620+
25621+ {Opt_add, "add=%d:%s"},
25622+ {Opt_add, "add:%d:%s"},
25623+ {Opt_add, "ins=%d:%s"},
25624+ {Opt_add, "ins:%d:%s"},
25625+ {Opt_append, "append=%s"},
25626+ {Opt_append, "append:%s"},
25627+ {Opt_prepend, "prepend=%s"},
25628+ {Opt_prepend, "prepend:%s"},
25629+
25630+ {Opt_del, "del=%s"},
25631+ {Opt_del, "del:%s"},
25632+ /* {Opt_idel, "idel:%d"}, */
25633+ {Opt_mod, "mod=%s"},
25634+ {Opt_mod, "mod:%s"},
25635+ /* {Opt_imod, "imod:%d:%s"}, */
25636+
25637+ {Opt_dirwh, "dirwh=%d"},
25638+
25639+ {Opt_xino, "xino=%s"},
25640+ {Opt_noxino, "noxino"},
25641+ {Opt_trunc_xino, "trunc_xino"},
25642+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
25643+ {Opt_notrunc_xino, "notrunc_xino"},
25644+ {Opt_trunc_xino_path, "trunc_xino=%s"},
25645+ {Opt_itrunc_xino, "itrunc_xino=%d"},
25646+ /* {Opt_zxino, "zxino=%s"}, */
25647+ {Opt_trunc_xib, "trunc_xib"},
25648+ {Opt_notrunc_xib, "notrunc_xib"},
25649+
e49829fe 25650+#ifdef CONFIG_PROC_FS
1facf9fc 25651+ {Opt_plink, "plink"},
e49829fe
JR
25652+#else
25653+ {Opt_ignore_silent, "plink"},
25654+#endif
25655+
1facf9fc 25656+ {Opt_noplink, "noplink"},
e49829fe 25657+
1facf9fc 25658+#ifdef CONFIG_AUFS_DEBUG
25659+ {Opt_list_plink, "list_plink"},
25660+#endif
25661+
25662+ {Opt_udba, "udba=%s"},
25663+
4a4d8108
AM
25664+ {Opt_dio, "dio"},
25665+ {Opt_nodio, "nodio"},
25666+
8b6a4947
AM
25667+#ifdef CONFIG_AUFS_DIRREN
25668+ {Opt_dirren, "dirren"},
25669+ {Opt_nodirren, "nodirren"},
25670+#else
25671+ {Opt_ignore, "dirren"},
25672+ {Opt_ignore_silent, "nodirren"},
25673+#endif
25674+
076b876e
AM
25675+#ifdef CONFIG_AUFS_FHSM
25676+ {Opt_fhsm_sec, "fhsm_sec=%d"},
25677+#else
8b6a4947 25678+ {Opt_ignore, "fhsm_sec=%d"},
076b876e
AM
25679+#endif
25680+
1facf9fc 25681+ {Opt_diropq_a, "diropq=always"},
25682+ {Opt_diropq_a, "diropq=a"},
25683+ {Opt_diropq_w, "diropq=whiteouted"},
25684+ {Opt_diropq_w, "diropq=w"},
25685+
25686+ {Opt_warn_perm, "warn_perm"},
25687+ {Opt_nowarn_perm, "nowarn_perm"},
25688+
25689+ /* keep them temporary */
1facf9fc 25690+ {Opt_ignore_silent, "nodlgt"},
8b6a4947 25691+ {Opt_ignore, "clean_plink"},
1facf9fc 25692+
dece6358
AM
25693+#ifdef CONFIG_AUFS_SHWH
25694+ {Opt_shwh, "shwh"},
25695+#endif
25696+ {Opt_noshwh, "noshwh"},
25697+
076b876e
AM
25698+ {Opt_dirperm1, "dirperm1"},
25699+ {Opt_nodirperm1, "nodirperm1"},
25700+
1facf9fc 25701+ {Opt_verbose, "verbose"},
25702+ {Opt_verbose, "v"},
25703+ {Opt_noverbose, "noverbose"},
25704+ {Opt_noverbose, "quiet"},
25705+ {Opt_noverbose, "q"},
25706+ {Opt_noverbose, "silent"},
25707+
25708+ {Opt_sum, "sum"},
25709+ {Opt_nosum, "nosum"},
25710+ {Opt_wsum, "wsum"},
25711+
25712+ {Opt_rdcache, "rdcache=%d"},
25713+ {Opt_rdblk, "rdblk=%d"},
dece6358 25714+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 25715+ {Opt_rdhash, "rdhash=%d"},
dece6358 25716+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 25717+
25718+ {Opt_wbr_create, "create=%s"},
25719+ {Opt_wbr_create, "create_policy=%s"},
25720+ {Opt_wbr_copyup, "cpup=%s"},
25721+ {Opt_wbr_copyup, "copyup=%s"},
25722+ {Opt_wbr_copyup, "copyup_policy=%s"},
25723+
c1595e42
JR
25724+ /* generic VFS flag */
25725+#ifdef CONFIG_FS_POSIX_ACL
25726+ {Opt_acl, "acl"},
25727+ {Opt_noacl, "noacl"},
25728+#else
8b6a4947 25729+ {Opt_ignore, "acl"},
c1595e42
JR
25730+ {Opt_ignore_silent, "noacl"},
25731+#endif
25732+
1facf9fc 25733+ /* internal use for the scripts */
25734+ {Opt_ignore_silent, "si=%s"},
25735+
25736+ {Opt_br, "dirs=%s"},
25737+ {Opt_ignore, "debug=%d"},
25738+ {Opt_ignore, "delete=whiteout"},
25739+ {Opt_ignore, "delete=all"},
25740+ {Opt_ignore, "imap=%s"},
25741+
1308ab2a 25742+ /* temporary workaround, due to old mount(8)? */
25743+ {Opt_ignore_silent, "relatime"},
25744+
1facf9fc 25745+ {Opt_err, NULL}
25746+};
25747+
25748+/* ---------------------------------------------------------------------- */
25749+
076b876e 25750+static const char *au_parser_pattern(int val, match_table_t tbl)
1facf9fc 25751+{
076b876e
AM
25752+ struct match_token *p;
25753+
25754+ p = tbl;
25755+ while (p->pattern) {
25756+ if (p->token == val)
25757+ return p->pattern;
25758+ p++;
1facf9fc 25759+ }
25760+ BUG();
25761+ return "??";
25762+}
25763+
076b876e
AM
25764+static const char *au_optstr(int *val, match_table_t tbl)
25765+{
25766+ struct match_token *p;
25767+ int v;
25768+
25769+ v = *val;
2000de60
JR
25770+ if (!v)
25771+ goto out;
076b876e 25772+ p = tbl;
2000de60
JR
25773+ while (p->pattern) {
25774+ if (p->token
25775+ && (v & p->token) == p->token) {
076b876e
AM
25776+ *val &= ~p->token;
25777+ return p->pattern;
25778+ }
25779+ p++;
25780+ }
2000de60
JR
25781+
25782+out:
076b876e
AM
25783+ return NULL;
25784+}
25785+
1facf9fc 25786+/* ---------------------------------------------------------------------- */
25787+
1e00d052 25788+static match_table_t brperm = {
1facf9fc 25789+ {AuBrPerm_RO, AUFS_BRPERM_RO},
25790+ {AuBrPerm_RR, AUFS_BRPERM_RR},
25791+ {AuBrPerm_RW, AUFS_BRPERM_RW},
1e00d052
AM
25792+ {0, NULL}
25793+};
1facf9fc 25794+
86dc4139 25795+static match_table_t brattr = {
076b876e
AM
25796+ /* general */
25797+ {AuBrAttr_COO_REG, AUFS_BRATTR_COO_REG},
25798+ {AuBrAttr_COO_ALL, AUFS_BRATTR_COO_ALL},
c1595e42 25799+ /* 'unpin' attrib is meaningless since linux-3.18-rc1 */
86dc4139 25800+ {AuBrAttr_UNPIN, AUFS_BRATTR_UNPIN},
2000de60 25801+#ifdef CONFIG_AUFS_FHSM
076b876e 25802+ {AuBrAttr_FHSM, AUFS_BRATTR_FHSM},
2000de60
JR
25803+#endif
25804+#ifdef CONFIG_AUFS_XATTR
c1595e42
JR
25805+ {AuBrAttr_ICEX, AUFS_BRATTR_ICEX},
25806+ {AuBrAttr_ICEX_SEC, AUFS_BRATTR_ICEX_SEC},
25807+ {AuBrAttr_ICEX_SYS, AUFS_BRATTR_ICEX_SYS},
25808+ {AuBrAttr_ICEX_TR, AUFS_BRATTR_ICEX_TR},
25809+ {AuBrAttr_ICEX_USR, AUFS_BRATTR_ICEX_USR},
25810+ {AuBrAttr_ICEX_OTH, AUFS_BRATTR_ICEX_OTH},
2000de60 25811+#endif
076b876e
AM
25812+
25813+ /* ro/rr branch */
1e00d052 25814+ {AuBrRAttr_WH, AUFS_BRRATTR_WH},
076b876e
AM
25815+
25816+ /* rw branch */
25817+ {AuBrWAttr_MOO, AUFS_BRWATTR_MOO},
1e00d052 25818+ {AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH},
076b876e 25819+
1e00d052 25820+ {0, NULL}
1facf9fc 25821+};
25822+
1e00d052
AM
25823+static int br_attr_val(char *str, match_table_t table, substring_t args[])
25824+{
25825+ int attr, v;
25826+ char *p;
25827+
25828+ attr = 0;
25829+ do {
25830+ p = strchr(str, '+');
25831+ if (p)
25832+ *p = 0;
25833+ v = match_token(str, table, args);
076b876e
AM
25834+ if (v) {
25835+ if (v & AuBrAttr_CMOO_Mask)
25836+ attr &= ~AuBrAttr_CMOO_Mask;
1e00d052 25837+ attr |= v;
076b876e 25838+ } else {
1e00d052
AM
25839+ if (p)
25840+ *p = '+';
0c3ec466 25841+ pr_warn("ignored branch attribute %s\n", str);
1e00d052
AM
25842+ break;
25843+ }
25844+ if (p)
25845+ str = p + 1;
25846+ } while (p);
25847+
25848+ return attr;
25849+}
25850+
076b876e
AM
25851+static int au_do_optstr_br_attr(au_br_perm_str_t *str, int perm)
25852+{
25853+ int sz;
25854+ const char *p;
25855+ char *q;
25856+
076b876e
AM
25857+ q = str->a;
25858+ *q = 0;
25859+ p = au_optstr(&perm, brattr);
25860+ if (p) {
25861+ sz = strlen(p);
25862+ memcpy(q, p, sz + 1);
25863+ q += sz;
25864+ } else
25865+ goto out;
25866+
25867+ do {
25868+ p = au_optstr(&perm, brattr);
25869+ if (p) {
25870+ *q++ = '+';
25871+ sz = strlen(p);
25872+ memcpy(q, p, sz + 1);
25873+ q += sz;
25874+ }
25875+ } while (p);
25876+
25877+out:
c1595e42 25878+ return q - str->a;
076b876e
AM
25879+}
25880+
4a4d8108 25881+static int noinline_for_stack br_perm_val(char *perm)
1facf9fc 25882+{
076b876e
AM
25883+ int val, bad, sz;
25884+ char *p;
1facf9fc 25885+ substring_t args[MAX_OPT_ARGS];
076b876e 25886+ au_br_perm_str_t attr;
1facf9fc 25887+
1e00d052
AM
25888+ p = strchr(perm, '+');
25889+ if (p)
25890+ *p = 0;
25891+ val = match_token(perm, brperm, args);
25892+ if (!val) {
25893+ if (p)
25894+ *p = '+';
0c3ec466 25895+ pr_warn("ignored branch permission %s\n", perm);
1e00d052
AM
25896+ val = AuBrPerm_RO;
25897+ goto out;
25898+ }
25899+ if (!p)
25900+ goto out;
25901+
076b876e
AM
25902+ val |= br_attr_val(p + 1, brattr, args);
25903+
25904+ bad = 0;
86dc4139 25905+ switch (val & AuBrPerm_Mask) {
1e00d052
AM
25906+ case AuBrPerm_RO:
25907+ case AuBrPerm_RR:
076b876e
AM
25908+ bad = val & AuBrWAttr_Mask;
25909+ val &= ~AuBrWAttr_Mask;
1e00d052
AM
25910+ break;
25911+ case AuBrPerm_RW:
076b876e
AM
25912+ bad = val & AuBrRAttr_Mask;
25913+ val &= ~AuBrRAttr_Mask;
1e00d052
AM
25914+ break;
25915+ }
c1595e42
JR
25916+
25917+ /*
25918+ * 'unpin' attrib becomes meaningless since linux-3.18-rc1, but aufs
25919+ * does not treat it as an error, just warning.
25920+ * this is a tiny guard for the user operation.
25921+ */
25922+ if (val & AuBrAttr_UNPIN) {
25923+ bad |= AuBrAttr_UNPIN;
25924+ val &= ~AuBrAttr_UNPIN;
25925+ }
25926+
076b876e
AM
25927+ if (unlikely(bad)) {
25928+ sz = au_do_optstr_br_attr(&attr, bad);
25929+ AuDebugOn(!sz);
25930+ pr_warn("ignored branch attribute %s\n", attr.a);
25931+ }
1e00d052
AM
25932+
25933+out:
1facf9fc 25934+ return val;
25935+}
25936+
076b876e 25937+void au_optstr_br_perm(au_br_perm_str_t *str, int perm)
1facf9fc 25938+{
076b876e
AM
25939+ au_br_perm_str_t attr;
25940+ const char *p;
25941+ char *q;
1e00d052
AM
25942+ int sz;
25943+
076b876e
AM
25944+ q = str->a;
25945+ p = au_optstr(&perm, brperm);
25946+ AuDebugOn(!p || !*p);
25947+ sz = strlen(p);
25948+ memcpy(q, p, sz + 1);
25949+ q += sz;
1e00d052 25950+
076b876e
AM
25951+ sz = au_do_optstr_br_attr(&attr, perm);
25952+ if (sz) {
25953+ *q++ = '+';
25954+ memcpy(q, attr.a, sz + 1);
1e00d052
AM
25955+ }
25956+
076b876e 25957+ AuDebugOn(strlen(str->a) >= sizeof(str->a));
1facf9fc 25958+}
25959+
25960+/* ---------------------------------------------------------------------- */
25961+
25962+static match_table_t udbalevel = {
25963+ {AuOpt_UDBA_REVAL, "reval"},
25964+ {AuOpt_UDBA_NONE, "none"},
4a4d8108
AM
25965+#ifdef CONFIG_AUFS_HNOTIFY
25966+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
25967+#ifdef CONFIG_AUFS_HFSNOTIFY
25968+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
4a4d8108 25969+#endif
1facf9fc 25970+#endif
25971+ {-1, NULL}
25972+};
25973+
4a4d8108 25974+static int noinline_for_stack udba_val(char *str)
1facf9fc 25975+{
25976+ substring_t args[MAX_OPT_ARGS];
25977+
7f207e10 25978+ return match_token(str, udbalevel, args);
1facf9fc 25979+}
25980+
25981+const char *au_optstr_udba(int udba)
25982+{
076b876e 25983+ return au_parser_pattern(udba, udbalevel);
1facf9fc 25984+}
25985+
25986+/* ---------------------------------------------------------------------- */
25987+
25988+static match_table_t au_wbr_create_policy = {
25989+ {AuWbrCreate_TDP, "tdp"},
25990+ {AuWbrCreate_TDP, "top-down-parent"},
25991+ {AuWbrCreate_RR, "rr"},
25992+ {AuWbrCreate_RR, "round-robin"},
25993+ {AuWbrCreate_MFS, "mfs"},
25994+ {AuWbrCreate_MFS, "most-free-space"},
25995+ {AuWbrCreate_MFSV, "mfs:%d"},
25996+ {AuWbrCreate_MFSV, "most-free-space:%d"},
25997+
f2c43d5f
AM
25998+ /* top-down regardless the parent, and then mfs */
25999+ {AuWbrCreate_TDMFS, "tdmfs:%d"},
26000+ {AuWbrCreate_TDMFSV, "tdmfs:%d:%d"},
26001+
1facf9fc 26002+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
26003+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
26004+ {AuWbrCreate_PMFS, "pmfs"},
26005+ {AuWbrCreate_PMFSV, "pmfs:%d"},
392086de
AM
26006+ {AuWbrCreate_PMFSRR, "pmfsrr:%d"},
26007+ {AuWbrCreate_PMFSRRV, "pmfsrr:%d:%d"},
1facf9fc 26008+
26009+ {-1, NULL}
26010+};
26011+
1facf9fc 26012+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
26013+ struct au_opt_wbr_create *create)
26014+{
26015+ int err;
26016+ unsigned long long ull;
26017+
26018+ err = 0;
a2654f78 26019+ if (!match_u64(arg, &ull))
1facf9fc 26020+ create->mfsrr_watermark = ull;
26021+ else {
4a4d8108 26022+ pr_err("bad integer in %s\n", str);
1facf9fc 26023+ err = -EINVAL;
26024+ }
26025+
26026+ return err;
26027+}
26028+
26029+static int au_wbr_mfs_sec(substring_t *arg, char *str,
26030+ struct au_opt_wbr_create *create)
26031+{
26032+ int n, err;
26033+
26034+ err = 0;
027c5e7a 26035+ if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC)
1facf9fc 26036+ create->mfs_second = n;
26037+ else {
4a4d8108 26038+ pr_err("bad integer in %s\n", str);
1facf9fc 26039+ err = -EINVAL;
26040+ }
26041+
26042+ return err;
26043+}
26044+
4a4d8108
AM
26045+static int noinline_for_stack
26046+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
1facf9fc 26047+{
26048+ int err, e;
26049+ substring_t args[MAX_OPT_ARGS];
26050+
26051+ err = match_token(str, au_wbr_create_policy, args);
26052+ create->wbr_create = err;
26053+ switch (err) {
26054+ case AuWbrCreate_MFSRRV:
f2c43d5f 26055+ case AuWbrCreate_TDMFSV:
392086de 26056+ case AuWbrCreate_PMFSRRV:
1facf9fc 26057+ e = au_wbr_mfs_wmark(&args[0], str, create);
26058+ if (!e)
26059+ e = au_wbr_mfs_sec(&args[1], str, create);
26060+ if (unlikely(e))
26061+ err = e;
26062+ break;
26063+ case AuWbrCreate_MFSRR:
f2c43d5f 26064+ case AuWbrCreate_TDMFS:
392086de 26065+ case AuWbrCreate_PMFSRR:
1facf9fc 26066+ e = au_wbr_mfs_wmark(&args[0], str, create);
26067+ if (unlikely(e)) {
26068+ err = e;
26069+ break;
26070+ }
42a736d3 26071+ fallthrough;
1facf9fc 26072+ case AuWbrCreate_MFS:
26073+ case AuWbrCreate_PMFS:
027c5e7a 26074+ create->mfs_second = AUFS_MFS_DEF_SEC;
1facf9fc 26075+ break;
26076+ case AuWbrCreate_MFSV:
26077+ case AuWbrCreate_PMFSV:
26078+ e = au_wbr_mfs_sec(&args[0], str, create);
26079+ if (unlikely(e))
26080+ err = e;
26081+ break;
26082+ }
26083+
26084+ return err;
26085+}
26086+
26087+const char *au_optstr_wbr_create(int wbr_create)
26088+{
076b876e 26089+ return au_parser_pattern(wbr_create, au_wbr_create_policy);
1facf9fc 26090+}
26091+
26092+static match_table_t au_wbr_copyup_policy = {
26093+ {AuWbrCopyup_TDP, "tdp"},
26094+ {AuWbrCopyup_TDP, "top-down-parent"},
26095+ {AuWbrCopyup_BUP, "bup"},
26096+ {AuWbrCopyup_BUP, "bottom-up-parent"},
26097+ {AuWbrCopyup_BU, "bu"},
26098+ {AuWbrCopyup_BU, "bottom-up"},
26099+ {-1, NULL}
26100+};
26101+
4a4d8108 26102+static int noinline_for_stack au_wbr_copyup_val(char *str)
1facf9fc 26103+{
26104+ substring_t args[MAX_OPT_ARGS];
26105+
26106+ return match_token(str, au_wbr_copyup_policy, args);
26107+}
26108+
26109+const char *au_optstr_wbr_copyup(int wbr_copyup)
26110+{
076b876e 26111+ return au_parser_pattern(wbr_copyup, au_wbr_copyup_policy);
1facf9fc 26112+}
26113+
26114+/* ---------------------------------------------------------------------- */
26115+
26116+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
26117+
26118+static void dump_opts(struct au_opts *opts)
26119+{
26120+#ifdef CONFIG_AUFS_DEBUG
26121+ /* reduce stack space */
26122+ union {
26123+ struct au_opt_add *add;
26124+ struct au_opt_del *del;
26125+ struct au_opt_mod *mod;
26126+ struct au_opt_xino *xino;
26127+ struct au_opt_xino_itrunc *xino_itrunc;
26128+ struct au_opt_wbr_create *create;
26129+ } u;
26130+ struct au_opt *opt;
26131+
26132+ opt = opts->opt;
26133+ while (opt->type != Opt_tail) {
26134+ switch (opt->type) {
26135+ case Opt_add:
26136+ u.add = &opt->add;
26137+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
26138+ u.add->bindex, u.add->pathname, u.add->perm,
26139+ u.add->path.dentry);
26140+ break;
26141+ case Opt_del:
26142+ case Opt_idel:
26143+ u.del = &opt->del;
26144+ AuDbg("del {%s, %p}\n",
26145+ u.del->pathname, u.del->h_path.dentry);
26146+ break;
26147+ case Opt_mod:
26148+ case Opt_imod:
26149+ u.mod = &opt->mod;
26150+ AuDbg("mod {%s, 0x%x, %p}\n",
26151+ u.mod->path, u.mod->perm, u.mod->h_root);
26152+ break;
26153+ case Opt_append:
26154+ u.add = &opt->add;
26155+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
26156+ u.add->bindex, u.add->pathname, u.add->perm,
26157+ u.add->path.dentry);
26158+ break;
26159+ case Opt_prepend:
26160+ u.add = &opt->add;
26161+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
26162+ u.add->bindex, u.add->pathname, u.add->perm,
26163+ u.add->path.dentry);
26164+ break;
26165+ case Opt_dirwh:
26166+ AuDbg("dirwh %d\n", opt->dirwh);
26167+ break;
26168+ case Opt_rdcache:
26169+ AuDbg("rdcache %d\n", opt->rdcache);
26170+ break;
26171+ case Opt_rdblk:
26172+ AuDbg("rdblk %u\n", opt->rdblk);
26173+ break;
dece6358
AM
26174+ case Opt_rdblk_def:
26175+ AuDbg("rdblk_def\n");
26176+ break;
1facf9fc 26177+ case Opt_rdhash:
26178+ AuDbg("rdhash %u\n", opt->rdhash);
26179+ break;
dece6358
AM
26180+ case Opt_rdhash_def:
26181+ AuDbg("rdhash_def\n");
26182+ break;
1facf9fc 26183+ case Opt_xino:
26184+ u.xino = &opt->xino;
523b37e3 26185+ AuDbg("xino {%s %pD}\n", u.xino->path, u.xino->file);
1facf9fc 26186+ break;
26187+ case Opt_trunc_xino:
26188+ AuLabel(trunc_xino);
26189+ break;
26190+ case Opt_notrunc_xino:
26191+ AuLabel(notrunc_xino);
26192+ break;
26193+ case Opt_trunc_xino_path:
26194+ case Opt_itrunc_xino:
26195+ u.xino_itrunc = &opt->xino_itrunc;
26196+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
26197+ break;
1facf9fc 26198+ case Opt_noxino:
26199+ AuLabel(noxino);
26200+ break;
26201+ case Opt_trunc_xib:
26202+ AuLabel(trunc_xib);
26203+ break;
26204+ case Opt_notrunc_xib:
26205+ AuLabel(notrunc_xib);
26206+ break;
dece6358
AM
26207+ case Opt_shwh:
26208+ AuLabel(shwh);
26209+ break;
26210+ case Opt_noshwh:
26211+ AuLabel(noshwh);
26212+ break;
076b876e
AM
26213+ case Opt_dirperm1:
26214+ AuLabel(dirperm1);
26215+ break;
26216+ case Opt_nodirperm1:
26217+ AuLabel(nodirperm1);
26218+ break;
1facf9fc 26219+ case Opt_plink:
26220+ AuLabel(plink);
26221+ break;
26222+ case Opt_noplink:
26223+ AuLabel(noplink);
26224+ break;
26225+ case Opt_list_plink:
26226+ AuLabel(list_plink);
26227+ break;
26228+ case Opt_udba:
26229+ AuDbg("udba %d, %s\n",
26230+ opt->udba, au_optstr_udba(opt->udba));
26231+ break;
4a4d8108
AM
26232+ case Opt_dio:
26233+ AuLabel(dio);
26234+ break;
26235+ case Opt_nodio:
26236+ AuLabel(nodio);
26237+ break;
1facf9fc 26238+ case Opt_diropq_a:
26239+ AuLabel(diropq_a);
26240+ break;
26241+ case Opt_diropq_w:
26242+ AuLabel(diropq_w);
26243+ break;
26244+ case Opt_warn_perm:
26245+ AuLabel(warn_perm);
26246+ break;
26247+ case Opt_nowarn_perm:
26248+ AuLabel(nowarn_perm);
26249+ break;
1facf9fc 26250+ case Opt_verbose:
26251+ AuLabel(verbose);
26252+ break;
26253+ case Opt_noverbose:
26254+ AuLabel(noverbose);
26255+ break;
26256+ case Opt_sum:
26257+ AuLabel(sum);
26258+ break;
26259+ case Opt_nosum:
26260+ AuLabel(nosum);
26261+ break;
26262+ case Opt_wsum:
26263+ AuLabel(wsum);
26264+ break;
26265+ case Opt_wbr_create:
26266+ u.create = &opt->wbr_create;
26267+ AuDbg("create %d, %s\n", u.create->wbr_create,
26268+ au_optstr_wbr_create(u.create->wbr_create));
26269+ switch (u.create->wbr_create) {
26270+ case AuWbrCreate_MFSV:
26271+ case AuWbrCreate_PMFSV:
26272+ AuDbg("%d sec\n", u.create->mfs_second);
26273+ break;
26274+ case AuWbrCreate_MFSRR:
f2c43d5f 26275+ case AuWbrCreate_TDMFS:
1facf9fc 26276+ AuDbg("%llu watermark\n",
26277+ u.create->mfsrr_watermark);
26278+ break;
26279+ case AuWbrCreate_MFSRRV:
f2c43d5f 26280+ case AuWbrCreate_TDMFSV:
392086de 26281+ case AuWbrCreate_PMFSRRV:
1facf9fc 26282+ AuDbg("%llu watermark, %d sec\n",
26283+ u.create->mfsrr_watermark,
26284+ u.create->mfs_second);
26285+ break;
26286+ }
26287+ break;
26288+ case Opt_wbr_copyup:
26289+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
26290+ au_optstr_wbr_copyup(opt->wbr_copyup));
26291+ break;
076b876e
AM
26292+ case Opt_fhsm_sec:
26293+ AuDbg("fhsm_sec %u\n", opt->fhsm_second);
26294+ break;
8b6a4947
AM
26295+ case Opt_dirren:
26296+ AuLabel(dirren);
26297+ break;
26298+ case Opt_nodirren:
26299+ AuLabel(nodirren);
26300+ break;
c1595e42
JR
26301+ case Opt_acl:
26302+ AuLabel(acl);
26303+ break;
26304+ case Opt_noacl:
26305+ AuLabel(noacl);
26306+ break;
1facf9fc 26307+ default:
26308+ BUG();
26309+ }
26310+ opt++;
26311+ }
26312+#endif
26313+}
26314+
26315+void au_opts_free(struct au_opts *opts)
26316+{
26317+ struct au_opt *opt;
26318+
26319+ opt = opts->opt;
26320+ while (opt->type != Opt_tail) {
26321+ switch (opt->type) {
26322+ case Opt_add:
26323+ case Opt_append:
26324+ case Opt_prepend:
26325+ path_put(&opt->add.path);
26326+ break;
26327+ case Opt_del:
26328+ case Opt_idel:
26329+ path_put(&opt->del.h_path);
26330+ break;
26331+ case Opt_mod:
26332+ case Opt_imod:
26333+ dput(opt->mod.h_root);
26334+ break;
26335+ case Opt_xino:
26336+ fput(opt->xino.file);
26337+ break;
26338+ }
26339+ opt++;
26340+ }
26341+}
26342+
26343+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
26344+ aufs_bindex_t bindex)
26345+{
26346+ int err;
26347+ struct au_opt_add *add = &opt->add;
26348+ char *p;
26349+
26350+ add->bindex = bindex;
1e00d052 26351+ add->perm = AuBrPerm_RO;
1facf9fc 26352+ add->pathname = opt_str;
26353+ p = strchr(opt_str, '=');
26354+ if (p) {
26355+ *p++ = 0;
26356+ if (*p)
26357+ add->perm = br_perm_val(p);
26358+ }
26359+
26360+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
26361+ if (!err) {
26362+ if (!p) {
26363+ add->perm = AuBrPerm_RO;
26364+ if (au_test_fs_rr(add->path.dentry->d_sb))
26365+ add->perm = AuBrPerm_RR;
2121bcd9 26366+ else if (!bindex && !(sb_flags & SB_RDONLY))
1facf9fc 26367+ add->perm = AuBrPerm_RW;
26368+ }
26369+ opt->type = Opt_add;
26370+ goto out;
26371+ }
4a4d8108 26372+ pr_err("lookup failed %s (%d)\n", add->pathname, err);
1facf9fc 26373+ err = -EINVAL;
26374+
4f0767ce 26375+out:
1facf9fc 26376+ return err;
26377+}
26378+
26379+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
26380+{
26381+ int err;
26382+
26383+ del->pathname = args[0].from;
26384+ AuDbg("del path %s\n", del->pathname);
26385+
26386+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
26387+ if (unlikely(err))
4a4d8108 26388+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
1facf9fc 26389+
26390+ return err;
26391+}
26392+
26393+#if 0 /* reserved for future use */
26394+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
26395+ struct au_opt_del *del, substring_t args[])
26396+{
26397+ int err;
26398+ struct dentry *root;
26399+
26400+ err = -EINVAL;
26401+ root = sb->s_root;
26402+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d 26403+ if (bindex < 0 || au_sbbot(sb) < bindex) {
4a4d8108 26404+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 26405+ goto out;
26406+ }
26407+
26408+ err = 0;
26409+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
26410+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
26411+
4f0767ce 26412+out:
1facf9fc 26413+ aufs_read_unlock(root, !AuLock_IR);
26414+ return err;
26415+}
26416+#endif
26417+
4a4d8108
AM
26418+static int noinline_for_stack
26419+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
1facf9fc 26420+{
26421+ int err;
26422+ struct path path;
26423+ char *p;
26424+
26425+ err = -EINVAL;
26426+ mod->path = args[0].from;
26427+ p = strchr(mod->path, '=');
26428+ if (unlikely(!p)) {
acd2b654 26429+ pr_err("no permission %s\n", args[0].from);
1facf9fc 26430+ goto out;
26431+ }
26432+
26433+ *p++ = 0;
26434+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
26435+ if (unlikely(err)) {
4a4d8108 26436+ pr_err("lookup failed %s (%d)\n", mod->path, err);
1facf9fc 26437+ goto out;
26438+ }
26439+
26440+ mod->perm = br_perm_val(p);
26441+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
26442+ mod->h_root = dget(path.dentry);
26443+ path_put(&path);
26444+
4f0767ce 26445+out:
1facf9fc 26446+ return err;
26447+}
26448+
26449+#if 0 /* reserved for future use */
26450+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
26451+ struct au_opt_mod *mod, substring_t args[])
26452+{
26453+ int err;
26454+ struct dentry *root;
26455+
26456+ err = -EINVAL;
26457+ root = sb->s_root;
26458+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d 26459+ if (bindex < 0 || au_sbbot(sb) < bindex) {
4a4d8108 26460+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 26461+ goto out;
26462+ }
26463+
26464+ err = 0;
26465+ mod->perm = br_perm_val(args[1].from);
26466+ AuDbg("mod path %s, perm 0x%x, %s\n",
26467+ mod->path, mod->perm, args[1].from);
26468+ mod->h_root = dget(au_h_dptr(root, bindex));
26469+
4f0767ce 26470+out:
1facf9fc 26471+ aufs_read_unlock(root, !AuLock_IR);
26472+ return err;
26473+}
26474+#endif
26475+
26476+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
26477+ substring_t args[])
26478+{
26479+ int err;
26480+ struct file *file;
26481+
83b672a5 26482+ file = au_xino_create(sb, args[0].from, /*silent*/0, /*wbrtop*/0);
1facf9fc 26483+ err = PTR_ERR(file);
26484+ if (IS_ERR(file))
26485+ goto out;
26486+
26487+ err = -EINVAL;
2000de60 26488+ if (unlikely(file->f_path.dentry->d_sb == sb)) {
1facf9fc 26489+ fput(file);
4a4d8108 26490+ pr_err("%s must be outside\n", args[0].from);
1facf9fc 26491+ goto out;
26492+ }
26493+
26494+ err = 0;
26495+ xino->file = file;
26496+ xino->path = args[0].from;
26497+
4f0767ce 26498+out:
1facf9fc 26499+ return err;
26500+}
26501+
4a4d8108
AM
26502+static int noinline_for_stack
26503+au_opts_parse_xino_itrunc_path(struct super_block *sb,
26504+ struct au_opt_xino_itrunc *xino_itrunc,
26505+ substring_t args[])
1facf9fc 26506+{
26507+ int err;
5afbbe0d 26508+ aufs_bindex_t bbot, bindex;
1facf9fc 26509+ struct path path;
26510+ struct dentry *root;
26511+
26512+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
26513+ if (unlikely(err)) {
4a4d8108 26514+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
1facf9fc 26515+ goto out;
26516+ }
26517+
26518+ xino_itrunc->bindex = -1;
26519+ root = sb->s_root;
26520+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d
AM
26521+ bbot = au_sbbot(sb);
26522+ for (bindex = 0; bindex <= bbot; bindex++) {
1facf9fc 26523+ if (au_h_dptr(root, bindex) == path.dentry) {
26524+ xino_itrunc->bindex = bindex;
26525+ break;
26526+ }
26527+ }
26528+ aufs_read_unlock(root, !AuLock_IR);
26529+ path_put(&path);
26530+
26531+ if (unlikely(xino_itrunc->bindex < 0)) {
4a4d8108 26532+ pr_err("no such branch %s\n", args[0].from);
1facf9fc 26533+ err = -EINVAL;
26534+ }
26535+
4f0767ce 26536+out:
1facf9fc 26537+ return err;
26538+}
26539+
26540+/* called without aufs lock */
26541+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
26542+{
26543+ int err, n, token;
26544+ aufs_bindex_t bindex;
26545+ unsigned char skipped;
26546+ struct dentry *root;
26547+ struct au_opt *opt, *opt_tail;
26548+ char *opt_str;
26549+ /* reduce the stack space */
26550+ union {
26551+ struct au_opt_xino_itrunc *xino_itrunc;
26552+ struct au_opt_wbr_create *create;
26553+ } u;
26554+ struct {
26555+ substring_t args[MAX_OPT_ARGS];
26556+ } *a;
26557+
26558+ err = -ENOMEM;
26559+ a = kmalloc(sizeof(*a), GFP_NOFS);
26560+ if (unlikely(!a))
26561+ goto out;
26562+
26563+ root = sb->s_root;
26564+ err = 0;
26565+ bindex = 0;
26566+ opt = opts->opt;
26567+ opt_tail = opt + opts->max_opt - 1;
26568+ opt->type = Opt_tail;
26569+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
26570+ err = -EINVAL;
26571+ skipped = 0;
26572+ token = match_token(opt_str, options, a->args);
26573+ switch (token) {
26574+ case Opt_br:
26575+ err = 0;
26576+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
26577+ && *opt_str) {
26578+ err = opt_add(opt, opt_str, opts->sb_flags,
26579+ bindex++);
26580+ if (unlikely(!err && ++opt > opt_tail)) {
26581+ err = -E2BIG;
26582+ break;
26583+ }
26584+ opt->type = Opt_tail;
26585+ skipped = 1;
26586+ }
26587+ break;
26588+ case Opt_add:
26589+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 26590+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26591+ break;
26592+ }
26593+ bindex = n;
26594+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
26595+ bindex);
26596+ if (!err)
26597+ opt->type = token;
26598+ break;
26599+ case Opt_append:
26600+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
26601+ /*dummy bindex*/1);
26602+ if (!err)
26603+ opt->type = token;
26604+ break;
26605+ case Opt_prepend:
26606+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
26607+ /*bindex*/0);
26608+ if (!err)
26609+ opt->type = token;
26610+ break;
26611+ case Opt_del:
26612+ err = au_opts_parse_del(&opt->del, a->args);
26613+ if (!err)
26614+ opt->type = token;
26615+ break;
26616+#if 0 /* reserved for future use */
26617+ case Opt_idel:
26618+ del->pathname = "(indexed)";
26619+ if (unlikely(match_int(&args[0], &n))) {
4a4d8108 26620+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26621+ break;
26622+ }
26623+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
26624+ if (!err)
26625+ opt->type = token;
26626+ break;
26627+#endif
26628+ case Opt_mod:
26629+ err = au_opts_parse_mod(&opt->mod, a->args);
26630+ if (!err)
26631+ opt->type = token;
26632+ break;
26633+#ifdef IMOD /* reserved for future use */
26634+ case Opt_imod:
26635+ u.mod->path = "(indexed)";
26636+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 26637+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26638+ break;
26639+ }
26640+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
26641+ if (!err)
26642+ opt->type = token;
26643+ break;
26644+#endif
26645+ case Opt_xino:
26646+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
26647+ if (!err)
26648+ opt->type = token;
26649+ break;
26650+
26651+ case Opt_trunc_xino_path:
26652+ err = au_opts_parse_xino_itrunc_path
26653+ (sb, &opt->xino_itrunc, a->args);
26654+ if (!err)
26655+ opt->type = token;
26656+ break;
26657+
26658+ case Opt_itrunc_xino:
26659+ u.xino_itrunc = &opt->xino_itrunc;
26660+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 26661+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26662+ break;
26663+ }
26664+ u.xino_itrunc->bindex = n;
26665+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d 26666+ if (n < 0 || au_sbbot(sb) < n) {
4a4d8108 26667+ pr_err("out of bounds, %d\n", n);
1facf9fc 26668+ aufs_read_unlock(root, !AuLock_IR);
26669+ break;
26670+ }
26671+ aufs_read_unlock(root, !AuLock_IR);
26672+ err = 0;
26673+ opt->type = token;
26674+ break;
26675+
26676+ case Opt_dirwh:
26677+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
26678+ break;
26679+ err = 0;
26680+ opt->type = token;
26681+ break;
26682+
26683+ case Opt_rdcache:
027c5e7a
AM
26684+ if (unlikely(match_int(&a->args[0], &n))) {
26685+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26686+ break;
027c5e7a
AM
26687+ }
26688+ if (unlikely(n > AUFS_RDCACHE_MAX)) {
26689+ pr_err("rdcache must be smaller than %d\n",
26690+ AUFS_RDCACHE_MAX);
26691+ break;
26692+ }
26693+ opt->rdcache = n;
1facf9fc 26694+ err = 0;
26695+ opt->type = token;
26696+ break;
26697+ case Opt_rdblk:
26698+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 26699+ || n < 0
1facf9fc 26700+ || n > KMALLOC_MAX_SIZE)) {
4a4d8108 26701+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26702+ break;
26703+ }
1308ab2a 26704+ if (unlikely(n && n < NAME_MAX)) {
4a4d8108
AM
26705+ pr_err("rdblk must be larger than %d\n",
26706+ NAME_MAX);
1facf9fc 26707+ break;
26708+ }
26709+ opt->rdblk = n;
26710+ err = 0;
26711+ opt->type = token;
26712+ break;
26713+ case Opt_rdhash:
26714+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 26715+ || n < 0
1facf9fc 26716+ || n * sizeof(struct hlist_head)
26717+ > KMALLOC_MAX_SIZE)) {
4a4d8108 26718+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26719+ break;
26720+ }
26721+ opt->rdhash = n;
26722+ err = 0;
26723+ opt->type = token;
26724+ break;
26725+
26726+ case Opt_trunc_xino:
26727+ case Opt_notrunc_xino:
26728+ case Opt_noxino:
26729+ case Opt_trunc_xib:
26730+ case Opt_notrunc_xib:
dece6358
AM
26731+ case Opt_shwh:
26732+ case Opt_noshwh:
076b876e
AM
26733+ case Opt_dirperm1:
26734+ case Opt_nodirperm1:
1facf9fc 26735+ case Opt_plink:
26736+ case Opt_noplink:
26737+ case Opt_list_plink:
4a4d8108
AM
26738+ case Opt_dio:
26739+ case Opt_nodio:
1facf9fc 26740+ case Opt_diropq_a:
26741+ case Opt_diropq_w:
26742+ case Opt_warn_perm:
26743+ case Opt_nowarn_perm:
1facf9fc 26744+ case Opt_verbose:
26745+ case Opt_noverbose:
26746+ case Opt_sum:
26747+ case Opt_nosum:
26748+ case Opt_wsum:
dece6358
AM
26749+ case Opt_rdblk_def:
26750+ case Opt_rdhash_def:
8b6a4947
AM
26751+ case Opt_dirren:
26752+ case Opt_nodirren:
c1595e42
JR
26753+ case Opt_acl:
26754+ case Opt_noacl:
1facf9fc 26755+ err = 0;
26756+ opt->type = token;
26757+ break;
26758+
26759+ case Opt_udba:
26760+ opt->udba = udba_val(a->args[0].from);
26761+ if (opt->udba >= 0) {
26762+ err = 0;
26763+ opt->type = token;
26764+ } else
4a4d8108 26765+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 26766+ break;
26767+
26768+ case Opt_wbr_create:
26769+ u.create = &opt->wbr_create;
26770+ u.create->wbr_create
26771+ = au_wbr_create_val(a->args[0].from, u.create);
26772+ if (u.create->wbr_create >= 0) {
26773+ err = 0;
26774+ opt->type = token;
26775+ } else
4a4d8108 26776+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 26777+ break;
26778+ case Opt_wbr_copyup:
26779+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
26780+ if (opt->wbr_copyup >= 0) {
26781+ err = 0;
26782+ opt->type = token;
26783+ } else
4a4d8108 26784+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 26785+ break;
26786+
076b876e
AM
26787+ case Opt_fhsm_sec:
26788+ if (unlikely(match_int(&a->args[0], &n)
26789+ || n < 0)) {
26790+ pr_err("bad integer in %s\n", opt_str);
26791+ break;
26792+ }
26793+ if (sysaufs_brs) {
26794+ opt->fhsm_second = n;
26795+ opt->type = token;
26796+ } else
26797+ pr_warn("ignored %s\n", opt_str);
26798+ err = 0;
26799+ break;
26800+
1facf9fc 26801+ case Opt_ignore:
0c3ec466 26802+ pr_warn("ignored %s\n", opt_str);
42a736d3 26803+ fallthrough;
1facf9fc 26804+ case Opt_ignore_silent:
26805+ skipped = 1;
26806+ err = 0;
26807+ break;
26808+ case Opt_err:
4a4d8108 26809+ pr_err("unknown option %s\n", opt_str);
1facf9fc 26810+ break;
26811+ }
26812+
26813+ if (!err && !skipped) {
26814+ if (unlikely(++opt > opt_tail)) {
26815+ err = -E2BIG;
26816+ opt--;
26817+ opt->type = Opt_tail;
26818+ break;
26819+ }
26820+ opt->type = Opt_tail;
26821+ }
26822+ }
26823+
9f237c51 26824+ au_kfree_rcu(a);
1facf9fc 26825+ dump_opts(opts);
26826+ if (unlikely(err))
26827+ au_opts_free(opts);
26828+
4f0767ce 26829+out:
1facf9fc 26830+ return err;
26831+}
26832+
26833+static int au_opt_wbr_create(struct super_block *sb,
26834+ struct au_opt_wbr_create *create)
26835+{
26836+ int err;
26837+ struct au_sbinfo *sbinfo;
26838+
dece6358
AM
26839+ SiMustWriteLock(sb);
26840+
1facf9fc 26841+ err = 1; /* handled */
26842+ sbinfo = au_sbi(sb);
26843+ if (sbinfo->si_wbr_create_ops->fin) {
26844+ err = sbinfo->si_wbr_create_ops->fin(sb);
26845+ if (!err)
26846+ err = 1;
26847+ }
26848+
26849+ sbinfo->si_wbr_create = create->wbr_create;
26850+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
26851+ switch (create->wbr_create) {
26852+ case AuWbrCreate_MFSRRV:
26853+ case AuWbrCreate_MFSRR:
f2c43d5f
AM
26854+ case AuWbrCreate_TDMFS:
26855+ case AuWbrCreate_TDMFSV:
392086de
AM
26856+ case AuWbrCreate_PMFSRR:
26857+ case AuWbrCreate_PMFSRRV:
1facf9fc 26858+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
42a736d3 26859+ fallthrough;
1facf9fc 26860+ case AuWbrCreate_MFS:
26861+ case AuWbrCreate_MFSV:
26862+ case AuWbrCreate_PMFS:
26863+ case AuWbrCreate_PMFSV:
e49829fe
JR
26864+ sbinfo->si_wbr_mfs.mfs_expire
26865+ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC);
1facf9fc 26866+ break;
26867+ }
26868+
26869+ if (sbinfo->si_wbr_create_ops->init)
26870+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
26871+
26872+ return err;
26873+}
26874+
26875+/*
26876+ * returns,
26877+ * plus: processed without an error
26878+ * zero: unprocessed
26879+ */
26880+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
26881+ struct au_opts *opts)
26882+{
26883+ int err;
26884+ struct au_sbinfo *sbinfo;
26885+
dece6358
AM
26886+ SiMustWriteLock(sb);
26887+
1facf9fc 26888+ err = 1; /* handled */
26889+ sbinfo = au_sbi(sb);
26890+ switch (opt->type) {
26891+ case Opt_udba:
26892+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
26893+ sbinfo->si_mntflags |= opt->udba;
26894+ opts->given_udba |= opt->udba;
26895+ break;
26896+
26897+ case Opt_plink:
26898+ au_opt_set(sbinfo->si_mntflags, PLINK);
26899+ break;
26900+ case Opt_noplink:
26901+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
e49829fe 26902+ au_plink_put(sb, /*verbose*/1);
1facf9fc 26903+ au_opt_clr(sbinfo->si_mntflags, PLINK);
26904+ break;
26905+ case Opt_list_plink:
26906+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
26907+ au_plink_list(sb);
26908+ break;
26909+
4a4d8108
AM
26910+ case Opt_dio:
26911+ au_opt_set(sbinfo->si_mntflags, DIO);
26912+ au_fset_opts(opts->flags, REFRESH_DYAOP);
26913+ break;
26914+ case Opt_nodio:
26915+ au_opt_clr(sbinfo->si_mntflags, DIO);
26916+ au_fset_opts(opts->flags, REFRESH_DYAOP);
26917+ break;
26918+
076b876e
AM
26919+ case Opt_fhsm_sec:
26920+ au_fhsm_set(sbinfo, opt->fhsm_second);
26921+ break;
26922+
1facf9fc 26923+ case Opt_diropq_a:
26924+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
26925+ break;
26926+ case Opt_diropq_w:
26927+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
26928+ break;
26929+
26930+ case Opt_warn_perm:
26931+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
26932+ break;
26933+ case Opt_nowarn_perm:
26934+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
26935+ break;
26936+
1facf9fc 26937+ case Opt_verbose:
26938+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
26939+ break;
26940+ case Opt_noverbose:
26941+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
26942+ break;
26943+
26944+ case Opt_sum:
26945+ au_opt_set(sbinfo->si_mntflags, SUM);
26946+ break;
26947+ case Opt_wsum:
26948+ au_opt_clr(sbinfo->si_mntflags, SUM);
26949+ au_opt_set(sbinfo->si_mntflags, SUM_W);
eca34b5c 26950+ break;
1facf9fc 26951+ case Opt_nosum:
26952+ au_opt_clr(sbinfo->si_mntflags, SUM);
26953+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
26954+ break;
26955+
26956+ case Opt_wbr_create:
26957+ err = au_opt_wbr_create(sb, &opt->wbr_create);
26958+ break;
26959+ case Opt_wbr_copyup:
26960+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
26961+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
26962+ break;
26963+
26964+ case Opt_dirwh:
26965+ sbinfo->si_dirwh = opt->dirwh;
26966+ break;
26967+
26968+ case Opt_rdcache:
e49829fe
JR
26969+ sbinfo->si_rdcache
26970+ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
1facf9fc 26971+ break;
26972+ case Opt_rdblk:
26973+ sbinfo->si_rdblk = opt->rdblk;
26974+ break;
dece6358
AM
26975+ case Opt_rdblk_def:
26976+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
26977+ break;
1facf9fc 26978+ case Opt_rdhash:
26979+ sbinfo->si_rdhash = opt->rdhash;
26980+ break;
dece6358
AM
26981+ case Opt_rdhash_def:
26982+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
26983+ break;
26984+
26985+ case Opt_shwh:
26986+ au_opt_set(sbinfo->si_mntflags, SHWH);
26987+ break;
26988+ case Opt_noshwh:
26989+ au_opt_clr(sbinfo->si_mntflags, SHWH);
26990+ break;
1facf9fc 26991+
076b876e
AM
26992+ case Opt_dirperm1:
26993+ au_opt_set(sbinfo->si_mntflags, DIRPERM1);
26994+ break;
26995+ case Opt_nodirperm1:
26996+ au_opt_clr(sbinfo->si_mntflags, DIRPERM1);
26997+ break;
26998+
1facf9fc 26999+ case Opt_trunc_xino:
27000+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
27001+ break;
27002+ case Opt_notrunc_xino:
27003+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
27004+ break;
27005+
27006+ case Opt_trunc_xino_path:
27007+ case Opt_itrunc_xino:
acd2b654
AM
27008+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex,
27009+ /*idx_begin*/0);
1facf9fc 27010+ if (!err)
27011+ err = 1;
27012+ break;
27013+
27014+ case Opt_trunc_xib:
27015+ au_fset_opts(opts->flags, TRUNC_XIB);
27016+ break;
27017+ case Opt_notrunc_xib:
27018+ au_fclr_opts(opts->flags, TRUNC_XIB);
27019+ break;
27020+
8b6a4947
AM
27021+ case Opt_dirren:
27022+ err = 1;
27023+ if (!au_opt_test(sbinfo->si_mntflags, DIRREN)) {
27024+ err = au_dr_opt_set(sb);
27025+ if (!err)
27026+ err = 1;
27027+ }
27028+ if (err == 1)
27029+ au_opt_set(sbinfo->si_mntflags, DIRREN);
27030+ break;
27031+ case Opt_nodirren:
27032+ err = 1;
27033+ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) {
27034+ err = au_dr_opt_clr(sb, au_ftest_opts(opts->flags,
27035+ DR_FLUSHED));
27036+ if (!err)
27037+ err = 1;
27038+ }
27039+ if (err == 1)
27040+ au_opt_clr(sbinfo->si_mntflags, DIRREN);
27041+ break;
27042+
c1595e42 27043+ case Opt_acl:
2121bcd9 27044+ sb->s_flags |= SB_POSIXACL;
c1595e42
JR
27045+ break;
27046+ case Opt_noacl:
2121bcd9 27047+ sb->s_flags &= ~SB_POSIXACL;
c1595e42
JR
27048+ break;
27049+
1facf9fc 27050+ default:
27051+ err = 0;
27052+ break;
27053+ }
27054+
27055+ return err;
27056+}
27057+
27058+/*
27059+ * returns tri-state.
27060+ * plus: processed without an error
27061+ * zero: unprocessed
27062+ * minus: error
27063+ */
27064+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
27065+ struct au_opts *opts)
27066+{
27067+ int err, do_refresh;
27068+
27069+ err = 0;
27070+ switch (opt->type) {
27071+ case Opt_append:
5afbbe0d 27072+ opt->add.bindex = au_sbbot(sb) + 1;
1facf9fc 27073+ if (opt->add.bindex < 0)
27074+ opt->add.bindex = 0;
27075+ goto add;
eca34b5c 27076+ /* Always goto add, not fallthrough */
1facf9fc 27077+ case Opt_prepend:
27078+ opt->add.bindex = 0;
42a736d3 27079+ fallthrough;
f6b6e03d 27080+ add: /* indented label */
1facf9fc 27081+ case Opt_add:
27082+ err = au_br_add(sb, &opt->add,
27083+ au_ftest_opts(opts->flags, REMOUNT));
27084+ if (!err) {
27085+ err = 1;
027c5e7a 27086+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 27087+ }
27088+ break;
27089+
27090+ case Opt_del:
27091+ case Opt_idel:
27092+ err = au_br_del(sb, &opt->del,
27093+ au_ftest_opts(opts->flags, REMOUNT));
27094+ if (!err) {
27095+ err = 1;
27096+ au_fset_opts(opts->flags, TRUNC_XIB);
027c5e7a 27097+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 27098+ }
27099+ break;
27100+
27101+ case Opt_mod:
27102+ case Opt_imod:
27103+ err = au_br_mod(sb, &opt->mod,
27104+ au_ftest_opts(opts->flags, REMOUNT),
27105+ &do_refresh);
27106+ if (!err) {
27107+ err = 1;
027c5e7a
AM
27108+ if (do_refresh)
27109+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 27110+ }
27111+ break;
27112+ }
1facf9fc 27113+ return err;
27114+}
27115+
27116+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
27117+ struct au_opt_xino **opt_xino,
27118+ struct au_opts *opts)
27119+{
27120+ int err;
1facf9fc 27121+
27122+ err = 0;
27123+ switch (opt->type) {
27124+ case Opt_xino:
062440b3
AM
27125+ err = au_xino_set(sb, &opt->xino,
27126+ !!au_ftest_opts(opts->flags, REMOUNT));
27127+ if (unlikely(err))
27128+ break;
27129+
27130+ *opt_xino = &opt->xino;
1facf9fc 27131+ break;
27132+
27133+ case Opt_noxino:
27134+ au_xino_clr(sb);
1facf9fc 27135+ *opt_xino = (void *)-1;
27136+ break;
27137+ }
27138+
27139+ return err;
27140+}
27141+
27142+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
27143+ unsigned int pending)
27144+{
076b876e 27145+ int err, fhsm;
5afbbe0d 27146+ aufs_bindex_t bindex, bbot;
79b8bda9 27147+ unsigned char do_plink, skip, do_free, can_no_dreval;
1facf9fc 27148+ struct au_branch *br;
27149+ struct au_wbr *wbr;
79b8bda9 27150+ struct dentry *root, *dentry;
1facf9fc 27151+ struct inode *dir, *h_dir;
27152+ struct au_sbinfo *sbinfo;
27153+ struct au_hinode *hdir;
27154+
dece6358
AM
27155+ SiMustAnyLock(sb);
27156+
1facf9fc 27157+ sbinfo = au_sbi(sb);
27158+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
27159+
2121bcd9 27160+ if (!(sb_flags & SB_RDONLY)) {
dece6358 27161+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
0c3ec466 27162+ pr_warn("first branch should be rw\n");
dece6358 27163+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
febd17d6 27164+ pr_warn_once("shwh should be used with ro\n");
dece6358 27165+ }
1facf9fc 27166+
4a4d8108 27167+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1facf9fc 27168+ && !au_opt_test(sbinfo->si_mntflags, XINO))
febd17d6 27169+ pr_warn_once("udba=*notify requires xino\n");
1facf9fc 27170+
076b876e 27171+ if (au_opt_test(sbinfo->si_mntflags, DIRPERM1))
febd17d6
JR
27172+ pr_warn_once("dirperm1 breaks the protection"
27173+ " by the permission bits on the lower branch\n");
076b876e 27174+
1facf9fc 27175+ err = 0;
076b876e 27176+ fhsm = 0;
1facf9fc 27177+ root = sb->s_root;
5527c038 27178+ dir = d_inode(root);
1facf9fc 27179+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
79b8bda9
AM
27180+ can_no_dreval = !!au_opt_test((sbinfo->si_mntflags | pending),
27181+ UDBA_NONE);
5afbbe0d
AM
27182+ bbot = au_sbbot(sb);
27183+ for (bindex = 0; !err && bindex <= bbot; bindex++) {
1facf9fc 27184+ skip = 0;
27185+ h_dir = au_h_iptr(dir, bindex);
27186+ br = au_sbr(sb, bindex);
1facf9fc 27187+
c1595e42
JR
27188+ if ((br->br_perm & AuBrAttr_ICEX)
27189+ && !h_dir->i_op->listxattr)
27190+ br->br_perm &= ~AuBrAttr_ICEX;
43982f53 27191+#if 0 /* untested */
c1595e42 27192+ if ((br->br_perm & AuBrAttr_ICEX_SEC)
2121bcd9 27193+ && (au_br_sb(br)->s_flags & SB_NOSEC))
c1595e42
JR
27194+ br->br_perm &= ~AuBrAttr_ICEX_SEC;
27195+#endif
27196+
27197+ do_free = 0;
1facf9fc 27198+ wbr = br->br_wbr;
27199+ if (wbr)
27200+ wbr_wh_read_lock(wbr);
27201+
1e00d052 27202+ if (!au_br_writable(br->br_perm)) {
1facf9fc 27203+ do_free = !!wbr;
27204+ skip = (!wbr
27205+ || (!wbr->wbr_whbase
27206+ && !wbr->wbr_plink
27207+ && !wbr->wbr_orph));
1e00d052 27208+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 27209+ /* skip = (!br->br_whbase && !br->br_orph); */
27210+ skip = (!wbr || !wbr->wbr_whbase);
27211+ if (skip && wbr) {
27212+ if (do_plink)
27213+ skip = !!wbr->wbr_plink;
27214+ else
27215+ skip = !wbr->wbr_plink;
27216+ }
1e00d052 27217+ } else {
1facf9fc 27218+ /* skip = (br->br_whbase && br->br_ohph); */
27219+ skip = (wbr && wbr->wbr_whbase);
27220+ if (skip) {
27221+ if (do_plink)
27222+ skip = !!wbr->wbr_plink;
27223+ else
27224+ skip = !wbr->wbr_plink;
27225+ }
1facf9fc 27226+ }
27227+ if (wbr)
27228+ wbr_wh_read_unlock(wbr);
27229+
79b8bda9
AM
27230+ if (can_no_dreval) {
27231+ dentry = br->br_path.dentry;
27232+ spin_lock(&dentry->d_lock);
27233+ if (dentry->d_flags &
27234+ (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE))
27235+ can_no_dreval = 0;
27236+ spin_unlock(&dentry->d_lock);
27237+ }
27238+
076b876e
AM
27239+ if (au_br_fhsm(br->br_perm)) {
27240+ fhsm++;
27241+ AuDebugOn(!br->br_fhsm);
27242+ }
27243+
1facf9fc 27244+ if (skip)
27245+ continue;
27246+
27247+ hdir = au_hi(dir, bindex);
5afbbe0d 27248+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 27249+ if (wbr)
27250+ wbr_wh_write_lock(wbr);
86dc4139 27251+ err = au_wh_init(br, sb);
1facf9fc 27252+ if (wbr)
27253+ wbr_wh_write_unlock(wbr);
5afbbe0d 27254+ au_hn_inode_unlock(hdir);
1facf9fc 27255+
27256+ if (!err && do_free) {
9f237c51 27257+ au_kfree_rcu(wbr);
1facf9fc 27258+ br->br_wbr = NULL;
27259+ }
27260+ }
27261+
79b8bda9
AM
27262+ if (can_no_dreval)
27263+ au_fset_si(sbinfo, NO_DREVAL);
27264+ else
27265+ au_fclr_si(sbinfo, NO_DREVAL);
27266+
c1595e42 27267+ if (fhsm >= 2) {
076b876e 27268+ au_fset_si(sbinfo, FHSM);
5afbbe0d 27269+ for (bindex = bbot; bindex >= 0; bindex--) {
c1595e42
JR
27270+ br = au_sbr(sb, bindex);
27271+ if (au_br_fhsm(br->br_perm)) {
27272+ au_fhsm_set_bottom(sb, bindex);
27273+ break;
27274+ }
27275+ }
27276+ } else {
076b876e 27277+ au_fclr_si(sbinfo, FHSM);
c1595e42
JR
27278+ au_fhsm_set_bottom(sb, -1);
27279+ }
076b876e 27280+
1facf9fc 27281+ return err;
27282+}
27283+
27284+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
27285+{
27286+ int err;
27287+ unsigned int tmp;
5afbbe0d 27288+ aufs_bindex_t bindex, bbot;
1facf9fc 27289+ struct au_opt *opt;
27290+ struct au_opt_xino *opt_xino, xino;
27291+ struct au_sbinfo *sbinfo;
027c5e7a 27292+ struct au_branch *br;
076b876e 27293+ struct inode *dir;
1facf9fc 27294+
dece6358
AM
27295+ SiMustWriteLock(sb);
27296+
1facf9fc 27297+ err = 0;
27298+ opt_xino = NULL;
27299+ opt = opts->opt;
27300+ while (err >= 0 && opt->type != Opt_tail)
27301+ err = au_opt_simple(sb, opt++, opts);
27302+ if (err > 0)
27303+ err = 0;
27304+ else if (unlikely(err < 0))
27305+ goto out;
27306+
27307+ /* disable xino and udba temporary */
27308+ sbinfo = au_sbi(sb);
27309+ tmp = sbinfo->si_mntflags;
27310+ au_opt_clr(sbinfo->si_mntflags, XINO);
27311+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
27312+
27313+ opt = opts->opt;
27314+ while (err >= 0 && opt->type != Opt_tail)
27315+ err = au_opt_br(sb, opt++, opts);
27316+ if (err > 0)
27317+ err = 0;
27318+ else if (unlikely(err < 0))
27319+ goto out;
27320+
5afbbe0d
AM
27321+ bbot = au_sbbot(sb);
27322+ if (unlikely(bbot < 0)) {
1facf9fc 27323+ err = -EINVAL;
4a4d8108 27324+ pr_err("no branches\n");
1facf9fc 27325+ goto out;
27326+ }
27327+
27328+ if (au_opt_test(tmp, XINO))
27329+ au_opt_set(sbinfo->si_mntflags, XINO);
27330+ opt = opts->opt;
27331+ while (!err && opt->type != Opt_tail)
27332+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
27333+ if (unlikely(err))
27334+ goto out;
27335+
27336+ err = au_opts_verify(sb, sb->s_flags, tmp);
27337+ if (unlikely(err))
27338+ goto out;
27339+
27340+ /* restore xino */
27341+ if (au_opt_test(tmp, XINO) && !opt_xino) {
27342+ xino.file = au_xino_def(sb);
27343+ err = PTR_ERR(xino.file);
27344+ if (IS_ERR(xino.file))
27345+ goto out;
27346+
27347+ err = au_xino_set(sb, &xino, /*remount*/0);
27348+ fput(xino.file);
27349+ if (unlikely(err))
27350+ goto out;
27351+ }
27352+
27353+ /* restore udba */
027c5e7a 27354+ tmp &= AuOptMask_UDBA;
1facf9fc 27355+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
027c5e7a 27356+ sbinfo->si_mntflags |= tmp;
5afbbe0d
AM
27357+ bbot = au_sbbot(sb);
27358+ for (bindex = 0; bindex <= bbot; bindex++) {
027c5e7a
AM
27359+ br = au_sbr(sb, bindex);
27360+ err = au_hnotify_reset_br(tmp, br, br->br_perm);
27361+ if (unlikely(err))
27362+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
27363+ bindex, err);
27364+ /* go on even if err */
27365+ }
4a4d8108 27366+ if (au_opt_test(tmp, UDBA_HNOTIFY)) {
5527c038 27367+ dir = d_inode(sb->s_root);
4a4d8108 27368+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1facf9fc 27369+ }
27370+
4f0767ce 27371+out:
1facf9fc 27372+ return err;
27373+}
27374+
27375+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
27376+{
27377+ int err, rerr;
79b8bda9 27378+ unsigned char no_dreval;
1facf9fc 27379+ struct inode *dir;
27380+ struct au_opt_xino *opt_xino;
27381+ struct au_opt *opt;
27382+ struct au_sbinfo *sbinfo;
27383+
dece6358
AM
27384+ SiMustWriteLock(sb);
27385+
8b6a4947
AM
27386+ err = au_dr_opt_flush(sb);
27387+ if (unlikely(err))
27388+ goto out;
27389+ au_fset_opts(opts->flags, DR_FLUSHED);
27390+
5527c038 27391+ dir = d_inode(sb->s_root);
1facf9fc 27392+ sbinfo = au_sbi(sb);
1facf9fc 27393+ opt_xino = NULL;
27394+ opt = opts->opt;
27395+ while (err >= 0 && opt->type != Opt_tail) {
27396+ err = au_opt_simple(sb, opt, opts);
27397+ if (!err)
27398+ err = au_opt_br(sb, opt, opts);
27399+ if (!err)
27400+ err = au_opt_xino(sb, opt, &opt_xino, opts);
27401+ opt++;
27402+ }
27403+ if (err > 0)
27404+ err = 0;
27405+ AuTraceErr(err);
27406+ /* go on even err */
27407+
79b8bda9 27408+ no_dreval = !!au_ftest_si(sbinfo, NO_DREVAL);
1facf9fc 27409+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
27410+ if (unlikely(rerr && !err))
27411+ err = rerr;
27412+
79b8bda9 27413+ if (no_dreval != !!au_ftest_si(sbinfo, NO_DREVAL))
b95c5147 27414+ au_fset_opts(opts->flags, REFRESH_IDOP);
79b8bda9 27415+
1facf9fc 27416+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
27417+ rerr = au_xib_trunc(sb);
27418+ if (unlikely(rerr && !err))
27419+ err = rerr;
27420+ }
27421+
27422+ /* will be handled by the caller */
027c5e7a 27423+ if (!au_ftest_opts(opts->flags, REFRESH)
79b8bda9
AM
27424+ && (opts->given_udba
27425+ || au_opt_test(sbinfo->si_mntflags, XINO)
b95c5147 27426+ || au_ftest_opts(opts->flags, REFRESH_IDOP)
79b8bda9 27427+ ))
027c5e7a 27428+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 27429+
27430+ AuDbg("status 0x%x\n", opts->flags);
8b6a4947
AM
27431+
27432+out:
1facf9fc 27433+ return err;
27434+}
27435+
27436+/* ---------------------------------------------------------------------- */
27437+
27438+unsigned int au_opt_udba(struct super_block *sb)
27439+{
27440+ return au_mntflags(sb) & AuOptMask_UDBA;
27441+}
7f207e10 27442diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
eca34b5c 27443--- /usr/share/empty/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
319657f6 27444+++ linux/fs/aufs/opts.h 2021-12-03 15:38:59.939980643 +0100
062440b3
AM
27445@@ -0,0 +1,225 @@
27446+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 27447+/*
6d176551 27448+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 27449+ *
27450+ * This program, aufs is free software; you can redistribute it and/or modify
27451+ * it under the terms of the GNU General Public License as published by
27452+ * the Free Software Foundation; either version 2 of the License, or
27453+ * (at your option) any later version.
dece6358
AM
27454+ *
27455+ * This program is distributed in the hope that it will be useful,
27456+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27457+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27458+ * GNU General Public License for more details.
27459+ *
27460+ * You should have received a copy of the GNU General Public License
523b37e3 27461+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 27462+ */
27463+
27464+/*
27465+ * mount options/flags
27466+ */
27467+
27468+#ifndef __AUFS_OPTS_H__
27469+#define __AUFS_OPTS_H__
27470+
27471+#ifdef __KERNEL__
27472+
dece6358 27473+#include <linux/path.h>
1facf9fc 27474+
dece6358 27475+struct file;
dece6358 27476+
1facf9fc 27477+/* ---------------------------------------------------------------------- */
27478+
27479+/* mount flags */
27480+#define AuOpt_XINO 1 /* external inode number bitmap
27481+ and translation table */
27482+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
27483+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
27484+#define AuOpt_UDBA_REVAL (1 << 3)
4a4d8108 27485+#define AuOpt_UDBA_HNOTIFY (1 << 4)
dece6358
AM
27486+#define AuOpt_SHWH (1 << 5) /* show whiteout */
27487+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
076b876e
AM
27488+#define AuOpt_DIRPERM1 (1 << 7) /* ignore the lower dir's perm
27489+ bits */
dece6358
AM
27490+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
27491+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
27492+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
27493+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
eca801bf 27494+#define AuOpt_VERBOSE (1 << 13) /* print the cause of error */
4a4d8108 27495+#define AuOpt_DIO (1 << 14) /* direct io */
8b6a4947 27496+#define AuOpt_DIRREN (1 << 15) /* directory rename */
1facf9fc 27497+
4a4d8108
AM
27498+#ifndef CONFIG_AUFS_HNOTIFY
27499+#undef AuOpt_UDBA_HNOTIFY
27500+#define AuOpt_UDBA_HNOTIFY 0
1facf9fc 27501+#endif
8b6a4947
AM
27502+#ifndef CONFIG_AUFS_DIRREN
27503+#undef AuOpt_DIRREN
27504+#define AuOpt_DIRREN 0
27505+#endif
dece6358
AM
27506+#ifndef CONFIG_AUFS_SHWH
27507+#undef AuOpt_SHWH
27508+#define AuOpt_SHWH 0
27509+#endif
1facf9fc 27510+
27511+#define AuOpt_Def (AuOpt_XINO \
27512+ | AuOpt_UDBA_REVAL \
27513+ | AuOpt_PLINK \
27514+ /* | AuOpt_DIRPERM1 */ \
27515+ | AuOpt_WARN_PERM)
27516+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
27517+ | AuOpt_UDBA_REVAL \
4a4d8108 27518+ | AuOpt_UDBA_HNOTIFY)
1facf9fc 27519+
27520+#define au_opt_test(flags, name) (flags & AuOpt_##name)
27521+#define au_opt_set(flags, name) do { \
27522+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
27523+ ((flags) |= AuOpt_##name); \
27524+} while (0)
27525+#define au_opt_set_udba(flags, name) do { \
27526+ (flags) &= ~AuOptMask_UDBA; \
27527+ ((flags) |= AuOpt_##name); \
27528+} while (0)
7f207e10
AM
27529+#define au_opt_clr(flags, name) do { \
27530+ ((flags) &= ~AuOpt_##name); \
27531+} while (0)
1facf9fc 27532+
e49829fe
JR
27533+static inline unsigned int au_opts_plink(unsigned int mntflags)
27534+{
27535+#ifdef CONFIG_PROC_FS
27536+ return mntflags;
27537+#else
27538+ return mntflags & ~AuOpt_PLINK;
27539+#endif
27540+}
27541+
1facf9fc 27542+/* ---------------------------------------------------------------------- */
27543+
27544+/* policies to select one among multiple writable branches */
27545+enum {
27546+ AuWbrCreate_TDP, /* top down parent */
27547+ AuWbrCreate_RR, /* round robin */
27548+ AuWbrCreate_MFS, /* most free space */
27549+ AuWbrCreate_MFSV, /* mfs with seconds */
27550+ AuWbrCreate_MFSRR, /* mfs then rr */
27551+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
f2c43d5f
AM
27552+ AuWbrCreate_TDMFS, /* top down regardless parent and mfs */
27553+ AuWbrCreate_TDMFSV, /* top down regardless parent and mfs */
1facf9fc 27554+ AuWbrCreate_PMFS, /* parent and mfs */
27555+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
392086de
AM
27556+ AuWbrCreate_PMFSRR, /* parent, mfs and round-robin */
27557+ AuWbrCreate_PMFSRRV, /* plus seconds */
1facf9fc 27558+
27559+ AuWbrCreate_Def = AuWbrCreate_TDP
27560+};
27561+
27562+enum {
27563+ AuWbrCopyup_TDP, /* top down parent */
27564+ AuWbrCopyup_BUP, /* bottom up parent */
27565+ AuWbrCopyup_BU, /* bottom up */
27566+
27567+ AuWbrCopyup_Def = AuWbrCopyup_TDP
27568+};
27569+
27570+/* ---------------------------------------------------------------------- */
27571+
27572+struct au_opt_add {
27573+ aufs_bindex_t bindex;
27574+ char *pathname;
27575+ int perm;
27576+ struct path path;
27577+};
27578+
27579+struct au_opt_del {
27580+ char *pathname;
27581+ struct path h_path;
27582+};
27583+
27584+struct au_opt_mod {
27585+ char *path;
27586+ int perm;
27587+ struct dentry *h_root;
27588+};
27589+
27590+struct au_opt_xino {
27591+ char *path;
27592+ struct file *file;
27593+};
27594+
27595+struct au_opt_xino_itrunc {
27596+ aufs_bindex_t bindex;
27597+};
27598+
27599+struct au_opt_wbr_create {
27600+ int wbr_create;
27601+ int mfs_second;
27602+ unsigned long long mfsrr_watermark;
27603+};
27604+
27605+struct au_opt {
27606+ int type;
27607+ union {
27608+ struct au_opt_xino xino;
27609+ struct au_opt_xino_itrunc xino_itrunc;
27610+ struct au_opt_add add;
27611+ struct au_opt_del del;
27612+ struct au_opt_mod mod;
27613+ int dirwh;
27614+ int rdcache;
27615+ unsigned int rdblk;
27616+ unsigned int rdhash;
27617+ int udba;
27618+ struct au_opt_wbr_create wbr_create;
27619+ int wbr_copyup;
076b876e 27620+ unsigned int fhsm_second;
1facf9fc 27621+ };
27622+};
27623+
27624+/* opts flags */
27625+#define AuOpts_REMOUNT 1
027c5e7a
AM
27626+#define AuOpts_REFRESH (1 << 1)
27627+#define AuOpts_TRUNC_XIB (1 << 2)
27628+#define AuOpts_REFRESH_DYAOP (1 << 3)
b95c5147 27629+#define AuOpts_REFRESH_IDOP (1 << 4)
8b6a4947 27630+#define AuOpts_DR_FLUSHED (1 << 5)
1facf9fc 27631+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
7f207e10
AM
27632+#define au_fset_opts(flags, name) \
27633+ do { (flags) |= AuOpts_##name; } while (0)
27634+#define au_fclr_opts(flags, name) \
27635+ do { (flags) &= ~AuOpts_##name; } while (0)
1facf9fc 27636+
8b6a4947
AM
27637+#ifndef CONFIG_AUFS_DIRREN
27638+#undef AuOpts_DR_FLUSHED
27639+#define AuOpts_DR_FLUSHED 0
27640+#endif
27641+
1facf9fc 27642+struct au_opts {
27643+ struct au_opt *opt;
27644+ int max_opt;
27645+
27646+ unsigned int given_udba;
27647+ unsigned int flags;
27648+ unsigned long sb_flags;
27649+};
27650+
27651+/* ---------------------------------------------------------------------- */
27652+
7e9cd9fe 27653+/* opts.c */
076b876e 27654+void au_optstr_br_perm(au_br_perm_str_t *str, int perm);
1facf9fc 27655+const char *au_optstr_udba(int udba);
27656+const char *au_optstr_wbr_copyup(int wbr_copyup);
27657+const char *au_optstr_wbr_create(int wbr_create);
27658+
27659+void au_opts_free(struct au_opts *opts);
3c1bdaff 27660+struct super_block;
1facf9fc 27661+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
27662+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
27663+ unsigned int pending);
27664+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
27665+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
27666+
27667+unsigned int au_opt_udba(struct super_block *sb);
27668+
1facf9fc 27669+#endif /* __KERNEL__ */
27670+#endif /* __AUFS_OPTS_H__ */
7f207e10 27671diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
eca34b5c 27672--- /usr/share/empty/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
319657f6 27673+++ linux/fs/aufs/plink.c 2021-12-03 15:38:59.939980643 +0100
062440b3 27674@@ -0,0 +1,516 @@
cd7a4cd9 27675+// SPDX-License-Identifier: GPL-2.0
1facf9fc 27676+/*
6d176551 27677+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 27678+ *
27679+ * This program, aufs is free software; you can redistribute it and/or modify
27680+ * it under the terms of the GNU General Public License as published by
27681+ * the Free Software Foundation; either version 2 of the License, or
27682+ * (at your option) any later version.
dece6358
AM
27683+ *
27684+ * This program is distributed in the hope that it will be useful,
27685+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27686+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27687+ * GNU General Public License for more details.
27688+ *
27689+ * You should have received a copy of the GNU General Public License
523b37e3 27690+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 27691+ */
27692+
27693+/*
27694+ * pseudo-link
27695+ */
27696+
27697+#include "aufs.h"
27698+
27699+/*
e49829fe 27700+ * the pseudo-link maintenance mode.
1facf9fc 27701+ * during a user process maintains the pseudo-links,
27702+ * prohibit adding a new plink and branch manipulation.
e49829fe
JR
27703+ *
27704+ * Flags
27705+ * NOPLM:
27706+ * For entry functions which will handle plink, and i_mutex is already held
27707+ * in VFS.
27708+ * They cannot wait and should return an error at once.
27709+ * Callers has to check the error.
27710+ * NOPLMW:
27711+ * For entry functions which will handle plink, but i_mutex is not held
27712+ * in VFS.
27713+ * They can wait the plink maintenance mode to finish.
27714+ *
27715+ * They behave like F_SETLK and F_SETLKW.
27716+ * If the caller never handle plink, then both flags are unnecessary.
1facf9fc 27717+ */
e49829fe
JR
27718+
27719+int au_plink_maint(struct super_block *sb, int flags)
1facf9fc 27720+{
e49829fe
JR
27721+ int err;
27722+ pid_t pid, ppid;
f0c0a007 27723+ struct task_struct *parent, *prev;
e49829fe 27724+ struct au_sbinfo *sbi;
dece6358
AM
27725+
27726+ SiMustAnyLock(sb);
27727+
e49829fe
JR
27728+ err = 0;
27729+ if (!au_opt_test(au_mntflags(sb), PLINK))
27730+ goto out;
27731+
27732+ sbi = au_sbi(sb);
27733+ pid = sbi->si_plink_maint_pid;
27734+ if (!pid || pid == current->pid)
27735+ goto out;
27736+
27737+ /* todo: it highly depends upon /sbin/mount.aufs */
f0c0a007
AM
27738+ prev = NULL;
27739+ parent = current;
27740+ ppid = 0;
e49829fe 27741+ rcu_read_lock();
f0c0a007
AM
27742+ while (1) {
27743+ parent = rcu_dereference(parent->real_parent);
27744+ if (parent == prev)
27745+ break;
27746+ ppid = task_pid_vnr(parent);
27747+ if (pid == ppid) {
27748+ rcu_read_unlock();
27749+ goto out;
27750+ }
27751+ prev = parent;
27752+ }
e49829fe 27753+ rcu_read_unlock();
e49829fe
JR
27754+
27755+ if (au_ftest_lock(flags, NOPLMW)) {
027c5e7a
AM
27756+ /* if there is no i_mutex lock in VFS, we don't need to wait */
27757+ /* AuDebugOn(!lockdep_depth(current)); */
e49829fe
JR
27758+ while (sbi->si_plink_maint_pid) {
27759+ si_read_unlock(sb);
27760+ /* gave up wake_up_bit() */
27761+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid);
27762+
27763+ if (au_ftest_lock(flags, FLUSH))
27764+ au_nwt_flush(&sbi->si_nowait);
27765+ si_noflush_read_lock(sb);
27766+ }
27767+ } else if (au_ftest_lock(flags, NOPLM)) {
27768+ AuDbg("ppid %d, pid %d\n", ppid, pid);
27769+ err = -EAGAIN;
27770+ }
27771+
27772+out:
27773+ return err;
4a4d8108
AM
27774+}
27775+
e49829fe 27776+void au_plink_maint_leave(struct au_sbinfo *sbinfo)
4a4d8108 27777+{
4a4d8108 27778+ spin_lock(&sbinfo->si_plink_maint_lock);
027c5e7a 27779+ sbinfo->si_plink_maint_pid = 0;
4a4d8108 27780+ spin_unlock(&sbinfo->si_plink_maint_lock);
027c5e7a 27781+ wake_up_all(&sbinfo->si_plink_wq);
4a4d8108
AM
27782+}
27783+
e49829fe 27784+int au_plink_maint_enter(struct super_block *sb)
4a4d8108
AM
27785+{
27786+ int err;
4a4d8108
AM
27787+ struct au_sbinfo *sbinfo;
27788+
27789+ err = 0;
4a4d8108
AM
27790+ sbinfo = au_sbi(sb);
27791+ /* make sure i am the only one in this fs */
e49829fe
JR
27792+ si_write_lock(sb, AuLock_FLUSH);
27793+ if (au_opt_test(au_mntflags(sb), PLINK)) {
27794+ spin_lock(&sbinfo->si_plink_maint_lock);
27795+ if (!sbinfo->si_plink_maint_pid)
27796+ sbinfo->si_plink_maint_pid = current->pid;
27797+ else
27798+ err = -EBUSY;
27799+ spin_unlock(&sbinfo->si_plink_maint_lock);
27800+ }
4a4d8108
AM
27801+ si_write_unlock(sb);
27802+
27803+ return err;
1facf9fc 27804+}
27805+
27806+/* ---------------------------------------------------------------------- */
27807+
1facf9fc 27808+#ifdef CONFIG_AUFS_DEBUG
27809+void au_plink_list(struct super_block *sb)
27810+{
86dc4139 27811+ int i;
1facf9fc 27812+ struct au_sbinfo *sbinfo;
8b6a4947
AM
27813+ struct hlist_bl_head *hbl;
27814+ struct hlist_bl_node *pos;
5afbbe0d 27815+ struct au_icntnr *icntnr;
1facf9fc 27816+
dece6358
AM
27817+ SiMustAnyLock(sb);
27818+
1facf9fc 27819+ sbinfo = au_sbi(sb);
27820+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 27821+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 27822+
86dc4139 27823+ for (i = 0; i < AuPlink_NHASH; i++) {
8b6a4947
AM
27824+ hbl = sbinfo->si_plink + i;
27825+ hlist_bl_lock(hbl);
27826+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink)
5afbbe0d 27827+ AuDbg("%lu\n", icntnr->vfs_inode.i_ino);
8b6a4947 27828+ hlist_bl_unlock(hbl);
86dc4139 27829+ }
1facf9fc 27830+}
27831+#endif
27832+
27833+/* is the inode pseudo-linked? */
27834+int au_plink_test(struct inode *inode)
27835+{
86dc4139 27836+ int found, i;
1facf9fc 27837+ struct au_sbinfo *sbinfo;
8b6a4947
AM
27838+ struct hlist_bl_head *hbl;
27839+ struct hlist_bl_node *pos;
5afbbe0d 27840+ struct au_icntnr *icntnr;
1facf9fc 27841+
27842+ sbinfo = au_sbi(inode->i_sb);
dece6358 27843+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 27844+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
e49829fe 27845+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
1facf9fc 27846+
27847+ found = 0;
86dc4139 27848+ i = au_plink_hash(inode->i_ino);
8b6a4947
AM
27849+ hbl = sbinfo->si_plink + i;
27850+ hlist_bl_lock(hbl);
27851+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink)
5afbbe0d 27852+ if (&icntnr->vfs_inode == inode) {
1facf9fc 27853+ found = 1;
27854+ break;
27855+ }
8b6a4947 27856+ hlist_bl_unlock(hbl);
1facf9fc 27857+ return found;
27858+}
27859+
27860+/* ---------------------------------------------------------------------- */
27861+
27862+/*
27863+ * generate a name for plink.
27864+ * the file will be stored under AUFS_WH_PLINKDIR.
27865+ */
27866+/* 20 is max digits length of ulong 64 */
27867+#define PLINK_NAME_LEN ((20 + 1) * 2)
27868+
27869+static int plink_name(char *name, int len, struct inode *inode,
27870+ aufs_bindex_t bindex)
27871+{
27872+ int rlen;
27873+ struct inode *h_inode;
27874+
27875+ h_inode = au_h_iptr(inode, bindex);
27876+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
27877+ return rlen;
27878+}
27879+
7f207e10
AM
27880+struct au_do_plink_lkup_args {
27881+ struct dentry **errp;
27882+ struct qstr *tgtname;
758e9dad 27883+ struct path *h_ppath;
7f207e10
AM
27884+};
27885+
27886+static struct dentry *au_do_plink_lkup(struct qstr *tgtname,
758e9dad 27887+ struct path *h_ppath)
7f207e10
AM
27888+{
27889+ struct dentry *h_dentry;
febd17d6 27890+ struct inode *h_inode;
7f207e10 27891+
758e9dad 27892+ h_inode = d_inode(h_ppath->dentry);
be118d29 27893+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD2);
758e9dad 27894+ h_dentry = vfsub_lkup_one(tgtname, h_ppath);
3c1bdaff 27895+ inode_unlock_shared(h_inode);
758e9dad 27896+
7f207e10
AM
27897+ return h_dentry;
27898+}
27899+
27900+static void au_call_do_plink_lkup(void *args)
27901+{
27902+ struct au_do_plink_lkup_args *a = args;
758e9dad 27903+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_ppath);
7f207e10
AM
27904+}
27905+
1facf9fc 27906+/* lookup the plink-ed @inode under the branch at @bindex */
27907+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
27908+{
758e9dad 27909+ struct dentry *h_dentry;
1facf9fc 27910+ struct au_branch *br;
758e9dad 27911+ struct path h_ppath;
7f207e10 27912+ int wkq_err;
1facf9fc 27913+ char a[PLINK_NAME_LEN];
0c3ec466 27914+ struct qstr tgtname = QSTR_INIT(a, 0);
1facf9fc 27915+
e49829fe
JR
27916+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
27917+
1facf9fc 27918+ br = au_sbr(inode->i_sb, bindex);
758e9dad
AM
27919+ h_ppath.dentry = br->br_wbr->wbr_plink;
27920+ h_ppath.mnt = au_br_mnt(br);
1facf9fc 27921+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
27922+
2dfbb274 27923+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) {
7f207e10
AM
27924+ struct au_do_plink_lkup_args args = {
27925+ .errp = &h_dentry,
27926+ .tgtname = &tgtname,
758e9dad 27927+ .h_ppath = &h_ppath
7f207e10
AM
27928+ };
27929+
27930+ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args);
27931+ if (unlikely(wkq_err))
27932+ h_dentry = ERR_PTR(wkq_err);
27933+ } else
758e9dad 27934+ h_dentry = au_do_plink_lkup(&tgtname, &h_ppath);
7f207e10 27935+
1facf9fc 27936+ return h_dentry;
27937+}
27938+
27939+/* create a pseudo-link */
758e9dad
AM
27940+static int do_whplink(struct qstr *tgt, struct path *h_ppath,
27941+ struct dentry *h_dentry)
1facf9fc 27942+{
27943+ int err;
758e9dad 27944+ struct path h_path;
523b37e3 27945+ struct inode *h_dir, *delegated;
1facf9fc 27946+
758e9dad 27947+ h_dir = d_inode(h_ppath->dentry);
febd17d6 27948+ inode_lock_nested(h_dir, AuLsc_I_CHILD2);
758e9dad 27949+ h_path.mnt = h_ppath->mnt;
4f0767ce 27950+again:
758e9dad 27951+ h_path.dentry = vfsub_lkup_one(tgt, h_ppath);
1facf9fc 27952+ err = PTR_ERR(h_path.dentry);
27953+ if (IS_ERR(h_path.dentry))
27954+ goto out;
27955+
27956+ err = 0;
27957+ /* wh.plink dir is not monitored */
7f207e10 27958+ /* todo: is it really safe? */
5527c038
JR
27959+ if (d_is_positive(h_path.dentry)
27960+ && d_inode(h_path.dentry) != d_inode(h_dentry)) {
523b37e3
AM
27961+ delegated = NULL;
27962+ err = vfsub_unlink(h_dir, &h_path, &delegated, /*force*/0);
27963+ if (unlikely(err == -EWOULDBLOCK)) {
27964+ pr_warn("cannot retry for NFSv4 delegation"
27965+ " for an internal unlink\n");
27966+ iput(delegated);
27967+ }
1facf9fc 27968+ dput(h_path.dentry);
27969+ h_path.dentry = NULL;
27970+ if (!err)
27971+ goto again;
27972+ }
5527c038 27973+ if (!err && d_is_negative(h_path.dentry)) {
523b37e3
AM
27974+ delegated = NULL;
27975+ err = vfsub_link(h_dentry, h_dir, &h_path, &delegated);
27976+ if (unlikely(err == -EWOULDBLOCK)) {
27977+ pr_warn("cannot retry for NFSv4 delegation"
27978+ " for an internal link\n");
27979+ iput(delegated);
27980+ }
27981+ }
1facf9fc 27982+ dput(h_path.dentry);
27983+
4f0767ce 27984+out:
febd17d6 27985+ inode_unlock(h_dir);
1facf9fc 27986+ return err;
27987+}
27988+
27989+struct do_whplink_args {
27990+ int *errp;
27991+ struct qstr *tgt;
758e9dad 27992+ struct path *h_ppath;
1facf9fc 27993+ struct dentry *h_dentry;
1facf9fc 27994+};
27995+
27996+static void call_do_whplink(void *args)
27997+{
27998+ struct do_whplink_args *a = args;
758e9dad 27999+ *a->errp = do_whplink(a->tgt, a->h_ppath, a->h_dentry);
1facf9fc 28000+}
28001+
28002+static int whplink(struct dentry *h_dentry, struct inode *inode,
758e9dad 28003+ aufs_bindex_t bindex)
1facf9fc 28004+{
28005+ int err, wkq_err;
758e9dad 28006+ struct au_branch *br;
1facf9fc 28007+ struct au_wbr *wbr;
758e9dad 28008+ struct path h_ppath;
1facf9fc 28009+ char a[PLINK_NAME_LEN];
0c3ec466 28010+ struct qstr tgtname = QSTR_INIT(a, 0);
1facf9fc 28011+
758e9dad
AM
28012+ br = au_sbr(inode->i_sb, bindex);
28013+ wbr = br->br_wbr;
28014+ h_ppath.dentry = wbr->wbr_plink;
28015+ h_ppath.mnt = au_br_mnt(br);
1facf9fc 28016+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
28017+
28018+ /* always superio. */
2dfbb274 28019+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) {
1facf9fc 28020+ struct do_whplink_args args = {
28021+ .errp = &err,
28022+ .tgt = &tgtname,
758e9dad
AM
28023+ .h_ppath = &h_ppath,
28024+ .h_dentry = h_dentry
1facf9fc 28025+ };
28026+ wkq_err = au_wkq_wait(call_do_whplink, &args);
28027+ if (unlikely(wkq_err))
28028+ err = wkq_err;
28029+ } else
758e9dad 28030+ err = do_whplink(&tgtname, &h_ppath, h_dentry);
1facf9fc 28031+
28032+ return err;
28033+}
28034+
1facf9fc 28035+/*
28036+ * create a new pseudo-link for @h_dentry on @bindex.
28037+ * the linked inode is held in aufs @inode.
28038+ */
28039+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
28040+ struct dentry *h_dentry)
28041+{
28042+ struct super_block *sb;
28043+ struct au_sbinfo *sbinfo;
8b6a4947
AM
28044+ struct hlist_bl_head *hbl;
28045+ struct hlist_bl_node *pos;
5afbbe0d 28046+ struct au_icntnr *icntnr;
86dc4139 28047+ int found, err, cnt, i;
1facf9fc 28048+
28049+ sb = inode->i_sb;
28050+ sbinfo = au_sbi(sb);
28051+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 28052+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 28053+
86dc4139 28054+ found = au_plink_test(inode);
4a4d8108 28055+ if (found)
1facf9fc 28056+ return;
4a4d8108 28057+
86dc4139 28058+ i = au_plink_hash(inode->i_ino);
8b6a4947 28059+ hbl = sbinfo->si_plink + i;
5afbbe0d 28060+ au_igrab(inode);
1facf9fc 28061+
8b6a4947
AM
28062+ hlist_bl_lock(hbl);
28063+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) {
5afbbe0d 28064+ if (&icntnr->vfs_inode == inode) {
4a4d8108
AM
28065+ found = 1;
28066+ break;
28067+ }
1facf9fc 28068+ }
5afbbe0d
AM
28069+ if (!found) {
28070+ icntnr = container_of(inode, struct au_icntnr, vfs_inode);
8b6a4947 28071+ hlist_bl_add_head(&icntnr->plink, hbl);
5afbbe0d 28072+ }
8b6a4947 28073+ hlist_bl_unlock(hbl);
4a4d8108 28074+ if (!found) {
8b6a4947 28075+ cnt = au_hbl_count(hbl);
acd2b654 28076+#define msg "unexpectedly unbalanced or too many pseudo-links"
86dc4139
AM
28077+ if (cnt > AUFS_PLINK_WARN)
28078+ AuWarn1(msg ", %d\n", cnt);
28079+#undef msg
758e9dad 28080+ err = whplink(h_dentry, inode, bindex);
5afbbe0d
AM
28081+ if (unlikely(err)) {
28082+ pr_warn("err %d, damaged pseudo link.\n", err);
8b6a4947 28083+ au_hbl_del(&icntnr->plink, hbl);
5afbbe0d 28084+ iput(&icntnr->vfs_inode);
4a4d8108 28085+ }
5afbbe0d
AM
28086+ } else
28087+ iput(&icntnr->vfs_inode);
1facf9fc 28088+}
28089+
28090+/* free all plinks */
e49829fe 28091+void au_plink_put(struct super_block *sb, int verbose)
1facf9fc 28092+{
86dc4139 28093+ int i, warned;
1facf9fc 28094+ struct au_sbinfo *sbinfo;
8b6a4947
AM
28095+ struct hlist_bl_head *hbl;
28096+ struct hlist_bl_node *pos, *tmp;
5afbbe0d 28097+ struct au_icntnr *icntnr;
1facf9fc 28098+
dece6358
AM
28099+ SiMustWriteLock(sb);
28100+
1facf9fc 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+
1facf9fc 28105+ /* no spin_lock since sbinfo is write-locked */
86dc4139
AM
28106+ warned = 0;
28107+ for (i = 0; i < AuPlink_NHASH; i++) {
8b6a4947
AM
28108+ hbl = sbinfo->si_plink + i;
28109+ if (!warned && verbose && !hlist_bl_empty(hbl)) {
86dc4139
AM
28110+ pr_warn("pseudo-link is not flushed");
28111+ warned = 1;
28112+ }
8b6a4947 28113+ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink)
5afbbe0d 28114+ iput(&icntnr->vfs_inode);
8b6a4947 28115+ INIT_HLIST_BL_HEAD(hbl);
86dc4139 28116+ }
1facf9fc 28117+}
28118+
e49829fe
JR
28119+void au_plink_clean(struct super_block *sb, int verbose)
28120+{
28121+ struct dentry *root;
28122+
28123+ root = sb->s_root;
28124+ aufs_write_lock(root);
28125+ if (au_opt_test(au_mntflags(sb), PLINK))
28126+ au_plink_put(sb, verbose);
28127+ aufs_write_unlock(root);
28128+}
28129+
86dc4139
AM
28130+static int au_plink_do_half_refresh(struct inode *inode, aufs_bindex_t br_id)
28131+{
28132+ int do_put;
5afbbe0d 28133+ aufs_bindex_t btop, bbot, bindex;
86dc4139
AM
28134+
28135+ do_put = 0;
5afbbe0d
AM
28136+ btop = au_ibtop(inode);
28137+ bbot = au_ibbot(inode);
28138+ if (btop >= 0) {
28139+ for (bindex = btop; bindex <= bbot; bindex++) {
86dc4139
AM
28140+ if (!au_h_iptr(inode, bindex)
28141+ || au_ii_br_id(inode, bindex) != br_id)
28142+ continue;
28143+ au_set_h_iptr(inode, bindex, NULL, 0);
28144+ do_put = 1;
28145+ break;
28146+ }
28147+ if (do_put)
5afbbe0d 28148+ for (bindex = btop; bindex <= bbot; bindex++)
86dc4139
AM
28149+ if (au_h_iptr(inode, bindex)) {
28150+ do_put = 0;
28151+ break;
28152+ }
28153+ } else
28154+ do_put = 1;
28155+
28156+ return do_put;
28157+}
28158+
1facf9fc 28159+/* free the plinks on a branch specified by @br_id */
28160+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
28161+{
28162+ struct au_sbinfo *sbinfo;
8b6a4947
AM
28163+ struct hlist_bl_head *hbl;
28164+ struct hlist_bl_node *pos, *tmp;
5afbbe0d 28165+ struct au_icntnr *icntnr;
1facf9fc 28166+ struct inode *inode;
86dc4139 28167+ int i, do_put;
1facf9fc 28168+
dece6358
AM
28169+ SiMustWriteLock(sb);
28170+
1facf9fc 28171+ sbinfo = au_sbi(sb);
28172+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 28173+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 28174+
8b6a4947 28175+ /* no bit_lock since sbinfo is write-locked */
86dc4139 28176+ for (i = 0; i < AuPlink_NHASH; i++) {
8b6a4947
AM
28177+ hbl = sbinfo->si_plink + i;
28178+ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink) {
5afbbe0d 28179+ inode = au_igrab(&icntnr->vfs_inode);
86dc4139
AM
28180+ ii_write_lock_child(inode);
28181+ do_put = au_plink_do_half_refresh(inode, br_id);
5afbbe0d 28182+ if (do_put) {
8b6a4947 28183+ hlist_bl_del(&icntnr->plink);
5afbbe0d
AM
28184+ iput(inode);
28185+ }
86dc4139
AM
28186+ ii_write_unlock(inode);
28187+ iput(inode);
dece6358 28188+ }
dece6358
AM
28189+ }
28190+}
7f207e10 28191diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
eca34b5c 28192--- /usr/share/empty/fs/aufs/poll.c 1970-01-01 01:00:00.000000000 +0100
319657f6 28193+++ linux/fs/aufs/poll.c 2021-12-03 15:38:59.939980643 +0100
cd7a4cd9
AM
28194@@ -0,0 +1,51 @@
28195+// SPDX-License-Identifier: GPL-2.0
dece6358 28196+/*
6d176551 28197+ * Copyright (C) 2005-2021 Junjiro R. Okajima
dece6358
AM
28198+ *
28199+ * This program, aufs is free software; you can redistribute it and/or modify
28200+ * it under the terms of the GNU General Public License as published by
28201+ * the Free Software Foundation; either version 2 of the License, or
28202+ * (at your option) any later version.
28203+ *
28204+ * This program is distributed in the hope that it will be useful,
28205+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28206+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28207+ * GNU General Public License for more details.
28208+ *
28209+ * You should have received a copy of the GNU General Public License
523b37e3 28210+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
dece6358
AM
28211+ */
28212+
1308ab2a 28213+/*
28214+ * poll operation
28215+ * There is only one filesystem which implements ->poll operation, currently.
28216+ */
28217+
28218+#include "aufs.h"
28219+
cd7a4cd9 28220+__poll_t aufs_poll(struct file *file, struct poll_table_struct *pt)
1308ab2a 28221+{
be118d29 28222+ __poll_t mask;
1308ab2a 28223+ struct file *h_file;
1308ab2a 28224+ struct super_block *sb;
28225+
28226+ /* We should pretend an error happened. */
be118d29 28227+ mask = EPOLLERR /* | EPOLLIN | EPOLLOUT */;
b912730e 28228+ sb = file->f_path.dentry->d_sb;
e49829fe 28229+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
b912730e 28230+
521ced18 28231+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
062440b3
AM
28232+ if (IS_ERR(h_file)) {
28233+ AuDbg("h_file %ld\n", PTR_ERR(h_file));
1308ab2a 28234+ goto out;
062440b3 28235+ }
1308ab2a 28236+
cd7a4cd9 28237+ mask = vfs_poll(h_file, pt);
b912730e 28238+ fput(h_file); /* instead of au_read_post() */
1308ab2a 28239+
4f0767ce 28240+out:
1308ab2a 28241+ si_read_unlock(sb);
062440b3 28242+ if (mask & EPOLLERR)
b00004a5 28243+ AuDbg("mask 0x%x\n", mask);
1308ab2a 28244+ return mask;
28245+}
c1595e42 28246diff -urN /usr/share/empty/fs/aufs/posix_acl.c linux/fs/aufs/posix_acl.c
eca34b5c 28247--- /usr/share/empty/fs/aufs/posix_acl.c 1970-01-01 01:00:00.000000000 +0100
319657f6 28248+++ linux/fs/aufs/posix_acl.c 2021-12-03 15:40:58.236647297 +0100
758e9dad 28249@@ -0,0 +1,111 @@
cd7a4cd9 28250+// SPDX-License-Identifier: GPL-2.0
c1595e42 28251+/*
6d176551 28252+ * Copyright (C) 2014-2021 Junjiro R. Okajima
c1595e42
JR
28253+ *
28254+ * This program, aufs is free software; you can redistribute it and/or modify
28255+ * it under the terms of the GNU General Public License as published by
28256+ * the Free Software Foundation; either version 2 of the License, or
28257+ * (at your option) any later version.
28258+ *
28259+ * This program is distributed in the hope that it will be useful,
28260+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28261+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28262+ * GNU General Public License for more details.
28263+ *
28264+ * You should have received a copy of the GNU General Public License
28265+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
28266+ */
28267+
28268+/*
28269+ * posix acl operations
28270+ */
28271+
28272+#include <linux/fs.h>
c1595e42
JR
28273+#include "aufs.h"
28274+
758e9dad 28275+struct posix_acl *aufs_get_acl(struct inode *inode, int type, bool rcu)
c1595e42
JR
28276+{
28277+ struct posix_acl *acl;
28278+ int err;
28279+ aufs_bindex_t bindex;
28280+ struct inode *h_inode;
28281+ struct super_block *sb;
28282+
758e9dad
AM
28283+ acl = ERR_PTR(-ECHILD);
28284+ if (rcu)
28285+ goto out;
28286+
c1595e42
JR
28287+ acl = NULL;
28288+ sb = inode->i_sb;
28289+ si_read_lock(sb, AuLock_FLUSH);
28290+ ii_read_lock_child(inode);
2121bcd9 28291+ if (!(sb->s_flags & SB_POSIXACL))
758e9dad 28292+ goto unlock;
c1595e42 28293+
5afbbe0d 28294+ bindex = au_ibtop(inode);
c1595e42
JR
28295+ h_inode = au_h_iptr(inode, bindex);
28296+ if (unlikely(!h_inode
28297+ || ((h_inode->i_mode & S_IFMT)
28298+ != (inode->i_mode & S_IFMT)))) {
28299+ err = au_busy_or_stale();
28300+ acl = ERR_PTR(err);
758e9dad 28301+ goto unlock;
c1595e42
JR
28302+ }
28303+
28304+ /* always topmost only */
28305+ acl = get_acl(h_inode, type);
9f00928d
AM
28306+ if (IS_ERR(acl))
28307+ forget_cached_acl(inode, type);
28308+ else
a2654f78 28309+ set_cached_acl(inode, type, acl);
c1595e42 28310+
758e9dad 28311+unlock:
c1595e42
JR
28312+ ii_read_unlock(inode);
28313+ si_read_unlock(sb);
28314+
758e9dad 28315+out:
c1595e42
JR
28316+ AuTraceErrPtr(acl);
28317+ return acl;
28318+}
28319+
0b2a12c6
JR
28320+int aufs_set_acl(struct user_namespace *userns, struct inode *inode,
28321+ struct posix_acl *acl, int type)
c1595e42
JR
28322+{
28323+ int err;
28324+ ssize_t ssz;
28325+ struct dentry *dentry;
f2c43d5f 28326+ struct au_sxattr arg = {
c1595e42
JR
28327+ .type = AU_ACL_SET,
28328+ .u.acl_set = {
28329+ .acl = acl,
28330+ .type = type
28331+ },
28332+ };
28333+
5afbbe0d
AM
28334+ IMustLock(inode);
28335+
c1595e42
JR
28336+ if (inode->i_ino == AUFS_ROOT_INO)
28337+ dentry = dget(inode->i_sb->s_root);
28338+ else {
28339+ dentry = d_find_alias(inode);
28340+ if (!dentry)
28341+ dentry = d_find_any_alias(inode);
28342+ if (!dentry) {
28343+ pr_warn("cannot handle this inode, "
28344+ "please report to aufs-users ML\n");
28345+ err = -ENOENT;
28346+ goto out;
28347+ }
28348+ }
28349+
f2c43d5f 28350+ ssz = au_sxattr(dentry, inode, &arg);
9f00928d
AM
28351+ /* forget even it if succeeds since the branch might set differently */
28352+ forget_cached_acl(inode, type);
c1595e42
JR
28353+ dput(dentry);
28354+ err = ssz;
9f00928d 28355+ if (ssz >= 0)
c1595e42
JR
28356+ err = 0;
28357+
28358+out:
c1595e42
JR
28359+ return err;
28360+}
7f207e10 28361diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c
eca34b5c 28362--- /usr/share/empty/fs/aufs/procfs.c 1970-01-01 01:00:00.000000000 +0100
319657f6 28363+++ linux/fs/aufs/procfs.c 2021-12-03 15:38:59.939980643 +0100
394e211a 28364@@ -0,0 +1,170 @@
cd7a4cd9 28365+// SPDX-License-Identifier: GPL-2.0
e49829fe 28366+/*
6d176551 28367+ * Copyright (C) 2010-2021 Junjiro R. Okajima
e49829fe
JR
28368+ *
28369+ * This program, aufs is free software; you can redistribute it and/or modify
28370+ * it under the terms of the GNU General Public License as published by
28371+ * the Free Software Foundation; either version 2 of the License, or
28372+ * (at your option) any later version.
28373+ *
28374+ * This program is distributed in the hope that it will be useful,
28375+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28376+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28377+ * GNU General Public License for more details.
28378+ *
28379+ * You should have received a copy of the GNU General Public License
523b37e3 28380+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
e49829fe
JR
28381+ */
28382+
28383+/*
28384+ * procfs interfaces
28385+ */
28386+
28387+#include <linux/proc_fs.h>
28388+#include "aufs.h"
28389+
28390+static int au_procfs_plm_release(struct inode *inode, struct file *file)
28391+{
28392+ struct au_sbinfo *sbinfo;
28393+
28394+ sbinfo = file->private_data;
28395+ if (sbinfo) {
28396+ au_plink_maint_leave(sbinfo);
28397+ kobject_put(&sbinfo->si_kobj);
28398+ }
28399+
28400+ return 0;
28401+}
28402+
28403+static void au_procfs_plm_write_clean(struct file *file)
28404+{
28405+ struct au_sbinfo *sbinfo;
28406+
28407+ sbinfo = file->private_data;
28408+ if (sbinfo)
28409+ au_plink_clean(sbinfo->si_sb, /*verbose*/0);
28410+}
28411+
28412+static int au_procfs_plm_write_si(struct file *file, unsigned long id)
28413+{
28414+ int err;
28415+ struct super_block *sb;
28416+ struct au_sbinfo *sbinfo;
8b6a4947 28417+ struct hlist_bl_node *pos;
e49829fe
JR
28418+
28419+ err = -EBUSY;
28420+ if (unlikely(file->private_data))
28421+ goto out;
28422+
28423+ sb = NULL;
53392da6 28424+ /* don't use au_sbilist_lock() here */
8b6a4947
AM
28425+ hlist_bl_lock(&au_sbilist);
28426+ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list)
e49829fe 28427+ if (id == sysaufs_si_id(sbinfo)) {
83b672a5
AM
28428+ if (kobject_get_unless_zero(&sbinfo->si_kobj))
28429+ sb = sbinfo->si_sb;
e49829fe
JR
28430+ break;
28431+ }
8b6a4947 28432+ hlist_bl_unlock(&au_sbilist);
e49829fe
JR
28433+
28434+ err = -EINVAL;
28435+ if (unlikely(!sb))
28436+ goto out;
28437+
28438+ err = au_plink_maint_enter(sb);
28439+ if (!err)
28440+ /* keep kobject_get() */
28441+ file->private_data = sbinfo;
28442+ else
28443+ kobject_put(&sbinfo->si_kobj);
28444+out:
28445+ return err;
28446+}
28447+
28448+/*
28449+ * Accept a valid "si=xxxx" only.
28450+ * Once it is accepted successfully, accept "clean" too.
28451+ */
28452+static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf,
28453+ size_t count, loff_t *ppos)
28454+{
28455+ ssize_t err;
28456+ unsigned long id;
28457+ /* last newline is allowed */
28458+ char buf[3 + sizeof(unsigned long) * 2 + 1];
28459+
28460+ err = -EACCES;
28461+ if (unlikely(!capable(CAP_SYS_ADMIN)))
28462+ goto out;
28463+
28464+ err = -EINVAL;
28465+ if (unlikely(count > sizeof(buf)))
28466+ goto out;
28467+
28468+ err = copy_from_user(buf, ubuf, count);
28469+ if (unlikely(err)) {
28470+ err = -EFAULT;
28471+ goto out;
28472+ }
28473+ buf[count] = 0;
28474+
28475+ err = -EINVAL;
28476+ if (!strcmp("clean", buf)) {
28477+ au_procfs_plm_write_clean(file);
28478+ goto out_success;
28479+ } else if (unlikely(strncmp("si=", buf, 3)))
28480+ goto out;
28481+
9dbd164d 28482+ err = kstrtoul(buf + 3, 16, &id);
e49829fe
JR
28483+ if (unlikely(err))
28484+ goto out;
28485+
28486+ err = au_procfs_plm_write_si(file, id);
28487+ if (unlikely(err))
28488+ goto out;
28489+
28490+out_success:
28491+ err = count; /* success */
28492+out:
28493+ return err;
28494+}
28495+
394e211a
AM
28496+static const struct proc_ops au_procfs_plm_op = {
28497+ .proc_write = au_procfs_plm_write,
28498+ .proc_release = au_procfs_plm_release
e49829fe
JR
28499+};
28500+
28501+/* ---------------------------------------------------------------------- */
28502+
28503+static struct proc_dir_entry *au_procfs_dir;
28504+
28505+void au_procfs_fin(void)
28506+{
28507+ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir);
28508+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
28509+}
28510+
28511+int __init au_procfs_init(void)
28512+{
28513+ int err;
28514+ struct proc_dir_entry *entry;
28515+
28516+ err = -ENOMEM;
28517+ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL);
28518+ if (unlikely(!au_procfs_dir))
28519+ goto out;
28520+
cd7a4cd9 28521+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | 0200,
394e211a 28522+ au_procfs_dir, &au_procfs_plm_op);
e49829fe
JR
28523+ if (unlikely(!entry))
28524+ goto out_dir;
28525+
28526+ err = 0;
28527+ goto out; /* success */
28528+
28529+
28530+out_dir:
28531+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
28532+out:
28533+ return err;
28534+}
7f207e10 28535diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
eca34b5c 28536--- /usr/share/empty/fs/aufs/rdu.c 1970-01-01 01:00:00.000000000 +0100
319657f6 28537+++ linux/fs/aufs/rdu.c 2021-12-03 15:38:59.939980643 +0100
ba1aed25 28538@@ -0,0 +1,384 @@
cd7a4cd9 28539+// SPDX-License-Identifier: GPL-2.0
1308ab2a 28540+/*
6d176551 28541+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1308ab2a 28542+ *
28543+ * This program, aufs is free software; you can redistribute it and/or modify
28544+ * it under the terms of the GNU General Public License as published by
28545+ * the Free Software Foundation; either version 2 of the License, or
28546+ * (at your option) any later version.
28547+ *
28548+ * This program is distributed in the hope that it will be useful,
28549+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28550+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28551+ * GNU General Public License for more details.
28552+ *
28553+ * You should have received a copy of the GNU General Public License
523b37e3 28554+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1308ab2a 28555+ */
28556+
28557+/*
28558+ * readdir in userspace.
28559+ */
28560+
b752ccd1 28561+#include <linux/compat.h>
4a4d8108 28562+#include <linux/fs_stack.h>
1308ab2a 28563+#include <linux/security.h>
1308ab2a 28564+#include "aufs.h"
28565+
28566+/* bits for struct aufs_rdu.flags */
28567+#define AuRdu_CALLED 1
28568+#define AuRdu_CONT (1 << 1)
28569+#define AuRdu_FULL (1 << 2)
28570+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
7f207e10
AM
28571+#define au_fset_rdu(flags, name) \
28572+ do { (flags) |= AuRdu_##name; } while (0)
28573+#define au_fclr_rdu(flags, name) \
28574+ do { (flags) &= ~AuRdu_##name; } while (0)
1308ab2a 28575+
28576+struct au_rdu_arg {
392086de 28577+ struct dir_context ctx;
1308ab2a 28578+ struct aufs_rdu *rdu;
28579+ union au_rdu_ent_ul ent;
28580+ unsigned long end;
28581+
28582+ struct super_block *sb;
28583+ int err;
28584+};
28585+
392086de 28586+static int au_rdu_fill(struct dir_context *ctx, const char *name, int nlen,
1308ab2a 28587+ loff_t offset, u64 h_ino, unsigned int d_type)
28588+{
28589+ int err, len;
392086de 28590+ struct au_rdu_arg *arg = container_of(ctx, struct au_rdu_arg, ctx);
1308ab2a 28591+ struct aufs_rdu *rdu = arg->rdu;
28592+ struct au_rdu_ent ent;
28593+
28594+ err = 0;
28595+ arg->err = 0;
28596+ au_fset_rdu(rdu->cookie.flags, CALLED);
28597+ len = au_rdu_len(nlen);
28598+ if (arg->ent.ul + len < arg->end) {
28599+ ent.ino = h_ino;
28600+ ent.bindex = rdu->cookie.bindex;
28601+ ent.type = d_type;
28602+ ent.nlen = nlen;
4a4d8108
AM
28603+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
28604+ ent.type = DT_UNKNOWN;
1308ab2a 28605+
9dbd164d 28606+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 28607+ err = -EFAULT;
28608+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
28609+ goto out;
28610+ if (copy_to_user(arg->ent.e->name, name, nlen))
28611+ goto out;
28612+ /* the terminating NULL */
28613+ if (__put_user(0, arg->ent.e->name + nlen))
28614+ goto out;
28615+ err = 0;
28616+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
28617+ arg->ent.ul += len;
28618+ rdu->rent++;
28619+ } else {
28620+ err = -EFAULT;
28621+ au_fset_rdu(rdu->cookie.flags, FULL);
28622+ rdu->full = 1;
28623+ rdu->tail = arg->ent;
28624+ }
28625+
4f0767ce 28626+out:
1308ab2a 28627+ /* AuTraceErr(err); */
28628+ return err;
28629+}
28630+
28631+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
28632+{
28633+ int err;
28634+ loff_t offset;
28635+ struct au_rdu_cookie *cookie = &arg->rdu->cookie;
28636+
92d182d2 28637+ /* we don't have to care (FMODE_32BITHASH | FMODE_64BITHASH) for ext4 */
1308ab2a 28638+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
28639+ err = offset;
28640+ if (unlikely(offset != cookie->h_pos))
28641+ goto out;
28642+
28643+ err = 0;
28644+ do {
28645+ arg->err = 0;
28646+ au_fclr_rdu(cookie->flags, CALLED);
28647+ /* smp_mb(); */
392086de 28648+ err = vfsub_iterate_dir(h_file, &arg->ctx);
1308ab2a 28649+ if (err >= 0)
28650+ err = arg->err;
28651+ } while (!err
28652+ && au_ftest_rdu(cookie->flags, CALLED)
28653+ && !au_ftest_rdu(cookie->flags, FULL));
28654+ cookie->h_pos = h_file->f_pos;
28655+
4f0767ce 28656+out:
1308ab2a 28657+ AuTraceErr(err);
28658+ return err;
28659+}
28660+
28661+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
28662+{
28663+ int err;
5afbbe0d 28664+ aufs_bindex_t bbot;
392086de
AM
28665+ struct au_rdu_arg arg = {
28666+ .ctx = {
2000de60 28667+ .actor = au_rdu_fill
392086de
AM
28668+ }
28669+ };
1308ab2a 28670+ struct dentry *dentry;
28671+ struct inode *inode;
28672+ struct file *h_file;
28673+ struct au_rdu_cookie *cookie = &rdu->cookie;
28674+
ba1aed25
AM
28675+ /* VERIFY_WRITE */
28676+ err = !access_ok(rdu->ent.e, rdu->sz);
1308ab2a 28677+ if (unlikely(err)) {
28678+ err = -EFAULT;
28679+ AuTraceErr(err);
28680+ goto out;
28681+ }
28682+ rdu->rent = 0;
28683+ rdu->tail = rdu->ent;
28684+ rdu->full = 0;
28685+ arg.rdu = rdu;
28686+ arg.ent = rdu->ent;
28687+ arg.end = arg.ent.ul;
28688+ arg.end += rdu->sz;
28689+
28690+ err = -ENOTDIR;
5afbbe0d 28691+ if (unlikely(!file->f_op->iterate && !file->f_op->iterate_shared))
1308ab2a 28692+ goto out;
28693+
28694+ err = security_file_permission(file, MAY_READ);
28695+ AuTraceErr(err);
28696+ if (unlikely(err))
28697+ goto out;
28698+
2000de60 28699+ dentry = file->f_path.dentry;
5527c038 28700+ inode = d_inode(dentry);
5afbbe0d 28701+ inode_lock_shared(inode);
1308ab2a 28702+
28703+ arg.sb = inode->i_sb;
e49829fe
JR
28704+ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM);
28705+ if (unlikely(err))
28706+ goto out_mtx;
027c5e7a
AM
28707+ err = au_alive_dir(dentry);
28708+ if (unlikely(err))
28709+ goto out_si;
e49829fe 28710+ /* todo: reval? */
1308ab2a 28711+ fi_read_lock(file);
28712+
28713+ err = -EAGAIN;
28714+ if (unlikely(au_ftest_rdu(cookie->flags, CONT)
28715+ && cookie->generation != au_figen(file)))
28716+ goto out_unlock;
28717+
28718+ err = 0;
28719+ if (!rdu->blk) {
28720+ rdu->blk = au_sbi(arg.sb)->si_rdblk;
28721+ if (!rdu->blk)
28722+ rdu->blk = au_dir_size(file, /*dentry*/NULL);
28723+ }
5afbbe0d
AM
28724+ bbot = au_fbtop(file);
28725+ if (cookie->bindex < bbot)
28726+ cookie->bindex = bbot;
28727+ bbot = au_fbbot_dir(file);
28728+ /* AuDbg("b%d, b%d\n", cookie->bindex, bbot); */
28729+ for (; !err && cookie->bindex <= bbot;
1308ab2a 28730+ cookie->bindex++, cookie->h_pos = 0) {
4a4d8108 28731+ h_file = au_hf_dir(file, cookie->bindex);
1308ab2a 28732+ if (!h_file)
28733+ continue;
28734+
28735+ au_fclr_rdu(cookie->flags, FULL);
28736+ err = au_rdu_do(h_file, &arg);
28737+ AuTraceErr(err);
28738+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
28739+ break;
28740+ }
28741+ AuDbg("rent %llu\n", rdu->rent);
28742+
28743+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
28744+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
28745+ au_fset_rdu(cookie->flags, CONT);
28746+ cookie->generation = au_figen(file);
28747+ }
28748+
28749+ ii_read_lock_child(inode);
5afbbe0d 28750+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibtop(inode)));
1308ab2a 28751+ ii_read_unlock(inode);
28752+
4f0767ce 28753+out_unlock:
1308ab2a 28754+ fi_read_unlock(file);
027c5e7a 28755+out_si:
1308ab2a 28756+ si_read_unlock(arg.sb);
4f0767ce 28757+out_mtx:
5afbbe0d 28758+ inode_unlock_shared(inode);
4f0767ce 28759+out:
1308ab2a 28760+ AuTraceErr(err);
28761+ return err;
28762+}
28763+
28764+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
28765+{
28766+ int err;
28767+ ino_t ino;
28768+ unsigned long long nent;
28769+ union au_rdu_ent_ul *u;
28770+ struct au_rdu_ent ent;
28771+ struct super_block *sb;
28772+
28773+ err = 0;
28774+ nent = rdu->nent;
28775+ u = &rdu->ent;
2000de60 28776+ sb = file->f_path.dentry->d_sb;
1308ab2a 28777+ si_read_lock(sb, AuLock_FLUSH);
28778+ while (nent-- > 0) {
9dbd164d 28779+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 28780+ err = copy_from_user(&ent, u->e, sizeof(ent));
4a4d8108 28781+ if (!err)
ba1aed25
AM
28782+ /* VERIFY_WRITE */
28783+ err = !access_ok(&u->e->ino, sizeof(ino));
1308ab2a 28784+ if (unlikely(err)) {
28785+ err = -EFAULT;
28786+ AuTraceErr(err);
28787+ break;
28788+ }
28789+
28790+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
28791+ if (!ent.wh)
28792+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
28793+ else
28794+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
28795+ &ino);
28796+ if (unlikely(err)) {
28797+ AuTraceErr(err);
28798+ break;
28799+ }
28800+
28801+ err = __put_user(ino, &u->e->ino);
28802+ if (unlikely(err)) {
28803+ err = -EFAULT;
28804+ AuTraceErr(err);
28805+ break;
28806+ }
28807+ u->ul += au_rdu_len(ent.nlen);
28808+ }
28809+ si_read_unlock(sb);
28810+
28811+ return err;
28812+}
28813+
28814+/* ---------------------------------------------------------------------- */
28815+
28816+static int au_rdu_verify(struct aufs_rdu *rdu)
28817+{
b752ccd1 28818+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
1308ab2a 28819+ "%llu, b%d, 0x%x, g%u}\n",
b752ccd1 28820+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
1308ab2a 28821+ rdu->blk,
28822+ rdu->rent, rdu->shwh, rdu->full,
28823+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
28824+ rdu->cookie.generation);
dece6358 28825+
b752ccd1 28826+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
1308ab2a 28827+ return 0;
dece6358 28828+
b752ccd1
AM
28829+ AuDbg("%u:%u\n",
28830+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
1308ab2a 28831+ return -EINVAL;
28832+}
28833+
28834+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dece6358 28835+{
1308ab2a 28836+ long err, e;
28837+ struct aufs_rdu rdu;
28838+ void __user *p = (void __user *)arg;
dece6358 28839+
1308ab2a 28840+ err = copy_from_user(&rdu, p, sizeof(rdu));
28841+ if (unlikely(err)) {
28842+ err = -EFAULT;
28843+ AuTraceErr(err);
28844+ goto out;
28845+ }
28846+ err = au_rdu_verify(&rdu);
dece6358
AM
28847+ if (unlikely(err))
28848+ goto out;
28849+
1308ab2a 28850+ switch (cmd) {
28851+ case AUFS_CTL_RDU:
28852+ err = au_rdu(file, &rdu);
28853+ if (unlikely(err))
28854+ break;
dece6358 28855+
1308ab2a 28856+ e = copy_to_user(p, &rdu, sizeof(rdu));
28857+ if (unlikely(e)) {
28858+ err = -EFAULT;
28859+ AuTraceErr(err);
28860+ }
28861+ break;
28862+ case AUFS_CTL_RDU_INO:
28863+ err = au_rdu_ino(file, &rdu);
28864+ break;
28865+
28866+ default:
4a4d8108 28867+ /* err = -ENOTTY; */
1308ab2a 28868+ err = -EINVAL;
28869+ }
dece6358 28870+
4f0767ce 28871+out:
1308ab2a 28872+ AuTraceErr(err);
28873+ return err;
1facf9fc 28874+}
b752ccd1
AM
28875+
28876+#ifdef CONFIG_COMPAT
28877+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
28878+{
28879+ long err, e;
28880+ struct aufs_rdu rdu;
28881+ void __user *p = compat_ptr(arg);
28882+
28883+ /* todo: get_user()? */
28884+ err = copy_from_user(&rdu, p, sizeof(rdu));
28885+ if (unlikely(err)) {
28886+ err = -EFAULT;
28887+ AuTraceErr(err);
28888+ goto out;
28889+ }
28890+ rdu.ent.e = compat_ptr(rdu.ent.ul);
28891+ err = au_rdu_verify(&rdu);
28892+ if (unlikely(err))
28893+ goto out;
28894+
28895+ switch (cmd) {
28896+ case AUFS_CTL_RDU:
28897+ err = au_rdu(file, &rdu);
28898+ if (unlikely(err))
28899+ break;
28900+
28901+ rdu.ent.ul = ptr_to_compat(rdu.ent.e);
28902+ rdu.tail.ul = ptr_to_compat(rdu.tail.e);
28903+ e = copy_to_user(p, &rdu, sizeof(rdu));
28904+ if (unlikely(e)) {
28905+ err = -EFAULT;
28906+ AuTraceErr(err);
28907+ }
28908+ break;
28909+ case AUFS_CTL_RDU_INO:
28910+ err = au_rdu_ino(file, &rdu);
28911+ break;
28912+
28913+ default:
28914+ /* err = -ENOTTY; */
28915+ err = -EINVAL;
28916+ }
28917+
4f0767ce 28918+out:
b752ccd1
AM
28919+ AuTraceErr(err);
28920+ return err;
28921+}
28922+#endif
7f207e10 28923diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
eca34b5c 28924--- /usr/share/empty/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100
319657f6 28925+++ linux/fs/aufs/rwsem.h 2021-12-03 15:40:58.236647297 +0100
42a736d3 28926@@ -0,0 +1,85 @@
062440b3 28927+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 28928+/*
6d176551 28929+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 28930+ *
28931+ * This program, aufs is free software; you can redistribute it and/or modify
28932+ * it under the terms of the GNU General Public License as published by
28933+ * the Free Software Foundation; either version 2 of the License, or
28934+ * (at your option) any later version.
dece6358
AM
28935+ *
28936+ * This program is distributed in the hope that it will be useful,
28937+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28938+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28939+ * GNU General Public License for more details.
28940+ *
28941+ * You should have received a copy of the GNU General Public License
523b37e3 28942+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 28943+ */
28944+
28945+/*
28946+ * simple read-write semaphore wrappers
28947+ */
28948+
28949+#ifndef __AUFS_RWSEM_H__
28950+#define __AUFS_RWSEM_H__
28951+
28952+#ifdef __KERNEL__
28953+
4a4d8108 28954+#include "debug.h"
dece6358 28955+
acd2b654 28956+/* in the future, the name 'au_rwsem' will be totally gone */
8b6a4947 28957+#define au_rwsem rw_semaphore
dece6358
AM
28958+
28959+/* to debug easier, do not make them inlined functions */
8b6a4947 28960+#define AuRwMustNoWaiters(rw) AuDebugOn(rwsem_is_contended(rw))
42a736d3
AM
28961+
28962+#ifdef CONFIG_LOCKDEP
dece6358 28963+/* rwsem_is_locked() is unusable */
42a736d3
AM
28964+#define AuRwMustReadLock(rw) AuDebugOn(IS_ENABLED(CONFIG_LOCKDEP) \
28965+ && !lockdep_recursing(current) \
28966+ && debug_locks \
8b6a4947 28967+ && !lockdep_is_held_type(rw, 1))
42a736d3
AM
28968+#define AuRwMustWriteLock(rw) AuDebugOn(IS_ENABLED(CONFIG_LOCKDEP) \
28969+ && !lockdep_recursing(current) \
28970+ && debug_locks \
8b6a4947 28971+ && !lockdep_is_held_type(rw, 0))
42a736d3
AM
28972+#define AuRwMustAnyLock(rw) AuDebugOn(IS_ENABLED(CONFIG_LOCKDEP) \
28973+ && !lockdep_recursing(current) \
28974+ && debug_locks \
8b6a4947 28975+ && !lockdep_is_held(rw))
42a736d3
AM
28976+#define AuRwDestroy(rw) AuDebugOn(IS_ENABLED(CONFIG_LOCKDEP) \
28977+ && !lockdep_recursing(current) \
28978+ && debug_locks \
8b6a4947 28979+ && lockdep_is_held(rw))
42a736d3
AM
28980+#else
28981+#define AuRwMustReadLock(rw) do {} while (0)
28982+#define AuRwMustWriteLock(rw) do {} while (0)
28983+#define AuRwMustAnyLock(rw) do {} while (0)
28984+#define AuRwDestroy(rw) do {} while (0)
28985+#endif
8b6a4947
AM
28986+
28987+#define au_rw_init(rw) init_rwsem(rw)
dece6358 28988+
5afbbe0d
AM
28989+#define au_rw_init_wlock(rw) do { \
28990+ au_rw_init(rw); \
8b6a4947 28991+ down_write(rw); \
5afbbe0d 28992+ } while (0)
dece6358 28993+
8b6a4947
AM
28994+#define au_rw_init_wlock_nested(rw, lsc) do { \
28995+ au_rw_init(rw); \
28996+ down_write_nested(rw, lsc); \
5afbbe0d 28997+ } while (0)
dece6358 28998+
8b6a4947
AM
28999+#define au_rw_read_lock(rw) down_read(rw)
29000+#define au_rw_read_lock_nested(rw, lsc) down_read_nested(rw, lsc)
29001+#define au_rw_read_unlock(rw) up_read(rw)
29002+#define au_rw_dgrade_lock(rw) downgrade_write(rw)
29003+#define au_rw_write_lock(rw) down_write(rw)
29004+#define au_rw_write_lock_nested(rw, lsc) down_write_nested(rw, lsc)
29005+#define au_rw_write_unlock(rw) up_write(rw)
29006+/* why is not _nested version defined? */
29007+#define au_rw_read_trylock(rw) down_read_trylock(rw)
29008+#define au_rw_write_trylock(rw) down_write_trylock(rw)
1facf9fc 29009+
29010+#endif /* __KERNEL__ */
29011+#endif /* __AUFS_RWSEM_H__ */
7f207e10 29012diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
eca34b5c 29013--- /usr/share/empty/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
319657f6 29014+++ linux/fs/aufs/sbinfo.c 2021-12-03 15:38:59.939980643 +0100
eca801bf 29015@@ -0,0 +1,314 @@
cd7a4cd9 29016+// SPDX-License-Identifier: GPL-2.0
1facf9fc 29017+/*
6d176551 29018+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 29019+ *
29020+ * This program, aufs is free software; you can redistribute it and/or modify
29021+ * it under the terms of the GNU General Public License as published by
29022+ * the Free Software Foundation; either version 2 of the License, or
29023+ * (at your option) any later version.
dece6358
AM
29024+ *
29025+ * This program is distributed in the hope that it will be useful,
29026+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29027+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29028+ * GNU General Public License for more details.
29029+ *
29030+ * You should have received a copy of the GNU General Public License
523b37e3 29031+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 29032+ */
29033+
29034+/*
29035+ * superblock private data
29036+ */
29037+
eca801bf 29038+#include <linux/iversion.h>
1facf9fc 29039+#include "aufs.h"
29040+
29041+/*
29042+ * they are necessary regardless sysfs is disabled.
29043+ */
29044+void au_si_free(struct kobject *kobj)
29045+{
86dc4139 29046+ int i;
1facf9fc 29047+ struct au_sbinfo *sbinfo;
b752ccd1 29048+ char *locked __maybe_unused; /* debug only */
1facf9fc 29049+
29050+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
86dc4139 29051+ for (i = 0; i < AuPlink_NHASH; i++)
8b6a4947 29052+ AuDebugOn(!hlist_bl_empty(sbinfo->si_plink + i));
f0c0a007 29053+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
5afbbe0d 29054+
acd2b654
AM
29055+ AuLCntZero(au_lcnt_read(&sbinfo->si_ninodes, /*do_rev*/0));
29056+ au_lcnt_fin(&sbinfo->si_ninodes, /*do_sync*/0);
29057+ AuLCntZero(au_lcnt_read(&sbinfo->si_nfiles, /*do_rev*/0));
29058+ au_lcnt_fin(&sbinfo->si_nfiles, /*do_sync*/0);
1facf9fc 29059+
062440b3 29060+ dbgaufs_si_fin(sbinfo);
e49829fe 29061+ au_rw_write_lock(&sbinfo->si_rwsem);
1facf9fc 29062+ au_br_free(sbinfo);
e49829fe 29063+ au_rw_write_unlock(&sbinfo->si_rwsem);
b752ccd1 29064+
9f237c51 29065+ au_kfree_try_rcu(sbinfo->si_branch);
1facf9fc 29066+ mutex_destroy(&sbinfo->si_xib_mtx);
dece6358 29067+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 29068+
acd2b654
AM
29069+ au_lcnt_wait_for_fin(&sbinfo->si_ninodes);
29070+ /* si_nfiles is waited too */
9f237c51 29071+ au_kfree_rcu(sbinfo);
1facf9fc 29072+}
29073+
29074+int au_si_alloc(struct super_block *sb)
29075+{
86dc4139 29076+ int err, i;
1facf9fc 29077+ struct au_sbinfo *sbinfo;
29078+
29079+ err = -ENOMEM;
4a4d8108 29080+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
1facf9fc 29081+ if (unlikely(!sbinfo))
29082+ goto out;
29083+
29084+ /* will be reallocated separately */
29085+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
29086+ if (unlikely(!sbinfo->si_branch))
febd17d6 29087+ goto out_sbinfo;
1facf9fc 29088+
1facf9fc 29089+ err = sysaufs_si_init(sbinfo);
062440b3
AM
29090+ if (!err) {
29091+ dbgaufs_si_null(sbinfo);
29092+ err = dbgaufs_si_init(sbinfo);
29093+ if (unlikely(err))
29094+ kobject_put(&sbinfo->si_kobj);
29095+ }
1facf9fc 29096+ if (unlikely(err))
29097+ goto out_br;
29098+
29099+ au_nwt_init(&sbinfo->si_nowait);
dece6358 29100+ au_rw_init_wlock(&sbinfo->si_rwsem);
b752ccd1 29101+
acd2b654
AM
29102+ au_lcnt_init(&sbinfo->si_ninodes, /*release*/NULL);
29103+ au_lcnt_init(&sbinfo->si_nfiles, /*release*/NULL);
7f207e10 29104+
5afbbe0d 29105+ sbinfo->si_bbot = -1;
392086de 29106+ sbinfo->si_last_br_id = AUFS_BRANCH_MAX / 2;
1facf9fc 29107+
29108+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
29109+ sbinfo->si_wbr_create = AuWbrCreate_Def;
4a4d8108
AM
29110+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
29111+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
1facf9fc 29112+
076b876e
AM
29113+ au_fhsm_init(sbinfo);
29114+
e49829fe 29115+ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def);
1facf9fc 29116+
392086de
AM
29117+ sbinfo->si_xino_jiffy = jiffies;
29118+ sbinfo->si_xino_expire
29119+ = msecs_to_jiffies(AUFS_XINO_DEF_SEC * MSEC_PER_SEC);
1facf9fc 29120+ mutex_init(&sbinfo->si_xib_mtx);
1facf9fc 29121+ /* leave si_xib_last_pindex and si_xib_next_bit */
29122+
8b6a4947 29123+ INIT_HLIST_BL_HEAD(&sbinfo->si_aopen);
b912730e 29124+
e49829fe 29125+ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC);
1facf9fc 29126+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
29127+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
29128+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
29129+
86dc4139 29130+ for (i = 0; i < AuPlink_NHASH; i++)
8b6a4947 29131+ INIT_HLIST_BL_HEAD(sbinfo->si_plink + i);
1facf9fc 29132+ init_waitqueue_head(&sbinfo->si_plink_wq);
4a4d8108 29133+ spin_lock_init(&sbinfo->si_plink_maint_lock);
1facf9fc 29134+
8b6a4947 29135+ INIT_HLIST_BL_HEAD(&sbinfo->si_files);
523b37e3 29136+
b95c5147
AM
29137+ /* with getattr by default */
29138+ sbinfo->si_iop_array = aufs_iop;
29139+
1facf9fc 29140+ /* leave other members for sysaufs and si_mnt. */
29141+ sbinfo->si_sb = sb;
29142+ sb->s_fs_info = sbinfo;
b752ccd1 29143+ si_pid_set(sb);
1facf9fc 29144+ return 0; /* success */
29145+
4f0767ce 29146+out_br:
9f237c51 29147+ au_kfree_try_rcu(sbinfo->si_branch);
4f0767ce 29148+out_sbinfo:
9f237c51 29149+ au_kfree_rcu(sbinfo);
4f0767ce 29150+out:
1facf9fc 29151+ return err;
29152+}
29153+
e2f27e51 29154+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink)
1facf9fc 29155+{
29156+ int err, sz;
29157+ struct au_branch **brp;
29158+
dece6358
AM
29159+ AuRwMustWriteLock(&sbinfo->si_rwsem);
29160+
1facf9fc 29161+ err = -ENOMEM;
5afbbe0d 29162+ sz = sizeof(*brp) * (sbinfo->si_bbot + 1);
1facf9fc 29163+ if (unlikely(!sz))
29164+ sz = sizeof(*brp);
e2f27e51
AM
29165+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS,
29166+ may_shrink);
1facf9fc 29167+ if (brp) {
29168+ sbinfo->si_branch = brp;
29169+ err = 0;
29170+ }
29171+
29172+ return err;
29173+}
29174+
29175+/* ---------------------------------------------------------------------- */
29176+
29177+unsigned int au_sigen_inc(struct super_block *sb)
29178+{
29179+ unsigned int gen;
5527c038 29180+ struct inode *inode;
1facf9fc 29181+
dece6358
AM
29182+ SiMustWriteLock(sb);
29183+
1facf9fc 29184+ gen = ++au_sbi(sb)->si_generation;
29185+ au_update_digen(sb->s_root);
5527c038
JR
29186+ inode = d_inode(sb->s_root);
29187+ au_update_iigen(inode, /*half*/0);
be118d29 29188+ inode_inc_iversion(inode);
1facf9fc 29189+ return gen;
29190+}
29191+
29192+aufs_bindex_t au_new_br_id(struct super_block *sb)
29193+{
29194+ aufs_bindex_t br_id;
29195+ int i;
29196+ struct au_sbinfo *sbinfo;
29197+
dece6358
AM
29198+ SiMustWriteLock(sb);
29199+
1facf9fc 29200+ sbinfo = au_sbi(sb);
29201+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
29202+ br_id = ++sbinfo->si_last_br_id;
7f207e10 29203+ AuDebugOn(br_id < 0);
1facf9fc 29204+ if (br_id && au_br_index(sb, br_id) < 0)
29205+ return br_id;
29206+ }
29207+
29208+ return -1;
29209+}
29210+
29211+/* ---------------------------------------------------------------------- */
29212+
e49829fe
JR
29213+/* it is ok that new 'nwt' tasks are appended while we are sleeping */
29214+int si_read_lock(struct super_block *sb, int flags)
29215+{
29216+ int err;
29217+
29218+ err = 0;
29219+ if (au_ftest_lock(flags, FLUSH))
29220+ au_nwt_flush(&au_sbi(sb)->si_nowait);
29221+
29222+ si_noflush_read_lock(sb);
29223+ err = au_plink_maint(sb, flags);
29224+ if (unlikely(err))
29225+ si_read_unlock(sb);
29226+
29227+ return err;
29228+}
29229+
29230+int si_write_lock(struct super_block *sb, int flags)
29231+{
29232+ int err;
29233+
29234+ if (au_ftest_lock(flags, FLUSH))
29235+ au_nwt_flush(&au_sbi(sb)->si_nowait);
29236+
29237+ si_noflush_write_lock(sb);
29238+ err = au_plink_maint(sb, flags);
29239+ if (unlikely(err))
29240+ si_write_unlock(sb);
29241+
29242+ return err;
29243+}
29244+
1facf9fc 29245+/* dentry and super_block lock. call at entry point */
e49829fe 29246+int aufs_read_lock(struct dentry *dentry, int flags)
1facf9fc 29247+{
e49829fe 29248+ int err;
027c5e7a 29249+ struct super_block *sb;
e49829fe 29250+
027c5e7a
AM
29251+ sb = dentry->d_sb;
29252+ err = si_read_lock(sb, flags);
29253+ if (unlikely(err))
29254+ goto out;
29255+
29256+ if (au_ftest_lock(flags, DW))
29257+ di_write_lock_child(dentry);
29258+ else
29259+ di_read_lock_child(dentry, flags);
29260+
29261+ if (au_ftest_lock(flags, GEN)) {
29262+ err = au_digen_test(dentry, au_sigen(sb));
79b8bda9
AM
29263+ if (!au_opt_test(au_mntflags(sb), UDBA_NONE))
29264+ AuDebugOn(!err && au_dbrange_test(dentry));
29265+ else if (!err)
29266+ err = au_dbrange_test(dentry);
027c5e7a
AM
29267+ if (unlikely(err))
29268+ aufs_read_unlock(dentry, flags);
e49829fe
JR
29269+ }
29270+
027c5e7a 29271+out:
e49829fe 29272+ return err;
1facf9fc 29273+}
29274+
29275+void aufs_read_unlock(struct dentry *dentry, int flags)
29276+{
29277+ if (au_ftest_lock(flags, DW))
29278+ di_write_unlock(dentry);
29279+ else
29280+ di_read_unlock(dentry, flags);
29281+ si_read_unlock(dentry->d_sb);
29282+}
29283+
29284+void aufs_write_lock(struct dentry *dentry)
29285+{
e49829fe 29286+ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW);
1facf9fc 29287+ di_write_lock_child(dentry);
29288+}
29289+
29290+void aufs_write_unlock(struct dentry *dentry)
29291+{
29292+ di_write_unlock(dentry);
29293+ si_write_unlock(dentry->d_sb);
29294+}
29295+
e49829fe 29296+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
1facf9fc 29297+{
e49829fe 29298+ int err;
027c5e7a
AM
29299+ unsigned int sigen;
29300+ struct super_block *sb;
e49829fe 29301+
027c5e7a
AM
29302+ sb = d1->d_sb;
29303+ err = si_read_lock(sb, flags);
29304+ if (unlikely(err))
29305+ goto out;
29306+
b95c5147 29307+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIRS));
027c5e7a
AM
29308+
29309+ if (au_ftest_lock(flags, GEN)) {
29310+ sigen = au_sigen(sb);
29311+ err = au_digen_test(d1, sigen);
29312+ AuDebugOn(!err && au_dbrange_test(d1));
29313+ if (!err) {
29314+ err = au_digen_test(d2, sigen);
29315+ AuDebugOn(!err && au_dbrange_test(d2));
29316+ }
29317+ if (unlikely(err))
29318+ aufs_read_and_write_unlock2(d1, d2);
29319+ }
29320+
29321+out:
e49829fe 29322+ return err;
1facf9fc 29323+}
29324+
29325+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
29326+{
29327+ di_write_unlock2(d1, d2);
29328+ si_read_unlock(d1->d_sb);
29329+}
7f207e10 29330diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
eca34b5c 29331--- /usr/share/empty/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
319657f6 29332+++ linux/fs/aufs/super.c 2021-12-03 15:40:58.236647297 +0100
0b2a12c6 29333@@ -0,0 +1,1050 @@
cd7a4cd9 29334+// SPDX-License-Identifier: GPL-2.0
1facf9fc 29335+/*
6d176551 29336+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 29337+ *
29338+ * This program, aufs is free software; you can redistribute it and/or modify
29339+ * it under the terms of the GNU General Public License as published by
29340+ * the Free Software Foundation; either version 2 of the License, or
29341+ * (at your option) any later version.
dece6358
AM
29342+ *
29343+ * This program is distributed in the hope that it will be useful,
29344+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29345+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29346+ * GNU General Public License for more details.
29347+ *
29348+ * You should have received a copy of the GNU General Public License
523b37e3 29349+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 29350+ */
29351+
29352+/*
29353+ * mount and super_block operations
29354+ */
29355+
eca801bf 29356+#include <linux/iversion.h>
f6c5ef8b 29357+#include <linux/mm.h>
1facf9fc 29358+#include <linux/seq_file.h>
29359+#include <linux/statfs.h>
7f207e10 29360+#include <linux/vmalloc.h>
1facf9fc 29361+#include "aufs.h"
29362+
29363+/*
29364+ * super_operations
29365+ */
29366+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
29367+{
29368+ struct au_icntnr *c;
29369+
29370+ c = au_cache_alloc_icntnr();
29371+ if (c) {
027c5e7a 29372+ au_icntnr_init(c);
be118d29 29373+ inode_set_iversion(&c->vfs_inode, 1); /* sigen(sb); */
1facf9fc 29374+ c->iinfo.ii_hinode = NULL;
29375+ return &c->vfs_inode;
29376+ }
29377+ return NULL;
29378+}
29379+
29380+static void aufs_destroy_inode(struct inode *inode)
29381+{
5afbbe0d
AM
29382+ if (!au_is_bad_inode(inode))
29383+ au_iinfo_fin(inode);
fbc438ed
JR
29384+}
29385+
29386+static void aufs_free_inode(struct inode *inode)
29387+{
29388+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
1facf9fc 29389+}
29390+
29391+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
29392+{
29393+ struct inode *inode;
29394+ int err;
29395+
29396+ inode = iget_locked(sb, ino);
29397+ if (unlikely(!inode)) {
29398+ inode = ERR_PTR(-ENOMEM);
29399+ goto out;
29400+ }
29401+ if (!(inode->i_state & I_NEW))
29402+ goto out;
29403+
29404+ err = au_xigen_new(inode);
29405+ if (!err)
29406+ err = au_iinfo_init(inode);
29407+ if (!err)
be118d29 29408+ inode_inc_iversion(inode);
1facf9fc 29409+ else {
29410+ iget_failed(inode);
29411+ inode = ERR_PTR(err);
29412+ }
29413+
4f0767ce 29414+out:
1facf9fc 29415+ /* never return NULL */
29416+ AuDebugOn(!inode);
29417+ AuTraceErrPtr(inode);
29418+ return inode;
29419+}
29420+
29421+/* lock free root dinfo */
29422+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
29423+{
29424+ int err;
5afbbe0d 29425+ aufs_bindex_t bindex, bbot;
1facf9fc 29426+ struct path path;
4a4d8108 29427+ struct au_hdentry *hdp;
1facf9fc 29428+ struct au_branch *br;
076b876e 29429+ au_br_perm_str_t perm;
1facf9fc 29430+
29431+ err = 0;
5afbbe0d
AM
29432+ bbot = au_sbbot(sb);
29433+ bindex = 0;
29434+ hdp = au_hdentry(au_di(sb->s_root), bindex);
29435+ for (; !err && bindex <= bbot; bindex++, hdp++) {
1facf9fc 29436+ br = au_sbr(sb, bindex);
86dc4139 29437+ path.mnt = au_br_mnt(br);
5afbbe0d 29438+ path.dentry = hdp->hd_dentry;
1facf9fc 29439+ err = au_seq_path(seq, &path);
79b8bda9 29440+ if (!err) {
076b876e 29441+ au_optstr_br_perm(&perm, br->br_perm);
79b8bda9 29442+ seq_printf(seq, "=%s", perm.a);
5afbbe0d 29443+ if (bindex != bbot)
79b8bda9 29444+ seq_putc(seq, ':');
1e00d052 29445+ }
1facf9fc 29446+ }
79b8bda9
AM
29447+ if (unlikely(err || seq_has_overflowed(seq)))
29448+ err = -E2BIG;
1facf9fc 29449+
29450+ return err;
29451+}
29452+
f2c43d5f
AM
29453+static void au_gen_fmt(char *fmt, int len __maybe_unused, const char *pat,
29454+ const char *append)
29455+{
29456+ char *p;
29457+
29458+ p = fmt;
29459+ while (*pat != ':')
29460+ *p++ = *pat++;
29461+ *p++ = *pat++;
29462+ strcpy(p, append);
29463+ AuDebugOn(strlen(fmt) >= len);
29464+}
29465+
1facf9fc 29466+static void au_show_wbr_create(struct seq_file *m, int v,
29467+ struct au_sbinfo *sbinfo)
29468+{
29469+ const char *pat;
f2c43d5f
AM
29470+ char fmt[32];
29471+ struct au_wbr_mfs *mfs;
1facf9fc 29472+
dece6358
AM
29473+ AuRwMustAnyLock(&sbinfo->si_rwsem);
29474+
c2b27bf2 29475+ seq_puts(m, ",create=");
1facf9fc 29476+ pat = au_optstr_wbr_create(v);
f2c43d5f 29477+ mfs = &sbinfo->si_wbr_mfs;
1facf9fc 29478+ switch (v) {
29479+ case AuWbrCreate_TDP:
29480+ case AuWbrCreate_RR:
29481+ case AuWbrCreate_MFS:
29482+ case AuWbrCreate_PMFS:
c2b27bf2 29483+ seq_puts(m, pat);
1facf9fc 29484+ break;
f2c43d5f
AM
29485+ case AuWbrCreate_MFSRR:
29486+ case AuWbrCreate_TDMFS:
29487+ case AuWbrCreate_PMFSRR:
29488+ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu");
29489+ seq_printf(m, fmt, mfs->mfsrr_watermark);
1facf9fc 29490+ break;
f2c43d5f 29491+ case AuWbrCreate_MFSV:
1facf9fc 29492+ case AuWbrCreate_PMFSV:
f2c43d5f
AM
29493+ au_gen_fmt(fmt, sizeof(fmt), pat, "%lu");
29494+ seq_printf(m, fmt,
29495+ jiffies_to_msecs(mfs->mfs_expire)
e49829fe 29496+ / MSEC_PER_SEC);
1facf9fc 29497+ break;
1facf9fc 29498+ case AuWbrCreate_MFSRRV:
f2c43d5f 29499+ case AuWbrCreate_TDMFSV:
392086de 29500+ case AuWbrCreate_PMFSRRV:
f2c43d5f
AM
29501+ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu:%lu");
29502+ seq_printf(m, fmt, mfs->mfsrr_watermark,
29503+ jiffies_to_msecs(mfs->mfs_expire) / MSEC_PER_SEC);
392086de 29504+ break;
f2c43d5f
AM
29505+ default:
29506+ BUG();
1facf9fc 29507+ }
29508+}
29509+
7eafdf33 29510+static int au_show_xino(struct seq_file *seq, struct super_block *sb)
1facf9fc 29511+{
29512+#ifdef CONFIG_SYSFS
29513+ return 0;
29514+#else
29515+ int err;
29516+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
29517+ aufs_bindex_t bindex, brid;
1facf9fc 29518+ struct qstr *name;
29519+ struct file *f;
29520+ struct dentry *d, *h_root;
acd2b654 29521+ struct au_branch *br;
1facf9fc 29522+
dece6358
AM
29523+ AuRwMustAnyLock(&sbinfo->si_rwsem);
29524+
1facf9fc 29525+ err = 0;
1facf9fc 29526+ f = au_sbi(sb)->si_xib;
29527+ if (!f)
29528+ goto out;
29529+
29530+ /* stop printing the default xino path on the first writable branch */
29531+ h_root = NULL;
acd2b654
AM
29532+ bindex = au_xi_root(sb, f->f_path.dentry);
29533+ if (bindex >= 0) {
29534+ br = au_sbr_sb(sb, bindex);
29535+ h_root = au_br_dentry(br);
1facf9fc 29536+ }
acd2b654 29537+
2000de60 29538+ d = f->f_path.dentry;
1facf9fc 29539+ name = &d->d_name;
29540+ /* safe ->d_parent because the file is unlinked */
29541+ if (d->d_parent == h_root
29542+ && name->len == len
29543+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
29544+ goto out;
29545+
29546+ seq_puts(seq, ",xino=");
29547+ err = au_xino_path(seq, f);
29548+
4f0767ce 29549+out:
1facf9fc 29550+ return err;
29551+#endif
29552+}
29553+
29554+/* seq_file will re-call me in case of too long string */
7eafdf33 29555+static int aufs_show_options(struct seq_file *m, struct dentry *dentry)
1facf9fc 29556+{
027c5e7a 29557+ int err;
1facf9fc 29558+ unsigned int mnt_flags, v;
29559+ struct super_block *sb;
29560+ struct au_sbinfo *sbinfo;
29561+
29562+#define AuBool(name, str) do { \
29563+ v = au_opt_test(mnt_flags, name); \
29564+ if (v != au_opt_test(AuOpt_Def, name)) \
29565+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
29566+} while (0)
29567+
29568+#define AuStr(name, str) do { \
29569+ v = mnt_flags & AuOptMask_##name; \
29570+ if (v != (AuOpt_Def & AuOptMask_##name)) \
29571+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
29572+} while (0)
29573+
29574+#define AuUInt(name, str, val) do { \
29575+ if (val != AUFS_##name##_DEF) \
29576+ seq_printf(m, "," #str "=%u", val); \
29577+} while (0)
29578+
7eafdf33 29579+ sb = dentry->d_sb;
2121bcd9 29580+ if (sb->s_flags & SB_POSIXACL)
c1595e42 29581+ seq_puts(m, ",acl");
43982f53 29582+#if 0 /* reserved for future use */
be118d29
JR
29583+ if (sb->s_flags & SB_I_VERSION)
29584+ seq_puts(m, ",i_version");
29585+#endif
c1595e42
JR
29586+
29587+ /* lock free root dinfo */
1facf9fc 29588+ si_noflush_read_lock(sb);
29589+ sbinfo = au_sbi(sb);
29590+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
29591+
29592+ mnt_flags = au_mntflags(sb);
29593+ if (au_opt_test(mnt_flags, XINO)) {
7eafdf33 29594+ err = au_show_xino(m, sb);
1facf9fc 29595+ if (unlikely(err))
29596+ goto out;
29597+ } else
29598+ seq_puts(m, ",noxino");
29599+
29600+ AuBool(TRUNC_XINO, trunc_xino);
29601+ AuStr(UDBA, udba);
dece6358 29602+ AuBool(SHWH, shwh);
1facf9fc 29603+ AuBool(PLINK, plink);
4a4d8108 29604+ AuBool(DIO, dio);
076b876e 29605+ AuBool(DIRPERM1, dirperm1);
1facf9fc 29606+
29607+ v = sbinfo->si_wbr_create;
29608+ if (v != AuWbrCreate_Def)
29609+ au_show_wbr_create(m, v, sbinfo);
29610+
29611+ v = sbinfo->si_wbr_copyup;
29612+ if (v != AuWbrCopyup_Def)
29613+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
29614+
29615+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
29616+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
29617+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
29618+
29619+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
29620+
027c5e7a
AM
29621+ v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC;
29622+ AuUInt(RDCACHE, rdcache, v);
1facf9fc 29623+
29624+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
29625+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
29626+
076b876e
AM
29627+ au_fhsm_show(m, sbinfo);
29628+
8b6a4947 29629+ AuBool(DIRREN, dirren);
1facf9fc 29630+ AuBool(SUM, sum);
29631+ /* AuBool(SUM_W, wsum); */
29632+ AuBool(WARN_PERM, warn_perm);
29633+ AuBool(VERBOSE, verbose);
29634+
4f0767ce 29635+out:
1facf9fc 29636+ /* be sure to print "br:" last */
29637+ if (!sysaufs_brs) {
29638+ seq_puts(m, ",br:");
29639+ au_show_brs(m, sb);
29640+ }
29641+ si_read_unlock(sb);
29642+ return 0;
29643+
1facf9fc 29644+#undef AuBool
29645+#undef AuStr
4a4d8108 29646+#undef AuUInt
1facf9fc 29647+}
29648+
29649+/* ---------------------------------------------------------------------- */
29650+
29651+/* sum mode which returns the summation for statfs(2) */
29652+
29653+static u64 au_add_till_max(u64 a, u64 b)
29654+{
29655+ u64 old;
29656+
29657+ old = a;
29658+ a += b;
92d182d2
AM
29659+ if (old <= a)
29660+ return a;
29661+ return ULLONG_MAX;
29662+}
29663+
29664+static u64 au_mul_till_max(u64 a, long mul)
29665+{
29666+ u64 old;
29667+
29668+ old = a;
29669+ a *= mul;
29670+ if (old <= a)
1facf9fc 29671+ return a;
29672+ return ULLONG_MAX;
29673+}
29674+
29675+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
29676+{
29677+ int err;
92d182d2 29678+ long bsize, factor;
1facf9fc 29679+ u64 blocks, bfree, bavail, files, ffree;
5afbbe0d 29680+ aufs_bindex_t bbot, bindex, i;
1facf9fc 29681+ unsigned char shared;
7f207e10 29682+ struct path h_path;
1facf9fc 29683+ struct super_block *h_sb;
29684+
92d182d2
AM
29685+ err = 0;
29686+ bsize = LONG_MAX;
29687+ files = 0;
29688+ ffree = 0;
1facf9fc 29689+ blocks = 0;
29690+ bfree = 0;
29691+ bavail = 0;
5afbbe0d
AM
29692+ bbot = au_sbbot(sb);
29693+ for (bindex = 0; bindex <= bbot; bindex++) {
7f207e10
AM
29694+ h_path.mnt = au_sbr_mnt(sb, bindex);
29695+ h_sb = h_path.mnt->mnt_sb;
1facf9fc 29696+ shared = 0;
92d182d2 29697+ for (i = 0; !shared && i < bindex; i++)
1facf9fc 29698+ shared = (au_sbr_sb(sb, i) == h_sb);
29699+ if (shared)
29700+ continue;
29701+
29702+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
29703+ h_path.dentry = h_path.mnt->mnt_root;
29704+ err = vfs_statfs(&h_path, buf);
1facf9fc 29705+ if (unlikely(err))
29706+ goto out;
29707+
92d182d2
AM
29708+ if (bsize > buf->f_bsize) {
29709+ /*
29710+ * we will reduce bsize, so we have to expand blocks
29711+ * etc. to match them again
29712+ */
29713+ factor = (bsize / buf->f_bsize);
29714+ blocks = au_mul_till_max(blocks, factor);
29715+ bfree = au_mul_till_max(bfree, factor);
29716+ bavail = au_mul_till_max(bavail, factor);
29717+ bsize = buf->f_bsize;
29718+ }
29719+
29720+ factor = (buf->f_bsize / bsize);
29721+ blocks = au_add_till_max(blocks,
29722+ au_mul_till_max(buf->f_blocks, factor));
29723+ bfree = au_add_till_max(bfree,
29724+ au_mul_till_max(buf->f_bfree, factor));
29725+ bavail = au_add_till_max(bavail,
29726+ au_mul_till_max(buf->f_bavail, factor));
1facf9fc 29727+ files = au_add_till_max(files, buf->f_files);
29728+ ffree = au_add_till_max(ffree, buf->f_ffree);
29729+ }
29730+
92d182d2 29731+ buf->f_bsize = bsize;
1facf9fc 29732+ buf->f_blocks = blocks;
29733+ buf->f_bfree = bfree;
29734+ buf->f_bavail = bavail;
29735+ buf->f_files = files;
29736+ buf->f_ffree = ffree;
92d182d2 29737+ buf->f_frsize = 0;
1facf9fc 29738+
4f0767ce 29739+out:
1facf9fc 29740+ return err;
29741+}
29742+
29743+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
29744+{
29745+ int err;
7f207e10 29746+ struct path h_path;
1facf9fc 29747+ struct super_block *sb;
29748+
29749+ /* lock free root dinfo */
29750+ sb = dentry->d_sb;
29751+ si_noflush_read_lock(sb);
7f207e10 29752+ if (!au_opt_test(au_mntflags(sb), SUM)) {
1facf9fc 29753+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
29754+ h_path.mnt = au_sbr_mnt(sb, 0);
29755+ h_path.dentry = h_path.mnt->mnt_root;
29756+ err = vfs_statfs(&h_path, buf);
29757+ } else
1facf9fc 29758+ err = au_statfs_sum(sb, buf);
29759+ si_read_unlock(sb);
29760+
29761+ if (!err) {
29762+ buf->f_type = AUFS_SUPER_MAGIC;
4a4d8108 29763+ buf->f_namelen = AUFS_MAX_NAMELEN;
1facf9fc 29764+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
29765+ }
29766+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
29767+
29768+ return err;
29769+}
29770+
29771+/* ---------------------------------------------------------------------- */
29772+
537831f9
AM
29773+static int aufs_sync_fs(struct super_block *sb, int wait)
29774+{
29775+ int err, e;
5afbbe0d 29776+ aufs_bindex_t bbot, bindex;
537831f9
AM
29777+ struct au_branch *br;
29778+ struct super_block *h_sb;
29779+
29780+ err = 0;
29781+ si_noflush_read_lock(sb);
5afbbe0d
AM
29782+ bbot = au_sbbot(sb);
29783+ for (bindex = 0; bindex <= bbot; bindex++) {
537831f9
AM
29784+ br = au_sbr(sb, bindex);
29785+ if (!au_br_writable(br->br_perm))
29786+ continue;
29787+
29788+ h_sb = au_sbr_sb(sb, bindex);
a2654f78
AM
29789+ e = vfsub_sync_filesystem(h_sb, wait);
29790+ if (unlikely(e && !err))
29791+ err = e;
29792+ /* go on even if an error happens */
537831f9
AM
29793+ }
29794+ si_read_unlock(sb);
29795+
29796+ return err;
29797+}
29798+
29799+/* ---------------------------------------------------------------------- */
29800+
1facf9fc 29801+/* final actions when unmounting a file system */
29802+static void aufs_put_super(struct super_block *sb)
29803+{
29804+ struct au_sbinfo *sbinfo;
29805+
29806+ sbinfo = au_sbi(sb);
062440b3
AM
29807+ if (sbinfo)
29808+ kobject_put(&sbinfo->si_kobj);
1facf9fc 29809+}
29810+
29811+/* ---------------------------------------------------------------------- */
29812+
79b8bda9
AM
29813+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb,
29814+ struct super_block *sb, void *arg)
7f207e10
AM
29815+{
29816+ void *array;
076b876e 29817+ unsigned long long n, sz;
7f207e10
AM
29818+
29819+ array = NULL;
29820+ n = 0;
29821+ if (!*hint)
29822+ goto out;
29823+
29824+ if (*hint > ULLONG_MAX / sizeof(array)) {
29825+ array = ERR_PTR(-EMFILE);
29826+ pr_err("hint %llu\n", *hint);
29827+ goto out;
29828+ }
29829+
076b876e
AM
29830+ sz = sizeof(array) * *hint;
29831+ array = kzalloc(sz, GFP_NOFS);
7f207e10 29832+ if (unlikely(!array))
076b876e 29833+ array = vzalloc(sz);
7f207e10
AM
29834+ if (unlikely(!array)) {
29835+ array = ERR_PTR(-ENOMEM);
29836+ goto out;
29837+ }
29838+
79b8bda9 29839+ n = cb(sb, array, *hint, arg);
7f207e10
AM
29840+ AuDebugOn(n > *hint);
29841+
29842+out:
29843+ *hint = n;
29844+ return array;
29845+}
29846+
79b8bda9 29847+static unsigned long long au_iarray_cb(struct super_block *sb, void *a,
7f207e10
AM
29848+ unsigned long long max __maybe_unused,
29849+ void *arg)
29850+{
29851+ unsigned long long n;
29852+ struct inode **p, *inode;
29853+ struct list_head *head;
29854+
29855+ n = 0;
29856+ p = a;
29857+ head = arg;
79b8bda9 29858+ spin_lock(&sb->s_inode_list_lock);
7f207e10 29859+ list_for_each_entry(inode, head, i_sb_list) {
5afbbe0d
AM
29860+ if (!au_is_bad_inode(inode)
29861+ && au_ii(inode)->ii_btop >= 0) {
2cbb1c4b
JR
29862+ spin_lock(&inode->i_lock);
29863+ if (atomic_read(&inode->i_count)) {
29864+ au_igrab(inode);
29865+ *p++ = inode;
29866+ n++;
29867+ AuDebugOn(n > max);
29868+ }
29869+ spin_unlock(&inode->i_lock);
7f207e10
AM
29870+ }
29871+ }
79b8bda9 29872+ spin_unlock(&sb->s_inode_list_lock);
7f207e10
AM
29873+
29874+ return n;
29875+}
29876+
29877+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max)
29878+{
acd2b654
AM
29879+ struct au_sbinfo *sbi;
29880+
29881+ sbi = au_sbi(sb);
29882+ *max = au_lcnt_read(&sbi->si_ninodes, /*do_rev*/1);
79b8bda9 29883+ return au_array_alloc(max, au_iarray_cb, sb, &sb->s_inodes);
7f207e10
AM
29884+}
29885+
29886+void au_iarray_free(struct inode **a, unsigned long long max)
29887+{
29888+ unsigned long long ull;
29889+
29890+ for (ull = 0; ull < max; ull++)
29891+ iput(a[ull]);
be52b249 29892+ kvfree(a);
7f207e10
AM
29893+}
29894+
29895+/* ---------------------------------------------------------------------- */
29896+
1facf9fc 29897+/*
29898+ * refresh dentry and inode at remount time.
29899+ */
027c5e7a
AM
29900+/* todo: consolidate with simple_reval_dpath() and au_reval_for_attr() */
29901+static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags,
29902+ struct dentry *parent)
1facf9fc 29903+{
29904+ int err;
1facf9fc 29905+
29906+ di_write_lock_child(dentry);
1facf9fc 29907+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
29908+ err = au_refresh_dentry(dentry, parent);
29909+ if (!err && dir_flags)
5527c038 29910+ au_hn_reset(d_inode(dentry), dir_flags);
1facf9fc 29911+ di_read_unlock(parent, AuLock_IR);
1facf9fc 29912+ di_write_unlock(dentry);
29913+
29914+ return err;
29915+}
29916+
027c5e7a
AM
29917+static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen,
29918+ struct au_sbinfo *sbinfo,
b95c5147 29919+ const unsigned int dir_flags, unsigned int do_idop)
1facf9fc 29920+{
027c5e7a
AM
29921+ int err;
29922+ struct dentry *parent;
027c5e7a
AM
29923+
29924+ err = 0;
29925+ parent = dget_parent(dentry);
29926+ if (!au_digen_test(parent, sigen) && au_digen_test(dentry, sigen)) {
5527c038
JR
29927+ if (d_really_is_positive(dentry)) {
29928+ if (!d_is_dir(dentry))
027c5e7a
AM
29929+ err = au_do_refresh(dentry, /*dir_flags*/0,
29930+ parent);
29931+ else {
29932+ err = au_do_refresh(dentry, dir_flags, parent);
29933+ if (unlikely(err))
29934+ au_fset_si(sbinfo, FAILED_REFRESH_DIR);
29935+ }
29936+ } else
29937+ err = au_do_refresh(dentry, /*dir_flags*/0, parent);
29938+ AuDbgDentry(dentry);
29939+ }
29940+ dput(parent);
29941+
79b8bda9 29942+ if (!err) {
b95c5147 29943+ if (do_idop)
79b8bda9
AM
29944+ au_refresh_dop(dentry, /*force_reval*/0);
29945+ } else
29946+ au_refresh_dop(dentry, /*force_reval*/1);
29947+
027c5e7a
AM
29948+ AuTraceErr(err);
29949+ return err;
1facf9fc 29950+}
29951+
b95c5147 29952+static int au_refresh_d(struct super_block *sb, unsigned int do_idop)
1facf9fc 29953+{
29954+ int err, i, j, ndentry, e;
027c5e7a 29955+ unsigned int sigen;
1facf9fc 29956+ struct au_dcsub_pages dpages;
29957+ struct au_dpage *dpage;
027c5e7a
AM
29958+ struct dentry **dentries, *d;
29959+ struct au_sbinfo *sbinfo;
29960+ struct dentry *root = sb->s_root;
5527c038 29961+ const unsigned int dir_flags = au_hi_flags(d_inode(root), /*isdir*/1);
1facf9fc 29962+
b95c5147 29963+ if (do_idop)
79b8bda9
AM
29964+ au_refresh_dop(root, /*force_reval*/0);
29965+
027c5e7a
AM
29966+ err = au_dpages_init(&dpages, GFP_NOFS);
29967+ if (unlikely(err))
1facf9fc 29968+ goto out;
027c5e7a
AM
29969+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
29970+ if (unlikely(err))
1facf9fc 29971+ goto out_dpages;
1facf9fc 29972+
027c5e7a
AM
29973+ sigen = au_sigen(sb);
29974+ sbinfo = au_sbi(sb);
29975+ for (i = 0; i < dpages.ndpage; i++) {
1facf9fc 29976+ dpage = dpages.dpages + i;
29977+ dentries = dpage->dentries;
29978+ ndentry = dpage->ndentry;
027c5e7a 29979+ for (j = 0; j < ndentry; j++) {
1facf9fc 29980+ d = dentries[j];
79b8bda9 29981+ e = au_do_refresh_d(d, sigen, sbinfo, dir_flags,
b95c5147 29982+ do_idop);
027c5e7a
AM
29983+ if (unlikely(e && !err))
29984+ err = e;
29985+ /* go on even err */
1facf9fc 29986+ }
29987+ }
29988+
4f0767ce 29989+out_dpages:
1facf9fc 29990+ au_dpages_free(&dpages);
4f0767ce 29991+out:
1facf9fc 29992+ return err;
29993+}
29994+
b95c5147 29995+static int au_refresh_i(struct super_block *sb, unsigned int do_idop)
1facf9fc 29996+{
027c5e7a
AM
29997+ int err, e;
29998+ unsigned int sigen;
29999+ unsigned long long max, ull;
30000+ struct inode *inode, **array;
1facf9fc 30001+
027c5e7a
AM
30002+ array = au_iarray_alloc(sb, &max);
30003+ err = PTR_ERR(array);
30004+ if (IS_ERR(array))
30005+ goto out;
1facf9fc 30006+
30007+ err = 0;
027c5e7a
AM
30008+ sigen = au_sigen(sb);
30009+ for (ull = 0; ull < max; ull++) {
30010+ inode = array[ull];
076b876e
AM
30011+ if (unlikely(!inode))
30012+ break;
b95c5147
AM
30013+
30014+ e = 0;
30015+ ii_write_lock_child(inode);
537831f9 30016+ if (au_iigen(inode, NULL) != sigen) {
027c5e7a 30017+ e = au_refresh_hinode_self(inode);
1facf9fc 30018+ if (unlikely(e)) {
b95c5147 30019+ au_refresh_iop(inode, /*force_getattr*/1);
027c5e7a 30020+ pr_err("error %d, i%lu\n", e, inode->i_ino);
1facf9fc 30021+ if (!err)
30022+ err = e;
30023+ /* go on even if err */
30024+ }
30025+ }
b95c5147
AM
30026+ if (!e && do_idop)
30027+ au_refresh_iop(inode, /*force_getattr*/0);
30028+ ii_write_unlock(inode);
1facf9fc 30029+ }
30030+
027c5e7a 30031+ au_iarray_free(array, max);
1facf9fc 30032+
4f0767ce 30033+out:
1facf9fc 30034+ return err;
30035+}
30036+
b95c5147 30037+static void au_remount_refresh(struct super_block *sb, unsigned int do_idop)
1facf9fc 30038+{
027c5e7a
AM
30039+ int err, e;
30040+ unsigned int udba;
5afbbe0d 30041+ aufs_bindex_t bindex, bbot;
1facf9fc 30042+ struct dentry *root;
30043+ struct inode *inode;
027c5e7a 30044+ struct au_branch *br;
79b8bda9 30045+ struct au_sbinfo *sbi;
1facf9fc 30046+
30047+ au_sigen_inc(sb);
79b8bda9
AM
30048+ sbi = au_sbi(sb);
30049+ au_fclr_si(sbi, FAILED_REFRESH_DIR);
1facf9fc 30050+
30051+ root = sb->s_root;
30052+ DiMustNoWaiters(root);
5527c038 30053+ inode = d_inode(root);
1facf9fc 30054+ IiMustNoWaiters(inode);
1facf9fc 30055+
027c5e7a 30056+ udba = au_opt_udba(sb);
5afbbe0d
AM
30057+ bbot = au_sbbot(sb);
30058+ for (bindex = 0; bindex <= bbot; bindex++) {
027c5e7a
AM
30059+ br = au_sbr(sb, bindex);
30060+ err = au_hnotify_reset_br(udba, br, br->br_perm);
1facf9fc 30061+ if (unlikely(err))
027c5e7a
AM
30062+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
30063+ bindex, err);
30064+ /* go on even if err */
1facf9fc 30065+ }
027c5e7a 30066+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
1facf9fc 30067+
b95c5147 30068+ if (do_idop) {
79b8bda9
AM
30069+ if (au_ftest_si(sbi, NO_DREVAL)) {
30070+ AuDebugOn(sb->s_d_op == &aufs_dop_noreval);
30071+ sb->s_d_op = &aufs_dop_noreval;
b95c5147
AM
30072+ AuDebugOn(sbi->si_iop_array == aufs_iop_nogetattr);
30073+ sbi->si_iop_array = aufs_iop_nogetattr;
79b8bda9
AM
30074+ } else {
30075+ AuDebugOn(sb->s_d_op == &aufs_dop);
30076+ sb->s_d_op = &aufs_dop;
b95c5147
AM
30077+ AuDebugOn(sbi->si_iop_array == aufs_iop);
30078+ sbi->si_iop_array = aufs_iop;
79b8bda9 30079+ }
062440b3 30080+ pr_info("reset to %ps and %ps\n",
b95c5147 30081+ sb->s_d_op, sbi->si_iop_array);
79b8bda9
AM
30082+ }
30083+
027c5e7a 30084+ di_write_unlock(root);
b95c5147
AM
30085+ err = au_refresh_d(sb, do_idop);
30086+ e = au_refresh_i(sb, do_idop);
027c5e7a
AM
30087+ if (unlikely(e && !err))
30088+ err = e;
1facf9fc 30089+ /* aufs_write_lock() calls ..._child() */
30090+ di_write_lock_child(root);
027c5e7a
AM
30091+
30092+ au_cpup_attr_all(inode, /*force*/1);
30093+
30094+ if (unlikely(err))
30095+ AuIOErr("refresh failed, ignored, %d\n", err);
1facf9fc 30096+}
30097+
30098+/* stop extra interpretation of errno in mount(8), and strange error messages */
30099+static int cvt_err(int err)
30100+{
30101+ AuTraceErr(err);
30102+
30103+ switch (err) {
30104+ case -ENOENT:
30105+ case -ENOTDIR:
30106+ case -EEXIST:
30107+ case -EIO:
30108+ err = -EINVAL;
30109+ }
30110+ return err;
30111+}
30112+
30113+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
30114+{
4a4d8108
AM
30115+ int err, do_dx;
30116+ unsigned int mntflags;
be52b249
AM
30117+ struct au_opts opts = {
30118+ .opt = NULL
30119+ };
1facf9fc 30120+ struct dentry *root;
30121+ struct inode *inode;
30122+ struct au_sbinfo *sbinfo;
30123+
30124+ err = 0;
30125+ root = sb->s_root;
30126+ if (!data || !*data) {
e49829fe
JR
30127+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
30128+ if (!err) {
30129+ di_write_lock_child(root);
30130+ err = au_opts_verify(sb, *flags, /*pending*/0);
30131+ aufs_write_unlock(root);
30132+ }
1facf9fc 30133+ goto out;
30134+ }
30135+
30136+ err = -ENOMEM;
1facf9fc 30137+ opts.opt = (void *)__get_free_page(GFP_NOFS);
30138+ if (unlikely(!opts.opt))
30139+ goto out;
30140+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
30141+ opts.flags = AuOpts_REMOUNT;
30142+ opts.sb_flags = *flags;
30143+
30144+ /* parse it before aufs lock */
30145+ err = au_opts_parse(sb, data, &opts);
30146+ if (unlikely(err))
30147+ goto out_opts;
30148+
30149+ sbinfo = au_sbi(sb);
5527c038 30150+ inode = d_inode(root);
febd17d6 30151+ inode_lock(inode);
e49829fe
JR
30152+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
30153+ if (unlikely(err))
30154+ goto out_mtx;
30155+ di_write_lock_child(root);
1facf9fc 30156+
30157+ /* au_opts_remount() may return an error */
30158+ err = au_opts_remount(sb, &opts);
30159+ au_opts_free(&opts);
30160+
027c5e7a 30161+ if (au_ftest_opts(opts.flags, REFRESH))
b95c5147 30162+ au_remount_refresh(sb, au_ftest_opts(opts.flags, REFRESH_IDOP));
1facf9fc 30163+
4a4d8108
AM
30164+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
30165+ mntflags = au_mntflags(sb);
30166+ do_dx = !!au_opt_test(mntflags, DIO);
30167+ au_dy_arefresh(do_dx);
30168+ }
30169+
076b876e 30170+ au_fhsm_wrote_all(sb, /*force*/1); /* ?? */
1facf9fc 30171+ aufs_write_unlock(root);
953406b4 30172+
e49829fe 30173+out_mtx:
febd17d6 30174+ inode_unlock(inode);
4f0767ce 30175+out_opts:
1c60b727 30176+ free_page((unsigned long)opts.opt);
4f0767ce 30177+out:
1facf9fc 30178+ err = cvt_err(err);
30179+ AuTraceErr(err);
30180+ return err;
30181+}
30182+
4a4d8108 30183+static const struct super_operations aufs_sop = {
1facf9fc 30184+ .alloc_inode = aufs_alloc_inode,
30185+ .destroy_inode = aufs_destroy_inode,
fbc438ed 30186+ .free_inode = aufs_free_inode,
b752ccd1 30187+ /* always deleting, no clearing */
1facf9fc 30188+ .drop_inode = generic_delete_inode,
30189+ .show_options = aufs_show_options,
30190+ .statfs = aufs_statfs,
30191+ .put_super = aufs_put_super,
537831f9 30192+ .sync_fs = aufs_sync_fs,
1facf9fc 30193+ .remount_fs = aufs_remount_fs
30194+};
30195+
30196+/* ---------------------------------------------------------------------- */
30197+
30198+static int alloc_root(struct super_block *sb)
30199+{
30200+ int err;
30201+ struct inode *inode;
30202+ struct dentry *root;
30203+
30204+ err = -ENOMEM;
30205+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
30206+ err = PTR_ERR(inode);
30207+ if (IS_ERR(inode))
30208+ goto out;
30209+
b95c5147 30210+ inode->i_op = aufs_iop + AuIop_DIR; /* with getattr by default */
1facf9fc 30211+ inode->i_fop = &aufs_dir_fop;
30212+ inode->i_mode = S_IFDIR;
9dbd164d 30213+ set_nlink(inode, 2);
1facf9fc 30214+ unlock_new_inode(inode);
30215+
92d182d2 30216+ root = d_make_root(inode);
1facf9fc 30217+ if (unlikely(!root))
92d182d2 30218+ goto out;
1facf9fc 30219+ err = PTR_ERR(root);
30220+ if (IS_ERR(root))
92d182d2 30221+ goto out;
1facf9fc 30222+
4a4d8108 30223+ err = au_di_init(root);
1facf9fc 30224+ if (!err) {
30225+ sb->s_root = root;
30226+ return 0; /* success */
30227+ }
30228+ dput(root);
1facf9fc 30229+
4f0767ce 30230+out:
1facf9fc 30231+ return err;
1facf9fc 30232+}
30233+
30234+static int aufs_fill_super(struct super_block *sb, void *raw_data,
30235+ int silent __maybe_unused)
30236+{
30237+ int err;
be52b249
AM
30238+ struct au_opts opts = {
30239+ .opt = NULL
30240+ };
79b8bda9 30241+ struct au_sbinfo *sbinfo;
1facf9fc 30242+ struct dentry *root;
30243+ struct inode *inode;
30244+ char *arg = raw_data;
30245+
30246+ if (unlikely(!arg || !*arg)) {
30247+ err = -EINVAL;
4a4d8108 30248+ pr_err("no arg\n");
1facf9fc 30249+ goto out;
30250+ }
30251+
30252+ err = -ENOMEM;
1facf9fc 30253+ opts.opt = (void *)__get_free_page(GFP_NOFS);
30254+ if (unlikely(!opts.opt))
30255+ goto out;
30256+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
30257+ opts.sb_flags = sb->s_flags;
30258+
30259+ err = au_si_alloc(sb);
30260+ if (unlikely(err))
30261+ goto out_opts;
79b8bda9 30262+ sbinfo = au_sbi(sb);
1facf9fc 30263+
30264+ /* all timestamps always follow the ones on the branch */
2121bcd9 30265+ sb->s_flags |= SB_NOATIME | SB_NODIRATIME;
be118d29 30266+ sb->s_flags |= SB_I_VERSION; /* do we really need this? */
1facf9fc 30267+ sb->s_op = &aufs_sop;
027c5e7a 30268+ sb->s_d_op = &aufs_dop;
1facf9fc 30269+ sb->s_magic = AUFS_SUPER_MAGIC;
30270+ sb->s_maxbytes = 0;
c1595e42 30271+ sb->s_stack_depth = 1;
1facf9fc 30272+ au_export_init(sb);
f2c43d5f 30273+ au_xattr_init(sb);
1facf9fc 30274+
30275+ err = alloc_root(sb);
30276+ if (unlikely(err)) {
30277+ si_write_unlock(sb);
30278+ goto out_info;
30279+ }
30280+ root = sb->s_root;
5527c038 30281+ inode = d_inode(root);
1facf9fc 30282+
30283+ /*
30284+ * actually we can parse options regardless aufs lock here.
30285+ * but at remount time, parsing must be done before aufs lock.
30286+ * so we follow the same rule.
30287+ */
30288+ ii_write_lock_parent(inode);
30289+ aufs_write_unlock(root);
30290+ err = au_opts_parse(sb, arg, &opts);
30291+ if (unlikely(err))
30292+ goto out_root;
30293+
30294+ /* lock vfs_inode first, then aufs. */
febd17d6 30295+ inode_lock(inode);
1facf9fc 30296+ aufs_write_lock(root);
30297+ err = au_opts_mount(sb, &opts);
30298+ au_opts_free(&opts);
79b8bda9
AM
30299+ if (!err && au_ftest_si(sbinfo, NO_DREVAL)) {
30300+ sb->s_d_op = &aufs_dop_noreval;
062440b3 30301+ pr_info("%ps\n", sb->s_d_op);
79b8bda9 30302+ au_refresh_dop(root, /*force_reval*/0);
b95c5147
AM
30303+ sbinfo->si_iop_array = aufs_iop_nogetattr;
30304+ au_refresh_iop(inode, /*force_getattr*/0);
79b8bda9 30305+ }
1facf9fc 30306+ aufs_write_unlock(root);
febd17d6 30307+ inode_unlock(inode);
4a4d8108
AM
30308+ if (!err)
30309+ goto out_opts; /* success */
1facf9fc 30310+
4f0767ce 30311+out_root:
1facf9fc 30312+ dput(root);
30313+ sb->s_root = NULL;
4f0767ce 30314+out_info:
79b8bda9 30315+ kobject_put(&sbinfo->si_kobj);
1facf9fc 30316+ sb->s_fs_info = NULL;
4f0767ce 30317+out_opts:
1c60b727 30318+ free_page((unsigned long)opts.opt);
4f0767ce 30319+out:
1facf9fc 30320+ AuTraceErr(err);
30321+ err = cvt_err(err);
30322+ AuTraceErr(err);
30323+ return err;
30324+}
30325+
30326+/* ---------------------------------------------------------------------- */
30327+
027c5e7a
AM
30328+static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags,
30329+ const char *dev_name __maybe_unused,
30330+ void *raw_data)
1facf9fc 30331+{
027c5e7a 30332+ struct dentry *root;
1facf9fc 30333+
30334+ /* all timestamps always follow the ones on the branch */
30335+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
027c5e7a
AM
30336+ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super);
30337+ if (IS_ERR(root))
30338+ goto out;
30339+
062440b3 30340+ au_sbilist_add(root->d_sb);
027c5e7a
AM
30341+
30342+out:
30343+ return root;
1facf9fc 30344+}
30345+
e49829fe
JR
30346+static void aufs_kill_sb(struct super_block *sb)
30347+{
30348+ struct au_sbinfo *sbinfo;
30349+
30350+ sbinfo = au_sbi(sb);
30351+ if (sbinfo) {
30352+ au_sbilist_del(sb);
30353+ aufs_write_lock(sb->s_root);
076b876e 30354+ au_fhsm_fin(sb);
e49829fe
JR
30355+ if (sbinfo->si_wbr_create_ops->fin)
30356+ sbinfo->si_wbr_create_ops->fin(sb);
30357+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
30358+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
b95c5147 30359+ au_remount_refresh(sb, /*do_idop*/0);
e49829fe
JR
30360+ }
30361+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
30362+ au_plink_put(sb, /*verbose*/1);
30363+ au_xino_clr(sb);
8b6a4947 30364+ au_dr_opt_flush(sb);
1e00d052 30365+ sbinfo->si_sb = NULL;
e49829fe 30366+ aufs_write_unlock(sb->s_root);
e49829fe
JR
30367+ au_nwt_flush(&sbinfo->si_nowait);
30368+ }
98d9a5b1 30369+ kill_anon_super(sb);
e49829fe
JR
30370+}
30371+
1facf9fc 30372+struct file_system_type aufs_fs_type = {
30373+ .name = AUFS_FSTYPE,
c06a8ce3 30374+ /* a race between rename and others */
0b2a12c6
JR
30375+ .fs_flags = FS_RENAME_DOES_D_MOVE
30376+ /* untested */
30377+ /*| FS_ALLOW_IDMAP*/
30378+ ,
027c5e7a 30379+ .mount = aufs_mount,
e49829fe 30380+ .kill_sb = aufs_kill_sb,
1facf9fc 30381+ /* no need to __module_get() and module_put(). */
30382+ .owner = THIS_MODULE,
30383+};
7f207e10 30384diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
eca34b5c 30385--- /usr/share/empty/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
319657f6 30386+++ linux/fs/aufs/super.h 2021-12-03 15:38:59.939980643 +0100
e37dd06a 30387@@ -0,0 +1,587 @@
062440b3 30388+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 30389+/*
6d176551 30390+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 30391+ *
30392+ * This program, aufs is free software; you can redistribute it and/or modify
30393+ * it under the terms of the GNU General Public License as published by
30394+ * the Free Software Foundation; either version 2 of the License, or
30395+ * (at your option) any later version.
dece6358
AM
30396+ *
30397+ * This program is distributed in the hope that it will be useful,
30398+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
30399+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30400+ * GNU General Public License for more details.
30401+ *
30402+ * You should have received a copy of the GNU General Public License
523b37e3 30403+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 30404+ */
30405+
30406+/*
30407+ * super_block operations
30408+ */
30409+
30410+#ifndef __AUFS_SUPER_H__
30411+#define __AUFS_SUPER_H__
30412+
30413+#ifdef __KERNEL__
30414+
30415+#include <linux/fs.h>
5527c038 30416+#include <linux/kobject.h>
8b6a4947 30417+#include "hbl.h"
acd2b654 30418+#include "lcnt.h"
1facf9fc 30419+#include "rwsem.h"
1facf9fc 30420+#include "wkq.h"
30421+
1facf9fc 30422+/* policies to select one among multiple writable branches */
30423+struct au_wbr_copyup_operations {
30424+ int (*copyup)(struct dentry *dentry);
30425+};
30426+
392086de
AM
30427+#define AuWbr_DIR 1 /* target is a dir */
30428+#define AuWbr_PARENT (1 << 1) /* always require a parent */
30429+
30430+#define au_ftest_wbr(flags, name) ((flags) & AuWbr_##name)
30431+#define au_fset_wbr(flags, name) { (flags) |= AuWbr_##name; }
30432+#define au_fclr_wbr(flags, name) { (flags) &= ~AuWbr_##name; }
30433+
1facf9fc 30434+struct au_wbr_create_operations {
392086de 30435+ int (*create)(struct dentry *dentry, unsigned int flags);
1facf9fc 30436+ int (*init)(struct super_block *sb);
30437+ int (*fin)(struct super_block *sb);
30438+};
30439+
30440+struct au_wbr_mfs {
30441+ struct mutex mfs_lock; /* protect this structure */
30442+ unsigned long mfs_jiffy;
30443+ unsigned long mfs_expire;
30444+ aufs_bindex_t mfs_bindex;
30445+
30446+ unsigned long long mfsrr_bytes;
30447+ unsigned long long mfsrr_watermark;
30448+};
30449+
86dc4139
AM
30450+#define AuPlink_NHASH 100
30451+static inline int au_plink_hash(ino_t ino)
30452+{
30453+ return ino % AuPlink_NHASH;
30454+}
30455+
076b876e
AM
30456+/* File-based Hierarchical Storage Management */
30457+struct au_fhsm {
30458+#ifdef CONFIG_AUFS_FHSM
30459+ /* allow only one process who can receive the notification */
30460+ spinlock_t fhsm_spin;
30461+ pid_t fhsm_pid;
30462+ wait_queue_head_t fhsm_wqh;
30463+ atomic_t fhsm_readable;
30464+
c1595e42 30465+ /* these are protected by si_rwsem */
076b876e 30466+ unsigned long fhsm_expire;
c1595e42 30467+ aufs_bindex_t fhsm_bottom;
076b876e
AM
30468+#endif
30469+};
30470+
1facf9fc 30471+struct au_branch;
30472+struct au_sbinfo {
30473+ /* nowait tasks in the system-wide workqueue */
30474+ struct au_nowait_tasks si_nowait;
30475+
b752ccd1 30476+ /*
acd2b654 30477+ * tried sb->s_umount, but failed due to the dependency between i_mutex.
b752ccd1
AM
30478+ * rwsem for au_sbinfo is necessary.
30479+ */
dece6358 30480+ struct au_rwsem si_rwsem;
1facf9fc 30481+
7f207e10 30482+ /*
523b37e3
AM
30483+ * dirty approach to protect sb->sb_inodes and ->s_files (gone) from
30484+ * remount.
7f207e10 30485+ */
acd2b654 30486+ au_lcnt_t si_ninodes, si_nfiles;
7f207e10 30487+
1facf9fc 30488+ /* branch management */
30489+ unsigned int si_generation;
30490+
2000de60 30491+ /* see AuSi_ flags */
1facf9fc 30492+ unsigned char au_si_status;
30493+
5afbbe0d 30494+ aufs_bindex_t si_bbot;
7f207e10
AM
30495+
30496+ /* dirty trick to keep br_id plus */
30497+ unsigned int si_last_br_id :
30498+ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1;
1facf9fc 30499+ struct au_branch **si_branch;
30500+
30501+ /* policy to select a writable branch */
30502+ unsigned char si_wbr_copyup;
30503+ unsigned char si_wbr_create;
30504+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
30505+ struct au_wbr_create_operations *si_wbr_create_ops;
30506+
30507+ /* round robin */
30508+ atomic_t si_wbr_rr_next;
30509+
30510+ /* most free space */
30511+ struct au_wbr_mfs si_wbr_mfs;
30512+
076b876e
AM
30513+ /* File-based Hierarchical Storage Management */
30514+ struct au_fhsm si_fhsm;
30515+
1facf9fc 30516+ /* mount flags */
30517+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
30518+ unsigned int si_mntflags;
30519+
30520+ /* external inode number (bitmap and translation table) */
acd2b654
AM
30521+ loff_t si_ximaxent; /* max entries in a xino */
30522+
1facf9fc 30523+ struct file *si_xib;
30524+ struct mutex si_xib_mtx; /* protect xib members */
30525+ unsigned long *si_xib_buf;
30526+ unsigned long si_xib_last_pindex;
30527+ int si_xib_next_bit;
acd2b654 30528+
392086de
AM
30529+ unsigned long si_xino_jiffy;
30530+ unsigned long si_xino_expire;
1facf9fc 30531+ /* reserved for future use */
30532+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
30533+
30534+#ifdef CONFIG_AUFS_EXPORT
30535+ /* i_generation */
acd2b654 30536+ /* todo: make xigen file an array to support many inode numbers */
1facf9fc 30537+ struct file *si_xigen;
30538+ atomic_t si_xigen_next;
30539+#endif
30540+
acd2b654 30541+ /* dirty trick to support atomic_open */
8b6a4947 30542+ struct hlist_bl_head si_aopen;
b912730e 30543+
1facf9fc 30544+ /* vdir parameters */
e49829fe 30545+ unsigned long si_rdcache; /* max cache time in jiffies */
1facf9fc 30546+ unsigned int si_rdblk; /* deblk size */
30547+ unsigned int si_rdhash; /* hash size */
30548+
30549+ /*
30550+ * If the number of whiteouts are larger than si_dirwh, leave all of
30551+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
30552+ * future fsck.aufs or kernel thread will remove them later.
30553+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
30554+ */
30555+ unsigned int si_dirwh;
30556+
1facf9fc 30557+ /* pseudo_link list */
8b6a4947 30558+ struct hlist_bl_head si_plink[AuPlink_NHASH];
1facf9fc 30559+ wait_queue_head_t si_plink_wq;
4a4d8108 30560+ spinlock_t si_plink_maint_lock;
e49829fe 30561+ pid_t si_plink_maint_pid;
1facf9fc 30562+
523b37e3 30563+ /* file list */
8b6a4947 30564+ struct hlist_bl_head si_files;
523b37e3 30565+
b95c5147 30566+ /* with/without getattr, brother of sb->s_d_op */
43982f53 30567+ const struct inode_operations *si_iop_array;
b95c5147 30568+
1facf9fc 30569+ /*
30570+ * sysfs and lifetime management.
30571+ * this is not a small structure and it may be a waste of memory in case
acd2b654 30572+ * of sysfs is disabled, particularly when many aufs-es are mounted.
1facf9fc 30573+ * but using sysfs is majority.
30574+ */
30575+ struct kobject si_kobj;
30576+#ifdef CONFIG_DEBUG_FS
86dc4139
AM
30577+ struct dentry *si_dbgaufs;
30578+ struct dentry *si_dbgaufs_plink;
30579+ struct dentry *si_dbgaufs_xib;
1facf9fc 30580+#ifdef CONFIG_AUFS_EXPORT
30581+ struct dentry *si_dbgaufs_xigen;
30582+#endif
30583+#endif
30584+
e49829fe 30585+#ifdef CONFIG_AUFS_SBILIST
8b6a4947 30586+ struct hlist_bl_node si_list;
e49829fe
JR
30587+#endif
30588+
1facf9fc 30589+ /* dirty, necessary for unmounting, sysfs and sysrq */
30590+ struct super_block *si_sb;
30591+};
30592+
dece6358
AM
30593+/* sbinfo status flags */
30594+/*
30595+ * set true when refresh_dirs() failed at remount time.
30596+ * then try refreshing dirs at access time again.
062440b3 30597+ * if it is false, refreshing dirs at access time is unnecessary
dece6358 30598+ */
027c5e7a 30599+#define AuSi_FAILED_REFRESH_DIR 1
076b876e 30600+#define AuSi_FHSM (1 << 1) /* fhsm is active now */
79b8bda9 30601+#define AuSi_NO_DREVAL (1 << 2) /* disable all d_revalidate */
076b876e
AM
30602+
30603+#ifndef CONFIG_AUFS_FHSM
30604+#undef AuSi_FHSM
30605+#define AuSi_FHSM 0
30606+#endif
30607+
dece6358
AM
30608+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
30609+ unsigned int flag)
30610+{
30611+ AuRwMustAnyLock(&sbi->si_rwsem);
30612+ return sbi->au_si_status & flag;
30613+}
30614+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
30615+#define au_fset_si(sbinfo, name) do { \
30616+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
30617+ (sbinfo)->au_si_status |= AuSi_##name; \
30618+} while (0)
30619+#define au_fclr_si(sbinfo, name) do { \
30620+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
30621+ (sbinfo)->au_si_status &= ~AuSi_##name; \
30622+} while (0)
30623+
1facf9fc 30624+/* ---------------------------------------------------------------------- */
30625+
30626+/* policy to select one among writable branches */
4a4d8108
AM
30627+#define AuWbrCopyup(sbinfo, ...) \
30628+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
30629+#define AuWbrCreate(sbinfo, ...) \
30630+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
1facf9fc 30631+
30632+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
30633+#define AuLock_DW 1 /* write-lock dentry */
30634+#define AuLock_IR (1 << 1) /* read-lock inode */
30635+#define AuLock_IW (1 << 2) /* write-lock inode */
30636+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
b95c5147 30637+#define AuLock_DIRS (1 << 4) /* target is a pair of dirs */
f2c43d5f 30638+ /* except RENAME_EXCHANGE */
e49829fe
JR
30639+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */
30640+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */
027c5e7a 30641+#define AuLock_GEN (1 << 7) /* test digen/iigen */
1facf9fc 30642+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
7f207e10
AM
30643+#define au_fset_lock(flags, name) \
30644+ do { (flags) |= AuLock_##name; } while (0)
30645+#define au_fclr_lock(flags, name) \
30646+ do { (flags) &= ~AuLock_##name; } while (0)
1facf9fc 30647+
30648+/* ---------------------------------------------------------------------- */
30649+
30650+/* super.c */
30651+extern struct file_system_type aufs_fs_type;
30652+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
79b8bda9
AM
30653+typedef unsigned long long (*au_arraycb_t)(struct super_block *sb, void *array,
30654+ unsigned long long max, void *arg);
79b8bda9
AM
30655+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb,
30656+ struct super_block *sb, void *arg);
7f207e10
AM
30657+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max);
30658+void au_iarray_free(struct inode **a, unsigned long long max);
1facf9fc 30659+
30660+/* sbinfo.c */
30661+void au_si_free(struct kobject *kobj);
30662+int au_si_alloc(struct super_block *sb);
e2f27e51 30663+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink);
1facf9fc 30664+
30665+unsigned int au_sigen_inc(struct super_block *sb);
30666+aufs_bindex_t au_new_br_id(struct super_block *sb);
30667+
e49829fe
JR
30668+int si_read_lock(struct super_block *sb, int flags);
30669+int si_write_lock(struct super_block *sb, int flags);
30670+int aufs_read_lock(struct dentry *dentry, int flags);
1facf9fc 30671+void aufs_read_unlock(struct dentry *dentry, int flags);
30672+void aufs_write_lock(struct dentry *dentry);
30673+void aufs_write_unlock(struct dentry *dentry);
e49829fe 30674+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags);
1facf9fc 30675+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
30676+
30677+/* wbr_policy.c */
30678+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
30679+extern struct au_wbr_create_operations au_wbr_create_ops[];
30680+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
c2b27bf2 30681+int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex);
5afbbe0d 30682+int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop);
c2b27bf2
AM
30683+
30684+/* mvdown.c */
30685+int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *arg);
1facf9fc 30686+
076b876e
AM
30687+#ifdef CONFIG_AUFS_FHSM
30688+/* fhsm.c */
30689+
30690+static inline pid_t au_fhsm_pid(struct au_fhsm *fhsm)
30691+{
30692+ pid_t pid;
30693+
30694+ spin_lock(&fhsm->fhsm_spin);
30695+ pid = fhsm->fhsm_pid;
30696+ spin_unlock(&fhsm->fhsm_spin);
30697+
30698+ return pid;
30699+}
30700+
30701+void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force);
30702+void au_fhsm_wrote_all(struct super_block *sb, int force);
30703+int au_fhsm_fd(struct super_block *sb, int oflags);
30704+int au_fhsm_br_alloc(struct au_branch *br);
c1595e42 30705+void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex);
076b876e
AM
30706+void au_fhsm_fin(struct super_block *sb);
30707+void au_fhsm_init(struct au_sbinfo *sbinfo);
30708+void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec);
30709+void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo);
30710+#else
30711+AuStubVoid(au_fhsm_wrote, struct super_block *sb, aufs_bindex_t bindex,
30712+ int force)
30713+AuStubVoid(au_fhsm_wrote_all, struct super_block *sb, int force)
30714+AuStub(int, au_fhsm_fd, return -EOPNOTSUPP, struct super_block *sb, int oflags)
c1595e42
JR
30715+AuStub(pid_t, au_fhsm_pid, return 0, struct au_fhsm *fhsm)
30716+AuStubInt0(au_fhsm_br_alloc, struct au_branch *br)
30717+AuStubVoid(au_fhsm_set_bottom, struct super_block *sb, aufs_bindex_t bindex)
076b876e
AM
30718+AuStubVoid(au_fhsm_fin, struct super_block *sb)
30719+AuStubVoid(au_fhsm_init, struct au_sbinfo *sbinfo)
30720+AuStubVoid(au_fhsm_set, struct au_sbinfo *sbinfo, unsigned int sec)
30721+AuStubVoid(au_fhsm_show, struct seq_file *seq, struct au_sbinfo *sbinfo)
30722+#endif
30723+
1facf9fc 30724+/* ---------------------------------------------------------------------- */
30725+
30726+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
30727+{
30728+ return sb->s_fs_info;
30729+}
30730+
30731+/* ---------------------------------------------------------------------- */
30732+
30733+#ifdef CONFIG_AUFS_EXPORT
a2a7ad62 30734+int au_test_nfsd(void);
1facf9fc 30735+void au_export_init(struct super_block *sb);
b752ccd1 30736+void au_xigen_inc(struct inode *inode);
1facf9fc 30737+int au_xigen_new(struct inode *inode);
062440b3 30738+int au_xigen_set(struct super_block *sb, struct path *path);
1facf9fc 30739+void au_xigen_clr(struct super_block *sb);
30740+
30741+static inline int au_busy_or_stale(void)
30742+{
b752ccd1 30743+ if (!au_test_nfsd())
1facf9fc 30744+ return -EBUSY;
30745+ return -ESTALE;
30746+}
30747+#else
b752ccd1 30748+AuStubInt0(au_test_nfsd, void)
a2a7ad62 30749+AuStubVoid(au_export_init, struct super_block *sb)
b752ccd1 30750+AuStubVoid(au_xigen_inc, struct inode *inode)
4a4d8108 30751+AuStubInt0(au_xigen_new, struct inode *inode)
062440b3 30752+AuStubInt0(au_xigen_set, struct super_block *sb, struct path *path)
4a4d8108 30753+AuStubVoid(au_xigen_clr, struct super_block *sb)
c1595e42 30754+AuStub(int, au_busy_or_stale, return -EBUSY, void)
1facf9fc 30755+#endif /* CONFIG_AUFS_EXPORT */
30756+
30757+/* ---------------------------------------------------------------------- */
30758+
e49829fe
JR
30759+#ifdef CONFIG_AUFS_SBILIST
30760+/* module.c */
8b6a4947 30761+extern struct hlist_bl_head au_sbilist;
e49829fe
JR
30762+
30763+static inline void au_sbilist_init(void)
30764+{
8b6a4947 30765+ INIT_HLIST_BL_HEAD(&au_sbilist);
e49829fe
JR
30766+}
30767+
30768+static inline void au_sbilist_add(struct super_block *sb)
30769+{
8b6a4947 30770+ au_hbl_add(&au_sbi(sb)->si_list, &au_sbilist);
e49829fe
JR
30771+}
30772+
30773+static inline void au_sbilist_del(struct super_block *sb)
30774+{
8b6a4947 30775+ au_hbl_del(&au_sbi(sb)->si_list, &au_sbilist);
e49829fe 30776+}
53392da6
AM
30777+
30778+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
30779+static inline void au_sbilist_lock(void)
30780+{
8b6a4947 30781+ hlist_bl_lock(&au_sbilist);
53392da6
AM
30782+}
30783+
30784+static inline void au_sbilist_unlock(void)
30785+{
8b6a4947 30786+ hlist_bl_unlock(&au_sbilist);
53392da6
AM
30787+}
30788+#define AuGFP_SBILIST GFP_ATOMIC
30789+#else
30790+AuStubVoid(au_sbilist_lock, void)
30791+AuStubVoid(au_sbilist_unlock, void)
30792+#define AuGFP_SBILIST GFP_NOFS
30793+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
e49829fe
JR
30794+#else
30795+AuStubVoid(au_sbilist_init, void)
c1595e42
JR
30796+AuStubVoid(au_sbilist_add, struct super_block *sb)
30797+AuStubVoid(au_sbilist_del, struct super_block *sb)
53392da6
AM
30798+AuStubVoid(au_sbilist_lock, void)
30799+AuStubVoid(au_sbilist_unlock, void)
30800+#define AuGFP_SBILIST GFP_NOFS
e49829fe
JR
30801+#endif
30802+
30803+/* ---------------------------------------------------------------------- */
30804+
1facf9fc 30805+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
30806+{
dece6358 30807+ /*
c1595e42 30808+ * This function is a dynamic '__init' function actually,
dece6358
AM
30809+ * so the tiny check for si_rwsem is unnecessary.
30810+ */
30811+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 30812+#ifdef CONFIG_DEBUG_FS
30813+ sbinfo->si_dbgaufs = NULL;
86dc4139 30814+ sbinfo->si_dbgaufs_plink = NULL;
1facf9fc 30815+ sbinfo->si_dbgaufs_xib = NULL;
30816+#ifdef CONFIG_AUFS_EXPORT
30817+ sbinfo->si_dbgaufs_xigen = NULL;
30818+#endif
30819+#endif
30820+}
30821+
30822+/* ---------------------------------------------------------------------- */
30823+
a2654f78
AM
30824+/* current->atomic_flags */
30825+/* this value should never corrupt the ones defined in linux/sched.h */
fbc438ed 30826+#define PFA_AUFS 0x10
a2654f78
AM
30827+
30828+TASK_PFA_TEST(AUFS, test_aufs) /* task_test_aufs */
30829+TASK_PFA_SET(AUFS, aufs) /* task_set_aufs */
30830+TASK_PFA_CLEAR(AUFS, aufs) /* task_clear_aufs */
b752ccd1
AM
30831+
30832+static inline int si_pid_test(struct super_block *sb)
30833+{
a2654f78 30834+ return !!task_test_aufs(current);
b752ccd1
AM
30835+}
30836+
30837+static inline void si_pid_clr(struct super_block *sb)
30838+{
a2654f78
AM
30839+ AuDebugOn(!task_test_aufs(current));
30840+ task_clear_aufs(current);
b752ccd1
AM
30841+}
30842+
a2654f78
AM
30843+static inline void si_pid_set(struct super_block *sb)
30844+{
30845+ AuDebugOn(task_test_aufs(current));
30846+ task_set_aufs(current);
30847+}
febd17d6 30848+
b752ccd1
AM
30849+/* ---------------------------------------------------------------------- */
30850+
1facf9fc 30851+/* lock superblock. mainly for entry point functions */
8b6a4947
AM
30852+#define __si_read_lock(sb) au_rw_read_lock(&au_sbi(sb)->si_rwsem)
30853+#define __si_write_lock(sb) au_rw_write_lock(&au_sbi(sb)->si_rwsem)
30854+#define __si_read_trylock(sb) au_rw_read_trylock(&au_sbi(sb)->si_rwsem)
30855+#define __si_write_trylock(sb) au_rw_write_trylock(&au_sbi(sb)->si_rwsem)
30856+/*
30857+#define __si_read_trylock_nested(sb) \
30858+ au_rw_read_trylock_nested(&au_sbi(sb)->si_rwsem)
30859+#define __si_write_trylock_nested(sb) \
30860+ au_rw_write_trylock_nested(&au_sbi(sb)->si_rwsem)
30861+*/
30862+
30863+#define __si_read_unlock(sb) au_rw_read_unlock(&au_sbi(sb)->si_rwsem)
30864+#define __si_write_unlock(sb) au_rw_write_unlock(&au_sbi(sb)->si_rwsem)
30865+#define __si_downgrade_lock(sb) au_rw_dgrade_lock(&au_sbi(sb)->si_rwsem)
1facf9fc 30866+
dece6358
AM
30867+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
30868+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
30869+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
30870+
b752ccd1
AM
30871+static inline void si_noflush_read_lock(struct super_block *sb)
30872+{
30873+ __si_read_lock(sb);
30874+ si_pid_set(sb);
30875+}
30876+
30877+static inline int si_noflush_read_trylock(struct super_block *sb)
30878+{
076b876e
AM
30879+ int locked;
30880+
30881+ locked = __si_read_trylock(sb);
b752ccd1
AM
30882+ if (locked)
30883+ si_pid_set(sb);
30884+ return locked;
30885+}
30886+
30887+static inline void si_noflush_write_lock(struct super_block *sb)
30888+{
30889+ __si_write_lock(sb);
30890+ si_pid_set(sb);
30891+}
30892+
30893+static inline int si_noflush_write_trylock(struct super_block *sb)
30894+{
076b876e
AM
30895+ int locked;
30896+
30897+ locked = __si_write_trylock(sb);
b752ccd1
AM
30898+ if (locked)
30899+ si_pid_set(sb);
30900+ return locked;
30901+}
30902+
7e9cd9fe 30903+#if 0 /* reserved */
1facf9fc 30904+static inline int si_read_trylock(struct super_block *sb, int flags)
30905+{
30906+ if (au_ftest_lock(flags, FLUSH))
30907+ au_nwt_flush(&au_sbi(sb)->si_nowait);
30908+ return si_noflush_read_trylock(sb);
30909+}
e49829fe 30910+#endif
1facf9fc 30911+
b752ccd1
AM
30912+static inline void si_read_unlock(struct super_block *sb)
30913+{
30914+ si_pid_clr(sb);
30915+ __si_read_unlock(sb);
30916+}
30917+
7e9cd9fe 30918+#if 0 /* reserved */
1facf9fc 30919+static inline int si_write_trylock(struct super_block *sb, int flags)
30920+{
30921+ if (au_ftest_lock(flags, FLUSH))
30922+ au_nwt_flush(&au_sbi(sb)->si_nowait);
30923+ return si_noflush_write_trylock(sb);
30924+}
b752ccd1
AM
30925+#endif
30926+
30927+static inline void si_write_unlock(struct super_block *sb)
30928+{
30929+ si_pid_clr(sb);
30930+ __si_write_unlock(sb);
30931+}
30932+
7e9cd9fe 30933+#if 0 /* reserved */
b752ccd1
AM
30934+static inline void si_downgrade_lock(struct super_block *sb)
30935+{
30936+ __si_downgrade_lock(sb);
30937+}
30938+#endif
1facf9fc 30939+
30940+/* ---------------------------------------------------------------------- */
30941+
5afbbe0d 30942+static inline aufs_bindex_t au_sbbot(struct super_block *sb)
1facf9fc 30943+{
dece6358 30944+ SiMustAnyLock(sb);
5afbbe0d 30945+ return au_sbi(sb)->si_bbot;
1facf9fc 30946+}
30947+
30948+static inline unsigned int au_mntflags(struct super_block *sb)
30949+{
dece6358 30950+ SiMustAnyLock(sb);
1facf9fc 30951+ return au_sbi(sb)->si_mntflags;
30952+}
30953+
30954+static inline unsigned int au_sigen(struct super_block *sb)
30955+{
dece6358 30956+ SiMustAnyLock(sb);
1facf9fc 30957+ return au_sbi(sb)->si_generation;
30958+}
30959+
30960+static inline struct au_branch *au_sbr(struct super_block *sb,
30961+ aufs_bindex_t bindex)
30962+{
dece6358 30963+ SiMustAnyLock(sb);
1facf9fc 30964+ return au_sbi(sb)->si_branch[0 + bindex];
30965+}
30966+
acd2b654 30967+static inline loff_t au_xi_maxent(struct super_block *sb)
1facf9fc 30968+{
dece6358 30969+ SiMustAnyLock(sb);
acd2b654 30970+ return au_sbi(sb)->si_ximaxent;
1facf9fc 30971+}
30972+
30973+#endif /* __KERNEL__ */
30974+#endif /* __AUFS_SUPER_H__ */
7f207e10 30975diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
eca34b5c 30976--- /usr/share/empty/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
319657f6 30977+++ linux/fs/aufs/sysaufs.c 2021-12-03 15:38:59.939980643 +0100
062440b3 30978@@ -0,0 +1,93 @@
cd7a4cd9 30979+// SPDX-License-Identifier: GPL-2.0
1facf9fc 30980+/*
6d176551 30981+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 30982+ *
30983+ * This program, aufs is free software; you can redistribute it and/or modify
30984+ * it under the terms of the GNU General Public License as published by
30985+ * the Free Software Foundation; either version 2 of the License, or
30986+ * (at your option) any later version.
dece6358
AM
30987+ *
30988+ * This program is distributed in the hope that it will be useful,
30989+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
30990+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30991+ * GNU General Public License for more details.
30992+ *
30993+ * You should have received a copy of the GNU General Public License
523b37e3 30994+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 30995+ */
30996+
30997+/*
30998+ * sysfs interface and lifetime management
30999+ * they are necessary regardless sysfs is disabled.
31000+ */
31001+
1facf9fc 31002+#include <linux/random.h>
1facf9fc 31003+#include "aufs.h"
31004+
31005+unsigned long sysaufs_si_mask;
e49829fe 31006+struct kset *sysaufs_kset;
1facf9fc 31007+
31008+#define AuSiAttr(_name) { \
31009+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
31010+ .show = sysaufs_si_##_name, \
31011+}
31012+
31013+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
31014+struct attribute *sysaufs_si_attrs[] = {
31015+ &sysaufs_si_attr_xi_path.attr,
31016+ NULL,
31017+};
31018+
4a4d8108 31019+static const struct sysfs_ops au_sbi_ops = {
1facf9fc 31020+ .show = sysaufs_si_show
31021+};
31022+
31023+static struct kobj_type au_sbi_ktype = {
31024+ .release = au_si_free,
31025+ .sysfs_ops = &au_sbi_ops,
31026+ .default_attrs = sysaufs_si_attrs
31027+};
31028+
31029+/* ---------------------------------------------------------------------- */
31030+
31031+int sysaufs_si_init(struct au_sbinfo *sbinfo)
31032+{
31033+ int err;
31034+
e49829fe 31035+ sbinfo->si_kobj.kset = sysaufs_kset;
1facf9fc 31036+ /* cf. sysaufs_name() */
31037+ err = kobject_init_and_add
e49829fe 31038+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL,
1facf9fc 31039+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
31040+
1facf9fc 31041+ return err;
31042+}
31043+
31044+void sysaufs_fin(void)
31045+{
e49829fe
JR
31046+ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group);
31047+ kset_unregister(sysaufs_kset);
1facf9fc 31048+}
31049+
31050+int __init sysaufs_init(void)
31051+{
31052+ int err;
31053+
31054+ do {
31055+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
31056+ } while (!sysaufs_si_mask);
31057+
4a4d8108 31058+ err = -EINVAL;
e49829fe
JR
31059+ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
31060+ if (unlikely(!sysaufs_kset))
4a4d8108 31061+ goto out;
e49829fe
JR
31062+ err = PTR_ERR(sysaufs_kset);
31063+ if (IS_ERR(sysaufs_kset))
1facf9fc 31064+ goto out;
e49829fe 31065+ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group);
062440b3 31066+ if (unlikely(err))
e49829fe 31067+ kset_unregister(sysaufs_kset);
1facf9fc 31068+
4f0767ce 31069+out:
1facf9fc 31070+ return err;
31071+}
7f207e10 31072diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
eca34b5c 31073--- /usr/share/empty/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
319657f6 31074+++ linux/fs/aufs/sysaufs.h 2021-12-03 15:38:59.939980643 +0100
062440b3
AM
31075@@ -0,0 +1,102 @@
31076+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 31077+/*
6d176551 31078+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 31079+ *
31080+ * This program, aufs is free software; you can redistribute it and/or modify
31081+ * it under the terms of the GNU General Public License as published by
31082+ * the Free Software Foundation; either version 2 of the License, or
31083+ * (at your option) any later version.
dece6358
AM
31084+ *
31085+ * This program is distributed in the hope that it will be useful,
31086+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31087+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31088+ * GNU General Public License for more details.
31089+ *
31090+ * You should have received a copy of the GNU General Public License
523b37e3 31091+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31092+ */
31093+
31094+/*
31095+ * sysfs interface and mount lifetime management
31096+ */
31097+
31098+#ifndef __SYSAUFS_H__
31099+#define __SYSAUFS_H__
31100+
31101+#ifdef __KERNEL__
31102+
1facf9fc 31103+#include <linux/sysfs.h>
1facf9fc 31104+#include "module.h"
31105+
dece6358
AM
31106+struct super_block;
31107+struct au_sbinfo;
31108+
1facf9fc 31109+struct sysaufs_si_attr {
31110+ struct attribute attr;
31111+ int (*show)(struct seq_file *seq, struct super_block *sb);
31112+};
31113+
31114+/* ---------------------------------------------------------------------- */
31115+
31116+/* sysaufs.c */
31117+extern unsigned long sysaufs_si_mask;
e49829fe 31118+extern struct kset *sysaufs_kset;
1facf9fc 31119+extern struct attribute *sysaufs_si_attrs[];
31120+int sysaufs_si_init(struct au_sbinfo *sbinfo);
31121+int __init sysaufs_init(void);
31122+void sysaufs_fin(void);
31123+
31124+/* ---------------------------------------------------------------------- */
31125+
31126+/* some people doesn't like to show a pointer in kernel */
31127+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
31128+{
31129+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
31130+}
31131+
31132+#define SysaufsSiNamePrefix "si_"
31133+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
31134+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
31135+{
31136+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
31137+ sysaufs_si_id(sbinfo));
31138+}
31139+
31140+struct au_branch;
31141+#ifdef CONFIG_SYSFS
31142+/* sysfs.c */
31143+extern struct attribute_group *sysaufs_attr_group;
31144+
31145+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
31146+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
31147+ char *buf);
076b876e
AM
31148+long au_brinfo_ioctl(struct file *file, unsigned long arg);
31149+#ifdef CONFIG_COMPAT
31150+long au_brinfo_compat_ioctl(struct file *file, unsigned long arg);
31151+#endif
1facf9fc 31152+
31153+void sysaufs_br_init(struct au_branch *br);
31154+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
31155+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
31156+
31157+#define sysaufs_brs_init() do {} while (0)
31158+
31159+#else
31160+#define sysaufs_attr_group NULL
31161+
4a4d8108 31162+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
c1595e42
JR
31163+AuStub(ssize_t, sysaufs_si_show, return 0, struct kobject *kobj,
31164+ struct attribute *attr, char *buf)
4a4d8108
AM
31165+AuStubVoid(sysaufs_br_init, struct au_branch *br)
31166+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
31167+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
1facf9fc 31168+
31169+static inline void sysaufs_brs_init(void)
31170+{
31171+ sysaufs_brs = 0;
31172+}
31173+
31174+#endif /* CONFIG_SYSFS */
31175+
31176+#endif /* __KERNEL__ */
31177+#endif /* __SYSAUFS_H__ */
7f207e10 31178diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
eca34b5c 31179--- /usr/share/empty/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
319657f6 31180+++ linux/fs/aufs/sysfs.c 2021-12-03 15:38:59.939980643 +0100
ba1aed25 31181@@ -0,0 +1,374 @@
cd7a4cd9 31182+// SPDX-License-Identifier: GPL-2.0
1facf9fc 31183+/*
6d176551 31184+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 31185+ *
31186+ * This program, aufs is free software; you can redistribute it and/or modify
31187+ * it under the terms of the GNU General Public License as published by
31188+ * the Free Software Foundation; either version 2 of the License, or
31189+ * (at your option) any later version.
dece6358
AM
31190+ *
31191+ * This program is distributed in the hope that it will be useful,
31192+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31193+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31194+ * GNU General Public License for more details.
31195+ *
31196+ * You should have received a copy of the GNU General Public License
523b37e3 31197+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31198+ */
31199+
31200+/*
31201+ * sysfs interface
31202+ */
31203+
076b876e 31204+#include <linux/compat.h>
1facf9fc 31205+#include <linux/seq_file.h>
1facf9fc 31206+#include "aufs.h"
31207+
4a4d8108
AM
31208+#ifdef CONFIG_AUFS_FS_MODULE
31209+/* this entry violates the "one line per file" policy of sysfs */
31210+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
31211+ char *buf)
31212+{
31213+ ssize_t err;
31214+ static char *conf =
31215+/* this file is generated at compiling */
31216+#include "conf.str"
31217+ ;
31218+
31219+ err = snprintf(buf, PAGE_SIZE, conf);
31220+ if (unlikely(err >= PAGE_SIZE))
31221+ err = -EFBIG;
31222+ return err;
31223+}
31224+
31225+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
31226+#endif
31227+
1facf9fc 31228+static struct attribute *au_attr[] = {
4a4d8108
AM
31229+#ifdef CONFIG_AUFS_FS_MODULE
31230+ &au_config_attr.attr,
31231+#endif
1facf9fc 31232+ NULL, /* need to NULL terminate the list of attributes */
31233+};
31234+
31235+static struct attribute_group sysaufs_attr_group_body = {
31236+ .attrs = au_attr
31237+};
31238+
31239+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
31240+
31241+/* ---------------------------------------------------------------------- */
31242+
31243+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
31244+{
31245+ int err;
31246+
dece6358
AM
31247+ SiMustAnyLock(sb);
31248+
1facf9fc 31249+ err = 0;
31250+ if (au_opt_test(au_mntflags(sb), XINO)) {
31251+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
31252+ seq_putc(seq, '\n');
31253+ }
31254+ return err;
31255+}
31256+
31257+/*
31258+ * the lifetime of branch is independent from the entry under sysfs.
31259+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
31260+ * unlinked.
31261+ */
31262+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
392086de 31263+ aufs_bindex_t bindex, int idx)
1facf9fc 31264+{
1e00d052 31265+ int err;
1facf9fc 31266+ struct path path;
31267+ struct dentry *root;
31268+ struct au_branch *br;
076b876e 31269+ au_br_perm_str_t perm;
1facf9fc 31270+
31271+ AuDbg("b%d\n", bindex);
31272+
1e00d052 31273+ err = 0;
1facf9fc 31274+ root = sb->s_root;
31275+ di_read_lock_parent(root, !AuLock_IR);
31276+ br = au_sbr(sb, bindex);
392086de
AM
31277+
31278+ switch (idx) {
31279+ case AuBrSysfs_BR:
31280+ path.mnt = au_br_mnt(br);
31281+ path.dentry = au_h_dptr(root, bindex);
79b8bda9
AM
31282+ err = au_seq_path(seq, &path);
31283+ if (!err) {
31284+ au_optstr_br_perm(&perm, br->br_perm);
31285+ seq_printf(seq, "=%s\n", perm.a);
31286+ }
392086de
AM
31287+ break;
31288+ case AuBrSysfs_BRID:
79b8bda9 31289+ seq_printf(seq, "%d\n", br->br_id);
392086de
AM
31290+ break;
31291+ }
076b876e 31292+ di_read_unlock(root, !AuLock_IR);
79b8bda9 31293+ if (unlikely(err || seq_has_overflowed(seq)))
076b876e 31294+ err = -E2BIG;
392086de 31295+
1e00d052 31296+ return err;
1facf9fc 31297+}
31298+
31299+/* ---------------------------------------------------------------------- */
31300+
31301+static struct seq_file *au_seq(char *p, ssize_t len)
31302+{
31303+ struct seq_file *seq;
31304+
31305+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
31306+ if (seq) {
31307+ /* mutex_init(&seq.lock); */
31308+ seq->buf = p;
31309+ seq->size = len;
31310+ return seq; /* success */
31311+ }
31312+
31313+ seq = ERR_PTR(-ENOMEM);
31314+ return seq;
31315+}
31316+
392086de
AM
31317+#define SysaufsBr_PREFIX "br"
31318+#define SysaufsBrid_PREFIX "brid"
1facf9fc 31319+
31320+/* todo: file size may exceed PAGE_SIZE */
31321+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
1308ab2a 31322+ char *buf)
1facf9fc 31323+{
31324+ ssize_t err;
392086de 31325+ int idx;
1facf9fc 31326+ long l;
5afbbe0d 31327+ aufs_bindex_t bbot;
1facf9fc 31328+ struct au_sbinfo *sbinfo;
31329+ struct super_block *sb;
31330+ struct seq_file *seq;
31331+ char *name;
31332+ struct attribute **cattr;
31333+
31334+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
31335+ sb = sbinfo->si_sb;
1308ab2a 31336+
31337+ /*
31338+ * prevent a race condition between sysfs and aufs.
31339+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which
31340+ * prohibits maintaining the sysfs entries.
31341+ * hew we acquire read lock after sysfs_get_active_two().
31342+ * on the other hand, the remount process may maintain the sysfs/aufs
31343+ * entries after acquiring write lock.
31344+ * it can cause a deadlock.
31345+ * simply we gave up processing read here.
31346+ */
31347+ err = -EBUSY;
31348+ if (unlikely(!si_noflush_read_trylock(sb)))
31349+ goto out;
1facf9fc 31350+
31351+ seq = au_seq(buf, PAGE_SIZE);
31352+ err = PTR_ERR(seq);
31353+ if (IS_ERR(seq))
1308ab2a 31354+ goto out_unlock;
1facf9fc 31355+
31356+ name = (void *)attr->name;
31357+ cattr = sysaufs_si_attrs;
31358+ while (*cattr) {
31359+ if (!strcmp(name, (*cattr)->name)) {
31360+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
31361+ ->show(seq, sb);
31362+ goto out_seq;
31363+ }
31364+ cattr++;
31365+ }
31366+
392086de
AM
31367+ if (!strncmp(name, SysaufsBrid_PREFIX,
31368+ sizeof(SysaufsBrid_PREFIX) - 1)) {
31369+ idx = AuBrSysfs_BRID;
31370+ name += sizeof(SysaufsBrid_PREFIX) - 1;
31371+ } else if (!strncmp(name, SysaufsBr_PREFIX,
31372+ sizeof(SysaufsBr_PREFIX) - 1)) {
31373+ idx = AuBrSysfs_BR;
1facf9fc 31374+ name += sizeof(SysaufsBr_PREFIX) - 1;
392086de
AM
31375+ } else
31376+ BUG();
31377+
31378+ err = kstrtol(name, 10, &l);
31379+ if (!err) {
5afbbe0d
AM
31380+ bbot = au_sbbot(sb);
31381+ if (l <= bbot)
392086de
AM
31382+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l, idx);
31383+ else
31384+ err = -ENOENT;
1facf9fc 31385+ }
1facf9fc 31386+
4f0767ce 31387+out_seq:
1facf9fc 31388+ if (!err) {
31389+ err = seq->count;
31390+ /* sysfs limit */
31391+ if (unlikely(err == PAGE_SIZE))
31392+ err = -EFBIG;
31393+ }
9f237c51 31394+ au_kfree_rcu(seq);
4f0767ce 31395+out_unlock:
1facf9fc 31396+ si_read_unlock(sb);
4f0767ce 31397+out:
1facf9fc 31398+ return err;
31399+}
31400+
31401+/* ---------------------------------------------------------------------- */
31402+
076b876e
AM
31403+static int au_brinfo(struct super_block *sb, union aufs_brinfo __user *arg)
31404+{
31405+ int err;
31406+ int16_t brid;
5afbbe0d 31407+ aufs_bindex_t bindex, bbot;
076b876e
AM
31408+ size_t sz;
31409+ char *buf;
31410+ struct seq_file *seq;
31411+ struct au_branch *br;
31412+
31413+ si_read_lock(sb, AuLock_FLUSH);
5afbbe0d
AM
31414+ bbot = au_sbbot(sb);
31415+ err = bbot + 1;
076b876e
AM
31416+ if (!arg)
31417+ goto out;
31418+
31419+ err = -ENOMEM;
31420+ buf = (void *)__get_free_page(GFP_NOFS);
31421+ if (unlikely(!buf))
31422+ goto out;
31423+
31424+ seq = au_seq(buf, PAGE_SIZE);
31425+ err = PTR_ERR(seq);
31426+ if (IS_ERR(seq))
31427+ goto out_buf;
31428+
31429+ sz = sizeof(*arg) - offsetof(union aufs_brinfo, path);
5afbbe0d 31430+ for (bindex = 0; bindex <= bbot; bindex++, arg++) {
ba1aed25
AM
31431+ /* VERIFY_WRITE */
31432+ err = !access_ok(arg, sizeof(*arg));
076b876e
AM
31433+ if (unlikely(err))
31434+ break;
31435+
31436+ br = au_sbr(sb, bindex);
31437+ brid = br->br_id;
31438+ BUILD_BUG_ON(sizeof(brid) != sizeof(arg->id));
31439+ err = __put_user(brid, &arg->id);
31440+ if (unlikely(err))
31441+ break;
31442+
31443+ BUILD_BUG_ON(sizeof(br->br_perm) != sizeof(arg->perm));
31444+ err = __put_user(br->br_perm, &arg->perm);
31445+ if (unlikely(err))
31446+ break;
31447+
79b8bda9
AM
31448+ err = au_seq_path(seq, &br->br_path);
31449+ if (unlikely(err))
31450+ break;
31451+ seq_putc(seq, '\0');
31452+ if (!seq_has_overflowed(seq)) {
076b876e
AM
31453+ err = copy_to_user(arg->path, seq->buf, seq->count);
31454+ seq->count = 0;
31455+ if (unlikely(err))
31456+ break;
31457+ } else {
31458+ err = -E2BIG;
31459+ goto out_seq;
31460+ }
31461+ }
31462+ if (unlikely(err))
31463+ err = -EFAULT;
31464+
31465+out_seq:
9f237c51 31466+ au_kfree_rcu(seq);
076b876e 31467+out_buf:
1c60b727 31468+ free_page((unsigned long)buf);
076b876e
AM
31469+out:
31470+ si_read_unlock(sb);
31471+ return err;
31472+}
31473+
31474+long au_brinfo_ioctl(struct file *file, unsigned long arg)
31475+{
2000de60 31476+ return au_brinfo(file->f_path.dentry->d_sb, (void __user *)arg);
076b876e
AM
31477+}
31478+
31479+#ifdef CONFIG_COMPAT
31480+long au_brinfo_compat_ioctl(struct file *file, unsigned long arg)
31481+{
2000de60 31482+ return au_brinfo(file->f_path.dentry->d_sb, compat_ptr(arg));
076b876e
AM
31483+}
31484+#endif
31485+
31486+/* ---------------------------------------------------------------------- */
31487+
1facf9fc 31488+void sysaufs_br_init(struct au_branch *br)
31489+{
392086de
AM
31490+ int i;
31491+ struct au_brsysfs *br_sysfs;
31492+ struct attribute *attr;
4a4d8108 31493+
392086de
AM
31494+ br_sysfs = br->br_sysfs;
31495+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
31496+ attr = &br_sysfs->attr;
31497+ sysfs_attr_init(attr);
31498+ attr->name = br_sysfs->name;
cd7a4cd9 31499+ attr->mode = 0444;
392086de
AM
31500+ br_sysfs++;
31501+ }
1facf9fc 31502+}
31503+
31504+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
31505+{
31506+ struct au_branch *br;
31507+ struct kobject *kobj;
392086de
AM
31508+ struct au_brsysfs *br_sysfs;
31509+ int i;
5afbbe0d 31510+ aufs_bindex_t bbot;
1facf9fc 31511+
1facf9fc 31512+ if (!sysaufs_brs)
31513+ return;
31514+
31515+ kobj = &au_sbi(sb)->si_kobj;
5afbbe0d
AM
31516+ bbot = au_sbbot(sb);
31517+ for (; bindex <= bbot; bindex++) {
1facf9fc 31518+ br = au_sbr(sb, bindex);
392086de
AM
31519+ br_sysfs = br->br_sysfs;
31520+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
31521+ sysfs_remove_file(kobj, &br_sysfs->attr);
31522+ br_sysfs++;
31523+ }
1facf9fc 31524+ }
31525+}
31526+
31527+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
31528+{
392086de 31529+ int err, i;
5afbbe0d 31530+ aufs_bindex_t bbot;
1facf9fc 31531+ struct kobject *kobj;
31532+ struct au_branch *br;
392086de 31533+ struct au_brsysfs *br_sysfs;
1facf9fc 31534+
1facf9fc 31535+ if (!sysaufs_brs)
31536+ return;
31537+
31538+ kobj = &au_sbi(sb)->si_kobj;
5afbbe0d
AM
31539+ bbot = au_sbbot(sb);
31540+ for (; bindex <= bbot; bindex++) {
1facf9fc 31541+ br = au_sbr(sb, bindex);
392086de
AM
31542+ br_sysfs = br->br_sysfs;
31543+ snprintf(br_sysfs[AuBrSysfs_BR].name, sizeof(br_sysfs->name),
31544+ SysaufsBr_PREFIX "%d", bindex);
31545+ snprintf(br_sysfs[AuBrSysfs_BRID].name, sizeof(br_sysfs->name),
31546+ SysaufsBrid_PREFIX "%d", bindex);
31547+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
31548+ err = sysfs_create_file(kobj, &br_sysfs->attr);
31549+ if (unlikely(err))
31550+ pr_warn("failed %s under sysfs(%d)\n",
31551+ br_sysfs->name, err);
31552+ br_sysfs++;
31553+ }
1facf9fc 31554+ }
31555+}
7f207e10 31556diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
eca34b5c 31557--- /usr/share/empty/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
319657f6 31558+++ linux/fs/aufs/sysrq.c 2021-12-03 15:38:59.939980643 +0100
43982f53 31559@@ -0,0 +1,149 @@
cd7a4cd9 31560+// SPDX-License-Identifier: GPL-2.0
1facf9fc 31561+/*
6d176551 31562+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 31563+ *
31564+ * This program, aufs is free software; you can redistribute it and/or modify
31565+ * it under the terms of the GNU General Public License as published by
31566+ * the Free Software Foundation; either version 2 of the License, or
31567+ * (at your option) any later version.
dece6358
AM
31568+ *
31569+ * This program is distributed in the hope that it will be useful,
31570+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31571+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31572+ * GNU General Public License for more details.
31573+ *
31574+ * You should have received a copy of the GNU General Public License
523b37e3 31575+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31576+ */
31577+
31578+/*
acd2b654 31579+ * magic sysrq handler
1facf9fc 31580+ */
31581+
1facf9fc 31582+/* #include <linux/sysrq.h> */
027c5e7a 31583+#include <linux/writeback.h>
1facf9fc 31584+#include "aufs.h"
31585+
31586+/* ---------------------------------------------------------------------- */
31587+
31588+static void sysrq_sb(struct super_block *sb)
31589+{
31590+ char *plevel;
31591+ struct au_sbinfo *sbinfo;
31592+ struct file *file;
8b6a4947
AM
31593+ struct hlist_bl_head *files;
31594+ struct hlist_bl_node *pos;
523b37e3 31595+ struct au_finfo *finfo;
43982f53 31596+ struct inode *i;
1facf9fc 31597+
31598+ plevel = au_plevel;
31599+ au_plevel = KERN_WARNING;
1facf9fc 31600+
4a4d8108 31601+ /* since we define pr_fmt, call printk directly */
c06a8ce3
AM
31602+#define pr(str) printk(KERN_WARNING AUFS_NAME ": " str)
31603+
31604+ sbinfo = au_sbi(sb);
4a4d8108 31605+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
c06a8ce3 31606+ pr("superblock\n");
1facf9fc 31607+ au_dpri_sb(sb);
027c5e7a 31608+
43982f53 31609+#if 0 /* reserved */
027c5e7a
AM
31610+ do {
31611+ int err, i, j, ndentry;
31612+ struct au_dcsub_pages dpages;
31613+ struct au_dpage *dpage;
31614+
31615+ err = au_dpages_init(&dpages, GFP_ATOMIC);
31616+ if (unlikely(err))
31617+ break;
31618+ err = au_dcsub_pages(&dpages, sb->s_root, NULL, NULL);
31619+ if (!err)
31620+ for (i = 0; i < dpages.ndpage; i++) {
31621+ dpage = dpages.dpages + i;
31622+ ndentry = dpage->ndentry;
31623+ for (j = 0; j < ndentry; j++)
31624+ au_dpri_dentry(dpage->dentries[j]);
31625+ }
31626+ au_dpages_free(&dpages);
31627+ } while (0);
31628+#endif
31629+
43982f53
AM
31630+ pr("isolated inode\n");
31631+ spin_lock(&sb->s_inode_list_lock);
31632+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
31633+ spin_lock(&i->i_lock);
31634+ if (hlist_empty(&i->i_dentry))
31635+ au_dpri_inode(i);
31636+ spin_unlock(&i->i_lock);
027c5e7a 31637+ }
43982f53
AM
31638+ spin_unlock(&sb->s_inode_list_lock);
31639+
c06a8ce3 31640+ pr("files\n");
523b37e3 31641+ files = &au_sbi(sb)->si_files;
8b6a4947
AM
31642+ hlist_bl_lock(files);
31643+ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) {
4a4d8108 31644+ umode_t mode;
076b876e 31645+
523b37e3 31646+ file = finfo->fi_file;
c06a8ce3 31647+ mode = file_inode(file)->i_mode;
38d290e6 31648+ if (!special_file(mode))
1facf9fc 31649+ au_dpri_file(file);
523b37e3 31650+ }
8b6a4947 31651+ hlist_bl_unlock(files);
c06a8ce3 31652+ pr("done\n");
1facf9fc 31653+
c06a8ce3 31654+#undef pr
1facf9fc 31655+ au_plevel = plevel;
1facf9fc 31656+}
31657+
31658+/* ---------------------------------------------------------------------- */
31659+
31660+/* module parameter */
31661+static char *aufs_sysrq_key = "a";
cd7a4cd9 31662+module_param_named(sysrq, aufs_sysrq_key, charp, 0444);
1facf9fc 31663+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
31664+
0c5527e5 31665+static void au_sysrq(int key __maybe_unused)
1facf9fc 31666+{
1facf9fc 31667+ struct au_sbinfo *sbinfo;
8b6a4947 31668+ struct hlist_bl_node *pos;
1facf9fc 31669+
027c5e7a 31670+ lockdep_off();
53392da6 31671+ au_sbilist_lock();
8b6a4947 31672+ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list)
1facf9fc 31673+ sysrq_sb(sbinfo->si_sb);
53392da6 31674+ au_sbilist_unlock();
027c5e7a 31675+ lockdep_on();
1facf9fc 31676+}
31677+
31678+static struct sysrq_key_op au_sysrq_op = {
31679+ .handler = au_sysrq,
31680+ .help_msg = "Aufs",
31681+ .action_msg = "Aufs",
31682+ .enable_mask = SYSRQ_ENABLE_DUMP
31683+};
31684+
31685+/* ---------------------------------------------------------------------- */
31686+
31687+int __init au_sysrq_init(void)
31688+{
31689+ int err;
31690+ char key;
31691+
31692+ err = -1;
31693+ key = *aufs_sysrq_key;
31694+ if ('a' <= key && key <= 'z')
31695+ err = register_sysrq_key(key, &au_sysrq_op);
31696+ if (unlikely(err))
4a4d8108 31697+ pr_err("err %d, sysrq=%c\n", err, key);
1facf9fc 31698+ return err;
31699+}
31700+
31701+void au_sysrq_fin(void)
31702+{
31703+ int err;
076b876e 31704+
1facf9fc 31705+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
31706+ if (unlikely(err))
4a4d8108 31707+ pr_err("err %d (ignored)\n", err);
1facf9fc 31708+}
7f207e10 31709diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
eca34b5c 31710--- /usr/share/empty/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
319657f6 31711+++ linux/fs/aufs/vdir.c 2021-12-03 15:38:59.939980643 +0100
eca801bf 31712@@ -0,0 +1,896 @@
cd7a4cd9 31713+// SPDX-License-Identifier: GPL-2.0
1facf9fc 31714+/*
6d176551 31715+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 31716+ *
31717+ * This program, aufs is free software; you can redistribute it and/or modify
31718+ * it under the terms of the GNU General Public License as published by
31719+ * the Free Software Foundation; either version 2 of the License, or
31720+ * (at your option) any later version.
dece6358
AM
31721+ *
31722+ * This program is distributed in the hope that it will be useful,
31723+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31724+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31725+ * GNU General Public License for more details.
31726+ *
31727+ * You should have received a copy of the GNU General Public License
523b37e3 31728+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31729+ */
31730+
31731+/*
31732+ * virtual or vertical directory
31733+ */
31734+
eca801bf 31735+#include <linux/iversion.h>
1facf9fc 31736+#include "aufs.h"
31737+
dece6358 31738+static unsigned int calc_size(int nlen)
1facf9fc 31739+{
dece6358 31740+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 31741+}
31742+
31743+static int set_deblk_end(union au_vdir_deblk_p *p,
31744+ union au_vdir_deblk_p *deblk_end)
31745+{
31746+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
31747+ p->de->de_str.len = 0;
31748+ /* smp_mb(); */
31749+ return 0;
31750+ }
31751+ return -1; /* error */
31752+}
31753+
31754+/* returns true or false */
31755+static int is_deblk_end(union au_vdir_deblk_p *p,
31756+ union au_vdir_deblk_p *deblk_end)
31757+{
31758+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
31759+ return !p->de->de_str.len;
31760+ return 1;
31761+}
31762+
31763+static unsigned char *last_deblk(struct au_vdir *vdir)
31764+{
31765+ return vdir->vd_deblk[vdir->vd_nblk - 1];
31766+}
31767+
31768+/* ---------------------------------------------------------------------- */
31769+
79b8bda9 31770+/* estimate the appropriate size for name hash table */
1308ab2a 31771+unsigned int au_rdhash_est(loff_t sz)
31772+{
31773+ unsigned int n;
31774+
31775+ n = UINT_MAX;
31776+ sz >>= 10;
31777+ if (sz < n)
31778+ n = sz;
31779+ if (sz < AUFS_RDHASH_DEF)
31780+ n = AUFS_RDHASH_DEF;
4a4d8108 31781+ /* pr_info("n %u\n", n); */
1308ab2a 31782+ return n;
31783+}
31784+
1facf9fc 31785+/*
31786+ * the allocated memory has to be freed by
dece6358 31787+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 31788+ */
dece6358 31789+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 31790+{
1facf9fc 31791+ struct hlist_head *head;
dece6358 31792+ unsigned int u;
076b876e 31793+ size_t sz;
1facf9fc 31794+
076b876e
AM
31795+ sz = sizeof(*nhash->nh_head) * num_hash;
31796+ head = kmalloc(sz, gfp);
dece6358
AM
31797+ if (head) {
31798+ nhash->nh_num = num_hash;
31799+ nhash->nh_head = head;
31800+ for (u = 0; u < num_hash; u++)
1facf9fc 31801+ INIT_HLIST_HEAD(head++);
dece6358 31802+ return 0; /* success */
1facf9fc 31803+ }
1facf9fc 31804+
dece6358 31805+ return -ENOMEM;
1facf9fc 31806+}
31807+
dece6358
AM
31808+static void nhash_count(struct hlist_head *head)
31809+{
43982f53 31810+#if 0 /* debugging */
dece6358
AM
31811+ unsigned long n;
31812+ struct hlist_node *pos;
31813+
31814+ n = 0;
31815+ hlist_for_each(pos, head)
31816+ n++;
4a4d8108 31817+ pr_info("%lu\n", n);
dece6358
AM
31818+#endif
31819+}
31820+
31821+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 31822+{
c06a8ce3
AM
31823+ struct au_vdir_wh *pos;
31824+ struct hlist_node *node;
1facf9fc 31825+
c06a8ce3 31826+ hlist_for_each_entry_safe(pos, node, head, wh_hash)
9f237c51 31827+ au_kfree_rcu(pos);
1facf9fc 31828+}
31829+
dece6358 31830+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 31831+{
c06a8ce3
AM
31832+ struct au_vdir_dehstr *pos;
31833+ struct hlist_node *node;
1facf9fc 31834+
c06a8ce3 31835+ hlist_for_each_entry_safe(pos, node, head, hash)
1c60b727 31836+ au_cache_free_vdir_dehstr(pos);
1facf9fc 31837+}
31838+
dece6358
AM
31839+static void au_nhash_do_free(struct au_nhash *nhash,
31840+ void (*free)(struct hlist_head *head))
1facf9fc 31841+{
1308ab2a 31842+ unsigned int n;
1facf9fc 31843+ struct hlist_head *head;
1facf9fc 31844+
dece6358 31845+ n = nhash->nh_num;
1308ab2a 31846+ if (!n)
31847+ return;
31848+
dece6358 31849+ head = nhash->nh_head;
1308ab2a 31850+ while (n-- > 0) {
dece6358
AM
31851+ nhash_count(head);
31852+ free(head++);
1facf9fc 31853+ }
9f237c51 31854+ au_kfree_try_rcu(nhash->nh_head);
1facf9fc 31855+}
31856+
dece6358 31857+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 31858+{
dece6358
AM
31859+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
31860+}
1facf9fc 31861+
dece6358
AM
31862+static void au_nhash_de_free(struct au_nhash *delist)
31863+{
31864+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 31865+}
31866+
31867+/* ---------------------------------------------------------------------- */
31868+
31869+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
31870+ int limit)
31871+{
31872+ int num;
31873+ unsigned int u, n;
31874+ struct hlist_head *head;
c06a8ce3 31875+ struct au_vdir_wh *pos;
1facf9fc 31876+
31877+ num = 0;
31878+ n = whlist->nh_num;
31879+ head = whlist->nh_head;
1308ab2a 31880+ for (u = 0; u < n; u++, head++)
c06a8ce3
AM
31881+ hlist_for_each_entry(pos, head, wh_hash)
31882+ if (pos->wh_bindex == btgt && ++num > limit)
1facf9fc 31883+ return 1;
1facf9fc 31884+ return 0;
31885+}
31886+
31887+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 31888+ unsigned char *name,
1facf9fc 31889+ unsigned int len)
31890+{
dece6358
AM
31891+ unsigned int v;
31892+ /* const unsigned int magic_bit = 12; */
31893+
1308ab2a 31894+ AuDebugOn(!nhash->nh_num || !nhash->nh_head);
31895+
dece6358 31896+ v = 0;
f0c0a007
AM
31897+ if (len > 8)
31898+ len = 8;
dece6358
AM
31899+ while (len--)
31900+ v += *name++;
31901+ /* v = hash_long(v, magic_bit); */
31902+ v %= nhash->nh_num;
31903+ return nhash->nh_head + v;
31904+}
31905+
31906+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
31907+ int nlen)
31908+{
31909+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 31910+}
31911+
31912+/* returns found or not */
dece6358 31913+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 31914+{
31915+ struct hlist_head *head;
c06a8ce3 31916+ struct au_vdir_wh *pos;
1facf9fc 31917+ struct au_vdir_destr *str;
31918+
dece6358 31919+ head = au_name_hash(whlist, name, nlen);
c06a8ce3
AM
31920+ hlist_for_each_entry(pos, head, wh_hash) {
31921+ str = &pos->wh_str;
1facf9fc 31922+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
31923+ if (au_nhash_test_name(str, name, nlen))
31924+ return 1;
31925+ }
31926+ return 0;
31927+}
31928+
31929+/* returns found(true) or not */
31930+static int test_known(struct au_nhash *delist, char *name, int nlen)
31931+{
31932+ struct hlist_head *head;
c06a8ce3 31933+ struct au_vdir_dehstr *pos;
dece6358
AM
31934+ struct au_vdir_destr *str;
31935+
31936+ head = au_name_hash(delist, name, nlen);
c06a8ce3
AM
31937+ hlist_for_each_entry(pos, head, hash) {
31938+ str = pos->str;
dece6358
AM
31939+ AuDbg("%.*s\n", str->len, str->name);
31940+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 31941+ return 1;
31942+ }
31943+ return 0;
31944+}
31945+
dece6358
AM
31946+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
31947+ unsigned char d_type)
31948+{
31949+#ifdef CONFIG_AUFS_SHWH
31950+ wh->wh_ino = ino;
31951+ wh->wh_type = d_type;
31952+#endif
31953+}
31954+
31955+/* ---------------------------------------------------------------------- */
31956+
31957+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
31958+ unsigned int d_type, aufs_bindex_t bindex,
31959+ unsigned char shwh)
1facf9fc 31960+{
31961+ int err;
31962+ struct au_vdir_destr *str;
31963+ struct au_vdir_wh *wh;
31964+
dece6358 31965+ AuDbg("%.*s\n", nlen, name);
1308ab2a 31966+ AuDebugOn(!whlist->nh_num || !whlist->nh_head);
31967+
1facf9fc 31968+ err = -ENOMEM;
dece6358 31969+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 31970+ if (unlikely(!wh))
31971+ goto out;
31972+
31973+ err = 0;
31974+ wh->wh_bindex = bindex;
dece6358
AM
31975+ if (shwh)
31976+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 31977+ str = &wh->wh_str;
dece6358
AM
31978+ str->len = nlen;
31979+ memcpy(str->name, name, nlen);
31980+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 31981+ /* smp_mb(); */
31982+
4f0767ce 31983+out:
1facf9fc 31984+ return err;
31985+}
31986+
1facf9fc 31987+static int append_deblk(struct au_vdir *vdir)
31988+{
31989+ int err;
dece6358 31990+ unsigned long ul;
1facf9fc 31991+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
31992+ union au_vdir_deblk_p p, deblk_end;
31993+ unsigned char **o;
31994+
31995+ err = -ENOMEM;
e2f27e51
AM
31996+ o = au_krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
31997+ GFP_NOFS, /*may_shrink*/0);
1facf9fc 31998+ if (unlikely(!o))
31999+ goto out;
32000+
32001+ vdir->vd_deblk = o;
32002+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
32003+ if (p.deblk) {
32004+ ul = vdir->vd_nblk++;
32005+ vdir->vd_deblk[ul] = p.deblk;
32006+ vdir->vd_last.ul = ul;
32007+ vdir->vd_last.p.deblk = p.deblk;
32008+ deblk_end.deblk = p.deblk + deblk_sz;
32009+ err = set_deblk_end(&p, &deblk_end);
32010+ }
32011+
4f0767ce 32012+out:
1facf9fc 32013+ return err;
32014+}
32015+
dece6358
AM
32016+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
32017+ unsigned int d_type, struct au_nhash *delist)
32018+{
32019+ int err;
32020+ unsigned int sz;
32021+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
32022+ union au_vdir_deblk_p p, *room, deblk_end;
32023+ struct au_vdir_dehstr *dehstr;
32024+
32025+ p.deblk = last_deblk(vdir);
32026+ deblk_end.deblk = p.deblk + deblk_sz;
32027+ room = &vdir->vd_last.p;
32028+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
32029+ || !is_deblk_end(room, &deblk_end));
32030+
32031+ sz = calc_size(nlen);
32032+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
32033+ err = append_deblk(vdir);
32034+ if (unlikely(err))
32035+ goto out;
32036+
32037+ p.deblk = last_deblk(vdir);
32038+ deblk_end.deblk = p.deblk + deblk_sz;
32039+ /* smp_mb(); */
32040+ AuDebugOn(room->deblk != p.deblk);
32041+ }
32042+
32043+ err = -ENOMEM;
4a4d8108 32044+ dehstr = au_cache_alloc_vdir_dehstr();
dece6358
AM
32045+ if (unlikely(!dehstr))
32046+ goto out;
32047+
32048+ dehstr->str = &room->de->de_str;
32049+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
32050+ room->de->de_ino = ino;
32051+ room->de->de_type = d_type;
32052+ room->de->de_str.len = nlen;
32053+ memcpy(room->de->de_str.name, name, nlen);
32054+
32055+ err = 0;
32056+ room->deblk += sz;
32057+ if (unlikely(set_deblk_end(room, &deblk_end)))
32058+ err = append_deblk(vdir);
32059+ /* smp_mb(); */
32060+
4f0767ce 32061+out:
dece6358
AM
32062+ return err;
32063+}
32064+
32065+/* ---------------------------------------------------------------------- */
32066+
1c60b727 32067+void au_vdir_free(struct au_vdir *vdir)
dece6358
AM
32068+{
32069+ unsigned char **deblk;
32070+
32071+ deblk = vdir->vd_deblk;
1c60b727 32072+ while (vdir->vd_nblk--)
9f237c51
AM
32073+ au_kfree_try_rcu(*deblk++);
32074+ au_kfree_try_rcu(vdir->vd_deblk);
1c60b727 32075+ au_cache_free_vdir(vdir);
dece6358
AM
32076+}
32077+
1308ab2a 32078+static struct au_vdir *alloc_vdir(struct file *file)
1facf9fc 32079+{
32080+ struct au_vdir *vdir;
1308ab2a 32081+ struct super_block *sb;
1facf9fc 32082+ int err;
32083+
2000de60 32084+ sb = file->f_path.dentry->d_sb;
dece6358
AM
32085+ SiMustAnyLock(sb);
32086+
1facf9fc 32087+ err = -ENOMEM;
32088+ vdir = au_cache_alloc_vdir();
32089+ if (unlikely(!vdir))
32090+ goto out;
32091+
32092+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
32093+ if (unlikely(!vdir->vd_deblk))
32094+ goto out_free;
32095+
32096+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
1308ab2a 32097+ if (!vdir->vd_deblk_sz) {
79b8bda9 32098+ /* estimate the appropriate size for deblk */
1308ab2a 32099+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
4a4d8108 32100+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
1308ab2a 32101+ }
1facf9fc 32102+ vdir->vd_nblk = 0;
32103+ vdir->vd_version = 0;
32104+ vdir->vd_jiffy = 0;
32105+ err = append_deblk(vdir);
32106+ if (!err)
32107+ return vdir; /* success */
32108+
9f237c51 32109+ au_kfree_try_rcu(vdir->vd_deblk);
1facf9fc 32110+
4f0767ce 32111+out_free:
1c60b727 32112+ au_cache_free_vdir(vdir);
4f0767ce 32113+out:
1facf9fc 32114+ vdir = ERR_PTR(err);
32115+ return vdir;
32116+}
32117+
32118+static int reinit_vdir(struct au_vdir *vdir)
32119+{
32120+ int err;
32121+ union au_vdir_deblk_p p, deblk_end;
32122+
32123+ while (vdir->vd_nblk > 1) {
9f237c51 32124+ au_kfree_try_rcu(vdir->vd_deblk[vdir->vd_nblk - 1]);
1facf9fc 32125+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
32126+ vdir->vd_nblk--;
32127+ }
32128+ p.deblk = vdir->vd_deblk[0];
32129+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
32130+ err = set_deblk_end(&p, &deblk_end);
32131+ /* keep vd_dblk_sz */
32132+ vdir->vd_last.ul = 0;
32133+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
32134+ vdir->vd_version = 0;
32135+ vdir->vd_jiffy = 0;
32136+ /* smp_mb(); */
32137+ return err;
32138+}
32139+
32140+/* ---------------------------------------------------------------------- */
32141+
1facf9fc 32142+#define AuFillVdir_CALLED 1
32143+#define AuFillVdir_WHABLE (1 << 1)
dece6358 32144+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 32145+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
7f207e10
AM
32146+#define au_fset_fillvdir(flags, name) \
32147+ do { (flags) |= AuFillVdir_##name; } while (0)
32148+#define au_fclr_fillvdir(flags, name) \
32149+ do { (flags) &= ~AuFillVdir_##name; } while (0)
1facf9fc 32150+
dece6358
AM
32151+#ifndef CONFIG_AUFS_SHWH
32152+#undef AuFillVdir_SHWH
32153+#define AuFillVdir_SHWH 0
32154+#endif
32155+
1facf9fc 32156+struct fillvdir_arg {
392086de 32157+ struct dir_context ctx;
1facf9fc 32158+ struct file *file;
32159+ struct au_vdir *vdir;
dece6358
AM
32160+ struct au_nhash delist;
32161+ struct au_nhash whlist;
1facf9fc 32162+ aufs_bindex_t bindex;
32163+ unsigned int flags;
32164+ int err;
32165+};
32166+
392086de 32167+static int fillvdir(struct dir_context *ctx, const char *__name, int nlen,
1facf9fc 32168+ loff_t offset __maybe_unused, u64 h_ino,
32169+ unsigned int d_type)
32170+{
392086de 32171+ struct fillvdir_arg *arg = container_of(ctx, struct fillvdir_arg, ctx);
1facf9fc 32172+ char *name = (void *)__name;
32173+ struct super_block *sb;
1facf9fc 32174+ ino_t ino;
dece6358 32175+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 32176+
1facf9fc 32177+ arg->err = 0;
2000de60 32178+ sb = arg->file->f_path.dentry->d_sb;
1facf9fc 32179+ au_fset_fillvdir(arg->flags, CALLED);
32180+ /* smp_mb(); */
dece6358 32181+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 32182+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
32183+ if (test_known(&arg->delist, name, nlen)
32184+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
32185+ goto out; /* already exists or whiteouted */
1facf9fc 32186+
dece6358 32187+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
4a4d8108
AM
32188+ if (!arg->err) {
32189+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
32190+ d_type = DT_UNKNOWN;
dece6358
AM
32191+ arg->err = append_de(arg->vdir, name, nlen, ino,
32192+ d_type, &arg->delist);
4a4d8108 32193+ }
1facf9fc 32194+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
32195+ name += AUFS_WH_PFX_LEN;
dece6358
AM
32196+ nlen -= AUFS_WH_PFX_LEN;
32197+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
32198+ goto out; /* already whiteouted */
1facf9fc 32199+
acd2b654 32200+ ino = 0; /* just to suppress a warning */
dece6358
AM
32201+ if (shwh)
32202+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
32203+ &ino);
4a4d8108
AM
32204+ if (!arg->err) {
32205+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
32206+ d_type = DT_UNKNOWN;
1facf9fc 32207+ arg->err = au_nhash_append_wh
dece6358
AM
32208+ (&arg->whlist, name, nlen, ino, d_type,
32209+ arg->bindex, shwh);
4a4d8108 32210+ }
1facf9fc 32211+ }
32212+
4f0767ce 32213+out:
1facf9fc 32214+ if (!arg->err)
32215+ arg->vdir->vd_jiffy = jiffies;
32216+ /* smp_mb(); */
32217+ AuTraceErr(arg->err);
32218+ return arg->err;
32219+}
32220+
dece6358
AM
32221+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
32222+ struct au_nhash *whlist, struct au_nhash *delist)
32223+{
32224+#ifdef CONFIG_AUFS_SHWH
32225+ int err;
32226+ unsigned int nh, u;
32227+ struct hlist_head *head;
c06a8ce3
AM
32228+ struct au_vdir_wh *pos;
32229+ struct hlist_node *n;
dece6358
AM
32230+ char *p, *o;
32231+ struct au_vdir_destr *destr;
32232+
32233+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
32234+
32235+ err = -ENOMEM;
537831f9 32236+ o = p = (void *)__get_free_page(GFP_NOFS);
dece6358
AM
32237+ if (unlikely(!p))
32238+ goto out;
32239+
32240+ err = 0;
32241+ nh = whlist->nh_num;
32242+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
32243+ p += AUFS_WH_PFX_LEN;
32244+ for (u = 0; u < nh; u++) {
32245+ head = whlist->nh_head + u;
c06a8ce3
AM
32246+ hlist_for_each_entry_safe(pos, n, head, wh_hash) {
32247+ destr = &pos->wh_str;
dece6358
AM
32248+ memcpy(p, destr->name, destr->len);
32249+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
c06a8ce3 32250+ pos->wh_ino, pos->wh_type, delist);
dece6358
AM
32251+ if (unlikely(err))
32252+ break;
32253+ }
32254+ }
32255+
1c60b727 32256+ free_page((unsigned long)o);
dece6358 32257+
4f0767ce 32258+out:
dece6358
AM
32259+ AuTraceErr(err);
32260+ return err;
32261+#else
32262+ return 0;
32263+#endif
32264+}
32265+
1facf9fc 32266+static int au_do_read_vdir(struct fillvdir_arg *arg)
32267+{
32268+ int err;
dece6358 32269+ unsigned int rdhash;
1facf9fc 32270+ loff_t offset;
5afbbe0d 32271+ aufs_bindex_t bbot, bindex, btop;
dece6358 32272+ unsigned char shwh;
1facf9fc 32273+ struct file *hf, *file;
32274+ struct super_block *sb;
32275+
1facf9fc 32276+ file = arg->file;
2000de60 32277+ sb = file->f_path.dentry->d_sb;
dece6358
AM
32278+ SiMustAnyLock(sb);
32279+
32280+ rdhash = au_sbi(sb)->si_rdhash;
1308ab2a 32281+ if (!rdhash)
32282+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
dece6358
AM
32283+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
32284+ if (unlikely(err))
1facf9fc 32285+ goto out;
dece6358
AM
32286+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
32287+ if (unlikely(err))
1facf9fc 32288+ goto out_delist;
32289+
32290+ err = 0;
32291+ arg->flags = 0;
dece6358
AM
32292+ shwh = 0;
32293+ if (au_opt_test(au_mntflags(sb), SHWH)) {
32294+ shwh = 1;
32295+ au_fset_fillvdir(arg->flags, SHWH);
32296+ }
5afbbe0d
AM
32297+ btop = au_fbtop(file);
32298+ bbot = au_fbbot_dir(file);
32299+ for (bindex = btop; !err && bindex <= bbot; bindex++) {
4a4d8108 32300+ hf = au_hf_dir(file, bindex);
1facf9fc 32301+ if (!hf)
32302+ continue;
32303+
32304+ offset = vfsub_llseek(hf, 0, SEEK_SET);
32305+ err = offset;
32306+ if (unlikely(offset))
32307+ break;
32308+
32309+ arg->bindex = bindex;
32310+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358 32311+ if (shwh
5afbbe0d 32312+ || (bindex != bbot
dece6358 32313+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 32314+ au_fset_fillvdir(arg->flags, WHABLE);
32315+ do {
32316+ arg->err = 0;
32317+ au_fclr_fillvdir(arg->flags, CALLED);
32318+ /* smp_mb(); */
392086de 32319+ err = vfsub_iterate_dir(hf, &arg->ctx);
1facf9fc 32320+ if (err >= 0)
32321+ err = arg->err;
32322+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
392086de
AM
32323+
32324+ /*
32325+ * dir_relax() may be good for concurrency, but aufs should not
32326+ * use it since it will cause a lockdep problem.
32327+ */
1facf9fc 32328+ }
dece6358
AM
32329+
32330+ if (!err && shwh)
32331+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
32332+
32333+ au_nhash_wh_free(&arg->whlist);
1facf9fc 32334+
4f0767ce 32335+out_delist:
dece6358 32336+ au_nhash_de_free(&arg->delist);
4f0767ce 32337+out:
1facf9fc 32338+ return err;
32339+}
32340+
32341+static int read_vdir(struct file *file, int may_read)
32342+{
32343+ int err;
32344+ unsigned long expire;
32345+ unsigned char do_read;
392086de
AM
32346+ struct fillvdir_arg arg = {
32347+ .ctx = {
2000de60 32348+ .actor = fillvdir
392086de
AM
32349+ }
32350+ };
1facf9fc 32351+ struct inode *inode;
32352+ struct au_vdir *vdir, *allocated;
32353+
32354+ err = 0;
c06a8ce3 32355+ inode = file_inode(file);
1facf9fc 32356+ IMustLock(inode);
5afbbe0d 32357+ IiMustWriteLock(inode);
dece6358
AM
32358+ SiMustAnyLock(inode->i_sb);
32359+
1facf9fc 32360+ allocated = NULL;
32361+ do_read = 0;
32362+ expire = au_sbi(inode->i_sb)->si_rdcache;
32363+ vdir = au_ivdir(inode);
32364+ if (!vdir) {
32365+ do_read = 1;
1308ab2a 32366+ vdir = alloc_vdir(file);
1facf9fc 32367+ err = PTR_ERR(vdir);
32368+ if (IS_ERR(vdir))
32369+ goto out;
32370+ err = 0;
32371+ allocated = vdir;
32372+ } else if (may_read
be118d29 32373+ && (!inode_eq_iversion(inode, vdir->vd_version)
1facf9fc 32374+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
32375+ do_read = 1;
32376+ err = reinit_vdir(vdir);
32377+ if (unlikely(err))
32378+ goto out;
32379+ }
32380+
32381+ if (!do_read)
32382+ return 0; /* success */
32383+
32384+ arg.file = file;
32385+ arg.vdir = vdir;
32386+ err = au_do_read_vdir(&arg);
32387+ if (!err) {
392086de 32388+ /* file->f_pos = 0; */ /* todo: ctx->pos? */
be118d29 32389+ vdir->vd_version = inode_query_iversion(inode);
1facf9fc 32390+ vdir->vd_last.ul = 0;
32391+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
32392+ if (allocated)
32393+ au_set_ivdir(inode, allocated);
32394+ } else if (allocated)
1c60b727 32395+ au_vdir_free(allocated);
1facf9fc 32396+
4f0767ce 32397+out:
1facf9fc 32398+ return err;
32399+}
32400+
32401+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
32402+{
32403+ int err, rerr;
32404+ unsigned long ul, n;
32405+ const unsigned int deblk_sz = src->vd_deblk_sz;
32406+
32407+ AuDebugOn(tgt->vd_nblk != 1);
32408+
32409+ err = -ENOMEM;
32410+ if (tgt->vd_nblk < src->vd_nblk) {
32411+ unsigned char **p;
32412+
e2f27e51
AM
32413+ p = au_krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
32414+ GFP_NOFS, /*may_shrink*/0);
1facf9fc 32415+ if (unlikely(!p))
32416+ goto out;
32417+ tgt->vd_deblk = p;
32418+ }
32419+
1308ab2a 32420+ if (tgt->vd_deblk_sz != deblk_sz) {
32421+ unsigned char *p;
32422+
32423+ tgt->vd_deblk_sz = deblk_sz;
e2f27e51
AM
32424+ p = au_krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS,
32425+ /*may_shrink*/1);
1308ab2a 32426+ if (unlikely(!p))
32427+ goto out;
32428+ tgt->vd_deblk[0] = p;
32429+ }
1facf9fc 32430+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
1facf9fc 32431+ tgt->vd_version = src->vd_version;
32432+ tgt->vd_jiffy = src->vd_jiffy;
32433+
32434+ n = src->vd_nblk;
32435+ for (ul = 1; ul < n; ul++) {
dece6358
AM
32436+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
32437+ GFP_NOFS);
32438+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 32439+ goto out;
1308ab2a 32440+ tgt->vd_nblk++;
1facf9fc 32441+ }
1308ab2a 32442+ tgt->vd_nblk = n;
32443+ tgt->vd_last.ul = tgt->vd_last.ul;
32444+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
32445+ tgt->vd_last.p.deblk += src->vd_last.p.deblk
32446+ - src->vd_deblk[src->vd_last.ul];
1facf9fc 32447+ /* smp_mb(); */
32448+ return 0; /* success */
32449+
4f0767ce 32450+out:
1facf9fc 32451+ rerr = reinit_vdir(tgt);
32452+ BUG_ON(rerr);
32453+ return err;
32454+}
32455+
32456+int au_vdir_init(struct file *file)
32457+{
32458+ int err;
32459+ struct inode *inode;
32460+ struct au_vdir *vdir_cache, *allocated;
32461+
392086de 32462+ /* test file->f_pos here instead of ctx->pos */
1facf9fc 32463+ err = read_vdir(file, !file->f_pos);
32464+ if (unlikely(err))
32465+ goto out;
32466+
32467+ allocated = NULL;
32468+ vdir_cache = au_fvdir_cache(file);
32469+ if (!vdir_cache) {
1308ab2a 32470+ vdir_cache = alloc_vdir(file);
1facf9fc 32471+ err = PTR_ERR(vdir_cache);
32472+ if (IS_ERR(vdir_cache))
32473+ goto out;
32474+ allocated = vdir_cache;
32475+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
392086de 32476+ /* test file->f_pos here instead of ctx->pos */
1facf9fc 32477+ err = reinit_vdir(vdir_cache);
32478+ if (unlikely(err))
32479+ goto out;
32480+ } else
32481+ return 0; /* success */
32482+
c06a8ce3 32483+ inode = file_inode(file);
1facf9fc 32484+ err = copy_vdir(vdir_cache, au_ivdir(inode));
32485+ if (!err) {
be118d29 32486+ file->f_version = inode_query_iversion(inode);
1facf9fc 32487+ if (allocated)
32488+ au_set_fvdir_cache(file, allocated);
32489+ } else if (allocated)
1c60b727 32490+ au_vdir_free(allocated);
1facf9fc 32491+
4f0767ce 32492+out:
1facf9fc 32493+ return err;
32494+}
32495+
32496+static loff_t calc_offset(struct au_vdir *vdir)
32497+{
32498+ loff_t offset;
32499+ union au_vdir_deblk_p p;
32500+
32501+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
32502+ offset = vdir->vd_last.p.deblk - p.deblk;
32503+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
32504+ return offset;
32505+}
32506+
32507+/* returns true or false */
392086de 32508+static int seek_vdir(struct file *file, struct dir_context *ctx)
1facf9fc 32509+{
32510+ int valid;
32511+ unsigned int deblk_sz;
32512+ unsigned long ul, n;
32513+ loff_t offset;
32514+ union au_vdir_deblk_p p, deblk_end;
32515+ struct au_vdir *vdir_cache;
32516+
32517+ valid = 1;
32518+ vdir_cache = au_fvdir_cache(file);
32519+ offset = calc_offset(vdir_cache);
32520+ AuDbg("offset %lld\n", offset);
392086de 32521+ if (ctx->pos == offset)
1facf9fc 32522+ goto out;
32523+
32524+ vdir_cache->vd_last.ul = 0;
32525+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
392086de 32526+ if (!ctx->pos)
1facf9fc 32527+ goto out;
32528+
32529+ valid = 0;
32530+ deblk_sz = vdir_cache->vd_deblk_sz;
392086de 32531+ ul = div64_u64(ctx->pos, deblk_sz);
1facf9fc 32532+ AuDbg("ul %lu\n", ul);
32533+ if (ul >= vdir_cache->vd_nblk)
32534+ goto out;
32535+
32536+ n = vdir_cache->vd_nblk;
32537+ for (; ul < n; ul++) {
32538+ p.deblk = vdir_cache->vd_deblk[ul];
32539+ deblk_end.deblk = p.deblk + deblk_sz;
32540+ offset = ul;
32541+ offset *= deblk_sz;
392086de 32542+ while (!is_deblk_end(&p, &deblk_end) && offset < ctx->pos) {
1facf9fc 32543+ unsigned int l;
32544+
32545+ l = calc_size(p.de->de_str.len);
32546+ offset += l;
32547+ p.deblk += l;
32548+ }
32549+ if (!is_deblk_end(&p, &deblk_end)) {
32550+ valid = 1;
32551+ vdir_cache->vd_last.ul = ul;
32552+ vdir_cache->vd_last.p = p;
32553+ break;
32554+ }
32555+ }
32556+
4f0767ce 32557+out:
1facf9fc 32558+ /* smp_mb(); */
b00004a5
AM
32559+ if (!valid)
32560+ AuDbg("valid %d\n", !valid);
1facf9fc 32561+ return valid;
32562+}
32563+
392086de 32564+int au_vdir_fill_de(struct file *file, struct dir_context *ctx)
1facf9fc 32565+{
1facf9fc 32566+ unsigned int l, deblk_sz;
32567+ union au_vdir_deblk_p deblk_end;
32568+ struct au_vdir *vdir_cache;
32569+ struct au_vdir_de *de;
32570+
392086de 32571+ if (!seek_vdir(file, ctx))
1facf9fc 32572+ return 0;
32573+
acd2b654 32574+ vdir_cache = au_fvdir_cache(file);
1facf9fc 32575+ deblk_sz = vdir_cache->vd_deblk_sz;
32576+ while (1) {
32577+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
32578+ deblk_end.deblk += deblk_sz;
32579+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
32580+ de = vdir_cache->vd_last.p.de;
32581+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
392086de 32582+ de->de_str.len, de->de_str.name, ctx->pos,
1facf9fc 32583+ (unsigned long)de->de_ino, de->de_type);
392086de
AM
32584+ if (unlikely(!dir_emit(ctx, de->de_str.name,
32585+ de->de_str.len, de->de_ino,
32586+ de->de_type))) {
1facf9fc 32587+ /* todo: ignore the error caused by udba? */
32588+ /* return err; */
32589+ return 0;
32590+ }
32591+
32592+ l = calc_size(de->de_str.len);
32593+ vdir_cache->vd_last.p.deblk += l;
392086de 32594+ ctx->pos += l;
1facf9fc 32595+ }
32596+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
32597+ vdir_cache->vd_last.ul++;
32598+ vdir_cache->vd_last.p.deblk
32599+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
392086de 32600+ ctx->pos = deblk_sz * vdir_cache->vd_last.ul;
1facf9fc 32601+ continue;
32602+ }
32603+ break;
32604+ }
32605+
32606+ /* smp_mb(); */
32607+ return 0;
32608+}
7f207e10 32609diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
eca34b5c 32610--- /usr/share/empty/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
319657f6 32611+++ linux/fs/aufs/vfsub.c 2021-12-03 15:40:58.236647297 +0100
758e9dad 32612@@ -0,0 +1,919 @@
cd7a4cd9 32613+// SPDX-License-Identifier: GPL-2.0
1facf9fc 32614+/*
6d176551 32615+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 32616+ *
32617+ * This program, aufs is free software; you can redistribute it and/or modify
32618+ * it under the terms of the GNU General Public License as published by
32619+ * the Free Software Foundation; either version 2 of the License, or
32620+ * (at your option) any later version.
dece6358
AM
32621+ *
32622+ * This program is distributed in the hope that it will be useful,
32623+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
32624+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32625+ * GNU General Public License for more details.
32626+ *
32627+ * You should have received a copy of the GNU General Public License
523b37e3 32628+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 32629+ */
32630+
32631+/*
32632+ * sub-routines for VFS
32633+ */
32634+
8b6a4947 32635+#include <linux/mnt_namespace.h>
dece6358 32636+#include <linux/namei.h>
8cdd5066 32637+#include <linux/nsproxy.h>
dece6358
AM
32638+#include <linux/security.h>
32639+#include <linux/splice.h>
1facf9fc 32640+#include "aufs.h"
32641+
8cdd5066
JR
32642+#ifdef CONFIG_AUFS_BR_FUSE
32643+int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb)
32644+{
8cdd5066
JR
32645+ if (!au_test_fuse(h_sb) || !au_userns)
32646+ return 0;
32647+
8b6a4947 32648+ return is_current_mnt_ns(mnt) ? 0 : -EACCES;
8cdd5066
JR
32649+}
32650+#endif
32651+
a2654f78
AM
32652+int vfsub_sync_filesystem(struct super_block *h_sb, int wait)
32653+{
32654+ int err;
32655+
32656+ lockdep_off();
32657+ down_read(&h_sb->s_umount);
4df42b26 32658+ err = sync_filesystem(h_sb);
a2654f78
AM
32659+ up_read(&h_sb->s_umount);
32660+ lockdep_on();
32661+
32662+ return err;
32663+}
32664+
8cdd5066
JR
32665+/* ---------------------------------------------------------------------- */
32666+
1facf9fc 32667+int vfsub_update_h_iattr(struct path *h_path, int *did)
32668+{
32669+ int err;
32670+ struct kstat st;
32671+ struct super_block *h_sb;
32672+
758e9dad
AM
32673+ /*
32674+ * Always needs h_path->mnt for LSM or FUSE branch.
32675+ */
32676+ AuDebugOn(!h_path->mnt);
32677+
1facf9fc 32678+ /* for remote fs, leave work for its getattr or d_revalidate */
32679+ /* for bad i_attr fs, handle them in aufs_getattr() */
32680+ /* still some fs may acquire i_mutex. we need to skip them */
32681+ err = 0;
32682+ if (!did)
32683+ did = &err;
32684+ h_sb = h_path->dentry->d_sb;
32685+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
32686+ if (*did)
521ced18 32687+ err = vfsub_getattr(h_path, &st);
1facf9fc 32688+
32689+ return err;
32690+}
32691+
32692+/* ---------------------------------------------------------------------- */
32693+
4a4d8108 32694+struct file *vfsub_dentry_open(struct path *path, int flags)
1308ab2a 32695+{
42b5c33a 32696+ return dentry_open(path, flags /* | __FMODE_NONOTIFY */,
7f207e10 32697+ current_cred());
1308ab2a 32698+}
32699+
1facf9fc 32700+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
32701+{
32702+ struct file *file;
32703+
2cbb1c4b 32704+ lockdep_off();
7f207e10 32705+ file = filp_open(path,
2cbb1c4b 32706+ oflags /* | __FMODE_NONOTIFY */,
7f207e10 32707+ mode);
2cbb1c4b 32708+ lockdep_on();
1facf9fc 32709+ if (IS_ERR(file))
32710+ goto out;
32711+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
32712+
4f0767ce 32713+out:
1facf9fc 32714+ return file;
32715+}
32716+
b912730e
AM
32717+/*
32718+ * Ideally this function should call VFS:do_last() in order to keep all its
32719+ * checkings. But it is very hard for aufs to regenerate several VFS internal
32720+ * structure such as nameidata. This is a second (or third) best approach.
32721+ * cf. linux/fs/namei.c:do_last(), lookup_open() and atomic_open().
32722+ */
32723+int vfsub_atomic_open(struct inode *dir, struct dentry *dentry,
acd2b654 32724+ struct vfsub_aopen_args *args)
b912730e
AM
32725+{
32726+ int err;
acd2b654 32727+ struct au_branch *br = args->br;
b912730e
AM
32728+ struct file *file = args->file;
32729+ /* copied from linux/fs/namei.c:atomic_open() */
32730+ struct dentry *const DENTRY_NOT_SET = (void *)-1UL;
32731+
32732+ IMustLock(dir);
32733+ AuDebugOn(!dir->i_op->atomic_open);
32734+
32735+ err = au_br_test_oflag(args->open_flag, br);
32736+ if (unlikely(err))
32737+ goto out;
32738+
acd2b654
AM
32739+ au_lcnt_inc(&br->br_nfiles);
32740+ file->f_path.dentry = DENTRY_NOT_SET;
32741+ file->f_path.mnt = au_br_mnt(br);
32742+ AuDbg("%ps\n", dir->i_op->atomic_open);
b912730e 32743+ err = dir->i_op->atomic_open(dir, dentry, file, args->open_flag,
acd2b654
AM
32744+ args->create_mode);
32745+ if (unlikely(err < 0)) {
32746+ au_lcnt_dec(&br->br_nfiles);
b912730e 32747+ goto out;
acd2b654 32748+ }
b912730e 32749+
acd2b654
AM
32750+ /* temporary workaround for nfsv4 branch */
32751+ if (au_test_nfs(dir->i_sb))
32752+ nfs_mark_for_revalidate(dir);
b912730e 32753+
acd2b654
AM
32754+ if (file->f_mode & FMODE_CREATED)
32755+ fsnotify_create(dir, dentry);
32756+ if (!(file->f_mode & FMODE_OPENED)) {
32757+ au_lcnt_dec(&br->br_nfiles);
32758+ goto out;
b912730e
AM
32759+ }
32760+
acd2b654
AM
32761+ /* todo: call VFS:may_open() here */
32762+ /* todo: ima_file_check() too? */
32763+ if (!err && (args->open_flag & __FMODE_EXEC))
32764+ err = deny_write_access(file);
32765+ if (!err)
32766+ fsnotify_open(file);
32767+ else
32768+ au_lcnt_dec(&br->br_nfiles);
32769+ /* note that the file is created and still opened */
b912730e
AM
32770+
32771+out:
32772+ return err;
32773+}
32774+
1facf9fc 32775+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
32776+{
32777+ int err;
32778+
1facf9fc 32779+ err = kern_path(name, flags, path);
5527c038 32780+ if (!err && d_is_positive(path->dentry))
1facf9fc 32781+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
32782+ return err;
32783+}
32784+
febd17d6 32785+struct dentry *vfsub_lookup_one_len_unlocked(const char *name,
758e9dad 32786+ struct path *ppath, int len)
febd17d6 32787+{
758e9dad 32788+ struct path path;
febd17d6 32789+
758e9dad 32790+ path.dentry = lookup_one_len_unlocked(name, ppath->dentry, len);
febd17d6
JR
32791+ if (IS_ERR(path.dentry))
32792+ goto out;
758e9dad
AM
32793+ if (d_is_positive(path.dentry)) {
32794+ path.mnt = ppath->mnt;
febd17d6 32795+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
758e9dad 32796+ }
febd17d6
JR
32797+
32798+out:
32799+ AuTraceErrPtr(path.dentry);
32800+ return path.dentry;
32801+}
32802+
758e9dad 32803+struct dentry *vfsub_lookup_one_len(const char *name, struct path *ppath,
1facf9fc 32804+ int len)
32805+{
758e9dad 32806+ struct path path;
1facf9fc 32807+
1308ab2a 32808+ /* VFS checks it too, but by WARN_ON_ONCE() */
758e9dad 32809+ IMustLock(d_inode(ppath->dentry));
1facf9fc 32810+
758e9dad 32811+ path.dentry = lookup_one_len(name, ppath->dentry, len);
1facf9fc 32812+ if (IS_ERR(path.dentry))
32813+ goto out;
758e9dad
AM
32814+ if (d_is_positive(path.dentry)) {
32815+ path.mnt = ppath->mnt;
1facf9fc 32816+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
758e9dad 32817+ }
1facf9fc 32818+
4f0767ce 32819+out:
4a4d8108 32820+ AuTraceErrPtr(path.dentry);
1facf9fc 32821+ return path.dentry;
32822+}
32823+
b4510431 32824+void vfsub_call_lkup_one(void *args)
2cbb1c4b 32825+{
b4510431 32826+ struct vfsub_lkup_one_args *a = args;
758e9dad 32827+ *a->errp = vfsub_lkup_one(a->name, a->ppath);
2cbb1c4b
JR
32828+}
32829+
1facf9fc 32830+/* ---------------------------------------------------------------------- */
32831+
32832+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
32833+ struct dentry *d2, struct au_hinode *hdir2)
32834+{
32835+ struct dentry *d;
32836+
2cbb1c4b 32837+ lockdep_off();
1facf9fc 32838+ d = lock_rename(d1, d2);
2cbb1c4b 32839+ lockdep_on();
4a4d8108 32840+ au_hn_suspend(hdir1);
1facf9fc 32841+ if (hdir1 != hdir2)
4a4d8108 32842+ au_hn_suspend(hdir2);
1facf9fc 32843+
32844+ return d;
32845+}
32846+
32847+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
32848+ struct dentry *d2, struct au_hinode *hdir2)
32849+{
4a4d8108 32850+ au_hn_resume(hdir1);
1facf9fc 32851+ if (hdir1 != hdir2)
4a4d8108 32852+ au_hn_resume(hdir2);
2cbb1c4b 32853+ lockdep_off();
1facf9fc 32854+ unlock_rename(d1, d2);
2cbb1c4b 32855+ lockdep_on();
1facf9fc 32856+}
32857+
32858+/* ---------------------------------------------------------------------- */
32859+
b4510431 32860+int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl)
1facf9fc 32861+{
32862+ int err;
32863+ struct dentry *d;
0b2a12c6 32864+ struct user_namespace *userns;
1facf9fc 32865+
32866+ IMustLock(dir);
32867+
32868+ d = path->dentry;
32869+ path->dentry = d->d_parent;
b752ccd1 32870+ err = security_path_mknod(path, d, mode, 0);
1facf9fc 32871+ path->dentry = d;
32872+ if (unlikely(err))
32873+ goto out;
0b2a12c6 32874+ userns = mnt_user_ns(path->mnt);
1facf9fc 32875+
c1595e42 32876+ lockdep_off();
0b2a12c6 32877+ err = vfs_create(userns, dir, path->dentry, mode, want_excl);
c1595e42 32878+ lockdep_on();
1facf9fc 32879+ if (!err) {
32880+ struct path tmp = *path;
32881+ int did;
32882+
32883+ vfsub_update_h_iattr(&tmp, &did);
32884+ if (did) {
32885+ tmp.dentry = path->dentry->d_parent;
32886+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
32887+ }
32888+ /*ignore*/
32889+ }
32890+
4f0767ce 32891+out:
1facf9fc 32892+ return err;
32893+}
32894+
32895+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
32896+{
32897+ int err;
32898+ struct dentry *d;
0b2a12c6 32899+ struct user_namespace *userns;
1facf9fc 32900+
32901+ IMustLock(dir);
32902+
32903+ d = path->dentry;
32904+ path->dentry = d->d_parent;
b752ccd1 32905+ err = security_path_symlink(path, d, symname);
1facf9fc 32906+ path->dentry = d;
32907+ if (unlikely(err))
32908+ goto out;
0b2a12c6 32909+ userns = mnt_user_ns(path->mnt);
1facf9fc 32910+
c1595e42 32911+ lockdep_off();
0b2a12c6 32912+ err = vfs_symlink(userns, dir, path->dentry, symname);
c1595e42 32913+ lockdep_on();
1facf9fc 32914+ if (!err) {
32915+ struct path tmp = *path;
32916+ int did;
32917+
32918+ vfsub_update_h_iattr(&tmp, &did);
32919+ if (did) {
32920+ tmp.dentry = path->dentry->d_parent;
32921+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
32922+ }
32923+ /*ignore*/
32924+ }
32925+
4f0767ce 32926+out:
1facf9fc 32927+ return err;
32928+}
32929+
32930+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
32931+{
32932+ int err;
32933+ struct dentry *d;
0b2a12c6 32934+ struct user_namespace *userns;
1facf9fc 32935+
32936+ IMustLock(dir);
32937+
32938+ d = path->dentry;
32939+ path->dentry = d->d_parent;
027c5e7a 32940+ err = security_path_mknod(path, d, mode, new_encode_dev(dev));
1facf9fc 32941+ path->dentry = d;
32942+ if (unlikely(err))
32943+ goto out;
0b2a12c6 32944+ userns = mnt_user_ns(path->mnt);
1facf9fc 32945+
c1595e42 32946+ lockdep_off();
0b2a12c6 32947+ err = vfs_mknod(userns, dir, path->dentry, mode, dev);
c1595e42 32948+ lockdep_on();
1facf9fc 32949+ if (!err) {
32950+ struct path tmp = *path;
32951+ int did;
32952+
32953+ vfsub_update_h_iattr(&tmp, &did);
32954+ if (did) {
32955+ tmp.dentry = path->dentry->d_parent;
32956+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
32957+ }
32958+ /*ignore*/
32959+ }
32960+
4f0767ce 32961+out:
1facf9fc 32962+ return err;
32963+}
32964+
32965+static int au_test_nlink(struct inode *inode)
32966+{
32967+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
32968+
32969+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
32970+ || inode->i_nlink < link_max)
32971+ return 0;
32972+ return -EMLINK;
32973+}
32974+
523b37e3
AM
32975+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path,
32976+ struct inode **delegated_inode)
1facf9fc 32977+{
32978+ int err;
32979+ struct dentry *d;
0b2a12c6 32980+ struct user_namespace *userns;
1facf9fc 32981+
32982+ IMustLock(dir);
32983+
5527c038 32984+ err = au_test_nlink(d_inode(src_dentry));
1facf9fc 32985+ if (unlikely(err))
32986+ return err;
32987+
b4510431 32988+ /* we don't call may_linkat() */
1facf9fc 32989+ d = path->dentry;
32990+ path->dentry = d->d_parent;
b752ccd1 32991+ err = security_path_link(src_dentry, path, d);
1facf9fc 32992+ path->dentry = d;
32993+ if (unlikely(err))
32994+ goto out;
0b2a12c6 32995+ userns = mnt_user_ns(path->mnt);
1facf9fc 32996+
2cbb1c4b 32997+ lockdep_off();
0b2a12c6 32998+ err = vfs_link(src_dentry, userns, dir, path->dentry, delegated_inode);
2cbb1c4b 32999+ lockdep_on();
1facf9fc 33000+ if (!err) {
33001+ struct path tmp = *path;
33002+ int did;
33003+
33004+ /* fuse has different memory inode for the same inumber */
33005+ vfsub_update_h_iattr(&tmp, &did);
33006+ if (did) {
33007+ tmp.dentry = path->dentry->d_parent;
33008+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33009+ tmp.dentry = src_dentry;
33010+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33011+ }
33012+ /*ignore*/
33013+ }
33014+
4f0767ce 33015+out:
1facf9fc 33016+ return err;
33017+}
33018+
33019+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
523b37e3 33020+ struct inode *dir, struct path *path,
f2c43d5f 33021+ struct inode **delegated_inode, unsigned int flags)
1facf9fc 33022+{
33023+ int err;
0b2a12c6 33024+ struct renamedata rd;
1facf9fc 33025+ struct path tmp = {
33026+ .mnt = path->mnt
33027+ };
33028+ struct dentry *d;
33029+
33030+ IMustLock(dir);
33031+ IMustLock(src_dir);
33032+
33033+ d = path->dentry;
33034+ path->dentry = d->d_parent;
33035+ tmp.dentry = src_dentry->d_parent;
38d290e6 33036+ err = security_path_rename(&tmp, src_dentry, path, d, /*flags*/0);
1facf9fc 33037+ path->dentry = d;
33038+ if (unlikely(err))
33039+ goto out;
33040+
0b2a12c6
JR
33041+ rd.old_mnt_userns = mnt_user_ns(path->mnt);
33042+ rd.old_dir = src_dir;
33043+ rd.old_dentry = src_dentry;
33044+ rd.new_mnt_userns = rd.old_mnt_userns;
33045+ rd.new_dir = dir;
33046+ rd.new_dentry = path->dentry;
33047+ rd.delegated_inode = delegated_inode;
33048+ rd.flags = flags;
2cbb1c4b 33049+ lockdep_off();
0b2a12c6 33050+ err = vfs_rename(&rd);
2cbb1c4b 33051+ lockdep_on();
1facf9fc 33052+ if (!err) {
33053+ int did;
33054+
33055+ tmp.dentry = d->d_parent;
33056+ vfsub_update_h_iattr(&tmp, &did);
33057+ if (did) {
33058+ tmp.dentry = src_dentry;
33059+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33060+ tmp.dentry = src_dentry->d_parent;
33061+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33062+ }
33063+ /*ignore*/
33064+ }
33065+
4f0767ce 33066+out:
1facf9fc 33067+ return err;
33068+}
33069+
33070+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
33071+{
33072+ int err;
33073+ struct dentry *d;
0b2a12c6 33074+ struct user_namespace *userns;
1facf9fc 33075+
33076+ IMustLock(dir);
33077+
33078+ d = path->dentry;
33079+ path->dentry = d->d_parent;
b752ccd1 33080+ err = security_path_mkdir(path, d, mode);
1facf9fc 33081+ path->dentry = d;
33082+ if (unlikely(err))
33083+ goto out;
0b2a12c6 33084+ userns = mnt_user_ns(path->mnt);
1facf9fc 33085+
c1595e42 33086+ lockdep_off();
0b2a12c6 33087+ err = vfs_mkdir(userns, dir, path->dentry, mode);
c1595e42 33088+ lockdep_on();
1facf9fc 33089+ if (!err) {
33090+ struct path tmp = *path;
33091+ int did;
33092+
33093+ vfsub_update_h_iattr(&tmp, &did);
33094+ if (did) {
33095+ tmp.dentry = path->dentry->d_parent;
33096+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33097+ }
33098+ /*ignore*/
33099+ }
33100+
4f0767ce 33101+out:
1facf9fc 33102+ return err;
33103+}
33104+
33105+int vfsub_rmdir(struct inode *dir, struct path *path)
33106+{
33107+ int err;
33108+ struct dentry *d;
0b2a12c6 33109+ struct user_namespace *userns;
1facf9fc 33110+
33111+ IMustLock(dir);
33112+
33113+ d = path->dentry;
33114+ path->dentry = d->d_parent;
b752ccd1 33115+ err = security_path_rmdir(path, d);
1facf9fc 33116+ path->dentry = d;
33117+ if (unlikely(err))
33118+ goto out;
0b2a12c6 33119+ userns = mnt_user_ns(path->mnt);
1facf9fc 33120+
2cbb1c4b 33121+ lockdep_off();
0b2a12c6 33122+ err = vfs_rmdir(userns, dir, path->dentry);
2cbb1c4b 33123+ lockdep_on();
1facf9fc 33124+ if (!err) {
33125+ struct path tmp = {
33126+ .dentry = path->dentry->d_parent,
33127+ .mnt = path->mnt
33128+ };
33129+
33130+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
33131+ }
33132+
4f0767ce 33133+out:
1facf9fc 33134+ return err;
33135+}
33136+
33137+/* ---------------------------------------------------------------------- */
33138+
9dbd164d 33139+/* todo: support mmap_sem? */
1facf9fc 33140+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
33141+ loff_t *ppos)
33142+{
33143+ ssize_t err;
33144+
2cbb1c4b 33145+ lockdep_off();
1facf9fc 33146+ err = vfs_read(file, ubuf, count, ppos);
2cbb1c4b 33147+ lockdep_on();
1facf9fc 33148+ if (err >= 0)
33149+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
33150+ return err;
33151+}
33152+
1facf9fc 33153+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
33154+ loff_t *ppos)
33155+{
33156+ ssize_t err;
1facf9fc 33157+
e37dd06a
AM
33158+ lockdep_off();
33159+ err = kernel_read(file, kbuf, count, ppos);
33160+ lockdep_on();
33161+ AuTraceErr(err);
33162+ if (err >= 0)
33163+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
1facf9fc 33164+ return err;
33165+}
33166+
33167+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
33168+ loff_t *ppos)
33169+{
33170+ ssize_t err;
33171+
2cbb1c4b 33172+ lockdep_off();
1facf9fc 33173+ err = vfs_write(file, ubuf, count, ppos);
2cbb1c4b 33174+ lockdep_on();
1facf9fc 33175+ if (err >= 0)
33176+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
33177+ return err;
33178+}
33179+
33180+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
33181+{
33182+ ssize_t err;
1facf9fc 33183+
e37dd06a
AM
33184+ lockdep_off();
33185+ err = kernel_write(file, kbuf, count, ppos);
33186+ lockdep_on();
33187+ if (err >= 0)
33188+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
1facf9fc 33189+ return err;
33190+}
33191+
4a4d8108
AM
33192+int vfsub_flush(struct file *file, fl_owner_t id)
33193+{
33194+ int err;
33195+
33196+ err = 0;
523b37e3 33197+ if (file->f_op->flush) {
2000de60 33198+ if (!au_test_nfs(file->f_path.dentry->d_sb))
2cbb1c4b
JR
33199+ err = file->f_op->flush(file, id);
33200+ else {
33201+ lockdep_off();
33202+ err = file->f_op->flush(file, id);
33203+ lockdep_on();
33204+ }
4a4d8108
AM
33205+ if (!err)
33206+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
33207+ /*ignore*/
33208+ }
33209+ return err;
33210+}
33211+
392086de 33212+int vfsub_iterate_dir(struct file *file, struct dir_context *ctx)
1facf9fc 33213+{
33214+ int err;
33215+
062440b3 33216+ AuDbg("%pD, ctx{%ps, %llu}\n", file, ctx->actor, ctx->pos);
392086de 33217+
2cbb1c4b 33218+ lockdep_off();
392086de 33219+ err = iterate_dir(file, ctx);
2cbb1c4b 33220+ lockdep_on();
1facf9fc 33221+ if (err >= 0)
33222+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
1c60b727 33223+
1facf9fc 33224+ return err;
33225+}
33226+
33227+long vfsub_splice_to(struct file *in, loff_t *ppos,
33228+ struct pipe_inode_info *pipe, size_t len,
33229+ unsigned int flags)
33230+{
33231+ long err;
33232+
2cbb1c4b 33233+ lockdep_off();
0fc653ad 33234+ err = do_splice_to(in, ppos, pipe, len, flags);
2cbb1c4b 33235+ lockdep_on();
4a4d8108 33236+ file_accessed(in);
1facf9fc 33237+ if (err >= 0)
33238+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
33239+ return err;
33240+}
33241+
33242+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
33243+ loff_t *ppos, size_t len, unsigned int flags)
33244+{
33245+ long err;
33246+
2cbb1c4b 33247+ lockdep_off();
0fc653ad 33248+ err = do_splice_from(pipe, out, ppos, len, flags);
2cbb1c4b 33249+ lockdep_on();
1facf9fc 33250+ if (err >= 0)
33251+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
33252+ return err;
33253+}
33254+
53392da6
AM
33255+int vfsub_fsync(struct file *file, struct path *path, int datasync)
33256+{
33257+ int err;
33258+
33259+ /* file can be NULL */
33260+ lockdep_off();
33261+ err = vfs_fsync(file, datasync);
33262+ lockdep_on();
33263+ if (!err) {
33264+ if (!path) {
33265+ AuDebugOn(!file);
33266+ path = &file->f_path;
33267+ }
33268+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
33269+ }
33270+ return err;
33271+}
33272+
1facf9fc 33273+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
33274+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
33275+ struct file *h_file)
33276+{
33277+ int err;
33278+ struct inode *h_inode;
c06a8ce3 33279+ struct super_block *h_sb;
0b2a12c6 33280+ struct user_namespace *h_userns;
1facf9fc 33281+
1facf9fc 33282+ if (!h_file) {
c06a8ce3
AM
33283+ err = vfsub_truncate(h_path, length);
33284+ goto out;
1facf9fc 33285+ }
33286+
5527c038 33287+ h_inode = d_inode(h_path->dentry);
c06a8ce3
AM
33288+ h_sb = h_inode->i_sb;
33289+ lockdep_off();
33290+ sb_start_write(h_sb);
33291+ lockdep_on();
758e9dad 33292+ err = security_path_truncate(h_path);
2cbb1c4b 33293+ if (!err) {
0b2a12c6 33294+ h_userns = mnt_user_ns(h_path->mnt);
2cbb1c4b 33295+ lockdep_off();
0b2a12c6
JR
33296+ err = do_truncate(h_userns, h_path->dentry, length, attr,
33297+ h_file);
2cbb1c4b
JR
33298+ lockdep_on();
33299+ }
c06a8ce3
AM
33300+ lockdep_off();
33301+ sb_end_write(h_sb);
33302+ lockdep_on();
1facf9fc 33303+
4f0767ce 33304+out:
1facf9fc 33305+ return err;
33306+}
33307+
33308+/* ---------------------------------------------------------------------- */
33309+
33310+struct au_vfsub_mkdir_args {
33311+ int *errp;
33312+ struct inode *dir;
33313+ struct path *path;
33314+ int mode;
33315+};
33316+
33317+static void au_call_vfsub_mkdir(void *args)
33318+{
33319+ struct au_vfsub_mkdir_args *a = args;
33320+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
33321+}
33322+
33323+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
33324+{
33325+ int err, do_sio, wkq_err;
0b2a12c6 33326+ struct user_namespace *userns;
1facf9fc 33327+
0b2a12c6
JR
33328+ userns = mnt_user_ns(path->mnt);
33329+ do_sio = au_test_h_perm_sio(userns, dir, MAY_EXEC | MAY_WRITE);
c1595e42
JR
33330+ if (!do_sio) {
33331+ lockdep_off();
1facf9fc 33332+ err = vfsub_mkdir(dir, path, mode);
c1595e42
JR
33333+ lockdep_on();
33334+ } else {
1facf9fc 33335+ struct au_vfsub_mkdir_args args = {
33336+ .errp = &err,
33337+ .dir = dir,
33338+ .path = path,
33339+ .mode = mode
33340+ };
33341+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
33342+ if (unlikely(wkq_err))
33343+ err = wkq_err;
33344+ }
33345+
33346+ return err;
33347+}
33348+
33349+struct au_vfsub_rmdir_args {
33350+ int *errp;
33351+ struct inode *dir;
33352+ struct path *path;
33353+};
33354+
33355+static void au_call_vfsub_rmdir(void *args)
33356+{
33357+ struct au_vfsub_rmdir_args *a = args;
33358+ *a->errp = vfsub_rmdir(a->dir, a->path);
33359+}
33360+
33361+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
33362+{
33363+ int err, do_sio, wkq_err;
0b2a12c6 33364+ struct user_namespace *userns;
1facf9fc 33365+
0b2a12c6
JR
33366+ userns = mnt_user_ns(path->mnt);
33367+ do_sio = au_test_h_perm_sio(userns, dir, MAY_EXEC | MAY_WRITE);
c1595e42
JR
33368+ if (!do_sio) {
33369+ lockdep_off();
1facf9fc 33370+ err = vfsub_rmdir(dir, path);
c1595e42
JR
33371+ lockdep_on();
33372+ } else {
1facf9fc 33373+ struct au_vfsub_rmdir_args args = {
33374+ .errp = &err,
33375+ .dir = dir,
33376+ .path = path
33377+ };
33378+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
33379+ if (unlikely(wkq_err))
33380+ err = wkq_err;
33381+ }
33382+
33383+ return err;
33384+}
33385+
33386+/* ---------------------------------------------------------------------- */
33387+
33388+struct notify_change_args {
33389+ int *errp;
33390+ struct path *path;
33391+ struct iattr *ia;
523b37e3 33392+ struct inode **delegated_inode;
1facf9fc 33393+};
33394+
33395+static void call_notify_change(void *args)
33396+{
33397+ struct notify_change_args *a = args;
33398+ struct inode *h_inode;
0b2a12c6 33399+ struct user_namespace *userns;
1facf9fc 33400+
5527c038 33401+ h_inode = d_inode(a->path->dentry);
1facf9fc 33402+ IMustLock(h_inode);
33403+
33404+ *a->errp = -EPERM;
33405+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
0b2a12c6 33406+ userns = mnt_user_ns(a->path->mnt);
c1595e42 33407+ lockdep_off();
0b2a12c6 33408+ *a->errp = notify_change(userns, a->path->dentry, a->ia,
523b37e3 33409+ a->delegated_inode);
c1595e42 33410+ lockdep_on();
1facf9fc 33411+ if (!*a->errp)
33412+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
33413+ }
33414+ AuTraceErr(*a->errp);
33415+}
33416+
523b37e3
AM
33417+int vfsub_notify_change(struct path *path, struct iattr *ia,
33418+ struct inode **delegated_inode)
1facf9fc 33419+{
33420+ int err;
33421+ struct notify_change_args args = {
523b37e3
AM
33422+ .errp = &err,
33423+ .path = path,
33424+ .ia = ia,
33425+ .delegated_inode = delegated_inode
1facf9fc 33426+ };
33427+
33428+ call_notify_change(&args);
33429+
33430+ return err;
33431+}
33432+
523b37e3
AM
33433+int vfsub_sio_notify_change(struct path *path, struct iattr *ia,
33434+ struct inode **delegated_inode)
1facf9fc 33435+{
33436+ int err, wkq_err;
33437+ struct notify_change_args args = {
523b37e3
AM
33438+ .errp = &err,
33439+ .path = path,
33440+ .ia = ia,
33441+ .delegated_inode = delegated_inode
1facf9fc 33442+ };
33443+
33444+ wkq_err = au_wkq_wait(call_notify_change, &args);
33445+ if (unlikely(wkq_err))
33446+ err = wkq_err;
33447+
33448+ return err;
33449+}
33450+
33451+/* ---------------------------------------------------------------------- */
33452+
33453+struct unlink_args {
33454+ int *errp;
33455+ struct inode *dir;
33456+ struct path *path;
523b37e3 33457+ struct inode **delegated_inode;
1facf9fc 33458+};
33459+
33460+static void call_unlink(void *args)
33461+{
33462+ struct unlink_args *a = args;
33463+ struct dentry *d = a->path->dentry;
33464+ struct inode *h_inode;
0b2a12c6 33465+ struct user_namespace *userns;
1facf9fc 33466+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
c1595e42 33467+ && au_dcount(d) == 1);
1facf9fc 33468+
33469+ IMustLock(a->dir);
33470+
33471+ a->path->dentry = d->d_parent;
33472+ *a->errp = security_path_unlink(a->path, d);
33473+ a->path->dentry = d;
33474+ if (unlikely(*a->errp))
33475+ return;
33476+
33477+ if (!stop_sillyrename)
33478+ dget(d);
5527c038
JR
33479+ h_inode = NULL;
33480+ if (d_is_positive(d)) {
33481+ h_inode = d_inode(d);
027c5e7a 33482+ ihold(h_inode);
5527c038 33483+ }
1facf9fc 33484+
0b2a12c6 33485+ userns = mnt_user_ns(a->path->mnt);
2cbb1c4b 33486+ lockdep_off();
0b2a12c6 33487+ *a->errp = vfs_unlink(userns, a->dir, d, a->delegated_inode);
2cbb1c4b 33488+ lockdep_on();
1facf9fc 33489+ if (!*a->errp) {
33490+ struct path tmp = {
33491+ .dentry = d->d_parent,
33492+ .mnt = a->path->mnt
33493+ };
33494+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
33495+ }
33496+
33497+ if (!stop_sillyrename)
33498+ dput(d);
33499+ if (h_inode)
33500+ iput(h_inode);
33501+
33502+ AuTraceErr(*a->errp);
33503+}
33504+
33505+/*
33506+ * @dir: must be locked.
33507+ * @dentry: target dentry.
33508+ */
523b37e3
AM
33509+int vfsub_unlink(struct inode *dir, struct path *path,
33510+ struct inode **delegated_inode, int force)
1facf9fc 33511+{
33512+ int err;
33513+ struct unlink_args args = {
523b37e3
AM
33514+ .errp = &err,
33515+ .dir = dir,
33516+ .path = path,
33517+ .delegated_inode = delegated_inode
1facf9fc 33518+ };
33519+
33520+ if (!force)
33521+ call_unlink(&args);
33522+ else {
33523+ int wkq_err;
33524+
33525+ wkq_err = au_wkq_wait(call_unlink, &args);
33526+ if (unlikely(wkq_err))
33527+ err = wkq_err;
33528+ }
33529+
33530+ return err;
33531+}
7f207e10 33532diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
eca34b5c 33533--- /usr/share/empty/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
319657f6 33534+++ linux/fs/aufs/vfsub.h 2021-12-03 15:40:58.236647297 +0100
0b2a12c6 33535@@ -0,0 +1,358 @@
062440b3 33536+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 33537+/*
6d176551 33538+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 33539+ *
33540+ * This program, aufs is free software; you can redistribute it and/or modify
33541+ * it under the terms of the GNU General Public License as published by
33542+ * the Free Software Foundation; either version 2 of the License, or
33543+ * (at your option) any later version.
dece6358
AM
33544+ *
33545+ * This program is distributed in the hope that it will be useful,
33546+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
33547+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33548+ * GNU General Public License for more details.
33549+ *
33550+ * You should have received a copy of the GNU General Public License
523b37e3 33551+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 33552+ */
33553+
33554+/*
33555+ * sub-routines for VFS
33556+ */
33557+
33558+#ifndef __AUFS_VFSUB_H__
33559+#define __AUFS_VFSUB_H__
33560+
33561+#ifdef __KERNEL__
33562+
33563+#include <linux/fs.h>
b4510431 33564+#include <linux/mount.h>
8cdd5066 33565+#include <linux/posix_acl.h>
c1595e42 33566+#include <linux/xattr.h>
7f207e10 33567+#include "debug.h"
1facf9fc 33568+
7f207e10 33569+/* copied from linux/fs/internal.h */
2cbb1c4b 33570+/* todo: BAD approach!! */
c06a8ce3 33571+extern void __mnt_drop_write(struct vfsmount *);
acd2b654 33572+extern struct file *alloc_empty_file(int, const struct cred *);
7f207e10
AM
33573+
33574+/* ---------------------------------------------------------------------- */
1facf9fc 33575+
33576+/* lock subclass for lower inode */
33577+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
33578+/* reduce? gave up. */
33579+enum {
c1595e42 33580+ AuLsc_I_Begin = I_MUTEX_PARENT2, /* 5 */
1facf9fc 33581+ AuLsc_I_PARENT, /* lower inode, parent first */
33582+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 33583+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 33584+ AuLsc_I_CHILD,
33585+ AuLsc_I_CHILD2,
33586+ AuLsc_I_End
33587+};
33588+
33589+/* to debug easier, do not make them inlined functions */
33590+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
febd17d6 33591+#define IMustLock(i) AuDebugOn(!inode_is_locked(i))
1facf9fc 33592+
33593+/* ---------------------------------------------------------------------- */
33594+
7f207e10
AM
33595+static inline void vfsub_drop_nlink(struct inode *inode)
33596+{
33597+ AuDebugOn(!inode->i_nlink);
33598+ drop_nlink(inode);
33599+}
33600+
027c5e7a
AM
33601+static inline void vfsub_dead_dir(struct inode *inode)
33602+{
33603+ AuDebugOn(!S_ISDIR(inode->i_mode));
33604+ inode->i_flags |= S_DEAD;
33605+ clear_nlink(inode);
33606+}
33607+
392086de
AM
33608+static inline int vfsub_native_ro(struct inode *inode)
33609+{
8b6a4947 33610+ return sb_rdonly(inode->i_sb)
392086de
AM
33611+ || IS_RDONLY(inode)
33612+ /* || IS_APPEND(inode) */
33613+ || IS_IMMUTABLE(inode);
33614+}
33615+
8cdd5066
JR
33616+#ifdef CONFIG_AUFS_BR_FUSE
33617+int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb);
33618+#else
33619+AuStubInt0(vfsub_test_mntns, struct vfsmount *mnt, struct super_block *h_sb);
33620+#endif
33621+
a2654f78
AM
33622+int vfsub_sync_filesystem(struct super_block *h_sb, int wait);
33623+
7f207e10
AM
33624+/* ---------------------------------------------------------------------- */
33625+
33626+int vfsub_update_h_iattr(struct path *h_path, int *did);
33627+struct file *vfsub_dentry_open(struct path *path, int flags);
33628+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
acd2b654 33629+struct au_branch;
b912730e 33630+struct vfsub_aopen_args {
acd2b654
AM
33631+ struct file *file;
33632+ unsigned int open_flag;
33633+ umode_t create_mode;
33634+ struct au_branch *br;
b912730e 33635+};
b912730e 33636+int vfsub_atomic_open(struct inode *dir, struct dentry *dentry,
acd2b654 33637+ struct vfsub_aopen_args *args);
1facf9fc 33638+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
b4510431 33639+
febd17d6 33640+struct dentry *vfsub_lookup_one_len_unlocked(const char *name,
758e9dad
AM
33641+ struct path *ppath, int len);
33642+struct dentry *vfsub_lookup_one_len(const char *name, struct path *ppath,
1facf9fc 33643+ int len);
b4510431
AM
33644+
33645+struct vfsub_lkup_one_args {
33646+ struct dentry **errp;
33647+ struct qstr *name;
758e9dad 33648+ struct path *ppath;
b4510431
AM
33649+};
33650+
33651+static inline struct dentry *vfsub_lkup_one(struct qstr *name,
758e9dad 33652+ struct path *ppath)
b4510431 33653+{
758e9dad 33654+ return vfsub_lookup_one_len(name->name, ppath, name->len);
b4510431
AM
33655+}
33656+
33657+void vfsub_call_lkup_one(void *args);
33658+
33659+/* ---------------------------------------------------------------------- */
33660+
33661+static inline int vfsub_mnt_want_write(struct vfsmount *mnt)
33662+{
33663+ int err;
076b876e 33664+
b4510431
AM
33665+ lockdep_off();
33666+ err = mnt_want_write(mnt);
33667+ lockdep_on();
33668+ return err;
33669+}
33670+
33671+static inline void vfsub_mnt_drop_write(struct vfsmount *mnt)
33672+{
33673+ lockdep_off();
33674+ mnt_drop_write(mnt);
33675+ lockdep_on();
33676+}
1facf9fc 33677+
7e9cd9fe 33678+#if 0 /* reserved */
c06a8ce3
AM
33679+static inline void vfsub_mnt_drop_write_file(struct file *file)
33680+{
33681+ lockdep_off();
33682+ mnt_drop_write_file(file);
33683+ lockdep_on();
33684+}
7e9cd9fe 33685+#endif
c06a8ce3 33686+
1facf9fc 33687+/* ---------------------------------------------------------------------- */
33688+
33689+struct au_hinode;
33690+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
33691+ struct dentry *d2, struct au_hinode *hdir2);
33692+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
33693+ struct dentry *d2, struct au_hinode *hdir2);
33694+
537831f9
AM
33695+int vfsub_create(struct inode *dir, struct path *path, int mode,
33696+ bool want_excl);
1facf9fc 33697+int vfsub_symlink(struct inode *dir, struct path *path,
33698+ const char *symname);
33699+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
33700+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
523b37e3 33701+ struct path *path, struct inode **delegated_inode);
1facf9fc 33702+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
523b37e3 33703+ struct inode *hdir, struct path *path,
f2c43d5f 33704+ struct inode **delegated_inode, unsigned int flags);
1facf9fc 33705+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
33706+int vfsub_rmdir(struct inode *dir, struct path *path);
33707+
33708+/* ---------------------------------------------------------------------- */
33709+
33710+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
33711+ loff_t *ppos);
33712+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
33713+ loff_t *ppos);
33714+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
33715+ loff_t *ppos);
33716+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
33717+ loff_t *ppos);
4a4d8108 33718+int vfsub_flush(struct file *file, fl_owner_t id);
392086de
AM
33719+int vfsub_iterate_dir(struct file *file, struct dir_context *ctx);
33720+
c06a8ce3
AM
33721+static inline loff_t vfsub_f_size_read(struct file *file)
33722+{
33723+ return i_size_read(file_inode(file));
33724+}
33725+
4a4d8108
AM
33726+static inline unsigned int vfsub_file_flags(struct file *file)
33727+{
33728+ unsigned int flags;
33729+
33730+ spin_lock(&file->f_lock);
33731+ flags = file->f_flags;
33732+ spin_unlock(&file->f_lock);
33733+
33734+ return flags;
33735+}
1308ab2a 33736+
f0c0a007
AM
33737+static inline int vfsub_file_execed(struct file *file)
33738+{
33739+ /* todo: direct access f_flags */
33740+ return !!(vfsub_file_flags(file) & __FMODE_EXEC);
33741+}
33742+
7e9cd9fe 33743+#if 0 /* reserved */
1facf9fc 33744+static inline void vfsub_file_accessed(struct file *h_file)
33745+{
33746+ file_accessed(h_file);
33747+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
33748+}
7e9cd9fe 33749+#endif
1facf9fc 33750+
79b8bda9 33751+#if 0 /* reserved */
1facf9fc 33752+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
33753+ struct dentry *h_dentry)
33754+{
33755+ struct path h_path = {
33756+ .dentry = h_dentry,
33757+ .mnt = h_mnt
33758+ };
92d182d2 33759+ touch_atime(&h_path);
1facf9fc 33760+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
33761+}
79b8bda9 33762+#endif
1facf9fc 33763+
cd7a4cd9
AM
33764+static inline int vfsub_update_time(struct inode *h_inode,
33765+ struct timespec64 *ts, int flags)
0c3ec466 33766+{
614c9df0 33767+ return inode_update_time(h_inode, ts, flags);
0c3ec466
AM
33768+ /* no vfsub_update_h_iattr() since we don't have struct path */
33769+}
33770+
8cdd5066 33771+#ifdef CONFIG_FS_POSIX_ACL
0b2a12c6
JR
33772+static inline int vfsub_acl_chmod(struct user_namespace *h_userns,
33773+ struct inode *h_inode, umode_t h_mode)
8cdd5066
JR
33774+{
33775+ int err;
33776+
0b2a12c6 33777+ err = posix_acl_chmod(h_userns, h_inode, h_mode);
8cdd5066
JR
33778+ if (err == -EOPNOTSUPP)
33779+ err = 0;
33780+ return err;
33781+}
33782+#else
0b2a12c6
JR
33783+AuStubInt0(vfsub_acl_chmod, struct user_namespace *h_userns,
33784+ struct inode *h_inode, umode_t h_mode);
8cdd5066
JR
33785+#endif
33786+
4a4d8108
AM
33787+long vfsub_splice_to(struct file *in, loff_t *ppos,
33788+ struct pipe_inode_info *pipe, size_t len,
33789+ unsigned int flags);
33790+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
33791+ loff_t *ppos, size_t len, unsigned int flags);
c06a8ce3
AM
33792+
33793+static inline long vfsub_truncate(struct path *path, loff_t length)
33794+{
33795+ long err;
076b876e 33796+
c06a8ce3
AM
33797+ lockdep_off();
33798+ err = vfs_truncate(path, length);
33799+ lockdep_on();
33800+ return err;
33801+}
33802+
4a4d8108
AM
33803+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
33804+ struct file *h_file);
53392da6 33805+int vfsub_fsync(struct file *file, struct path *path, int datasync);
4a4d8108 33806+
521ced18
JR
33807+/*
33808+ * re-use branch fs's ioctl(FICLONE) while aufs itself doesn't support such
33809+ * ioctl.
33810+ */
9f237c51
AM
33811+static inline loff_t vfsub_clone_file_range(struct file *src, struct file *dst,
33812+ loff_t len)
521ced18 33813+{
9f237c51 33814+ loff_t err;
521ced18
JR
33815+
33816+ lockdep_off();
9f237c51 33817+ err = vfs_clone_file_range(src, 0, dst, 0, len, /*remap_flags*/0);
521ced18
JR
33818+ lockdep_on();
33819+
33820+ return err;
33821+}
33822+
33823+/* copy_file_range(2) is a systemcall */
33824+static inline ssize_t vfsub_copy_file_range(struct file *src, loff_t src_pos,
33825+ struct file *dst, loff_t dst_pos,
33826+ size_t len, unsigned int flags)
33827+{
33828+ ssize_t ssz;
33829+
33830+ lockdep_off();
33831+ ssz = vfs_copy_file_range(src, src_pos, dst, dst_pos, len, flags);
33832+ lockdep_on();
33833+
33834+ return ssz;
33835+}
33836+
1facf9fc 33837+/* ---------------------------------------------------------------------- */
33838+
33839+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
33840+{
33841+ loff_t err;
33842+
2cbb1c4b 33843+ lockdep_off();
1facf9fc 33844+ err = vfs_llseek(file, offset, origin);
2cbb1c4b 33845+ lockdep_on();
1facf9fc 33846+ return err;
33847+}
33848+
33849+/* ---------------------------------------------------------------------- */
33850+
4a4d8108
AM
33851+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
33852+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
523b37e3
AM
33853+int vfsub_sio_notify_change(struct path *path, struct iattr *ia,
33854+ struct inode **delegated_inode);
33855+int vfsub_notify_change(struct path *path, struct iattr *ia,
33856+ struct inode **delegated_inode);
33857+int vfsub_unlink(struct inode *dir, struct path *path,
33858+ struct inode **delegated_inode, int force);
4a4d8108 33859+
521ced18
JR
33860+static inline int vfsub_getattr(const struct path *path, struct kstat *st)
33861+{
33862+ return vfs_getattr(path, st, STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT);
33863+}
33864+
c1595e42
JR
33865+/* ---------------------------------------------------------------------- */
33866+
0b2a12c6
JR
33867+static inline int vfsub_setxattr(struct user_namespace *userns,
33868+ struct dentry *dentry, const char *name,
c1595e42
JR
33869+ const void *value, size_t size, int flags)
33870+{
33871+ int err;
33872+
33873+ lockdep_off();
0b2a12c6 33874+ err = vfs_setxattr(userns, dentry, name, value, size, flags);
c1595e42
JR
33875+ lockdep_on();
33876+
33877+ return err;
33878+}
33879+
0b2a12c6
JR
33880+static inline int vfsub_removexattr(struct user_namespace *userns,
33881+ struct dentry *dentry, const char *name)
c1595e42
JR
33882+{
33883+ int err;
33884+
33885+ lockdep_off();
0b2a12c6 33886+ err = vfs_removexattr(userns, dentry, name);
c1595e42
JR
33887+ lockdep_on();
33888+
33889+ return err;
33890+}
33891+
1facf9fc 33892+#endif /* __KERNEL__ */
33893+#endif /* __AUFS_VFSUB_H__ */
7f207e10 33894diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
eca34b5c 33895--- /usr/share/empty/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
319657f6 33896+++ linux/fs/aufs/wbr_policy.c 2021-12-03 15:38:59.939980643 +0100
cd7a4cd9
AM
33897@@ -0,0 +1,830 @@
33898+// SPDX-License-Identifier: GPL-2.0
1facf9fc 33899+/*
6d176551 33900+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 33901+ *
33902+ * This program, aufs is free software; you can redistribute it and/or modify
33903+ * it under the terms of the GNU General Public License as published by
33904+ * the Free Software Foundation; either version 2 of the License, or
33905+ * (at your option) any later version.
dece6358
AM
33906+ *
33907+ * This program is distributed in the hope that it will be useful,
33908+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
33909+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33910+ * GNU General Public License for more details.
33911+ *
33912+ * You should have received a copy of the GNU General Public License
523b37e3 33913+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 33914+ */
33915+
33916+/*
33917+ * policies for selecting one among multiple writable branches
33918+ */
33919+
33920+#include <linux/statfs.h>
33921+#include "aufs.h"
33922+
33923+/* subset of cpup_attr() */
33924+static noinline_for_stack
33925+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
33926+{
33927+ int err, sbits;
33928+ struct iattr ia;
33929+ struct inode *h_isrc;
33930+
5527c038 33931+ h_isrc = d_inode(h_src);
1facf9fc 33932+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
33933+ ia.ia_mode = h_isrc->i_mode;
33934+ ia.ia_uid = h_isrc->i_uid;
33935+ ia.ia_gid = h_isrc->i_gid;
33936+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
5527c038 33937+ au_cpup_attr_flags(d_inode(h_path->dentry), h_isrc->i_flags);
523b37e3
AM
33938+ /* no delegation since it is just created */
33939+ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL);
1facf9fc 33940+
33941+ /* is this nfs only? */
33942+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
33943+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
33944+ ia.ia_mode = h_isrc->i_mode;
523b37e3 33945+ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL);
1facf9fc 33946+ }
33947+
33948+ return err;
33949+}
33950+
33951+#define AuCpdown_PARENT_OPQ 1
33952+#define AuCpdown_WHED (1 << 1)
33953+#define AuCpdown_MADE_DIR (1 << 2)
33954+#define AuCpdown_DIROPQ (1 << 3)
33955+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
7f207e10
AM
33956+#define au_fset_cpdown(flags, name) \
33957+ do { (flags) |= AuCpdown_##name; } while (0)
33958+#define au_fclr_cpdown(flags, name) \
33959+ do { (flags) &= ~AuCpdown_##name; } while (0)
1facf9fc 33960+
1facf9fc 33961+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
c2b27bf2 33962+ unsigned int *flags)
1facf9fc 33963+{
33964+ int err;
33965+ struct dentry *opq_dentry;
33966+
33967+ opq_dentry = au_diropq_create(dentry, bdst);
33968+ err = PTR_ERR(opq_dentry);
33969+ if (IS_ERR(opq_dentry))
33970+ goto out;
33971+ dput(opq_dentry);
c2b27bf2 33972+ au_fset_cpdown(*flags, DIROPQ);
1facf9fc 33973+
4f0767ce 33974+out:
1facf9fc 33975+ return err;
33976+}
33977+
33978+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
33979+ struct inode *dir, aufs_bindex_t bdst)
33980+{
33981+ int err;
33982+ struct path h_path;
33983+ struct au_branch *br;
33984+
33985+ br = au_sbr(dentry->d_sb, bdst);
33986+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
33987+ err = PTR_ERR(h_path.dentry);
33988+ if (IS_ERR(h_path.dentry))
33989+ goto out;
33990+
33991+ err = 0;
5527c038 33992+ if (d_is_positive(h_path.dentry)) {
86dc4139 33993+ h_path.mnt = au_br_mnt(br);
1facf9fc 33994+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
33995+ dentry);
33996+ }
33997+ dput(h_path.dentry);
33998+
4f0767ce 33999+out:
1facf9fc 34000+ return err;
34001+}
34002+
34003+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 34004+ struct au_pin *pin,
1facf9fc 34005+ struct dentry *h_parent, void *arg)
34006+{
34007+ int err, rerr;
5afbbe0d 34008+ aufs_bindex_t bopq, btop;
1facf9fc 34009+ struct path h_path;
34010+ struct dentry *parent;
34011+ struct inode *h_dir, *h_inode, *inode, *dir;
c2b27bf2 34012+ unsigned int *flags = arg;
1facf9fc 34013+
5afbbe0d 34014+ btop = au_dbtop(dentry);
1facf9fc 34015+ /* dentry is di-locked */
34016+ parent = dget_parent(dentry);
5527c038
JR
34017+ dir = d_inode(parent);
34018+ h_dir = d_inode(h_parent);
1facf9fc 34019+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
34020+ IMustLock(h_dir);
34021+
86dc4139 34022+ err = au_lkup_neg(dentry, bdst, /*wh*/0);
1facf9fc 34023+ if (unlikely(err < 0))
34024+ goto out;
34025+ h_path.dentry = au_h_dptr(dentry, bdst);
34026+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
cd7a4cd9 34027+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path, 0755);
1facf9fc 34028+ if (unlikely(err))
34029+ goto out_put;
c2b27bf2 34030+ au_fset_cpdown(*flags, MADE_DIR);
1facf9fc 34031+
1facf9fc 34032+ bopq = au_dbdiropq(dentry);
c2b27bf2
AM
34033+ au_fclr_cpdown(*flags, WHED);
34034+ au_fclr_cpdown(*flags, DIROPQ);
1facf9fc 34035+ if (au_dbwh(dentry) == bdst)
c2b27bf2
AM
34036+ au_fset_cpdown(*flags, WHED);
34037+ if (!au_ftest_cpdown(*flags, PARENT_OPQ) && bopq <= bdst)
34038+ au_fset_cpdown(*flags, PARENT_OPQ);
5527c038 34039+ h_inode = d_inode(h_path.dentry);
febd17d6 34040+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
c2b27bf2
AM
34041+ if (au_ftest_cpdown(*flags, WHED)) {
34042+ err = au_cpdown_dir_opq(dentry, bdst, flags);
1facf9fc 34043+ if (unlikely(err)) {
febd17d6 34044+ inode_unlock(h_inode);
1facf9fc 34045+ goto out_dir;
34046+ }
34047+ }
34048+
5afbbe0d 34049+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, btop));
febd17d6 34050+ inode_unlock(h_inode);
1facf9fc 34051+ if (unlikely(err))
34052+ goto out_opq;
34053+
c2b27bf2 34054+ if (au_ftest_cpdown(*flags, WHED)) {
1facf9fc 34055+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
34056+ if (unlikely(err))
34057+ goto out_opq;
34058+ }
34059+
5527c038 34060+ inode = d_inode(dentry);
5afbbe0d
AM
34061+ if (au_ibbot(inode) < bdst)
34062+ au_set_ibbot(inode, bdst);
1facf9fc 34063+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
34064+ au_hi_flags(inode, /*isdir*/1));
076b876e 34065+ au_fhsm_wrote(dentry->d_sb, bdst, /*force*/0);
1facf9fc 34066+ goto out; /* success */
34067+
34068+ /* revert */
4f0767ce 34069+out_opq:
c2b27bf2 34070+ if (au_ftest_cpdown(*flags, DIROPQ)) {
febd17d6 34071+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
1facf9fc 34072+ rerr = au_diropq_remove(dentry, bdst);
febd17d6 34073+ inode_unlock(h_inode);
1facf9fc 34074+ if (unlikely(rerr)) {
523b37e3
AM
34075+ AuIOErr("failed removing diropq for %pd b%d (%d)\n",
34076+ dentry, bdst, rerr);
1facf9fc 34077+ err = -EIO;
34078+ goto out;
34079+ }
34080+ }
4f0767ce 34081+out_dir:
c2b27bf2 34082+ if (au_ftest_cpdown(*flags, MADE_DIR)) {
1facf9fc 34083+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
34084+ if (unlikely(rerr)) {
523b37e3
AM
34085+ AuIOErr("failed removing %pd b%d (%d)\n",
34086+ dentry, bdst, rerr);
1facf9fc 34087+ err = -EIO;
34088+ }
34089+ }
4f0767ce 34090+out_put:
1facf9fc 34091+ au_set_h_dptr(dentry, bdst, NULL);
5afbbe0d
AM
34092+ if (au_dbbot(dentry) == bdst)
34093+ au_update_dbbot(dentry);
4f0767ce 34094+out:
1facf9fc 34095+ dput(parent);
34096+ return err;
34097+}
34098+
34099+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
34100+{
34101+ int err;
c2b27bf2 34102+ unsigned int flags;
1facf9fc 34103+
c2b27bf2
AM
34104+ flags = 0;
34105+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &flags);
1facf9fc 34106+
34107+ return err;
34108+}
34109+
34110+/* ---------------------------------------------------------------------- */
34111+
34112+/* policies for create */
34113+
c2b27bf2 34114+int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
4a4d8108
AM
34115+{
34116+ int err, i, j, ndentry;
34117+ aufs_bindex_t bopq;
34118+ struct au_dcsub_pages dpages;
34119+ struct au_dpage *dpage;
34120+ struct dentry **dentries, *parent, *d;
34121+
34122+ err = au_dpages_init(&dpages, GFP_NOFS);
34123+ if (unlikely(err))
34124+ goto out;
34125+ parent = dget_parent(dentry);
027c5e7a 34126+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0);
4a4d8108
AM
34127+ if (unlikely(err))
34128+ goto out_free;
34129+
34130+ err = bindex;
34131+ for (i = 0; i < dpages.ndpage; i++) {
34132+ dpage = dpages.dpages + i;
34133+ dentries = dpage->dentries;
34134+ ndentry = dpage->ndentry;
34135+ for (j = 0; j < ndentry; j++) {
34136+ d = dentries[j];
34137+ di_read_lock_parent2(d, !AuLock_IR);
34138+ bopq = au_dbdiropq(d);
34139+ di_read_unlock(d, !AuLock_IR);
34140+ if (bopq >= 0 && bopq < err)
34141+ err = bopq;
34142+ }
34143+ }
34144+
34145+out_free:
34146+ dput(parent);
34147+ au_dpages_free(&dpages);
34148+out:
34149+ return err;
34150+}
34151+
1facf9fc 34152+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
34153+{
34154+ for (; bindex >= 0; bindex--)
34155+ if (!au_br_rdonly(au_sbr(sb, bindex)))
34156+ return bindex;
34157+ return -EROFS;
34158+}
34159+
34160+/* top down parent */
392086de
AM
34161+static int au_wbr_create_tdp(struct dentry *dentry,
34162+ unsigned int flags __maybe_unused)
1facf9fc 34163+{
34164+ int err;
5afbbe0d 34165+ aufs_bindex_t btop, bindex;
1facf9fc 34166+ struct super_block *sb;
34167+ struct dentry *parent, *h_parent;
34168+
34169+ sb = dentry->d_sb;
5afbbe0d
AM
34170+ btop = au_dbtop(dentry);
34171+ err = btop;
34172+ if (!au_br_rdonly(au_sbr(sb, btop)))
1facf9fc 34173+ goto out;
34174+
34175+ err = -EROFS;
34176+ parent = dget_parent(dentry);
5afbbe0d 34177+ for (bindex = au_dbtop(parent); bindex < btop; bindex++) {
1facf9fc 34178+ h_parent = au_h_dptr(parent, bindex);
5527c038 34179+ if (!h_parent || d_is_negative(h_parent))
1facf9fc 34180+ continue;
34181+
34182+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
34183+ err = bindex;
34184+ break;
34185+ }
34186+ }
34187+ dput(parent);
34188+
34189+ /* bottom up here */
4a4d8108 34190+ if (unlikely(err < 0)) {
5afbbe0d 34191+ err = au_wbr_bu(sb, btop - 1);
4a4d8108
AM
34192+ if (err >= 0)
34193+ err = au_wbr_nonopq(dentry, err);
34194+ }
1facf9fc 34195+
4f0767ce 34196+out:
1facf9fc 34197+ AuDbg("b%d\n", err);
34198+ return err;
34199+}
34200+
34201+/* ---------------------------------------------------------------------- */
34202+
34203+/* an exception for the policy other than tdp */
34204+static int au_wbr_create_exp(struct dentry *dentry)
34205+{
34206+ int err;
34207+ aufs_bindex_t bwh, bdiropq;
34208+ struct dentry *parent;
34209+
34210+ err = -1;
34211+ bwh = au_dbwh(dentry);
34212+ parent = dget_parent(dentry);
34213+ bdiropq = au_dbdiropq(parent);
34214+ if (bwh >= 0) {
34215+ if (bdiropq >= 0)
34216+ err = min(bdiropq, bwh);
34217+ else
34218+ err = bwh;
34219+ AuDbg("%d\n", err);
34220+ } else if (bdiropq >= 0) {
34221+ err = bdiropq;
34222+ AuDbg("%d\n", err);
34223+ }
34224+ dput(parent);
34225+
4a4d8108
AM
34226+ if (err >= 0)
34227+ err = au_wbr_nonopq(dentry, err);
34228+
1facf9fc 34229+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
34230+ err = -1;
34231+
34232+ AuDbg("%d\n", err);
34233+ return err;
34234+}
34235+
34236+/* ---------------------------------------------------------------------- */
34237+
34238+/* round robin */
34239+static int au_wbr_create_init_rr(struct super_block *sb)
34240+{
34241+ int err;
34242+
5afbbe0d 34243+ err = au_wbr_bu(sb, au_sbbot(sb));
1facf9fc 34244+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 34245+ /* smp_mb(); */
1facf9fc 34246+
34247+ AuDbg("b%d\n", err);
34248+ return err;
34249+}
34250+
392086de 34251+static int au_wbr_create_rr(struct dentry *dentry, unsigned int flags)
1facf9fc 34252+{
34253+ int err, nbr;
34254+ unsigned int u;
5afbbe0d 34255+ aufs_bindex_t bindex, bbot;
1facf9fc 34256+ struct super_block *sb;
34257+ atomic_t *next;
34258+
34259+ err = au_wbr_create_exp(dentry);
34260+ if (err >= 0)
34261+ goto out;
34262+
34263+ sb = dentry->d_sb;
34264+ next = &au_sbi(sb)->si_wbr_rr_next;
5afbbe0d
AM
34265+ bbot = au_sbbot(sb);
34266+ nbr = bbot + 1;
34267+ for (bindex = 0; bindex <= bbot; bindex++) {
392086de 34268+ if (!au_ftest_wbr(flags, DIR)) {
1facf9fc 34269+ err = atomic_dec_return(next) + 1;
34270+ /* modulo for 0 is meaningless */
34271+ if (unlikely(!err))
34272+ err = atomic_dec_return(next) + 1;
34273+ } else
34274+ err = atomic_read(next);
34275+ AuDbg("%d\n", err);
34276+ u = err;
34277+ err = u % nbr;
34278+ AuDbg("%d\n", err);
34279+ if (!au_br_rdonly(au_sbr(sb, err)))
34280+ break;
34281+ err = -EROFS;
34282+ }
34283+
4a4d8108
AM
34284+ if (err >= 0)
34285+ err = au_wbr_nonopq(dentry, err);
34286+
4f0767ce 34287+out:
1facf9fc 34288+ AuDbg("%d\n", err);
34289+ return err;
34290+}
34291+
34292+/* ---------------------------------------------------------------------- */
34293+
34294+/* most free space */
392086de 34295+static void au_mfs(struct dentry *dentry, struct dentry *parent)
1facf9fc 34296+{
34297+ struct super_block *sb;
34298+ struct au_branch *br;
34299+ struct au_wbr_mfs *mfs;
392086de 34300+ struct dentry *h_parent;
5afbbe0d 34301+ aufs_bindex_t bindex, bbot;
1facf9fc 34302+ int err;
34303+ unsigned long long b, bavail;
7f207e10 34304+ struct path h_path;
1facf9fc 34305+ /* reduce the stack usage */
34306+ struct kstatfs *st;
34307+
34308+ st = kmalloc(sizeof(*st), GFP_NOFS);
34309+ if (unlikely(!st)) {
34310+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
34311+ return;
34312+ }
34313+
34314+ bavail = 0;
34315+ sb = dentry->d_sb;
34316+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 34317+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 34318+ mfs->mfs_bindex = -EROFS;
34319+ mfs->mfsrr_bytes = 0;
392086de
AM
34320+ if (!parent) {
34321+ bindex = 0;
5afbbe0d 34322+ bbot = au_sbbot(sb);
392086de 34323+ } else {
5afbbe0d
AM
34324+ bindex = au_dbtop(parent);
34325+ bbot = au_dbtaildir(parent);
392086de
AM
34326+ }
34327+
5afbbe0d 34328+ for (; bindex <= bbot; bindex++) {
392086de
AM
34329+ if (parent) {
34330+ h_parent = au_h_dptr(parent, bindex);
5527c038 34331+ if (!h_parent || d_is_negative(h_parent))
392086de
AM
34332+ continue;
34333+ }
1facf9fc 34334+ br = au_sbr(sb, bindex);
34335+ if (au_br_rdonly(br))
34336+ continue;
34337+
34338+ /* sb->s_root for NFS is unreliable */
86dc4139 34339+ h_path.mnt = au_br_mnt(br);
7f207e10
AM
34340+ h_path.dentry = h_path.mnt->mnt_root;
34341+ err = vfs_statfs(&h_path, st);
1facf9fc 34342+ if (unlikely(err)) {
34343+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
34344+ continue;
34345+ }
34346+
34347+ /* when the available size is equal, select the lower one */
34348+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
34349+ || sizeof(b) < sizeof(st->f_bsize));
34350+ b = st->f_bavail * st->f_bsize;
34351+ br->br_wbr->wbr_bytes = b;
34352+ if (b >= bavail) {
34353+ bavail = b;
34354+ mfs->mfs_bindex = bindex;
34355+ mfs->mfs_jiffy = jiffies;
34356+ }
34357+ }
34358+
34359+ mfs->mfsrr_bytes = bavail;
34360+ AuDbg("b%d\n", mfs->mfs_bindex);
9f237c51 34361+ au_kfree_rcu(st);
1facf9fc 34362+}
34363+
392086de 34364+static int au_wbr_create_mfs(struct dentry *dentry, unsigned int flags)
1facf9fc 34365+{
34366+ int err;
392086de 34367+ struct dentry *parent;
1facf9fc 34368+ struct super_block *sb;
34369+ struct au_wbr_mfs *mfs;
34370+
34371+ err = au_wbr_create_exp(dentry);
34372+ if (err >= 0)
34373+ goto out;
34374+
34375+ sb = dentry->d_sb;
392086de
AM
34376+ parent = NULL;
34377+ if (au_ftest_wbr(flags, PARENT))
34378+ parent = dget_parent(dentry);
1facf9fc 34379+ mfs = &au_sbi(sb)->si_wbr_mfs;
34380+ mutex_lock(&mfs->mfs_lock);
34381+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
34382+ || mfs->mfs_bindex < 0
34383+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
392086de 34384+ au_mfs(dentry, parent);
1facf9fc 34385+ mutex_unlock(&mfs->mfs_lock);
34386+ err = mfs->mfs_bindex;
392086de 34387+ dput(parent);
1facf9fc 34388+
4a4d8108
AM
34389+ if (err >= 0)
34390+ err = au_wbr_nonopq(dentry, err);
34391+
4f0767ce 34392+out:
1facf9fc 34393+ AuDbg("b%d\n", err);
34394+ return err;
34395+}
34396+
34397+static int au_wbr_create_init_mfs(struct super_block *sb)
34398+{
34399+ struct au_wbr_mfs *mfs;
34400+
34401+ mfs = &au_sbi(sb)->si_wbr_mfs;
34402+ mutex_init(&mfs->mfs_lock);
34403+ mfs->mfs_jiffy = 0;
34404+ mfs->mfs_bindex = -EROFS;
34405+
34406+ return 0;
34407+}
34408+
34409+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
34410+{
34411+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
34412+ return 0;
34413+}
34414+
34415+/* ---------------------------------------------------------------------- */
34416+
f2c43d5f
AM
34417+/* top down regardless parent, and then mfs */
34418+static int au_wbr_create_tdmfs(struct dentry *dentry,
34419+ unsigned int flags __maybe_unused)
34420+{
34421+ int err;
34422+ aufs_bindex_t bwh, btail, bindex, bfound, bmfs;
34423+ unsigned long long watermark;
34424+ struct super_block *sb;
34425+ struct au_wbr_mfs *mfs;
34426+ struct au_branch *br;
34427+ struct dentry *parent;
34428+
34429+ sb = dentry->d_sb;
34430+ mfs = &au_sbi(sb)->si_wbr_mfs;
34431+ mutex_lock(&mfs->mfs_lock);
34432+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
34433+ || mfs->mfs_bindex < 0)
34434+ au_mfs(dentry, /*parent*/NULL);
34435+ watermark = mfs->mfsrr_watermark;
34436+ bmfs = mfs->mfs_bindex;
34437+ mutex_unlock(&mfs->mfs_lock);
34438+
34439+ /* another style of au_wbr_create_exp() */
34440+ bwh = au_dbwh(dentry);
34441+ parent = dget_parent(dentry);
34442+ btail = au_dbtaildir(parent);
34443+ if (bwh >= 0 && bwh < btail)
34444+ btail = bwh;
34445+
34446+ err = au_wbr_nonopq(dentry, btail);
34447+ if (unlikely(err < 0))
34448+ goto out;
34449+ btail = err;
34450+ bfound = -1;
34451+ for (bindex = 0; bindex <= btail; bindex++) {
34452+ br = au_sbr(sb, bindex);
34453+ if (au_br_rdonly(br))
34454+ continue;
34455+ if (br->br_wbr->wbr_bytes > watermark) {
34456+ bfound = bindex;
34457+ break;
34458+ }
34459+ }
34460+ err = bfound;
34461+ if (err < 0)
34462+ err = bmfs;
34463+
34464+out:
34465+ dput(parent);
34466+ AuDbg("b%d\n", err);
34467+ return err;
34468+}
34469+
34470+/* ---------------------------------------------------------------------- */
34471+
1facf9fc 34472+/* most free space and then round robin */
392086de 34473+static int au_wbr_create_mfsrr(struct dentry *dentry, unsigned int flags)
1facf9fc 34474+{
34475+ int err;
34476+ struct au_wbr_mfs *mfs;
34477+
392086de 34478+ err = au_wbr_create_mfs(dentry, flags);
1facf9fc 34479+ if (err >= 0) {
34480+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 34481+ mutex_lock(&mfs->mfs_lock);
1facf9fc 34482+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
392086de 34483+ err = au_wbr_create_rr(dentry, flags);
dece6358 34484+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 34485+ }
34486+
34487+ AuDbg("b%d\n", err);
34488+ return err;
34489+}
34490+
34491+static int au_wbr_create_init_mfsrr(struct super_block *sb)
34492+{
34493+ int err;
34494+
34495+ au_wbr_create_init_mfs(sb); /* ignore */
34496+ err = au_wbr_create_init_rr(sb);
34497+
34498+ return err;
34499+}
34500+
34501+/* ---------------------------------------------------------------------- */
34502+
34503+/* top down parent and most free space */
392086de 34504+static int au_wbr_create_pmfs(struct dentry *dentry, unsigned int flags)
1facf9fc 34505+{
34506+ int err, e2;
34507+ unsigned long long b;
5afbbe0d 34508+ aufs_bindex_t bindex, btop, bbot;
1facf9fc 34509+ struct super_block *sb;
34510+ struct dentry *parent, *h_parent;
34511+ struct au_branch *br;
34512+
392086de 34513+ err = au_wbr_create_tdp(dentry, flags);
1facf9fc 34514+ if (unlikely(err < 0))
34515+ goto out;
34516+ parent = dget_parent(dentry);
5afbbe0d
AM
34517+ btop = au_dbtop(parent);
34518+ bbot = au_dbtaildir(parent);
34519+ if (btop == bbot)
1facf9fc 34520+ goto out_parent; /* success */
34521+
392086de 34522+ e2 = au_wbr_create_mfs(dentry, flags);
1facf9fc 34523+ if (e2 < 0)
34524+ goto out_parent; /* success */
34525+
34526+ /* when the available size is equal, select upper one */
34527+ sb = dentry->d_sb;
34528+ br = au_sbr(sb, err);
34529+ b = br->br_wbr->wbr_bytes;
34530+ AuDbg("b%d, %llu\n", err, b);
34531+
5afbbe0d 34532+ for (bindex = btop; bindex <= bbot; bindex++) {
1facf9fc 34533+ h_parent = au_h_dptr(parent, bindex);
5527c038 34534+ if (!h_parent || d_is_negative(h_parent))
1facf9fc 34535+ continue;
34536+
34537+ br = au_sbr(sb, bindex);
34538+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
34539+ b = br->br_wbr->wbr_bytes;
34540+ err = bindex;
34541+ AuDbg("b%d, %llu\n", err, b);
34542+ }
34543+ }
34544+
4a4d8108
AM
34545+ if (err >= 0)
34546+ err = au_wbr_nonopq(dentry, err);
34547+
4f0767ce 34548+out_parent:
1facf9fc 34549+ dput(parent);
4f0767ce 34550+out:
1facf9fc 34551+ AuDbg("b%d\n", err);
34552+ return err;
34553+}
34554+
34555+/* ---------------------------------------------------------------------- */
34556+
392086de
AM
34557+/*
34558+ * - top down parent
34559+ * - most free space with parent
34560+ * - most free space round-robin regardless parent
34561+ */
34562+static int au_wbr_create_pmfsrr(struct dentry *dentry, unsigned int flags)
34563+{
34564+ int err;
34565+ unsigned long long watermark;
34566+ struct super_block *sb;
34567+ struct au_branch *br;
34568+ struct au_wbr_mfs *mfs;
34569+
34570+ err = au_wbr_create_pmfs(dentry, flags | AuWbr_PARENT);
34571+ if (unlikely(err < 0))
34572+ goto out;
34573+
34574+ sb = dentry->d_sb;
34575+ br = au_sbr(sb, err);
34576+ mfs = &au_sbi(sb)->si_wbr_mfs;
34577+ mutex_lock(&mfs->mfs_lock);
34578+ watermark = mfs->mfsrr_watermark;
34579+ mutex_unlock(&mfs->mfs_lock);
34580+ if (br->br_wbr->wbr_bytes < watermark)
34581+ /* regardless the parent dir */
34582+ err = au_wbr_create_mfsrr(dentry, flags);
34583+
34584+out:
34585+ AuDbg("b%d\n", err);
34586+ return err;
34587+}
34588+
34589+/* ---------------------------------------------------------------------- */
34590+
1facf9fc 34591+/* policies for copyup */
34592+
34593+/* top down parent */
34594+static int au_wbr_copyup_tdp(struct dentry *dentry)
34595+{
392086de 34596+ return au_wbr_create_tdp(dentry, /*flags, anything is ok*/0);
1facf9fc 34597+}
34598+
34599+/* bottom up parent */
34600+static int au_wbr_copyup_bup(struct dentry *dentry)
34601+{
34602+ int err;
5afbbe0d 34603+ aufs_bindex_t bindex, btop;
1facf9fc 34604+ struct dentry *parent, *h_parent;
34605+ struct super_block *sb;
34606+
34607+ err = -EROFS;
34608+ sb = dentry->d_sb;
34609+ parent = dget_parent(dentry);
5afbbe0d
AM
34610+ btop = au_dbtop(parent);
34611+ for (bindex = au_dbtop(dentry); bindex >= btop; bindex--) {
1facf9fc 34612+ h_parent = au_h_dptr(parent, bindex);
5527c038 34613+ if (!h_parent || d_is_negative(h_parent))
1facf9fc 34614+ continue;
34615+
34616+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
34617+ err = bindex;
34618+ break;
34619+ }
34620+ }
34621+ dput(parent);
34622+
34623+ /* bottom up here */
34624+ if (unlikely(err < 0))
5afbbe0d 34625+ err = au_wbr_bu(sb, btop - 1);
1facf9fc 34626+
34627+ AuDbg("b%d\n", err);
34628+ return err;
34629+}
34630+
34631+/* bottom up */
5afbbe0d 34632+int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop)
1facf9fc 34633+{
34634+ int err;
34635+
5afbbe0d 34636+ err = au_wbr_bu(dentry->d_sb, btop);
4a4d8108 34637+ AuDbg("b%d\n", err);
5afbbe0d 34638+ if (err > btop)
4a4d8108 34639+ err = au_wbr_nonopq(dentry, err);
1facf9fc 34640+
34641+ AuDbg("b%d\n", err);
34642+ return err;
34643+}
34644+
076b876e
AM
34645+static int au_wbr_copyup_bu(struct dentry *dentry)
34646+{
34647+ int err;
5afbbe0d 34648+ aufs_bindex_t btop;
076b876e 34649+
5afbbe0d
AM
34650+ btop = au_dbtop(dentry);
34651+ err = au_wbr_do_copyup_bu(dentry, btop);
076b876e
AM
34652+ return err;
34653+}
34654+
1facf9fc 34655+/* ---------------------------------------------------------------------- */
34656+
34657+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
34658+ [AuWbrCopyup_TDP] = {
34659+ .copyup = au_wbr_copyup_tdp
34660+ },
34661+ [AuWbrCopyup_BUP] = {
34662+ .copyup = au_wbr_copyup_bup
34663+ },
34664+ [AuWbrCopyup_BU] = {
34665+ .copyup = au_wbr_copyup_bu
34666+ }
34667+};
34668+
34669+struct au_wbr_create_operations au_wbr_create_ops[] = {
34670+ [AuWbrCreate_TDP] = {
34671+ .create = au_wbr_create_tdp
34672+ },
34673+ [AuWbrCreate_RR] = {
34674+ .create = au_wbr_create_rr,
34675+ .init = au_wbr_create_init_rr
34676+ },
34677+ [AuWbrCreate_MFS] = {
34678+ .create = au_wbr_create_mfs,
34679+ .init = au_wbr_create_init_mfs,
34680+ .fin = au_wbr_create_fin_mfs
34681+ },
34682+ [AuWbrCreate_MFSV] = {
34683+ .create = au_wbr_create_mfs,
34684+ .init = au_wbr_create_init_mfs,
34685+ .fin = au_wbr_create_fin_mfs
34686+ },
34687+ [AuWbrCreate_MFSRR] = {
34688+ .create = au_wbr_create_mfsrr,
34689+ .init = au_wbr_create_init_mfsrr,
34690+ .fin = au_wbr_create_fin_mfs
34691+ },
34692+ [AuWbrCreate_MFSRRV] = {
34693+ .create = au_wbr_create_mfsrr,
34694+ .init = au_wbr_create_init_mfsrr,
34695+ .fin = au_wbr_create_fin_mfs
34696+ },
f2c43d5f
AM
34697+ [AuWbrCreate_TDMFS] = {
34698+ .create = au_wbr_create_tdmfs,
34699+ .init = au_wbr_create_init_mfs,
34700+ .fin = au_wbr_create_fin_mfs
34701+ },
34702+ [AuWbrCreate_TDMFSV] = {
34703+ .create = au_wbr_create_tdmfs,
34704+ .init = au_wbr_create_init_mfs,
34705+ .fin = au_wbr_create_fin_mfs
34706+ },
1facf9fc 34707+ [AuWbrCreate_PMFS] = {
34708+ .create = au_wbr_create_pmfs,
34709+ .init = au_wbr_create_init_mfs,
34710+ .fin = au_wbr_create_fin_mfs
34711+ },
34712+ [AuWbrCreate_PMFSV] = {
34713+ .create = au_wbr_create_pmfs,
34714+ .init = au_wbr_create_init_mfs,
34715+ .fin = au_wbr_create_fin_mfs
392086de
AM
34716+ },
34717+ [AuWbrCreate_PMFSRR] = {
34718+ .create = au_wbr_create_pmfsrr,
34719+ .init = au_wbr_create_init_mfsrr,
34720+ .fin = au_wbr_create_fin_mfs
34721+ },
34722+ [AuWbrCreate_PMFSRRV] = {
34723+ .create = au_wbr_create_pmfsrr,
34724+ .init = au_wbr_create_init_mfsrr,
34725+ .fin = au_wbr_create_fin_mfs
1facf9fc 34726+ }
34727+};
7f207e10 34728diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
eca34b5c 34729--- /usr/share/empty/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
319657f6 34730+++ linux/fs/aufs/whout.c 2021-12-03 15:40:58.236647297 +0100
758e9dad 34731@@ -0,0 +1,1072 @@
cd7a4cd9 34732+// SPDX-License-Identifier: GPL-2.0
1facf9fc 34733+/*
6d176551 34734+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 34735+ *
34736+ * This program, aufs is free software; you can redistribute it and/or modify
34737+ * it under the terms of the GNU General Public License as published by
34738+ * the Free Software Foundation; either version 2 of the License, or
34739+ * (at your option) any later version.
dece6358
AM
34740+ *
34741+ * This program is distributed in the hope that it will be useful,
34742+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
34743+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34744+ * GNU General Public License for more details.
34745+ *
34746+ * You should have received a copy of the GNU General Public License
523b37e3 34747+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 34748+ */
34749+
34750+/*
34751+ * whiteout for logical deletion and opaque directory
34752+ */
34753+
1facf9fc 34754+#include "aufs.h"
34755+
cd7a4cd9 34756+#define WH_MASK 0444
1facf9fc 34757+
34758+/*
34759+ * If a directory contains this file, then it is opaque. We start with the
34760+ * .wh. flag so that it is blocked by lookup.
34761+ */
0c3ec466
AM
34762+static struct qstr diropq_name = QSTR_INIT(AUFS_WH_DIROPQ,
34763+ sizeof(AUFS_WH_DIROPQ) - 1);
1facf9fc 34764+
34765+/*
34766+ * generate whiteout name, which is NOT terminated by NULL.
34767+ * @name: original d_name.name
34768+ * @len: original d_name.len
34769+ * @wh: whiteout qstr
34770+ * returns zero when succeeds, otherwise error.
34771+ * succeeded value as wh->name should be freed by kfree().
34772+ */
34773+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
34774+{
34775+ char *p;
34776+
34777+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
34778+ return -ENAMETOOLONG;
34779+
34780+ wh->len = name->len + AUFS_WH_PFX_LEN;
34781+ p = kmalloc(wh->len, GFP_NOFS);
34782+ wh->name = p;
34783+ if (p) {
34784+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
34785+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
34786+ /* smp_mb(); */
34787+ return 0;
34788+ }
34789+ return -ENOMEM;
34790+}
34791+
34792+/* ---------------------------------------------------------------------- */
34793+
34794+/*
758e9dad 34795+ * test if the @wh_name exists under @h_ppath.
1facf9fc 34796+ * @try_sio specifies the necessary of super-io.
34797+ */
758e9dad 34798+int au_wh_test(struct user_namespace *h_userns, struct path *h_ppath,
0b2a12c6 34799+ struct qstr *wh_name, int try_sio)
1facf9fc 34800+{
34801+ int err;
34802+ struct dentry *wh_dentry;
1facf9fc 34803+
1facf9fc 34804+ if (!try_sio)
758e9dad 34805+ wh_dentry = vfsub_lkup_one(wh_name, h_ppath);
1facf9fc 34806+ else
758e9dad 34807+ wh_dentry = au_sio_lkup_one(h_userns, wh_name, h_ppath);
1facf9fc 34808+ err = PTR_ERR(wh_dentry);
2000de60
JR
34809+ if (IS_ERR(wh_dentry)) {
34810+ if (err == -ENAMETOOLONG)
34811+ err = 0;
1facf9fc 34812+ goto out;
2000de60 34813+ }
1facf9fc 34814+
34815+ err = 0;
5527c038 34816+ if (d_is_negative(wh_dentry))
1facf9fc 34817+ goto out_wh; /* success */
34818+
34819+ err = 1;
7e9cd9fe 34820+ if (d_is_reg(wh_dentry))
1facf9fc 34821+ goto out_wh; /* success */
34822+
34823+ err = -EIO;
523b37e3 34824+ AuIOErr("%pd Invalid whiteout entry type 0%o.\n",
5527c038 34825+ wh_dentry, d_inode(wh_dentry)->i_mode);
1facf9fc 34826+
4f0767ce 34827+out_wh:
1facf9fc 34828+ dput(wh_dentry);
4f0767ce 34829+out:
1facf9fc 34830+ return err;
34831+}
34832+
34833+/*
758e9dad 34834+ * test if the @h_path->dentry sets opaque or not.
1facf9fc 34835+ */
758e9dad 34836+int au_diropq_test(struct user_namespace *h_userns, struct path *h_path)
1facf9fc 34837+{
34838+ int err;
34839+ struct inode *h_dir;
34840+
758e9dad
AM
34841+ h_dir = d_inode(h_path->dentry);
34842+ err = au_wh_test(h_userns, h_path, &diropq_name,
0b2a12c6 34843+ au_test_h_perm_sio(h_userns, h_dir, MAY_EXEC));
1facf9fc 34844+ return err;
34845+}
34846+
34847+/*
34848+ * returns a negative dentry whose name is unique and temporary.
34849+ */
34850+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
34851+ struct qstr *prefix)
34852+{
1facf9fc 34853+ struct dentry *dentry;
34854+ int i;
027c5e7a 34855+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1],
4a4d8108 34856+ *name, *p;
027c5e7a 34857+ /* strict atomic_t is unnecessary here */
1facf9fc 34858+ static unsigned short cnt;
34859+ struct qstr qs;
758e9dad 34860+ struct path h_ppath;
0b2a12c6 34861+ struct user_namespace *h_userns;
1facf9fc 34862+
4a4d8108
AM
34863+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
34864+
1facf9fc 34865+ name = defname;
027c5e7a
AM
34866+ qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1;
34867+ if (unlikely(prefix->len > DNAME_INLINE_LEN)) {
1facf9fc 34868+ dentry = ERR_PTR(-ENAMETOOLONG);
4a4d8108 34869+ if (unlikely(qs.len > NAME_MAX))
1facf9fc 34870+ goto out;
34871+ dentry = ERR_PTR(-ENOMEM);
34872+ name = kmalloc(qs.len + 1, GFP_NOFS);
34873+ if (unlikely(!name))
34874+ goto out;
34875+ }
34876+
34877+ /* doubly whiteout-ed */
34878+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
34879+ p = name + AUFS_WH_PFX_LEN * 2;
34880+ memcpy(p, prefix->name, prefix->len);
34881+ p += prefix->len;
34882+ *p++ = '.';
4a4d8108 34883+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
1facf9fc 34884+
758e9dad
AM
34885+ h_ppath.dentry = h_parent;
34886+ h_ppath.mnt = au_br_mnt(br);
0b2a12c6 34887+ h_userns = au_br_userns(br);
1facf9fc 34888+ qs.name = name;
34889+ for (i = 0; i < 3; i++) {
b752ccd1 34890+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
758e9dad 34891+ dentry = au_sio_lkup_one(h_userns, &qs, &h_ppath);
5527c038 34892+ if (IS_ERR(dentry) || d_is_negative(dentry))
1facf9fc 34893+ goto out_name;
34894+ dput(dentry);
34895+ }
0c3ec466 34896+ /* pr_warn("could not get random name\n"); */
1facf9fc 34897+ dentry = ERR_PTR(-EEXIST);
34898+ AuDbg("%.*s\n", AuLNPair(&qs));
34899+ BUG();
34900+
4f0767ce 34901+out_name:
1facf9fc 34902+ if (name != defname)
9f237c51 34903+ au_kfree_try_rcu(name);
4f0767ce 34904+out:
4a4d8108 34905+ AuTraceErrPtr(dentry);
1facf9fc 34906+ return dentry;
1facf9fc 34907+}
34908+
34909+/*
34910+ * rename the @h_dentry on @br to the whiteouted temporary name.
34911+ */
34912+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
34913+{
34914+ int err;
34915+ struct path h_path = {
86dc4139 34916+ .mnt = au_br_mnt(br)
1facf9fc 34917+ };
523b37e3 34918+ struct inode *h_dir, *delegated;
1facf9fc 34919+ struct dentry *h_parent;
34920+
34921+ h_parent = h_dentry->d_parent; /* dir inode is locked */
5527c038 34922+ h_dir = d_inode(h_parent);
1facf9fc 34923+ IMustLock(h_dir);
34924+
34925+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
34926+ err = PTR_ERR(h_path.dentry);
34927+ if (IS_ERR(h_path.dentry))
34928+ goto out;
34929+
34930+ /* under the same dir, no need to lock_rename() */
523b37e3 34931+ delegated = NULL;
f2c43d5f
AM
34932+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path, &delegated,
34933+ /*flags*/0);
1facf9fc 34934+ AuTraceErr(err);
523b37e3
AM
34935+ if (unlikely(err == -EWOULDBLOCK)) {
34936+ pr_warn("cannot retry for NFSv4 delegation"
34937+ " for an internal rename\n");
34938+ iput(delegated);
34939+ }
1facf9fc 34940+ dput(h_path.dentry);
34941+
4f0767ce 34942+out:
4a4d8108 34943+ AuTraceErr(err);
1facf9fc 34944+ return err;
34945+}
34946+
34947+/* ---------------------------------------------------------------------- */
34948+/*
34949+ * functions for removing a whiteout
34950+ */
34951+
34952+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
34953+{
523b37e3
AM
34954+ int err, force;
34955+ struct inode *delegated;
1facf9fc 34956+
34957+ /*
34958+ * forces superio when the dir has a sticky bit.
34959+ * this may be a violation of unix fs semantics.
34960+ */
34961+ force = (h_dir->i_mode & S_ISVTX)
5527c038 34962+ && !uid_eq(current_fsuid(), d_inode(h_path->dentry)->i_uid);
523b37e3
AM
34963+ delegated = NULL;
34964+ err = vfsub_unlink(h_dir, h_path, &delegated, force);
34965+ if (unlikely(err == -EWOULDBLOCK)) {
34966+ pr_warn("cannot retry for NFSv4 delegation"
34967+ " for an internal unlink\n");
34968+ iput(delegated);
34969+ }
34970+ return err;
1facf9fc 34971+}
34972+
34973+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
34974+ struct dentry *dentry)
34975+{
34976+ int err;
34977+
34978+ err = do_unlink_wh(h_dir, h_path);
34979+ if (!err && dentry)
34980+ au_set_dbwh(dentry, -1);
34981+
34982+ return err;
34983+}
34984+
758e9dad 34985+static int unlink_wh_name(struct path *h_ppath, struct qstr *wh)
1facf9fc 34986+{
34987+ int err;
758e9dad 34988+ struct path h_path;
1facf9fc 34989+
34990+ err = 0;
758e9dad 34991+ h_path.dentry = vfsub_lkup_one(wh, h_ppath);
1facf9fc 34992+ if (IS_ERR(h_path.dentry))
34993+ err = PTR_ERR(h_path.dentry);
34994+ else {
758e9dad
AM
34995+ if (d_is_reg(h_path.dentry)) {
34996+ h_path.mnt = h_ppath->mnt;
34997+ err = do_unlink_wh(d_inode(h_ppath->dentry), &h_path);
34998+ }
1facf9fc 34999+ dput(h_path.dentry);
35000+ }
35001+
35002+ return err;
35003+}
35004+
35005+/* ---------------------------------------------------------------------- */
35006+/*
35007+ * initialize/clean whiteout for a branch
35008+ */
35009+
35010+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
35011+ const int isdir)
35012+{
35013+ int err;
523b37e3 35014+ struct inode *delegated;
1facf9fc 35015+
5527c038 35016+ if (d_is_negative(whpath->dentry))
1facf9fc 35017+ return;
35018+
86dc4139
AM
35019+ if (isdir)
35020+ err = vfsub_rmdir(h_dir, whpath);
523b37e3
AM
35021+ else {
35022+ delegated = NULL;
35023+ err = vfsub_unlink(h_dir, whpath, &delegated, /*force*/0);
35024+ if (unlikely(err == -EWOULDBLOCK)) {
35025+ pr_warn("cannot retry for NFSv4 delegation"
35026+ " for an internal unlink\n");
35027+ iput(delegated);
35028+ }
35029+ }
1facf9fc 35030+ if (unlikely(err))
523b37e3
AM
35031+ pr_warn("failed removing %pd (%d), ignored.\n",
35032+ whpath->dentry, err);
1facf9fc 35033+}
35034+
35035+static int test_linkable(struct dentry *h_root)
35036+{
5527c038 35037+ struct inode *h_dir = d_inode(h_root);
1facf9fc 35038+
35039+ if (h_dir->i_op->link)
35040+ return 0;
35041+
523b37e3
AM
35042+ pr_err("%pd (%s) doesn't support link(2), use noplink and rw+nolwh\n",
35043+ h_root, au_sbtype(h_root->d_sb));
43982f53 35044+ return -ENOSYS; /* the branch doesn't have its ->link() */
1facf9fc 35045+}
35046+
35047+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
35048+static int au_whdir(struct inode *h_dir, struct path *path)
35049+{
35050+ int err;
35051+
35052+ err = -EEXIST;
5527c038 35053+ if (d_is_negative(path->dentry)) {
cd7a4cd9 35054+ int mode = 0700;
1facf9fc 35055+
35056+ if (au_test_nfs(path->dentry->d_sb))
cd7a4cd9 35057+ mode |= 0111;
86dc4139 35058+ err = vfsub_mkdir(h_dir, path, mode);
2000de60 35059+ } else if (d_is_dir(path->dentry))
1facf9fc 35060+ err = 0;
35061+ else
523b37e3 35062+ pr_err("unknown %pd exists\n", path->dentry);
1facf9fc 35063+
35064+ return err;
35065+}
35066+
35067+struct au_wh_base {
35068+ const struct qstr *name;
35069+ struct dentry *dentry;
35070+};
35071+
35072+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
35073+ struct path *h_path)
35074+{
35075+ h_path->dentry = base[AuBrWh_BASE].dentry;
35076+ au_wh_clean(h_dir, h_path, /*isdir*/0);
35077+ h_path->dentry = base[AuBrWh_PLINK].dentry;
35078+ au_wh_clean(h_dir, h_path, /*isdir*/1);
35079+ h_path->dentry = base[AuBrWh_ORPH].dentry;
35080+ au_wh_clean(h_dir, h_path, /*isdir*/1);
35081+}
35082+
35083+/*
35084+ * returns tri-state,
c1595e42 35085+ * minus: error, caller should print the message
acd2b654 35086+ * zero: success
c1595e42 35087+ * plus: error, caller should NOT print the message
1facf9fc 35088+ */
35089+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
35090+ int do_plink, struct au_wh_base base[],
35091+ struct path *h_path)
35092+{
35093+ int err;
35094+ struct inode *h_dir;
35095+
5527c038 35096+ h_dir = d_inode(h_root);
1facf9fc 35097+ h_path->dentry = base[AuBrWh_BASE].dentry;
35098+ au_wh_clean(h_dir, h_path, /*isdir*/0);
35099+ h_path->dentry = base[AuBrWh_PLINK].dentry;
35100+ if (do_plink) {
35101+ err = test_linkable(h_root);
35102+ if (unlikely(err)) {
35103+ err = 1;
35104+ goto out;
35105+ }
35106+
35107+ err = au_whdir(h_dir, h_path);
35108+ if (unlikely(err))
35109+ goto out;
35110+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
35111+ } else
35112+ au_wh_clean(h_dir, h_path, /*isdir*/1);
35113+ h_path->dentry = base[AuBrWh_ORPH].dentry;
35114+ err = au_whdir(h_dir, h_path);
35115+ if (unlikely(err))
35116+ goto out;
35117+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
35118+
4f0767ce 35119+out:
1facf9fc 35120+ return err;
35121+}
35122+
35123+/*
35124+ * for the moment, aufs supports the branch filesystem which does not support
35125+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
35126+ * copyup failed. finally, such filesystem will not be used as the writable
35127+ * branch.
35128+ *
35129+ * returns tri-state, see above.
35130+ */
35131+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
35132+ int do_plink, struct au_wh_base base[],
35133+ struct path *h_path)
35134+{
35135+ int err;
35136+ struct inode *h_dir;
35137+
1308ab2a 35138+ WbrWhMustWriteLock(wbr);
35139+
1facf9fc 35140+ err = test_linkable(h_root);
35141+ if (unlikely(err)) {
35142+ err = 1;
35143+ goto out;
35144+ }
35145+
35146+ /*
35147+ * todo: should this create be done in /sbin/mount.aufs helper?
35148+ */
35149+ err = -EEXIST;
5527c038
JR
35150+ h_dir = d_inode(h_root);
35151+ if (d_is_negative(base[AuBrWh_BASE].dentry)) {
86dc4139
AM
35152+ h_path->dentry = base[AuBrWh_BASE].dentry;
35153+ err = vfsub_create(h_dir, h_path, WH_MASK, /*want_excl*/true);
7e9cd9fe 35154+ } else if (d_is_reg(base[AuBrWh_BASE].dentry))
1facf9fc 35155+ err = 0;
35156+ else
523b37e3 35157+ pr_err("unknown %pd2 exists\n", base[AuBrWh_BASE].dentry);
1facf9fc 35158+ if (unlikely(err))
35159+ goto out;
35160+
35161+ h_path->dentry = base[AuBrWh_PLINK].dentry;
35162+ if (do_plink) {
35163+ err = au_whdir(h_dir, h_path);
35164+ if (unlikely(err))
35165+ goto out;
35166+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
35167+ } else
35168+ au_wh_clean(h_dir, h_path, /*isdir*/1);
35169+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
35170+
35171+ h_path->dentry = base[AuBrWh_ORPH].dentry;
35172+ err = au_whdir(h_dir, h_path);
35173+ if (unlikely(err))
35174+ goto out;
35175+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
35176+
4f0767ce 35177+out:
1facf9fc 35178+ return err;
35179+}
35180+
35181+/*
35182+ * initialize the whiteout base file/dir for @br.
35183+ */
86dc4139 35184+int au_wh_init(struct au_branch *br, struct super_block *sb)
1facf9fc 35185+{
35186+ int err, i;
35187+ const unsigned char do_plink
35188+ = !!au_opt_test(au_mntflags(sb), PLINK);
1facf9fc 35189+ struct inode *h_dir;
86dc4139
AM
35190+ struct path path = br->br_path;
35191+ struct dentry *h_root = path.dentry;
1facf9fc 35192+ struct au_wbr *wbr = br->br_wbr;
35193+ static const struct qstr base_name[] = {
0c3ec466
AM
35194+ [AuBrWh_BASE] = QSTR_INIT(AUFS_BASE_NAME,
35195+ sizeof(AUFS_BASE_NAME) - 1),
35196+ [AuBrWh_PLINK] = QSTR_INIT(AUFS_PLINKDIR_NAME,
35197+ sizeof(AUFS_PLINKDIR_NAME) - 1),
35198+ [AuBrWh_ORPH] = QSTR_INIT(AUFS_ORPHDIR_NAME,
35199+ sizeof(AUFS_ORPHDIR_NAME) - 1)
1facf9fc 35200+ };
35201+ struct au_wh_base base[] = {
35202+ [AuBrWh_BASE] = {
35203+ .name = base_name + AuBrWh_BASE,
35204+ .dentry = NULL
35205+ },
35206+ [AuBrWh_PLINK] = {
35207+ .name = base_name + AuBrWh_PLINK,
35208+ .dentry = NULL
35209+ },
35210+ [AuBrWh_ORPH] = {
35211+ .name = base_name + AuBrWh_ORPH,
35212+ .dentry = NULL
35213+ }
35214+ };
35215+
1308ab2a 35216+ if (wbr)
35217+ WbrWhMustWriteLock(wbr);
1facf9fc 35218+
1facf9fc 35219+ for (i = 0; i < AuBrWh_Last; i++) {
35220+ /* doubly whiteouted */
35221+ struct dentry *d;
35222+
35223+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
35224+ err = PTR_ERR(d);
35225+ if (IS_ERR(d))
35226+ goto out;
35227+
35228+ base[i].dentry = d;
35229+ AuDebugOn(wbr
35230+ && wbr->wbr_wh[i]
35231+ && wbr->wbr_wh[i] != base[i].dentry);
35232+ }
35233+
35234+ if (wbr)
35235+ for (i = 0; i < AuBrWh_Last; i++) {
35236+ dput(wbr->wbr_wh[i]);
35237+ wbr->wbr_wh[i] = NULL;
35238+ }
35239+
35240+ err = 0;
1e00d052 35241+ if (!au_br_writable(br->br_perm)) {
5527c038 35242+ h_dir = d_inode(h_root);
1facf9fc 35243+ au_wh_init_ro(h_dir, base, &path);
1e00d052 35244+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 35245+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
35246+ if (err > 0)
35247+ goto out;
35248+ else if (err)
35249+ goto out_err;
1e00d052 35250+ } else {
1facf9fc 35251+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
35252+ if (err > 0)
35253+ goto out;
35254+ else if (err)
35255+ goto out_err;
1facf9fc 35256+ }
35257+ goto out; /* success */
35258+
4f0767ce 35259+out_err:
523b37e3
AM
35260+ pr_err("an error(%d) on the writable branch %pd(%s)\n",
35261+ err, h_root, au_sbtype(h_root->d_sb));
4f0767ce 35262+out:
1facf9fc 35263+ for (i = 0; i < AuBrWh_Last; i++)
35264+ dput(base[i].dentry);
35265+ return err;
35266+}
35267+
35268+/* ---------------------------------------------------------------------- */
35269+/*
35270+ * whiteouts are all hard-linked usually.
35271+ * when its link count reaches a ceiling, we create a new whiteout base
35272+ * asynchronously.
35273+ */
35274+
35275+struct reinit_br_wh {
35276+ struct super_block *sb;
35277+ struct au_branch *br;
35278+};
35279+
35280+static void reinit_br_wh(void *arg)
35281+{
35282+ int err;
35283+ aufs_bindex_t bindex;
35284+ struct path h_path;
35285+ struct reinit_br_wh *a = arg;
35286+ struct au_wbr *wbr;
523b37e3 35287+ struct inode *dir, *delegated;
1facf9fc 35288+ struct dentry *h_root;
35289+ struct au_hinode *hdir;
35290+
35291+ err = 0;
35292+ wbr = a->br->br_wbr;
35293+ /* big aufs lock */
35294+ si_noflush_write_lock(a->sb);
35295+ if (!au_br_writable(a->br->br_perm))
35296+ goto out;
35297+ bindex = au_br_index(a->sb, a->br->br_id);
35298+ if (unlikely(bindex < 0))
35299+ goto out;
35300+
1308ab2a 35301+ di_read_lock_parent(a->sb->s_root, AuLock_IR);
5527c038 35302+ dir = d_inode(a->sb->s_root);
1facf9fc 35303+ hdir = au_hi(dir, bindex);
35304+ h_root = au_h_dptr(a->sb->s_root, bindex);
86dc4139 35305+ AuDebugOn(h_root != au_br_dentry(a->br));
1facf9fc 35306+
5afbbe0d 35307+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 35308+ wbr_wh_write_lock(wbr);
35309+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
35310+ h_root, a->br);
35311+ if (!err) {
86dc4139
AM
35312+ h_path.dentry = wbr->wbr_whbase;
35313+ h_path.mnt = au_br_mnt(a->br);
523b37e3
AM
35314+ delegated = NULL;
35315+ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated,
35316+ /*force*/0);
35317+ if (unlikely(err == -EWOULDBLOCK)) {
35318+ pr_warn("cannot retry for NFSv4 delegation"
35319+ " for an internal unlink\n");
35320+ iput(delegated);
35321+ }
1facf9fc 35322+ } else {
523b37e3 35323+ pr_warn("%pd is moved, ignored\n", wbr->wbr_whbase);
1facf9fc 35324+ err = 0;
35325+ }
35326+ dput(wbr->wbr_whbase);
35327+ wbr->wbr_whbase = NULL;
35328+ if (!err)
86dc4139 35329+ err = au_wh_init(a->br, a->sb);
1facf9fc 35330+ wbr_wh_write_unlock(wbr);
5afbbe0d 35331+ au_hn_inode_unlock(hdir);
1308ab2a 35332+ di_read_unlock(a->sb->s_root, AuLock_IR);
076b876e
AM
35333+ if (!err)
35334+ au_fhsm_wrote(a->sb, bindex, /*force*/0);
1facf9fc 35335+
4f0767ce 35336+out:
1facf9fc 35337+ if (wbr)
35338+ atomic_dec(&wbr->wbr_wh_running);
acd2b654 35339+ au_lcnt_dec(&a->br->br_count);
1facf9fc 35340+ si_write_unlock(a->sb);
027c5e7a 35341+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
9f237c51 35342+ au_kfree_rcu(a);
1facf9fc 35343+ if (unlikely(err))
35344+ AuIOErr("err %d\n", err);
35345+}
35346+
35347+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
35348+{
35349+ int do_dec, wkq_err;
35350+ struct reinit_br_wh *arg;
35351+
35352+ do_dec = 1;
35353+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
35354+ goto out;
35355+
35356+ /* ignore ENOMEM */
35357+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
35358+ if (arg) {
35359+ /*
35360+ * dec(wh_running), kfree(arg) and dec(br_count)
35361+ * in reinit function
35362+ */
35363+ arg->sb = sb;
35364+ arg->br = br;
acd2b654 35365+ au_lcnt_inc(&br->br_count);
53392da6 35366+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*flags*/0);
1facf9fc 35367+ if (unlikely(wkq_err)) {
35368+ atomic_dec(&br->br_wbr->wbr_wh_running);
acd2b654 35369+ au_lcnt_dec(&br->br_count);
9f237c51 35370+ au_kfree_rcu(arg);
1facf9fc 35371+ }
35372+ do_dec = 0;
35373+ }
35374+
4f0767ce 35375+out:
1facf9fc 35376+ if (do_dec)
35377+ atomic_dec(&br->br_wbr->wbr_wh_running);
35378+}
35379+
35380+/* ---------------------------------------------------------------------- */
35381+
35382+/*
35383+ * create the whiteout @wh.
35384+ */
35385+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
35386+ struct dentry *wh)
35387+{
35388+ int err;
35389+ struct path h_path = {
35390+ .dentry = wh
35391+ };
35392+ struct au_branch *br;
35393+ struct au_wbr *wbr;
35394+ struct dentry *h_parent;
523b37e3 35395+ struct inode *h_dir, *delegated;
1facf9fc 35396+
35397+ h_parent = wh->d_parent; /* dir inode is locked */
5527c038 35398+ h_dir = d_inode(h_parent);
1facf9fc 35399+ IMustLock(h_dir);
35400+
35401+ br = au_sbr(sb, bindex);
86dc4139 35402+ h_path.mnt = au_br_mnt(br);
1facf9fc 35403+ wbr = br->br_wbr;
35404+ wbr_wh_read_lock(wbr);
35405+ if (wbr->wbr_whbase) {
523b37e3
AM
35406+ delegated = NULL;
35407+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path, &delegated);
35408+ if (unlikely(err == -EWOULDBLOCK)) {
35409+ pr_warn("cannot retry for NFSv4 delegation"
35410+ " for an internal link\n");
35411+ iput(delegated);
35412+ }
1facf9fc 35413+ if (!err || err != -EMLINK)
35414+ goto out;
35415+
35416+ /* link count full. re-initialize br_whbase. */
35417+ kick_reinit_br_wh(sb, br);
35418+ }
35419+
35420+ /* return this error in this context */
b4510431 35421+ err = vfsub_create(h_dir, &h_path, WH_MASK, /*want_excl*/true);
076b876e
AM
35422+ if (!err)
35423+ au_fhsm_wrote(sb, bindex, /*force*/0);
1facf9fc 35424+
4f0767ce 35425+out:
1facf9fc 35426+ wbr_wh_read_unlock(wbr);
35427+ return err;
35428+}
35429+
35430+/* ---------------------------------------------------------------------- */
35431+
35432+/*
35433+ * create or remove the diropq.
35434+ */
35435+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
35436+ unsigned int flags)
35437+{
758e9dad 35438+ struct dentry *opq_dentry;
1facf9fc 35439+ struct super_block *sb;
35440+ struct au_branch *br;
758e9dad 35441+ struct path h_path;
1facf9fc 35442+ int err;
35443+
35444+ sb = dentry->d_sb;
35445+ br = au_sbr(sb, bindex);
758e9dad
AM
35446+ h_path.dentry = au_h_dptr(dentry, bindex);
35447+ h_path.mnt = au_br_mnt(br);
35448+ opq_dentry = vfsub_lkup_one(&diropq_name, &h_path);
1facf9fc 35449+ if (IS_ERR(opq_dentry))
35450+ goto out;
35451+
35452+ if (au_ftest_diropq(flags, CREATE)) {
35453+ err = link_or_create_wh(sb, bindex, opq_dentry);
35454+ if (!err) {
35455+ au_set_dbdiropq(dentry, bindex);
35456+ goto out; /* success */
35457+ }
35458+ } else {
758e9dad
AM
35459+ h_path.dentry = opq_dentry;
35460+ err = do_unlink_wh(au_h_iptr(d_inode(dentry), bindex), &h_path);
1facf9fc 35461+ if (!err)
35462+ au_set_dbdiropq(dentry, -1);
35463+ }
35464+ dput(opq_dentry);
35465+ opq_dentry = ERR_PTR(err);
35466+
4f0767ce 35467+out:
1facf9fc 35468+ return opq_dentry;
35469+}
35470+
35471+struct do_diropq_args {
35472+ struct dentry **errp;
35473+ struct dentry *dentry;
35474+ aufs_bindex_t bindex;
35475+ unsigned int flags;
35476+};
35477+
35478+static void call_do_diropq(void *args)
35479+{
35480+ struct do_diropq_args *a = args;
35481+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
35482+}
35483+
35484+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
35485+ unsigned int flags)
35486+{
35487+ struct dentry *diropq, *h_dentry;
0b2a12c6 35488+ struct user_namespace *h_userns;
1facf9fc 35489+
0b2a12c6 35490+ h_userns = au_sbr_userns(dentry->d_sb, bindex);
1facf9fc 35491+ h_dentry = au_h_dptr(dentry, bindex);
0b2a12c6
JR
35492+ if (!au_test_h_perm_sio(h_userns, d_inode(h_dentry),
35493+ MAY_EXEC | MAY_WRITE))
1facf9fc 35494+ diropq = do_diropq(dentry, bindex, flags);
35495+ else {
35496+ int wkq_err;
35497+ struct do_diropq_args args = {
35498+ .errp = &diropq,
35499+ .dentry = dentry,
35500+ .bindex = bindex,
35501+ .flags = flags
35502+ };
35503+
35504+ wkq_err = au_wkq_wait(call_do_diropq, &args);
35505+ if (unlikely(wkq_err))
35506+ diropq = ERR_PTR(wkq_err);
35507+ }
35508+
35509+ return diropq;
35510+}
35511+
35512+/* ---------------------------------------------------------------------- */
35513+
35514+/*
35515+ * lookup whiteout dentry.
35516+ * @h_parent: lower parent dentry which must exist and be locked
35517+ * @base_name: name of dentry which will be whiteouted
35518+ * returns dentry for whiteout.
35519+ */
35520+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
35521+ struct au_branch *br)
35522+{
35523+ int err;
35524+ struct qstr wh_name;
35525+ struct dentry *wh_dentry;
758e9dad 35526+ struct path h_path;
1facf9fc 35527+
35528+ err = au_wh_name_alloc(&wh_name, base_name);
35529+ wh_dentry = ERR_PTR(err);
35530+ if (!err) {
758e9dad
AM
35531+ h_path.dentry = h_parent;
35532+ h_path.mnt = au_br_mnt(br);
35533+ wh_dentry = vfsub_lkup_one(&wh_name, &h_path);
9f237c51 35534+ au_kfree_try_rcu(wh_name.name);
1facf9fc 35535+ }
35536+ return wh_dentry;
35537+}
35538+
35539+/*
35540+ * link/create a whiteout for @dentry on @bindex.
35541+ */
35542+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
35543+ struct dentry *h_parent)
35544+{
35545+ struct dentry *wh_dentry;
35546+ struct super_block *sb;
35547+ int err;
35548+
35549+ sb = dentry->d_sb;
35550+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
5527c038 35551+ if (!IS_ERR(wh_dentry) && d_is_negative(wh_dentry)) {
1facf9fc 35552+ err = link_or_create_wh(sb, bindex, wh_dentry);
076b876e 35553+ if (!err) {
1facf9fc 35554+ au_set_dbwh(dentry, bindex);
076b876e
AM
35555+ au_fhsm_wrote(sb, bindex, /*force*/0);
35556+ } else {
1facf9fc 35557+ dput(wh_dentry);
35558+ wh_dentry = ERR_PTR(err);
35559+ }
35560+ }
35561+
35562+ return wh_dentry;
35563+}
35564+
35565+/* ---------------------------------------------------------------------- */
35566+
35567+/* Delete all whiteouts in this directory on branch bindex. */
758e9dad
AM
35568+static int del_wh_children(struct path *h_path, struct au_nhash *whlist,
35569+ aufs_bindex_t bindex)
1facf9fc 35570+{
35571+ int err;
35572+ unsigned long ul, n;
35573+ struct qstr wh_name;
35574+ char *p;
35575+ struct hlist_head *head;
c06a8ce3 35576+ struct au_vdir_wh *pos;
1facf9fc 35577+ struct au_vdir_destr *str;
35578+
35579+ err = -ENOMEM;
537831f9 35580+ p = (void *)__get_free_page(GFP_NOFS);
1facf9fc 35581+ wh_name.name = p;
35582+ if (unlikely(!wh_name.name))
35583+ goto out;
35584+
35585+ err = 0;
35586+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
35587+ p += AUFS_WH_PFX_LEN;
35588+ n = whlist->nh_num;
35589+ head = whlist->nh_head;
35590+ for (ul = 0; !err && ul < n; ul++, head++) {
c06a8ce3
AM
35591+ hlist_for_each_entry(pos, head, wh_hash) {
35592+ if (pos->wh_bindex != bindex)
1facf9fc 35593+ continue;
35594+
c06a8ce3 35595+ str = &pos->wh_str;
1facf9fc 35596+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
35597+ memcpy(p, str->name, str->len);
35598+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
758e9dad 35599+ err = unlink_wh_name(h_path, &wh_name);
1facf9fc 35600+ if (!err)
35601+ continue;
35602+ break;
35603+ }
35604+ AuIOErr("whiteout name too long %.*s\n",
35605+ str->len, str->name);
35606+ err = -EIO;
35607+ break;
35608+ }
35609+ }
1c60b727 35610+ free_page((unsigned long)wh_name.name);
1facf9fc 35611+
4f0767ce 35612+out:
1facf9fc 35613+ return err;
35614+}
35615+
35616+struct del_wh_children_args {
35617+ int *errp;
758e9dad 35618+ struct path *h_path;
1308ab2a 35619+ struct au_nhash *whlist;
1facf9fc 35620+ aufs_bindex_t bindex;
1facf9fc 35621+};
35622+
35623+static void call_del_wh_children(void *args)
35624+{
35625+ struct del_wh_children_args *a = args;
758e9dad 35626+ *a->errp = del_wh_children(a->h_path, a->whlist, a->bindex);
1facf9fc 35627+}
35628+
35629+/* ---------------------------------------------------------------------- */
35630+
35631+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
35632+{
35633+ struct au_whtmp_rmdir *whtmp;
dece6358 35634+ int err;
1308ab2a 35635+ unsigned int rdhash;
dece6358
AM
35636+
35637+ SiMustAnyLock(sb);
1facf9fc 35638+
be52b249 35639+ whtmp = kzalloc(sizeof(*whtmp), gfp);
dece6358
AM
35640+ if (unlikely(!whtmp)) {
35641+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 35642+ goto out;
dece6358 35643+ }
1facf9fc 35644+
1308ab2a 35645+ /* no estimation for dir size */
35646+ rdhash = au_sbi(sb)->si_rdhash;
35647+ if (!rdhash)
35648+ rdhash = AUFS_RDHASH_DEF;
35649+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
35650+ if (unlikely(err)) {
9f237c51 35651+ au_kfree_rcu(whtmp);
1308ab2a 35652+ whtmp = ERR_PTR(err);
35653+ }
dece6358 35654+
4f0767ce 35655+out:
dece6358 35656+ return whtmp;
1facf9fc 35657+}
35658+
35659+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
35660+{
027c5e7a 35661+ if (whtmp->br)
acd2b654 35662+ au_lcnt_dec(&whtmp->br->br_count);
1facf9fc 35663+ dput(whtmp->wh_dentry);
35664+ iput(whtmp->dir);
dece6358 35665+ au_nhash_wh_free(&whtmp->whlist);
9f237c51 35666+ au_kfree_rcu(whtmp);
1facf9fc 35667+}
35668+
35669+/*
35670+ * rmdir the whiteouted temporary named dir @h_dentry.
35671+ * @whlist: whiteouted children.
35672+ */
35673+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
35674+ struct dentry *wh_dentry, struct au_nhash *whlist)
35675+{
35676+ int err;
2000de60 35677+ unsigned int h_nlink;
758e9dad 35678+ struct path wh_path;
1facf9fc 35679+ struct inode *wh_inode, *h_dir;
35680+ struct au_branch *br;
0b2a12c6 35681+ struct user_namespace *h_userns;
1facf9fc 35682+
5527c038 35683+ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */
1facf9fc 35684+ IMustLock(h_dir);
35685+
35686+ br = au_sbr(dir->i_sb, bindex);
758e9dad
AM
35687+ wh_path.dentry = wh_dentry;
35688+ wh_path.mnt = au_br_mnt(br);
0b2a12c6 35689+ h_userns = au_br_userns(br);
5527c038 35690+ wh_inode = d_inode(wh_dentry);
febd17d6 35691+ inode_lock_nested(wh_inode, AuLsc_I_CHILD);
1facf9fc 35692+
35693+ /*
35694+ * someone else might change some whiteouts while we were sleeping.
35695+ * it means this whlist may have an obsoleted entry.
35696+ */
0b2a12c6 35697+ if (!au_test_h_perm_sio(h_userns, wh_inode, MAY_EXEC | MAY_WRITE))
758e9dad 35698+ err = del_wh_children(&wh_path, whlist, bindex);
1facf9fc 35699+ else {
35700+ int wkq_err;
35701+ struct del_wh_children_args args = {
35702+ .errp = &err,
758e9dad 35703+ .h_path = &wh_path,
1308ab2a 35704+ .whlist = whlist,
758e9dad 35705+ .bindex = bindex
1facf9fc 35706+ };
35707+
35708+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
35709+ if (unlikely(wkq_err))
35710+ err = wkq_err;
35711+ }
febd17d6 35712+ inode_unlock(wh_inode);
1facf9fc 35713+
35714+ if (!err) {
2000de60 35715+ h_nlink = h_dir->i_nlink;
758e9dad 35716+ err = vfsub_rmdir(h_dir, &wh_path);
2000de60
JR
35717+ /* some fs doesn't change the parent nlink in some cases */
35718+ h_nlink -= h_dir->i_nlink;
1facf9fc 35719+ }
35720+
35721+ if (!err) {
5afbbe0d 35722+ if (au_ibtop(dir) == bindex) {
7f207e10 35723+ /* todo: dir->i_mutex is necessary */
1facf9fc 35724+ au_cpup_attr_timesizes(dir);
2000de60
JR
35725+ if (h_nlink)
35726+ vfsub_drop_nlink(dir);
1facf9fc 35727+ }
35728+ return 0; /* success */
35729+ }
35730+
523b37e3 35731+ pr_warn("failed removing %pd(%d), ignored\n", wh_dentry, err);
1facf9fc 35732+ return err;
35733+}
35734+
35735+static void call_rmdir_whtmp(void *args)
35736+{
35737+ int err;
e49829fe 35738+ aufs_bindex_t bindex;
1facf9fc 35739+ struct au_whtmp_rmdir *a = args;
35740+ struct super_block *sb;
35741+ struct dentry *h_parent;
35742+ struct inode *h_dir;
1facf9fc 35743+ struct au_hinode *hdir;
35744+
35745+ /* rmdir by nfsd may cause deadlock with this i_mutex */
febd17d6 35746+ /* inode_lock(a->dir); */
e49829fe 35747+ err = -EROFS;
1facf9fc 35748+ sb = a->dir->i_sb;
e49829fe
JR
35749+ si_read_lock(sb, !AuLock_FLUSH);
35750+ if (!au_br_writable(a->br->br_perm))
35751+ goto out;
35752+ bindex = au_br_index(sb, a->br->br_id);
35753+ if (unlikely(bindex < 0))
1facf9fc 35754+ goto out;
35755+
35756+ err = -EIO;
1facf9fc 35757+ ii_write_lock_parent(a->dir);
35758+ h_parent = dget_parent(a->wh_dentry);
5527c038 35759+ h_dir = d_inode(h_parent);
e49829fe 35760+ hdir = au_hi(a->dir, bindex);
86dc4139
AM
35761+ err = vfsub_mnt_want_write(au_br_mnt(a->br));
35762+ if (unlikely(err))
35763+ goto out_mnt;
5afbbe0d 35764+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
e49829fe
JR
35765+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent,
35766+ a->br);
86dc4139
AM
35767+ if (!err)
35768+ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry, &a->whlist);
5afbbe0d 35769+ au_hn_inode_unlock(hdir);
86dc4139
AM
35770+ vfsub_mnt_drop_write(au_br_mnt(a->br));
35771+
35772+out_mnt:
1facf9fc 35773+ dput(h_parent);
35774+ ii_write_unlock(a->dir);
4f0767ce 35775+out:
febd17d6 35776+ /* inode_unlock(a->dir); */
1facf9fc 35777+ au_whtmp_rmdir_free(a);
027c5e7a
AM
35778+ si_read_unlock(sb);
35779+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 35780+ if (unlikely(err))
35781+ AuIOErr("err %d\n", err);
35782+}
35783+
35784+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
35785+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
35786+{
35787+ int wkq_err;
e49829fe 35788+ struct super_block *sb;
1facf9fc 35789+
35790+ IMustLock(dir);
35791+
35792+ /* all post-process will be done in do_rmdir_whtmp(). */
e49829fe 35793+ sb = dir->i_sb;
1facf9fc 35794+ args->dir = au_igrab(dir);
e49829fe 35795+ args->br = au_sbr(sb, bindex);
acd2b654 35796+ au_lcnt_inc(&args->br->br_count);
1facf9fc 35797+ args->wh_dentry = dget(wh_dentry);
53392da6 35798+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb, /*flags*/0);
1facf9fc 35799+ if (unlikely(wkq_err)) {
523b37e3 35800+ pr_warn("rmdir error %pd (%d), ignored\n", wh_dentry, wkq_err);
1facf9fc 35801+ au_whtmp_rmdir_free(args);
35802+ }
35803+}
7f207e10 35804diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
eca34b5c 35805--- /usr/share/empty/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
319657f6 35806+++ linux/fs/aufs/whout.h 2021-12-03 15:40:58.236647297 +0100
0b2a12c6 35807@@ -0,0 +1,87 @@
062440b3 35808+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 35809+/*
6d176551 35810+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 35811+ *
35812+ * This program, aufs is free software; you can redistribute it and/or modify
35813+ * it under the terms of the GNU General Public License as published by
35814+ * the Free Software Foundation; either version 2 of the License, or
35815+ * (at your option) any later version.
dece6358
AM
35816+ *
35817+ * This program is distributed in the hope that it will be useful,
35818+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
35819+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35820+ * GNU General Public License for more details.
35821+ *
35822+ * You should have received a copy of the GNU General Public License
523b37e3 35823+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 35824+ */
35825+
35826+/*
35827+ * whiteout for logical deletion and opaque directory
35828+ */
35829+
35830+#ifndef __AUFS_WHOUT_H__
35831+#define __AUFS_WHOUT_H__
35832+
35833+#ifdef __KERNEL__
35834+
1facf9fc 35835+#include "dir.h"
35836+
35837+/* whout.c */
35838+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
758e9dad 35839+int au_wh_test(struct user_namespace *h_userns, struct path *h_ppath,
0b2a12c6 35840+ struct qstr *wh_name, int try_sio);
758e9dad 35841+int au_diropq_test(struct user_namespace *h_userns, struct path *h_path);
3c1bdaff 35842+struct au_branch;
1facf9fc 35843+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
35844+ struct qstr *prefix);
35845+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
35846+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
35847+ struct dentry *dentry);
86dc4139 35848+int au_wh_init(struct au_branch *br, struct super_block *sb);
1facf9fc 35849+
35850+/* diropq flags */
35851+#define AuDiropq_CREATE 1
35852+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
7f207e10
AM
35853+#define au_fset_diropq(flags, name) \
35854+ do { (flags) |= AuDiropq_##name; } while (0)
35855+#define au_fclr_diropq(flags, name) \
35856+ do { (flags) &= ~AuDiropq_##name; } while (0)
1facf9fc 35857+
35858+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
35859+ unsigned int flags);
35860+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
35861+ struct au_branch *br);
35862+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
35863+ struct dentry *h_parent);
35864+
35865+/* real rmdir for the whiteout-ed dir */
35866+struct au_whtmp_rmdir {
35867+ struct inode *dir;
e49829fe 35868+ struct au_branch *br;
1facf9fc 35869+ struct dentry *wh_dentry;
dece6358 35870+ struct au_nhash whlist;
1facf9fc 35871+};
35872+
35873+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
35874+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
35875+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
35876+ struct dentry *wh_dentry, struct au_nhash *whlist);
35877+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
35878+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
35879+
35880+/* ---------------------------------------------------------------------- */
35881+
35882+static inline struct dentry *au_diropq_create(struct dentry *dentry,
35883+ aufs_bindex_t bindex)
35884+{
35885+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
35886+}
35887+
35888+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
35889+{
35890+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
35891+}
35892+
35893+#endif /* __KERNEL__ */
35894+#endif /* __AUFS_WHOUT_H__ */
7f207e10 35895diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
eca34b5c 35896--- /usr/share/empty/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
319657f6 35897+++ linux/fs/aufs/wkq.c 2021-12-03 15:38:59.943313977 +0100
43982f53 35898@@ -0,0 +1,372 @@
cd7a4cd9 35899+// SPDX-License-Identifier: GPL-2.0
1facf9fc 35900+/*
6d176551 35901+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 35902+ *
35903+ * This program, aufs is free software; you can redistribute it and/or modify
35904+ * it under the terms of the GNU General Public License as published by
35905+ * the Free Software Foundation; either version 2 of the License, or
35906+ * (at your option) any later version.
dece6358
AM
35907+ *
35908+ * This program is distributed in the hope that it will be useful,
35909+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
35910+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35911+ * GNU General Public License for more details.
35912+ *
35913+ * You should have received a copy of the GNU General Public License
523b37e3 35914+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 35915+ */
35916+
35917+/*
35918+ * workqueue for asynchronous/super-io operations
acd2b654 35919+ * todo: try new credential scheme
1facf9fc 35920+ */
35921+
dece6358 35922+#include <linux/module.h>
1facf9fc 35923+#include "aufs.h"
35924+
9dbd164d 35925+/* internal workqueue named AUFS_WKQ_NAME */
b752ccd1 35926+
9dbd164d 35927+static struct workqueue_struct *au_wkq;
1facf9fc 35928+
35929+struct au_wkinfo {
35930+ struct work_struct wk;
7f207e10 35931+ struct kobject *kobj;
1facf9fc 35932+
35933+ unsigned int flags; /* see wkq.h */
35934+
35935+ au_wkq_func_t func;
35936+ void *args;
35937+
8b6a4947
AM
35938+#ifdef CONFIG_LOCKDEP
35939+ int dont_check;
35940+ struct held_lock **hlock;
35941+#endif
35942+
1facf9fc 35943+ struct completion *comp;
35944+};
35945+
35946+/* ---------------------------------------------------------------------- */
8b6a4947
AM
35947+/*
35948+ * Aufs passes some operations to the workqueue such as the internal copyup.
35949+ * This scheme looks rather unnatural for LOCKDEP debugging feature, since the
35950+ * job run by workqueue depends upon the locks acquired in the other task.
35951+ * Delegating a small operation to the workqueue, aufs passes its lockdep
35952+ * information too. And the job in the workqueue restores the info in order to
35953+ * pretend as if it acquired those locks. This is just to make LOCKDEP work
35954+ * correctly and expectedly.
35955+ */
35956+
35957+#ifndef CONFIG_LOCKDEP
35958+AuStubInt0(au_wkq_lockdep_alloc, struct au_wkinfo *wkinfo);
35959+AuStubVoid(au_wkq_lockdep_free, struct au_wkinfo *wkinfo);
35960+AuStubVoid(au_wkq_lockdep_pre, struct au_wkinfo *wkinfo);
35961+AuStubVoid(au_wkq_lockdep_post, struct au_wkinfo *wkinfo);
35962+AuStubVoid(au_wkq_lockdep_init, struct au_wkinfo *wkinfo);
35963+#else
35964+static void au_wkq_lockdep_init(struct au_wkinfo *wkinfo)
35965+{
35966+ wkinfo->hlock = NULL;
35967+ wkinfo->dont_check = 0;
35968+}
35969+
35970+/*
35971+ * 1: matched
35972+ * 0: unmatched
35973+ */
35974+static int au_wkq_lockdep_test(struct lock_class_key *key, const char *name)
35975+{
35976+ static DEFINE_SPINLOCK(spin);
35977+ static struct {
35978+ char *name;
35979+ struct lock_class_key *key;
35980+ } a[] = {
35981+ { .name = "&sbinfo->si_rwsem" },
35982+ { .name = "&finfo->fi_rwsem" },
35983+ { .name = "&dinfo->di_rwsem" },
35984+ { .name = "&iinfo->ii_rwsem" }
35985+ };
35986+ static int set;
35987+ int i;
35988+
35989+ /* lockless read from 'set.' see below */
35990+ if (set == ARRAY_SIZE(a)) {
35991+ for (i = 0; i < ARRAY_SIZE(a); i++)
35992+ if (a[i].key == key)
35993+ goto match;
35994+ goto unmatch;
35995+ }
35996+
35997+ spin_lock(&spin);
35998+ if (set)
35999+ for (i = 0; i < ARRAY_SIZE(a); i++)
36000+ if (a[i].key == key) {
36001+ spin_unlock(&spin);
36002+ goto match;
36003+ }
36004+ for (i = 0; i < ARRAY_SIZE(a); i++) {
36005+ if (a[i].key) {
36006+ if (unlikely(a[i].key == key)) { /* rare but possible */
36007+ spin_unlock(&spin);
36008+ goto match;
36009+ } else
36010+ continue;
36011+ }
36012+ if (strstr(a[i].name, name)) {
36013+ /*
36014+ * the order of these three lines is important for the
36015+ * lockless read above.
36016+ */
36017+ a[i].key = key;
36018+ spin_unlock(&spin);
36019+ set++;
36020+ /* AuDbg("%d, %s\n", set, name); */
36021+ goto match;
36022+ }
36023+ }
36024+ spin_unlock(&spin);
36025+ goto unmatch;
36026+
36027+match:
36028+ return 1;
36029+unmatch:
36030+ return 0;
36031+}
36032+
36033+static int au_wkq_lockdep_alloc(struct au_wkinfo *wkinfo)
36034+{
36035+ int err, n;
36036+ struct task_struct *curr;
36037+ struct held_lock **hl, *held_locks, *p;
36038+
36039+ err = 0;
36040+ curr = current;
36041+ wkinfo->dont_check = lockdep_recursing(curr);
36042+ if (wkinfo->dont_check)
36043+ goto out;
36044+ n = curr->lockdep_depth;
36045+ if (!n)
36046+ goto out;
36047+
36048+ err = -ENOMEM;
36049+ wkinfo->hlock = kmalloc_array(n + 1, sizeof(*wkinfo->hlock), GFP_NOFS);
36050+ if (unlikely(!wkinfo->hlock))
36051+ goto out;
36052+
36053+ err = 0;
43982f53
AM
36054+#if 0 /* left for debugging */
36055+ if (0 && au_debug_test())
8b6a4947
AM
36056+ lockdep_print_held_locks(curr);
36057+#endif
36058+ held_locks = curr->held_locks;
36059+ hl = wkinfo->hlock;
36060+ while (n--) {
36061+ p = held_locks++;
36062+ if (au_wkq_lockdep_test(p->instance->key, p->instance->name))
36063+ *hl++ = p;
36064+ }
36065+ *hl = NULL;
36066+
36067+out:
36068+ return err;
36069+}
36070+
36071+static void au_wkq_lockdep_free(struct au_wkinfo *wkinfo)
36072+{
9f237c51 36073+ au_kfree_try_rcu(wkinfo->hlock);
8b6a4947
AM
36074+}
36075+
36076+static void au_wkq_lockdep_pre(struct au_wkinfo *wkinfo)
36077+{
36078+ struct held_lock *p, **hl = wkinfo->hlock;
36079+ int subclass;
36080+
36081+ if (wkinfo->dont_check)
36082+ lockdep_off();
36083+ if (!hl)
36084+ return;
36085+ while ((p = *hl++)) { /* assignment */
36086+ subclass = lockdep_hlock_class(p)->subclass;
36087+ /* AuDbg("%s, %d\n", p->instance->name, subclass); */
36088+ if (p->read)
36089+ rwsem_acquire_read(p->instance, subclass, 0,
36090+ /*p->acquire_ip*/_RET_IP_);
36091+ else
36092+ rwsem_acquire(p->instance, subclass, 0,
36093+ /*p->acquire_ip*/_RET_IP_);
36094+ }
36095+}
36096+
36097+static void au_wkq_lockdep_post(struct au_wkinfo *wkinfo)
36098+{
36099+ struct held_lock *p, **hl = wkinfo->hlock;
36100+
36101+ if (wkinfo->dont_check)
36102+ lockdep_on();
36103+ if (!hl)
36104+ return;
36105+ while ((p = *hl++)) /* assignment */
d58c55f2 36106+ rwsem_release(p->instance, /*p->acquire_ip*/_RET_IP_);
8b6a4947
AM
36107+}
36108+#endif
1facf9fc 36109+
1facf9fc 36110+static void wkq_func(struct work_struct *wk)
36111+{
36112+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
36113+
2dfbb274 36114+ AuDebugOn(!uid_eq(current_fsuid(), GLOBAL_ROOT_UID));
7f207e10
AM
36115+ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
36116+
8b6a4947 36117+ au_wkq_lockdep_pre(wkinfo);
1facf9fc 36118+ wkinfo->func(wkinfo->args);
8b6a4947 36119+ au_wkq_lockdep_post(wkinfo);
1facf9fc 36120+ if (au_ftest_wkq(wkinfo->flags, WAIT))
36121+ complete(wkinfo->comp);
36122+ else {
7f207e10 36123+ kobject_put(wkinfo->kobj);
9dbd164d 36124+ module_put(THIS_MODULE); /* todo: ?? */
9f237c51 36125+ au_kfree_rcu(wkinfo);
1facf9fc 36126+ }
36127+}
36128+
36129+/*
36130+ * Since struct completion is large, try allocating it dynamically.
36131+ */
1facf9fc 36132+#define AuWkqCompDeclare(name) struct completion *comp = NULL
36133+
36134+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
36135+{
36136+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
36137+ if (*comp) {
36138+ init_completion(*comp);
36139+ wkinfo->comp = *comp;
36140+ return 0;
36141+ }
36142+ return -ENOMEM;
36143+}
36144+
36145+static void au_wkq_comp_free(struct completion *comp)
36146+{
9f237c51 36147+ au_kfree_rcu(comp);
1facf9fc 36148+}
36149+
53392da6 36150+static void au_wkq_run(struct au_wkinfo *wkinfo)
1facf9fc 36151+{
53392da6
AM
36152+ if (au_ftest_wkq(wkinfo->flags, NEST)) {
36153+ if (au_wkq_test()) {
38d290e6 36154+ AuWarn1("wkq from wkq, unless silly-rename on NFS,"
acd2b654
AM
36155+ " due to a dead dir by UDBA,"
36156+ " or async xino write?\n");
53392da6
AM
36157+ AuDebugOn(au_ftest_wkq(wkinfo->flags, WAIT));
36158+ }
36159+ } else
36160+ au_dbg_verify_kthread();
36161+
36162+ if (au_ftest_wkq(wkinfo->flags, WAIT)) {
a1f66529 36163+ INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func);
9dbd164d 36164+ queue_work(au_wkq, &wkinfo->wk);
4a4d8108
AM
36165+ } else {
36166+ INIT_WORK(&wkinfo->wk, wkq_func);
36167+ schedule_work(&wkinfo->wk);
36168+ }
1facf9fc 36169+}
36170+
7f207e10
AM
36171+/*
36172+ * Be careful. It is easy to make deadlock happen.
36173+ * processA: lock, wkq and wait
36174+ * processB: wkq and wait, lock in wkq
36175+ * --> deadlock
36176+ */
b752ccd1 36177+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
1facf9fc 36178+{
36179+ int err;
36180+ AuWkqCompDeclare(comp);
36181+ struct au_wkinfo wkinfo = {
b752ccd1 36182+ .flags = flags,
1facf9fc 36183+ .func = func,
36184+ .args = args
36185+ };
36186+
36187+ err = au_wkq_comp_alloc(&wkinfo, &comp);
8b6a4947
AM
36188+ if (unlikely(err))
36189+ goto out;
36190+ err = au_wkq_lockdep_alloc(&wkinfo);
36191+ if (unlikely(err))
36192+ goto out_comp;
1facf9fc 36193+ if (!err) {
53392da6 36194+ au_wkq_run(&wkinfo);
1facf9fc 36195+ /* no timeout, no interrupt */
36196+ wait_for_completion(wkinfo.comp);
1facf9fc 36197+ }
8b6a4947 36198+ au_wkq_lockdep_free(&wkinfo);
1facf9fc 36199+
8b6a4947
AM
36200+out_comp:
36201+ au_wkq_comp_free(comp);
36202+out:
36203+ destroy_work_on_stack(&wkinfo.wk);
1facf9fc 36204+ return err;
1facf9fc 36205+}
36206+
027c5e7a
AM
36207+/*
36208+ * Note: dget/dput() in func for aufs dentries are not supported. It will be a
36209+ * problem in a concurrent umounting.
36210+ */
53392da6
AM
36211+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
36212+ unsigned int flags)
1facf9fc 36213+{
36214+ int err;
36215+ struct au_wkinfo *wkinfo;
36216+
f0c0a007 36217+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
1facf9fc 36218+
36219+ /*
36220+ * wkq_func() must free this wkinfo.
36221+ * it highly depends upon the implementation of workqueue.
36222+ */
36223+ err = 0;
36224+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
36225+ if (wkinfo) {
7f207e10 36226+ wkinfo->kobj = &au_sbi(sb)->si_kobj;
53392da6 36227+ wkinfo->flags = flags & ~AuWkq_WAIT;
1facf9fc 36228+ wkinfo->func = func;
36229+ wkinfo->args = args;
36230+ wkinfo->comp = NULL;
8b6a4947 36231+ au_wkq_lockdep_init(wkinfo);
7f207e10 36232+ kobject_get(wkinfo->kobj);
9dbd164d 36233+ __module_get(THIS_MODULE); /* todo: ?? */
1facf9fc 36234+
53392da6 36235+ au_wkq_run(wkinfo);
1facf9fc 36236+ } else {
36237+ err = -ENOMEM;
e49829fe 36238+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 36239+ }
36240+
36241+ return err;
36242+}
36243+
36244+/* ---------------------------------------------------------------------- */
36245+
36246+void au_nwt_init(struct au_nowait_tasks *nwt)
36247+{
f0c0a007
AM
36248+ atomic_set(&nwt->nw_len, 0);
36249+ /* smp_mb(); */ /* atomic_set */
1facf9fc 36250+ init_waitqueue_head(&nwt->nw_wq);
36251+}
36252+
36253+void au_wkq_fin(void)
36254+{
9dbd164d 36255+ destroy_workqueue(au_wkq);
1facf9fc 36256+}
36257+
36258+int __init au_wkq_init(void)
36259+{
9dbd164d 36260+ int err;
b752ccd1
AM
36261+
36262+ err = 0;
86dc4139 36263+ au_wkq = alloc_workqueue(AUFS_WKQ_NAME, 0, WQ_DFL_ACTIVE);
9dbd164d
AM
36264+ if (IS_ERR(au_wkq))
36265+ err = PTR_ERR(au_wkq);
36266+ else if (!au_wkq)
36267+ err = -ENOMEM;
b752ccd1
AM
36268+
36269+ return err;
1facf9fc 36270+}
7f207e10 36271diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
eca34b5c 36272--- /usr/share/empty/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
319657f6 36273+++ linux/fs/aufs/wkq.h 2021-12-03 15:38:59.943313977 +0100
acd2b654 36274@@ -0,0 +1,89 @@
062440b3 36275+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 36276+/*
6d176551 36277+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 36278+ *
36279+ * This program, aufs is free software; you can redistribute it and/or modify
36280+ * it under the terms of the GNU General Public License as published by
36281+ * the Free Software Foundation; either version 2 of the License, or
36282+ * (at your option) any later version.
dece6358
AM
36283+ *
36284+ * This program is distributed in the hope that it will be useful,
36285+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36286+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36287+ * GNU General Public License for more details.
36288+ *
36289+ * You should have received a copy of the GNU General Public License
523b37e3 36290+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 36291+ */
36292+
36293+/*
36294+ * workqueue for asynchronous/super-io operations
36295+ * todo: try new credentials management scheme
36296+ */
36297+
36298+#ifndef __AUFS_WKQ_H__
36299+#define __AUFS_WKQ_H__
36300+
36301+#ifdef __KERNEL__
36302+
8b6a4947 36303+#include <linux/wait.h>
5afbbe0d 36304+
dece6358
AM
36305+struct super_block;
36306+
1facf9fc 36307+/* ---------------------------------------------------------------------- */
36308+
36309+/*
36310+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
36311+ */
36312+struct au_nowait_tasks {
f0c0a007 36313+ atomic_t nw_len;
1facf9fc 36314+ wait_queue_head_t nw_wq;
36315+};
36316+
36317+/* ---------------------------------------------------------------------- */
36318+
36319+typedef void (*au_wkq_func_t)(void *args);
36320+
36321+/* wkq flags */
36322+#define AuWkq_WAIT 1
9dbd164d 36323+#define AuWkq_NEST (1 << 1)
1facf9fc 36324+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
7f207e10
AM
36325+#define au_fset_wkq(flags, name) \
36326+ do { (flags) |= AuWkq_##name; } while (0)
36327+#define au_fclr_wkq(flags, name) \
36328+ do { (flags) &= ~AuWkq_##name; } while (0)
1facf9fc 36329+
36330+/* wkq.c */
b752ccd1 36331+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
53392da6
AM
36332+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
36333+ unsigned int flags);
1facf9fc 36334+void au_nwt_init(struct au_nowait_tasks *nwt);
36335+int __init au_wkq_init(void);
36336+void au_wkq_fin(void);
36337+
36338+/* ---------------------------------------------------------------------- */
36339+
53392da6
AM
36340+static inline int au_wkq_test(void)
36341+{
36342+ return current->flags & PF_WQ_WORKER;
36343+}
36344+
b752ccd1 36345+static inline int au_wkq_wait(au_wkq_func_t func, void *args)
1facf9fc 36346+{
b752ccd1 36347+ return au_wkq_do_wait(AuWkq_WAIT, func, args);
1facf9fc 36348+}
36349+
36350+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
36351+{
f0c0a007 36352+ if (atomic_dec_and_test(&nwt->nw_len))
1facf9fc 36353+ wake_up_all(&nwt->nw_wq);
36354+}
36355+
36356+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
36357+{
f0c0a007 36358+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
1facf9fc 36359+ return 0;
36360+}
36361+
36362+#endif /* __KERNEL__ */
36363+#endif /* __AUFS_WKQ_H__ */
c1595e42 36364diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c
eca34b5c 36365--- /usr/share/empty/fs/aufs/xattr.c 1970-01-01 01:00:00.000000000 +0100
319657f6 36366+++ linux/fs/aufs/xattr.c 2021-12-03 15:40:58.236647297 +0100
0b2a12c6 36367@@ -0,0 +1,368 @@
cd7a4cd9 36368+// SPDX-License-Identifier: GPL-2.0
c1595e42 36369+/*
6d176551 36370+ * Copyright (C) 2014-2021 Junjiro R. Okajima
c1595e42
JR
36371+ *
36372+ * This program, aufs is free software; you can redistribute it and/or modify
36373+ * it under the terms of the GNU General Public License as published by
36374+ * the Free Software Foundation; either version 2 of the License, or
36375+ * (at your option) any later version.
36376+ *
36377+ * This program is distributed in the hope that it will be useful,
36378+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36379+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36380+ * GNU General Public License for more details.
36381+ *
36382+ * You should have received a copy of the GNU General Public License
36383+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
36384+ */
36385+
36386+/*
36387+ * handling xattr functions
36388+ */
36389+
a2654f78
AM
36390+#include <linux/fs.h>
36391+#include <linux/posix_acl_xattr.h>
c1595e42
JR
36392+#include <linux/xattr.h>
36393+#include "aufs.h"
36394+
36395+static int au_xattr_ignore(int err, char *name, unsigned int ignore_flags)
36396+{
36397+ if (!ignore_flags)
36398+ goto out;
36399+ switch (err) {
36400+ case -ENOMEM:
36401+ case -EDQUOT:
36402+ goto out;
36403+ }
36404+
36405+ if ((ignore_flags & AuBrAttr_ICEX) == AuBrAttr_ICEX) {
36406+ err = 0;
36407+ goto out;
36408+ }
36409+
36410+#define cmp(brattr, prefix) do { \
36411+ if (!strncmp(name, XATTR_##prefix##_PREFIX, \
36412+ XATTR_##prefix##_PREFIX_LEN)) { \
36413+ if (ignore_flags & AuBrAttr_ICEX_##brattr) \
36414+ err = 0; \
36415+ goto out; \
36416+ } \
36417+ } while (0)
36418+
36419+ cmp(SEC, SECURITY);
36420+ cmp(SYS, SYSTEM);
36421+ cmp(TR, TRUSTED);
36422+ cmp(USR, USER);
36423+#undef cmp
36424+
36425+ if (ignore_flags & AuBrAttr_ICEX_OTH)
36426+ err = 0;
36427+
36428+out:
36429+ return err;
36430+}
36431+
36432+static const int au_xattr_out_of_list = AuBrAttr_ICEX_OTH << 1;
36433+
0b2a12c6 36434+static int au_do_cpup_xattr(struct path *h_dst, struct path *h_src,
7e9cd9fe
AM
36435+ char *name, char **buf, unsigned int ignore_flags,
36436+ unsigned int verbose)
c1595e42
JR
36437+{
36438+ int err;
36439+ ssize_t ssz;
36440+ struct inode *h_idst;
0b2a12c6
JR
36441+ struct dentry *h_dst_dentry, *h_src_dentry;
36442+ struct user_namespace *h_dst_userns, *h_src_userns;
c1595e42 36443+
0b2a12c6
JR
36444+ h_src_userns = mnt_user_ns(h_src->mnt);
36445+ h_src_dentry = h_src->dentry;
36446+ ssz = vfs_getxattr_alloc(h_src_userns, h_src_dentry, name, buf, 0,
36447+ GFP_NOFS);
c1595e42
JR
36448+ err = ssz;
36449+ if (unlikely(err <= 0)) {
c1595e42
JR
36450+ if (err == -ENODATA
36451+ || (err == -EOPNOTSUPP
b912730e 36452+ && ((ignore_flags & au_xattr_out_of_list)
0b2a12c6 36453+ || (au_test_nfs_noacl(d_inode(h_src_dentry))
b912730e
AM
36454+ && (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS)
36455+ || !strcmp(name,
36456+ XATTR_NAME_POSIX_ACL_DEFAULT))))
36457+ ))
c1595e42 36458+ err = 0;
b912730e
AM
36459+ if (err && (verbose || au_debug_test()))
36460+ pr_err("%s, err %d\n", name, err);
c1595e42
JR
36461+ goto out;
36462+ }
36463+
36464+ /* unlock it temporary */
0b2a12c6
JR
36465+ h_dst_userns = mnt_user_ns(h_dst->mnt);
36466+ h_dst_dentry = h_dst->dentry;
36467+ h_idst = d_inode(h_dst_dentry);
febd17d6 36468+ inode_unlock(h_idst);
0b2a12c6
JR
36469+ err = vfsub_setxattr(h_dst_userns, h_dst_dentry, name, *buf, ssz,
36470+ /*flags*/0);
febd17d6 36471+ inode_lock_nested(h_idst, AuLsc_I_CHILD2);
c1595e42 36472+ if (unlikely(err)) {
7e9cd9fe
AM
36473+ if (verbose || au_debug_test())
36474+ pr_err("%s, err %d\n", name, err);
c1595e42
JR
36475+ err = au_xattr_ignore(err, name, ignore_flags);
36476+ }
36477+
36478+out:
36479+ return err;
36480+}
36481+
0b2a12c6 36482+int au_cpup_xattr(struct path *h_dst, struct path *h_src, int ignore_flags,
7e9cd9fe 36483+ unsigned int verbose)
c1595e42
JR
36484+{
36485+ int err, unlocked, acl_access, acl_default;
36486+ ssize_t ssz;
0b2a12c6 36487+ struct dentry *h_dst_dentry, *h_src_dentry;
c1595e42
JR
36488+ struct inode *h_isrc, *h_idst;
36489+ char *value, *p, *o, *e;
36490+
36491+ /* try stopping to update the source inode while we are referencing */
7e9cd9fe 36492+ /* there should not be the parent-child relationship between them */
0b2a12c6
JR
36493+ h_dst_dentry = h_dst->dentry;
36494+ h_idst = d_inode(h_dst_dentry);
36495+ h_src_dentry = h_src->dentry;
36496+ h_isrc = d_inode(h_src_dentry);
febd17d6 36497+ inode_unlock(h_idst);
be118d29 36498+ inode_lock_shared_nested(h_isrc, AuLsc_I_CHILD);
febd17d6 36499+ inode_lock_nested(h_idst, AuLsc_I_CHILD2);
c1595e42
JR
36500+ unlocked = 0;
36501+
36502+ /* some filesystems don't list POSIX ACL, for example tmpfs */
0b2a12c6 36503+ ssz = vfs_listxattr(h_src_dentry, NULL, 0);
c1595e42
JR
36504+ err = ssz;
36505+ if (unlikely(err < 0)) {
36506+ AuTraceErr(err);
36507+ if (err == -ENODATA
36508+ || err == -EOPNOTSUPP)
36509+ err = 0; /* ignore */
36510+ goto out;
36511+ }
36512+
36513+ err = 0;
36514+ p = NULL;
36515+ o = NULL;
36516+ if (ssz) {
36517+ err = -ENOMEM;
36518+ p = kmalloc(ssz, GFP_NOFS);
36519+ o = p;
36520+ if (unlikely(!p))
36521+ goto out;
0b2a12c6 36522+ err = vfs_listxattr(h_src_dentry, p, ssz);
c1595e42 36523+ }
3c1bdaff 36524+ inode_unlock_shared(h_isrc);
c1595e42
JR
36525+ unlocked = 1;
36526+ AuDbg("err %d, ssz %zd\n", err, ssz);
36527+ if (unlikely(err < 0))
36528+ goto out_free;
36529+
36530+ err = 0;
36531+ e = p + ssz;
36532+ value = NULL;
36533+ acl_access = 0;
36534+ acl_default = 0;
36535+ while (!err && p < e) {
36536+ acl_access |= !strncmp(p, XATTR_NAME_POSIX_ACL_ACCESS,
36537+ sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1);
36538+ acl_default |= !strncmp(p, XATTR_NAME_POSIX_ACL_DEFAULT,
36539+ sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)
36540+ - 1);
7e9cd9fe
AM
36541+ err = au_do_cpup_xattr(h_dst, h_src, p, &value, ignore_flags,
36542+ verbose);
c1595e42
JR
36543+ p += strlen(p) + 1;
36544+ }
36545+ AuTraceErr(err);
36546+ ignore_flags |= au_xattr_out_of_list;
36547+ if (!err && !acl_access) {
36548+ err = au_do_cpup_xattr(h_dst, h_src,
36549+ XATTR_NAME_POSIX_ACL_ACCESS, &value,
7e9cd9fe 36550+ ignore_flags, verbose);
c1595e42
JR
36551+ AuTraceErr(err);
36552+ }
36553+ if (!err && !acl_default) {
36554+ err = au_do_cpup_xattr(h_dst, h_src,
36555+ XATTR_NAME_POSIX_ACL_DEFAULT, &value,
7e9cd9fe 36556+ ignore_flags, verbose);
c1595e42
JR
36557+ AuTraceErr(err);
36558+ }
36559+
9f237c51 36560+ au_kfree_try_rcu(value);
c1595e42
JR
36561+
36562+out_free:
9f237c51 36563+ au_kfree_try_rcu(o);
c1595e42
JR
36564+out:
36565+ if (!unlocked)
3c1bdaff 36566+ inode_unlock_shared(h_isrc);
c1595e42
JR
36567+ AuTraceErr(err);
36568+ return err;
36569+}
36570+
36571+/* ---------------------------------------------------------------------- */
36572+
a2654f78
AM
36573+static int au_smack_reentering(struct super_block *sb)
36574+{
42b5c33a 36575+#if IS_ENABLED(CONFIG_SECURITY_SMACK) || IS_ENABLED(CONFIG_SECURITY_SELINUX)
a2654f78
AM
36576+ /*
36577+ * as a part of lookup, smack_d_instantiate() is called, and it calls
36578+ * i_op->getxattr(). ouch.
36579+ */
36580+ return si_pid_test(sb);
36581+#else
36582+ return 0;
36583+#endif
36584+}
36585+
c1595e42
JR
36586+enum {
36587+ AU_XATTR_LIST,
36588+ AU_XATTR_GET
36589+};
36590+
36591+struct au_lgxattr {
36592+ int type;
36593+ union {
36594+ struct {
36595+ char *list;
36596+ size_t size;
36597+ } list;
36598+ struct {
36599+ const char *name;
36600+ void *value;
36601+ size_t size;
36602+ } get;
36603+ } u;
36604+};
36605+
42b5c33a
AM
36606+static ssize_t au_lgxattr(struct dentry *dentry, struct inode *inode,
36607+ struct au_lgxattr *arg)
c1595e42
JR
36608+{
36609+ ssize_t err;
a2654f78 36610+ int reenter;
c1595e42
JR
36611+ struct path h_path;
36612+ struct super_block *sb;
36613+
36614+ sb = dentry->d_sb;
a2654f78
AM
36615+ reenter = au_smack_reentering(sb);
36616+ if (!reenter) {
36617+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
36618+ if (unlikely(err))
36619+ goto out;
36620+ }
42b5c33a 36621+ err = au_h_path_getattr(dentry, inode, /*force*/1, &h_path, reenter);
c1595e42
JR
36622+ if (unlikely(err))
36623+ goto out_si;
36624+ if (unlikely(!h_path.dentry))
36625+ /* illegally overlapped or something */
36626+ goto out_di; /* pretending success */
36627+
36628+ /* always topmost entry only */
36629+ switch (arg->type) {
36630+ case AU_XATTR_LIST:
36631+ err = vfs_listxattr(h_path.dentry,
36632+ arg->u.list.list, arg->u.list.size);
36633+ break;
36634+ case AU_XATTR_GET:
5afbbe0d 36635+ AuDebugOn(d_is_negative(h_path.dentry));
0b2a12c6 36636+ err = vfs_getxattr(mnt_user_ns(h_path.mnt), h_path.dentry,
c1595e42
JR
36637+ arg->u.get.name, arg->u.get.value,
36638+ arg->u.get.size);
36639+ break;
36640+ }
36641+
36642+out_di:
a2654f78
AM
36643+ if (!reenter)
36644+ di_read_unlock(dentry, AuLock_IR);
c1595e42 36645+out_si:
a2654f78
AM
36646+ if (!reenter)
36647+ si_read_unlock(sb);
c1595e42
JR
36648+out:
36649+ AuTraceErr(err);
36650+ return err;
36651+}
36652+
36653+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size)
36654+{
36655+ struct au_lgxattr arg = {
36656+ .type = AU_XATTR_LIST,
36657+ .u.list = {
36658+ .list = list,
36659+ .size = size
36660+ },
36661+ };
36662+
42b5c33a 36663+ return au_lgxattr(dentry, /*inode*/NULL, &arg);
c1595e42
JR
36664+}
36665+
42b5c33a 36666+static ssize_t au_getxattr(struct dentry *dentry, struct inode *inode,
f2c43d5f 36667+ const char *name, void *value, size_t size)
c1595e42
JR
36668+{
36669+ struct au_lgxattr arg = {
36670+ .type = AU_XATTR_GET,
36671+ .u.get = {
36672+ .name = name,
36673+ .value = value,
36674+ .size = size
36675+ },
36676+ };
36677+
42b5c33a 36678+ return au_lgxattr(dentry, inode, &arg);
c1595e42
JR
36679+}
36680+
f2c43d5f
AM
36681+static int au_setxattr(struct dentry *dentry, struct inode *inode,
36682+ const char *name, const void *value, size_t size,
36683+ int flags)
c1595e42 36684+{
f2c43d5f 36685+ struct au_sxattr arg = {
c1595e42
JR
36686+ .type = AU_XATTR_SET,
36687+ .u.set = {
36688+ .name = name,
36689+ .value = value,
36690+ .size = size,
36691+ .flags = flags
36692+ },
36693+ };
36694+
f2c43d5f 36695+ return au_sxattr(dentry, inode, &arg);
c1595e42
JR
36696+}
36697+
36698+/* ---------------------------------------------------------------------- */
36699+
f2c43d5f
AM
36700+static int au_xattr_get(const struct xattr_handler *handler,
36701+ struct dentry *dentry, struct inode *inode,
36702+ const char *name, void *buffer, size_t size)
c1595e42 36703+{
f2c43d5f 36704+ return au_getxattr(dentry, inode, name, buffer, size);
c1595e42
JR
36705+}
36706+
f2c43d5f 36707+static int au_xattr_set(const struct xattr_handler *handler,
0b2a12c6 36708+ struct user_namespace *userns,
f2c43d5f
AM
36709+ struct dentry *dentry, struct inode *inode,
36710+ const char *name, const void *value, size_t size,
36711+ int flags)
c1595e42 36712+{
f2c43d5f 36713+ return au_setxattr(dentry, inode, name, value, size, flags);
c1595e42
JR
36714+}
36715+
36716+static const struct xattr_handler au_xattr_handler = {
f2c43d5f
AM
36717+ .name = "",
36718+ .prefix = "",
c1595e42
JR
36719+ .get = au_xattr_get,
36720+ .set = au_xattr_set
c1595e42
JR
36721+};
36722+
36723+static const struct xattr_handler *au_xattr_handlers[] = {
a2654f78
AM
36724+#ifdef CONFIG_FS_POSIX_ACL
36725+ &posix_acl_access_xattr_handler,
36726+ &posix_acl_default_xattr_handler,
36727+#endif
36728+ &au_xattr_handler, /* must be last */
f2c43d5f 36729+ NULL
c1595e42
JR
36730+};
36731+
36732+void au_xattr_init(struct super_block *sb)
36733+{
f2c43d5f 36734+ sb->s_xattr = au_xattr_handlers;
c1595e42 36735+}
7f207e10 36736diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
eca34b5c 36737--- /usr/share/empty/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
319657f6 36738+++ linux/fs/aufs/xino.c 2021-12-03 15:40:58.236647297 +0100
758e9dad 36739@@ -0,0 +1,1926 @@
cd7a4cd9 36740+// SPDX-License-Identifier: GPL-2.0
1facf9fc 36741+/*
6d176551 36742+ * Copyright (C) 2005-2021 Junjiro R. Okajima
1facf9fc 36743+ *
36744+ * This program, aufs is free software; you can redistribute it and/or modify
36745+ * it under the terms of the GNU General Public License as published by
36746+ * the Free Software Foundation; either version 2 of the License, or
36747+ * (at your option) any later version.
dece6358
AM
36748+ *
36749+ * This program is distributed in the hope that it will be useful,
36750+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36751+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36752+ * GNU General Public License for more details.
36753+ *
36754+ * You should have received a copy of the GNU General Public License
523b37e3 36755+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 36756+ */
36757+
36758+/*
36759+ * external inode number translation table and bitmap
062440b3
AM
36760+ *
36761+ * things to consider
36762+ * - the lifetime
36763+ * + au_xino object
36764+ * + XINO files (xino, xib, xigen)
36765+ * + dynamic debugfs entries (xiN)
36766+ * + static debugfs entries (xib, xigen)
36767+ * + static sysfs entry (xi_path)
36768+ * - several entry points to handle them.
36769+ * + mount(2) without xino option (default)
36770+ * + mount(2) with xino option
36771+ * + mount(2) with noxino option
36772+ * + umount(2)
36773+ * + remount with add/del branches
36774+ * + remount with xino/noxino options
1facf9fc 36775+ */
36776+
36777+#include <linux/seq_file.h>
392086de 36778+#include <linux/statfs.h>
1facf9fc 36779+#include "aufs.h"
36780+
062440b3
AM
36781+static aufs_bindex_t sbr_find_shared(struct super_block *sb, aufs_bindex_t btop,
36782+ aufs_bindex_t bbot,
36783+ struct super_block *h_sb)
1facf9fc 36784+{
062440b3
AM
36785+ /* todo: try binary-search if the branches are many */
36786+ for (; btop <= bbot; btop++)
36787+ if (h_sb == au_sbr_sb(sb, btop))
36788+ return btop;
36789+ return -1;
be52b249
AM
36790+}
36791+
062440b3
AM
36792+/*
36793+ * find another branch who is on the same filesystem of the specified
36794+ * branch{@btgt}. search until @bbot.
36795+ */
36796+static aufs_bindex_t is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
36797+ aufs_bindex_t bbot)
1facf9fc 36798+{
062440b3
AM
36799+ aufs_bindex_t bindex;
36800+ struct super_block *tgt_sb;
1facf9fc 36801+
062440b3
AM
36802+ tgt_sb = au_sbr_sb(sb, btgt);
36803+ bindex = sbr_find_shared(sb, /*btop*/0, btgt - 1, tgt_sb);
36804+ if (bindex < 0)
36805+ bindex = sbr_find_shared(sb, btgt + 1, bbot, tgt_sb);
1facf9fc 36806+
062440b3 36807+ return bindex;
1facf9fc 36808+}
36809+
36810+/* ---------------------------------------------------------------------- */
36811+
36812+/*
062440b3 36813+ * stop unnecessary notify events at creating xino files
1facf9fc 36814+ */
acd2b654
AM
36815+
36816+aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry)
36817+{
36818+ aufs_bindex_t bfound, bindex, bbot;
36819+ struct dentry *parent;
36820+ struct au_branch *br;
36821+
36822+ bfound = -1;
36823+ parent = dentry->d_parent; /* safe d_parent access */
36824+ bbot = au_sbbot(sb);
36825+ for (bindex = 0; bindex <= bbot; bindex++) {
36826+ br = au_sbr(sb, bindex);
36827+ if (au_br_dentry(br) == parent) {
36828+ bfound = bindex;
36829+ break;
36830+ }
36831+ }
36832+
36833+ AuDbg("bfound b%d\n", bfound);
36834+ return bfound;
36835+}
36836+
062440b3
AM
36837+struct au_xino_lock_dir {
36838+ struct au_hinode *hdir;
36839+ struct dentry *parent;
36840+ struct inode *dir;
36841+};
36842+
36843+static struct dentry *au_dget_parent_lock(struct dentry *dentry,
36844+ unsigned int lsc)
1facf9fc 36845+{
062440b3
AM
36846+ struct dentry *parent;
36847+ struct inode *dir;
1facf9fc 36848+
062440b3 36849+ parent = dget_parent(dentry);
5527c038 36850+ dir = d_inode(parent);
062440b3
AM
36851+ inode_lock_nested(dir, lsc);
36852+#if 0 /* it should not happen */
36853+ spin_lock(&dentry->d_lock);
36854+ if (unlikely(dentry->d_parent != parent)) {
36855+ spin_unlock(&dentry->d_lock);
36856+ inode_unlock(dir);
36857+ dput(parent);
36858+ parent = NULL;
1facf9fc 36859+ goto out;
36860+ }
062440b3 36861+ spin_unlock(&dentry->d_lock);
1facf9fc 36862+
4f0767ce 36863+out:
062440b3
AM
36864+#endif
36865+ return parent;
1facf9fc 36866+}
36867+
062440b3 36868+static void au_xino_lock_dir(struct super_block *sb, struct path *xipath,
1facf9fc 36869+ struct au_xino_lock_dir *ldir)
36870+{
acd2b654 36871+ aufs_bindex_t bindex;
1facf9fc 36872+
36873+ ldir->hdir = NULL;
acd2b654 36874+ bindex = au_xi_root(sb, xipath->dentry);
1facf9fc 36875+ if (bindex >= 0) {
062440b3 36876+ /* rw branch root */
5527c038 36877+ ldir->hdir = au_hi(d_inode(sb->s_root), bindex);
5afbbe0d 36878+ au_hn_inode_lock_nested(ldir->hdir, AuLsc_I_PARENT);
1facf9fc 36879+ } else {
062440b3
AM
36880+ /* other */
36881+ ldir->parent = au_dget_parent_lock(xipath->dentry,
36882+ AuLsc_I_PARENT);
febd17d6 36883+ ldir->dir = d_inode(ldir->parent);
1facf9fc 36884+ }
36885+}
36886+
36887+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
36888+{
36889+ if (ldir->hdir)
5afbbe0d 36890+ au_hn_inode_unlock(ldir->hdir);
1facf9fc 36891+ else {
febd17d6 36892+ inode_unlock(ldir->dir);
1facf9fc 36893+ dput(ldir->parent);
36894+ }
36895+}
36896+
36897+/* ---------------------------------------------------------------------- */
36898+
062440b3
AM
36899+/*
36900+ * create and set a new xino file
36901+ */
83b672a5
AM
36902+struct file *au_xino_create(struct super_block *sb, char *fpath, int silent,
36903+ int wbrtop)
062440b3
AM
36904+{
36905+ struct file *file;
36906+ struct dentry *h_parent, *d;
36907+ struct inode *h_dir, *inode;
36908+ int err;
83b672a5 36909+ static DEFINE_MUTEX(mtx);
062440b3
AM
36910+
36911+ /*
36912+ * at mount-time, and the xino file is the default path,
36913+ * hnotify is disabled so we have no notify events to ignore.
36914+ * when a user specified the xino, we cannot get au_hdir to be ignored.
36915+ */
83b672a5
AM
36916+ if (!wbrtop)
36917+ mutex_lock(&mtx);
062440b3
AM
36918+ file = vfsub_filp_open(fpath, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
36919+ /* | __FMODE_NONOTIFY */,
cd7a4cd9 36920+ 0666);
062440b3 36921+ if (IS_ERR(file)) {
83b672a5
AM
36922+ if (!wbrtop)
36923+ mutex_unlock(&mtx);
062440b3
AM
36924+ if (!silent)
36925+ pr_err("open %s(%ld)\n", fpath, PTR_ERR(file));
36926+ return file;
36927+ }
36928+
36929+ /* keep file count */
36930+ err = 0;
36931+ d = file->f_path.dentry;
36932+ h_parent = au_dget_parent_lock(d, AuLsc_I_PARENT);
83b672a5
AM
36933+ if (!wbrtop)
36934+ mutex_unlock(&mtx);
062440b3
AM
36935+ /* mnt_want_write() is unnecessary here */
36936+ h_dir = d_inode(h_parent);
36937+ inode = file_inode(file);
36938+ /* no delegation since it is just created */
36939+ if (inode->i_nlink)
36940+ err = vfsub_unlink(h_dir, &file->f_path, /*delegated*/NULL,
36941+ /*force*/0);
36942+ inode_unlock(h_dir);
36943+ dput(h_parent);
36944+ if (unlikely(err)) {
36945+ if (!silent)
36946+ pr_err("unlink %s(%d)\n", fpath, err);
36947+ goto out;
36948+ }
36949+
36950+ err = -EINVAL;
36951+ if (unlikely(sb == d->d_sb)) {
36952+ if (!silent)
36953+ pr_err("%s must be outside\n", fpath);
36954+ goto out;
36955+ }
36956+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
36957+ if (!silent)
36958+ pr_err("xino doesn't support %s(%s)\n",
36959+ fpath, au_sbtype(d->d_sb));
36960+ goto out;
36961+ }
36962+ return file; /* success */
36963+
36964+out:
36965+ fput(file);
36966+ file = ERR_PTR(err);
36967+ return file;
36968+}
36969+
36970+/*
36971+ * create a new xinofile at the same place/path as @base.
36972+ */
36973+struct file *au_xino_create2(struct super_block *sb, struct path *base,
36974+ struct file *copy_src)
36975+{
36976+ struct file *file;
758e9dad 36977+ struct dentry *dentry;
062440b3
AM
36978+ struct inode *dir, *delegated;
36979+ struct qstr *name;
758e9dad 36980+ struct path ppath, path;
062440b3
AM
36981+ int err, do_unlock;
36982+ struct au_xino_lock_dir ldir;
36983+
36984+ do_unlock = 1;
36985+ au_xino_lock_dir(sb, base, &ldir);
36986+ dentry = base->dentry;
758e9dad
AM
36987+ ppath.dentry = dentry->d_parent; /* dir inode is locked */
36988+ ppath.mnt = base->mnt;
36989+ dir = d_inode(ppath.dentry);
062440b3
AM
36990+ IMustLock(dir);
36991+
36992+ name = &dentry->d_name;
758e9dad 36993+ path.dentry = vfsub_lookup_one_len(name->name, &ppath, name->len);
062440b3
AM
36994+ if (IS_ERR(path.dentry)) {
36995+ file = (void *)path.dentry;
36996+ pr_err("%pd lookup err %ld\n", dentry, PTR_ERR(path.dentry));
36997+ goto out;
36998+ }
36999+
37000+ /* no need to mnt_want_write() since we call dentry_open() later */
0b2a12c6 37001+ err = vfs_create(mnt_user_ns(base->mnt), dir, path.dentry, 0666, NULL);
062440b3
AM
37002+ if (unlikely(err)) {
37003+ file = ERR_PTR(err);
37004+ pr_err("%pd create err %d\n", dentry, err);
37005+ goto out_dput;
37006+ }
37007+
37008+ path.mnt = base->mnt;
37009+ file = vfsub_dentry_open(&path,
37010+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
37011+ /* | __FMODE_NONOTIFY */);
37012+ if (IS_ERR(file)) {
37013+ pr_err("%pd open err %ld\n", dentry, PTR_ERR(file));
37014+ goto out_dput;
37015+ }
37016+
37017+ delegated = NULL;
37018+ err = vfsub_unlink(dir, &file->f_path, &delegated, /*force*/0);
37019+ au_xino_unlock_dir(&ldir);
37020+ do_unlock = 0;
37021+ if (unlikely(err == -EWOULDBLOCK)) {
37022+ pr_warn("cannot retry for NFSv4 delegation"
37023+ " for an internal unlink\n");
37024+ iput(delegated);
37025+ }
37026+ if (unlikely(err)) {
37027+ pr_err("%pd unlink err %d\n", dentry, err);
37028+ goto out_fput;
37029+ }
37030+
37031+ if (copy_src) {
37032+ /* no one can touch copy_src xino */
37033+ err = au_copy_file(file, copy_src, vfsub_f_size_read(copy_src));
37034+ if (unlikely(err)) {
37035+ pr_err("%pd copy err %d\n", dentry, err);
37036+ goto out_fput;
37037+ }
37038+ }
37039+ goto out_dput; /* success */
1facf9fc 37040+
062440b3
AM
37041+out_fput:
37042+ fput(file);
37043+ file = ERR_PTR(err);
37044+out_dput:
37045+ dput(path.dentry);
37046+out:
37047+ if (do_unlock)
37048+ au_xino_unlock_dir(&ldir);
37049+ return file;
37050+}
37051+
acd2b654
AM
37052+struct file *au_xino_file1(struct au_xino *xi)
37053+{
37054+ struct file *file;
37055+ unsigned int u, nfile;
37056+
37057+ file = NULL;
37058+ nfile = xi->xi_nfile;
37059+ for (u = 0; u < nfile; u++) {
37060+ file = xi->xi_file[u];
37061+ if (file)
37062+ break;
37063+ }
37064+
37065+ return file;
37066+}
37067+
37068+static int au_xino_file_set(struct au_xino *xi, int idx, struct file *file)
37069+{
37070+ int err;
37071+ struct file *f;
37072+ void *p;
37073+
37074+ if (file)
37075+ get_file(file);
37076+
37077+ err = 0;
37078+ f = NULL;
37079+ if (idx < xi->xi_nfile) {
37080+ f = xi->xi_file[idx];
37081+ if (f)
37082+ fput(f);
37083+ } else {
37084+ p = au_kzrealloc(xi->xi_file,
37085+ sizeof(*xi->xi_file) * xi->xi_nfile,
37086+ sizeof(*xi->xi_file) * (idx + 1),
37087+ GFP_NOFS, /*may_shrink*/0);
37088+ if (p) {
37089+ MtxMustLock(&xi->xi_mtx);
37090+ xi->xi_file = p;
37091+ xi->xi_nfile = idx + 1;
37092+ } else {
37093+ err = -ENOMEM;
37094+ if (file)
37095+ fput(file);
37096+ goto out;
37097+ }
37098+ }
37099+ xi->xi_file[idx] = file;
37100+
37101+out:
37102+ return err;
37103+}
37104+
37105+/*
37106+ * if @xinew->xi is not set, then create new xigen file.
37107+ */
37108+struct file *au_xi_new(struct super_block *sb, struct au_xi_new *xinew)
37109+{
37110+ struct file *file;
37111+ int err;
37112+
37113+ SiMustAnyLock(sb);
37114+
37115+ file = au_xino_create2(sb, xinew->base, xinew->copy_src);
37116+ if (IS_ERR(file)) {
37117+ err = PTR_ERR(file);
37118+ pr_err("%s[%d], err %d\n",
37119+ xinew->xi ? "xino" : "xigen",
37120+ xinew->idx, err);
37121+ goto out;
37122+ }
37123+
37124+ if (xinew->xi)
37125+ err = au_xino_file_set(xinew->xi, xinew->idx, file);
37126+ else {
37127+ BUG();
37128+ /* todo: make xigen file an array */
37129+ /* err = au_xigen_file_set(sb, xinew->idx, file); */
37130+ }
37131+ fput(file);
37132+ if (unlikely(err))
37133+ file = ERR_PTR(err);
37134+
37135+out:
37136+ return file;
37137+}
37138+
062440b3
AM
37139+/* ---------------------------------------------------------------------- */
37140+
37141+/*
37142+ * truncate xino files
37143+ */
acd2b654
AM
37144+static int au_xino_do_trunc(struct super_block *sb, aufs_bindex_t bindex,
37145+ int idx, struct kstatfs *st)
1facf9fc 37146+{
37147+ int err;
392086de 37148+ blkcnt_t blocks;
acd2b654
AM
37149+ struct file *file, *new_xino;
37150+ struct au_xi_new xinew = {
37151+ .idx = idx
37152+ };
37153+
37154+ err = 0;
37155+ xinew.xi = au_sbr(sb, bindex)->br_xino;
37156+ file = au_xino_file(xinew.xi, idx);
37157+ if (!file)
37158+ goto out;
37159+
37160+ xinew.base = &file->f_path;
37161+ err = vfs_statfs(xinew.base, st);
37162+ if (unlikely(err)) {
37163+ AuErr1("statfs err %d, ignored\n", err);
37164+ err = 0;
37165+ goto out;
37166+ }
37167+
37168+ blocks = file_inode(file)->i_blocks;
37169+ pr_info("begin truncating xino(b%d-%d), ib%llu, %llu/%llu free blks\n",
37170+ bindex, idx, (u64)blocks, st->f_bfree, st->f_blocks);
37171+
37172+ xinew.copy_src = file;
37173+ new_xino = au_xi_new(sb, &xinew);
37174+ if (IS_ERR(new_xino)) {
37175+ err = PTR_ERR(new_xino);
37176+ pr_err("xino(b%d-%d), err %d, ignored\n", bindex, idx, err);
37177+ goto out;
37178+ }
37179+
37180+ err = vfs_statfs(&new_xino->f_path, st);
37181+ if (!err)
37182+ pr_info("end truncating xino(b%d-%d), ib%llu, %llu/%llu free blks\n",
37183+ bindex, idx, (u64)file_inode(new_xino)->i_blocks,
37184+ st->f_bfree, st->f_blocks);
37185+ else {
37186+ AuErr1("statfs err %d, ignored\n", err);
37187+ err = 0;
37188+ }
37189+
37190+out:
37191+ return err;
37192+}
37193+
37194+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin)
37195+{
37196+ int err, i;
37197+ unsigned long jiffy;
062440b3 37198+ aufs_bindex_t bbot;
392086de 37199+ struct kstatfs *st;
1facf9fc 37200+ struct au_branch *br;
acd2b654 37201+ struct au_xino *xi;
1facf9fc 37202+
392086de 37203+ err = -ENOMEM;
be52b249 37204+ st = kmalloc(sizeof(*st), GFP_NOFS);
392086de
AM
37205+ if (unlikely(!st))
37206+ goto out;
37207+
1facf9fc 37208+ err = -EINVAL;
5afbbe0d
AM
37209+ bbot = au_sbbot(sb);
37210+ if (unlikely(bindex < 0 || bbot < bindex))
392086de 37211+ goto out_st;
392086de 37212+
1facf9fc 37213+ err = 0;
acd2b654
AM
37214+ jiffy = jiffies;
37215+ br = au_sbr(sb, bindex);
37216+ xi = br->br_xino;
37217+ for (i = idx_begin; !err && i < xi->xi_nfile; i++)
37218+ err = au_xino_do_trunc(sb, bindex, i, st);
37219+ if (!err)
37220+ au_sbi(sb)->si_xino_jiffy = jiffy;
392086de
AM
37221+
37222+out_st:
9f237c51 37223+ au_kfree_rcu(st);
4f0767ce 37224+out:
1facf9fc 37225+ return err;
37226+}
37227+
37228+struct xino_do_trunc_args {
37229+ struct super_block *sb;
37230+ struct au_branch *br;
acd2b654 37231+ int idx;
1facf9fc 37232+};
37233+
37234+static void xino_do_trunc(void *_args)
37235+{
37236+ struct xino_do_trunc_args *args = _args;
37237+ struct super_block *sb;
37238+ struct au_branch *br;
37239+ struct inode *dir;
acd2b654 37240+ int err, idx;
1facf9fc 37241+ aufs_bindex_t bindex;
37242+
37243+ err = 0;
37244+ sb = args->sb;
5527c038 37245+ dir = d_inode(sb->s_root);
1facf9fc 37246+ br = args->br;
acd2b654 37247+ idx = args->idx;
1facf9fc 37248+
37249+ si_noflush_write_lock(sb);
37250+ ii_read_lock_parent(dir);
37251+ bindex = au_br_index(sb, br->br_id);
acd2b654 37252+ err = au_xino_trunc(sb, bindex, idx);
1facf9fc 37253+ ii_read_unlock(dir);
37254+ if (unlikely(err))
392086de 37255+ pr_warn("err b%d, (%d)\n", bindex, err);
062440b3 37256+ atomic_dec(&br->br_xino->xi_truncating);
acd2b654 37257+ au_lcnt_dec(&br->br_count);
1facf9fc 37258+ si_write_unlock(sb);
027c5e7a 37259+ au_nwt_done(&au_sbi(sb)->si_nowait);
9f237c51 37260+ au_kfree_rcu(args);
1facf9fc 37261+}
37262+
acd2b654
AM
37263+/*
37264+ * returns the index in the xi_file array whose corresponding file is necessary
37265+ * to truncate, or -1 which means no need to truncate.
37266+ */
392086de
AM
37267+static int xino_trunc_test(struct super_block *sb, struct au_branch *br)
37268+{
37269+ int err;
acd2b654 37270+ unsigned int u;
392086de
AM
37271+ struct kstatfs st;
37272+ struct au_sbinfo *sbinfo;
acd2b654 37273+ struct au_xino *xi;
062440b3 37274+ struct file *file;
392086de
AM
37275+
37276+ /* todo: si_xino_expire and the ratio should be customizable */
37277+ sbinfo = au_sbi(sb);
37278+ if (time_before(jiffies,
37279+ sbinfo->si_xino_jiffy + sbinfo->si_xino_expire))
acd2b654 37280+ return -1;
392086de
AM
37281+
37282+ /* truncation border */
acd2b654
AM
37283+ xi = br->br_xino;
37284+ for (u = 0; u < xi->xi_nfile; u++) {
37285+ file = au_xino_file(xi, u);
37286+ if (!file)
37287+ continue;
37288+
37289+ err = vfs_statfs(&file->f_path, &st);
37290+ if (unlikely(err)) {
37291+ AuErr1("statfs err %d, ignored\n", err);
37292+ return -1;
37293+ }
37294+ if (div64_u64(st.f_bfree * 100, st.f_blocks)
37295+ >= AUFS_XINO_DEF_TRUNC)
37296+ return u;
392086de 37297+ }
392086de 37298+
acd2b654 37299+ return -1;
392086de
AM
37300+}
37301+
1facf9fc 37302+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
37303+{
acd2b654 37304+ int idx;
1facf9fc 37305+ struct xino_do_trunc_args *args;
37306+ int wkq_err;
37307+
acd2b654
AM
37308+ idx = xino_trunc_test(sb, br);
37309+ if (idx < 0)
1facf9fc 37310+ return;
37311+
062440b3 37312+ if (atomic_inc_return(&br->br_xino->xi_truncating) > 1)
1facf9fc 37313+ goto out;
37314+
37315+ /* lock and kfree() will be called in trunc_xino() */
37316+ args = kmalloc(sizeof(*args), GFP_NOFS);
37317+ if (unlikely(!args)) {
37318+ AuErr1("no memory\n");
f0c0a007 37319+ goto out;
1facf9fc 37320+ }
37321+
acd2b654 37322+ au_lcnt_inc(&br->br_count);
1facf9fc 37323+ args->sb = sb;
37324+ args->br = br;
acd2b654 37325+ args->idx = idx;
53392da6 37326+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb, /*flags*/0);
1facf9fc 37327+ if (!wkq_err)
37328+ return; /* success */
37329+
4a4d8108 37330+ pr_err("wkq %d\n", wkq_err);
acd2b654 37331+ au_lcnt_dec(&br->br_count);
9f237c51 37332+ au_kfree_rcu(args);
1facf9fc 37333+
4f0767ce 37334+out:
062440b3 37335+ atomic_dec(&br->br_xino->xi_truncating);
1facf9fc 37336+}
37337+
37338+/* ---------------------------------------------------------------------- */
37339+
acd2b654
AM
37340+struct au_xi_calc {
37341+ int idx;
37342+ loff_t pos;
37343+};
37344+
37345+static void au_xi_calc(struct super_block *sb, ino_t h_ino,
37346+ struct au_xi_calc *calc)
37347+{
37348+ loff_t maxent;
37349+
37350+ maxent = au_xi_maxent(sb);
37351+ calc->idx = div64_u64_rem(h_ino, maxent, &calc->pos);
37352+ calc->pos *= sizeof(ino_t);
37353+}
37354+
37355+static int au_xino_do_new_async(struct super_block *sb, struct au_branch *br,
37356+ struct au_xi_calc *calc)
37357+{
37358+ int err;
37359+ struct file *file;
37360+ struct au_xino *xi = br->br_xino;
37361+ struct au_xi_new xinew = {
37362+ .xi = xi
37363+ };
37364+
37365+ SiMustAnyLock(sb);
37366+
37367+ err = 0;
37368+ if (!xi)
37369+ goto out;
37370+
37371+ mutex_lock(&xi->xi_mtx);
37372+ file = au_xino_file(xi, calc->idx);
37373+ if (file)
37374+ goto out_mtx;
37375+
37376+ file = au_xino_file(xi, /*idx*/-1);
37377+ AuDebugOn(!file);
37378+ xinew.idx = calc->idx;
37379+ xinew.base = &file->f_path;
37380+ /* xinew.copy_src = NULL; */
37381+ file = au_xi_new(sb, &xinew);
37382+ if (IS_ERR(file))
37383+ err = PTR_ERR(file);
37384+
37385+out_mtx:
37386+ mutex_unlock(&xi->xi_mtx);
37387+out:
37388+ return err;
37389+}
37390+
37391+struct au_xino_do_new_async_args {
37392+ struct super_block *sb;
37393+ struct au_branch *br;
37394+ struct au_xi_calc calc;
37395+ ino_t ino;
37396+};
37397+
9f237c51
AM
37398+struct au_xi_writing {
37399+ struct hlist_bl_node node;
37400+ ino_t h_ino, ino;
37401+};
37402+
e37dd06a
AM
37403+static int au_xino_do_write(struct file *file, struct au_xi_calc *calc,
37404+ ino_t ino);
acd2b654
AM
37405+
37406+static void au_xino_call_do_new_async(void *args)
37407+{
37408+ struct au_xino_do_new_async_args *a = args;
37409+ struct au_branch *br;
37410+ struct super_block *sb;
37411+ struct au_sbinfo *sbi;
37412+ struct inode *root;
37413+ struct file *file;
9f237c51
AM
37414+ struct au_xi_writing *del, *p;
37415+ struct hlist_bl_head *hbl;
37416+ struct hlist_bl_node *pos;
acd2b654
AM
37417+ int err;
37418+
37419+ br = a->br;
37420+ sb = a->sb;
37421+ sbi = au_sbi(sb);
37422+ si_noflush_read_lock(sb);
37423+ root = d_inode(sb->s_root);
37424+ ii_read_lock_child(root);
37425+ err = au_xino_do_new_async(sb, br, &a->calc);
9f237c51
AM
37426+ if (unlikely(err)) {
37427+ AuIOErr("err %d\n", err);
37428+ goto out;
37429+ }
37430+
37431+ file = au_xino_file(br->br_xino, a->calc.idx);
37432+ AuDebugOn(!file);
e37dd06a 37433+ err = au_xino_do_write(file, &a->calc, a->ino);
9f237c51 37434+ if (unlikely(err)) {
acd2b654 37435+ AuIOErr("err %d\n", err);
9f237c51
AM
37436+ goto out;
37437+ }
37438+
37439+ del = NULL;
37440+ hbl = &br->br_xino->xi_writing;
37441+ hlist_bl_lock(hbl);
37442+ au_hbl_for_each(pos, hbl) {
37443+ p = container_of(pos, struct au_xi_writing, node);
37444+ if (p->ino == a->ino) {
37445+ del = p;
37446+ hlist_bl_del(&p->node);
37447+ break;
37448+ }
37449+ }
37450+ hlist_bl_unlock(hbl);
37451+ au_kfree_rcu(del);
37452+
37453+out:
acd2b654
AM
37454+ au_lcnt_dec(&br->br_count);
37455+ ii_read_unlock(root);
37456+ si_read_unlock(sb);
37457+ au_nwt_done(&sbi->si_nowait);
9f237c51 37458+ au_kfree_rcu(a);
acd2b654
AM
37459+}
37460+
37461+/*
37462+ * create a new xino file asynchronously
37463+ */
37464+static int au_xino_new_async(struct super_block *sb, struct au_branch *br,
37465+ struct au_xi_calc *calc, ino_t ino)
37466+{
37467+ int err;
37468+ struct au_xino_do_new_async_args *arg;
37469+
37470+ err = -ENOMEM;
37471+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
37472+ if (unlikely(!arg))
37473+ goto out;
37474+
37475+ arg->sb = sb;
37476+ arg->br = br;
37477+ arg->calc = *calc;
37478+ arg->ino = ino;
37479+ au_lcnt_inc(&br->br_count);
37480+ err = au_wkq_nowait(au_xino_call_do_new_async, arg, sb, AuWkq_NEST);
37481+ if (unlikely(err)) {
37482+ pr_err("wkq %d\n", err);
37483+ au_lcnt_dec(&br->br_count);
9f237c51 37484+ au_kfree_rcu(arg);
acd2b654
AM
37485+ }
37486+
37487+out:
37488+ return err;
37489+}
37490+
062440b3
AM
37491+/*
37492+ * read @ino from xinofile for the specified branch{@sb, @bindex}
37493+ * at the position of @h_ino.
37494+ */
37495+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
37496+ ino_t *ino)
37497+{
37498+ int err;
37499+ ssize_t sz;
acd2b654 37500+ struct au_xi_calc calc;
062440b3 37501+ struct au_sbinfo *sbinfo;
acd2b654 37502+ struct file *file;
9f237c51
AM
37503+ struct au_xino *xi;
37504+ struct hlist_bl_head *hbl;
37505+ struct hlist_bl_node *pos;
37506+ struct au_xi_writing *p;
062440b3
AM
37507+
37508+ *ino = 0;
37509+ if (!au_opt_test(au_mntflags(sb), XINO))
37510+ return 0; /* no xino */
37511+
37512+ err = 0;
acd2b654 37513+ au_xi_calc(sb, h_ino, &calc);
9f237c51
AM
37514+ xi = au_sbr(sb, bindex)->br_xino;
37515+ file = au_xino_file(xi, calc.idx);
37516+ if (!file) {
37517+ hbl = &xi->xi_writing;
37518+ hlist_bl_lock(hbl);
37519+ au_hbl_for_each(pos, hbl) {
37520+ p = container_of(pos, struct au_xi_writing, node);
37521+ if (p->h_ino == h_ino) {
37522+ AuDbg("hi%llu, i%llu, found\n",
37523+ (u64)p->h_ino, (u64)p->ino);
37524+ *ino = p->ino;
37525+ break;
37526+ }
37527+ }
37528+ hlist_bl_unlock(hbl);
37529+ return 0;
37530+ } else if (vfsub_f_size_read(file) < calc.pos + sizeof(*ino))
37531+ return 0; /* no xino */
062440b3 37532+
acd2b654 37533+ sbinfo = au_sbi(sb);
e37dd06a 37534+ sz = xino_fread(file, ino, sizeof(*ino), &calc.pos);
062440b3
AM
37535+ if (sz == sizeof(*ino))
37536+ return 0; /* success */
37537+
37538+ err = sz;
37539+ if (unlikely(sz >= 0)) {
37540+ err = -EIO;
37541+ AuIOErr("xino read error (%zd)\n", sz);
37542+ }
062440b3
AM
37543+ return err;
37544+}
37545+
e37dd06a
AM
37546+static int au_xino_do_write(struct file *file, struct au_xi_calc *calc,
37547+ ino_t ino)
1facf9fc 37548+{
1facf9fc 37549+ ssize_t sz;
37550+
e37dd06a 37551+ sz = xino_fwrite(file, &ino, sizeof(ino), &calc->pos);
1facf9fc 37552+ if (sz == sizeof(ino))
37553+ return 0; /* success */
37554+
37555+ AuIOErr("write failed (%zd)\n", sz);
37556+ return -EIO;
37557+}
37558+
37559+/*
37560+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
37561+ * at the position of @h_ino.
37562+ * even if @ino is zero, it is written to the xinofile and means no entry.
37563+ * if the size of the xino file on a specific filesystem exceeds the watermark,
37564+ * try truncating it.
37565+ */
37566+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
37567+ ino_t ino)
37568+{
37569+ int err;
37570+ unsigned int mnt_flags;
acd2b654
AM
37571+ struct au_xi_calc calc;
37572+ struct file *file;
1facf9fc 37573+ struct au_branch *br;
acd2b654 37574+ struct au_xino *xi;
9f237c51 37575+ struct au_xi_writing *p;
1facf9fc 37576+
dece6358 37577+ SiMustAnyLock(sb);
1facf9fc 37578+
37579+ mnt_flags = au_mntflags(sb);
37580+ if (!au_opt_test(mnt_flags, XINO))
37581+ return 0;
37582+
acd2b654 37583+ au_xi_calc(sb, h_ino, &calc);
1facf9fc 37584+ br = au_sbr(sb, bindex);
acd2b654
AM
37585+ xi = br->br_xino;
37586+ file = au_xino_file(xi, calc.idx);
37587+ if (!file) {
9f237c51
AM
37588+ /* store the inum pair into the list */
37589+ p = kmalloc(sizeof(*p), GFP_NOFS | __GFP_NOFAIL);
37590+ p->h_ino = h_ino;
37591+ p->ino = ino;
37592+ au_hbl_add(&p->node, &xi->xi_writing);
37593+
acd2b654
AM
37594+ /* create and write a new xino file asynchronously */
37595+ err = au_xino_new_async(sb, br, &calc, ino);
37596+ if (!err)
37597+ return 0; /* success */
37598+ goto out;
37599+ }
37600+
e37dd06a 37601+ err = au_xino_do_write(file, &calc, ino);
1facf9fc 37602+ if (!err) {
acd2b654 37603+ br = au_sbr(sb, bindex);
1facf9fc 37604+ if (au_opt_test(mnt_flags, TRUNC_XINO)
86dc4139 37605+ && au_test_fs_trunc_xino(au_br_sb(br)))
1facf9fc 37606+ xino_try_trunc(sb, br);
37607+ return 0; /* success */
37608+ }
37609+
acd2b654 37610+out:
1facf9fc 37611+ AuIOErr("write failed (%d)\n", err);
37612+ return -EIO;
37613+}
37614+
e37dd06a
AM
37615+static ssize_t xino_fread_wkq(struct file *file, void *buf, size_t size,
37616+ loff_t *pos);
1facf9fc 37617+
062440b3 37618+/* todo: unnecessary to support mmap_sem since kernel-space? */
e37dd06a 37619+ssize_t xino_fread(struct file *file, void *kbuf, size_t size, loff_t *pos)
062440b3
AM
37620+{
37621+ ssize_t err;
062440b3
AM
37622+ int i;
37623+ const int prevent_endless = 10;
1facf9fc 37624+
062440b3 37625+ i = 0;
062440b3 37626+ do {
e37dd06a 37627+ err = vfsub_read_k(file, kbuf, size, pos);
062440b3
AM
37628+ if (err == -EINTR
37629+ && !au_wkq_test()
37630+ && fatal_signal_pending(current)) {
e37dd06a 37631+ err = xino_fread_wkq(file, kbuf, size, pos);
062440b3 37632+ BUG_ON(err == -EINTR);
062440b3
AM
37633+ }
37634+ } while (i++ < prevent_endless
37635+ && (err == -EAGAIN || err == -EINTR));
062440b3
AM
37636+
37637+#if 0 /* reserved for future use */
37638+ if (err > 0)
37639+ fsnotify_access(file->f_path.dentry);
37640+#endif
37641+
37642+ return err;
37643+}
37644+
37645+struct xino_fread_args {
37646+ ssize_t *errp;
062440b3
AM
37647+ struct file *file;
37648+ void *buf;
37649+ size_t size;
37650+ loff_t *pos;
37651+};
37652+
37653+static void call_xino_fread(void *args)
37654+{
37655+ struct xino_fread_args *a = args;
e37dd06a 37656+ *a->errp = xino_fread(a->file, a->buf, a->size, a->pos);
062440b3
AM
37657+}
37658+
e37dd06a
AM
37659+static ssize_t xino_fread_wkq(struct file *file, void *buf, size_t size,
37660+ loff_t *pos)
062440b3
AM
37661+{
37662+ ssize_t err;
37663+ int wkq_err;
37664+ struct xino_fread_args args = {
37665+ .errp = &err,
062440b3
AM
37666+ .file = file,
37667+ .buf = buf,
37668+ .size = size,
37669+ .pos = pos
37670+ };
37671+
37672+ wkq_err = au_wkq_wait(call_xino_fread, &args);
37673+ if (unlikely(wkq_err))
37674+ err = wkq_err;
37675+
37676+ return err;
37677+}
37678+
e37dd06a
AM
37679+static ssize_t xino_fwrite_wkq(struct file *file, void *buf, size_t size,
37680+ loff_t *pos);
062440b3 37681+
e37dd06a
AM
37682+static ssize_t do_xino_fwrite(struct file *file, void *kbuf, size_t size,
37683+ loff_t *pos)
062440b3
AM
37684+{
37685+ ssize_t err;
062440b3
AM
37686+ int i;
37687+ const int prevent_endless = 10;
37688+
37689+ i = 0;
062440b3 37690+ do {
e37dd06a 37691+ err = vfsub_write_k(file, kbuf, size, pos);
062440b3
AM
37692+ if (err == -EINTR
37693+ && !au_wkq_test()
37694+ && fatal_signal_pending(current)) {
e37dd06a 37695+ err = xino_fwrite_wkq(file, kbuf, size, pos);
062440b3 37696+ BUG_ON(err == -EINTR);
062440b3
AM
37697+ }
37698+ } while (i++ < prevent_endless
37699+ && (err == -EAGAIN || err == -EINTR));
062440b3
AM
37700+
37701+#if 0 /* reserved for future use */
37702+ if (err > 0)
37703+ fsnotify_modify(file->f_path.dentry);
37704+#endif
37705+
37706+ return err;
37707+}
37708+
37709+struct do_xino_fwrite_args {
37710+ ssize_t *errp;
062440b3
AM
37711+ struct file *file;
37712+ void *buf;
37713+ size_t size;
37714+ loff_t *pos;
37715+};
37716+
37717+static void call_do_xino_fwrite(void *args)
37718+{
37719+ struct do_xino_fwrite_args *a = args;
e37dd06a 37720+ *a->errp = do_xino_fwrite(a->file, a->buf, a->size, a->pos);
062440b3
AM
37721+}
37722+
e37dd06a
AM
37723+static ssize_t xino_fwrite_wkq(struct file *file, void *buf, size_t size,
37724+ loff_t *pos)
062440b3
AM
37725+{
37726+ ssize_t err;
37727+ int wkq_err;
37728+ struct do_xino_fwrite_args args = {
37729+ .errp = &err,
062440b3
AM
37730+ .file = file,
37731+ .buf = buf,
37732+ .size = size,
37733+ .pos = pos
37734+ };
37735+
37736+ /*
37737+ * it breaks RLIMIT_FSIZE and normal user's limit,
37738+ * users should care about quota and real 'filesystem full.'
37739+ */
37740+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
37741+ if (unlikely(wkq_err))
37742+ err = wkq_err;
37743+
37744+ return err;
37745+}
37746+
e37dd06a 37747+ssize_t xino_fwrite(struct file *file, void *buf, size_t size, loff_t *pos)
062440b3
AM
37748+{
37749+ ssize_t err;
37750+
37751+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
37752+ lockdep_off();
e37dd06a 37753+ err = do_xino_fwrite(file, buf, size, pos);
062440b3
AM
37754+ lockdep_on();
37755+ } else {
37756+ lockdep_off();
e37dd06a 37757+ err = xino_fwrite_wkq(file, buf, size, pos);
062440b3
AM
37758+ lockdep_on();
37759+ }
37760+
37761+ return err;
37762+}
37763+
37764+/* ---------------------------------------------------------------------- */
37765+
37766+/*
37767+ * inode number bitmap
37768+ */
1facf9fc 37769+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
37770+static ino_t xib_calc_ino(unsigned long pindex, int bit)
37771+{
37772+ ino_t ino;
37773+
37774+ AuDebugOn(bit < 0 || page_bits <= bit);
37775+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
37776+ return ino;
37777+}
37778+
37779+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
37780+{
37781+ AuDebugOn(ino < AUFS_FIRST_INO);
37782+ ino -= AUFS_FIRST_INO;
37783+ *pindex = ino / page_bits;
37784+ *bit = ino % page_bits;
37785+}
37786+
37787+static int xib_pindex(struct super_block *sb, unsigned long pindex)
37788+{
37789+ int err;
37790+ loff_t pos;
37791+ ssize_t sz;
37792+ struct au_sbinfo *sbinfo;
37793+ struct file *xib;
37794+ unsigned long *p;
37795+
37796+ sbinfo = au_sbi(sb);
37797+ MtxMustLock(&sbinfo->si_xib_mtx);
37798+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
37799+ || !au_opt_test(sbinfo->si_mntflags, XINO));
37800+
37801+ if (pindex == sbinfo->si_xib_last_pindex)
37802+ return 0;
37803+
37804+ xib = sbinfo->si_xib;
37805+ p = sbinfo->si_xib_buf;
37806+ pos = sbinfo->si_xib_last_pindex;
37807+ pos *= PAGE_SIZE;
e37dd06a 37808+ sz = xino_fwrite(xib, p, PAGE_SIZE, &pos);
1facf9fc 37809+ if (unlikely(sz != PAGE_SIZE))
37810+ goto out;
37811+
37812+ pos = pindex;
37813+ pos *= PAGE_SIZE;
c06a8ce3 37814+ if (vfsub_f_size_read(xib) >= pos + PAGE_SIZE)
e37dd06a 37815+ sz = xino_fread(xib, p, PAGE_SIZE, &pos);
1facf9fc 37816+ else {
37817+ memset(p, 0, PAGE_SIZE);
e37dd06a 37818+ sz = xino_fwrite(xib, p, PAGE_SIZE, &pos);
1facf9fc 37819+ }
37820+ if (sz == PAGE_SIZE) {
37821+ sbinfo->si_xib_last_pindex = pindex;
37822+ return 0; /* success */
37823+ }
37824+
4f0767ce 37825+out:
b752ccd1
AM
37826+ AuIOErr1("write failed (%zd)\n", sz);
37827+ err = sz;
37828+ if (sz >= 0)
37829+ err = -EIO;
37830+ return err;
37831+}
37832+
b752ccd1
AM
37833+static void au_xib_clear_bit(struct inode *inode)
37834+{
37835+ int err, bit;
37836+ unsigned long pindex;
37837+ struct super_block *sb;
37838+ struct au_sbinfo *sbinfo;
37839+
37840+ AuDebugOn(inode->i_nlink);
37841+
37842+ sb = inode->i_sb;
37843+ xib_calc_bit(inode->i_ino, &pindex, &bit);
37844+ AuDebugOn(page_bits <= bit);
37845+ sbinfo = au_sbi(sb);
37846+ mutex_lock(&sbinfo->si_xib_mtx);
37847+ err = xib_pindex(sb, pindex);
37848+ if (!err) {
37849+ clear_bit(bit, sbinfo->si_xib_buf);
37850+ sbinfo->si_xib_next_bit = bit;
37851+ }
37852+ mutex_unlock(&sbinfo->si_xib_mtx);
37853+}
37854+
1facf9fc 37855+/* ---------------------------------------------------------------------- */
37856+
1facf9fc 37857+/*
062440b3 37858+ * truncate a xino bitmap file
1facf9fc 37859+ */
1facf9fc 37860+
37861+/* todo: slow */
37862+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
37863+{
37864+ int err, bit;
37865+ ssize_t sz;
37866+ unsigned long pindex;
37867+ loff_t pos, pend;
37868+ struct au_sbinfo *sbinfo;
1facf9fc 37869+ ino_t *ino;
37870+ unsigned long *p;
37871+
37872+ err = 0;
37873+ sbinfo = au_sbi(sb);
dece6358 37874+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 37875+ p = sbinfo->si_xib_buf;
c06a8ce3 37876+ pend = vfsub_f_size_read(file);
1facf9fc 37877+ pos = 0;
37878+ while (pos < pend) {
e37dd06a 37879+ sz = xino_fread(file, page, PAGE_SIZE, &pos);
1facf9fc 37880+ err = sz;
37881+ if (unlikely(sz <= 0))
37882+ goto out;
37883+
37884+ err = 0;
37885+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
37886+ if (unlikely(*ino < AUFS_FIRST_INO))
37887+ continue;
37888+
37889+ xib_calc_bit(*ino, &pindex, &bit);
37890+ AuDebugOn(page_bits <= bit);
37891+ err = xib_pindex(sb, pindex);
37892+ if (!err)
37893+ set_bit(bit, p);
37894+ else
37895+ goto out;
37896+ }
37897+ }
37898+
4f0767ce 37899+out:
1facf9fc 37900+ return err;
37901+}
37902+
37903+static int xib_restore(struct super_block *sb)
37904+{
acd2b654
AM
37905+ int err, i;
37906+ unsigned int nfile;
5afbbe0d 37907+ aufs_bindex_t bindex, bbot;
1facf9fc 37908+ void *page;
062440b3 37909+ struct au_branch *br;
acd2b654
AM
37910+ struct au_xino *xi;
37911+ struct file *file;
1facf9fc 37912+
37913+ err = -ENOMEM;
37914+ page = (void *)__get_free_page(GFP_NOFS);
37915+ if (unlikely(!page))
37916+ goto out;
37917+
37918+ err = 0;
5afbbe0d
AM
37919+ bbot = au_sbbot(sb);
37920+ for (bindex = 0; !err && bindex <= bbot; bindex++)
062440b3
AM
37921+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0) {
37922+ br = au_sbr(sb, bindex);
acd2b654
AM
37923+ xi = br->br_xino;
37924+ nfile = xi->xi_nfile;
37925+ for (i = 0; i < nfile; i++) {
37926+ file = au_xino_file(xi, i);
37927+ if (file)
37928+ err = do_xib_restore(sb, file, page);
37929+ }
062440b3
AM
37930+ } else
37931+ AuDbg("skip shared b%d\n", bindex);
1c60b727 37932+ free_page((unsigned long)page);
1facf9fc 37933+
4f0767ce 37934+out:
1facf9fc 37935+ return err;
37936+}
37937+
37938+int au_xib_trunc(struct super_block *sb)
37939+{
37940+ int err;
37941+ ssize_t sz;
37942+ loff_t pos;
1facf9fc 37943+ struct au_sbinfo *sbinfo;
37944+ unsigned long *p;
37945+ struct file *file;
37946+
dece6358
AM
37947+ SiMustWriteLock(sb);
37948+
1facf9fc 37949+ err = 0;
37950+ sbinfo = au_sbi(sb);
37951+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
37952+ goto out;
37953+
37954+ file = sbinfo->si_xib;
c06a8ce3 37955+ if (vfsub_f_size_read(file) <= PAGE_SIZE)
1facf9fc 37956+ goto out;
37957+
062440b3 37958+ file = au_xino_create2(sb, &sbinfo->si_xib->f_path, NULL);
1facf9fc 37959+ err = PTR_ERR(file);
37960+ if (IS_ERR(file))
37961+ goto out;
37962+ fput(sbinfo->si_xib);
37963+ sbinfo->si_xib = file;
37964+
37965+ p = sbinfo->si_xib_buf;
37966+ memset(p, 0, PAGE_SIZE);
37967+ pos = 0;
e37dd06a 37968+ sz = xino_fwrite(sbinfo->si_xib, p, PAGE_SIZE, &pos);
1facf9fc 37969+ if (unlikely(sz != PAGE_SIZE)) {
37970+ err = sz;
37971+ AuIOErr("err %d\n", err);
37972+ if (sz >= 0)
37973+ err = -EIO;
37974+ goto out;
37975+ }
37976+
37977+ mutex_lock(&sbinfo->si_xib_mtx);
37978+ /* mnt_want_write() is unnecessary here */
37979+ err = xib_restore(sb);
37980+ mutex_unlock(&sbinfo->si_xib_mtx);
37981+
37982+out:
37983+ return err;
37984+}
37985+
37986+/* ---------------------------------------------------------------------- */
37987+
acd2b654 37988+struct au_xino *au_xino_alloc(unsigned int nfile)
062440b3
AM
37989+{
37990+ struct au_xino *xi;
37991+
37992+ xi = kzalloc(sizeof(*xi), GFP_NOFS);
37993+ if (unlikely(!xi))
37994+ goto out;
acd2b654
AM
37995+ xi->xi_nfile = nfile;
37996+ xi->xi_file = kcalloc(nfile, sizeof(*xi->xi_file), GFP_NOFS);
37997+ if (unlikely(!xi->xi_file))
37998+ goto out_free;
062440b3
AM
37999+
38000+ xi->xi_nondir.total = 8; /* initial size */
38001+ xi->xi_nondir.array = kcalloc(xi->xi_nondir.total, sizeof(ino_t),
38002+ GFP_NOFS);
38003+ if (unlikely(!xi->xi_nondir.array))
acd2b654 38004+ goto out_file;
062440b3
AM
38005+
38006+ spin_lock_init(&xi->xi_nondir.spin);
38007+ init_waitqueue_head(&xi->xi_nondir.wqh);
acd2b654 38008+ mutex_init(&xi->xi_mtx);
9f237c51 38009+ INIT_HLIST_BL_HEAD(&xi->xi_writing);
062440b3
AM
38010+ atomic_set(&xi->xi_truncating, 0);
38011+ kref_init(&xi->xi_kref);
38012+ goto out; /* success */
38013+
acd2b654 38014+out_file:
9f237c51 38015+ au_kfree_try_rcu(xi->xi_file);
062440b3 38016+out_free:
9f237c51 38017+ au_kfree_rcu(xi);
062440b3
AM
38018+ xi = NULL;
38019+out:
38020+ return xi;
38021+}
38022+
acd2b654 38023+static int au_xino_init(struct au_branch *br, int idx, struct file *file)
062440b3
AM
38024+{
38025+ int err;
38026+ struct au_xino *xi;
38027+
38028+ err = 0;
acd2b654 38029+ xi = au_xino_alloc(idx + 1);
062440b3
AM
38030+ if (unlikely(!xi)) {
38031+ err = -ENOMEM;
38032+ goto out;
38033+ }
38034+
acd2b654
AM
38035+ if (file)
38036+ get_file(file);
38037+ xi->xi_file[idx] = file;
062440b3
AM
38038+ AuDebugOn(br->br_xino);
38039+ br->br_xino = xi;
38040+
38041+out:
38042+ return err;
38043+}
38044+
38045+static void au_xino_release(struct kref *kref)
38046+{
38047+ struct au_xino *xi;
38048+ int i;
9f237c51
AM
38049+ unsigned long ul;
38050+ struct hlist_bl_head *hbl;
38051+ struct hlist_bl_node *pos, *n;
38052+ struct au_xi_writing *p;
062440b3
AM
38053+
38054+ xi = container_of(kref, struct au_xino, xi_kref);
acd2b654
AM
38055+ for (i = 0; i < xi->xi_nfile; i++)
38056+ if (xi->xi_file[i])
38057+ fput(xi->xi_file[i]);
062440b3
AM
38058+ for (i = xi->xi_nondir.total - 1; i >= 0; i--)
38059+ AuDebugOn(xi->xi_nondir.array[i]);
acd2b654 38060+ mutex_destroy(&xi->xi_mtx);
9f237c51
AM
38061+ hbl = &xi->xi_writing;
38062+ ul = au_hbl_count(hbl);
38063+ if (unlikely(ul)) {
38064+ pr_warn("xi_writing %lu\n", ul);
38065+ hlist_bl_lock(hbl);
43982f53 38066+ hlist_bl_for_each_entry_safe(p, pos, n, hbl, node) {
9f237c51 38067+ hlist_bl_del(&p->node);
394e211a
AM
38068+ /* kmemleak reported au_kfree_rcu() doesn't free it */
38069+ kfree(p);
9f237c51
AM
38070+ }
38071+ hlist_bl_unlock(hbl);
38072+ }
38073+ au_kfree_try_rcu(xi->xi_file);
38074+ au_kfree_try_rcu(xi->xi_nondir.array);
38075+ au_kfree_rcu(xi);
062440b3
AM
38076+}
38077+
38078+int au_xino_put(struct au_branch *br)
38079+{
38080+ int ret;
38081+ struct au_xino *xi;
38082+
38083+ ret = 0;
38084+ xi = br->br_xino;
38085+ if (xi) {
38086+ br->br_xino = NULL;
38087+ ret = kref_put(&xi->xi_kref, au_xino_release);
38088+ }
38089+
38090+ return ret;
38091+}
38092+
062440b3
AM
38093+/* ---------------------------------------------------------------------- */
38094+
1facf9fc 38095+/*
38096+ * xino mount option handlers
38097+ */
1facf9fc 38098+
38099+/* xino bitmap */
38100+static void xino_clear_xib(struct super_block *sb)
38101+{
38102+ struct au_sbinfo *sbinfo;
38103+
dece6358
AM
38104+ SiMustWriteLock(sb);
38105+
1facf9fc 38106+ sbinfo = au_sbi(sb);
1facf9fc 38107+ if (sbinfo->si_xib)
38108+ fput(sbinfo->si_xib);
38109+ sbinfo->si_xib = NULL;
f0c0a007 38110+ if (sbinfo->si_xib_buf)
1c60b727 38111+ free_page((unsigned long)sbinfo->si_xib_buf);
1facf9fc 38112+ sbinfo->si_xib_buf = NULL;
38113+}
38114+
062440b3 38115+static int au_xino_set_xib(struct super_block *sb, struct path *path)
1facf9fc 38116+{
38117+ int err;
38118+ loff_t pos;
38119+ struct au_sbinfo *sbinfo;
38120+ struct file *file;
acd2b654 38121+ struct super_block *xi_sb;
1facf9fc 38122+
dece6358
AM
38123+ SiMustWriteLock(sb);
38124+
1facf9fc 38125+ sbinfo = au_sbi(sb);
062440b3 38126+ file = au_xino_create2(sb, path, sbinfo->si_xib);
1facf9fc 38127+ err = PTR_ERR(file);
38128+ if (IS_ERR(file))
38129+ goto out;
38130+ if (sbinfo->si_xib)
38131+ fput(sbinfo->si_xib);
38132+ sbinfo->si_xib = file;
acd2b654
AM
38133+ xi_sb = file_inode(file)->i_sb;
38134+ sbinfo->si_ximaxent = xi_sb->s_maxbytes;
38135+ if (unlikely(sbinfo->si_ximaxent < PAGE_SIZE)) {
38136+ err = -EIO;
38137+ pr_err("s_maxbytes(%llu) on %s is too small\n",
38138+ (u64)sbinfo->si_ximaxent, au_sbtype(xi_sb));
38139+ goto out_unset;
38140+ }
38141+ sbinfo->si_ximaxent /= sizeof(ino_t);
1facf9fc 38142+
38143+ err = -ENOMEM;
38144+ if (!sbinfo->si_xib_buf)
38145+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
38146+ if (unlikely(!sbinfo->si_xib_buf))
38147+ goto out_unset;
38148+
38149+ sbinfo->si_xib_last_pindex = 0;
38150+ sbinfo->si_xib_next_bit = 0;
c06a8ce3 38151+ if (vfsub_f_size_read(file) < PAGE_SIZE) {
1facf9fc 38152+ pos = 0;
e37dd06a 38153+ err = xino_fwrite(file, sbinfo->si_xib_buf, PAGE_SIZE, &pos);
1facf9fc 38154+ if (unlikely(err != PAGE_SIZE))
38155+ goto out_free;
38156+ }
38157+ err = 0;
38158+ goto out; /* success */
38159+
4f0767ce 38160+out_free:
f0c0a007 38161+ if (sbinfo->si_xib_buf)
1c60b727 38162+ free_page((unsigned long)sbinfo->si_xib_buf);
b752ccd1
AM
38163+ sbinfo->si_xib_buf = NULL;
38164+ if (err >= 0)
38165+ err = -EIO;
4f0767ce 38166+out_unset:
b752ccd1
AM
38167+ fput(sbinfo->si_xib);
38168+ sbinfo->si_xib = NULL;
4f0767ce 38169+out:
062440b3 38170+ AuTraceErr(err);
b752ccd1 38171+ return err;
1facf9fc 38172+}
38173+
b752ccd1
AM
38174+/* xino for each branch */
38175+static void xino_clear_br(struct super_block *sb)
38176+{
5afbbe0d 38177+ aufs_bindex_t bindex, bbot;
b752ccd1 38178+ struct au_branch *br;
1facf9fc 38179+
5afbbe0d
AM
38180+ bbot = au_sbbot(sb);
38181+ for (bindex = 0; bindex <= bbot; bindex++) {
b752ccd1 38182+ br = au_sbr(sb, bindex);
062440b3
AM
38183+ AuDebugOn(!br);
38184+ au_xino_put(br);
38185+ }
38186+}
38187+
38188+static void au_xino_set_br_shared(struct super_block *sb, struct au_branch *br,
38189+ aufs_bindex_t bshared)
38190+{
38191+ struct au_branch *brshared;
b752ccd1 38192+
062440b3
AM
38193+ brshared = au_sbr(sb, bshared);
38194+ AuDebugOn(!brshared->br_xino);
38195+ AuDebugOn(!brshared->br_xino->xi_file);
38196+ if (br->br_xino != brshared->br_xino) {
38197+ au_xino_get(brshared);
38198+ au_xino_put(br);
38199+ br->br_xino = brshared->br_xino;
b752ccd1
AM
38200+ }
38201+}
38202+
062440b3 38203+struct au_xino_do_set_br {
062440b3
AM
38204+ struct au_branch *br;
38205+ ino_t h_ino;
38206+ aufs_bindex_t bshared;
38207+};
38208+
38209+static int au_xino_do_set_br(struct super_block *sb, struct path *path,
38210+ struct au_xino_do_set_br *args)
1facf9fc 38211+{
38212+ int err;
acd2b654 38213+ struct au_xi_calc calc;
062440b3 38214+ struct file *file;
acd2b654
AM
38215+ struct au_branch *br;
38216+ struct au_xi_new xinew = {
38217+ .base = path
38218+ };
062440b3 38219+
acd2b654
AM
38220+ br = args->br;
38221+ xinew.xi = br->br_xino;
38222+ au_xi_calc(sb, args->h_ino, &calc);
38223+ xinew.copy_src = au_xino_file(xinew.xi, calc.idx);
38224+ if (args->bshared >= 0)
062440b3 38225+ /* shared xino */
acd2b654
AM
38226+ au_xino_set_br_shared(sb, br, args->bshared);
38227+ else if (!xinew.xi) {
38228+ /* new xino */
38229+ err = au_xino_init(br, calc.idx, xinew.copy_src);
38230+ if (unlikely(err))
38231+ goto out;
062440b3
AM
38232+ }
38233+
acd2b654
AM
38234+ /* force re-creating */
38235+ xinew.xi = br->br_xino;
38236+ xinew.idx = calc.idx;
38237+ mutex_lock(&xinew.xi->xi_mtx);
38238+ file = au_xi_new(sb, &xinew);
38239+ mutex_unlock(&xinew.xi->xi_mtx);
062440b3
AM
38240+ err = PTR_ERR(file);
38241+ if (IS_ERR(file))
38242+ goto out;
acd2b654
AM
38243+ AuDebugOn(!file);
38244+
e37dd06a 38245+ err = au_xino_do_write(file, &calc, AUFS_ROOT_INO);
acd2b654
AM
38246+ if (unlikely(err))
38247+ au_xino_put(br);
062440b3 38248+
062440b3
AM
38249+out:
38250+ AuTraceErr(err);
38251+ return err;
38252+}
38253+
38254+static int au_xino_set_br(struct super_block *sb, struct path *path)
38255+{
38256+ int err;
38257+ aufs_bindex_t bindex, bbot;
38258+ struct au_xino_do_set_br args;
b752ccd1 38259+ struct inode *inode;
1facf9fc 38260+
b752ccd1
AM
38261+ SiMustWriteLock(sb);
38262+
5afbbe0d 38263+ bbot = au_sbbot(sb);
5527c038 38264+ inode = d_inode(sb->s_root);
062440b3
AM
38265+ for (bindex = 0; bindex <= bbot; bindex++) {
38266+ args.h_ino = au_h_iptr(inode, bindex)->i_ino;
38267+ args.br = au_sbr(sb, bindex);
38268+ args.bshared = is_sb_shared(sb, bindex, bindex - 1);
38269+ err = au_xino_do_set_br(sb, path, &args);
b752ccd1 38270+ if (unlikely(err))
062440b3 38271+ break;
b752ccd1 38272+ }
1facf9fc 38273+
062440b3 38274+ AuTraceErr(err);
1facf9fc 38275+ return err;
38276+}
b752ccd1
AM
38277+
38278+void au_xino_clr(struct super_block *sb)
38279+{
38280+ struct au_sbinfo *sbinfo;
38281+
38282+ au_xigen_clr(sb);
38283+ xino_clear_xib(sb);
38284+ xino_clear_br(sb);
062440b3 38285+ dbgaufs_brs_del(sb, 0);
b752ccd1
AM
38286+ sbinfo = au_sbi(sb);
38287+ /* lvalue, do not call au_mntflags() */
38288+ au_opt_clr(sbinfo->si_mntflags, XINO);
38289+}
38290+
062440b3 38291+int au_xino_set(struct super_block *sb, struct au_opt_xino *xiopt, int remount)
b752ccd1
AM
38292+{
38293+ int err, skip;
062440b3 38294+ struct dentry *dentry, *parent, *cur_dentry, *cur_parent;
b752ccd1
AM
38295+ struct qstr *dname, *cur_name;
38296+ struct file *cur_xino;
b752ccd1 38297+ struct au_sbinfo *sbinfo;
062440b3 38298+ struct path *path, *cur_path;
b752ccd1
AM
38299+
38300+ SiMustWriteLock(sb);
38301+
38302+ err = 0;
38303+ sbinfo = au_sbi(sb);
062440b3
AM
38304+ path = &xiopt->file->f_path;
38305+ dentry = path->dentry;
38306+ parent = dget_parent(dentry);
b752ccd1
AM
38307+ if (remount) {
38308+ skip = 0;
b752ccd1
AM
38309+ cur_xino = sbinfo->si_xib;
38310+ if (cur_xino) {
062440b3
AM
38311+ cur_path = &cur_xino->f_path;
38312+ cur_dentry = cur_path->dentry;
38313+ cur_parent = dget_parent(cur_dentry);
38314+ cur_name = &cur_dentry->d_name;
38315+ dname = &dentry->d_name;
b752ccd1 38316+ skip = (cur_parent == parent
38d290e6 38317+ && au_qstreq(dname, cur_name));
b752ccd1
AM
38318+ dput(cur_parent);
38319+ }
38320+ if (skip)
38321+ goto out;
38322+ }
38323+
38324+ au_opt_set(sbinfo->si_mntflags, XINO);
062440b3
AM
38325+ err = au_xino_set_xib(sb, path);
38326+ /* si_x{read,write} are set */
b752ccd1 38327+ if (!err)
062440b3 38328+ err = au_xigen_set(sb, path);
b752ccd1 38329+ if (!err)
062440b3
AM
38330+ err = au_xino_set_br(sb, path);
38331+ if (!err) {
38332+ dbgaufs_brs_add(sb, 0, /*topdown*/1);
b752ccd1 38333+ goto out; /* success */
062440b3 38334+ }
b752ccd1
AM
38335+
38336+ /* reset all */
062440b3
AM
38337+ AuIOErr("failed setting xino(%d).\n", err);
38338+ au_xino_clr(sb);
b752ccd1 38339+
4f0767ce 38340+out:
b752ccd1
AM
38341+ dput(parent);
38342+ return err;
38343+}
38344+
b752ccd1
AM
38345+/*
38346+ * create a xinofile at the default place/path.
38347+ */
38348+struct file *au_xino_def(struct super_block *sb)
38349+{
38350+ struct file *file;
38351+ char *page, *p;
38352+ struct au_branch *br;
38353+ struct super_block *h_sb;
38354+ struct path path;
5afbbe0d 38355+ aufs_bindex_t bbot, bindex, bwr;
b752ccd1
AM
38356+
38357+ br = NULL;
5afbbe0d 38358+ bbot = au_sbbot(sb);
b752ccd1 38359+ bwr = -1;
5afbbe0d 38360+ for (bindex = 0; bindex <= bbot; bindex++) {
b752ccd1
AM
38361+ br = au_sbr(sb, bindex);
38362+ if (au_br_writable(br->br_perm)
86dc4139 38363+ && !au_test_fs_bad_xino(au_br_sb(br))) {
b752ccd1
AM
38364+ bwr = bindex;
38365+ break;
38366+ }
38367+ }
38368+
7f207e10
AM
38369+ if (bwr >= 0) {
38370+ file = ERR_PTR(-ENOMEM);
537831f9 38371+ page = (void *)__get_free_page(GFP_NOFS);
7f207e10
AM
38372+ if (unlikely(!page))
38373+ goto out;
86dc4139 38374+ path.mnt = au_br_mnt(br);
7f207e10
AM
38375+ path.dentry = au_h_dptr(sb->s_root, bwr);
38376+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
38377+ file = (void *)p;
38378+ if (!IS_ERR(p)) {
38379+ strcat(p, "/" AUFS_XINO_FNAME);
38380+ AuDbg("%s\n", p);
83b672a5 38381+ file = au_xino_create(sb, p, /*silent*/0, /*wbrtop*/1);
7f207e10 38382+ }
1c60b727 38383+ free_page((unsigned long)page);
7f207e10 38384+ } else {
83b672a5
AM
38385+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0,
38386+ /*wbrtop*/0);
7f207e10
AM
38387+ if (IS_ERR(file))
38388+ goto out;
2000de60 38389+ h_sb = file->f_path.dentry->d_sb;
7f207e10
AM
38390+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
38391+ pr_err("xino doesn't support %s(%s)\n",
38392+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
38393+ fput(file);
38394+ file = ERR_PTR(-EINVAL);
38395+ }
7f207e10 38396+ }
0c5527e5 38397+
7f207e10
AM
38398+out:
38399+ return file;
38400+}
38401+
38402+/* ---------------------------------------------------------------------- */
38403+
062440b3
AM
38404+/*
38405+ * initialize the xinofile for the specified branch @br
38406+ * at the place/path where @base_file indicates.
38407+ * test whether another branch is on the same filesystem or not,
38408+ * if found then share the xinofile with another branch.
38409+ */
38410+int au_xino_init_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
38411+ struct path *base)
7f207e10
AM
38412+{
38413+ int err;
062440b3
AM
38414+ struct au_xino_do_set_br args = {
38415+ .h_ino = h_ino,
38416+ .br = br
38417+ };
7f207e10 38418+
062440b3
AM
38419+ args.bshared = sbr_find_shared(sb, /*btop*/0, au_sbbot(sb),
38420+ au_br_sb(br));
38421+ err = au_xino_do_set_br(sb, base, &args);
79b8bda9 38422+ if (unlikely(err))
062440b3 38423+ au_xino_put(br);
7f207e10 38424+
7f207e10
AM
38425+ return err;
38426+}
521ced18
JR
38427+
38428+/* ---------------------------------------------------------------------- */
38429+
062440b3
AM
38430+/*
38431+ * get an unused inode number from bitmap
38432+ */
38433+ino_t au_xino_new_ino(struct super_block *sb)
38434+{
38435+ ino_t ino;
38436+ unsigned long *p, pindex, ul, pend;
38437+ struct au_sbinfo *sbinfo;
38438+ struct file *file;
38439+ int free_bit, err;
38440+
38441+ if (!au_opt_test(au_mntflags(sb), XINO))
38442+ return iunique(sb, AUFS_FIRST_INO);
38443+
38444+ sbinfo = au_sbi(sb);
38445+ mutex_lock(&sbinfo->si_xib_mtx);
38446+ p = sbinfo->si_xib_buf;
38447+ free_bit = sbinfo->si_xib_next_bit;
38448+ if (free_bit < page_bits && !test_bit(free_bit, p))
38449+ goto out; /* success */
38450+ free_bit = find_first_zero_bit(p, page_bits);
38451+ if (free_bit < page_bits)
38452+ goto out; /* success */
38453+
38454+ pindex = sbinfo->si_xib_last_pindex;
38455+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
38456+ err = xib_pindex(sb, ul);
38457+ if (unlikely(err))
38458+ goto out_err;
38459+ free_bit = find_first_zero_bit(p, page_bits);
38460+ if (free_bit < page_bits)
38461+ goto out; /* success */
38462+ }
38463+
38464+ file = sbinfo->si_xib;
38465+ pend = vfsub_f_size_read(file) / PAGE_SIZE;
38466+ for (ul = pindex + 1; ul <= pend; ul++) {
38467+ err = xib_pindex(sb, ul);
38468+ if (unlikely(err))
38469+ goto out_err;
38470+ free_bit = find_first_zero_bit(p, page_bits);
38471+ if (free_bit < page_bits)
38472+ goto out; /* success */
38473+ }
38474+ BUG();
38475+
38476+out:
38477+ set_bit(free_bit, p);
38478+ sbinfo->si_xib_next_bit = free_bit + 1;
38479+ pindex = sbinfo->si_xib_last_pindex;
38480+ mutex_unlock(&sbinfo->si_xib_mtx);
38481+ ino = xib_calc_ino(pindex, free_bit);
38482+ AuDbg("i%lu\n", (unsigned long)ino);
38483+ return ino;
38484+out_err:
38485+ mutex_unlock(&sbinfo->si_xib_mtx);
38486+ AuDbg("i0\n");
38487+ return 0;
38488+}
38489+
38490+/* for s_op->delete_inode() */
38491+void au_xino_delete_inode(struct inode *inode, const int unlinked)
521ced18 38492+{
062440b3
AM
38493+ int err;
38494+ unsigned int mnt_flags;
38495+ aufs_bindex_t bindex, bbot, bi;
38496+ unsigned char try_trunc;
38497+ struct au_iinfo *iinfo;
38498+ struct super_block *sb;
38499+ struct au_hinode *hi;
38500+ struct inode *h_inode;
38501+ struct au_branch *br;
acd2b654
AM
38502+ struct au_xi_calc calc;
38503+ struct file *file;
521ced18 38504+
062440b3 38505+ AuDebugOn(au_is_bad_inode(inode));
521ced18 38506+
062440b3
AM
38507+ sb = inode->i_sb;
38508+ mnt_flags = au_mntflags(sb);
38509+ if (!au_opt_test(mnt_flags, XINO)
38510+ || inode->i_ino == AUFS_ROOT_INO)
38511+ return;
38512+
38513+ if (unlinked) {
38514+ au_xigen_inc(inode);
38515+ au_xib_clear_bit(inode);
38516+ }
38517+
38518+ iinfo = au_ii(inode);
38519+ bindex = iinfo->ii_btop;
38520+ if (bindex < 0)
38521+ return;
38522+
062440b3
AM
38523+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
38524+ hi = au_hinode(iinfo, bindex);
38525+ bbot = iinfo->ii_bbot;
38526+ for (; bindex <= bbot; bindex++, hi++) {
38527+ h_inode = hi->hi_inode;
38528+ if (!h_inode
38529+ || (!unlinked && h_inode->i_nlink))
38530+ continue;
38531+
38532+ /* inode may not be revalidated */
38533+ bi = au_br_index(sb, hi->hi_id);
38534+ if (bi < 0)
38535+ continue;
38536+
38537+ br = au_sbr(sb, bi);
acd2b654
AM
38538+ au_xi_calc(sb, h_inode->i_ino, &calc);
38539+ file = au_xino_file(br->br_xino, calc.idx);
38540+ if (IS_ERR_OR_NULL(file))
38541+ continue;
38542+
e37dd06a 38543+ err = au_xino_do_write(file, &calc, /*ino*/0);
062440b3
AM
38544+ if (!err && try_trunc
38545+ && au_test_fs_trunc_xino(au_br_sb(br)))
38546+ xino_try_trunc(sb, br);
38547+ }
521ced18
JR
38548+}
38549+
062440b3
AM
38550+/* ---------------------------------------------------------------------- */
38551+
38552+static int au_xinondir_find(struct au_xino *xi, ino_t h_ino)
521ced18
JR
38553+{
38554+ int found, total, i;
38555+
38556+ found = -1;
062440b3 38557+ total = xi->xi_nondir.total;
521ced18 38558+ for (i = 0; i < total; i++) {
062440b3 38559+ if (xi->xi_nondir.array[i] != h_ino)
521ced18
JR
38560+ continue;
38561+ found = i;
38562+ break;
38563+ }
38564+
38565+ return found;
38566+}
38567+
062440b3 38568+static int au_xinondir_expand(struct au_xino *xi)
521ced18
JR
38569+{
38570+ int err, sz;
38571+ ino_t *p;
38572+
38573+ BUILD_BUG_ON(KMALLOC_MAX_SIZE > INT_MAX);
38574+
38575+ err = -ENOMEM;
062440b3 38576+ sz = xi->xi_nondir.total * sizeof(ino_t);
521ced18
JR
38577+ if (unlikely(sz > KMALLOC_MAX_SIZE / 2))
38578+ goto out;
062440b3 38579+ p = au_kzrealloc(xi->xi_nondir.array, sz, sz << 1, GFP_ATOMIC,
521ced18
JR
38580+ /*may_shrink*/0);
38581+ if (p) {
062440b3
AM
38582+ xi->xi_nondir.array = p;
38583+ xi->xi_nondir.total <<= 1;
38584+ AuDbg("xi_nondir.total %d\n", xi->xi_nondir.total);
521ced18
JR
38585+ err = 0;
38586+ }
38587+
38588+out:
38589+ return err;
38590+}
38591+
062440b3
AM
38592+void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex,
38593+ ino_t h_ino, int idx)
38594+{
38595+ struct au_xino *xi;
38596+
38597+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
38598+ xi = au_sbr(sb, bindex)->br_xino;
38599+ AuDebugOn(idx < 0 || xi->xi_nondir.total <= idx);
38600+
38601+ spin_lock(&xi->xi_nondir.spin);
38602+ AuDebugOn(xi->xi_nondir.array[idx] != h_ino);
38603+ xi->xi_nondir.array[idx] = 0;
38604+ spin_unlock(&xi->xi_nondir.spin);
38605+ wake_up_all(&xi->xi_nondir.wqh);
38606+}
38607+
521ced18
JR
38608+int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
38609+ int *idx)
38610+{
38611+ int err, found, empty;
062440b3 38612+ struct au_xino *xi;
521ced18
JR
38613+
38614+ err = 0;
38615+ *idx = -1;
38616+ if (!au_opt_test(au_mntflags(sb), XINO))
38617+ goto out; /* no xino */
38618+
062440b3 38619+ xi = au_sbr(sb, bindex)->br_xino;
521ced18
JR
38620+
38621+again:
062440b3
AM
38622+ spin_lock(&xi->xi_nondir.spin);
38623+ found = au_xinondir_find(xi, h_ino);
521ced18 38624+ if (found == -1) {
062440b3 38625+ empty = au_xinondir_find(xi, /*h_ino*/0);
521ced18 38626+ if (empty == -1) {
062440b3
AM
38627+ empty = xi->xi_nondir.total;
38628+ err = au_xinondir_expand(xi);
521ced18
JR
38629+ if (unlikely(err))
38630+ goto out_unlock;
38631+ }
062440b3 38632+ xi->xi_nondir.array[empty] = h_ino;
521ced18
JR
38633+ *idx = empty;
38634+ } else {
062440b3
AM
38635+ spin_unlock(&xi->xi_nondir.spin);
38636+ wait_event(xi->xi_nondir.wqh,
38637+ xi->xi_nondir.array[found] != h_ino);
521ced18
JR
38638+ goto again;
38639+ }
38640+
38641+out_unlock:
062440b3
AM
38642+ spin_unlock(&xi->xi_nondir.spin);
38643+out:
38644+ return err;
38645+}
38646+
38647+/* ---------------------------------------------------------------------- */
38648+
38649+int au_xino_path(struct seq_file *seq, struct file *file)
38650+{
38651+ int err;
38652+
38653+ err = au_seq_path(seq, &file->f_path);
38654+ if (unlikely(err))
38655+ goto out;
38656+
38657+#define Deleted "\\040(deleted)"
38658+ seq->count -= sizeof(Deleted) - 1;
38659+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
38660+ sizeof(Deleted) - 1));
38661+#undef Deleted
38662+
521ced18
JR
38663+out:
38664+ return err;
38665+}
537831f9 38666diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/linux/aufs_type.h
eca34b5c 38667--- /usr/share/empty/include/uapi/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
319657f6 38668+++ linux/include/uapi/linux/aufs_type.h 2021-12-03 15:40:58.239980630 +0100
eca34b5c
AM
38669@@ -0,0 +1,452 @@
38670+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
7f207e10 38671+/*
6d176551 38672+ * Copyright (C) 2005-2021 Junjiro R. Okajima
7f207e10
AM
38673+ *
38674+ * This program, aufs is free software; you can redistribute it and/or modify
38675+ * it under the terms of the GNU General Public License as published by
38676+ * the Free Software Foundation; either version 2 of the License, or
38677+ * (at your option) any later version.
38678+ *
38679+ * This program is distributed in the hope that it will be useful,
38680+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
38681+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38682+ * GNU General Public License for more details.
38683+ *
38684+ * You should have received a copy of the GNU General Public License
523b37e3 38685+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
7f207e10
AM
38686+ */
38687+
38688+#ifndef __AUFS_TYPE_H__
38689+#define __AUFS_TYPE_H__
38690+
f6c5ef8b
AM
38691+#define AUFS_NAME "aufs"
38692+
9dbd164d 38693+#ifdef __KERNEL__
f6c5ef8b
AM
38694+/*
38695+ * define it before including all other headers.
38696+ * sched.h may use pr_* macros before defining "current", so define the
38697+ * no-current version first, and re-define later.
38698+ */
38699+#define pr_fmt(fmt) AUFS_NAME " %s:%d: " fmt, __func__, __LINE__
38700+#include <linux/sched.h>
38701+#undef pr_fmt
a2a7ad62
AM
38702+#define pr_fmt(fmt) \
38703+ AUFS_NAME " %s:%d:%.*s[%d]: " fmt, __func__, __LINE__, \
38704+ (int)sizeof(current->comm), current->comm, current->pid
43982f53 38705+#include <linux/limits.h>
9dbd164d
AM
38706+#else
38707+#include <stdint.h>
38708+#include <sys/types.h>
43982f53 38709+#include <limits.h>
f6c5ef8b 38710+#endif /* __KERNEL__ */
7f207e10 38711+
319657f6 38712+#define AUFS_VERSION "5.15.5-20211129"
7f207e10
AM
38713+
38714+/* todo? move this to linux-2.6.19/include/magic.h */
38715+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
38716+
38717+/* ---------------------------------------------------------------------- */
38718+
43982f53 38719+#ifdef __KERNEL__
7f207e10 38720+#ifdef CONFIG_AUFS_BRANCH_MAX_127
9dbd164d 38721+typedef int8_t aufs_bindex_t;
7f207e10
AM
38722+#define AUFS_BRANCH_MAX 127
38723+#else
9dbd164d 38724+typedef int16_t aufs_bindex_t;
7f207e10
AM
38725+#ifdef CONFIG_AUFS_BRANCH_MAX_511
38726+#define AUFS_BRANCH_MAX 511
38727+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
38728+#define AUFS_BRANCH_MAX 1023
38729+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
38730+#define AUFS_BRANCH_MAX 32767
38731+#endif
38732+#endif
38733+
7f207e10
AM
38734+#ifndef AUFS_BRANCH_MAX
38735+#error unknown CONFIG_AUFS_BRANCH_MAX value
38736+#endif
38737+#endif /* __KERNEL__ */
38738+
38739+/* ---------------------------------------------------------------------- */
38740+
7f207e10
AM
38741+#define AUFS_FSTYPE AUFS_NAME
38742+
38743+#define AUFS_ROOT_INO 2
38744+#define AUFS_FIRST_INO 11
38745+
38746+#define AUFS_WH_PFX ".wh."
38747+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
38748+#define AUFS_WH_TMP_LEN 4
86dc4139 38749+/* a limit for rmdir/rename a dir and copyup */
7f207e10
AM
38750+#define AUFS_MAX_NAMELEN (NAME_MAX \
38751+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
38752+ - 1 /* dot */\
38753+ - AUFS_WH_TMP_LEN) /* hex */
38754+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
38755+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
392086de
AM
38756+#define AUFS_XINO_DEF_SEC 30 /* seconds */
38757+#define AUFS_XINO_DEF_TRUNC 45 /* percentage */
7f207e10
AM
38758+#define AUFS_DIRWH_DEF 3
38759+#define AUFS_RDCACHE_DEF 10 /* seconds */
027c5e7a 38760+#define AUFS_RDCACHE_MAX 3600 /* seconds */
7f207e10
AM
38761+#define AUFS_RDBLK_DEF 512 /* bytes */
38762+#define AUFS_RDHASH_DEF 32
38763+#define AUFS_WKQ_NAME AUFS_NAME "d"
027c5e7a
AM
38764+#define AUFS_MFS_DEF_SEC 30 /* seconds */
38765+#define AUFS_MFS_MAX_SEC 3600 /* seconds */
076b876e 38766+#define AUFS_FHSM_CACHE_DEF_SEC 30 /* seconds */
86dc4139 38767+#define AUFS_PLINK_WARN 50 /* number of plinks in a single bucket */
7f207e10
AM
38768+
38769+/* pseudo-link maintenace under /proc */
38770+#define AUFS_PLINK_MAINT_NAME "plink_maint"
38771+#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME
38772+#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME
38773+
8b6a4947
AM
38774+/* dirren, renamed dir */
38775+#define AUFS_DR_INFO_PFX AUFS_WH_PFX ".dr."
38776+#define AUFS_DR_BRHINO_NAME AUFS_WH_PFX "hino"
38777+/* whiteouted doubly */
38778+#define AUFS_WH_DR_INFO_PFX AUFS_WH_PFX AUFS_DR_INFO_PFX
38779+#define AUFS_WH_DR_BRHINO AUFS_WH_PFX AUFS_DR_BRHINO_NAME
38780+
7f207e10
AM
38781+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
38782+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
38783+
38784+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
38785+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
38786+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
38787+
38788+/* doubly whiteouted */
38789+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
38790+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
38791+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
38792+
1e00d052 38793+/* branch permissions and attributes */
7f207e10
AM
38794+#define AUFS_BRPERM_RW "rw"
38795+#define AUFS_BRPERM_RO "ro"
38796+#define AUFS_BRPERM_RR "rr"
076b876e
AM
38797+#define AUFS_BRATTR_COO_REG "coo_reg"
38798+#define AUFS_BRATTR_COO_ALL "coo_all"
38799+#define AUFS_BRATTR_FHSM "fhsm"
38800+#define AUFS_BRATTR_UNPIN "unpin"
c1595e42
JR
38801+#define AUFS_BRATTR_ICEX "icex"
38802+#define AUFS_BRATTR_ICEX_SEC "icexsec"
38803+#define AUFS_BRATTR_ICEX_SYS "icexsys"
38804+#define AUFS_BRATTR_ICEX_TR "icextr"
38805+#define AUFS_BRATTR_ICEX_USR "icexusr"
38806+#define AUFS_BRATTR_ICEX_OTH "icexoth"
1e00d052
AM
38807+#define AUFS_BRRATTR_WH "wh"
38808+#define AUFS_BRWATTR_NLWH "nolwh"
076b876e
AM
38809+#define AUFS_BRWATTR_MOO "moo"
38810+
38811+#define AuBrPerm_RW 1 /* writable, hardlinkable wh */
38812+#define AuBrPerm_RO (1 << 1) /* readonly */
38813+#define AuBrPerm_RR (1 << 2) /* natively readonly */
38814+#define AuBrPerm_Mask (AuBrPerm_RW | AuBrPerm_RO | AuBrPerm_RR)
38815+
38816+#define AuBrAttr_COO_REG (1 << 3) /* copy-up on open */
38817+#define AuBrAttr_COO_ALL (1 << 4)
38818+#define AuBrAttr_COO_Mask (AuBrAttr_COO_REG | AuBrAttr_COO_ALL)
38819+
38820+#define AuBrAttr_FHSM (1 << 5) /* file-based hsm */
38821+#define AuBrAttr_UNPIN (1 << 6) /* rename-able top dir of
c1595e42
JR
38822+ branch. meaningless since
38823+ linux-3.18-rc1 */
38824+
38825+/* ignore error in copying XATTR */
38826+#define AuBrAttr_ICEX_SEC (1 << 7)
38827+#define AuBrAttr_ICEX_SYS (1 << 8)
38828+#define AuBrAttr_ICEX_TR (1 << 9)
38829+#define AuBrAttr_ICEX_USR (1 << 10)
38830+#define AuBrAttr_ICEX_OTH (1 << 11)
38831+#define AuBrAttr_ICEX (AuBrAttr_ICEX_SEC \
38832+ | AuBrAttr_ICEX_SYS \
38833+ | AuBrAttr_ICEX_TR \
38834+ | AuBrAttr_ICEX_USR \
38835+ | AuBrAttr_ICEX_OTH)
38836+
38837+#define AuBrRAttr_WH (1 << 12) /* whiteout-able */
076b876e
AM
38838+#define AuBrRAttr_Mask AuBrRAttr_WH
38839+
c1595e42
JR
38840+#define AuBrWAttr_NoLinkWH (1 << 13) /* un-hardlinkable whiteouts */
38841+#define AuBrWAttr_MOO (1 << 14) /* move-up on open */
076b876e
AM
38842+#define AuBrWAttr_Mask (AuBrWAttr_NoLinkWH | AuBrWAttr_MOO)
38843+
38844+#define AuBrAttr_CMOO_Mask (AuBrAttr_COO_Mask | AuBrWAttr_MOO)
38845+
c1595e42 38846+/* #warning test userspace */
076b876e
AM
38847+#ifdef __KERNEL__
38848+#ifndef CONFIG_AUFS_FHSM
38849+#undef AuBrAttr_FHSM
38850+#define AuBrAttr_FHSM 0
38851+#endif
c1595e42
JR
38852+#ifndef CONFIG_AUFS_XATTR
38853+#undef AuBrAttr_ICEX
38854+#define AuBrAttr_ICEX 0
38855+#undef AuBrAttr_ICEX_SEC
38856+#define AuBrAttr_ICEX_SEC 0
38857+#undef AuBrAttr_ICEX_SYS
38858+#define AuBrAttr_ICEX_SYS 0
38859+#undef AuBrAttr_ICEX_TR
38860+#define AuBrAttr_ICEX_TR 0
38861+#undef AuBrAttr_ICEX_USR
38862+#define AuBrAttr_ICEX_USR 0
38863+#undef AuBrAttr_ICEX_OTH
38864+#define AuBrAttr_ICEX_OTH 0
38865+#endif
076b876e
AM
38866+#endif
38867+
38868+/* the longest combination */
c1595e42
JR
38869+/* AUFS_BRATTR_ICEX and AUFS_BRATTR_ICEX_TR don't affect here */
38870+#define AuBrPermStrSz sizeof(AUFS_BRPERM_RW \
38871+ "+" AUFS_BRATTR_COO_REG \
38872+ "+" AUFS_BRATTR_FHSM \
38873+ "+" AUFS_BRATTR_UNPIN \
7e9cd9fe
AM
38874+ "+" AUFS_BRATTR_ICEX_SEC \
38875+ "+" AUFS_BRATTR_ICEX_SYS \
38876+ "+" AUFS_BRATTR_ICEX_USR \
38877+ "+" AUFS_BRATTR_ICEX_OTH \
076b876e
AM
38878+ "+" AUFS_BRWATTR_NLWH)
38879+
38880+typedef struct {
38881+ char a[AuBrPermStrSz];
38882+} au_br_perm_str_t;
38883+
38884+static inline int au_br_writable(int brperm)
38885+{
38886+ return brperm & AuBrPerm_RW;
38887+}
38888+
38889+static inline int au_br_whable(int brperm)
38890+{
38891+ return brperm & (AuBrPerm_RW | AuBrRAttr_WH);
38892+}
38893+
38894+static inline int au_br_wh_linkable(int brperm)
38895+{
38896+ return !(brperm & AuBrWAttr_NoLinkWH);
38897+}
38898+
38899+static inline int au_br_cmoo(int brperm)
38900+{
38901+ return brperm & AuBrAttr_CMOO_Mask;
38902+}
38903+
38904+static inline int au_br_fhsm(int brperm)
38905+{
38906+ return brperm & AuBrAttr_FHSM;
38907+}
7f207e10
AM
38908+
38909+/* ---------------------------------------------------------------------- */
38910+
38911+/* ioctl */
38912+enum {
38913+ /* readdir in userspace */
38914+ AuCtl_RDU,
38915+ AuCtl_RDU_INO,
38916+
076b876e
AM
38917+ AuCtl_WBR_FD, /* pathconf wrapper */
38918+ AuCtl_IBUSY, /* busy inode */
38919+ AuCtl_MVDOWN, /* move-down */
38920+ AuCtl_BR, /* info about branches */
38921+ AuCtl_FHSM_FD /* connection for fhsm */
7f207e10
AM
38922+};
38923+
38924+/* borrowed from linux/include/linux/kernel.h */
38925+#ifndef ALIGN
eca34b5c 38926+#ifdef _GNU_SOURCE
7f207e10 38927+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
eca34b5c
AM
38928+#else
38929+#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
38930+#endif
7f207e10
AM
38931+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
38932+#endif
38933+
38934+/* borrowed from linux/include/linux/compiler-gcc3.h */
38935+#ifndef __aligned
38936+#define __aligned(x) __attribute__((aligned(x)))
53392da6
AM
38937+#endif
38938+
38939+#ifdef __KERNEL__
38940+#ifndef __packed
7f207e10
AM
38941+#define __packed __attribute__((packed))
38942+#endif
53392da6 38943+#endif
7f207e10
AM
38944+
38945+struct au_rdu_cookie {
9dbd164d
AM
38946+ uint64_t h_pos;
38947+ int16_t bindex;
38948+ uint8_t flags;
38949+ uint8_t pad;
38950+ uint32_t generation;
7f207e10
AM
38951+} __aligned(8);
38952+
38953+struct au_rdu_ent {
9dbd164d
AM
38954+ uint64_t ino;
38955+ int16_t bindex;
38956+ uint8_t type;
38957+ uint8_t nlen;
38958+ uint8_t wh;
42b5c33a 38959+ char name[];
7f207e10
AM
38960+} __aligned(8);
38961+
38962+static inline int au_rdu_len(int nlen)
38963+{
38964+ /* include the terminating NULL */
38965+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
9dbd164d 38966+ sizeof(uint64_t));
7f207e10
AM
38967+}
38968+
38969+union au_rdu_ent_ul {
38970+ struct au_rdu_ent __user *e;
9dbd164d 38971+ uint64_t ul;
7f207e10
AM
38972+};
38973+
38974+enum {
38975+ AufsCtlRduV_SZ,
38976+ AufsCtlRduV_End
38977+};
38978+
38979+struct aufs_rdu {
38980+ /* input */
38981+ union {
9dbd164d
AM
38982+ uint64_t sz; /* AuCtl_RDU */
38983+ uint64_t nent; /* AuCtl_RDU_INO */
7f207e10
AM
38984+ };
38985+ union au_rdu_ent_ul ent;
9dbd164d 38986+ uint16_t verify[AufsCtlRduV_End];
7f207e10
AM
38987+
38988+ /* input/output */
9dbd164d 38989+ uint32_t blk;
7f207e10
AM
38990+
38991+ /* output */
38992+ union au_rdu_ent_ul tail;
38993+ /* number of entries which were added in a single call */
9dbd164d
AM
38994+ uint64_t rent;
38995+ uint8_t full;
38996+ uint8_t shwh;
7f207e10
AM
38997+
38998+ struct au_rdu_cookie cookie;
38999+} __aligned(8);
39000+
1e00d052
AM
39001+/* ---------------------------------------------------------------------- */
39002+
8b6a4947
AM
39003+/* dirren. the branch is identified by the filename who contains this */
39004+struct au_drinfo {
39005+ uint64_t ino;
39006+ union {
39007+ uint8_t oldnamelen;
39008+ uint64_t _padding;
39009+ };
42b5c33a 39010+ uint8_t oldname[];
8b6a4947
AM
39011+} __aligned(8);
39012+
39013+struct au_drinfo_fdata {
39014+ uint32_t magic;
39015+ struct au_drinfo drinfo;
39016+} __aligned(8);
39017+
39018+#define AUFS_DRINFO_MAGIC_V1 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x01)
39019+/* future */
39020+#define AUFS_DRINFO_MAGIC_V2 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x02)
39021+
39022+/* ---------------------------------------------------------------------- */
39023+
1e00d052 39024+struct aufs_wbr_fd {
9dbd164d
AM
39025+ uint32_t oflags;
39026+ int16_t brid;
1e00d052
AM
39027+} __aligned(8);
39028+
39029+/* ---------------------------------------------------------------------- */
39030+
027c5e7a 39031+struct aufs_ibusy {
9dbd164d
AM
39032+ uint64_t ino, h_ino;
39033+ int16_t bindex;
027c5e7a
AM
39034+} __aligned(8);
39035+
1e00d052
AM
39036+/* ---------------------------------------------------------------------- */
39037+
392086de
AM
39038+/* error code for move-down */
39039+/* the actual message strings are implemented in aufs-util.git */
39040+enum {
39041+ EAU_MVDOWN_OPAQUE = 1,
39042+ EAU_MVDOWN_WHITEOUT,
39043+ EAU_MVDOWN_UPPER,
39044+ EAU_MVDOWN_BOTTOM,
39045+ EAU_MVDOWN_NOUPPER,
39046+ EAU_MVDOWN_NOLOWERBR,
39047+ EAU_Last
39048+};
39049+
c2b27bf2 39050+/* flags for move-down */
392086de
AM
39051+#define AUFS_MVDOWN_DMSG 1
39052+#define AUFS_MVDOWN_OWLOWER (1 << 1) /* overwrite lower */
39053+#define AUFS_MVDOWN_KUPPER (1 << 2) /* keep upper */
39054+#define AUFS_MVDOWN_ROLOWER (1 << 3) /* do even if lower is RO */
39055+#define AUFS_MVDOWN_ROLOWER_R (1 << 4) /* did on lower RO */
39056+#define AUFS_MVDOWN_ROUPPER (1 << 5) /* do even if upper is RO */
39057+#define AUFS_MVDOWN_ROUPPER_R (1 << 6) /* did on upper RO */
39058+#define AUFS_MVDOWN_BRID_UPPER (1 << 7) /* upper brid */
39059+#define AUFS_MVDOWN_BRID_LOWER (1 << 8) /* lower brid */
076b876e
AM
39060+#define AUFS_MVDOWN_FHSM_LOWER (1 << 9) /* find fhsm attr for lower */
39061+#define AUFS_MVDOWN_STFS (1 << 10) /* req. stfs */
39062+#define AUFS_MVDOWN_STFS_FAILED (1 << 11) /* output: stfs is unusable */
39063+#define AUFS_MVDOWN_BOTTOM (1 << 12) /* output: no more lowers */
c2b27bf2 39064+
076b876e 39065+/* index for move-down */
392086de
AM
39066+enum {
39067+ AUFS_MVDOWN_UPPER,
39068+ AUFS_MVDOWN_LOWER,
39069+ AUFS_MVDOWN_NARRAY
39070+};
39071+
076b876e
AM
39072+/*
39073+ * additional info of move-down
39074+ * number of free blocks and inodes.
39075+ * subset of struct kstatfs, but smaller and always 64bit.
39076+ */
39077+struct aufs_stfs {
39078+ uint64_t f_blocks;
39079+ uint64_t f_bavail;
39080+ uint64_t f_files;
39081+ uint64_t f_ffree;
39082+};
39083+
39084+struct aufs_stbr {
39085+ int16_t brid; /* optional input */
39086+ int16_t bindex; /* output */
39087+ struct aufs_stfs stfs; /* output when AUFS_MVDOWN_STFS set */
39088+} __aligned(8);
39089+
c2b27bf2 39090+struct aufs_mvdown {
076b876e
AM
39091+ uint32_t flags; /* input/output */
39092+ struct aufs_stbr stbr[AUFS_MVDOWN_NARRAY]; /* input/output */
39093+ int8_t au_errno; /* output */
39094+} __aligned(8);
39095+
39096+/* ---------------------------------------------------------------------- */
39097+
39098+union aufs_brinfo {
39099+ /* PATH_MAX may differ between kernel-space and user-space */
39100+ char _spacer[4096];
392086de 39101+ struct {
076b876e
AM
39102+ int16_t id;
39103+ int perm;
42b5c33a 39104+ char path[];
076b876e 39105+ };
c2b27bf2
AM
39106+} __aligned(8);
39107+
39108+/* ---------------------------------------------------------------------- */
39109+
7f207e10
AM
39110+#define AuCtlType 'A'
39111+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
39112+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
1e00d052
AM
39113+#define AUFS_CTL_WBR_FD _IOW(AuCtlType, AuCtl_WBR_FD, \
39114+ struct aufs_wbr_fd)
027c5e7a 39115+#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy)
392086de
AM
39116+#define AUFS_CTL_MVDOWN _IOWR(AuCtlType, AuCtl_MVDOWN, \
39117+ struct aufs_mvdown)
076b876e
AM
39118+#define AUFS_CTL_BRINFO _IOW(AuCtlType, AuCtl_BR, union aufs_brinfo)
39119+#define AUFS_CTL_FHSM_FD _IOW(AuCtlType, AuCtl_FHSM_FD, int)
7f207e10
AM
39120+
39121+#endif /* __AUFS_TYPE_H__ */
2121bcd9 39122SPDX-License-Identifier: GPL-2.0
319657f6 39123aufs5.15.5 loopback patch
5527c038
JR
39124
39125diff --git a/drivers/block/loop.c b/drivers/block/loop.c
319657f6 39126index c9d1ef703673c..ca8b0b1146a60 100644
5527c038
JR
39127--- a/drivers/block/loop.c
39128+++ b/drivers/block/loop.c
319657f6 39129@@ -672,6 +672,15 @@ static inline void loop_update_dio(struct loop_device *lo)
42a736d3 39130 lo->use_dio);
5527c038
JR
39131 }
39132
5527c038
JR
39133+static struct file *loop_real_file(struct file *file)
39134+{
39135+ struct file *f = NULL;
39136+
39137+ if (file->f_path.dentry->d_sb->s_op->real_loop)
39138+ f = file->f_path.dentry->d_sb->s_op->real_loop(file);
39139+ return f;
8b6a4947
AM
39140+}
39141+
6d176551 39142 static void loop_reread_partitions(struct loop_device *lo)
8b6a4947 39143 {
6d176551 39144 int rc;
319657f6 39145@@ -729,6 +738,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
5527c038 39146 {
6d176551
JR
39147 struct file *file = fget(arg);
39148 struct file *old_file;
39149+ struct file *f, *virt_file = NULL, *old_virt_file;
39150 int error;
39151 bool partscan;
39152 bool is_loop;
319657f6 39153@@ -748,11 +758,19 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
6d176551 39154 if (!(lo->lo_flags & LO_FLAGS_READ_ONLY))
e1106418 39155 goto out_err;
6d176551 39156
5527c038
JR
39157+ f = loop_real_file(file);
39158+ if (f) {
39159+ virt_file = file;
39160+ file = f;
39161+ get_file(file);
39162+ }
6d176551 39163+
cd7a4cd9
AM
39164 error = loop_validate_file(file, bdev);
39165 if (error)
e1106418 39166 goto out_err;
cd7a4cd9 39167
5527c038
JR
39168 old_file = lo->lo_backing_file;
39169+ old_virt_file = lo->lo_backing_virt_file;
39170
39171 error = -EINVAL;
39172
319657f6 39173@@ -765,6 +783,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
8b6a4947
AM
39174 blk_mq_freeze_queue(lo->lo_queue);
39175 mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask);
39176 lo->lo_backing_file = file;
39177+ lo->lo_backing_virt_file = virt_file;
39178 lo->old_gfp_mask = mapping_gfp_mask(file->f_mapping);
39179 mapping_set_gfp_mask(file->f_mapping,
39180 lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
319657f6 39181@@ -787,6 +806,8 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
e1106418
JR
39182 * dependency.
39183 */
5527c038
JR
39184 fput(old_file);
39185+ if (old_virt_file)
39186+ fput(old_virt_file);
e1106418 39187 if (partscan)
6d176551 39188 loop_reread_partitions(lo);
5527c038 39189 return 0;
319657f6 39190@@ -795,6 +816,8 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
6d176551
JR
39191 loop_global_unlock(lo, is_loop);
39192 out_putf:
39193 fput(file);
5527c038
JR
39194+ if (virt_file)
39195+ fput(virt_file);
5527c038
JR
39196 return error;
39197 }
e1106418 39198
319657f6 39199@@ -1195,6 +1218,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
42a736d3 39200 const struct loop_config *config)
5527c038 39201 {
6d176551
JR
39202 struct file *file = fget(config->fd);
39203+ struct file *f, *virt_file = NULL;
39204 struct inode *inode;
5527c038 39205 struct address_space *mapping;
6d176551 39206 int error;
319657f6 39207@@ -1210,6 +1234,13 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
6d176551
JR
39208 /* This is safe, since we have a reference from open(). */
39209 __module_get(THIS_MODULE);
39210
5527c038
JR
39211+ f = loop_real_file(file);
39212+ if (f) {
39213+ virt_file = file;
39214+ file = f;
39215+ get_file(file);
39216+ }
6d176551 39217+
fbc438ed
JR
39218 /*
39219 * If we don't hold exclusive handle for the device, upgrade to it
6d176551 39220 * here to avoid changing device under exclusive owner.
319657f6 39221@@ -1275,6 +1306,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
f24b0ddd 39222 lo->use_dio = lo->lo_flags & LO_FLAGS_DIRECT_IO;
5527c038 39223 lo->lo_device = bdev;
5527c038
JR
39224 lo->lo_backing_file = file;
39225+ lo->lo_backing_virt_file = virt_file;
f24b0ddd
JR
39226 lo->old_gfp_mask = mapping_gfp_mask(mapping);
39227 mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
39228
319657f6 39229@@ -1325,6 +1357,8 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
42a736d3 39230 bd_abort_claiming(bdev, loop_configure);
e1106418 39231 out_putf:
5527c038
JR
39232 fput(file);
39233+ if (virt_file)
39234+ fput(virt_file);
5527c038
JR
39235 /* This is safe: open() is still holding a reference. */
39236 module_put(THIS_MODULE);
6d176551 39237 return error;
319657f6 39238@@ -1333,6 +1367,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode,
ba1aed25 39239 static int __loop_clr_fd(struct loop_device *lo, bool release)
5527c038 39240 {
e1106418 39241 struct file *filp = NULL;
5527c038
JR
39242+ struct file *virt_filp = lo->lo_backing_virt_file;
39243 gfp_t gfp = lo->old_gfp_mask;
39244 struct block_device *bdev = lo->lo_device;
ba1aed25 39245 int err = 0;
319657f6 39246@@ -1384,6 +1419,7 @@ static int __loop_clr_fd(struct loop_device *lo, bool release)
5527c038 39247
5527c038 39248 spin_lock_irq(&lo->lo_lock);
5527c038
JR
39249 lo->lo_backing_file = NULL;
39250+ lo->lo_backing_virt_file = NULL;
39251 spin_unlock_irq(&lo->lo_lock);
39252
39253 loop_release_xfer(lo);
319657f6 39254@@ -1464,6 +1500,8 @@ static int __loop_clr_fd(struct loop_device *lo, bool release)
5527c038 39255 */
e1106418
JR
39256 if (filp)
39257 fput(filp);
5527c038
JR
39258+ if (virt_filp)
39259+ fput(virt_filp);
e1106418 39260 return err;
5527c038
JR
39261 }
39262
39263diff --git a/drivers/block/loop.h b/drivers/block/loop.h
758e9dad 39264index 04c88dd6eabd6..0ff3ba22ee170 100644
5527c038
JR
39265--- a/drivers/block/loop.h
39266+++ b/drivers/block/loop.h
39267@@ -46,7 +46,7 @@ struct loop_device {
39268 int (*ioctl)(struct loop_device *, int cmd,
39269 unsigned long arg);
39270
39271- struct file * lo_backing_file;
43982f53 39272+ struct file *lo_backing_file, *lo_backing_virt_file;
5527c038 39273 struct block_device *lo_device;
5527c038 39274 void *key_data;
8b6a4947 39275
5527c038 39276diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c
6d176551 39277index 99ceca1440449..e49dfe8550329 100644
5527c038
JR
39278--- a/fs/aufs/f_op.c
39279+++ b/fs/aufs/f_op.c
42a736d3 39280@@ -304,7 +304,7 @@ static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter)
5527c038
JR
39281 if (IS_ERR(h_file))
39282 goto out;
39283
39284- if (au_test_loopback_kthread()) {
39285+ if (0 && au_test_loopback_kthread()) {
39286 au_warn_loopback(h_file->f_path.dentry->d_sb);
39287 if (file->f_mapping != h_file->f_mapping) {
39288 file->f_mapping = h_file->f_mapping;
39289diff --git a/fs/aufs/loop.c b/fs/aufs/loop.c
6d176551 39290index 74347bd75b380..5ef888a1d53f4 100644
5527c038
JR
39291--- a/fs/aufs/loop.c
39292+++ b/fs/aufs/loop.c
2121bcd9 39293@@ -133,3 +133,19 @@ void au_loopback_fin(void)
79b8bda9 39294 symbol_put(loop_backing_file);
9f237c51 39295 au_kfree_try_rcu(au_warn_loopback_array);
5527c038
JR
39296 }
39297+
39298+/* ---------------------------------------------------------------------- */
39299+
39300+/* support the loopback block device insude aufs */
39301+
39302+struct file *aufs_real_loop(struct file *file)
39303+{
39304+ struct file *f;
39305+
39306+ BUG_ON(!au_test_aufs(file->f_path.dentry->d_sb));
39307+ fi_read_lock(file);
39308+ f = au_hf_top(file);
39309+ fi_read_unlock(file);
39310+ AuDebugOn(!f);
39311+ return f;
39312+}
39313diff --git a/fs/aufs/loop.h b/fs/aufs/loop.h
6d176551 39314index 7293bee427f96..3345c098d0d47 100644
5527c038
JR
39315--- a/fs/aufs/loop.h
39316+++ b/fs/aufs/loop.h
eca801bf 39317@@ -26,6 +26,8 @@ void au_warn_loopback(struct super_block *h_sb);
5527c038
JR
39318
39319 int au_loopback_init(void);
39320 void au_loopback_fin(void);
39321+
39322+struct file *aufs_real_loop(struct file *file);
39323 #else
83b672a5 39324 AuStub(struct file *, loop_backing_file, return NULL, struct super_block *sb)
eca801bf
AM
39325
39326@@ -36,6 +38,8 @@ AuStubVoid(au_warn_loopback, struct super_block *h_sb)
5527c038
JR
39327
39328 AuStubInt0(au_loopback_init, void)
39329 AuStubVoid(au_loopback_fin, void)
39330+
39331+AuStub(struct file *, aufs_real_loop, return NULL, struct file *file)
39332 #endif /* BLK_DEV_LOOP */
39333
39334 #endif /* __KERNEL__ */
39335diff --git a/fs/aufs/super.c b/fs/aufs/super.c
6d176551 39336index ae38857541533..af32f0960e595 100644
5527c038
JR
39337--- a/fs/aufs/super.c
39338+++ b/fs/aufs/super.c
fbc438ed 39339@@ -844,7 +844,10 @@ static const struct super_operations aufs_sop = {
5527c038
JR
39340 .statfs = aufs_statfs,
39341 .put_super = aufs_put_super,
39342 .sync_fs = aufs_sync_fs,
39343- .remount_fs = aufs_remount_fs
39344+ .remount_fs = aufs_remount_fs,
39345+#ifdef CONFIG_AUFS_BDEV_LOOP
39346+ .real_loop = aufs_real_loop
39347+#endif
39348 };
39349
39350 /* ---------------------------------------------------------------------- */
39351diff --git a/include/linux/fs.h b/include/linux/fs.h
319657f6 39352index e60d8ad854004..2ac5317f9b795 100644
5527c038
JR
39353--- a/include/linux/fs.h
39354+++ b/include/linux/fs.h
758e9dad 39355@@ -2226,6 +2226,10 @@ struct super_operations {
5527c038
JR
39356 struct shrink_control *);
39357 long (*free_cached_objects)(struct super_block *,
39358 struct shrink_control *);
43982f53 39359+#if IS_ENABLED(CONFIG_BLK_DEV_LOOP) || IS_ENABLED(CONFIG_BLK_DEV_LOOP_MODULE)
5527c038
JR
39360+ /* and aufs */
39361+ struct file *(*real_loop)(struct file *);
39362+#endif
39363 };
39364
39365 /*
This page took 7.325767 seconds and 4 git commands to generate.