]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-aufs5.patch
- up to 5.4.75
[packages/kernel.git] / kernel-aufs5.patch
CommitLineData
2121bcd9 1SPDX-License-Identifier: GPL-2.0
43982f53 2aufs5.4 kbuild patch
7f207e10 3
fbc438ed 4diff --git a/fs/Kconfig b/fs/Kconfig
43982f53 5index 2501e6f1f965..38a6a5991da9 100644
fbc438ed
JR
6--- a/fs/Kconfig
7+++ b/fs/Kconfig
43982f53 8@@ -264,6 +264,7 @@ source "fs/pstore/Kconfig"
5527c038 9 source "fs/sysv/Kconfig"
7e9cd9fe 10 source "fs/ufs/Kconfig"
9d41a5bf 11 source "fs/erofs/Kconfig"
7f207e10
AM
12+source "fs/aufs/Kconfig"
13
14 endif # MISC_FILESYSTEMS
15
16diff --git a/fs/Makefile b/fs/Makefile
43982f53 17index 14231b4cf383..8765e191ebe0 100644
7f207e10
AM
18--- a/fs/Makefile
19+++ b/fs/Makefile
9d41a5bf 20@@ -132,3 +132,4 @@ obj-$(CONFIG_CEPH_FS) += ceph/
bf0370f2 21 obj-$(CONFIG_PSTORE) += pstore/
c06a8ce3 22 obj-$(CONFIG_EFIVAR_FS) += efivarfs/
9d41a5bf 23 obj-$(CONFIG_EROFS_FS) += erofs/
86dc4139 24+obj-$(CONFIG_AUFS_FS) += aufs/
2121bcd9 25SPDX-License-Identifier: GPL-2.0
43982f53 26aufs5.4 base patch
7f207e10 27
c1595e42 28diff --git a/MAINTAINERS b/MAINTAINERS
43982f53 29index 9d3a5c54a41d..f33398b47c42 100644
c1595e42
JR
30--- a/MAINTAINERS
31+++ b/MAINTAINERS
43982f53 32@@ -2832,6 +2832,19 @@ F: include/linux/audit.h
c1595e42
JR
33 F: include/uapi/linux/audit.h
34 F: kernel/audit*
35
36+AUFS (advanced multi layered unification filesystem) FILESYSTEM
37+M: "J. R. Okajima" <hooanon05g@gmail.com>
c1595e42 38+L: aufs-users@lists.sourceforge.net (members only)
eca801bf 39+L: linux-unionfs@vger.kernel.org
c1595e42 40+W: http://aufs.sourceforge.net
5527c038 41+T: git://github.com/sfjro/aufs4-linux.git
c1595e42
JR
42+S: Supported
43+F: Documentation/filesystems/aufs/
44+F: Documentation/ABI/testing/debugfs-aufs
45+F: Documentation/ABI/testing/sysfs-aufs
46+F: fs/aufs/
47+F: include/uapi/linux/aufs_type.h
48+
49 AUXILIARY DISPLAY DRIVERS
50 M: Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com>
cd7a4cd9 51 S: Maintained
392086de 52diff --git a/drivers/block/loop.c b/drivers/block/loop.c
43982f53 53index f6f77eaa7217..5e094699215e 100644
392086de
AM
54--- a/drivers/block/loop.c
55+++ b/drivers/block/loop.c
eca34b5c 56@@ -738,6 +738,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
eca34b5c 82index e88cf0554e65..7ce4ccf5a51c 100644
c1595e42
JR
83--- a/fs/dcache.c
84+++ b/fs/dcache.c
eca34b5c 85@@ -1264,7 +1264,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
43982f53 95index 3d40771e8e7c..12dd73930961 100644
febd17d6
JR
96--- a/fs/fcntl.c
97+++ b/fs/fcntl.c
2121bcd9 98@@ -32,7 +32,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;
2121bcd9 107@@ -63,6 +63,8 @@ static int setfl(int fd, struct file * filp, unsigned long arg)
febd17d6
JR
108
109 if (filp->f_op->check_flags)
110 error = filp->f_op->check_flags(arg);
111+ if (!error && filp->f_op->setfl)
112+ error = filp->f_op->setfl(filp, arg);
113 if (error)
114 return error;
115
5afbbe0d 116diff --git a/fs/inode.c b/fs/inode.c
43982f53 117index fef457a42882..aaeacde398ee 100644
5afbbe0d
AM
118--- a/fs/inode.c
119+++ b/fs/inode.c
43982f53 120@@ -1673,7 +1673,7 @@ EXPORT_SYMBOL(generic_update_time);
5afbbe0d
AM
121 * This does the actual work of updating an inodes time or version. Must have
122 * had called mnt_want_write() before calling this.
123 */
cd7a4cd9
AM
124-static int update_time(struct inode *inode, struct timespec64 *time, int flags)
125+int update_time(struct inode *inode, struct timespec64 *time, int flags)
5afbbe0d 126 {
cd7a4cd9 127 int (*update_time)(struct inode *, struct timespec64 *, int);
5afbbe0d 128
8b6a4947 129diff --git a/fs/namespace.c b/fs/namespace.c
43982f53 130index 2adfe7b166a3..0f7e57e5f4b7 100644
8b6a4947
AM
131--- a/fs/namespace.c
132+++ b/fs/namespace.c
eca34b5c 133@@ -776,6 +776,12 @@ static inline int check_mnt(struct mount *mnt)
8b6a4947
AM
134 return mnt->mnt_ns == current->nsproxy->mnt_ns;
135 }
136
137+/* for aufs, CONFIG_AUFS_BR_FUSE */
138+int is_current_mnt_ns(struct vfsmount *mnt)
139+{
140+ return check_mnt(real_mount(mnt));
141+}
142+
143 /*
144 * vfsmount lock must be held for write
145 */
5527c038 146diff --git a/fs/read_write.c b/fs/read_write.c
43982f53 147index 5bbf587f5bc1..fa9b3994b34c 100644
5527c038
JR
148--- a/fs/read_write.c
149+++ b/fs/read_write.c
fbc438ed 150@@ -498,6 +498,28 @@ static ssize_t __vfs_write(struct file *file, const char __user *p,
8b6a4947 151 return -EINVAL;
5527c038 152 }
5527c038
JR
153
154+vfs_readf_t vfs_readf(struct file *file)
155+{
156+ const struct file_operations *fop = file->f_op;
157+
158+ if (fop->read)
159+ return fop->read;
160+ if (fop->read_iter)
161+ return new_sync_read;
43982f53 162+ return ERR_PTR(-ENOSYS); /* doesn't have ->read(|_iter)() op */
5527c038
JR
163+}
164+
165+vfs_writef_t vfs_writef(struct file *file)
166+{
167+ const struct file_operations *fop = file->f_op;
168+
169+ if (fop->write)
170+ return fop->write;
171+ if (fop->write_iter)
172+ return new_sync_write;
43982f53 173+ return ERR_PTR(-ENOSYS); /* doesn't have ->write(|_iter)() op */
5527c038
JR
174+}
175+
8b6a4947 176 ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
5527c038
JR
177 {
178 mm_segment_t old_fs;
7f207e10 179diff --git a/fs/splice.c b/fs/splice.c
eca34b5c 180index 98412721f056..75b489fcb66f 100644
7f207e10
AM
181--- a/fs/splice.c
182+++ b/fs/splice.c
fbc438ed 183@@ -834,8 +834,8 @@ EXPORT_SYMBOL(generic_splice_sendpage);
7f207e10
AM
184 /*
185 * Attempt to initiate a splice from pipe to file.
186 */
187-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
188- loff_t *ppos, size_t len, unsigned int flags)
189+long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
190+ loff_t *ppos, size_t len, unsigned int flags)
191 {
192 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *,
193 loff_t *, size_t, unsigned int);
fbc438ed 194@@ -851,9 +851,9 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
7f207e10
AM
195 /*
196 * Attempt to initiate a splice from a file to a pipe.
197 */
198-static long do_splice_to(struct file *in, loff_t *ppos,
199- struct pipe_inode_info *pipe, size_t len,
200- unsigned int flags)
201+long do_splice_to(struct file *in, loff_t *ppos,
202+ struct pipe_inode_info *pipe, size_t len,
203+ unsigned int flags)
204 {
205 ssize_t (*splice_read)(struct file *, loff_t *,
206 struct pipe_inode_info *, size_t, unsigned int);
a2654f78 207diff --git a/fs/sync.c b/fs/sync.c
fbc438ed 208index 4d1ff010bc5a..457f4e4a5cc1 100644
a2654f78
AM
209--- a/fs/sync.c
210+++ b/fs/sync.c
2121bcd9 211@@ -28,7 +28,7 @@
a2654f78
AM
212 * wait == 1 case since in that case write_inode() functions do
213 * sync_dirty_buffer() and thus effectively write one block at a time.
214 */
215-static int __sync_filesystem(struct super_block *sb, int wait)
216+int __sync_filesystem(struct super_block *sb, int wait)
217 {
218 if (wait)
219 sync_inodes_sb(sb);
5527c038 220diff --git a/include/linux/fs.h b/include/linux/fs.h
43982f53 221index e0d909d35763..381a13995011 100644
5527c038
JR
222--- a/include/linux/fs.h
223+++ b/include/linux/fs.h
43982f53 224@@ -1349,6 +1349,7 @@ extern void fasync_free(struct fasync_struct *);
febd17d6
JR
225 /* can be called from interrupts */
226 extern void kill_fasync(struct fasync_struct **, int, int);
227
43982f53 228+extern int setfl(int fd, struct file *filp, unsigned long arg);
febd17d6 229 extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int force);
3c1bdaff 230 extern int f_setown(struct file *filp, unsigned long arg, int force);
febd17d6 231 extern void f_delown(struct file *filp);
43982f53 232@@ -1835,6 +1836,7 @@ struct file_operations {
febd17d6
JR
233 ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
234 unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
235 int (*check_flags)(int);
236+ int (*setfl)(struct file *, unsigned long);
237 int (*flock) (struct file *, int, struct file_lock *);
238 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
239 ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
43982f53 240@@ -1905,6 +1907,12 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
5527c038
JR
241 struct iovec *fast_pointer,
242 struct iovec **ret_pointer);
243
244+typedef ssize_t (*vfs_readf_t)(struct file *, char __user *, size_t, loff_t *);
245+typedef ssize_t (*vfs_writef_t)(struct file *, const char __user *, size_t,
246+ loff_t *);
247+vfs_readf_t vfs_readf(struct file *file);
248+vfs_writef_t vfs_writef(struct file *file);
249+
250 extern ssize_t __vfs_read(struct file *, char __user *, size_t, loff_t *);
5527c038 251 extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *);
8b6a4947 252 extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *);
43982f53 253@@ -2325,6 +2333,7 @@ extern int current_umask(void);
5afbbe0d
AM
254 extern void ihold(struct inode * inode);
255 extern void iput(struct inode *);
cd7a4cd9
AM
256 extern int generic_update_time(struct inode *, struct timespec64 *, int);
257+extern int update_time(struct inode *, struct timespec64 *, int);
5afbbe0d
AM
258
259 /* /sys/fs */
260 extern struct kobject *fs_kobj;
43982f53 261@@ -2613,6 +2622,7 @@ static inline bool sb_is_blkdev_sb(struct super_block *sb)
a2654f78
AM
262 return false;
263 }
264 #endif
265+extern int __sync_filesystem(struct super_block *, int);
266 extern int sync_filesystem(struct super_block *);
267 extern const struct file_operations def_blk_fops;
268 extern const struct file_operations def_chr_fops;
8b6a4947 269diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
43982f53 270index b8a835fd611b..f452521f2e05 100644
8b6a4947
AM
271--- a/include/linux/lockdep.h
272+++ b/include/linux/lockdep.h
43982f53 273@@ -331,6 +331,8 @@ static inline int lockdep_match_key(struct lockdep_map *lock,
8b6a4947
AM
274 return lock->key == key;
275 }
276
277+struct lock_class *lockdep_hlock_class(struct held_lock *hlock);
278+
279 /*
280 * Acquire a lock.
281 *
43982f53 282@@ -473,6 +475,7 @@ struct lockdep_map { };
8b6a4947
AM
283
284 #define lockdep_depth(tsk) (0)
285
286+#define lockdep_is_held(lock) (1)
287 #define lockdep_is_held_type(l, r) (1)
288
289 #define lockdep_assert_held(l) do { (void)(l); } while (0)
290diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h
ba1aed25 291index 35942084cd40..24f5fd1a789d 100644
8b6a4947
AM
292--- a/include/linux/mnt_namespace.h
293+++ b/include/linux/mnt_namespace.h
2121bcd9 294@@ -6,11 +6,14 @@
8b6a4947
AM
295 struct mnt_namespace;
296 struct fs_struct;
297 struct user_namespace;
298+struct vfsmount;
299
300 extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
301 struct user_namespace *, struct fs_struct *);
302 extern void put_mnt_ns(struct mnt_namespace *ns);
303
304+extern int is_current_mnt_ns(struct vfsmount *mnt);
305+
306 extern const struct file_operations proc_mounts_operations;
307 extern const struct file_operations proc_mountinfo_operations;
308 extern const struct file_operations proc_mountstats_operations;
1e00d052 309diff --git a/include/linux/splice.h b/include/linux/splice.h
ba1aed25 310index 74b4911ac16d..19789fbea567 100644
1e00d052
AM
311--- a/include/linux/splice.h
312+++ b/include/linux/splice.h
2121bcd9 313@@ -87,4 +87,10 @@ extern void splice_shrink_spd(struct splice_pipe_desc *);
4b3da204
AM
314
315 extern const struct pipe_buf_operations page_cache_pipe_buf_ops;
106341ce 316 extern const struct pipe_buf_operations default_pipe_buf_ops;
1e00d052
AM
317+
318+extern long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
319+ loff_t *ppos, size_t len, unsigned int flags);
320+extern long do_splice_to(struct file *in, loff_t *ppos,
321+ struct pipe_inode_info *pipe, size_t len,
322+ unsigned int flags);
323 #endif
8b6a4947 324diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
43982f53 325index 233459c03b5a..407c08ac8ac8 100644
8b6a4947
AM
326--- a/kernel/locking/lockdep.c
327+++ b/kernel/locking/lockdep.c
eca34b5c 328@@ -153,7 +153,7 @@ static
9f237c51 329 struct lock_class lock_classes[MAX_LOCKDEP_KEYS];
eca34b5c 330 static DECLARE_BITMAP(lock_classes_in_use, MAX_LOCKDEP_KEYS);
8b6a4947
AM
331
332-static inline struct lock_class *hlock_class(struct held_lock *hlock)
333+inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock)
334 {
eca34b5c
AM
335 unsigned int class_idx = hlock->class_idx;
336
337@@ -174,6 +174,7 @@ static inline struct lock_class *hlock_class(struct held_lock *hlock)
338 */
339 return lock_classes + class_idx;
8b6a4947
AM
340 }
341+#define hlock_class(hlock) lockdep_hlock_class(hlock)
342
343 #ifdef CONFIG_LOCK_STAT
344 static DEFINE_PER_CPU(struct lock_class_stats[MAX_LOCKDEP_KEYS], cpu_lock_stats);
2121bcd9 345SPDX-License-Identifier: GPL-2.0
43982f53 346aufs5.4 mmap patch
fb47a38f 347
c1595e42 348diff --git a/fs/proc/base.c b/fs/proc/base.c
eca34b5c 349index ebea9501afb8..dc7edc5f7267 100644
c1595e42
JR
350--- a/fs/proc/base.c
351+++ b/fs/proc/base.c
eca34b5c
AM
352@@ -2037,7 +2037,7 @@ static int map_files_get_link(struct dentry *dentry, struct path *path)
353 rc = -ENOENT;
c1595e42
JR
354 vma = find_exact_vma(mm, vm_start, vm_end);
355 if (vma && vma->vm_file) {
356- *path = vma->vm_file->f_path;
357+ *path = vma_pr_or_file(vma)->f_path;
358 path_get(path);
359 rc = 0;
360 }
fb47a38f 361diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c
fbc438ed 362index 14c2badb8fd9..65afe5287e43 100644
fb47a38f
JR
363--- a/fs/proc/nommu.c
364+++ b/fs/proc/nommu.c
fbc438ed 365@@ -41,7 +41,10 @@ static int nommu_region_show(struct seq_file *m, struct vm_region *region)
fb47a38f
JR
366 file = region->vm_file;
367
368 if (file) {
369- struct inode *inode = file_inode(region->vm_file);
370+ struct inode *inode;
076b876e 371+
fb47a38f
JR
372+ file = vmr_pr_or_file(region);
373+ inode = file_inode(file);
374 dev = inode->i_sb->s_dev;
375 ino = inode->i_ino;
376 }
377diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
43982f53 378index 9442631fd4af..1fa8a5fcdeee 100644
fb47a38f
JR
379--- a/fs/proc/task_mmu.c
380+++ b/fs/proc/task_mmu.c
eca34b5c 381@@ -309,7 +309,10 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
fb47a38f
JR
382 const char *name = NULL;
383
384 if (file) {
385- struct inode *inode = file_inode(vma->vm_file);
386+ struct inode *inode;
076b876e 387+
fb47a38f
JR
388+ file = vma_pr_or_file(vma);
389+ inode = file_inode(file);
390 dev = inode->i_sb->s_dev;
391 ino = inode->i_ino;
392 pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
43982f53 393@@ -1819,7 +1822,7 @@ static int show_numa_map(struct seq_file *m, void *v)
076b876e
AM
394 struct proc_maps_private *proc_priv = &numa_priv->proc_maps;
395 struct vm_area_struct *vma = v;
396 struct numa_maps *md = &numa_priv->md;
397- struct file *file = vma->vm_file;
398+ struct file *file = vma_pr_or_file(vma);
076b876e 399 struct mm_struct *mm = vma->vm_mm;
43982f53
AM
400 struct mempolicy *pol;
401 char buffer[64];
fb47a38f 402diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
eca34b5c 403index 7907e6419e57..d17209cf52bc 100644
fb47a38f
JR
404--- a/fs/proc/task_nommu.c
405+++ b/fs/proc/task_nommu.c
acd2b654 406@@ -155,7 +155,10 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
fb47a38f
JR
407 file = vma->vm_file;
408
409 if (file) {
410- struct inode *inode = file_inode(vma->vm_file);
411+ struct inode *inode;
076b876e 412+
b912730e 413+ file = vma_pr_or_file(vma);
fb47a38f
JR
414+ inode = file_inode(file);
415 dev = inode->i_sb->s_dev;
416 ino = inode->i_ino;
417 pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
418diff --git a/include/linux/mm.h b/include/linux/mm.h
43982f53 419index a2adf95b3f9c..70e1dccc1283 100644
fb47a38f
JR
420--- a/include/linux/mm.h
421+++ b/include/linux/mm.h
43982f53 422@@ -1510,6 +1510,28 @@ static inline void unmap_shared_mapping_range(struct address_space *mapping,
a3232e84 423 unmap_mapping_range(mapping, holebegin, holelen, 0);
fb47a38f 424 }
fb47a38f 425
076b876e
AM
426+extern void vma_do_file_update_time(struct vm_area_struct *, const char[], int);
427+extern struct file *vma_do_pr_or_file(struct vm_area_struct *, const char[],
f2c43d5f 428+ int);
076b876e
AM
429+extern void vma_do_get_file(struct vm_area_struct *, const char[], int);
430+extern void vma_do_fput(struct vm_area_struct *, const char[], int);
fb47a38f 431+
f2c43d5f
AM
432+#define vma_file_update_time(vma) vma_do_file_update_time(vma, __func__, \
433+ __LINE__)
434+#define vma_pr_or_file(vma) vma_do_pr_or_file(vma, __func__, \
435+ __LINE__)
436+#define vma_get_file(vma) vma_do_get_file(vma, __func__, __LINE__)
437+#define vma_fput(vma) vma_do_fput(vma, __func__, __LINE__)
b912730e
AM
438+
439+#ifndef CONFIG_MMU
076b876e
AM
440+extern struct file *vmr_do_pr_or_file(struct vm_region *, const char[], int);
441+extern void vmr_do_fput(struct vm_region *, const char[], int);
442+
f2c43d5f
AM
443+#define vmr_pr_or_file(region) vmr_do_pr_or_file(region, __func__, \
444+ __LINE__)
445+#define vmr_fput(region) vmr_do_fput(region, __func__, __LINE__)
b912730e 446+#endif /* !CONFIG_MMU */
fb47a38f 447+
a3232e84
JR
448 extern int access_process_vm(struct task_struct *tsk, unsigned long addr,
449 void *buf, int len, unsigned int gup_flags);
fb47a38f 450 extern int access_remote_vm(struct mm_struct *mm, unsigned long addr,
fb47a38f 451diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
43982f53 452index 270aa8fd2800..33848c2165e2 100644
fb47a38f
JR
453--- a/include/linux/mm_types.h
454+++ b/include/linux/mm_types.h
43982f53 455@@ -267,6 +267,7 @@ struct vm_region {
fb47a38f
JR
456 unsigned long vm_top; /* region allocated to here */
457 unsigned long vm_pgoff; /* the offset in vm_file corresponding to vm_start */
458 struct file *vm_file; /* the backing file or NULL */
459+ struct file *vm_prfile; /* the virtual backing file or NULL */
460
461 int vm_usage; /* region usage count (access under nommu_region_sem) */
462 bool vm_icache_flushed : 1; /* true if the icache has been flushed for
43982f53 463@@ -341,6 +342,7 @@ struct vm_area_struct {
fb47a38f 464 unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE
5afbbe0d 465 units */
fb47a38f
JR
466 struct file * vm_file; /* File we map to (can be NULL). */
467+ struct file *vm_prfile; /* shadow of vm_file */
468 void * vm_private_data; /* was vm_pte (shared mem) */
469
eca34b5c 470 #ifdef CONFIG_SWAP
fb47a38f 471diff --git a/kernel/fork.c b/kernel/fork.c
43982f53 472index 13b38794efb5..ede7225bae95 100644
fb47a38f
JR
473--- a/kernel/fork.c
474+++ b/kernel/fork.c
43982f53 475@@ -562,7 +562,7 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
fb47a38f
JR
476 struct inode *inode = file_inode(file);
477 struct address_space *mapping = file->f_mapping;
478
479- get_file(file);
480+ vma_get_file(tmp);
481 if (tmp->vm_flags & VM_DENYWRITE)
482 atomic_dec(&inode->i_writecount);
2000de60 483 i_mmap_lock_write(mapping);
076b876e 484diff --git a/mm/Makefile b/mm/Makefile
43982f53 485index d996846697ef..fbadb91df4e4 100644
076b876e
AM
486--- a/mm/Makefile
487+++ b/mm/Makefile
43982f53 488@@ -42,7 +42,7 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \
076b876e 489 mm_init.o mmu_context.o percpu.o slab_common.o \
b00004a5 490 compaction.o vmacache.o \
076b876e 491 interval_tree.o list_lru.o workingset.o \
eca34b5c
AM
492- debug.o gup.o $(mmu-y)
493+ prfile.o debug.o gup.o $(mmu-y)
076b876e 494
fbc438ed
JR
495 # Give 'page_alloc' its own module-parameter namespace
496 page-alloc-y := page_alloc.o
fb47a38f 497diff --git a/mm/filemap.c b/mm/filemap.c
43982f53 498index 85b7d087eb45..115275a4a0e2 100644
fb47a38f
JR
499--- a/mm/filemap.c
500+++ b/mm/filemap.c
43982f53 501@@ -2696,7 +2696,7 @@ vm_fault_t filemap_page_mkwrite(struct vm_fault *vmf)
cd7a4cd9 502 vm_fault_t ret = VM_FAULT_LOCKED;
fb47a38f
JR
503
504 sb_start_pagefault(inode->i_sb);
521ced18
JR
505- file_update_time(vmf->vma->vm_file);
506+ vma_file_update_time(vmf->vma);
fb47a38f
JR
507 lock_page(page);
508 if (page->mapping != inode->i_mapping) {
509 unlock_page(page);
fb47a38f 510diff --git a/mm/mmap.c b/mm/mmap.c
43982f53 511index a7d8c84d19b7..9c350dc3f570 100644
fb47a38f
JR
512--- a/mm/mmap.c
513+++ b/mm/mmap.c
fbc438ed 514@@ -182,7 +182,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma)
fb47a38f
JR
515 if (vma->vm_ops && vma->vm_ops->close)
516 vma->vm_ops->close(vma);
517 if (vma->vm_file)
518- fput(vma->vm_file);
519+ vma_fput(vma);
520 mpol_put(vma_policy(vma));
cd7a4cd9 521 vm_area_free(vma);
fb47a38f 522 return next;
43982f53 523@@ -940,7 +940,7 @@ int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
fb47a38f
JR
524 if (remove_next) {
525 if (file) {
526 uprobe_munmap(next, next->vm_start, next->vm_end);
527- fput(file);
528+ vma_fput(vma);
529 }
530 if (next->anon_vma)
531 anon_vma_merge(vma, next);
43982f53 532@@ -1865,8 +1865,8 @@ unsigned long mmap_region(struct file *file, unsigned long addr,
35939ee7
JR
533 return addr;
534
fb47a38f 535 unmap_and_free_vma:
fb47a38f
JR
536+ vma_fput(vma);
537 vma->vm_file = NULL;
538- fput(file);
539
540 /* Undo any partial mapping done by a device driver. */
541 unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end);
43982f53 542@@ -2695,7 +2695,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
fb47a38f
JR
543 goto out_free_mpol;
544
545 if (new->vm_file)
546- get_file(new->vm_file);
547+ vma_get_file(new);
548
549 if (new->vm_ops && new->vm_ops->open)
550 new->vm_ops->open(new);
43982f53 551@@ -2714,7 +2714,7 @@ int __split_vma(struct mm_struct *mm, struct vm_area_struct *vma,
fb47a38f
JR
552 if (new->vm_ops && new->vm_ops->close)
553 new->vm_ops->close(new);
554 if (new->vm_file)
555- fput(new->vm_file);
556+ vma_fput(new);
557 unlink_anon_vmas(new);
558 out_free_mpol:
559 mpol_put(vma_policy(new));
43982f53 560@@ -2906,7 +2906,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
7e9cd9fe
AM
561 struct vm_area_struct *vma;
562 unsigned long populate = 0;
563 unsigned long ret = -EINVAL;
564- struct file *file;
5afbbe0d 565+ struct file *file, *prfile;
7e9cd9fe 566
cd7a4cd9 567 pr_warn_once("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/vm/remap_file_pages.rst.\n",
5afbbe0d 568 current->comm, current->pid);
43982f53 569@@ -2981,10 +2981,27 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
febd17d6 570 }
7e9cd9fe
AM
571 }
572
573- file = get_file(vma->vm_file);
574+ vma_get_file(vma);
5afbbe0d
AM
575+ file = vma->vm_file;
576+ prfile = vma->vm_prfile;
7e9cd9fe 577 ret = do_mmap_pgoff(vma->vm_file, start, size,
521ced18 578 prot, flags, pgoff, &populate, NULL);
5afbbe0d
AM
579+ if (!IS_ERR_VALUE(ret) && file && prfile) {
580+ struct vm_area_struct *new_vma;
581+
582+ new_vma = find_vma(mm, ret);
583+ if (!new_vma->vm_prfile)
584+ new_vma->vm_prfile = prfile;
585+ if (new_vma != vma)
586+ get_file(prfile);
587+ }
588+ /*
589+ * two fput()s instead of vma_fput(vma),
590+ * coz vma may not be available anymore.
591+ */
592 fput(file);
593+ if (prfile)
594+ fput(prfile);
7e9cd9fe
AM
595 out:
596 up_write(&mm->mmap_sem);
597 if (populate)
43982f53 598@@ -3274,7 +3291,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
79b8bda9
AM
599 if (anon_vma_clone(new_vma, vma))
600 goto out_free_mempol;
601 if (new_vma->vm_file)
602- get_file(new_vma->vm_file);
603+ vma_get_file(new_vma);
604 if (new_vma->vm_ops && new_vma->vm_ops->open)
605 new_vma->vm_ops->open(new_vma);
606 vma_link(mm, new_vma, prev, rb_link, rb_parent);
fb47a38f 607diff --git a/mm/nommu.c b/mm/nommu.c
43982f53 608index 99b7ec318824..de5b6cd162fe 100644
fb47a38f
JR
609--- a/mm/nommu.c
610+++ b/mm/nommu.c
eca34b5c 611@@ -552,7 +552,7 @@ static void __put_nommu_region(struct vm_region *region)
fb47a38f
JR
612 up_write(&nommu_region_sem);
613
614 if (region->vm_file)
615- fput(region->vm_file);
616+ vmr_fput(region);
617
618 /* IO memory and memory shared directly out of the pagecache
619 * from ramfs/tmpfs mustn't be released here */
eca34b5c 620@@ -690,7 +690,7 @@ static void delete_vma(struct mm_struct *mm, struct vm_area_struct *vma)
fb47a38f
JR
621 if (vma->vm_ops && vma->vm_ops->close)
622 vma->vm_ops->close(vma);
623 if (vma->vm_file)
624- fput(vma->vm_file);
625+ vma_fput(vma);
626 put_nommu_region(vma->vm_region);
cd7a4cd9 627 vm_area_free(vma);
fb47a38f 628 }
eca34b5c 629@@ -1213,7 +1213,7 @@ unsigned long do_mmap(struct file *file,
fb47a38f
JR
630 goto error_just_free;
631 }
632 }
633- fput(region->vm_file);
634+ vmr_fput(region);
635 kmem_cache_free(vm_region_jar, region);
636 region = pregion;
637 result = start;
eca34b5c 638@@ -1290,10 +1290,10 @@ unsigned long do_mmap(struct file *file,
fb47a38f
JR
639 up_write(&nommu_region_sem);
640 error:
641 if (region->vm_file)
642- fput(region->vm_file);
643+ vmr_fput(region);
644 kmem_cache_free(vm_region_jar, region);
645 if (vma->vm_file)
eca801bf
AM
646- fput(vma->vm_file);
647+ vma_fput(vma);
648 vm_area_free(vma);
649 return ret;
650
076b876e
AM
651diff --git a/mm/prfile.c b/mm/prfile.c
652new file mode 100644
016522bc 653index 000000000000..00d51187c325
076b876e
AM
654--- /dev/null
655+++ b/mm/prfile.c
2121bcd9 656@@ -0,0 +1,86 @@
cd7a4cd9 657+// SPDX-License-Identifier: GPL-2.0
076b876e 658+/*
1c60b727
AM
659+ * Mainly for aufs which mmap(2) different file and wants to print different
660+ * path in /proc/PID/maps.
076b876e
AM
661+ * Call these functions via macros defined in linux/mm.h.
662+ *
663+ * See Documentation/filesystems/aufs/design/06mmap.txt
664+ *
016522bc 665+ * Copyright (c) 2014-2020 Junjro R. Okajima
076b876e
AM
666+ * Copyright (c) 2014 Ian Campbell
667+ */
668+
669+#include <linux/mm.h>
670+#include <linux/file.h>
671+#include <linux/fs.h>
672+
673+/* #define PRFILE_TRACE */
674+static inline void prfile_trace(struct file *f, struct file *pr,
675+ const char func[], int line, const char func2[])
676+{
677+#ifdef PRFILE_TRACE
678+ if (pr)
1c60b727 679+ pr_info("%s:%d: %s, %pD2\n", func, line, func2, f);
076b876e
AM
680+#endif
681+}
682+
076b876e
AM
683+void vma_do_file_update_time(struct vm_area_struct *vma, const char func[],
684+ int line)
685+{
686+ struct file *f = vma->vm_file, *pr = vma->vm_prfile;
687+
688+ prfile_trace(f, pr, func, line, __func__);
689+ file_update_time(f);
690+ if (f && pr)
691+ file_update_time(pr);
692+}
693+
694+struct file *vma_do_pr_or_file(struct vm_area_struct *vma, const char func[],
695+ int line)
696+{
697+ struct file *f = vma->vm_file, *pr = vma->vm_prfile;
698+
699+ prfile_trace(f, pr, func, line, __func__);
700+ return (f && pr) ? pr : f;
701+}
702+
703+void vma_do_get_file(struct vm_area_struct *vma, const char func[], int line)
704+{
705+ struct file *f = vma->vm_file, *pr = vma->vm_prfile;
706+
707+ prfile_trace(f, pr, func, line, __func__);
708+ get_file(f);
709+ if (f && pr)
710+ get_file(pr);
711+}
712+
713+void vma_do_fput(struct vm_area_struct *vma, const char func[], int line)
714+{
715+ struct file *f = vma->vm_file, *pr = vma->vm_prfile;
716+
717+ prfile_trace(f, pr, func, line, __func__);
718+ fput(f);
719+ if (f && pr)
720+ fput(pr);
721+}
b912730e
AM
722+
723+#ifndef CONFIG_MMU
076b876e
AM
724+struct file *vmr_do_pr_or_file(struct vm_region *region, const char func[],
725+ int line)
726+{
727+ struct file *f = region->vm_file, *pr = region->vm_prfile;
728+
729+ prfile_trace(f, pr, func, line, __func__);
730+ return (f && pr) ? pr : f;
731+}
732+
733+void vmr_do_fput(struct vm_region *region, const char func[], int line)
734+{
735+ struct file *f = region->vm_file, *pr = region->vm_prfile;
736+
737+ prfile_trace(f, pr, func, line, __func__);
738+ fput(f);
739+ if (f && pr)
740+ fput(pr);
741+}
b912730e 742+#endif /* !CONFIG_MMU */
2121bcd9 743SPDX-License-Identifier: GPL-2.0
43982f53 744aufs5.4 standalone patch
7f207e10 745
c1595e42 746diff --git a/fs/dcache.c b/fs/dcache.c
eca34b5c 747index 7ce4ccf5a51c..00d7e6a08026 100644
c1595e42
JR
748--- a/fs/dcache.c
749+++ b/fs/dcache.c
eca34b5c 750@@ -1369,6 +1369,7 @@ void d_walk(struct dentry *parent, void *data,
c1595e42
JR
751 seq = 1;
752 goto again;
753 }
febd17d6 754+EXPORT_SYMBOL_GPL(d_walk);
c1595e42 755
a2654f78
AM
756 struct check_mount {
757 struct vfsmount *mnt;
eca34b5c 758@@ -2914,6 +2915,7 @@ void d_exchange(struct dentry *dentry1, struct dentry *dentry2)
f2c43d5f
AM
759
760 write_sequnlock(&rename_lock);
761 }
762+EXPORT_SYMBOL_GPL(d_exchange);
763
764 /**
765 * d_ancestor - search for an ancestor
79b8bda9 766diff --git a/fs/exec.c b/fs/exec.c
43982f53 767index 555e93c7dec8..dad39c6b3878 100644
79b8bda9
AM
768--- a/fs/exec.c
769+++ b/fs/exec.c
fbc438ed 770@@ -110,6 +110,7 @@ bool path_noexec(const struct path *path)
79b8bda9
AM
771 return (path->mnt->mnt_flags & MNT_NOEXEC) ||
772 (path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC);
773 }
febd17d6 774+EXPORT_SYMBOL_GPL(path_noexec);
79b8bda9
AM
775
776 #ifdef CONFIG_USELIB
777 /*
febd17d6 778diff --git a/fs/fcntl.c b/fs/fcntl.c
43982f53 779index 12dd73930961..0468c845190f 100644
febd17d6
JR
780--- a/fs/fcntl.c
781+++ b/fs/fcntl.c
43982f53 782@@ -85,6 +85,7 @@ int setfl(int fd, struct file *filp, unsigned long arg)
febd17d6
JR
783 out:
784 return error;
785 }
786+EXPORT_SYMBOL_GPL(setfl);
787
788 static void f_modown(struct file *filp, struct pid *pid, enum pid_type type,
789 int force)
b912730e 790diff --git a/fs/file_table.c b/fs/file_table.c
43982f53 791index 30d55c9a1744..34b9bbf4c556 100644
b912730e
AM
792--- a/fs/file_table.c
793+++ b/fs/file_table.c
fbc438ed 794@@ -162,6 +162,7 @@ struct file *alloc_empty_file(int flags, const struct cred *cred)
b912730e
AM
795 }
796 return ERR_PTR(-ENFILE);
797 }
acd2b654 798+EXPORT_SYMBOL_GPL(alloc_empty_file);
b912730e 799
acd2b654
AM
800 /*
801 * Variant of alloc_empty_file() that doesn't check and modify nr_files.
43982f53 802@@ -375,6 +376,7 @@ void __fput_sync(struct file *file)
8cdd5066
JR
803 }
804
805 EXPORT_SYMBOL(fput);
febd17d6 806+EXPORT_SYMBOL_GPL(__fput_sync);
8cdd5066 807
79b8bda9 808 void __init files_init(void)
8b6a4947 809 {
5afbbe0d 810diff --git a/fs/inode.c b/fs/inode.c
43982f53 811index aaeacde398ee..5be87f2d3828 100644
5afbbe0d
AM
812--- a/fs/inode.c
813+++ b/fs/inode.c
43982f53 814@@ -1682,6 +1682,7 @@ int update_time(struct inode *inode, struct timespec64 *time, int flags)
5afbbe0d
AM
815
816 return update_time(inode, time, flags);
817 }
818+EXPORT_SYMBOL_GPL(update_time);
819
820 /**
821 * touch_atime - update the access time
7f207e10 822diff --git a/fs/namespace.c b/fs/namespace.c
43982f53 823index 0f7e57e5f4b7..516c2f397d33 100644
7f207e10
AM
824--- a/fs/namespace.c
825+++ b/fs/namespace.c
eca34b5c 826@@ -431,6 +431,7 @@ void __mnt_drop_write(struct vfsmount *mnt)
c06a8ce3
AM
827 mnt_dec_writers(real_mount(mnt));
828 preempt_enable();
829 }
830+EXPORT_SYMBOL_GPL(__mnt_drop_write);
831
832 /**
833 * mnt_drop_write - give up write access to a mount
eca34b5c 834@@ -781,6 +782,7 @@ int is_current_mnt_ns(struct vfsmount *mnt)
8b6a4947
AM
835 {
836 return check_mnt(real_mount(mnt));
837 }
838+EXPORT_SYMBOL_GPL(is_current_mnt_ns);
839
840 /*
841 * vfsmount lock must be held for write
43982f53 842@@ -1903,6 +1905,7 @@ int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg,
7f207e10
AM
843 }
844 return 0;
845 }
febd17d6 846+EXPORT_SYMBOL_GPL(iterate_mounts);
7f207e10 847
fbc438ed 848 static void lock_mnt_tree(struct mount *mnt)
7f207e10 849 {
43982f53
AM
850diff --git a/fs/notify/group.c b/fs/notify/group.c
851index 133f723aca07..0b9f7f6d8390 100644
852--- a/fs/notify/group.c
853+++ b/fs/notify/group.c
854@@ -99,6 +99,7 @@ void fsnotify_get_group(struct fsnotify_group *group)
1716fcea 855 {
2121bcd9 856 refcount_inc(&group->refcnt);
1716fcea 857 }
febd17d6 858+EXPORT_SYMBOL_GPL(fsnotify_get_group);
1716fcea
AM
859
860 /*
861 * Drop a reference to a group. Free it if it's through.
7f207e10 862diff --git a/fs/open.c b/fs/open.c
43982f53 863index b62f5c0923a8..89af4b9c7319 100644
7f207e10
AM
864--- a/fs/open.c
865+++ b/fs/open.c
fbc438ed 866@@ -65,6 +65,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
febd17d6 867 inode_unlock(dentry->d_inode);
7f207e10
AM
868 return ret;
869 }
febd17d6 870+EXPORT_SYMBOL_GPL(do_truncate);
7f207e10 871
5afbbe0d 872 long vfs_truncate(const struct path *path, loff_t length)
7f207e10 873 {
5527c038 874diff --git a/fs/read_write.c b/fs/read_write.c
43982f53 875index fa9b3994b34c..eb0e2c6ebaff 100644
5527c038
JR
876--- a/fs/read_write.c
877+++ b/fs/read_write.c
fbc438ed 878@@ -468,6 +468,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
8b6a4947
AM
879
880 return ret;
881 }
882+EXPORT_SYMBOL_GPL(vfs_read);
883
884 static ssize_t new_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos)
885 {
fbc438ed 886@@ -508,6 +509,7 @@ vfs_readf_t vfs_readf(struct file *file)
5527c038 887 return new_sync_read;
43982f53 888 return ERR_PTR(-ENOSYS); /* doesn't have ->read(|_iter)() op */
5527c038 889 }
febd17d6 890+EXPORT_SYMBOL_GPL(vfs_readf);
5527c038
JR
891
892 vfs_writef_t vfs_writef(struct file *file)
893 {
fbc438ed 894@@ -519,6 +521,7 @@ vfs_writef_t vfs_writef(struct file *file)
5527c038 895 return new_sync_write;
43982f53 896 return ERR_PTR(-ENOSYS); /* doesn't have ->write(|_iter)() op */
5527c038 897 }
febd17d6 898+EXPORT_SYMBOL_GPL(vfs_writef);
5527c038 899
8b6a4947
AM
900 ssize_t __kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
901 {
fbc438ed 902@@ -588,6 +591,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
8b6a4947
AM
903
904 return ret;
905 }
906+EXPORT_SYMBOL_GPL(vfs_write);
907
fbc438ed
JR
908 /* file_ppos returns &file->f_pos or NULL if file is stream */
909 static inline loff_t *file_ppos(struct file *file)
7f207e10 910diff --git a/fs/splice.c b/fs/splice.c
eca34b5c 911index 75b489fcb66f..0a1f7498c22b 100644
7f207e10
AM
912--- a/fs/splice.c
913+++ b/fs/splice.c
fbc438ed 914@@ -847,6 +847,7 @@ long do_splice_from(struct pipe_inode_info *pipe, struct file *out,
392086de
AM
915
916 return splice_write(pipe, out, ppos, len, flags);
7f207e10 917 }
febd17d6 918+EXPORT_SYMBOL_GPL(do_splice_from);
7f207e10
AM
919
920 /*
921 * Attempt to initiate a splice from a file to a pipe.
fbc438ed 922@@ -876,6 +877,7 @@ long do_splice_to(struct file *in, loff_t *ppos,
7f207e10
AM
923
924 return splice_read(in, ppos, pipe, len, flags);
925 }
febd17d6 926+EXPORT_SYMBOL_GPL(do_splice_to);
7f207e10
AM
927
928 /**
929 * splice_direct_to_actor - splices data directly between two non-pipes
a2654f78 930diff --git a/fs/sync.c b/fs/sync.c
fbc438ed 931index 457f4e4a5cc1..67c66358f3fe 100644
a2654f78
AM
932--- a/fs/sync.c
933+++ b/fs/sync.c
2121bcd9 934@@ -39,6 +39,7 @@ int __sync_filesystem(struct super_block *sb, int wait)
a2654f78
AM
935 sb->s_op->sync_fs(sb, wait);
936 return __sync_blockdev(sb->s_bdev, wait);
937 }
938+EXPORT_SYMBOL_GPL(__sync_filesystem);
939
940 /*
941 * Write out and wait upon all dirty data associated with this
c1595e42 942diff --git a/fs/xattr.c b/fs/xattr.c
fbc438ed 943index 90dd78f0eb27..40b01dd1b14a 100644
c1595e42
JR
944--- a/fs/xattr.c
945+++ b/fs/xattr.c
fbc438ed 946@@ -296,6 +296,7 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
c1595e42
JR
947 *xattr_value = value;
948 return error;
949 }
febd17d6 950+EXPORT_SYMBOL_GPL(vfs_getxattr_alloc);
c1595e42 951
febd17d6 952 ssize_t
f2c43d5f 953 __vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
8b6a4947 954diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
43982f53 955index 407c08ac8ac8..d7f71842f8a2 100644
8b6a4947
AM
956--- a/kernel/locking/lockdep.c
957+++ b/kernel/locking/lockdep.c
eca34b5c
AM
958@@ -174,6 +174,7 @@ inline struct lock_class *lockdep_hlock_class(struct held_lock *hlock)
959 */
960 return lock_classes + class_idx;
8b6a4947
AM
961 }
962+EXPORT_SYMBOL_GPL(lockdep_hlock_class);
963 #define hlock_class(hlock) lockdep_hlock_class(hlock)
964
965 #ifdef CONFIG_LOCK_STAT
8cdd5066 966diff --git a/kernel/task_work.c b/kernel/task_work.c
ba1aed25 967index 0fef395662a6..83fb1ecfc33d 100644
8cdd5066
JR
968--- a/kernel/task_work.c
969+++ b/kernel/task_work.c
2121bcd9 970@@ -116,3 +116,4 @@ void task_work_run(void)
8cdd5066
JR
971 } while (work);
972 }
973 }
febd17d6 974+EXPORT_SYMBOL_GPL(task_work_run);
7f207e10 975diff --git a/security/device_cgroup.c b/security/device_cgroup.c
eca34b5c 976index 725674f3276d..83f6494c52a2 100644
7f207e10
AM
977--- a/security/device_cgroup.c
978+++ b/security/device_cgroup.c
83b672a5 979@@ -824,3 +824,4 @@ int __devcgroup_check_permission(short type, u32 major, u32 minor,
7f207e10 980
2121bcd9
AM
981 return 0;
982 }
983+EXPORT_SYMBOL_GPL(__devcgroup_check_permission);
7f207e10 984diff --git a/security/security.c b/security/security.c
43982f53 985index 1bc000f834e2..306f2c9f7ee2 100644
7f207e10
AM
986--- a/security/security.c
987+++ b/security/security.c
43982f53 988@@ -1036,6 +1036,7 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry)
7f207e10 989 return 0;
c2c0f25c 990 return call_int_hook(path_rmdir, 0, dir, dentry);
7f207e10 991 }
febd17d6 992+EXPORT_SYMBOL_GPL(security_path_rmdir);
7f207e10 993
5afbbe0d 994 int security_path_unlink(const struct path *dir, struct dentry *dentry)
7f207e10 995 {
43982f53 996@@ -1052,6 +1053,7 @@ int security_path_symlink(const struct path *dir, struct dentry *dentry,
7f207e10 997 return 0;
c2c0f25c 998 return call_int_hook(path_symlink, 0, dir, dentry, old_name);
7f207e10 999 }
febd17d6 1000+EXPORT_SYMBOL_GPL(security_path_symlink);
7f207e10 1001
5afbbe0d 1002 int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
7f207e10 1003 struct dentry *new_dentry)
43982f53 1004@@ -1060,6 +1062,7 @@ int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
7f207e10 1005 return 0;
c2c0f25c 1006 return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry);
7f207e10 1007 }
febd17d6 1008+EXPORT_SYMBOL_GPL(security_path_link);
7f207e10 1009
5afbbe0d
AM
1010 int security_path_rename(const struct path *old_dir, struct dentry *old_dentry,
1011 const struct path *new_dir, struct dentry *new_dentry,
43982f53 1012@@ -1087,6 +1090,7 @@ int security_path_truncate(const struct path *path)
7f207e10 1013 return 0;
c2c0f25c 1014 return call_int_hook(path_truncate, 0, path);
7f207e10 1015 }
febd17d6 1016+EXPORT_SYMBOL_GPL(security_path_truncate);
7f207e10 1017
5afbbe0d 1018 int security_path_chmod(const struct path *path, umode_t mode)
7eafdf33 1019 {
43982f53 1020@@ -1094,6 +1098,7 @@ int security_path_chmod(const struct path *path, umode_t mode)
7f207e10 1021 return 0;
c2c0f25c 1022 return call_int_hook(path_chmod, 0, path, mode);
7f207e10 1023 }
febd17d6 1024+EXPORT_SYMBOL_GPL(security_path_chmod);
7f207e10 1025
5afbbe0d 1026 int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
7f207e10 1027 {
43982f53 1028@@ -1101,6 +1106,7 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
7f207e10 1029 return 0;
c2c0f25c 1030 return call_int_hook(path_chown, 0, path, uid, gid);
7f207e10 1031 }
febd17d6 1032+EXPORT_SYMBOL_GPL(security_path_chown);
7f207e10 1033
5afbbe0d 1034 int security_path_chroot(const struct path *path)
7f207e10 1035 {
43982f53 1036@@ -1201,6 +1207,7 @@ int security_inode_permission(struct inode *inode, int mask)
7f207e10 1037 return 0;
c2c0f25c 1038 return call_int_hook(inode_permission, 0, inode, mask);
7f207e10 1039 }
febd17d6 1040+EXPORT_SYMBOL_GPL(security_inode_permission);
7f207e10 1041
1e00d052 1042 int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
7f207e10 1043 {
43982f53 1044@@ -1378,6 +1385,7 @@ int security_file_permission(struct file *file, int mask)
7f207e10
AM
1045
1046 return fsnotify_perm(file, mask);
1047 }
febd17d6 1048+EXPORT_SYMBOL_GPL(security_file_permission);
7f207e10
AM
1049
1050 int security_file_alloc(struct file *file)
1051 {
7f207e10 1052diff -urN /usr/share/empty/Documentation/ABI/testing/debugfs-aufs linux/Documentation/ABI/testing/debugfs-aufs
eca34b5c
AM
1053--- /usr/share/empty/Documentation/ABI/testing/debugfs-aufs 1970-01-01 01:00:00.000000000 +0100
1054+++ linux/Documentation/ABI/testing/debugfs-aufs 2019-07-11 15:42:14.455570938 +0200
062440b3 1055@@ -0,0 +1,55 @@
7f207e10
AM
1056+What: /debug/aufs/si_<id>/
1057+Date: March 2009
f6b6e03d 1058+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
1059+Description:
1060+ Under /debug/aufs, a directory named si_<id> is created
1061+ per aufs mount, where <id> is a unique id generated
1062+ internally.
1facf9fc 1063+
86dc4139
AM
1064+What: /debug/aufs/si_<id>/plink
1065+Date: Apr 2013
f6b6e03d 1066+Contact: J. R. Okajima <hooanon05g@gmail.com>
86dc4139
AM
1067+Description:
1068+ It has three lines and shows the information about the
1069+ pseudo-link. The first line is a single number
1070+ representing a number of buckets. The second line is a
1071+ number of pseudo-links per buckets (separated by a
1072+ blank). The last line is a single number representing a
1073+ total number of psedo-links.
1074+ When the aufs mount option 'noplink' is specified, it
1075+ will show "1\n0\n0\n".
1076+
7f207e10
AM
1077+What: /debug/aufs/si_<id>/xib
1078+Date: March 2009
f6b6e03d 1079+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
1080+Description:
1081+ It shows the consumed blocks by xib (External Inode Number
1082+ Bitmap), its block size and file size.
1083+ When the aufs mount option 'noxino' is specified, it
1084+ will be empty. About XINO files, see the aufs manual.
1085+
062440b3 1086+What: /debug/aufs/si_<id>/xi0, xi1 ... xiN and xiN-N
7f207e10 1087+Date: March 2009
f6b6e03d 1088+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
1089+Description:
1090+ It shows the consumed blocks by xino (External Inode Number
1091+ Translation Table), its link count, block size and file
1092+ size.
062440b3
AM
1093+ Due to the file size limit, there may exist multiple
1094+ xino files per branch. In this case, "-N" is added to
1095+ the filename and it corresponds to the index of the
1096+ internal xino array. "-0" is omitted.
1097+ When the aufs mount option 'noxino' is specified, Those
1098+ entries won't exist. About XINO files, see the aufs
1099+ manual.
7f207e10
AM
1100+
1101+What: /debug/aufs/si_<id>/xigen
1102+Date: March 2009
f6b6e03d 1103+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
1104+Description:
1105+ It shows the consumed blocks by xigen (External Inode
1106+ Generation Table), its block size and file size.
1107+ If CONFIG_AUFS_EXPORT is disabled, this entry will not
1108+ be created.
1109+ When the aufs mount option 'noxino' is specified, it
1110+ will be empty. About XINO files, see the aufs manual.
1111diff -urN /usr/share/empty/Documentation/ABI/testing/sysfs-aufs linux/Documentation/ABI/testing/sysfs-aufs
eca34b5c
AM
1112--- /usr/share/empty/Documentation/ABI/testing/sysfs-aufs 1970-01-01 01:00:00.000000000 +0100
1113+++ linux/Documentation/ABI/testing/sysfs-aufs 2019-07-11 15:42:14.455570938 +0200
392086de 1114@@ -0,0 +1,31 @@
7f207e10
AM
1115+What: /sys/fs/aufs/si_<id>/
1116+Date: March 2009
f6b6e03d 1117+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
1118+Description:
1119+ Under /sys/fs/aufs, a directory named si_<id> is created
1120+ per aufs mount, where <id> is a unique id generated
1121+ internally.
1122+
1123+What: /sys/fs/aufs/si_<id>/br0, br1 ... brN
1124+Date: March 2009
f6b6e03d 1125+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
1126+Description:
1127+ It shows the abolute path of a member directory (which
1128+ is called branch) in aufs, and its permission.
1129+
392086de
AM
1130+What: /sys/fs/aufs/si_<id>/brid0, brid1 ... bridN
1131+Date: July 2013
f6b6e03d 1132+Contact: J. R. Okajima <hooanon05g@gmail.com>
392086de
AM
1133+Description:
1134+ It shows the id of a member directory (which is called
1135+ branch) in aufs.
1136+
7f207e10
AM
1137+What: /sys/fs/aufs/si_<id>/xi_path
1138+Date: March 2009
f6b6e03d 1139+Contact: J. R. Okajima <hooanon05g@gmail.com>
7f207e10
AM
1140+Description:
1141+ It shows the abolute path of XINO (External Inode Number
1142+ Bitmap, Translation Table and Generation Table) file
1143+ even if it is the default path.
1144+ When the aufs mount option 'noxino' is specified, it
1145+ will be empty. About XINO files, see the aufs manual.
53392da6 1146diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt linux/Documentation/filesystems/aufs/design/01intro.txt
eca34b5c 1147--- /usr/share/empty/Documentation/filesystems/aufs/design/01intro.txt 1970-01-01 01:00:00.000000000 +0100
016522bc 1148+++ linux/Documentation/filesystems/aufs/design/01intro.txt 2020-01-27 10:57:18.162204582 +0100
1c60b727 1149@@ -0,0 +1,171 @@
53392da6 1150+
016522bc 1151+# Copyright (C) 2005-2020 Junjiro R. Okajima
53392da6
AM
1152+#
1153+# This program is free software; you can redistribute it and/or modify
1154+# it under the terms of the GNU General Public License as published by
1155+# the Free Software Foundation; either version 2 of the License, or
1156+# (at your option) any later version.
1157+#
1158+# This program is distributed in the hope that it will be useful,
1159+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1160+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1161+# GNU General Public License for more details.
1162+#
1163+# You should have received a copy of the GNU General Public License
523b37e3 1164+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1165+
1166+Introduction
1167+----------------------------------------
1168+
3c1bdaff 1169+aufs [ei ju: ef es] | /ey-yoo-ef-es/ | [a u f s]
53392da6
AM
1170+1. abbrev. for "advanced multi-layered unification filesystem".
1171+2. abbrev. for "another unionfs".
1172+3. abbrev. for "auf das" in German which means "on the" in English.
1173+ Ex. "Butter aufs Brot"(G) means "butter onto bread"(E).
1174+ But "Filesystem aufs Filesystem" is hard to understand.
1c60b727 1175+4. abbrev. for "African Urban Fashion Show".
53392da6
AM
1176+
1177+AUFS is a filesystem with features:
1178+- multi layered stackable unification filesystem, the member directory
1179+ is called as a branch.
1180+- branch permission and attribute, 'readonly', 'real-readonly',
7e9cd9fe 1181+ 'readwrite', 'whiteout-able', 'link-able whiteout', etc. and their
53392da6
AM
1182+ combination.
1183+- internal "file copy-on-write".
1184+- logical deletion, whiteout.
1185+- dynamic branch manipulation, adding, deleting and changing permission.
1186+- allow bypassing aufs, user's direct branch access.
1187+- external inode number translation table and bitmap which maintains the
1188+ persistent aufs inode number.
1189+- seekable directory, including NFS readdir.
1190+- file mapping, mmap and sharing pages.
1191+- pseudo-link, hardlink over branches.
1192+- loopback mounted filesystem as a branch.
1193+- several policies to select one among multiple writable branches.
1194+- revert a single systemcall when an error occurs in aufs.
1195+- and more...
1196+
1197+
1198+Multi Layered Stackable Unification Filesystem
1199+----------------------------------------------------------------------
1200+Most people already knows what it is.
1201+It is a filesystem which unifies several directories and provides a
1202+merged single directory. When users access a file, the access will be
1203+passed/re-directed/converted (sorry, I am not sure which English word is
1204+correct) to the real file on the member filesystem. The member
1205+filesystem is called 'lower filesystem' or 'branch' and has a mode
1206+'readonly' and 'readwrite.' And the deletion for a file on the lower
1207+readonly branch is handled by creating 'whiteout' on the upper writable
1208+branch.
1209+
1210+On LKML, there have been discussions about UnionMount (Jan Blunck,
1211+Bharata B Rao and Valerie Aurora) and Unionfs (Erez Zadok). They took
1212+different approaches to implement the merged-view.
1213+The former tries putting it into VFS, and the latter implements as a
1214+separate filesystem.
1215+(If I misunderstand about these implementations, please let me know and
1216+I shall correct it. Because it is a long time ago when I read their
1217+source files last time).
1218+
1219+UnionMount's approach will be able to small, but may be hard to share
1220+branches between several UnionMount since the whiteout in it is
1221+implemented in the inode on branch filesystem and always
1222+shared. According to Bharata's post, readdir does not seems to be
1223+finished yet.
1224+There are several missing features known in this implementations such as
1225+- for users, the inode number may change silently. eg. copy-up.
1226+- link(2) may break by copy-up.
1227+- read(2) may get an obsoleted filedata (fstat(2) too).
1228+- fcntl(F_SETLK) may be broken by copy-up.
1229+- unnecessary copy-up may happen, for example mmap(MAP_PRIVATE) after
1230+ open(O_RDWR).
1231+
7e9cd9fe
AM
1232+In linux-3.18, "overlay" filesystem (formerly known as "overlayfs") was
1233+merged into mainline. This is another implementation of UnionMount as a
1234+separated filesystem. All the limitations and known problems which
1235+UnionMount are equally inherited to "overlay" filesystem.
1236+
1237+Unionfs has a longer history. When I started implementing a stackable
1238+filesystem (Aug 2005), it already existed. It has virtual super_block,
1239+inode, dentry and file objects and they have an array pointing lower
1240+same kind objects. After contributing many patches for Unionfs, I
1241+re-started my project AUFS (Jun 2006).
53392da6
AM
1242+
1243+In AUFS, the structure of filesystem resembles to Unionfs, but I
1244+implemented my own ideas, approaches and enhancements and it became
1245+totally different one.
1246+
1247+Comparing DM snapshot and fs based implementation
1248+- the number of bytes to be copied between devices is much smaller.
1249+- the type of filesystem must be one and only.
1250+- the fs must be writable, no readonly fs, even for the lower original
1251+ device. so the compression fs will not be usable. but if we use
1252+ loopback mount, we may address this issue.
1253+ for instance,
1254+ mount /cdrom/squashfs.img /sq
1255+ losetup /sq/ext2.img
1256+ losetup /somewhere/cow
1257+ dmsetup "snapshot /dev/loop0 /dev/loop1 ..."
1258+- it will be difficult (or needs more operations) to extract the
1259+ difference between the original device and COW.
1260+- DM snapshot-merge may help a lot when users try merging. in the
1261+ fs-layer union, users will use rsync(1).
1262+
7e9cd9fe
AM
1263+You may want to read my old paper "Filesystems in LiveCD"
1264+(http://aufs.sourceforge.net/aufs2/report/sq/sq.pdf).
53392da6 1265+
7e9cd9fe
AM
1266+
1267+Several characters/aspects/persona of aufs
53392da6
AM
1268+----------------------------------------------------------------------
1269+
7e9cd9fe 1270+Aufs has several characters, aspects or persona.
53392da6
AM
1271+1. a filesystem, callee of VFS helper
1272+2. sub-VFS, caller of VFS helper for branches
1273+3. a virtual filesystem which maintains persistent inode number
1274+4. reader/writer of files on branches such like an application
1275+
1276+1. Callee of VFS Helper
1277+As an ordinary linux filesystem, aufs is a callee of VFS. For instance,
1278+unlink(2) from an application reaches sys_unlink() kernel function and
1279+then vfs_unlink() is called. vfs_unlink() is one of VFS helper and it
1280+calls filesystem specific unlink operation. Actually aufs implements the
1281+unlink operation but it behaves like a redirector.
1282+
1283+2. Caller of VFS Helper for Branches
1284+aufs_unlink() passes the unlink request to the branch filesystem as if
1285+it were called from VFS. So the called unlink operation of the branch
1286+filesystem acts as usual. As a caller of VFS helper, aufs should handle
1287+every necessary pre/post operation for the branch filesystem.
1288+- acquire the lock for the parent dir on a branch
1289+- lookup in a branch
1290+- revalidate dentry on a branch
1291+- mnt_want_write() for a branch
1292+- vfs_unlink() for a branch
1293+- mnt_drop_write() for a branch
1294+- release the lock on a branch
1295+
1296+3. Persistent Inode Number
1297+One of the most important issue for a filesystem is to maintain inode
1298+numbers. This is particularly important to support exporting a
1299+filesystem via NFS. Aufs is a virtual filesystem which doesn't have a
1300+backend block device for its own. But some storage is necessary to
7e9cd9fe
AM
1301+keep and maintain the inode numbers. It may be a large space and may not
1302+suit to keep in memory. Aufs rents some space from its first writable
1303+branch filesystem (by default) and creates file(s) on it. These files
1304+are created by aufs internally and removed soon (currently) keeping
1305+opened.
53392da6
AM
1306+Note: Because these files are removed, they are totally gone after
1307+ unmounting aufs. It means the inode numbers are not persistent
1308+ across unmount or reboot. I have a plan to make them really
1309+ persistent which will be important for aufs on NFS server.
1310+
1311+4. Read/Write Files Internally (copy-on-write)
1312+Because a branch can be readonly, when you write a file on it, aufs will
1313+"copy-up" it to the upper writable branch internally. And then write the
1314+originally requested thing to the file. Generally kernel doesn't
1315+open/read/write file actively. In aufs, even a single write may cause a
1316+internal "file copy". This behaviour is very similar to cp(1) command.
1317+
1318+Some people may think it is better to pass such work to user space
1319+helper, instead of doing in kernel space. Actually I am still thinking
1320+about it. But currently I have implemented it in kernel space.
1321diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt linux/Documentation/filesystems/aufs/design/02struct.txt
eca34b5c 1322--- /usr/share/empty/Documentation/filesystems/aufs/design/02struct.txt 1970-01-01 01:00:00.000000000 +0100
016522bc 1323+++ linux/Documentation/filesystems/aufs/design/02struct.txt 2020-01-27 10:57:18.162204582 +0100
7e9cd9fe 1324@@ -0,0 +1,258 @@
53392da6 1325+
016522bc 1326+# Copyright (C) 2005-2020 Junjiro R. Okajima
53392da6
AM
1327+#
1328+# This program is free software; you can redistribute it and/or modify
1329+# it under the terms of the GNU General Public License as published by
1330+# the Free Software Foundation; either version 2 of the License, or
1331+# (at your option) any later version.
1332+#
1333+# This program is distributed in the hope that it will be useful,
1334+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1335+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1336+# GNU General Public License for more details.
1337+#
1338+# You should have received a copy of the GNU General Public License
523b37e3 1339+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1340+
1341+Basic Aufs Internal Structure
1342+
1343+Superblock/Inode/Dentry/File Objects
1344+----------------------------------------------------------------------
1345+As like an ordinary filesystem, aufs has its own
1346+superblock/inode/dentry/file objects. All these objects have a
1347+dynamically allocated array and store the same kind of pointers to the
1348+lower filesystem, branch.
1349+For example, when you build a union with one readwrite branch and one
1350+readonly, mounted /au, /rw and /ro respectively.
1351+- /au = /rw + /ro
1352+- /ro/fileA exists but /rw/fileA
1353+
1354+Aufs lookup operation finds /ro/fileA and gets dentry for that. These
1355+pointers are stored in a aufs dentry. The array in aufs dentry will be,
7e9cd9fe 1356+- [0] = NULL (because /rw/fileA doesn't exist)
53392da6
AM
1357+- [1] = /ro/fileA
1358+
1359+This style of an array is essentially same to the aufs
1360+superblock/inode/dentry/file objects.
1361+
1362+Because aufs supports manipulating branches, ie. add/delete/change
7e9cd9fe
AM
1363+branches dynamically, these objects has its own generation. When
1364+branches are changed, the generation in aufs superblock is
1365+incremented. And a generation in other object are compared when it is
1366+accessed. When a generation in other objects are obsoleted, aufs
1367+refreshes the internal array.
53392da6
AM
1368+
1369+
1370+Superblock
1371+----------------------------------------------------------------------
1372+Additionally aufs superblock has some data for policies to select one
1373+among multiple writable branches, XIB files, pseudo-links and kobject.
1374+See below in detail.
7e9cd9fe
AM
1375+About the policies which supports copy-down a directory, see
1376+wbr_policy.txt too.
53392da6
AM
1377+
1378+
1379+Branch and XINO(External Inode Number Translation Table)
1380+----------------------------------------------------------------------
1381+Every branch has its own xino (external inode number translation table)
1382+file. The xino file is created and unlinked by aufs internally. When two
1383+members of a union exist on the same filesystem, they share the single
1384+xino file.
1385+The struct of a xino file is simple, just a sequence of aufs inode
1386+numbers which is indexed by the lower inode number.
1387+In the above sample, assume the inode number of /ro/fileA is i111 and
1388+aufs assigns the inode number i999 for fileA. Then aufs writes 999 as
1389+4(8) bytes at 111 * 4(8) bytes offset in the xino file.
1390+
1391+When the inode numbers are not contiguous, the xino file will be sparse
1392+which has a hole in it and doesn't consume as much disk space as it
1393+might appear. If your branch filesystem consumes disk space for such
1394+holes, then you should specify 'xino=' option at mounting aufs.
1395+
7e9cd9fe
AM
1396+Aufs has a mount option to free the disk blocks for such holes in XINO
1397+files on tmpfs or ramdisk. But it is not so effective actually. If you
1398+meet a problem of disk shortage due to XINO files, then you should try
1399+"tmpfs-ino.patch" (and "vfs-ino.patch" too) in aufs4-standalone.git.
1400+The patch localizes the assignment inumbers per tmpfs-mount and avoid
1401+the holes in XINO files.
1402+
53392da6 1403+Also a writable branch has three kinds of "whiteout bases". All these
7e9cd9fe 1404+are existed when the branch is joined to aufs, and their names are
53392da6
AM
1405+whiteout-ed doubly, so that users will never see their names in aufs
1406+hierarchy.
7e9cd9fe 1407+1. a regular file which will be hardlinked to all whiteouts.
53392da6 1408+2. a directory to store a pseudo-link.
7e9cd9fe 1409+3. a directory to store an "orphan"-ed file temporary.
53392da6
AM
1410+
1411+1. Whiteout Base
1412+ When you remove a file on a readonly branch, aufs handles it as a
1413+ logical deletion and creates a whiteout on the upper writable branch
1414+ as a hardlink of this file in order not to consume inode on the
1415+ writable branch.
1416+2. Pseudo-link Dir
1417+ See below, Pseudo-link.
1418+3. Step-Parent Dir
1419+ When "fileC" exists on the lower readonly branch only and it is
1420+ opened and removed with its parent dir, and then user writes
1421+ something into it, then aufs copies-up fileC to this
1422+ directory. Because there is no other dir to store fileC. After
1423+ creating a file under this dir, the file is unlinked.
1424+
1425+Because aufs supports manipulating branches, ie. add/delete/change
7e9cd9fe
AM
1426+dynamically, a branch has its own id. When the branch order changes,
1427+aufs finds the new index by searching the branch id.
53392da6
AM
1428+
1429+
1430+Pseudo-link
1431+----------------------------------------------------------------------
1432+Assume "fileA" exists on the lower readonly branch only and it is
1433+hardlinked to "fileB" on the branch. When you write something to fileA,
1434+aufs copies-up it to the upper writable branch. Additionally aufs
1435+creates a hardlink under the Pseudo-link Directory of the writable
1436+branch. The inode of a pseudo-link is kept in aufs super_block as a
1437+simple list. If fileB is read after unlinking fileA, aufs returns
1438+filedata from the pseudo-link instead of the lower readonly
1439+branch. Because the pseudo-link is based upon the inode, to keep the
7e9cd9fe 1440+inode number by xino (see above) is essentially necessary.
53392da6
AM
1441+
1442+All the hardlinks under the Pseudo-link Directory of the writable branch
1443+should be restored in a proper location later. Aufs provides a utility
1444+to do this. The userspace helpers executed at remounting and unmounting
1445+aufs by default.
1446+During this utility is running, it puts aufs into the pseudo-link
1447+maintenance mode. In this mode, only the process which began the
1448+maintenance mode (and its child processes) is allowed to operate in
1449+aufs. Some other processes which are not related to the pseudo-link will
1450+be allowed to run too, but the rest have to return an error or wait
1451+until the maintenance mode ends. If a process already acquires an inode
1452+mutex (in VFS), it has to return an error.
1453+
1454+
1455+XIB(external inode number bitmap)
1456+----------------------------------------------------------------------
1457+Addition to the xino file per a branch, aufs has an external inode number
7e9cd9fe
AM
1458+bitmap in a superblock object. It is also an internal file such like a
1459+xino file.
53392da6
AM
1460+It is a simple bitmap to mark whether the aufs inode number is in-use or
1461+not.
1462+To reduce the file I/O, aufs prepares a single memory page to cache xib.
1463+
7e9cd9fe 1464+As well as XINO files, aufs has a feature to truncate/refresh XIB to
53392da6
AM
1465+reduce the number of consumed disk blocks for these files.
1466+
1467+
1468+Virtual or Vertical Dir, and Readdir in Userspace
1469+----------------------------------------------------------------------
1470+In order to support multiple layers (branches), aufs readdir operation
1471+constructs a virtual dir block on memory. For readdir, aufs calls
1472+vfs_readdir() internally for each dir on branches, merges their entries
1473+with eliminating the whiteout-ed ones, and sets it to file (dir)
1474+object. So the file object has its entry list until it is closed. The
1475+entry list will be updated when the file position is zero and becomes
7e9cd9fe 1476+obsoleted. This decision is made in aufs automatically.
53392da6
AM
1477+
1478+The dynamically allocated memory block for the name of entries has a
1479+unit of 512 bytes (by default) and stores the names contiguously (no
1480+padding). Another block for each entry is handled by kmem_cache too.
1481+During building dir blocks, aufs creates hash list and judging whether
1482+the entry is whiteouted by its upper branch or already listed.
1483+The merged result is cached in the corresponding inode object and
1484+maintained by a customizable life-time option.
1485+
1486+Some people may call it can be a security hole or invite DoS attack
1487+since the opened and once readdir-ed dir (file object) holds its entry
1488+list and becomes a pressure for system memory. But I'd say it is similar
1489+to files under /proc or /sys. The virtual files in them also holds a
1490+memory page (generally) while they are opened. When an idea to reduce
1491+memory for them is introduced, it will be applied to aufs too.
1492+For those who really hate this situation, I've developed readdir(3)
1493+library which operates this merging in userspace. You just need to set
1494+LD_PRELOAD environment variable, and aufs will not consume no memory in
1495+kernel space for readdir(3).
1496+
1497+
1498+Workqueue
1499+----------------------------------------------------------------------
1500+Aufs sometimes requires privilege access to a branch. For instance,
1501+in copy-up/down operation. When a user process is going to make changes
1502+to a file which exists in the lower readonly branch only, and the mode
1503+of one of ancestor directories may not be writable by a user
1504+process. Here aufs copy-up the file with its ancestors and they may
1505+require privilege to set its owner/group/mode/etc.
1506+This is a typical case of a application character of aufs (see
1507+Introduction).
1508+
1509+Aufs uses workqueue synchronously for this case. It creates its own
1510+workqueue. The workqueue is a kernel thread and has privilege. Aufs
1511+passes the request to call mkdir or write (for example), and wait for
1512+its completion. This approach solves a problem of a signal handler
1513+simply.
1514+If aufs didn't adopt the workqueue and changed the privilege of the
7e9cd9fe
AM
1515+process, then the process may receive the unexpected SIGXFSZ or other
1516+signals.
53392da6
AM
1517+
1518+Also aufs uses the system global workqueue ("events" kernel thread) too
1519+for asynchronous tasks, such like handling inotify/fsnotify, re-creating a
1520+whiteout base and etc. This is unrelated to a privilege.
1521+Most of aufs operation tries acquiring a rw_semaphore for aufs
1522+superblock at the beginning, at the same time waits for the completion
1523+of all queued asynchronous tasks.
1524+
1525+
1526+Whiteout
1527+----------------------------------------------------------------------
1528+The whiteout in aufs is very similar to Unionfs's. That is represented
1529+by its filename. UnionMount takes an approach of a file mode, but I am
1530+afraid several utilities (find(1) or something) will have to support it.
1531+
1532+Basically the whiteout represents "logical deletion" which stops aufs to
1533+lookup further, but also it represents "dir is opaque" which also stop
7e9cd9fe 1534+further lookup.
53392da6
AM
1535+
1536+In aufs, rmdir(2) and rename(2) for dir uses whiteout alternatively.
1537+In order to make several functions in a single systemcall to be
1538+revertible, aufs adopts an approach to rename a directory to a temporary
1539+unique whiteouted name.
1540+For example, in rename(2) dir where the target dir already existed, aufs
1541+renames the target dir to a temporary unique whiteouted name before the
7e9cd9fe 1542+actual rename on a branch, and then handles other actions (make it opaque,
53392da6
AM
1543+update the attributes, etc). If an error happens in these actions, aufs
1544+simply renames the whiteouted name back and returns an error. If all are
1545+succeeded, aufs registers a function to remove the whiteouted unique
1546+temporary name completely and asynchronously to the system global
1547+workqueue.
1548+
1549+
1550+Copy-up
1551+----------------------------------------------------------------------
1552+It is a well-known feature or concept.
1553+When user modifies a file on a readonly branch, aufs operate "copy-up"
1554+internally and makes change to the new file on the upper writable branch.
1555+When the trigger systemcall does not update the timestamps of the parent
1556+dir, aufs reverts it after copy-up.
c2b27bf2
AM
1557+
1558+
1559+Move-down (aufs3.9 and later)
1560+----------------------------------------------------------------------
1561+"Copy-up" is one of the essential feature in aufs. It copies a file from
1562+the lower readonly branch to the upper writable branch when a user
1563+changes something about the file.
1564+"Move-down" is an opposite action of copy-up. Basically this action is
1565+ran manually instead of automatically and internally.
076b876e
AM
1566+For desgin and implementation, aufs has to consider these issues.
1567+- whiteout for the file may exist on the lower branch.
1568+- ancestor directories may not exist on the lower branch.
1569+- diropq for the ancestor directories may exist on the upper branch.
1570+- free space on the lower branch will reduce.
1571+- another access to the file may happen during moving-down, including
7e9cd9fe 1572+ UDBA (see "Revalidate Dentry and UDBA").
076b876e
AM
1573+- the file should not be hard-linked nor pseudo-linked. they should be
1574+ handled by auplink utility later.
c2b27bf2
AM
1575+
1576+Sometimes users want to move-down a file from the upper writable branch
1577+to the lower readonly or writable branch. For instance,
1578+- the free space of the upper writable branch is going to run out.
1579+- create a new intermediate branch between the upper and lower branch.
1580+- etc.
1581+
1582+For this purpose, use "aumvdown" command in aufs-util.git.
b912730e 1583diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/03atomic_open.txt linux/Documentation/filesystems/aufs/design/03atomic_open.txt
eca34b5c 1584--- /usr/share/empty/Documentation/filesystems/aufs/design/03atomic_open.txt 1970-01-01 01:00:00.000000000 +0100
016522bc 1585+++ linux/Documentation/filesystems/aufs/design/03atomic_open.txt 2020-01-27 10:57:18.162204582 +0100
b912730e
AM
1586@@ -0,0 +1,85 @@
1587+
016522bc 1588+# Copyright (C) 2015-2020 Junjiro R. Okajima
b912730e
AM
1589+#
1590+# This program is free software; you can redistribute it and/or modify
1591+# it under the terms of the GNU General Public License as published by
1592+# the Free Software Foundation; either version 2 of the License, or
1593+# (at your option) any later version.
1594+#
1595+# This program is distributed in the hope that it will be useful,
1596+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1597+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1598+# GNU General Public License for more details.
1599+#
1600+# You should have received a copy of the GNU General Public License
1601+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1602+
1603+Support for a branch who has its ->atomic_open()
1604+----------------------------------------------------------------------
1605+The filesystems who implement its ->atomic_open() are not majority. For
1606+example NFSv4 does, and aufs should call NFSv4 ->atomic_open,
1607+particularly for open(O_CREAT|O_EXCL, 0400) case. Other than
1608+->atomic_open(), NFSv4 returns an error for this open(2). While I am not
1609+sure whether all filesystems who have ->atomic_open() behave like this,
1610+but NFSv4 surely returns the error.
1611+
1612+In order to support ->atomic_open() for aufs, there are a few
1613+approaches.
1614+
1615+A. Introduce aufs_atomic_open()
1616+ - calls one of VFS:do_last(), lookup_open() or atomic_open() for
1617+ branch fs.
1618+B. Introduce aufs_atomic_open() calling create, open and chmod. this is
1619+ an aufs user Pip Cet's approach
1620+ - calls aufs_create(), VFS finish_open() and notify_change().
1621+ - pass fake-mode to finish_open(), and then correct the mode by
1622+ notify_change().
1623+C. Extend aufs_open() to call branch fs's ->atomic_open()
1624+ - no aufs_atomic_open().
1625+ - aufs_lookup() registers the TID to an aufs internal object.
1626+ - aufs_create() does nothing when the matching TID is registered, but
1627+ registers the mode.
1628+ - aufs_open() calls branch fs's ->atomic_open() when the matching
1629+ TID is registered.
1630+D. Extend aufs_open() to re-try branch fs's ->open() with superuser's
1631+ credential
1632+ - no aufs_atomic_open().
1633+ - aufs_create() registers the TID to an internal object. this info
1634+ represents "this process created this file just now."
1635+ - when aufs gets EACCES from branch fs's ->open(), then confirm the
1636+ registered TID and re-try open() with superuser's credential.
1637+
1638+Pros and cons for each approach.
1639+
1640+A.
1641+ - straightforward but highly depends upon VFS internal.
1642+ - the atomic behavaiour is kept.
1643+ - some of parameters such as nameidata are hard to reproduce for
1644+ branch fs.
1645+ - large overhead.
1646+B.
1647+ - easy to implement.
1648+ - the atomic behavaiour is lost.
1649+C.
1650+ - the atomic behavaiour is kept.
1651+ - dirty and tricky.
1652+ - VFS checks whether the file is created correctly after calling
1653+ ->create(), which means this approach doesn't work.
1654+D.
1655+ - easy to implement.
1656+ - the atomic behavaiour is lost.
1657+ - to open a file with superuser's credential and give it to a user
1658+ process is a bad idea, since the file object keeps the credential
1659+ in it. It may affect LSM or something. This approach doesn't work
1660+ either.
1661+
1662+The approach A is ideal, but it hard to implement. So here is a
1663+variation of A, which is to be implemented.
1664+
1665+A-1. Introduce aufs_atomic_open()
1666+ - calls branch fs ->atomic_open() if exists. otherwise calls
1667+ vfs_create() and finish_open().
1668+ - the demerit is that the several checks after branch fs
1669+ ->atomic_open() are lost. in the ordinary case, the checks are
1670+ done by VFS:do_last(), lookup_open() and atomic_open(). some can
1671+ be implemented in aufs, but not all I am afraid.
53392da6 1672diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt linux/Documentation/filesystems/aufs/design/03lookup.txt
eca34b5c 1673--- /usr/share/empty/Documentation/filesystems/aufs/design/03lookup.txt 1970-01-01 01:00:00.000000000 +0100
016522bc 1674+++ linux/Documentation/filesystems/aufs/design/03lookup.txt 2020-01-27 10:57:18.165538015 +0100
7e9cd9fe 1675@@ -0,0 +1,113 @@
53392da6 1676+
016522bc 1677+# Copyright (C) 2005-2020 Junjiro R. Okajima
53392da6
AM
1678+#
1679+# This program is free software; you can redistribute it and/or modify
1680+# it under the terms of the GNU General Public License as published by
1681+# the Free Software Foundation; either version 2 of the License, or
1682+# (at your option) any later version.
1683+#
1684+# This program is distributed in the hope that it will be useful,
1685+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1686+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1687+# GNU General Public License for more details.
1688+#
1689+# You should have received a copy of the GNU General Public License
523b37e3 1690+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1691+
1692+Lookup in a Branch
1693+----------------------------------------------------------------------
1694+Since aufs has a character of sub-VFS (see Introduction), it operates
7e9cd9fe
AM
1695+lookup for branches as VFS does. It may be a heavy work. But almost all
1696+lookup operation in aufs is the simplest case, ie. lookup only an entry
1697+directly connected to its parent. Digging down the directory hierarchy
1698+is unnecessary. VFS has a function lookup_one_len() for that use, and
1699+aufs calls it.
1700+
1701+When a branch is a remote filesystem, aufs basically relies upon its
53392da6
AM
1702+->d_revalidate(), also aufs forces the hardest revalidate tests for
1703+them.
1704+For d_revalidate, aufs implements three levels of revalidate tests. See
1705+"Revalidate Dentry and UDBA" in detail.
1706+
1707+
076b876e
AM
1708+Test Only the Highest One for the Directory Permission (dirperm1 option)
1709+----------------------------------------------------------------------
1710+Let's try case study.
1711+- aufs has two branches, upper readwrite and lower readonly.
1712+ /au = /rw + /ro
1713+- "dirA" exists under /ro, but /rw. and its mode is 0700.
1714+- user invoked "chmod a+rx /au/dirA"
1715+- the internal copy-up is activated and "/rw/dirA" is created and its
7e9cd9fe 1716+ permission bits are set to world readable.
076b876e
AM
1717+- then "/au/dirA" becomes world readable?
1718+
1719+In this case, /ro/dirA is still 0700 since it exists in readonly branch,
1720+or it may be a natively readonly filesystem. If aufs respects the lower
1721+branch, it should not respond readdir request from other users. But user
1722+allowed it by chmod. Should really aufs rejects showing the entries
1723+under /ro/dirA?
1724+
7e9cd9fe
AM
1725+To be honest, I don't have a good solution for this case. So aufs
1726+implements 'dirperm1' and 'nodirperm1' mount options, and leave it to
1727+users.
076b876e
AM
1728+When dirperm1 is specified, aufs checks only the highest one for the
1729+directory permission, and shows the entries. Otherwise, as usual, checks
1730+every dir existing on all branches and rejects the request.
1731+
1732+As a side effect, dirperm1 option improves the performance of aufs
1733+because the number of permission check is reduced when the number of
1734+branch is many.
1735+
1736+
53392da6
AM
1737+Revalidate Dentry and UDBA (User's Direct Branch Access)
1738+----------------------------------------------------------------------
1739+Generally VFS helpers re-validate a dentry as a part of lookup.
1740+0. digging down the directory hierarchy.
1741+1. lock the parent dir by its i_mutex.
1742+2. lookup the final (child) entry.
1743+3. revalidate it.
1744+4. call the actual operation (create, unlink, etc.)
1745+5. unlock the parent dir
1746+
1747+If the filesystem implements its ->d_revalidate() (step 3), then it is
1748+called. Actually aufs implements it and checks the dentry on a branch is
1749+still valid.
1750+But it is not enough. Because aufs has to release the lock for the
1751+parent dir on a branch at the end of ->lookup() (step 2) and
1752+->d_revalidate() (step 3) while the i_mutex of the aufs dir is still
1753+held by VFS.
1754+If the file on a branch is changed directly, eg. bypassing aufs, after
1755+aufs released the lock, then the subsequent operation may cause
1756+something unpleasant result.
1757+
1758+This situation is a result of VFS architecture, ->lookup() and
1759+->d_revalidate() is separated. But I never say it is wrong. It is a good
1760+design from VFS's point of view. It is just not suitable for sub-VFS
1761+character in aufs.
1762+
1763+Aufs supports such case by three level of revalidation which is
1764+selectable by user.
1765+1. Simple Revalidate
1766+ Addition to the native flow in VFS's, confirm the child-parent
1767+ relationship on the branch just after locking the parent dir on the
1768+ branch in the "actual operation" (step 4). When this validation
1769+ fails, aufs returns EBUSY. ->d_revalidate() (step 3) in aufs still
1770+ checks the validation of the dentry on branches.
1771+2. Monitor Changes Internally by Inotify/Fsnotify
1772+ Addition to above, in the "actual operation" (step 4) aufs re-lookup
1773+ the dentry on the branch, and returns EBUSY if it finds different
1774+ dentry.
1775+ Additionally, aufs sets the inotify/fsnotify watch for every dir on branches
1776+ during it is in cache. When the event is notified, aufs registers a
1777+ function to kernel 'events' thread by schedule_work(). And the
1778+ function sets some special status to the cached aufs dentry and inode
1779+ private data. If they are not cached, then aufs has nothing to
1780+ do. When the same file is accessed through aufs (step 0-3) later,
1781+ aufs will detect the status and refresh all necessary data.
1782+ In this mode, aufs has to ignore the event which is fired by aufs
1783+ itself.
1784+3. No Extra Validation
1785+ This is the simplest test and doesn't add any additional revalidation
7e9cd9fe 1786+ test, and skip the revalidation in step 4. It is useful and improves
53392da6
AM
1787+ aufs performance when system surely hide the aufs branches from user,
1788+ by over-mounting something (or another method).
1789diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt linux/Documentation/filesystems/aufs/design/04branch.txt
eca34b5c 1790--- /usr/share/empty/Documentation/filesystems/aufs/design/04branch.txt 1970-01-01 01:00:00.000000000 +0100
016522bc 1791+++ linux/Documentation/filesystems/aufs/design/04branch.txt 2020-01-27 10:57:18.165538015 +0100
7e9cd9fe 1792@@ -0,0 +1,74 @@
53392da6 1793+
016522bc 1794+# Copyright (C) 2005-2020 Junjiro R. Okajima
53392da6
AM
1795+#
1796+# This program is free software; you can redistribute it and/or modify
1797+# it under the terms of the GNU General Public License as published by
1798+# the Free Software Foundation; either version 2 of the License, or
1799+# (at your option) any later version.
1800+#
1801+# This program is distributed in the hope that it will be useful,
1802+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1803+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1804+# GNU General Public License for more details.
1805+#
1806+# You should have received a copy of the GNU General Public License
523b37e3 1807+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1808+
1809+Branch Manipulation
1810+
1811+Since aufs supports dynamic branch manipulation, ie. add/remove a branch
1812+and changing its permission/attribute, there are a lot of works to do.
1813+
1814+
1815+Add a Branch
1816+----------------------------------------------------------------------
1817+o Confirm the adding dir exists outside of aufs, including loopback
7e9cd9fe 1818+ mount, and its various attributes.
53392da6
AM
1819+o Initialize the xino file and whiteout bases if necessary.
1820+ See struct.txt.
1821+
1822+o Check the owner/group/mode of the directory
1823+ When the owner/group/mode of the adding directory differs from the
1824+ existing branch, aufs issues a warning because it may impose a
1825+ security risk.
1826+ For example, when a upper writable branch has a world writable empty
1827+ top directory, a malicious user can create any files on the writable
1828+ branch directly, like copy-up and modify manually. If something like
1829+ /etc/{passwd,shadow} exists on the lower readonly branch but the upper
1830+ writable branch, and the writable branch is world-writable, then a
1831+ malicious guy may create /etc/passwd on the writable branch directly
1832+ and the infected file will be valid in aufs.
7e9cd9fe 1833+ I am afraid it can be a security issue, but aufs can do nothing except
53392da6
AM
1834+ producing a warning.
1835+
1836+
1837+Delete a Branch
1838+----------------------------------------------------------------------
1839+o Confirm the deleting branch is not busy
1840+ To be general, there is one merit to adopt "remount" interface to
1841+ manipulate branches. It is to discard caches. At deleting a branch,
1842+ aufs checks the still cached (and connected) dentries and inodes. If
1843+ there are any, then they are all in-use. An inode without its
1844+ corresponding dentry can be alive alone (for example, inotify/fsnotify case).
1845+
1846+ For the cached one, aufs checks whether the same named entry exists on
1847+ other branches.
1848+ If the cached one is a directory, because aufs provides a merged view
1849+ to users, as long as one dir is left on any branch aufs can show the
1850+ dir to users. In this case, the branch can be removed from aufs.
1851+ Otherwise aufs rejects deleting the branch.
1852+
1853+ If any file on the deleting branch is opened by aufs, then aufs
1854+ rejects deleting.
1855+
1856+
1857+Modify the Permission of a Branch
1858+----------------------------------------------------------------------
1859+o Re-initialize or remove the xino file and whiteout bases if necessary.
1860+ See struct.txt.
1861+
1862+o rw --> ro: Confirm the modifying branch is not busy
1863+ Aufs rejects the request if any of these conditions are true.
1864+ - a file on the branch is mmap-ed.
1865+ - a regular file on the branch is opened for write and there is no
1866+ same named entry on the upper branch.
1867diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt linux/Documentation/filesystems/aufs/design/05wbr_policy.txt
eca34b5c 1868--- /usr/share/empty/Documentation/filesystems/aufs/design/05wbr_policy.txt 1970-01-01 01:00:00.000000000 +0100
016522bc 1869+++ linux/Documentation/filesystems/aufs/design/05wbr_policy.txt 2020-01-27 10:57:18.165538015 +0100
523b37e3 1870@@ -0,0 +1,64 @@
53392da6 1871+
016522bc 1872+# Copyright (C) 2005-2020 Junjiro R. Okajima
53392da6
AM
1873+#
1874+# This program is free software; you can redistribute it and/or modify
1875+# it under the terms of the GNU General Public License as published by
1876+# the Free Software Foundation; either version 2 of the License, or
1877+# (at your option) any later version.
1878+#
1879+# This program is distributed in the hope that it will be useful,
1880+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1881+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1882+# GNU General Public License for more details.
1883+#
1884+# You should have received a copy of the GNU General Public License
523b37e3 1885+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
1886+
1887+Policies to Select One among Multiple Writable Branches
1888+----------------------------------------------------------------------
1889+When the number of writable branch is more than one, aufs has to decide
1890+the target branch for file creation or copy-up. By default, the highest
1891+writable branch which has the parent (or ancestor) dir of the target
1892+file is chosen (top-down-parent policy).
1893+By user's request, aufs implements some other policies to select the
7e9cd9fe
AM
1894+writable branch, for file creation several policies, round-robin,
1895+most-free-space, and other policies. For copy-up, top-down-parent,
1896+bottom-up-parent, bottom-up and others.
53392da6
AM
1897+
1898+As expected, the round-robin policy selects the branch in circular. When
1899+you have two writable branches and creates 10 new files, 5 files will be
1900+created for each branch. mkdir(2) systemcall is an exception. When you
1901+create 10 new directories, all will be created on the same branch.
1902+And the most-free-space policy selects the one which has most free
1903+space among the writable branches. The amount of free space will be
1904+checked by aufs internally, and users can specify its time interval.
1905+
1906+The policies for copy-up is more simple,
1907+top-down-parent is equivalent to the same named on in create policy,
1908+bottom-up-parent selects the writable branch where the parent dir
1909+exists and the nearest upper one from the copyup-source,
1910+bottom-up selects the nearest upper writable branch from the
1911+copyup-source, regardless the existence of the parent dir.
1912+
1913+There are some rules or exceptions to apply these policies.
1914+- If there is a readonly branch above the policy-selected branch and
1915+ the parent dir is marked as opaque (a variation of whiteout), or the
1916+ target (creating) file is whiteout-ed on the upper readonly branch,
1917+ then the result of the policy is ignored and the target file will be
1918+ created on the nearest upper writable branch than the readonly branch.
1919+- If there is a writable branch above the policy-selected branch and
1920+ the parent dir is marked as opaque or the target file is whiteouted
1921+ on the branch, then the result of the policy is ignored and the target
1922+ file will be created on the highest one among the upper writable
1923+ branches who has diropq or whiteout. In case of whiteout, aufs removes
1924+ it as usual.
1925+- link(2) and rename(2) systemcalls are exceptions in every policy.
1926+ They try selecting the branch where the source exists as possible
1927+ since copyup a large file will take long time. If it can't be,
1928+ ie. the branch where the source exists is readonly, then they will
1929+ follow the copyup policy.
1930+- There is an exception for rename(2) when the target exists.
1931+ If the rename target exists, aufs compares the index of the branches
1932+ where the source and the target exists and selects the higher
1933+ one. If the selected branch is readonly, then aufs follows the
1934+ copyup policy.
8b6a4947 1935diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.dot linux/Documentation/filesystems/aufs/design/06dirren.dot
eca34b5c
AM
1936--- /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.dot 1970-01-01 01:00:00.000000000 +0100
1937+++ linux/Documentation/filesystems/aufs/design/06dirren.dot 2019-07-11 15:42:14.458904362 +0200
8b6a4947
AM
1938@@ -0,0 +1,31 @@
1939+
1940+// to view this graph, run dot(1) command in GRAPHVIZ.
1941+
1942+digraph G {
1943+node [shape=box];
1944+whinfo [label="detailed info file\n(lower_brid_root-hinum, h_inum, namelen, old name)"];
1945+
1946+node [shape=oval];
1947+
1948+aufs_rename -> whinfo [label="store/remove"];
1949+
1950+node [shape=oval];
1951+inode_list [label="h_inum list in branch\ncache"];
1952+
1953+node [shape=box];
1954+whinode [label="h_inum list file"];
1955+
1956+node [shape=oval];
1957+brmgmt [label="br_add/del/mod/umount"];
1958+
1959+brmgmt -> inode_list [label="create/remove"];
1960+brmgmt -> whinode [label="load/store"];
1961+
1962+inode_list -> whinode [style=dashed,dir=both];
1963+
1964+aufs_rename -> inode_list [label="add/del"];
1965+
1966+aufs_lookup -> inode_list [label="search"];
1967+
1968+aufs_lookup -> whinfo [label="load/remove"];
1969+}
1970diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.txt linux/Documentation/filesystems/aufs/design/06dirren.txt
eca34b5c 1971--- /usr/share/empty/Documentation/filesystems/aufs/design/06dirren.txt 1970-01-01 01:00:00.000000000 +0100
016522bc 1972+++ linux/Documentation/filesystems/aufs/design/06dirren.txt 2020-01-27 10:57:18.165538015 +0100
8b6a4947
AM
1973@@ -0,0 +1,102 @@
1974+
016522bc 1975+# Copyright (C) 2017-2020 Junjiro R. Okajima
8b6a4947
AM
1976+#
1977+# This program is free software; you can redistribute it and/or modify
1978+# it under the terms of the GNU General Public License as published by
1979+# the Free Software Foundation; either version 2 of the License, or
1980+# (at your option) any later version.
1981+#
1982+# This program is distributed in the hope that it will be useful,
1983+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1984+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1985+# GNU General Public License for more details.
1986+#
1987+# You should have received a copy of the GNU General Public License
1988+# along with this program. If not, see <http://www.gnu.org/licenses/>.
1989+
1990+Special handling for renaming a directory (DIRREN)
1991+----------------------------------------------------------------------
1992+First, let's assume we have a simple usecase.
1993+
1994+- /u = /rw + /ro
1995+- /rw/dirA exists
1996+- /ro/dirA and /ro/dirA/file exist too
1997+- there is no dirB on both branches
1998+- a user issues rename("dirA", "dirB")
1999+
2000+Now, what should aufs behave against this rename(2)?
2001+There are a few possible cases.
2002+
2003+A. returns EROFS.
2004+ since dirA exists on a readonly branch which cannot be renamed.
2005+B. returns EXDEV.
2006+ it is possible to copy-up dirA (only the dir itself), but the child
2007+ entries ("file" in this case) should not be. it must be a bad
2008+ approach to copy-up recursively.
2009+C. returns a success.
2010+ even the branch /ro is readonly, aufs tries renaming it. Obviously it
2011+ is a violation of aufs' policy.
2012+D. construct an extra information which indicates that /ro/dirA should
2013+ be handled as the name of dirB.
2014+ overlayfs has a similar feature called REDIRECT.
2015+
2016+Until now, aufs implements the case B only which returns EXDEV, and
2017+expects the userspace application behaves like mv(1) which tries
2018+issueing rename(2) recursively.
2019+
2020+A new aufs feature called DIRREN is introduced which implements the case
2021+D. There are several "extra information" added.
2022+
2023+1. detailed info per renamed directory
2024+ path: /rw/dirB/$AUFS_WH_DR_INFO_PFX.<lower branch-id>
2025+2. the inode-number list of directories on a branch
2026+ path: /rw/dirB/$AUFS_WH_DR_BRHINO
2027+
2028+The filename of "detailed info per directory" represents the lower
2029+branch, and its format is
2030+- a type of the branch id
2031+ one of these.
2032+ + uuid (not implemented yet)
2033+ + fsid
2034+ + dev
2035+- the inode-number of the branch root dir
2036+
2037+And it contains these info in a single regular file.
2038+- magic number
2039+- branch's inode-number of the logically renamed dir
2040+- the name of the before-renamed dir
2041+
2042+The "detailed info per directory" file is created in aufs rename(2), and
2043+loaded in any lookup.
2044+The info is considered in lookup for the matching case only. Here
2045+"matching" means that the root of branch (in the info filename) is same
2046+to the current looking-up branch. After looking-up the before-renamed
2047+name, the inode-number is compared. And the matched dentry is used.
2048+
2049+The "inode-number list of directories" is a regular file which contains
2050+simply the inode-numbers on the branch. The file is created or updated
2051+in removing the branch, and loaded in adding the branch. Its lifetime is
2052+equal to the branch.
2053+The list is refered in lookup, and when the current target inode is
2054+found in the list, the aufs tries loading the "detailed info per
2055+directory" and get the changed and valid name of the dir.
2056+
2057+Theoretically these "extra informaiton" may be able to be put into XATTR
2058+in the dir inode. But aufs doesn't choose this way because
2059+1. XATTR may not be supported by the branch (or its configuration)
2060+2. XATTR may have its size limit.
2061+3. XATTR may be less easy to convert than a regular file, when the
2062+ format of the info is changed in the future.
2063+At the same time, I agree that the regular file approach is much slower
2064+than XATTR approach. So, in the future, aufs may take the XATTR or other
2065+better approach.
2066+
2067+This DIRREN feature is enabled by aufs configuration, and is activated
2068+by a new mount option.
2069+
2070+For the more complicated case, there is a work with UDBA option, which
2071+is to dected the direct access to the branches (by-passing aufs) and to
2072+maintain the cashes in aufs. Since a single cached aufs dentry may
2073+contains two names, before- and after-rename, the name comparision in
2074+UDBA handler may not work correctly. In this case, the behaviour will be
2075+equivalen to udba=reval case.
076b876e 2076diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06fhsm.txt linux/Documentation/filesystems/aufs/design/06fhsm.txt
eca34b5c 2077--- /usr/share/empty/Documentation/filesystems/aufs/design/06fhsm.txt 1970-01-01 01:00:00.000000000 +0100
016522bc 2078+++ linux/Documentation/filesystems/aufs/design/06fhsm.txt 2020-01-27 10:57:18.165538015 +0100
076b876e
AM
2079@@ -0,0 +1,120 @@
2080+
016522bc 2081+# Copyright (C) 2011-2020 Junjiro R. Okajima
076b876e
AM
2082+#
2083+# This program is free software; you can redistribute it and/or modify
2084+# it under the terms of the GNU General Public License as published by
2085+# the Free Software Foundation; either version 2 of the License, or
2086+# (at your option) any later version.
2087+#
2088+# This program is distributed in the hope that it will be useful,
2089+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2090+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2091+# GNU General Public License for more details.
2092+#
2093+# You should have received a copy of the GNU General Public License
2094+# along with this program; if not, write to the Free Software
2095+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2096+
2097+
2098+File-based Hierarchical Storage Management (FHSM)
2099+----------------------------------------------------------------------
2100+Hierarchical Storage Management (or HSM) is a well-known feature in the
2101+storage world. Aufs provides this feature as file-based with multiple
7e9cd9fe 2102+writable branches, based upon the principle of "Colder, the Lower".
076b876e 2103+Here the word "colder" means that the less used files, and "lower" means
7e9cd9fe 2104+that the position in the order of the stacked branches vertically.
076b876e
AM
2105+These multiple writable branches are prioritized, ie. the topmost one
2106+should be the fastest drive and be used heavily.
2107+
2108+o Characters in aufs FHSM story
2109+- aufs itself and a new branch attribute.
2110+- a new ioctl interface to move-down and to establish a connection with
2111+ the daemon ("move-down" is a converse of "copy-up").
2112+- userspace tool and daemon.
2113+
2114+The userspace daemon establishes a connection with aufs and waits for
2115+the notification. The notified information is very similar to struct
2116+statfs containing the number of consumed blocks and inodes.
2117+When the consumed blocks/inodes of a branch exceeds the user-specified
2118+upper watermark, the daemon activates its move-down process until the
2119+consumed blocks/inodes reaches the user-specified lower watermark.
2120+
2121+The actual move-down is done by aufs based upon the request from
2122+user-space since we need to maintain the inode number and the internal
2123+pointer arrays in aufs.
2124+
2125+Currently aufs FHSM handles the regular files only. Additionally they
2126+must not be hard-linked nor pseudo-linked.
2127+
2128+
2129+o Cowork of aufs and the user-space daemon
2130+ During the userspace daemon established the connection, aufs sends a
2131+ small notification to it whenever aufs writes something into the
2132+ writable branch. But it may cost high since aufs issues statfs(2)
2133+ internally. So user can specify a new option to cache the
2134+ info. Actually the notification is controlled by these factors.
2135+ + the specified cache time.
2136+ + classified as "force" by aufs internally.
2137+ Until the specified time expires, aufs doesn't send the info
2138+ except the forced cases. When aufs decide forcing, the info is always
2139+ notified to userspace.
2140+ For example, the number of free inodes is generally large enough and
2141+ the shortage of it happens rarely. So aufs doesn't force the
2142+ notification when creating a new file, directory and others. This is
2143+ the typical case which aufs doesn't force.
2144+ When aufs writes the actual filedata and the files consumes any of new
2145+ blocks, the aufs forces notifying.
2146+
2147+
2148+o Interfaces in aufs
2149+- New branch attribute.
2150+ + fhsm
2151+ Specifies that the branch is managed by FHSM feature. In other word,
2152+ participant in the FHSM.
2153+ When nofhsm is set to the branch, it will not be the source/target
2154+ branch of the move-down operation. This attribute is set
2155+ independently from coo and moo attributes, and if you want full
2156+ FHSM, you should specify them as well.
2157+- New mount option.
2158+ + fhsm_sec
2159+ Specifies a second to suppress many less important info to be
2160+ notified.
2161+- New ioctl.
2162+ + AUFS_CTL_FHSM_FD
2163+ create a new file descriptor which userspace can read the notification
2164+ (a subset of struct statfs) from aufs.
2165+- Module parameter 'brs'
2166+ It has to be set to 1. Otherwise the new mount option 'fhsm' will not
2167+ be set.
2168+- mount helpers /sbin/mount.aufs and /sbin/umount.aufs
2169+ When there are two or more branches with fhsm attributes,
2170+ /sbin/mount.aufs invokes the user-space daemon and /sbin/umount.aufs
2171+ terminates it. As a result of remounting and branch-manipulation, the
2172+ number of branches with fhsm attribute can be one. In this case,
2173+ /sbin/mount.aufs will terminate the user-space daemon.
2174+
2175+
2176+Finally the operation is done as these steps in kernel-space.
2177+- make sure that,
2178+ + no one else is using the file.
2179+ + the file is not hard-linked.
2180+ + the file is not pseudo-linked.
2181+ + the file is a regular file.
2182+ + the parent dir is not opaqued.
2183+- find the target writable branch.
2184+- make sure the file is not whiteout-ed by the upper (than the target)
2185+ branch.
2186+- make the parent dir on the target branch.
2187+- mutex lock the inode on the branch.
2188+- unlink the whiteout on the target branch (if exists).
2189+- lookup and create the whiteout-ed temporary name on the target branch.
2190+- copy the file as the whiteout-ed temporary name on the target branch.
2191+- rename the whiteout-ed temporary name to the original name.
2192+- unlink the file on the source branch.
2193+- maintain the internal pointer array and the external inode number
2194+ table (XINO).
2195+- maintain the timestamps and other attributes of the parent dir and the
2196+ file.
2197+
2198+And of course, in every step, an error may happen. So the operation
2199+should restore the original file state after an error happens.
53392da6 2200diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt linux/Documentation/filesystems/aufs/design/06mmap.txt
eca34b5c 2201--- /usr/share/empty/Documentation/filesystems/aufs/design/06mmap.txt 1970-01-01 01:00:00.000000000 +0100
016522bc 2202+++ linux/Documentation/filesystems/aufs/design/06mmap.txt 2020-01-27 10:57:18.165538015 +0100
b912730e 2203@@ -0,0 +1,72 @@
53392da6 2204+
016522bc 2205+# Copyright (C) 2005-2020 Junjiro R. Okajima
53392da6
AM
2206+#
2207+# This program is free software; you can redistribute it and/or modify
2208+# it under the terms of the GNU General Public License as published by
2209+# the Free Software Foundation; either version 2 of the License, or
2210+# (at your option) any later version.
2211+#
2212+# This program is distributed in the hope that it will be useful,
2213+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2214+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2215+# GNU General Public License for more details.
2216+#
2217+# You should have received a copy of the GNU General Public License
523b37e3 2218+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
2219+
2220+mmap(2) -- File Memory Mapping
2221+----------------------------------------------------------------------
2222+In aufs, the file-mapped pages are handled by a branch fs directly, no
2223+interaction with aufs. It means aufs_mmap() calls the branch fs's
2224+->mmap().
2225+This approach is simple and good, but there is one problem.
7e9cd9fe 2226+Under /proc, several entries show the mmapped files by its path (with
53392da6
AM
2227+device and inode number), and the printed path will be the path on the
2228+branch fs's instead of virtual aufs's.
2229+This is not a problem in most cases, but some utilities lsof(1) (and its
2230+user) may expect the path on aufs.
2231+
2232+To address this issue, aufs adds a new member called vm_prfile in struct
2233+vm_area_struct (and struct vm_region). The original vm_file points to
2234+the file on the branch fs in order to handle everything correctly as
2235+usual. The new vm_prfile points to a virtual file in aufs, and the
2236+show-functions in procfs refers to vm_prfile if it is set.
2237+Also we need to maintain several other places where touching vm_file
2238+such like
2239+- fork()/clone() copies vma and the reference count of vm_file is
2240+ incremented.
2241+- merging vma maintains the ref count too.
2242+
7e9cd9fe 2243+This is not a good approach. It just fakes the printed path. But it
53392da6
AM
2244+leaves all behaviour around f_mapping unchanged. This is surely an
2245+advantage.
2246+Actually aufs had adopted another complicated approach which calls
2247+generic_file_mmap() and handles struct vm_operations_struct. In this
2248+approach, aufs met a hard problem and I could not solve it without
2249+switching the approach.
b912730e
AM
2250+
2251+There may be one more another approach which is
2252+- bind-mount the branch-root onto the aufs-root internally
2253+- grab the new vfsmount (ie. struct mount)
2254+- lazy-umount the branch-root internally
2255+- in open(2) the aufs-file, open the branch-file with the hidden
2256+ vfsmount (instead of the original branch's vfsmount)
2257+- ideally this "bind-mount and lazy-umount" should be done atomically,
2258+ but it may be possible from userspace by the mount helper.
2259+
2260+Adding the internal hidden vfsmount and using it in opening a file, the
2261+file path under /proc will be printed correctly. This approach looks
2262+smarter, but is not possible I am afraid.
2263+- aufs-root may be bind-mount later. when it happens, another hidden
2264+ vfsmount will be required.
2265+- it is hard to get the chance to bind-mount and lazy-umount
2266+ + in kernel-space, FS can have vfsmount in open(2) via
2267+ file->f_path, and aufs can know its vfsmount. But several locks are
2268+ already acquired, and if aufs tries to bind-mount and lazy-umount
2269+ here, then it may cause a deadlock.
2270+ + in user-space, bind-mount doesn't invoke the mount helper.
2271+- since /proc shows dev and ino, aufs has to give vma these info. it
2272+ means a new member vm_prinode will be necessary. this is essentially
2273+ equivalent to vm_prfile described above.
2274+
2275+I have to give up this "looks-smater" approach.
c1595e42 2276diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/06xattr.txt linux/Documentation/filesystems/aufs/design/06xattr.txt
eca34b5c 2277--- /usr/share/empty/Documentation/filesystems/aufs/design/06xattr.txt 1970-01-01 01:00:00.000000000 +0100
016522bc 2278+++ linux/Documentation/filesystems/aufs/design/06xattr.txt 2020-01-27 10:57:18.165538015 +0100
c1595e42
JR
2279@@ -0,0 +1,96 @@
2280+
016522bc 2281+# Copyright (C) 2014-2020 Junjiro R. Okajima
c1595e42
JR
2282+#
2283+# This program is free software; you can redistribute it and/or modify
2284+# it under the terms of the GNU General Public License as published by
2285+# the Free Software Foundation; either version 2 of the License, or
2286+# (at your option) any later version.
2287+#
2288+# This program is distributed in the hope that it will be useful,
2289+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2290+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2291+# GNU General Public License for more details.
2292+#
2293+# You should have received a copy of the GNU General Public License
2294+# along with this program; if not, write to the Free Software
2295+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2296+
2297+
2298+Listing XATTR/EA and getting the value
2299+----------------------------------------------------------------------
2300+For the inode standard attributes (owner, group, timestamps, etc.), aufs
2301+shows the values from the topmost existing file. This behaviour is good
7e9cd9fe 2302+for the non-dir entries since the bahaviour exactly matches the shown
c1595e42
JR
2303+information. But for the directories, aufs considers all the same named
2304+entries on the lower branches. Which means, if one of the lower entry
2305+rejects readdir call, then aufs returns an error even if the topmost
2306+entry allows it. This behaviour is necessary to respect the branch fs's
2307+security, but can make users confused since the user-visible standard
2308+attributes don't match the behaviour.
2309+To address this issue, aufs has a mount option called dirperm1 which
2310+checks the permission for the topmost entry only, and ignores the lower
2311+entry's permission.
2312+
2313+A similar issue can happen around XATTR.
2314+getxattr(2) and listxattr(2) families behave as if dirperm1 option is
7e9cd9fe
AM
2315+always set. Otherwise these very unpleasant situation would happen.
2316+- listxattr(2) may return the duplicated entries.
c1595e42
JR
2317+- users may not be able to remove or reset the XATTR forever,
2318+
2319+
2320+XATTR/EA support in the internal (copy,move)-(up,down)
2321+----------------------------------------------------------------------
7e9cd9fe 2322+Generally the extended attributes of inode are categorized as these.
c1595e42
JR
2323+- "security" for LSM and capability.
2324+- "system" for posix ACL, 'acl' mount option is required for the branch
2325+ fs generally.
2326+- "trusted" for userspace, CAP_SYS_ADMIN is required.
2327+- "user" for userspace, 'user_xattr' mount option is required for the
2328+ branch fs generally.
2329+
2330+Moreover there are some other categories. Aufs handles these rather
2331+unpopular categories as the ordinary ones, ie. there is no special
2332+condition nor exception.
2333+
2334+In copy-up, the support for XATTR on the dst branch may differ from the
2335+src branch. In this case, the copy-up operation will get an error and
7e9cd9fe
AM
2336+the original user operation which triggered the copy-up will fail. It
2337+can happen that even all copy-up will fail.
c1595e42
JR
2338+When both of src and dst branches support XATTR and if an error occurs
2339+during copying XATTR, then the copy-up should fail obviously. That is a
2340+good reason and aufs should return an error to userspace. But when only
7e9cd9fe 2341+the src branch support that XATTR, aufs should not return an error.
c1595e42
JR
2342+For example, the src branch supports ACL but the dst branch doesn't
2343+because the dst branch may natively un-support it or temporary
2344+un-support it due to "noacl" mount option. Of course, the dst branch fs
2345+may NOT return an error even if the XATTR is not supported. It is
2346+totally up to the branch fs.
2347+
2348+Anyway when the aufs internal copy-up gets an error from the dst branch
2349+fs, then aufs tries removing the just copied entry and returns the error
2350+to the userspace. The worst case of this situation will be all copy-up
2351+will fail.
2352+
2353+For the copy-up operation, there two basic approaches.
2354+- copy the specified XATTR only (by category above), and return the
7e9cd9fe 2355+ error unconditionally if it happens.
c1595e42
JR
2356+- copy all XATTR, and ignore the error on the specified category only.
2357+
2358+In order to support XATTR and to implement the correct behaviour, aufs
7e9cd9fe
AM
2359+chooses the latter approach and introduces some new branch attributes,
2360+"icexsec", "icexsys", "icextr", "icexusr", and "icexoth".
c1595e42 2361+They correspond to the XATTR namespaces (see above). Additionally, to be
7e9cd9fe
AM
2362+convenient, "icex" is also provided which means all "icex*" attributes
2363+are set (here the word "icex" stands for "ignore copy-error on XATTR").
c1595e42
JR
2364+
2365+The meaning of these attributes is to ignore the error from setting
2366+XATTR on that branch.
2367+Note that aufs tries copying all XATTR unconditionally, and ignores the
2368+error from the dst branch according to the specified attributes.
2369+
2370+Some XATTR may have its default value. The default value may come from
2371+the parent dir or the environment. If the default value is set at the
2372+file creating-time, it will be overwritten by copy-up.
2373+Some contradiction may happen I am afraid.
2374+Do we need another attribute to stop copying XATTR? I am unsure. For
2375+now, aufs implements the branch attributes to ignore the error.
53392da6 2376diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt linux/Documentation/filesystems/aufs/design/07export.txt
eca34b5c 2377--- /usr/share/empty/Documentation/filesystems/aufs/design/07export.txt 1970-01-01 01:00:00.000000000 +0100
016522bc 2378+++ linux/Documentation/filesystems/aufs/design/07export.txt 2020-01-27 10:57:18.165538015 +0100
523b37e3 2379@@ -0,0 +1,58 @@
53392da6 2380+
016522bc 2381+# Copyright (C) 2005-2020 Junjiro R. Okajima
53392da6
AM
2382+#
2383+# This program is free software; you can redistribute it and/or modify
2384+# it under the terms of the GNU General Public License as published by
2385+# the Free Software Foundation; either version 2 of the License, or
2386+# (at your option) any later version.
2387+#
2388+# This program is distributed in the hope that it will be useful,
2389+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2390+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2391+# GNU General Public License for more details.
2392+#
2393+# You should have received a copy of the GNU General Public License
523b37e3 2394+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
2395+
2396+Export Aufs via NFS
2397+----------------------------------------------------------------------
2398+Here is an approach.
2399+- like xino/xib, add a new file 'xigen' which stores aufs inode
2400+ generation.
2401+- iget_locked(): initialize aufs inode generation for a new inode, and
2402+ store it in xigen file.
2403+- destroy_inode(): increment aufs inode generation and store it in xigen
2404+ file. it is necessary even if it is not unlinked, because any data of
2405+ inode may be changed by UDBA.
2406+- encode_fh(): for a root dir, simply return FILEID_ROOT. otherwise
2407+ build file handle by
2408+ + branch id (4 bytes)
2409+ + superblock generation (4 bytes)
2410+ + inode number (4 or 8 bytes)
2411+ + parent dir inode number (4 or 8 bytes)
2412+ + inode generation (4 bytes))
2413+ + return value of exportfs_encode_fh() for the parent on a branch (4
2414+ bytes)
2415+ + file handle for a branch (by exportfs_encode_fh())
2416+- fh_to_dentry():
2417+ + find the index of a branch from its id in handle, and check it is
2418+ still exist in aufs.
2419+ + 1st level: get the inode number from handle and search it in cache.
7e9cd9fe
AM
2420+ + 2nd level: if not found in cache, get the parent inode number from
2421+ the handle and search it in cache. and then open the found parent
2422+ dir, find the matching inode number by vfs_readdir() and get its
2423+ name, and call lookup_one_len() for the target dentry.
53392da6
AM
2424+ + 3rd level: if the parent dir is not cached, call
2425+ exportfs_decode_fh() for a branch and get the parent on a branch,
2426+ build a pathname of it, convert it a pathname in aufs, call
2427+ path_lookup(). now aufs gets a parent dir dentry, then handle it as
2428+ the 2nd level.
2429+ + to open the dir, aufs needs struct vfsmount. aufs keeps vfsmount
2430+ for every branch, but not itself. to get this, (currently) aufs
2431+ searches in current->nsproxy->mnt_ns list. it may not be a good
2432+ idea, but I didn't get other approach.
2433+ + test the generation of the gotten inode.
2434+- every inode operation: they may get EBUSY due to UDBA. in this case,
2435+ convert it into ESTALE for NFSD.
2436+- readdir(): call lockdep_on/off() because filldir in NFSD calls
2437+ lookup_one_len(), vfs_getattr(), encode_fh() and others.
2438diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt linux/Documentation/filesystems/aufs/design/08shwh.txt
eca34b5c 2439--- /usr/share/empty/Documentation/filesystems/aufs/design/08shwh.txt 1970-01-01 01:00:00.000000000 +0100
016522bc 2440+++ linux/Documentation/filesystems/aufs/design/08shwh.txt 2020-01-27 10:57:18.165538015 +0100
523b37e3 2441@@ -0,0 +1,52 @@
53392da6 2442+
016522bc 2443+# Copyright (C) 2005-2020 Junjiro R. Okajima
53392da6
AM
2444+#
2445+# This program is free software; you can redistribute it and/or modify
2446+# it under the terms of the GNU General Public License as published by
2447+# the Free Software Foundation; either version 2 of the License, or
2448+# (at your option) any later version.
2449+#
2450+# This program is distributed in the hope that it will be useful,
2451+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2452+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2453+# GNU General Public License for more details.
2454+#
2455+# You should have received a copy of the GNU General Public License
523b37e3 2456+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
2457+
2458+Show Whiteout Mode (shwh)
2459+----------------------------------------------------------------------
2460+Generally aufs hides the name of whiteouts. But in some cases, to show
2461+them is very useful for users. For instance, creating a new middle layer
2462+(branch) by merging existing layers.
2463+
2464+(borrowing aufs1 HOW-TO from a user, Michael Towers)
2465+When you have three branches,
2466+- Bottom: 'system', squashfs (underlying base system), read-only
2467+- Middle: 'mods', squashfs, read-only
2468+- Top: 'overlay', ram (tmpfs), read-write
2469+
2470+The top layer is loaded at boot time and saved at shutdown, to preserve
2471+the changes made to the system during the session.
2472+When larger changes have been made, or smaller changes have accumulated,
2473+the size of the saved top layer data grows. At this point, it would be
2474+nice to be able to merge the two overlay branches ('mods' and 'overlay')
2475+and rewrite the 'mods' squashfs, clearing the top layer and thus
2476+restoring save and load speed.
2477+
2478+This merging is simplified by the use of another aufs mount, of just the
2479+two overlay branches using the 'shwh' option.
2480+# mount -t aufs -o ro,shwh,br:/livesys/overlay=ro+wh:/livesys/mods=rr+wh \
2481+ aufs /livesys/merge_union
2482+
2483+A merged view of these two branches is then available at
2484+/livesys/merge_union, and the new feature is that the whiteouts are
2485+visible!
2486+Note that in 'shwh' mode the aufs mount must be 'ro', which will disable
2487+writing to all branches. Also the default mode for all branches is 'ro'.
2488+It is now possible to save the combined contents of the two overlay
2489+branches to a new squashfs, e.g.:
2490+# mksquashfs /livesys/merge_union /path/to/newmods.squash
2491+
2492+This new squashfs archive can be stored on the boot device and the
2493+initramfs will use it to replace the old one at the next boot.
2494diff -urN /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt linux/Documentation/filesystems/aufs/design/10dynop.txt
eca34b5c 2495--- /usr/share/empty/Documentation/filesystems/aufs/design/10dynop.txt 1970-01-01 01:00:00.000000000 +0100
016522bc 2496+++ linux/Documentation/filesystems/aufs/design/10dynop.txt 2020-01-27 10:57:18.165538015 +0100
7e9cd9fe 2497@@ -0,0 +1,47 @@
53392da6 2498+
016522bc 2499+# Copyright (C) 2010-2020 Junjiro R. Okajima
53392da6
AM
2500+#
2501+# This program is free software; you can redistribute it and/or modify
2502+# it under the terms of the GNU General Public License as published by
2503+# the Free Software Foundation; either version 2 of the License, or
2504+# (at your option) any later version.
2505+#
2506+# This program is distributed in the hope that it will be useful,
2507+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2508+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2509+# GNU General Public License for more details.
2510+#
2511+# You should have received a copy of the GNU General Public License
523b37e3 2512+# along with this program. If not, see <http://www.gnu.org/licenses/>.
53392da6
AM
2513+
2514+Dynamically customizable FS operations
2515+----------------------------------------------------------------------
2516+Generally FS operations (struct inode_operations, struct
2517+address_space_operations, struct file_operations, etc.) are defined as
2518+"static const", but it never means that FS have only one set of
2519+operation. Some FS have multiple sets of them. For instance, ext2 has
2520+three sets, one for XIP, for NOBH, and for normal.
2521+Since aufs overrides and redirects these operations, sometimes aufs has
7e9cd9fe 2522+to change its behaviour according to the branch FS type. More importantly
53392da6
AM
2523+VFS acts differently if a function (member in the struct) is set or
2524+not. It means aufs should have several sets of operations and select one
2525+among them according to the branch FS definition.
2526+
7e9cd9fe 2527+In order to solve this problem and not to affect the behaviour of VFS,
53392da6 2528+aufs defines these operations dynamically. For instance, aufs defines
7e9cd9fe
AM
2529+dummy direct_IO function for struct address_space_operations, but it may
2530+not be set to the address_space_operations actually. When the branch FS
2531+doesn't have it, aufs doesn't set it to its address_space_operations
2532+while the function definition itself is still alive. So the behaviour
2533+itself will not change, and it will return an error when direct_IO is
2534+not set.
53392da6
AM
2535+
2536+The lifetime of these dynamically generated operation object is
2537+maintained by aufs branch object. When the branch is removed from aufs,
2538+the reference counter of the object is decremented. When it reaches
2539+zero, the dynamically generated operation object will be freed.
2540+
7e9cd9fe
AM
2541+This approach is designed to support AIO (io_submit), Direct I/O and
2542+XIP (DAX) mainly.
2543+Currently this approach is applied to address_space_operations for
2544+regular files only.
53392da6 2545diff -urN /usr/share/empty/Documentation/filesystems/aufs/README linux/Documentation/filesystems/aufs/README
eca34b5c 2546--- /usr/share/empty/Documentation/filesystems/aufs/README 1970-01-01 01:00:00.000000000 +0100
43982f53
AM
2547+++ linux/Documentation/filesystems/aufs/README 2020-01-23 09:59:36.748660743 +0100
2548@@ -0,0 +1,401 @@
53392da6 2549+
fbc438ed 2550+Aufs5 -- advanced multi layered unification filesystem version 5.x
53392da6
AM
2551+http://aufs.sf.net
2552+Junjiro R. Okajima
2553+
2554+
2555+0. Introduction
2556+----------------------------------------
2557+In the early days, aufs was entirely re-designed and re-implemented
7e9cd9fe 2558+Unionfs Version 1.x series. Adding many original ideas, approaches,
fbc438ed 2559+improvements and implementations, it became totally different from
53392da6 2560+Unionfs while keeping the basic features.
fbc438ed 2561+Later, Unionfs Version 2.x series began taking some of the same
53392da6 2562+approaches to aufs1's.
fbc438ed 2563+Unionfs was being developed by Professor Erez Zadok at Stony Brook
53392da6
AM
2564+University and his team.
2565+
fbc438ed
JR
2566+Aufs5 supports linux-v5.0 and later, If you want older kernel version
2567+support,
2568+- for linux-v4.x series, try aufs4-linux.git or aufs4-standalone.git
2569+- for linux-v3.x series, try aufs3-linux.git or aufs3-standalone.git
2570+- for linux-v2.6.16 and later, try aufs2-2.6.git, aufs2-standalone.git
2571+ or aufs1 from CVS on SourceForge.
53392da6
AM
2572+
2573+Note: it becomes clear that "Aufs was rejected. Let's give it up."
38d290e6
JR
2574+ According to Christoph Hellwig, linux rejects all union-type
2575+ filesystems but UnionMount.
53392da6
AM
2576+<http://marc.info/?l=linux-kernel&m=123938533724484&w=2>
2577+
38d290e6
JR
2578+PS. Al Viro seems have a plan to merge aufs as well as overlayfs and
2579+ UnionMount, and he pointed out an issue around a directory mutex
2580+ lock and aufs addressed it. But it is still unsure whether aufs will
2581+ be merged (or any other union solution).
076b876e 2582+<http://marc.info/?l=linux-kernel&m=136312705029295&w=1>
38d290e6 2583+
53392da6
AM
2584+
2585+1. Features
2586+----------------------------------------
2587+- unite several directories into a single virtual filesystem. The member
2588+ directory is called as a branch.
2589+- you can specify the permission flags to the branch, which are 'readonly',
2590+ 'readwrite' and 'whiteout-able.'
2591+- by upper writable branch, internal copyup and whiteout, files/dirs on
2592+ readonly branch are modifiable logically.
2593+- dynamic branch manipulation, add, del.
2594+- etc...
2595+
7e9cd9fe
AM
2596+Also there are many enhancements in aufs, such as:
2597+- test only the highest one for the directory permission (dirperm1)
2598+- copyup on open (coo=)
2599+- 'move' policy for copy-up between two writable branches, after
2600+ checking free space.
2601+- xattr, acl
53392da6
AM
2602+- readdir(3) in userspace.
2603+- keep inode number by external inode number table
2604+- keep the timestamps of file/dir in internal copyup operation
2605+- seekable directory, supporting NFS readdir.
2606+- whiteout is hardlinked in order to reduce the consumption of inodes
2607+ on branch
2608+- do not copyup, nor create a whiteout when it is unnecessary
2609+- revert a single systemcall when an error occurs in aufs
2610+- remount interface instead of ioctl
2611+- maintain /etc/mtab by an external command, /sbin/mount.aufs.
2612+- loopback mounted filesystem as a branch
2613+- kernel thread for removing the dir who has a plenty of whiteouts
2614+- support copyup sparse file (a file which has a 'hole' in it)
2615+- default permission flags for branches
2616+- selectable permission flags for ro branch, whether whiteout can
2617+ exist or not
2618+- export via NFS.
2619+- support <sysfs>/fs/aufs and <debugfs>/aufs.
2620+- support multiple writable branches, some policies to select one
2621+ among multiple writable branches.
2622+- a new semantics for link(2) and rename(2) to support multiple
2623+ writable branches.
2624+- no glibc changes are required.
2625+- pseudo hardlink (hardlink over branches)
2626+- allow a direct access manually to a file on branch, e.g. bypassing aufs.
2627+ including NFS or remote filesystem branch.
2628+- userspace wrapper for pathconf(3)/fpathconf(3) with _PC_LINK_MAX.
2629+- and more...
2630+
fbc438ed 2631+Currently these features are dropped temporary from aufs5.
53392da6 2632+See design/08plan.txt in detail.
53392da6
AM
2633+- nested mount, i.e. aufs as readonly no-whiteout branch of another aufs
2634+ (robr)
2635+- statistics of aufs thread (/sys/fs/aufs/stat)
53392da6
AM
2636+
2637+Features or just an idea in the future (see also design/*.txt),
2638+- reorder the branch index without del/re-add.
2639+- permanent xino files for NFSD
2640+- an option for refreshing the opened files after add/del branches
53392da6
AM
2641+- light version, without branch manipulation. (unnecessary?)
2642+- copyup in userspace
2643+- inotify in userspace
2644+- readv/writev
53392da6
AM
2645+
2646+
2647+2. Download
2648+----------------------------------------
fbc438ed
JR
2649+There are three GIT trees for aufs5, aufs5-linux.git,
2650+aufs5-standalone.git, and aufs-util.git. Note that there is no "5" in
1e00d052 2651+"aufs-util.git."
fbc438ed
JR
2652+While the aufs-util is always necessary, you need either of aufs5-linux
2653+or aufs5-standalone.
1e00d052 2654+
fbc438ed 2655+The aufs5-linux tree includes the whole linux mainline GIT tree,
1e00d052
AM
2656+git://git.kernel.org/.../torvalds/linux.git.
2657+And you cannot select CONFIG_AUFS_FS=m for this version, eg. you cannot
fbc438ed 2658+build aufs5 as an external kernel module.
2000de60 2659+Several extra patches are not included in this tree. Only
fbc438ed 2660+aufs5-standalone tree contains them. They are described in the later
2000de60 2661+section "Configuration and Compilation."
1e00d052 2662+
fbc438ed 2663+On the other hand, the aufs5-standalone tree has only aufs source files
53392da6 2664+and necessary patches, and you can select CONFIG_AUFS_FS=m.
2000de60 2665+But you need to apply all aufs patches manually.
53392da6 2666+
fbc438ed
JR
2667+You will find GIT branches whose name is in form of "aufs5.x" where "x"
2668+represents the linux kernel version, "linux-5.x". For instance,
2669+"aufs5.0" is for linux-5.0. For latest "linux-5.x-rcN", use
2670+"aufs5.x-rcN" branch.
1e00d052 2671+
fbc438ed 2672+o aufs5-linux tree
1e00d052 2673+$ git clone --reference /your/linux/git/tree \
fbc438ed 2674+ git://github.com/sfjro/aufs5-linux.git aufs5-linux.git
1e00d052 2675+- if you don't have linux GIT tree, then remove "--reference ..."
fbc438ed
JR
2676+$ cd aufs5-linux.git
2677+$ git checkout origin/aufs5.0
53392da6 2678+
2000de60
JR
2679+Or You may want to directly git-pull aufs into your linux GIT tree, and
2680+leave the patch-work to GIT.
2681+$ cd /your/linux/git/tree
fbc438ed
JR
2682+$ git remote add aufs5 git://github.com/sfjro/aufs5-linux.git
2683+$ git fetch aufs5
2684+$ git checkout -b my5.0 v5.0
5527c038 2685+$ (add your local change...)
fbc438ed
JR
2686+$ git pull aufs5 aufs5.0
2687+- now you have v5.0 + your_changes + aufs5.0 in you my5.0 branch.
2000de60 2688+- you may need to solve some conflicts between your_changes and
fbc438ed
JR
2689+ aufs5.0. in this case, git-rerere is recommended so that you can
2690+ solve the similar conflicts automatically when you upgrade to 5.1 or
2000de60
JR
2691+ later in the future.
2692+
fbc438ed
JR
2693+o aufs5-standalone tree
2694+$ git clone git://github.com/sfjro/aufs5-standalone.git aufs5-standalone.git
2695+$ cd aufs5-standalone.git
2696+$ git checkout origin/aufs5.0
53392da6
AM
2697+
2698+o aufs-util tree
5527c038
JR
2699+$ git clone git://git.code.sf.net/p/aufs/aufs-util aufs-util.git
2700+- note that the public aufs-util.git is on SourceForge instead of
2701+ GitHUB.
53392da6 2702+$ cd aufs-util.git
fbc438ed 2703+$ git checkout origin/aufs5.0
53392da6 2704+
fbc438ed
JR
2705+Note: The 5.x-rcN branch is to be used with `rc' kernel versions ONLY.
2706+The minor version number, 'x' in '5.x', of aufs may not always
9dbd164d
AM
2707+follow the minor version number of the kernel.
2708+Because changes in the kernel that cause the use of a new
2709+minor version number do not always require changes to aufs-util.
2710+
2711+Since aufs-util has its own minor version number, you may not be
2712+able to find a GIT branch in aufs-util for your kernel's
2713+exact minor version number.
2714+In this case, you should git-checkout the branch for the
53392da6 2715+nearest lower number.
9dbd164d
AM
2716+
2717+For (an unreleased) example:
fbc438ed
JR
2718+If you are using "linux-5.10" and the "aufs5.10" branch
2719+does not exist in aufs-util repository, then "aufs5.9", "aufs5.8"
9dbd164d
AM
2720+or something numerically smaller is the branch for your kernel.
2721+
53392da6
AM
2722+Also you can view all branches by
2723+ $ git branch -a
2724+
2725+
2726+3. Configuration and Compilation
2727+----------------------------------------
2728+Make sure you have git-checkout'ed the correct branch.
2729+
fbc438ed 2730+For aufs5-linux tree,
c06a8ce3 2731+- enable CONFIG_AUFS_FS.
1e00d052
AM
2732+- set other aufs configurations if necessary.
2733+
fbc438ed 2734+For aufs5-standalone tree,
53392da6
AM
2735+There are several ways to build.
2736+
2737+1.
fbc438ed
JR
2738+- apply ./aufs5-kbuild.patch to your kernel source files.
2739+- apply ./aufs5-base.patch too.
2740+- apply ./aufs5-mmap.patch too.
2741+- apply ./aufs5-standalone.patch too, if you have a plan to set
2742+ CONFIG_AUFS_FS=m. otherwise you don't need ./aufs5-standalone.patch.
537831f9
AM
2743+- copy ./{Documentation,fs,include/uapi/linux/aufs_type.h} files to your
2744+ kernel source tree. Never copy $PWD/include/uapi/linux/Kbuild.
c06a8ce3 2745+- enable CONFIG_AUFS_FS, you can select either
53392da6
AM
2746+ =m or =y.
2747+- and build your kernel as usual.
2748+- install the built kernel.
7eafdf33
AM
2749+- install the header files too by "make headers_install" to the
2750+ directory where you specify. By default, it is $PWD/usr.
b4510431 2751+ "make help" shows a brief note for headers_install.
53392da6
AM
2752+- and reboot your system.
2753+
2754+2.
2755+- module only (CONFIG_AUFS_FS=m).
fbc438ed
JR
2756+- apply ./aufs5-base.patch to your kernel source files.
2757+- apply ./aufs5-mmap.patch too.
2758+- apply ./aufs5-standalone.patch too.
53392da6
AM
2759+- build your kernel, don't forget "make headers_install", and reboot.
2760+- edit ./config.mk and set other aufs configurations if necessary.
b4510431 2761+ Note: You should read $PWD/fs/aufs/Kconfig carefully which describes
53392da6
AM
2762+ every aufs configurations.
2763+- build the module by simple "make".
2764+- you can specify ${KDIR} make variable which points to your kernel
2765+ source tree.
2766+- install the files
2767+ + run "make install" to install the aufs module, or copy the built
b4510431
AM
2768+ $PWD/aufs.ko to /lib/modules/... and run depmod -a (or reboot simply).
2769+ + run "make install_headers" (instead of headers_install) to install
2770+ the modified aufs header file (you can specify DESTDIR which is
2771+ available in aufs standalone version's Makefile only), or copy
2772+ $PWD/usr/include/linux/aufs_type.h to /usr/include/linux or wherever
2773+ you like manually. By default, the target directory is $PWD/usr.
fbc438ed 2774+- no need to apply aufs5-kbuild.patch, nor copying source files to your
53392da6
AM
2775+ kernel source tree.
2776+
b4510431 2777+Note: The header file aufs_type.h is necessary to build aufs-util
53392da6
AM
2778+ as well as "make headers_install" in the kernel source tree.
2779+ headers_install is subject to be forgotten, but it is essentially
2780+ necessary, not only for building aufs-util.
2781+ You may not meet problems without headers_install in some older
2782+ version though.
2783+
2784+And then,
2785+- read README in aufs-util, build and install it
9dbd164d
AM
2786+- note that your distribution may contain an obsoleted version of
2787+ aufs_type.h in /usr/include/linux or something. When you build aufs
2788+ utilities, make sure that your compiler refers the correct aufs header
2789+ file which is built by "make headers_install."
53392da6
AM
2790+- if you want to use readdir(3) in userspace or pathconf(3) wrapper,
2791+ then run "make install_ulib" too. And refer to the aufs manual in
2792+ detail.
2793+
fbc438ed 2794+There several other patches in aufs5-standalone.git. They are all
38d290e6 2795+optional. When you meet some problems, they will help you.
fbc438ed 2796+- aufs5-loopback.patch
38d290e6
JR
2797+ Supports a nested loopback mount in a branch-fs. This patch is
2798+ unnecessary until aufs produces a message like "you may want to try
2799+ another patch for loopback file".
83b672a5
AM
2800+- proc_mounts.patch
2801+ When there are many mountpoints and many mount(2)/umount(2) are
2802+ running, then /proc/mounts may not show the all mountpoints. This
2803+ patch makes /proc/mounts always show the full mountpoints list.
2804+ If you don't want to apply this patch and meet such problem, then you
2805+ need to increase the value of 'ProcMounts_Times' make-variable in
2806+ aufs-util.git as a second best solution.
38d290e6
JR
2807+- vfs-ino.patch
2808+ Modifies a system global kernel internal function get_next_ino() in
2809+ order to stop assigning 0 for an inode-number. Not directly related to
2810+ aufs, but recommended generally.
2811+- tmpfs-idr.patch
2812+ Keeps the tmpfs inode number as the lowest value. Effective to reduce
2813+ the size of aufs XINO files for tmpfs branch. Also it prevents the
2814+ duplication of inode number, which is important for backup tools and
2815+ other utilities. When you find aufs XINO files for tmpfs branch
2816+ growing too much, try this patch.
be52b249
AM
2817+- lockdep-debug.patch
2818+ Because aufs is not only an ordinary filesystem (callee of VFS), but
2819+ also a caller of VFS functions for branch filesystems, subclassing of
2820+ the internal locks for LOCKDEP is necessary. LOCKDEP is a debugging
2821+ feature of linux kernel. If you enable CONFIG_LOCKDEP, then you will
2822+ need to apply this debug patch to expand several constant values.
43982f53
AM
2823+ If you don't know what LOCKDEP is, then you don't have apply this
2824+ patch.
38d290e6 2825+
53392da6
AM
2826+
2827+4. Usage
2828+----------------------------------------
2829+At first, make sure aufs-util are installed, and please read the aufs
2830+manual, aufs.5 in aufs-util.git tree.
2831+$ man -l aufs.5
2832+
2833+And then,
2834+$ mkdir /tmp/rw /tmp/aufs
2835+# mount -t aufs -o br=/tmp/rw:${HOME} none /tmp/aufs
2836+
2837+Here is another example. The result is equivalent.
2838+# mount -t aufs -o br=/tmp/rw=rw:${HOME}=ro none /tmp/aufs
2839+ Or
2840+# mount -t aufs -o br:/tmp/rw none /tmp/aufs
2841+# mount -o remount,append:${HOME} /tmp/aufs
2842+
2843+Then, you can see whole tree of your home dir through /tmp/aufs. If
2844+you modify a file under /tmp/aufs, the one on your home directory is
2845+not affected, instead the same named file will be newly created under
2846+/tmp/rw. And all of your modification to a file will be applied to
2847+the one under /tmp/rw. This is called the file based Copy on Write
2848+(COW) method.
2849+Aufs mount options are described in aufs.5.
2850+If you run chroot or something and make your aufs as a root directory,
2851+then you need to customize the shutdown script. See the aufs manual in
2852+detail.
2853+
2854+Additionally, there are some sample usages of aufs which are a
2855+diskless system with network booting, and LiveCD over NFS.
2856+See sample dir in CVS tree on SourceForge.
2857+
2858+
2859+5. Contact
2860+----------------------------------------
2861+When you have any problems or strange behaviour in aufs, please let me
2862+know with:
2863+- /proc/mounts (instead of the output of mount(8))
2864+- /sys/module/aufs/*
2865+- /sys/fs/aufs/* (if you have them)
2866+- /debug/aufs/* (if you have them)
2867+- linux kernel version
2868+ if your kernel is not plain, for example modified by distributor,
2869+ the url where i can download its source is necessary too.
2870+- aufs version which was printed at loading the module or booting the
2871+ system, instead of the date you downloaded.
2872+- configuration (define/undefine CONFIG_AUFS_xxx)
2873+- kernel configuration or /proc/config.gz (if you have it)
43982f53 2874+- LSM (linux security module, if you are using)
53392da6
AM
2875+- behaviour which you think to be incorrect
2876+- actual operation, reproducible one is better
2877+- mailto: aufs-users at lists.sourceforge.net
2878+
2879+Usually, I don't watch the Public Areas(Bugs, Support Requests, Patches,
2880+and Feature Requests) on SourceForge. Please join and write to
2881+aufs-users ML.
2882+
2883+
2884+6. Acknowledgements
2885+----------------------------------------
2886+Thanks to everyone who have tried and are using aufs, whoever
2887+have reported a bug or any feedback.
2888+
2889+Especially donators:
2890+Tomas Matejicek(slax.org) made a donation (much more than once).
2891+ Since Apr 2010, Tomas M (the author of Slax and Linux Live
2892+ scripts) is making "doubling" donations.
2893+ Unfortunately I cannot list all of the donators, but I really
b4510431 2894+ appreciate.
53392da6
AM
2895+ It ends Aug 2010, but the ordinary donation URL is still available.
2896+ <http://sourceforge.net/donate/index.php?group_id=167503>
2897+Dai Itasaka made a donation (2007/8).
2898+Chuck Smith made a donation (2008/4, 10 and 12).
2899+Henk Schoneveld made a donation (2008/9).
2900+Chih-Wei Huang, ASUS, CTC donated Eee PC 4G (2008/10).
2901+Francois Dupoux made a donation (2008/11).
2902+Bruno Cesar Ribas and Luis Carlos Erpen de Bona, C3SL serves public
2903+ aufs2 GIT tree (2009/2).
2904+William Grant made a donation (2009/3).
2905+Patrick Lane made a donation (2009/4).
2906+The Mail Archive (mail-archive.com) made donations (2009/5).
2907+Nippy Networks (Ed Wildgoose) made a donation (2009/7).
2908+New Dream Network, LLC (www.dreamhost.com) made a donation (2009/11).
2909+Pavel Pronskiy made a donation (2011/2).
2910+Iridium and Inmarsat satellite phone retailer (www.mailasail.com), Nippy
2911+ Networks (Ed Wildgoose) made a donation for hardware (2011/3).
537831f9
AM
2912+Max Lekomcev (DOM-TV project) made a donation (2011/7, 12, 2012/3, 6 and
2913+11).
1e00d052 2914+Sam Liddicott made a donation (2011/9).
86dc4139
AM
2915+Era Scarecrow made a donation (2013/4).
2916+Bor Ratajc made a donation (2013/4).
2917+Alessandro Gorreta made a donation (2013/4).
2918+POIRETTE Marc made a donation (2013/4).
2919+Alessandro Gorreta made a donation (2013/4).
2920+lauri kasvandik made a donation (2013/5).
392086de 2921+"pemasu from Finland" made a donation (2013/7).
523b37e3
AM
2922+The Parted Magic Project made a donation (2013/9 and 11).
2923+Pavel Barta made a donation (2013/10).
38d290e6 2924+Nikolay Pertsev made a donation (2014/5).
c2c0f25c 2925+James B made a donation (2014/7 and 2015/7).
076b876e 2926+Stefano Di Biase made a donation (2014/8).
2000de60 2927+Daniel Epellei made a donation (2015/1).
c4adf169 2928+OmegaPhil made a donation (2016/1, 2018/4).
5afbbe0d 2929+Tomasz Szewczyk made a donation (2016/4).
f2c43d5f 2930+James Burry made a donation (2016/12).
acd2b654 2931+Carsten Rose made a donation (2018/9).
9f237c51 2932+Porteus Kiosk made a donation (2018/10).
53392da6
AM
2933+
2934+Thank you very much.
2935+Donations are always, including future donations, very important and
2936+helpful for me to keep on developing aufs.
2937+
2938+
2939+7.
2940+----------------------------------------
2941+If you are an experienced user, no explanation is needed. Aufs is
2942+just a linux filesystem.
2943+
2944+
2945+Enjoy!
2946+
2947+# Local variables: ;
2948+# mode: text;
2949+# End: ;
7f207e10 2950diff -urN /usr/share/empty/fs/aufs/aufs.h linux/fs/aufs/aufs.h
eca34b5c 2951--- /usr/share/empty/fs/aufs/aufs.h 1970-01-01 01:00:00.000000000 +0100
016522bc 2952+++ linux/fs/aufs/aufs.h 2020-01-27 10:57:18.165538015 +0100
acd2b654 2953@@ -0,0 +1,62 @@
062440b3 2954+/* SPDX-License-Identifier: GPL-2.0 */
7f207e10 2955+/*
016522bc 2956+ * Copyright (C) 2005-2020 Junjiro R. Okajima
7f207e10
AM
2957+ *
2958+ * This program, aufs is free software; you can redistribute it and/or modify
2959+ * it under the terms of the GNU General Public License as published by
2960+ * the Free Software Foundation; either version 2 of the License, or
2961+ * (at your option) any later version.
2962+ *
2963+ * This program is distributed in the hope that it will be useful,
2964+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2965+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2966+ * GNU General Public License for more details.
2967+ *
2968+ * You should have received a copy of the GNU General Public License
523b37e3 2969+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
7f207e10
AM
2970+ */
2971+
2972+/*
2973+ * all header files
2974+ */
2975+
2976+#ifndef __AUFS_H__
2977+#define __AUFS_H__
2978+
2979+#ifdef __KERNEL__
2980+
2981+#define AuStub(type, name, body, ...) \
2982+ static inline type name(__VA_ARGS__) { body; }
2983+
2984+#define AuStubVoid(name, ...) \
2985+ AuStub(void, name, , __VA_ARGS__)
2986+#define AuStubInt0(name, ...) \
2987+ AuStub(int, name, return 0, __VA_ARGS__)
2988+
2989+#include "debug.h"
2990+
2991+#include "branch.h"
2992+#include "cpup.h"
2993+#include "dcsub.h"
2994+#include "dbgaufs.h"
2995+#include "dentry.h"
2996+#include "dir.h"
8b6a4947 2997+#include "dirren.h"
7f207e10
AM
2998+#include "dynop.h"
2999+#include "file.h"
3000+#include "fstype.h"
8b6a4947 3001+#include "hbl.h"
7f207e10 3002+#include "inode.h"
acd2b654 3003+#include "lcnt.h"
7f207e10
AM
3004+#include "loop.h"
3005+#include "module.h"
7f207e10
AM
3006+#include "opts.h"
3007+#include "rwsem.h"
7f207e10
AM
3008+#include "super.h"
3009+#include "sysaufs.h"
3010+#include "vfsub.h"
3011+#include "whout.h"
3012+#include "wkq.h"
3013+
3014+#endif /* __KERNEL__ */
3015+#endif /* __AUFS_H__ */
3016diff -urN /usr/share/empty/fs/aufs/branch.c linux/fs/aufs/branch.c
eca34b5c 3017--- /usr/share/empty/fs/aufs/branch.c 1970-01-01 01:00:00.000000000 +0100
016522bc 3018+++ linux/fs/aufs/branch.c 2020-01-27 10:57:18.165538015 +0100
eca34b5c 3019@@ -0,0 +1,1428 @@
cd7a4cd9 3020+// SPDX-License-Identifier: GPL-2.0
7f207e10 3021+/*
016522bc 3022+ * Copyright (C) 2005-2020 Junjiro R. Okajima
7f207e10
AM
3023+ *
3024+ * This program, aufs is free software; you can redistribute it and/or modify
3025+ * it under the terms of the GNU General Public License as published by
3026+ * the Free Software Foundation; either version 2 of the License, or
3027+ * (at your option) any later version.
3028+ *
3029+ * This program is distributed in the hope that it will be useful,
3030+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3031+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3032+ * GNU General Public License for more details.
3033+ *
3034+ * You should have received a copy of the GNU General Public License
523b37e3 3035+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
7f207e10
AM
3036+ */
3037+
3038+/*
3039+ * branch management
3040+ */
3041+
027c5e7a 3042+#include <linux/compat.h>
7f207e10
AM
3043+#include <linux/statfs.h>
3044+#include "aufs.h"
3045+
3046+/*
3047+ * free a single branch
1facf9fc 3048+ */
3049+static void au_br_do_free(struct au_branch *br)
3050+{
3051+ int i;
3052+ struct au_wbr *wbr;
4a4d8108 3053+ struct au_dykey **key;
1facf9fc 3054+
027c5e7a 3055+ au_hnotify_fin_br(br);
8b6a4947
AM
3056+ /* always, regardless the mount option */
3057+ au_dr_hino_free(&br->br_dirren);
062440b3 3058+ au_xino_put(br);
1facf9fc 3059+
acd2b654
AM
3060+ AuLCntZero(au_lcnt_read(&br->br_nfiles, /*do_rev*/0));
3061+ au_lcnt_fin(&br->br_nfiles, /*do_sync*/0);
3062+ AuLCntZero(au_lcnt_read(&br->br_count, /*do_rev*/0));
3063+ au_lcnt_fin(&br->br_count, /*do_sync*/0);
1facf9fc 3064+
3065+ wbr = br->br_wbr;
3066+ if (wbr) {
3067+ for (i = 0; i < AuBrWh_Last; i++)
3068+ dput(wbr->wbr_wh[i]);
3069+ AuDebugOn(atomic_read(&wbr->wbr_wh_running));
dece6358 3070+ AuRwDestroy(&wbr->wbr_wh_rwsem);
1facf9fc 3071+ }
3072+
076b876e
AM
3073+ if (br->br_fhsm) {
3074+ au_br_fhsm_fin(br->br_fhsm);
9f237c51 3075+ au_kfree_try_rcu(br->br_fhsm);
076b876e
AM
3076+ }
3077+
4a4d8108
AM
3078+ key = br->br_dykey;
3079+ for (i = 0; i < AuBrDynOp; i++, key++)
3080+ if (*key)
3081+ au_dy_put(*key);
3082+ else
3083+ break;
3084+
537831f9 3085+ /* recursive lock, s_umount of branch's */
acd2b654 3086+ /* synchronize_rcu(); */ /* why? */
537831f9 3087+ lockdep_off();
86dc4139 3088+ path_put(&br->br_path);
537831f9 3089+ lockdep_on();
9f237c51 3090+ au_kfree_rcu(wbr);
acd2b654
AM
3091+ au_lcnt_wait_for_fin(&br->br_nfiles);
3092+ au_lcnt_wait_for_fin(&br->br_count);
3093+ /* I don't know why, but percpu_refcount requires this */
3094+ /* synchronize_rcu(); */
9f237c51 3095+ au_kfree_rcu(br);
1facf9fc 3096+}
3097+
3098+/*
3099+ * frees all branches
3100+ */
3101+void au_br_free(struct au_sbinfo *sbinfo)
3102+{
3103+ aufs_bindex_t bmax;
3104+ struct au_branch **br;
3105+
dece6358
AM
3106+ AuRwMustWriteLock(&sbinfo->si_rwsem);
3107+
5afbbe0d 3108+ bmax = sbinfo->si_bbot + 1;
1facf9fc 3109+ br = sbinfo->si_branch;
3110+ while (bmax--)
3111+ au_br_do_free(*br++);
3112+}
3113+
3114+/*
3115+ * find the index of a branch which is specified by @br_id.
3116+ */
3117+int au_br_index(struct super_block *sb, aufs_bindex_t br_id)
3118+{
5afbbe0d 3119+ aufs_bindex_t bindex, bbot;
1facf9fc 3120+
5afbbe0d
AM
3121+ bbot = au_sbbot(sb);
3122+ for (bindex = 0; bindex <= bbot; bindex++)
1facf9fc 3123+ if (au_sbr_id(sb, bindex) == br_id)
3124+ return bindex;
3125+ return -1;
3126+}
3127+
3128+/* ---------------------------------------------------------------------- */
3129+
3130+/*
3131+ * add a branch
3132+ */
3133+
b752ccd1
AM
3134+static int test_overlap(struct super_block *sb, struct dentry *h_adding,
3135+ struct dentry *h_root)
1facf9fc 3136+{
b752ccd1
AM
3137+ if (unlikely(h_adding == h_root
3138+ || au_test_loopback_overlap(sb, h_adding)))
1facf9fc 3139+ return 1;
b752ccd1
AM
3140+ if (h_adding->d_sb != h_root->d_sb)
3141+ return 0;
3142+ return au_test_subdir(h_adding, h_root)
3143+ || au_test_subdir(h_root, h_adding);
1facf9fc 3144+}
3145+
3146+/*
3147+ * returns a newly allocated branch. @new_nbranch is a number of branches
3148+ * after adding a branch.
3149+ */
3150+static struct au_branch *au_br_alloc(struct super_block *sb, int new_nbranch,
3151+ int perm)
3152+{
3153+ struct au_branch *add_branch;
3154+ struct dentry *root;
5527c038 3155+ struct inode *inode;
4a4d8108 3156+ int err;
1facf9fc 3157+
4a4d8108 3158+ err = -ENOMEM;
be52b249 3159+ add_branch = kzalloc(sizeof(*add_branch), GFP_NOFS);
1facf9fc 3160+ if (unlikely(!add_branch))
3161+ goto out;
acd2b654 3162+ add_branch->br_xino = au_xino_alloc(/*nfile*/1);
062440b3 3163+ if (unlikely(!add_branch->br_xino))
521ced18 3164+ goto out_br;
027c5e7a
AM
3165+ err = au_hnotify_init_br(add_branch, perm);
3166+ if (unlikely(err))
062440b3 3167+ goto out_xino;
027c5e7a 3168+
1facf9fc 3169+ if (au_br_writable(perm)) {
3170+ /* may be freed separately at changing the branch permission */
be52b249 3171+ add_branch->br_wbr = kzalloc(sizeof(*add_branch->br_wbr),
1facf9fc 3172+ GFP_NOFS);
3173+ if (unlikely(!add_branch->br_wbr))
027c5e7a 3174+ goto out_hnotify;
1facf9fc 3175+ }
3176+
076b876e
AM
3177+ if (au_br_fhsm(perm)) {
3178+ err = au_fhsm_br_alloc(add_branch);
3179+ if (unlikely(err))
3180+ goto out_wbr;
3181+ }
3182+
521ced18 3183+ root = sb->s_root;
e2f27e51 3184+ err = au_sbr_realloc(au_sbi(sb), new_nbranch, /*may_shrink*/0);
4a4d8108 3185+ if (!err)
e2f27e51 3186+ err = au_di_realloc(au_di(root), new_nbranch, /*may_shrink*/0);
5527c038
JR
3187+ if (!err) {
3188+ inode = d_inode(root);
1c60b727
AM
3189+ err = au_hinode_realloc(au_ii(inode), new_nbranch,
3190+ /*may_shrink*/0);
5527c038 3191+ }
4a4d8108
AM
3192+ if (!err)
3193+ return add_branch; /* success */
1facf9fc 3194+
076b876e 3195+out_wbr:
9f237c51 3196+ au_kfree_rcu(add_branch->br_wbr);
027c5e7a
AM
3197+out_hnotify:
3198+ au_hnotify_fin_br(add_branch);
062440b3
AM
3199+out_xino:
3200+ au_xino_put(add_branch);
4f0767ce 3201+out_br:
9f237c51 3202+ au_kfree_rcu(add_branch);
4f0767ce 3203+out:
4a4d8108 3204+ return ERR_PTR(err);
1facf9fc 3205+}
3206+
3207+/*
3208+ * test if the branch permission is legal or not.
3209+ */
3210+static int test_br(struct inode *inode, int brperm, char *path)
3211+{
3212+ int err;
3213+
4a4d8108
AM
3214+ err = (au_br_writable(brperm) && IS_RDONLY(inode));
3215+ if (!err)
3216+ goto out;
1facf9fc 3217+
4a4d8108
AM
3218+ err = -EINVAL;
3219+ pr_err("write permission for readonly mount or inode, %s\n", path);
3220+
4f0767ce 3221+out:
1facf9fc 3222+ return err;
3223+}
3224+
3225+/*
3226+ * returns:
3227+ * 0: success, the caller will add it
3228+ * plus: success, it is already unified, the caller should ignore it
3229+ * minus: error
3230+ */
3231+static int test_add(struct super_block *sb, struct au_opt_add *add, int remount)
3232+{
3233+ int err;
5afbbe0d 3234+ aufs_bindex_t bbot, bindex;
5527c038 3235+ struct dentry *root, *h_dentry;
1facf9fc 3236+ struct inode *inode, *h_inode;
3237+
3238+ root = sb->s_root;
5afbbe0d
AM
3239+ bbot = au_sbbot(sb);
3240+ if (unlikely(bbot >= 0
1facf9fc 3241+ && au_find_dbindex(root, add->path.dentry) >= 0)) {
3242+ err = 1;
3243+ if (!remount) {
3244+ err = -EINVAL;
4a4d8108 3245+ pr_err("%s duplicated\n", add->pathname);
1facf9fc 3246+ }
3247+ goto out;
3248+ }
3249+
3250+ err = -ENOSPC; /* -E2BIG; */
3251+ if (unlikely(AUFS_BRANCH_MAX <= add->bindex
5afbbe0d 3252+ || AUFS_BRANCH_MAX - 1 <= bbot)) {
4a4d8108 3253+ pr_err("number of branches exceeded %s\n", add->pathname);
1facf9fc 3254+ goto out;
3255+ }
3256+
3257+ err = -EDOM;
5afbbe0d 3258+ if (unlikely(add->bindex < 0 || bbot + 1 < add->bindex)) {
4a4d8108 3259+ pr_err("bad index %d\n", add->bindex);
1facf9fc 3260+ goto out;
3261+ }
3262+
5527c038 3263+ inode = d_inode(add->path.dentry);
1facf9fc 3264+ err = -ENOENT;
3265+ if (unlikely(!inode->i_nlink)) {
4a4d8108 3266+ pr_err("no existence %s\n", add->pathname);
1facf9fc 3267+ goto out;
3268+ }
3269+
3270+ err = -EINVAL;
3271+ if (unlikely(inode->i_sb == sb)) {
4a4d8108 3272+ pr_err("%s must be outside\n", add->pathname);
1facf9fc 3273+ goto out;
3274+ }
3275+
3276+ if (unlikely(au_test_fs_unsuppoted(inode->i_sb))) {
4a4d8108
AM
3277+ pr_err("unsupported filesystem, %s (%s)\n",
3278+ add->pathname, au_sbtype(inode->i_sb));
1facf9fc 3279+ goto out;
3280+ }
3281+
c1595e42
JR
3282+ if (unlikely(inode->i_sb->s_stack_depth)) {
3283+ pr_err("already stacked, %s (%s)\n",
3284+ add->pathname, au_sbtype(inode->i_sb));
3285+ goto out;
3286+ }
3287+
5527c038 3288+ err = test_br(d_inode(add->path.dentry), add->perm, add->pathname);
1facf9fc 3289+ if (unlikely(err))
3290+ goto out;
3291+
5afbbe0d 3292+ if (bbot < 0)
1facf9fc 3293+ return 0; /* success */
3294+
3295+ err = -EINVAL;
5afbbe0d 3296+ for (bindex = 0; bindex <= bbot; bindex++)
1facf9fc 3297+ if (unlikely(test_overlap(sb, add->path.dentry,
3298+ au_h_dptr(root, bindex)))) {
4a4d8108 3299+ pr_err("%s is overlapped\n", add->pathname);
1facf9fc 3300+ goto out;
3301+ }
3302+
3303+ err = 0;
3304+ if (au_opt_test(au_mntflags(sb), WARN_PERM)) {
5527c038
JR
3305+ h_dentry = au_h_dptr(root, 0);
3306+ h_inode = d_inode(h_dentry);
1facf9fc 3307+ if ((h_inode->i_mode & S_IALLUGO) != (inode->i_mode & S_IALLUGO)
0c3ec466
AM
3308+ || !uid_eq(h_inode->i_uid, inode->i_uid)
3309+ || !gid_eq(h_inode->i_gid, inode->i_gid))
3310+ pr_warn("uid/gid/perm %s %u/%u/0%o, %u/%u/0%o\n",
3311+ add->pathname,
3312+ i_uid_read(inode), i_gid_read(inode),
3313+ (inode->i_mode & S_IALLUGO),
3314+ i_uid_read(h_inode), i_gid_read(h_inode),
3315+ (h_inode->i_mode & S_IALLUGO));
1facf9fc 3316+ }
3317+
4f0767ce 3318+out:
1facf9fc 3319+ return err;
3320+}
3321+
3322+/*
3323+ * initialize or clean the whiteouts for an adding branch
3324+ */
3325+static int au_br_init_wh(struct super_block *sb, struct au_branch *br,
86dc4139 3326+ int new_perm)
1facf9fc 3327+{
3328+ int err, old_perm;
3329+ aufs_bindex_t bindex;
febd17d6 3330+ struct inode *h_inode;
1facf9fc 3331+ struct au_wbr *wbr;
3332+ struct au_hinode *hdir;
5527c038 3333+ struct dentry *h_dentry;
1facf9fc 3334+
86dc4139
AM
3335+ err = vfsub_mnt_want_write(au_br_mnt(br));
3336+ if (unlikely(err))
3337+ goto out;
3338+
1facf9fc 3339+ wbr = br->br_wbr;
3340+ old_perm = br->br_perm;
3341+ br->br_perm = new_perm;
3342+ hdir = NULL;
febd17d6 3343+ h_inode = NULL;
1facf9fc 3344+ bindex = au_br_index(sb, br->br_id);
3345+ if (0 <= bindex) {
5527c038 3346+ hdir = au_hi(d_inode(sb->s_root), bindex);
5afbbe0d 3347+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 3348+ } else {
5527c038 3349+ h_dentry = au_br_dentry(br);
febd17d6
JR
3350+ h_inode = d_inode(h_dentry);
3351+ inode_lock_nested(h_inode, AuLsc_I_PARENT);
1facf9fc 3352+ }
3353+ if (!wbr)
86dc4139 3354+ err = au_wh_init(br, sb);
1facf9fc 3355+ else {
3356+ wbr_wh_write_lock(wbr);
86dc4139 3357+ err = au_wh_init(br, sb);
1facf9fc 3358+ wbr_wh_write_unlock(wbr);
3359+ }
3360+ if (hdir)
5afbbe0d 3361+ au_hn_inode_unlock(hdir);
1facf9fc 3362+ else
febd17d6 3363+ inode_unlock(h_inode);
86dc4139 3364+ vfsub_mnt_drop_write(au_br_mnt(br));
1facf9fc 3365+ br->br_perm = old_perm;
3366+
3367+ if (!err && wbr && !au_br_writable(new_perm)) {
9f237c51 3368+ au_kfree_rcu(wbr);
1facf9fc 3369+ br->br_wbr = NULL;
3370+ }
3371+
86dc4139 3372+out:
1facf9fc 3373+ return err;
3374+}
3375+
3376+static int au_wbr_init(struct au_branch *br, struct super_block *sb,
86dc4139 3377+ int perm)
1facf9fc 3378+{
3379+ int err;
4a4d8108 3380+ struct kstatfs kst;
1facf9fc 3381+ struct au_wbr *wbr;
3382+
3383+ wbr = br->br_wbr;
dece6358 3384+ au_rw_init(&wbr->wbr_wh_rwsem);
1facf9fc 3385+ atomic_set(&wbr->wbr_wh_running, 0);
1facf9fc 3386+
4a4d8108
AM
3387+ /*
3388+ * a limit for rmdir/rename a dir
523b37e3 3389+ * cf. AUFS_MAX_NAMELEN in include/uapi/linux/aufs_type.h
4a4d8108 3390+ */
86dc4139 3391+ err = vfs_statfs(&br->br_path, &kst);
4a4d8108
AM
3392+ if (unlikely(err))
3393+ goto out;
3394+ err = -EINVAL;
3395+ if (kst.f_namelen >= NAME_MAX)
86dc4139 3396+ err = au_br_init_wh(sb, br, perm);
4a4d8108 3397+ else
523b37e3
AM
3398+ pr_err("%pd(%s), unsupported namelen %ld\n",
3399+ au_br_dentry(br),
86dc4139 3400+ au_sbtype(au_br_dentry(br)->d_sb), kst.f_namelen);
1facf9fc 3401+
4f0767ce 3402+out:
1facf9fc 3403+ return err;
3404+}
3405+
c1595e42 3406+/* initialize a new branch */
1facf9fc 3407+static int au_br_init(struct au_branch *br, struct super_block *sb,
3408+ struct au_opt_add *add)
3409+{
3410+ int err;
062440b3
AM
3411+ struct au_branch *brbase;
3412+ struct file *xf;
5527c038 3413+ struct inode *h_inode;
1facf9fc 3414+
3415+ err = 0;
1facf9fc 3416+ br->br_perm = add->perm;
86dc4139 3417+ br->br_path = add->path; /* set first, path_get() later */
4a4d8108 3418+ spin_lock_init(&br->br_dykey_lock);
acd2b654
AM
3419+ au_lcnt_init(&br->br_nfiles, /*release*/NULL);
3420+ au_lcnt_init(&br->br_count, /*release*/NULL);
1facf9fc 3421+ br->br_id = au_new_br_id(sb);
7f207e10 3422+ AuDebugOn(br->br_id < 0);
1facf9fc 3423+
8b6a4947
AM
3424+ /* always, regardless the given option */
3425+ err = au_dr_br_init(sb, br, &add->path);
3426+ if (unlikely(err))
3427+ goto out_err;
3428+
1facf9fc 3429+ if (au_br_writable(add->perm)) {
86dc4139 3430+ err = au_wbr_init(br, sb, add->perm);
1facf9fc 3431+ if (unlikely(err))
b752ccd1 3432+ goto out_err;
1facf9fc 3433+ }
3434+
3435+ if (au_opt_test(au_mntflags(sb), XINO)) {
062440b3 3436+ brbase = au_sbr(sb, 0);
acd2b654 3437+ xf = au_xino_file(brbase->br_xino, /*idx*/-1);
062440b3 3438+ AuDebugOn(!xf);
5527c038 3439+ h_inode = d_inode(add->path.dentry);
062440b3 3440+ err = au_xino_init_br(sb, br, h_inode->i_ino, &xf->f_path);
1facf9fc 3441+ if (unlikely(err)) {
acd2b654 3442+ AuDebugOn(au_xino_file(br->br_xino, /*idx*/-1));
b752ccd1 3443+ goto out_err;
1facf9fc 3444+ }
3445+ }
3446+
3447+ sysaufs_br_init(br);
86dc4139 3448+ path_get(&br->br_path);
b752ccd1 3449+ goto out; /* success */
1facf9fc 3450+
4f0767ce 3451+out_err:
86dc4139 3452+ memset(&br->br_path, 0, sizeof(br->br_path));
4f0767ce 3453+out:
1facf9fc 3454+ return err;
3455+}
3456+
3457+static void au_br_do_add_brp(struct au_sbinfo *sbinfo, aufs_bindex_t bindex,
5afbbe0d 3458+ struct au_branch *br, aufs_bindex_t bbot,
1facf9fc 3459+ aufs_bindex_t amount)
3460+{
3461+ struct au_branch **brp;
3462+
dece6358
AM
3463+ AuRwMustWriteLock(&sbinfo->si_rwsem);
3464+
1facf9fc 3465+ brp = sbinfo->si_branch + bindex;
3466+ memmove(brp + 1, brp, sizeof(*brp) * amount);
3467+ *brp = br;
5afbbe0d
AM
3468+ sbinfo->si_bbot++;
3469+ if (unlikely(bbot < 0))
3470+ sbinfo->si_bbot = 0;
1facf9fc 3471+}
3472+
3473+static void au_br_do_add_hdp(struct au_dinfo *dinfo, aufs_bindex_t bindex,
5afbbe0d 3474+ aufs_bindex_t bbot, aufs_bindex_t amount)
1facf9fc 3475+{
3476+ struct au_hdentry *hdp;
3477+
1308ab2a 3478+ AuRwMustWriteLock(&dinfo->di_rwsem);
3479+
5afbbe0d 3480+ hdp = au_hdentry(dinfo, bindex);
1facf9fc 3481+ memmove(hdp + 1, hdp, sizeof(*hdp) * amount);
3482+ au_h_dentry_init(hdp);
5afbbe0d
AM
3483+ dinfo->di_bbot++;
3484+ if (unlikely(bbot < 0))
3485+ dinfo->di_btop = 0;
1facf9fc 3486+}
3487+
3488+static void au_br_do_add_hip(struct au_iinfo *iinfo, aufs_bindex_t bindex,
5afbbe0d 3489+ aufs_bindex_t bbot, aufs_bindex_t amount)
1facf9fc 3490+{
3491+ struct au_hinode *hip;
3492+
1308ab2a 3493+ AuRwMustWriteLock(&iinfo->ii_rwsem);
3494+
5afbbe0d 3495+ hip = au_hinode(iinfo, bindex);
1facf9fc 3496+ memmove(hip + 1, hip, sizeof(*hip) * amount);
5afbbe0d
AM
3497+ au_hinode_init(hip);
3498+ iinfo->ii_bbot++;
3499+ if (unlikely(bbot < 0))
3500+ iinfo->ii_btop = 0;
1facf9fc 3501+}
3502+
86dc4139
AM
3503+static void au_br_do_add(struct super_block *sb, struct au_branch *br,
3504+ aufs_bindex_t bindex)
1facf9fc 3505+{
86dc4139 3506+ struct dentry *root, *h_dentry;
5527c038 3507+ struct inode *root_inode, *h_inode;
5afbbe0d 3508+ aufs_bindex_t bbot, amount;
1facf9fc 3509+
3510+ root = sb->s_root;
5527c038 3511+ root_inode = d_inode(root);
5afbbe0d
AM
3512+ bbot = au_sbbot(sb);
3513+ amount = bbot + 1 - bindex;
86dc4139 3514+ h_dentry = au_br_dentry(br);
53392da6 3515+ au_sbilist_lock();
5afbbe0d
AM
3516+ au_br_do_add_brp(au_sbi(sb), bindex, br, bbot, amount);
3517+ au_br_do_add_hdp(au_di(root), bindex, bbot, amount);
3518+ au_br_do_add_hip(au_ii(root_inode), bindex, bbot, amount);
1facf9fc 3519+ au_set_h_dptr(root, bindex, dget(h_dentry));
5527c038
JR
3520+ h_inode = d_inode(h_dentry);
3521+ au_set_h_iptr(root_inode, bindex, au_igrab(h_inode), /*flags*/0);
53392da6 3522+ au_sbilist_unlock();
1facf9fc 3523+}
3524+
3525+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount)
3526+{
3527+ int err;
5afbbe0d 3528+ aufs_bindex_t bbot, add_bindex;
1facf9fc 3529+ struct dentry *root, *h_dentry;
3530+ struct inode *root_inode;
3531+ struct au_branch *add_branch;
3532+
3533+ root = sb->s_root;
5527c038 3534+ root_inode = d_inode(root);
1facf9fc 3535+ IMustLock(root_inode);
5afbbe0d 3536+ IiMustWriteLock(root_inode);
1facf9fc 3537+ err = test_add(sb, add, remount);
3538+ if (unlikely(err < 0))
3539+ goto out;
3540+ if (err) {
3541+ err = 0;
3542+ goto out; /* success */
3543+ }
3544+
5afbbe0d
AM
3545+ bbot = au_sbbot(sb);
3546+ add_branch = au_br_alloc(sb, bbot + 2, add->perm);
1facf9fc 3547+ err = PTR_ERR(add_branch);
3548+ if (IS_ERR(add_branch))
3549+ goto out;
3550+
3551+ err = au_br_init(add_branch, sb, add);
3552+ if (unlikely(err)) {
3553+ au_br_do_free(add_branch);
3554+ goto out;
3555+ }
3556+
3557+ add_bindex = add->bindex;
062440b3
AM
3558+ sysaufs_brs_del(sb, add_bindex); /* remove successors */
3559+ au_br_do_add(sb, add_branch, add_bindex);
3560+ sysaufs_brs_add(sb, add_bindex); /* append successors */
3561+ dbgaufs_brs_add(sb, add_bindex, /*topdown*/0); /* rename successors */
1facf9fc 3562+
86dc4139 3563+ h_dentry = add->path.dentry;
1308ab2a 3564+ if (!add_bindex) {
1facf9fc 3565+ au_cpup_attr_all(root_inode, /*force*/1);
1308ab2a 3566+ sb->s_maxbytes = h_dentry->d_sb->s_maxbytes;
3567+ } else
5527c038 3568+ au_add_nlink(root_inode, d_inode(h_dentry));
1facf9fc 3569+
4f0767ce 3570+out:
1facf9fc 3571+ return err;
3572+}
3573+
3574+/* ---------------------------------------------------------------------- */
3575+
79b8bda9 3576+static unsigned long long au_farray_cb(struct super_block *sb, void *a,
076b876e
AM
3577+ unsigned long long max __maybe_unused,
3578+ void *arg)
3579+{
3580+ unsigned long long n;
3581+ struct file **p, *f;
8b6a4947
AM
3582+ struct hlist_bl_head *files;
3583+ struct hlist_bl_node *pos;
076b876e 3584+ struct au_finfo *finfo;
076b876e
AM
3585+
3586+ n = 0;
3587+ p = a;
3588+ files = &au_sbi(sb)->si_files;
8b6a4947
AM
3589+ hlist_bl_lock(files);
3590+ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) {
076b876e
AM
3591+ f = finfo->fi_file;
3592+ if (file_count(f)
3593+ && !special_file(file_inode(f)->i_mode)) {
3594+ get_file(f);
3595+ *p++ = f;
3596+ n++;
3597+ AuDebugOn(n > max);
3598+ }
3599+ }
8b6a4947 3600+ hlist_bl_unlock(files);
076b876e
AM
3601+
3602+ return n;
3603+}
3604+
3605+static struct file **au_farray_alloc(struct super_block *sb,
3606+ unsigned long long *max)
3607+{
acd2b654
AM
3608+ struct au_sbinfo *sbi;
3609+
3610+ sbi = au_sbi(sb);
3611+ *max = au_lcnt_read(&sbi->si_nfiles, /*do_rev*/1);
79b8bda9 3612+ return au_array_alloc(max, au_farray_cb, sb, /*arg*/NULL);
076b876e
AM
3613+}
3614+
3615+static void au_farray_free(struct file **a, unsigned long long max)
3616+{
3617+ unsigned long long ull;
3618+
3619+ for (ull = 0; ull < max; ull++)
3620+ if (a[ull])
3621+ fput(a[ull]);
be52b249 3622+ kvfree(a);
076b876e
AM
3623+}
3624+
3625+/* ---------------------------------------------------------------------- */
3626+
1facf9fc 3627+/*
3628+ * delete a branch
3629+ */
3630+
3631+/* to show the line number, do not make it inlined function */
4a4d8108 3632+#define AuVerbose(do_info, fmt, ...) do { \
1facf9fc 3633+ if (do_info) \
4a4d8108 3634+ pr_info(fmt, ##__VA_ARGS__); \
1facf9fc 3635+} while (0)
3636+
5afbbe0d
AM
3637+static int au_test_ibusy(struct inode *inode, aufs_bindex_t btop,
3638+ aufs_bindex_t bbot)
027c5e7a 3639+{
5afbbe0d 3640+ return (inode && !S_ISDIR(inode->i_mode)) || btop == bbot;
027c5e7a
AM
3641+}
3642+
5afbbe0d
AM
3643+static int au_test_dbusy(struct dentry *dentry, aufs_bindex_t btop,
3644+ aufs_bindex_t bbot)
027c5e7a 3645+{
5afbbe0d 3646+ return au_test_ibusy(d_inode(dentry), btop, bbot);
027c5e7a
AM
3647+}
3648+
1facf9fc 3649+/*
3650+ * test if the branch is deletable or not.
3651+ */
3652+static int test_dentry_busy(struct dentry *root, aufs_bindex_t bindex,
b752ccd1 3653+ unsigned int sigen, const unsigned int verbose)
1facf9fc 3654+{
3655+ int err, i, j, ndentry;
5afbbe0d 3656+ aufs_bindex_t btop, bbot;
1facf9fc 3657+ struct au_dcsub_pages dpages;
3658+ struct au_dpage *dpage;
3659+ struct dentry *d;
1facf9fc 3660+
3661+ err = au_dpages_init(&dpages, GFP_NOFS);
3662+ if (unlikely(err))
3663+ goto out;
3664+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
3665+ if (unlikely(err))
3666+ goto out_dpages;
3667+
1facf9fc 3668+ for (i = 0; !err && i < dpages.ndpage; i++) {
3669+ dpage = dpages.dpages + i;
3670+ ndentry = dpage->ndentry;
3671+ for (j = 0; !err && j < ndentry; j++) {
3672+ d = dpage->dentries[j];
c1595e42 3673+ AuDebugOn(au_dcount(d) <= 0);
027c5e7a 3674+ if (!au_digen_test(d, sigen)) {
1facf9fc 3675+ di_read_lock_child(d, AuLock_IR);
027c5e7a
AM
3676+ if (unlikely(au_dbrange_test(d))) {
3677+ di_read_unlock(d, AuLock_IR);
3678+ continue;
3679+ }
3680+ } else {
1facf9fc 3681+ di_write_lock_child(d);
027c5e7a
AM
3682+ if (unlikely(au_dbrange_test(d))) {
3683+ di_write_unlock(d);
3684+ continue;
3685+ }
1facf9fc 3686+ err = au_reval_dpath(d, sigen);
3687+ if (!err)
3688+ di_downgrade_lock(d, AuLock_IR);
3689+ else {
3690+ di_write_unlock(d);
3691+ break;
3692+ }
3693+ }
3694+
027c5e7a 3695+ /* AuDbgDentry(d); */
5afbbe0d
AM
3696+ btop = au_dbtop(d);
3697+ bbot = au_dbbot(d);
3698+ if (btop <= bindex
3699+ && bindex <= bbot
1facf9fc 3700+ && au_h_dptr(d, bindex)
5afbbe0d 3701+ && au_test_dbusy(d, btop, bbot)) {
1facf9fc 3702+ err = -EBUSY;
523b37e3 3703+ AuVerbose(verbose, "busy %pd\n", d);
027c5e7a 3704+ AuDbgDentry(d);
1facf9fc 3705+ }
3706+ di_read_unlock(d, AuLock_IR);
3707+ }
3708+ }
3709+
4f0767ce 3710+out_dpages:
1facf9fc 3711+ au_dpages_free(&dpages);
4f0767ce 3712+out:
1facf9fc 3713+ return err;
3714+}
3715+
3716+static int test_inode_busy(struct super_block *sb, aufs_bindex_t bindex,
b752ccd1 3717+ unsigned int sigen, const unsigned int verbose)
1facf9fc 3718+{
3719+ int err;
7f207e10
AM
3720+ unsigned long long max, ull;
3721+ struct inode *i, **array;
5afbbe0d 3722+ aufs_bindex_t btop, bbot;
1facf9fc 3723+
7f207e10
AM
3724+ array = au_iarray_alloc(sb, &max);
3725+ err = PTR_ERR(array);
3726+ if (IS_ERR(array))
3727+ goto out;
3728+
1facf9fc 3729+ err = 0;
7f207e10
AM
3730+ AuDbg("b%d\n", bindex);
3731+ for (ull = 0; !err && ull < max; ull++) {
3732+ i = array[ull];
076b876e
AM
3733+ if (unlikely(!i))
3734+ break;
7f207e10 3735+ if (i->i_ino == AUFS_ROOT_INO)
1facf9fc 3736+ continue;
3737+
7f207e10 3738+ /* AuDbgInode(i); */
537831f9 3739+ if (au_iigen(i, NULL) == sigen)
1facf9fc 3740+ ii_read_lock_child(i);
3741+ else {
3742+ ii_write_lock_child(i);
027c5e7a
AM
3743+ err = au_refresh_hinode_self(i);
3744+ au_iigen_dec(i);
1facf9fc 3745+ if (!err)
3746+ ii_downgrade_lock(i);
3747+ else {
3748+ ii_write_unlock(i);
3749+ break;
3750+ }
3751+ }
3752+
5afbbe0d
AM
3753+ btop = au_ibtop(i);
3754+ bbot = au_ibbot(i);
3755+ if (btop <= bindex
3756+ && bindex <= bbot
1facf9fc 3757+ && au_h_iptr(i, bindex)
5afbbe0d 3758+ && au_test_ibusy(i, btop, bbot)) {
1facf9fc 3759+ err = -EBUSY;
3760+ AuVerbose(verbose, "busy i%lu\n", i->i_ino);
7f207e10 3761+ AuDbgInode(i);
1facf9fc 3762+ }
3763+ ii_read_unlock(i);
3764+ }
7f207e10 3765+ au_iarray_free(array, max);
1facf9fc 3766+
7f207e10 3767+out:
1facf9fc 3768+ return err;
3769+}
3770+
b752ccd1
AM
3771+static int test_children_busy(struct dentry *root, aufs_bindex_t bindex,
3772+ const unsigned int verbose)
1facf9fc 3773+{
3774+ int err;
3775+ unsigned int sigen;
3776+
3777+ sigen = au_sigen(root->d_sb);
3778+ DiMustNoWaiters(root);
5527c038 3779+ IiMustNoWaiters(d_inode(root));
1facf9fc 3780+ di_write_unlock(root);
b752ccd1 3781+ err = test_dentry_busy(root, bindex, sigen, verbose);
1facf9fc 3782+ if (!err)
b752ccd1 3783+ err = test_inode_busy(root->d_sb, bindex, sigen, verbose);
1facf9fc 3784+ di_write_lock_child(root); /* aufs_write_lock() calls ..._child() */
3785+
3786+ return err;
3787+}
3788+
076b876e
AM
3789+static int test_dir_busy(struct file *file, aufs_bindex_t br_id,
3790+ struct file **to_free, int *idx)
3791+{
3792+ int err;
c1595e42 3793+ unsigned char matched, root;
5afbbe0d 3794+ aufs_bindex_t bindex, bbot;
076b876e
AM
3795+ struct au_fidir *fidir;
3796+ struct au_hfile *hfile;
3797+
3798+ err = 0;
2000de60 3799+ root = IS_ROOT(file->f_path.dentry);
c1595e42
JR
3800+ if (root) {
3801+ get_file(file);
3802+ to_free[*idx] = file;
3803+ (*idx)++;
3804+ goto out;
3805+ }
3806+
076b876e 3807+ matched = 0;
076b876e
AM
3808+ fidir = au_fi(file)->fi_hdir;
3809+ AuDebugOn(!fidir);
5afbbe0d
AM
3810+ bbot = au_fbbot_dir(file);
3811+ for (bindex = au_fbtop(file); bindex <= bbot; bindex++) {
076b876e
AM
3812+ hfile = fidir->fd_hfile + bindex;
3813+ if (!hfile->hf_file)
3814+ continue;
3815+
c1595e42 3816+ if (hfile->hf_br->br_id == br_id) {
076b876e 3817+ matched = 1;
076b876e 3818+ break;
c1595e42 3819+ }
076b876e 3820+ }
c1595e42 3821+ if (matched)
076b876e
AM
3822+ err = -EBUSY;
3823+
3824+out:
3825+ return err;
3826+}
3827+
3828+static int test_file_busy(struct super_block *sb, aufs_bindex_t br_id,
3829+ struct file **to_free, int opened)
3830+{
3831+ int err, idx;
3832+ unsigned long long ull, max;
5afbbe0d 3833+ aufs_bindex_t btop;
076b876e 3834+ struct file *file, **array;
076b876e
AM
3835+ struct dentry *root;
3836+ struct au_hfile *hfile;
3837+
3838+ array = au_farray_alloc(sb, &max);
3839+ err = PTR_ERR(array);
3840+ if (IS_ERR(array))
3841+ goto out;
3842+
3843+ err = 0;
3844+ idx = 0;
3845+ root = sb->s_root;
3846+ di_write_unlock(root);
3847+ for (ull = 0; ull < max; ull++) {
3848+ file = array[ull];
3849+ if (unlikely(!file))
3850+ break;
3851+
3852+ /* AuDbg("%pD\n", file); */
3853+ fi_read_lock(file);
5afbbe0d 3854+ btop = au_fbtop(file);
2000de60 3855+ if (!d_is_dir(file->f_path.dentry)) {
076b876e
AM
3856+ hfile = &au_fi(file)->fi_htop;
3857+ if (hfile->hf_br->br_id == br_id)
3858+ err = -EBUSY;
3859+ } else
3860+ err = test_dir_busy(file, br_id, to_free, &idx);
3861+ fi_read_unlock(file);
3862+ if (unlikely(err))
3863+ break;
3864+ }
3865+ di_write_lock_child(root);
3866+ au_farray_free(array, max);
3867+ AuDebugOn(idx > opened);
3868+
3869+out:
3870+ return err;
3871+}
3872+
3873+static void br_del_file(struct file **to_free, unsigned long long opened,
062440b3 3874+ aufs_bindex_t br_id)
076b876e
AM
3875+{
3876+ unsigned long long ull;
5afbbe0d 3877+ aufs_bindex_t bindex, btop, bbot, bfound;
076b876e
AM
3878+ struct file *file;
3879+ struct au_fidir *fidir;
3880+ struct au_hfile *hfile;
3881+
3882+ for (ull = 0; ull < opened; ull++) {
3883+ file = to_free[ull];
3884+ if (unlikely(!file))
3885+ break;
3886+
3887+ /* AuDbg("%pD\n", file); */
2000de60 3888+ AuDebugOn(!d_is_dir(file->f_path.dentry));
076b876e
AM
3889+ bfound = -1;
3890+ fidir = au_fi(file)->fi_hdir;
3891+ AuDebugOn(!fidir);
3892+ fi_write_lock(file);
5afbbe0d
AM
3893+ btop = au_fbtop(file);
3894+ bbot = au_fbbot_dir(file);
3895+ for (bindex = btop; bindex <= bbot; bindex++) {
076b876e
AM
3896+ hfile = fidir->fd_hfile + bindex;
3897+ if (!hfile->hf_file)
3898+ continue;
3899+
3900+ if (hfile->hf_br->br_id == br_id) {
3901+ bfound = bindex;
3902+ break;
3903+ }
3904+ }
3905+ AuDebugOn(bfound < 0);
3906+ au_set_h_fptr(file, bfound, NULL);
5afbbe0d
AM
3907+ if (bfound == btop) {
3908+ for (btop++; btop <= bbot; btop++)
3909+ if (au_hf_dir(file, btop)) {
3910+ au_set_fbtop(file, btop);
076b876e
AM
3911+ break;
3912+ }
3913+ }
3914+ fi_write_unlock(file);
3915+ }
3916+}
3917+
1facf9fc 3918+static void au_br_do_del_brp(struct au_sbinfo *sbinfo,
3919+ const aufs_bindex_t bindex,
5afbbe0d 3920+ const aufs_bindex_t bbot)
1facf9fc 3921+{
3922+ struct au_branch **brp, **p;
3923+
dece6358
AM
3924+ AuRwMustWriteLock(&sbinfo->si_rwsem);
3925+
1facf9fc 3926+ brp = sbinfo->si_branch + bindex;
5afbbe0d
AM
3927+ if (bindex < bbot)
3928+ memmove(brp, brp + 1, sizeof(*brp) * (bbot - bindex));
3929+ sbinfo->si_branch[0 + bbot] = NULL;
3930+ sbinfo->si_bbot--;
1facf9fc 3931+
e2f27e51
AM
3932+ p = au_krealloc(sbinfo->si_branch, sizeof(*p) * bbot, AuGFP_SBILIST,
3933+ /*may_shrink*/1);
1facf9fc 3934+ if (p)
3935+ sbinfo->si_branch = p;
4a4d8108 3936+ /* harmless error */
1facf9fc 3937+}
3938+
3939+static void au_br_do_del_hdp(struct au_dinfo *dinfo, const aufs_bindex_t bindex,
5afbbe0d 3940+ const aufs_bindex_t bbot)
1facf9fc 3941+{
3942+ struct au_hdentry *hdp, *p;
3943+
1308ab2a 3944+ AuRwMustWriteLock(&dinfo->di_rwsem);
3945+
5afbbe0d
AM
3946+ hdp = au_hdentry(dinfo, bindex);
3947+ if (bindex < bbot)
3948+ memmove(hdp, hdp + 1, sizeof(*hdp) * (bbot - bindex));
3949+ /* au_h_dentry_init(au_hdentry(dinfo, bbot); */
3950+ dinfo->di_bbot--;
1facf9fc 3951+
e2f27e51
AM
3952+ p = au_krealloc(dinfo->di_hdentry, sizeof(*p) * bbot, AuGFP_SBILIST,
3953+ /*may_shrink*/1);
1facf9fc 3954+ if (p)
3955+ dinfo->di_hdentry = p;
4a4d8108 3956+ /* harmless error */
1facf9fc 3957+}
3958+
3959+static void au_br_do_del_hip(struct au_iinfo *iinfo, const aufs_bindex_t bindex,
5afbbe0d 3960+ const aufs_bindex_t bbot)
1facf9fc 3961+{
3962+ struct au_hinode *hip, *p;
3963+
1308ab2a 3964+ AuRwMustWriteLock(&iinfo->ii_rwsem);
3965+
5afbbe0d
AM
3966+ hip = au_hinode(iinfo, bindex);
3967+ if (bindex < bbot)
3968+ memmove(hip, hip + 1, sizeof(*hip) * (bbot - bindex));
3969+ /* au_hinode_init(au_hinode(iinfo, bbot)); */
3970+ iinfo->ii_bbot--;
1facf9fc 3971+
e2f27e51
AM
3972+ p = au_krealloc(iinfo->ii_hinode, sizeof(*p) * bbot, AuGFP_SBILIST,
3973+ /*may_shrink*/1);
1facf9fc 3974+ if (p)
3975+ iinfo->ii_hinode = p;
4a4d8108 3976+ /* harmless error */
1facf9fc 3977+}
3978+
3979+static void au_br_do_del(struct super_block *sb, aufs_bindex_t bindex,
3980+ struct au_branch *br)
3981+{
5afbbe0d 3982+ aufs_bindex_t bbot;
1facf9fc 3983+ struct au_sbinfo *sbinfo;
53392da6
AM
3984+ struct dentry *root, *h_root;
3985+ struct inode *inode, *h_inode;
3986+ struct au_hinode *hinode;
1facf9fc 3987+
dece6358
AM
3988+ SiMustWriteLock(sb);
3989+
1facf9fc 3990+ root = sb->s_root;
5527c038 3991+ inode = d_inode(root);
1facf9fc 3992+ sbinfo = au_sbi(sb);
5afbbe0d 3993+ bbot = sbinfo->si_bbot;
1facf9fc 3994+
53392da6
AM
3995+ h_root = au_h_dptr(root, bindex);
3996+ hinode = au_hi(inode, bindex);
3997+ h_inode = au_igrab(hinode->hi_inode);
3998+ au_hiput(hinode);
1facf9fc 3999+
53392da6 4000+ au_sbilist_lock();
5afbbe0d
AM
4001+ au_br_do_del_brp(sbinfo, bindex, bbot);
4002+ au_br_do_del_hdp(au_di(root), bindex, bbot);
4003+ au_br_do_del_hip(au_ii(inode), bindex, bbot);
53392da6
AM
4004+ au_sbilist_unlock();
4005+
8b6a4947
AM
4006+ /* ignore an error */
4007+ au_dr_br_fin(sb, br); /* always, regardless the mount option */
4008+
53392da6
AM
4009+ dput(h_root);
4010+ iput(h_inode);
4011+ au_br_do_free(br);
1facf9fc 4012+}
4013+
79b8bda9
AM
4014+static unsigned long long empty_cb(struct super_block *sb, void *array,
4015+ unsigned long long max, void *arg)
076b876e
AM
4016+{
4017+ return max;
4018+}
4019+
1facf9fc 4020+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount)
4021+{
4022+ int err, rerr, i;
076b876e 4023+ unsigned long long opened;
1facf9fc 4024+ unsigned int mnt_flags;
5afbbe0d 4025+ aufs_bindex_t bindex, bbot, br_id;
1facf9fc 4026+ unsigned char do_wh, verbose;
4027+ struct au_branch *br;
4028+ struct au_wbr *wbr;
076b876e
AM
4029+ struct dentry *root;
4030+ struct file **to_free;
1facf9fc 4031+
4032+ err = 0;
076b876e
AM
4033+ opened = 0;
4034+ to_free = NULL;
4035+ root = sb->s_root;
4036+ bindex = au_find_dbindex(root, del->h_path.dentry);
1facf9fc 4037+ if (bindex < 0) {
4038+ if (remount)
4039+ goto out; /* success */
4040+ err = -ENOENT;
4a4d8108 4041+ pr_err("%s no such branch\n", del->pathname);
1facf9fc 4042+ goto out;
4043+ }
4044+ AuDbg("bindex b%d\n", bindex);
4045+
4046+ err = -EBUSY;
4047+ mnt_flags = au_mntflags(sb);
4048+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
5afbbe0d
AM
4049+ bbot = au_sbbot(sb);
4050+ if (unlikely(!bbot)) {
1facf9fc 4051+ AuVerbose(verbose, "no more branches left\n");
4052+ goto out;
4053+ }
acd2b654 4054+
1facf9fc 4055+ br = au_sbr(sb, bindex);
86dc4139 4056+ AuDebugOn(!path_equal(&br->br_path, &del->h_path));
acd2b654
AM
4057+ if (unlikely(au_lcnt_read(&br->br_count, /*do_rev*/1))) {
4058+ AuVerbose(verbose, "br %pd2 is busy now\n", del->h_path.dentry);
4059+ goto out;
4060+ }
076b876e
AM
4061+
4062+ br_id = br->br_id;
acd2b654 4063+ opened = au_lcnt_read(&br->br_nfiles, /*do_rev*/1);
076b876e 4064+ if (unlikely(opened)) {
79b8bda9 4065+ to_free = au_array_alloc(&opened, empty_cb, sb, NULL);
076b876e
AM
4066+ err = PTR_ERR(to_free);
4067+ if (IS_ERR(to_free))
4068+ goto out;
4069+
4070+ err = test_file_busy(sb, br_id, to_free, opened);
4071+ if (unlikely(err)) {
4072+ AuVerbose(verbose, "%llu file(s) opened\n", opened);
4073+ goto out;
4074+ }
1facf9fc 4075+ }
4076+
4077+ wbr = br->br_wbr;
4078+ do_wh = wbr && (wbr->wbr_whbase || wbr->wbr_plink || wbr->wbr_orph);
4079+ if (do_wh) {
1308ab2a 4080+ /* instead of WbrWhMustWriteLock(wbr) */
4081+ SiMustWriteLock(sb);
1facf9fc 4082+ for (i = 0; i < AuBrWh_Last; i++) {
4083+ dput(wbr->wbr_wh[i]);
4084+ wbr->wbr_wh[i] = NULL;
4085+ }
4086+ }
4087+
076b876e 4088+ err = test_children_busy(root, bindex, verbose);
1facf9fc 4089+ if (unlikely(err)) {
4090+ if (do_wh)
4091+ goto out_wh;
4092+ goto out;
4093+ }
4094+
4095+ err = 0;
076b876e
AM
4096+ if (to_free) {
4097+ /*
4098+ * now we confirmed the branch is deletable.
4099+ * let's free the remaining opened dirs on the branch.
4100+ */
4101+ di_write_unlock(root);
4102+ br_del_file(to_free, opened, br_id);
4103+ di_write_lock_child(root);
4104+ }
4105+
062440b3
AM
4106+ sysaufs_brs_del(sb, bindex); /* remove successors */
4107+ dbgaufs_xino_del(br); /* remove one */
4108+ au_br_do_del(sb, bindex, br);
4109+ sysaufs_brs_add(sb, bindex); /* append successors */
4110+ dbgaufs_brs_add(sb, bindex, /*topdown*/1); /* rename successors */
1facf9fc 4111+
1308ab2a 4112+ if (!bindex) {
5527c038 4113+ au_cpup_attr_all(d_inode(root), /*force*/1);
1308ab2a 4114+ sb->s_maxbytes = au_sbr_sb(sb, 0)->s_maxbytes;
4115+ } else
5527c038 4116+ au_sub_nlink(d_inode(root), d_inode(del->h_path.dentry));
1facf9fc 4117+ if (au_opt_test(mnt_flags, PLINK))
4118+ au_plink_half_refresh(sb, br_id);
4119+
1facf9fc 4120+ goto out; /* success */
4121+
4f0767ce 4122+out_wh:
1facf9fc 4123+ /* revert */
86dc4139 4124+ rerr = au_br_init_wh(sb, br, br->br_perm);
1facf9fc 4125+ if (rerr)
0c3ec466
AM
4126+ pr_warn("failed re-creating base whiteout, %s. (%d)\n",
4127+ del->pathname, rerr);
4f0767ce 4128+out:
076b876e
AM
4129+ if (to_free)
4130+ au_farray_free(to_free, opened);
1facf9fc 4131+ return err;
4132+}
4133+
4134+/* ---------------------------------------------------------------------- */
4135+
027c5e7a
AM
4136+static int au_ibusy(struct super_block *sb, struct aufs_ibusy __user *arg)
4137+{
4138+ int err;
5afbbe0d 4139+ aufs_bindex_t btop, bbot;
027c5e7a
AM
4140+ struct aufs_ibusy ibusy;
4141+ struct inode *inode, *h_inode;
4142+
4143+ err = -EPERM;
4144+ if (unlikely(!capable(CAP_SYS_ADMIN)))
4145+ goto out;
4146+
4147+ err = copy_from_user(&ibusy, arg, sizeof(ibusy));
4148+ if (!err)
ba1aed25
AM
4149+ /* VERIFY_WRITE */
4150+ err = !access_ok(&arg->h_ino, sizeof(arg->h_ino));
027c5e7a
AM
4151+ if (unlikely(err)) {
4152+ err = -EFAULT;
4153+ AuTraceErr(err);
4154+ goto out;
4155+ }
4156+
4157+ err = -EINVAL;
4158+ si_read_lock(sb, AuLock_FLUSH);
5afbbe0d 4159+ if (unlikely(ibusy.bindex < 0 || ibusy.bindex > au_sbbot(sb)))
027c5e7a
AM
4160+ goto out_unlock;
4161+
4162+ err = 0;
4163+ ibusy.h_ino = 0; /* invalid */
4164+ inode = ilookup(sb, ibusy.ino);
4165+ if (!inode
4166+ || inode->i_ino == AUFS_ROOT_INO
5afbbe0d 4167+ || au_is_bad_inode(inode))
027c5e7a
AM
4168+ goto out_unlock;
4169+
4170+ ii_read_lock_child(inode);
5afbbe0d
AM
4171+ btop = au_ibtop(inode);
4172+ bbot = au_ibbot(inode);
4173+ if (btop <= ibusy.bindex && ibusy.bindex <= bbot) {
027c5e7a 4174+ h_inode = au_h_iptr(inode, ibusy.bindex);
5afbbe0d 4175+ if (h_inode && au_test_ibusy(inode, btop, bbot))
027c5e7a
AM
4176+ ibusy.h_ino = h_inode->i_ino;
4177+ }
4178+ ii_read_unlock(inode);
4179+ iput(inode);
4180+
4181+out_unlock:
4182+ si_read_unlock(sb);
4183+ if (!err) {
4184+ err = __put_user(ibusy.h_ino, &arg->h_ino);
4185+ if (unlikely(err)) {
4186+ err = -EFAULT;
4187+ AuTraceErr(err);
4188+ }
4189+ }
4190+out:
4191+ return err;
4192+}
4193+
4194+long au_ibusy_ioctl(struct file *file, unsigned long arg)
4195+{
2000de60 4196+ return au_ibusy(file->f_path.dentry->d_sb, (void __user *)arg);
027c5e7a
AM
4197+}
4198+
4199+#ifdef CONFIG_COMPAT
4200+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg)
4201+{
2000de60 4202+ return au_ibusy(file->f_path.dentry->d_sb, compat_ptr(arg));
027c5e7a
AM
4203+}
4204+#endif
4205+
4206+/* ---------------------------------------------------------------------- */
4207+
1facf9fc 4208+/*
4209+ * change a branch permission
4210+ */
4211+
dece6358
AM
4212+static void au_warn_ima(void)
4213+{
4214+#ifdef CONFIG_IMA
1308ab2a 4215+ /* since it doesn't support mark_files_ro() */
027c5e7a 4216+ AuWarn1("RW -> RO makes IMA to produce wrong message\n");
dece6358
AM
4217+#endif
4218+}
4219+
1facf9fc 4220+static int do_need_sigen_inc(int a, int b)
4221+{
4222+ return au_br_whable(a) && !au_br_whable(b);
4223+}
4224+
4225+static int need_sigen_inc(int old, int new)
4226+{
4227+ return do_need_sigen_inc(old, new)
4228+ || do_need_sigen_inc(new, old);
4229+}
4230+
4231+static int au_br_mod_files_ro(struct super_block *sb, aufs_bindex_t bindex)
4232+{
7f207e10 4233+ int err, do_warn;
027c5e7a 4234+ unsigned int mnt_flags;
7f207e10 4235+ unsigned long long ull, max;
e49829fe 4236+ aufs_bindex_t br_id;
38d290e6 4237+ unsigned char verbose, writer;
7f207e10 4238+ struct file *file, *hf, **array;
e49829fe 4239+ struct au_hfile *hfile;
eca34b5c 4240+ struct inode *h_inode;
1facf9fc 4241+
027c5e7a
AM
4242+ mnt_flags = au_mntflags(sb);
4243+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
4244+
7f207e10
AM
4245+ array = au_farray_alloc(sb, &max);
4246+ err = PTR_ERR(array);
4247+ if (IS_ERR(array))
1facf9fc 4248+ goto out;
4249+
7f207e10 4250+ do_warn = 0;
e49829fe 4251+ br_id = au_sbr_id(sb, bindex);
7f207e10
AM
4252+ for (ull = 0; ull < max; ull++) {
4253+ file = array[ull];
076b876e
AM
4254+ if (unlikely(!file))
4255+ break;
1facf9fc 4256+
523b37e3 4257+ /* AuDbg("%pD\n", file); */
1facf9fc 4258+ fi_read_lock(file);
4259+ if (unlikely(au_test_mmapped(file))) {
4260+ err = -EBUSY;
523b37e3 4261+ AuVerbose(verbose, "mmapped %pD\n", file);
7f207e10 4262+ AuDbgFile(file);
1facf9fc 4263+ FiMustNoWaiters(file);
4264+ fi_read_unlock(file);
7f207e10 4265+ goto out_array;
1facf9fc 4266+ }
4267+
e49829fe
JR
4268+ hfile = &au_fi(file)->fi_htop;
4269+ hf = hfile->hf_file;
7e9cd9fe 4270+ if (!d_is_reg(file->f_path.dentry)
1facf9fc 4271+ || !(file->f_mode & FMODE_WRITE)
e49829fe 4272+ || hfile->hf_br->br_id != br_id
7f207e10
AM
4273+ || !(hf->f_mode & FMODE_WRITE))
4274+ array[ull] = NULL;
4275+ else {
4276+ do_warn = 1;
4277+ get_file(file);
1facf9fc 4278+ }
4279+
1facf9fc 4280+ FiMustNoWaiters(file);
4281+ fi_read_unlock(file);
7f207e10
AM
4282+ fput(file);
4283+ }
1facf9fc 4284+
4285+ err = 0;
7f207e10 4286+ if (do_warn)
dece6358 4287+ au_warn_ima();
7f207e10
AM
4288+
4289+ for (ull = 0; ull < max; ull++) {
4290+ file = array[ull];
4291+ if (!file)
4292+ continue;
4293+
1facf9fc 4294+ /* todo: already flushed? */
523b37e3
AM
4295+ /*
4296+ * fs/super.c:mark_files_ro() is gone, but aufs keeps its
4297+ * approach which resets f_mode and calls mnt_drop_write() and
4298+ * file_release_write() for each file, because the branch
4299+ * attribute in aufs world is totally different from the native
4300+ * fs rw/ro mode.
4301+ */
7f207e10
AM
4302+ /* fi_read_lock(file); */
4303+ hfile = &au_fi(file)->fi_htop;
4304+ hf = hfile->hf_file;
4305+ /* fi_read_unlock(file); */
027c5e7a 4306+ spin_lock(&hf->f_lock);
38d290e6
JR
4307+ writer = !!(hf->f_mode & FMODE_WRITER);
4308+ hf->f_mode &= ~(FMODE_WRITE | FMODE_WRITER);
027c5e7a 4309+ spin_unlock(&hf->f_lock);
38d290e6 4310+ if (writer) {
eca34b5c
AM
4311+ h_inode = file_inode(hf);
4312+ put_write_access(h_inode);
c06a8ce3 4313+ __mnt_drop_write(hf->f_path.mnt);
eca34b5c
AM
4314+ if ((hf->f_mode & (FMODE_READ | FMODE_WRITE))
4315+ == FMODE_READ)
4316+ i_readcount_inc(h_inode);
1facf9fc 4317+ }
4318+ }
4319+
7f207e10
AM
4320+out_array:
4321+ au_farray_free(array, max);
4f0767ce 4322+out:
7f207e10 4323+ AuTraceErr(err);
1facf9fc 4324+ return err;
4325+}
4326+
4327+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 4328+ int *do_refresh)
1facf9fc 4329+{
4330+ int err, rerr;
4331+ aufs_bindex_t bindex;
4332+ struct dentry *root;
4333+ struct au_branch *br;
076b876e 4334+ struct au_br_fhsm *bf;
1facf9fc 4335+
4336+ root = sb->s_root;
1facf9fc 4337+ bindex = au_find_dbindex(root, mod->h_root);
4338+ if (bindex < 0) {
4339+ if (remount)
4340+ return 0; /* success */
4341+ err = -ENOENT;
4a4d8108 4342+ pr_err("%s no such branch\n", mod->path);
1facf9fc 4343+ goto out;
4344+ }
4345+ AuDbg("bindex b%d\n", bindex);
4346+
5527c038 4347+ err = test_br(d_inode(mod->h_root), mod->perm, mod->path);
1facf9fc 4348+ if (unlikely(err))
4349+ goto out;
4350+
4351+ br = au_sbr(sb, bindex);
86dc4139 4352+ AuDebugOn(mod->h_root != au_br_dentry(br));
1facf9fc 4353+ if (br->br_perm == mod->perm)
4354+ return 0; /* success */
4355+
076b876e
AM
4356+ /* pre-allocate for non-fhsm --> fhsm */
4357+ bf = NULL;
4358+ if (!au_br_fhsm(br->br_perm) && au_br_fhsm(mod->perm)) {
4359+ err = au_fhsm_br_alloc(br);
4360+ if (unlikely(err))
4361+ goto out;
4362+ bf = br->br_fhsm;
4363+ br->br_fhsm = NULL;
4364+ }
4365+
1facf9fc 4366+ if (au_br_writable(br->br_perm)) {
4367+ /* remove whiteout base */
86dc4139 4368+ err = au_br_init_wh(sb, br, mod->perm);
1facf9fc 4369+ if (unlikely(err))
076b876e 4370+ goto out_bf;
1facf9fc 4371+
4372+ if (!au_br_writable(mod->perm)) {
4373+ /* rw --> ro, file might be mmapped */
4374+ DiMustNoWaiters(root);
5527c038 4375+ IiMustNoWaiters(d_inode(root));
1facf9fc 4376+ di_write_unlock(root);
4377+ err = au_br_mod_files_ro(sb, bindex);
4378+ /* aufs_write_lock() calls ..._child() */
4379+ di_write_lock_child(root);
4380+
4381+ if (unlikely(err)) {
4382+ rerr = -ENOMEM;
be52b249 4383+ br->br_wbr = kzalloc(sizeof(*br->br_wbr),
1facf9fc 4384+ GFP_NOFS);
86dc4139
AM
4385+ if (br->br_wbr)
4386+ rerr = au_wbr_init(br, sb, br->br_perm);
1facf9fc 4387+ if (unlikely(rerr)) {
4388+ AuIOErr("nested error %d (%d)\n",
4389+ rerr, err);
4390+ br->br_perm = mod->perm;
4391+ }
4392+ }
4393+ }
4394+ } else if (au_br_writable(mod->perm)) {
4395+ /* ro --> rw */
4396+ err = -ENOMEM;
be52b249 4397+ br->br_wbr = kzalloc(sizeof(*br->br_wbr), GFP_NOFS);
1facf9fc 4398+ if (br->br_wbr) {
86dc4139 4399+ err = au_wbr_init(br, sb, mod->perm);
1facf9fc 4400+ if (unlikely(err)) {
9f237c51 4401+ au_kfree_rcu(br->br_wbr);
1facf9fc 4402+ br->br_wbr = NULL;
4403+ }
4404+ }
4405+ }
076b876e
AM
4406+ if (unlikely(err))
4407+ goto out_bf;
4408+
4409+ if (au_br_fhsm(br->br_perm)) {
4410+ if (!au_br_fhsm(mod->perm)) {
4411+ /* fhsm --> non-fhsm */
4412+ au_br_fhsm_fin(br->br_fhsm);
9f237c51 4413+ au_kfree_rcu(br->br_fhsm);
076b876e
AM
4414+ br->br_fhsm = NULL;
4415+ }
4416+ } else if (au_br_fhsm(mod->perm))
4417+ /* non-fhsm --> fhsm */
4418+ br->br_fhsm = bf;
4419+
076b876e
AM
4420+ *do_refresh |= need_sigen_inc(br->br_perm, mod->perm);
4421+ br->br_perm = mod->perm;
4422+ goto out; /* success */
1facf9fc 4423+
076b876e 4424+out_bf:
9f237c51 4425+ au_kfree_try_rcu(bf);
076b876e
AM
4426+out:
4427+ AuTraceErr(err);
4428+ return err;
4429+}
4430+
4431+/* ---------------------------------------------------------------------- */
4432+
4433+int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs)
4434+{
4435+ int err;
4436+ struct kstatfs kstfs;
4437+
4438+ err = vfs_statfs(&br->br_path, &kstfs);
1facf9fc 4439+ if (!err) {
076b876e
AM
4440+ stfs->f_blocks = kstfs.f_blocks;
4441+ stfs->f_bavail = kstfs.f_bavail;
4442+ stfs->f_files = kstfs.f_files;
4443+ stfs->f_ffree = kstfs.f_ffree;
1facf9fc 4444+ }
4445+
1facf9fc 4446+ return err;
4447+}
7f207e10 4448diff -urN /usr/share/empty/fs/aufs/branch.h linux/fs/aufs/branch.h
eca34b5c 4449--- /usr/share/empty/fs/aufs/branch.h 1970-01-01 01:00:00.000000000 +0100
016522bc 4450+++ linux/fs/aufs/branch.h 2020-01-27 10:57:18.165538015 +0100
83b672a5 4451@@ -0,0 +1,366 @@
062440b3 4452+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 4453+/*
016522bc 4454+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 4455+ *
4456+ * This program, aufs is free software; you can redistribute it and/or modify
4457+ * it under the terms of the GNU General Public License as published by
4458+ * the Free Software Foundation; either version 2 of the License, or
4459+ * (at your option) any later version.
dece6358
AM
4460+ *
4461+ * This program is distributed in the hope that it will be useful,
4462+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4463+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4464+ * GNU General Public License for more details.
4465+ *
4466+ * You should have received a copy of the GNU General Public License
523b37e3 4467+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 4468+ */
4469+
4470+/*
4471+ * branch filesystems and xino for them
4472+ */
4473+
4474+#ifndef __AUFS_BRANCH_H__
4475+#define __AUFS_BRANCH_H__
4476+
4477+#ifdef __KERNEL__
4478+
1facf9fc 4479+#include <linux/mount.h>
8b6a4947 4480+#include "dirren.h"
4a4d8108 4481+#include "dynop.h"
acd2b654 4482+#include "lcnt.h"
1facf9fc 4483+#include "rwsem.h"
4484+#include "super.h"
4485+
4486+/* ---------------------------------------------------------------------- */
4487+
4488+/* a xino file */
062440b3 4489+struct au_xino {
acd2b654
AM
4490+ struct file **xi_file;
4491+ unsigned int xi_nfile;
4492+
521ced18
JR
4493+ struct {
4494+ spinlock_t spin;
4495+ ino_t *array;
4496+ int total;
4497+ /* reserved for future use */
4498+ /* unsigned long *bitmap; */
4499+ wait_queue_head_t wqh;
4500+ } xi_nondir;
1facf9fc 4501+
acd2b654 4502+ struct mutex xi_mtx; /* protects xi_file array */
9f237c51 4503+ struct hlist_bl_head xi_writing;
acd2b654 4504+
062440b3 4505+ atomic_t xi_truncating;
1facf9fc 4506+
062440b3 4507+ struct kref xi_kref;
1facf9fc 4508+};
4509+
076b876e
AM
4510+/* File-based Hierarchical Storage Management */
4511+struct au_br_fhsm {
4512+#ifdef CONFIG_AUFS_FHSM
4513+ struct mutex bf_lock;
4514+ unsigned long bf_jiffy;
4515+ struct aufs_stfs bf_stfs;
4516+ int bf_readable;
4517+#endif
4518+};
4519+
1facf9fc 4520+/* members for writable branch only */
4521+enum {AuBrWh_BASE, AuBrWh_PLINK, AuBrWh_ORPH, AuBrWh_Last};
4522+struct au_wbr {
dece6358 4523+ struct au_rwsem wbr_wh_rwsem;
1facf9fc 4524+ struct dentry *wbr_wh[AuBrWh_Last];
4a4d8108 4525+ atomic_t wbr_wh_running;
1facf9fc 4526+#define wbr_whbase wbr_wh[AuBrWh_BASE] /* whiteout base */
4527+#define wbr_plink wbr_wh[AuBrWh_PLINK] /* pseudo-link dir */
4528+#define wbr_orph wbr_wh[AuBrWh_ORPH] /* dir for orphans */
4529+
4530+ /* mfs mode */
4531+ unsigned long long wbr_bytes;
4532+};
4533+
4a4d8108
AM
4534+/* ext2 has 3 types of operations at least, ext3 has 4 */
4535+#define AuBrDynOp (AuDyLast * 4)
4536+
1716fcea
AM
4537+#ifdef CONFIG_AUFS_HFSNOTIFY
4538+/* support for asynchronous destruction */
4539+struct au_br_hfsnotify {
4540+ struct fsnotify_group *hfsn_group;
4541+};
4542+#endif
4543+
392086de
AM
4544+/* sysfs entries */
4545+struct au_brsysfs {
4546+ char name[16];
4547+ struct attribute attr;
4548+};
4549+
4550+enum {
4551+ AuBrSysfs_BR,
4552+ AuBrSysfs_BRID,
4553+ AuBrSysfs_Last
4554+};
4555+
1facf9fc 4556+/* protected by superblock rwsem */
4557+struct au_branch {
062440b3 4558+ struct au_xino *br_xino;
1facf9fc 4559+
4560+ aufs_bindex_t br_id;
4561+
4562+ int br_perm;
86dc4139 4563+ struct path br_path;
4a4d8108
AM
4564+ spinlock_t br_dykey_lock;
4565+ struct au_dykey *br_dykey[AuBrDynOp];
acd2b654
AM
4566+ au_lcnt_t br_nfiles; /* opened files */
4567+ au_lcnt_t br_count; /* in-use for other */
1facf9fc 4568+
4569+ struct au_wbr *br_wbr;
076b876e 4570+ struct au_br_fhsm *br_fhsm;
1facf9fc 4571+
027c5e7a 4572+#ifdef CONFIG_AUFS_HFSNOTIFY
1716fcea 4573+ struct au_br_hfsnotify *br_hfsn;
027c5e7a
AM
4574+#endif
4575+
1facf9fc 4576+#ifdef CONFIG_SYSFS
392086de
AM
4577+ /* entries under sysfs per mount-point */
4578+ struct au_brsysfs br_sysfs[AuBrSysfs_Last];
1facf9fc 4579+#endif
8b6a4947 4580+
062440b3
AM
4581+#ifdef CONFIG_DEBUG_FS
4582+ struct dentry *br_dbgaufs; /* xino */
4583+#endif
4584+
8b6a4947 4585+ struct au_dr_br br_dirren;
1facf9fc 4586+};
4587+
4588+/* ---------------------------------------------------------------------- */
4589+
86dc4139
AM
4590+static inline struct vfsmount *au_br_mnt(struct au_branch *br)
4591+{
4592+ return br->br_path.mnt;
4593+}
4594+
4595+static inline struct dentry *au_br_dentry(struct au_branch *br)
4596+{
4597+ return br->br_path.dentry;
4598+}
4599+
4600+static inline struct super_block *au_br_sb(struct au_branch *br)
4601+{
4602+ return au_br_mnt(br)->mnt_sb;
4603+}
4604+
1facf9fc 4605+static inline int au_br_rdonly(struct au_branch *br)
4606+{
8b6a4947 4607+ return (sb_rdonly(au_br_sb(br))
1facf9fc 4608+ || !au_br_writable(br->br_perm))
4609+ ? -EROFS : 0;
4610+}
4611+
4a4d8108 4612+static inline int au_br_hnotifyable(int brperm __maybe_unused)
1facf9fc 4613+{
4a4d8108 4614+#ifdef CONFIG_AUFS_HNOTIFY
1e00d052 4615+ return !(brperm & AuBrPerm_RR);
1facf9fc 4616+#else
4617+ return 0;
4618+#endif
4619+}
4620+
b912730e
AM
4621+static inline int au_br_test_oflag(int oflag, struct au_branch *br)
4622+{
4623+ int err, exec_flag;
4624+
4625+ err = 0;
4626+ exec_flag = oflag & __FMODE_EXEC;
79b8bda9 4627+ if (unlikely(exec_flag && path_noexec(&br->br_path)))
b912730e
AM
4628+ err = -EACCES;
4629+
4630+ return err;
4631+}
4632+
062440b3
AM
4633+static inline void au_xino_get(struct au_branch *br)
4634+{
4635+ struct au_xino *xi;
4636+
4637+ xi = br->br_xino;
4638+ if (xi)
4639+ kref_get(&xi->xi_kref);
4640+}
4641+
4642+static inline int au_xino_count(struct au_branch *br)
4643+{
4644+ int v;
4645+ struct au_xino *xi;
4646+
4647+ v = 0;
4648+ xi = br->br_xino;
4649+ if (xi)
4650+ v = kref_read(&xi->xi_kref);
4651+
4652+ return v;
4653+}
4654+
1facf9fc 4655+/* ---------------------------------------------------------------------- */
4656+
4657+/* branch.c */
4658+struct au_sbinfo;
4659+void au_br_free(struct au_sbinfo *sinfo);
4660+int au_br_index(struct super_block *sb, aufs_bindex_t br_id);
4661+struct au_opt_add;
4662+int au_br_add(struct super_block *sb, struct au_opt_add *add, int remount);
4663+struct au_opt_del;
4664+int au_br_del(struct super_block *sb, struct au_opt_del *del, int remount);
027c5e7a
AM
4665+long au_ibusy_ioctl(struct file *file, unsigned long arg);
4666+#ifdef CONFIG_COMPAT
4667+long au_ibusy_compat_ioctl(struct file *file, unsigned long arg);
4668+#endif
1facf9fc 4669+struct au_opt_mod;
4670+int au_br_mod(struct super_block *sb, struct au_opt_mod *mod, int remount,
7f207e10 4671+ int *do_refresh);
076b876e
AM
4672+struct aufs_stfs;
4673+int au_br_stfs(struct au_branch *br, struct aufs_stfs *stfs);
1facf9fc 4674+
4675+/* xino.c */
4676+static const loff_t au_loff_max = LLONG_MAX;
4677+
acd2b654 4678+aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry);
83b672a5
AM
4679+struct file *au_xino_create(struct super_block *sb, char *fpath, int silent,
4680+ int wbrtop);
062440b3
AM
4681+struct file *au_xino_create2(struct super_block *sb, struct path *base,
4682+ struct file *copy_src);
acd2b654
AM
4683+struct au_xi_new {
4684+ struct au_xino *xi; /* switch between xino and xigen */
4685+ int idx;
4686+ struct path *base;
4687+ struct file *copy_src;
4688+};
4689+struct file *au_xi_new(struct super_block *sb, struct au_xi_new *xinew);
062440b3
AM
4690+
4691+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
4692+ ino_t *ino);
4693+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
4694+ ino_t ino);
5527c038 4695+ssize_t xino_fread(vfs_readf_t func, struct file *file, void *buf, size_t size,
1facf9fc 4696+ loff_t *pos);
5527c038
JR
4697+ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf,
4698+ size_t size, loff_t *pos);
062440b3
AM
4699+
4700+int au_xib_trunc(struct super_block *sb);
acd2b654 4701+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin);
1facf9fc 4702+
acd2b654 4703+struct au_xino *au_xino_alloc(unsigned int nfile);
062440b3 4704+int au_xino_put(struct au_branch *br);
acd2b654 4705+struct file *au_xino_file1(struct au_xino *xi);
062440b3 4706+
1facf9fc 4707+struct au_opt_xino;
1facf9fc 4708+void au_xino_clr(struct super_block *sb);
062440b3 4709+int au_xino_set(struct super_block *sb, struct au_opt_xino *xiopt, int remount);
1facf9fc 4710+struct file *au_xino_def(struct super_block *sb);
062440b3
AM
4711+int au_xino_init_br(struct super_block *sb, struct au_branch *br, ino_t hino,
4712+ struct path *base);
4713+
4714+ino_t au_xino_new_ino(struct super_block *sb);
4715+void au_xino_delete_inode(struct inode *inode, const int unlinked);
1facf9fc 4716+
521ced18
JR
4717+void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex,
4718+ ino_t h_ino, int idx);
4719+int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
4720+ int *idx);
4721+
062440b3
AM
4722+int au_xino_path(struct seq_file *seq, struct file *file);
4723+
1facf9fc 4724+/* ---------------------------------------------------------------------- */
4725+
acd2b654
AM
4726+/* @idx is signed to accept -1 meaning the first file */
4727+static inline struct file *au_xino_file(struct au_xino *xi, int idx)
4728+{
4729+ struct file *file;
4730+
4731+ file = NULL;
4732+ if (!xi)
4733+ goto out;
4734+
4735+ if (idx >= 0) {
4736+ if (idx < xi->xi_nfile)
4737+ file = xi->xi_file[idx];
4738+ } else
4739+ file = au_xino_file1(xi);
4740+
4741+out:
4742+ return file;
4743+}
4744+
4745+/* ---------------------------------------------------------------------- */
4746+
1facf9fc 4747+/* Superblock to branch */
4748+static inline
4749+aufs_bindex_t au_sbr_id(struct super_block *sb, aufs_bindex_t bindex)
4750+{
4751+ return au_sbr(sb, bindex)->br_id;
4752+}
4753+
4754+static inline
4755+struct vfsmount *au_sbr_mnt(struct super_block *sb, aufs_bindex_t bindex)
4756+{
86dc4139 4757+ return au_br_mnt(au_sbr(sb, bindex));
1facf9fc 4758+}
4759+
4760+static inline
4761+struct super_block *au_sbr_sb(struct super_block *sb, aufs_bindex_t bindex)
4762+{
86dc4139 4763+ return au_br_sb(au_sbr(sb, bindex));
1facf9fc 4764+}
4765+
1facf9fc 4766+static inline int au_sbr_perm(struct super_block *sb, aufs_bindex_t bindex)
4767+{
4768+ return au_sbr(sb, bindex)->br_perm;
4769+}
4770+
4771+static inline int au_sbr_whable(struct super_block *sb, aufs_bindex_t bindex)
4772+{
4773+ return au_br_whable(au_sbr_perm(sb, bindex));
4774+}
4775+
4776+/* ---------------------------------------------------------------------- */
4777+
8b6a4947
AM
4778+#define wbr_wh_read_lock(wbr) au_rw_read_lock(&(wbr)->wbr_wh_rwsem)
4779+#define wbr_wh_write_lock(wbr) au_rw_write_lock(&(wbr)->wbr_wh_rwsem)
4780+#define wbr_wh_read_trylock(wbr) au_rw_read_trylock(&(wbr)->wbr_wh_rwsem)
4781+#define wbr_wh_write_trylock(wbr) au_rw_write_trylock(&(wbr)->wbr_wh_rwsem)
1facf9fc 4782+/*
8b6a4947
AM
4783+#define wbr_wh_read_trylock_nested(wbr) \
4784+ au_rw_read_trylock_nested(&(wbr)->wbr_wh_rwsem)
4785+#define wbr_wh_write_trylock_nested(wbr) \
4786+ au_rw_write_trylock_nested(&(wbr)->wbr_wh_rwsem)
4787+*/
1facf9fc 4788+
8b6a4947
AM
4789+#define wbr_wh_read_unlock(wbr) au_rw_read_unlock(&(wbr)->wbr_wh_rwsem)
4790+#define wbr_wh_write_unlock(wbr) au_rw_write_unlock(&(wbr)->wbr_wh_rwsem)
4791+#define wbr_wh_downgrade_lock(wbr) au_rw_dgrade_lock(&(wbr)->wbr_wh_rwsem)
4792+
4793+#define WbrWhMustNoWaiters(wbr) AuRwMustNoWaiters(&(wbr)->wbr_wh_rwsem)
4794+#define WbrWhMustAnyLock(wbr) AuRwMustAnyLock(&(wbr)->wbr_wh_rwsem)
4795+#define WbrWhMustWriteLock(wbr) AuRwMustWriteLock(&(wbr)->wbr_wh_rwsem)
dece6358 4796+
076b876e
AM
4797+/* ---------------------------------------------------------------------- */
4798+
4799+#ifdef CONFIG_AUFS_FHSM
4800+static inline void au_br_fhsm_init(struct au_br_fhsm *brfhsm)
4801+{
4802+ mutex_init(&brfhsm->bf_lock);
4803+ brfhsm->bf_jiffy = 0;
4804+ brfhsm->bf_readable = 0;
4805+}
4806+
4807+static inline void au_br_fhsm_fin(struct au_br_fhsm *brfhsm)
4808+{
4809+ mutex_destroy(&brfhsm->bf_lock);
4810+}
4811+#else
4812+AuStubVoid(au_br_fhsm_init, struct au_br_fhsm *brfhsm)
4813+AuStubVoid(au_br_fhsm_fin, struct au_br_fhsm *brfhsm)
4814+#endif
4815+
1facf9fc 4816+#endif /* __KERNEL__ */
4817+#endif /* __AUFS_BRANCH_H__ */
7f207e10 4818diff -urN /usr/share/empty/fs/aufs/conf.mk linux/fs/aufs/conf.mk
eca34b5c
AM
4819--- /usr/share/empty/fs/aufs/conf.mk 1970-01-01 01:00:00.000000000 +0100
4820+++ linux/fs/aufs/conf.mk 2019-07-11 15:42:14.462237786 +0200
2121bcd9
AM
4821@@ -0,0 +1,40 @@
4822+# SPDX-License-Identifier: GPL-2.0
4a4d8108
AM
4823+
4824+AuConfStr = CONFIG_AUFS_FS=${CONFIG_AUFS_FS}
4825+
4826+define AuConf
4827+ifdef ${1}
4828+AuConfStr += ${1}=${${1}}
4829+endif
4830+endef
4831+
b752ccd1 4832+AuConfAll = BRANCH_MAX_127 BRANCH_MAX_511 BRANCH_MAX_1023 BRANCH_MAX_32767 \
e49829fe 4833+ SBILIST \
7f207e10 4834+ HNOTIFY HFSNOTIFY \
4a4d8108 4835+ EXPORT INO_T_64 \
c1595e42 4836+ XATTR \
076b876e 4837+ FHSM \
4a4d8108 4838+ RDU \
8b6a4947 4839+ DIRREN \
4a4d8108
AM
4840+ SHWH \
4841+ BR_RAMFS \
4842+ BR_FUSE POLL \
4843+ BR_HFSPLUS \
4844+ BDEV_LOOP \
b752ccd1
AM
4845+ DEBUG MAGIC_SYSRQ
4846+$(foreach i, ${AuConfAll}, \
4a4d8108
AM
4847+ $(eval $(call AuConf,CONFIG_AUFS_${i})))
4848+
4849+AuConfName = ${obj}/conf.str
4850+${AuConfName}.tmp: FORCE
4851+ @echo ${AuConfStr} | tr ' ' '\n' | sed -e 's/^/"/' -e 's/$$/\\n"/' > $@
4852+${AuConfName}: ${AuConfName}.tmp
4853+ @diff -q $< $@ > /dev/null 2>&1 || { \
4854+ echo ' GEN ' $@; \
4855+ cp -p $< $@; \
4856+ }
4857+FORCE:
4858+clean-files += ${AuConfName} ${AuConfName}.tmp
4859+${obj}/sysfs.o: ${AuConfName}
b752ccd1
AM
4860+
4861+-include ${srctree}/${src}/conf_priv.mk
7f207e10 4862diff -urN /usr/share/empty/fs/aufs/cpup.c linux/fs/aufs/cpup.c
eca34b5c 4863--- /usr/share/empty/fs/aufs/cpup.c 1970-01-01 01:00:00.000000000 +0100
016522bc 4864+++ linux/fs/aufs/cpup.c 2020-01-27 10:57:18.165538015 +0100
9f237c51 4865@@ -0,0 +1,1458 @@
cd7a4cd9 4866+// SPDX-License-Identifier: GPL-2.0
1facf9fc 4867+/*
016522bc 4868+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 4869+ *
4870+ * This program, aufs is free software; you can redistribute it and/or modify
4871+ * it under the terms of the GNU General Public License as published by
4872+ * the Free Software Foundation; either version 2 of the License, or
4873+ * (at your option) any later version.
dece6358
AM
4874+ *
4875+ * This program is distributed in the hope that it will be useful,
4876+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4877+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4878+ * GNU General Public License for more details.
4879+ *
4880+ * You should have received a copy of the GNU General Public License
523b37e3 4881+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 4882+ */
4883+
4884+/*
4885+ * copy-up functions, see wbr_policy.c for copy-down
4886+ */
4887+
4888+#include <linux/fs_stack.h>
dece6358 4889+#include <linux/mm.h>
8cdd5066 4890+#include <linux/task_work.h>
1facf9fc 4891+#include "aufs.h"
4892+
86dc4139 4893+void au_cpup_attr_flags(struct inode *dst, unsigned int iflags)
1facf9fc 4894+{
4895+ const unsigned int mask = S_DEAD | S_SWAPFILE | S_PRIVATE
367653fa 4896+ | S_NOATIME | S_NOCMTIME | S_AUTOMOUNT;
1facf9fc 4897+
86dc4139
AM
4898+ BUILD_BUG_ON(sizeof(iflags) != sizeof(dst->i_flags));
4899+
4900+ dst->i_flags |= iflags & ~mask;
1facf9fc 4901+ if (au_test_fs_notime(dst->i_sb))
4902+ dst->i_flags |= S_NOATIME | S_NOCMTIME;
4903+}
4904+
4905+void au_cpup_attr_timesizes(struct inode *inode)
4906+{
4907+ struct inode *h_inode;
4908+
5afbbe0d 4909+ h_inode = au_h_iptr(inode, au_ibtop(inode));
1facf9fc 4910+ fsstack_copy_attr_times(inode, h_inode);
4a4d8108 4911+ fsstack_copy_inode_size(inode, h_inode);
1facf9fc 4912+}
4913+
4914+void au_cpup_attr_nlink(struct inode *inode, int force)
4915+{
4916+ struct inode *h_inode;
4917+ struct super_block *sb;
5afbbe0d 4918+ aufs_bindex_t bindex, bbot;
1facf9fc 4919+
4920+ sb = inode->i_sb;
5afbbe0d 4921+ bindex = au_ibtop(inode);
1facf9fc 4922+ h_inode = au_h_iptr(inode, bindex);
4923+ if (!force
4924+ && !S_ISDIR(h_inode->i_mode)
4925+ && au_opt_test(au_mntflags(sb), PLINK)
4926+ && au_plink_test(inode))
4927+ return;
4928+
7eafdf33
AM
4929+ /*
4930+ * 0 can happen in revalidating.
38d290e6
JR
4931+ * h_inode->i_mutex may not be held here, but it is harmless since once
4932+ * i_nlink reaches 0, it will never become positive except O_TMPFILE
4933+ * case.
4934+ * todo: O_TMPFILE+linkat(AT_SYMLINK_FOLLOW) bypassing aufs may cause
4935+ * the incorrect link count.
7eafdf33 4936+ */
92d182d2 4937+ set_nlink(inode, h_inode->i_nlink);
1facf9fc 4938+
4939+ /*
4940+ * fewer nlink makes find(1) noisy, but larger nlink doesn't.
4941+ * it may includes whplink directory.
4942+ */
4943+ if (S_ISDIR(h_inode->i_mode)) {
5afbbe0d
AM
4944+ bbot = au_ibbot(inode);
4945+ for (bindex++; bindex <= bbot; bindex++) {
1facf9fc 4946+ h_inode = au_h_iptr(inode, bindex);
4947+ if (h_inode)
4948+ au_add_nlink(inode, h_inode);
4949+ }
4950+ }
4951+}
4952+
4953+void au_cpup_attr_changeable(struct inode *inode)
4954+{
4955+ struct inode *h_inode;
4956+
5afbbe0d 4957+ h_inode = au_h_iptr(inode, au_ibtop(inode));
1facf9fc 4958+ inode->i_mode = h_inode->i_mode;
4959+ inode->i_uid = h_inode->i_uid;
4960+ inode->i_gid = h_inode->i_gid;
4961+ au_cpup_attr_timesizes(inode);
86dc4139 4962+ au_cpup_attr_flags(inode, h_inode->i_flags);
1facf9fc 4963+}
4964+
4965+void au_cpup_igen(struct inode *inode, struct inode *h_inode)
4966+{
4967+ struct au_iinfo *iinfo = au_ii(inode);
4968+
1308ab2a 4969+ IiMustWriteLock(inode);
4970+
1facf9fc 4971+ iinfo->ii_higen = h_inode->i_generation;
4972+ iinfo->ii_hsb1 = h_inode->i_sb;
4973+}
4974+
4975+void au_cpup_attr_all(struct inode *inode, int force)
4976+{
4977+ struct inode *h_inode;
4978+
5afbbe0d 4979+ h_inode = au_h_iptr(inode, au_ibtop(inode));
1facf9fc 4980+ au_cpup_attr_changeable(inode);
4981+ if (inode->i_nlink > 0)
4982+ au_cpup_attr_nlink(inode, force);
4983+ inode->i_rdev = h_inode->i_rdev;
4984+ inode->i_blkbits = h_inode->i_blkbits;
4985+ au_cpup_igen(inode, h_inode);
4986+}
4987+
4988+/* ---------------------------------------------------------------------- */
4989+
4990+/* Note: dt_dentry and dt_h_dentry are not dget/dput-ed */
4991+
4992+/* keep the timestamps of the parent dir when cpup */
4993+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
4994+ struct path *h_path)
4995+{
4996+ struct inode *h_inode;
4997+
4998+ dt->dt_dentry = dentry;
4999+ dt->dt_h_path = *h_path;
5527c038 5000+ h_inode = d_inode(h_path->dentry);
1facf9fc 5001+ dt->dt_atime = h_inode->i_atime;
5002+ dt->dt_mtime = h_inode->i_mtime;
5003+ /* smp_mb(); */
5004+}
5005+
5006+void au_dtime_revert(struct au_dtime *dt)
5007+{
5008+ struct iattr attr;
5009+ int err;
5010+
5011+ attr.ia_atime = dt->dt_atime;
5012+ attr.ia_mtime = dt->dt_mtime;
5013+ attr.ia_valid = ATTR_FORCE | ATTR_MTIME | ATTR_MTIME_SET
5014+ | ATTR_ATIME | ATTR_ATIME_SET;
5015+
523b37e3
AM
5016+ /* no delegation since this is a directory */
5017+ err = vfsub_notify_change(&dt->dt_h_path, &attr, /*delegated*/NULL);
1facf9fc 5018+ if (unlikely(err))
0c3ec466 5019+ pr_warn("restoring timestamps failed(%d). ignored\n", err);
1facf9fc 5020+}
5021+
5022+/* ---------------------------------------------------------------------- */
5023+
86dc4139
AM
5024+/* internal use only */
5025+struct au_cpup_reg_attr {
5026+ int valid;
5027+ struct kstat st;
5028+ unsigned int iflags; /* inode->i_flags */
5029+};
5030+
1facf9fc 5031+static noinline_for_stack
86dc4139
AM
5032+int cpup_iattr(struct dentry *dst, aufs_bindex_t bindex, struct dentry *h_src,
5033+ struct au_cpup_reg_attr *h_src_attr)
1facf9fc 5034+{
c1595e42 5035+ int err, sbits, icex;
7e9cd9fe
AM
5036+ unsigned int mnt_flags;
5037+ unsigned char verbose;
1facf9fc 5038+ struct iattr ia;
5039+ struct path h_path;
1308ab2a 5040+ struct inode *h_isrc, *h_idst;
86dc4139 5041+ struct kstat *h_st;
c1595e42 5042+ struct au_branch *br;
1facf9fc 5043+
5044+ h_path.dentry = au_h_dptr(dst, bindex);
5527c038 5045+ h_idst = d_inode(h_path.dentry);
c1595e42
JR
5046+ br = au_sbr(dst->d_sb, bindex);
5047+ h_path.mnt = au_br_mnt(br);
5527c038 5048+ h_isrc = d_inode(h_src);
1308ab2a 5049+ ia.ia_valid = ATTR_FORCE | ATTR_UID | ATTR_GID
1facf9fc 5050+ | ATTR_ATIME | ATTR_MTIME
5051+ | ATTR_ATIME_SET | ATTR_MTIME_SET;
86dc4139
AM
5052+ if (h_src_attr && h_src_attr->valid) {
5053+ h_st = &h_src_attr->st;
5054+ ia.ia_uid = h_st->uid;
5055+ ia.ia_gid = h_st->gid;
5056+ ia.ia_atime = h_st->atime;
5057+ ia.ia_mtime = h_st->mtime;
5058+ if (h_idst->i_mode != h_st->mode
5059+ && !S_ISLNK(h_idst->i_mode)) {
5060+ ia.ia_valid |= ATTR_MODE;
5061+ ia.ia_mode = h_st->mode;
5062+ }
5063+ sbits = !!(h_st->mode & (S_ISUID | S_ISGID));
5064+ au_cpup_attr_flags(h_idst, h_src_attr->iflags);
5065+ } else {
5066+ ia.ia_uid = h_isrc->i_uid;
5067+ ia.ia_gid = h_isrc->i_gid;
5068+ ia.ia_atime = h_isrc->i_atime;
5069+ ia.ia_mtime = h_isrc->i_mtime;
5070+ if (h_idst->i_mode != h_isrc->i_mode
5071+ && !S_ISLNK(h_idst->i_mode)) {
5072+ ia.ia_valid |= ATTR_MODE;
5073+ ia.ia_mode = h_isrc->i_mode;
5074+ }
5075+ sbits = !!(h_isrc->i_mode & (S_ISUID | S_ISGID));
5076+ au_cpup_attr_flags(h_idst, h_isrc->i_flags);
1308ab2a 5077+ }
523b37e3
AM
5078+ /* no delegation since it is just created */
5079+ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL);
1facf9fc 5080+
5081+ /* is this nfs only? */
5082+ if (!err && sbits && au_test_nfs(h_path.dentry->d_sb)) {
5083+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
5084+ ia.ia_mode = h_isrc->i_mode;
523b37e3 5085+ err = vfsub_notify_change(&h_path, &ia, /*delegated*/NULL);
1facf9fc 5086+ }
5087+
c1595e42 5088+ icex = br->br_perm & AuBrAttr_ICEX;
7e9cd9fe
AM
5089+ if (!err) {
5090+ mnt_flags = au_mntflags(dst->d_sb);
5091+ verbose = !!au_opt_test(mnt_flags, VERBOSE);
5092+ err = au_cpup_xattr(h_path.dentry, h_src, icex, verbose);
5093+ }
c1595e42 5094+
1facf9fc 5095+ return err;
5096+}
5097+
5098+/* ---------------------------------------------------------------------- */
5099+
5100+static int au_do_copy_file(struct file *dst, struct file *src, loff_t len,
5101+ char *buf, unsigned long blksize)
5102+{
5103+ int err;
5104+ size_t sz, rbytes, wbytes;
5105+ unsigned char all_zero;
5106+ char *p, *zp;
febd17d6 5107+ struct inode *h_inode;
1facf9fc 5108+ /* reduce stack usage */
5109+ struct iattr *ia;
5110+
5111+ zp = page_address(ZERO_PAGE(0));
5112+ if (unlikely(!zp))
5113+ return -ENOMEM; /* possible? */
5114+
5115+ err = 0;
5116+ all_zero = 0;
5117+ while (len) {
5118+ AuDbg("len %lld\n", len);
5119+ sz = blksize;
5120+ if (len < blksize)
5121+ sz = len;
5122+
5123+ rbytes = 0;
5124+ /* todo: signal_pending? */
5125+ while (!rbytes || err == -EAGAIN || err == -EINTR) {
5126+ rbytes = vfsub_read_k(src, buf, sz, &src->f_pos);
5127+ err = rbytes;
5128+ }
5129+ if (unlikely(err < 0))
5130+ break;
5131+
5132+ all_zero = 0;
5133+ if (len >= rbytes && rbytes == blksize)
5134+ all_zero = !memcmp(buf, zp, rbytes);
5135+ if (!all_zero) {
5136+ wbytes = rbytes;
5137+ p = buf;
5138+ while (wbytes) {
5139+ size_t b;
5140+
5141+ b = vfsub_write_k(dst, p, wbytes, &dst->f_pos);
5142+ err = b;
5143+ /* todo: signal_pending? */
5144+ if (unlikely(err == -EAGAIN || err == -EINTR))
5145+ continue;
5146+ if (unlikely(err < 0))
5147+ break;
5148+ wbytes -= b;
5149+ p += b;
5150+ }
392086de
AM
5151+ if (unlikely(err < 0))
5152+ break;
1facf9fc 5153+ } else {
5154+ loff_t res;
5155+
5156+ AuLabel(hole);
5157+ res = vfsub_llseek(dst, rbytes, SEEK_CUR);
5158+ err = res;
5159+ if (unlikely(res < 0))
5160+ break;
5161+ }
5162+ len -= rbytes;
5163+ err = 0;
5164+ }
5165+
5166+ /* the last block may be a hole */
5167+ if (!err && all_zero) {
5168+ AuLabel(last hole);
5169+
5170+ err = 1;
2000de60 5171+ if (au_test_nfs(dst->f_path.dentry->d_sb)) {
1facf9fc 5172+ /* nfs requires this step to make last hole */
5173+ /* is this only nfs? */
5174+ do {
5175+ /* todo: signal_pending? */
5176+ err = vfsub_write_k(dst, "\0", 1, &dst->f_pos);
5177+ } while (err == -EAGAIN || err == -EINTR);
5178+ if (err == 1)
5179+ dst->f_pos--;
5180+ }
5181+
5182+ if (err == 1) {
5183+ ia = (void *)buf;
5184+ ia->ia_size = dst->f_pos;
5185+ ia->ia_valid = ATTR_SIZE | ATTR_FILE;
5186+ ia->ia_file = dst;
febd17d6
JR
5187+ h_inode = file_inode(dst);
5188+ inode_lock_nested(h_inode, AuLsc_I_CHILD2);
523b37e3
AM
5189+ /* no delegation since it is just created */
5190+ err = vfsub_notify_change(&dst->f_path, ia,
5191+ /*delegated*/NULL);
febd17d6 5192+ inode_unlock(h_inode);
1facf9fc 5193+ }
5194+ }
5195+
5196+ return err;
5197+}
5198+
5199+int au_copy_file(struct file *dst, struct file *src, loff_t len)
5200+{
5201+ int err;
5202+ unsigned long blksize;
5203+ unsigned char do_kfree;
5204+ char *buf;
9f237c51 5205+ struct super_block *h_sb;
1facf9fc 5206+
5207+ err = -ENOMEM;
9f237c51
AM
5208+ h_sb = file_inode(dst)->i_sb;
5209+ blksize = h_sb->s_blocksize;
1facf9fc 5210+ if (!blksize || PAGE_SIZE < blksize)
5211+ blksize = PAGE_SIZE;
5212+ AuDbg("blksize %lu\n", blksize);
5213+ do_kfree = (blksize != PAGE_SIZE && blksize >= sizeof(struct iattr *));
5214+ if (do_kfree)
5215+ buf = kmalloc(blksize, GFP_NOFS);
5216+ else
5217+ buf = (void *)__get_free_page(GFP_NOFS);
5218+ if (unlikely(!buf))
5219+ goto out;
5220+
5221+ if (len > (1 << 22))
5222+ AuDbg("copying a large file %lld\n", (long long)len);
5223+
5224+ src->f_pos = 0;
5225+ dst->f_pos = 0;
5226+ err = au_do_copy_file(dst, src, len, buf, blksize);
9f237c51
AM
5227+ if (do_kfree) {
5228+ AuDebugOn(!au_kfree_do_sz_test(blksize));
5229+ au_kfree_do_rcu(buf);
5230+ } else
1c60b727 5231+ free_page((unsigned long)buf);
1facf9fc 5232+
4f0767ce 5233+out:
1facf9fc 5234+ return err;
5235+}
5236+
1c60b727
AM
5237+static int au_do_copy(struct file *dst, struct file *src, loff_t len)
5238+{
5239+ int err;
5240+ struct super_block *h_src_sb;
5241+ struct inode *h_src_inode;
5242+
5243+ h_src_inode = file_inode(src);
5244+ h_src_sb = h_src_inode->i_sb;
5245+
5246+ /* XFS acquires inode_lock */
5247+ if (!au_test_xfs(h_src_sb))
5248+ err = au_copy_file(dst, src, len);
5249+ else {
3c1bdaff 5250+ inode_unlock_shared(h_src_inode);
1c60b727 5251+ err = au_copy_file(dst, src, len);
be118d29 5252+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
1c60b727
AM
5253+ }
5254+
5255+ return err;
5256+}
5257+
5258+static int au_clone_or_copy(struct file *dst, struct file *src, loff_t len)
5259+{
5260+ int err;
9f237c51 5261+ loff_t lo;
1c60b727
AM
5262+ struct super_block *h_src_sb;
5263+ struct inode *h_src_inode;
5264+
5265+ h_src_inode = file_inode(src);
5266+ h_src_sb = h_src_inode->i_sb;
5267+ if (h_src_sb != file_inode(dst)->i_sb
9f237c51 5268+ || !dst->f_op->remap_file_range) {
1c60b727
AM
5269+ err = au_do_copy(dst, src, len);
5270+ goto out;
5271+ }
5272+
5273+ if (!au_test_nfs(h_src_sb)) {
3c1bdaff 5274+ inode_unlock_shared(h_src_inode);
9f237c51 5275+ lo = vfsub_clone_file_range(src, dst, len);
be118d29 5276+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
1c60b727 5277+ } else
9f237c51
AM
5278+ lo = vfsub_clone_file_range(src, dst, len);
5279+ if (lo == len) {
5280+ err = 0;
5281+ goto out; /* success */
5282+ } else if (lo >= 0)
5283+ /* todo: possible? */
5284+ /* paritially succeeded */
5285+ AuDbg("lo %lld, len %lld. Retrying.\n", lo, len);
5286+ else if (lo != -EOPNOTSUPP) {
5287+ /* older XFS has a condition in cloning */
5288+ err = lo;
1c60b727 5289+ goto out;
9f237c51 5290+ }
1c60b727
AM
5291+
5292+ /* the backend fs on NFS may not support cloning */
5293+ err = au_do_copy(dst, src, len);
5294+
5295+out:
5296+ AuTraceErr(err);
5297+ return err;
5298+}
5299+
1facf9fc 5300+/*
5301+ * to support a sparse file which is opened with O_APPEND,
5302+ * we need to close the file.
5303+ */
c2b27bf2 5304+static int au_cp_regular(struct au_cp_generic *cpg)
1facf9fc 5305+{
5306+ int err, i;
5307+ enum { SRC, DST };
5308+ struct {
5309+ aufs_bindex_t bindex;
5310+ unsigned int flags;
5311+ struct dentry *dentry;
392086de 5312+ int force_wr;
1facf9fc 5313+ struct file *file;
1facf9fc 5314+ } *f, file[] = {
5315+ {
c2b27bf2 5316+ .bindex = cpg->bsrc,
1facf9fc 5317+ .flags = O_RDONLY | O_NOATIME | O_LARGEFILE,
1facf9fc 5318+ },
5319+ {
c2b27bf2 5320+ .bindex = cpg->bdst,
1facf9fc 5321+ .flags = O_WRONLY | O_NOATIME | O_LARGEFILE,
392086de 5322+ .force_wr = !!au_ftest_cpup(cpg->flags, RWDST),
1facf9fc 5323+ }
5324+ };
acd2b654 5325+ struct au_branch *br;
521ced18 5326+ struct super_block *sb, *h_src_sb;
e2f27e51 5327+ struct inode *h_src_inode;
8cdd5066 5328+ struct task_struct *tsk = current;
1facf9fc 5329+
5330+ /* bsrc branch can be ro/rw. */
c2b27bf2 5331+ sb = cpg->dentry->d_sb;
1facf9fc 5332+ f = file;
5333+ for (i = 0; i < 2; i++, f++) {
c2b27bf2
AM
5334+ f->dentry = au_h_dptr(cpg->dentry, f->bindex);
5335+ f->file = au_h_open(cpg->dentry, f->bindex, f->flags,
392086de 5336+ /*file*/NULL, f->force_wr);
9f237c51
AM
5337+ if (IS_ERR(f->file)) {
5338+ err = PTR_ERR(f->file);
5339+ if (i == SRC)
5340+ goto out;
5341+ else
5342+ goto out_src;
5343+ }
1facf9fc 5344+ }
5345+
5346+ /* try stopping to update while we copyup */
e2f27e51 5347+ h_src_inode = d_inode(file[SRC].dentry);
521ced18
JR
5348+ h_src_sb = h_src_inode->i_sb;
5349+ if (!au_test_nfs(h_src_sb))
e2f27e51 5350+ IMustLock(h_src_inode);
1c60b727 5351+ err = au_clone_or_copy(file[DST].file, file[SRC].file, cpg->len);
1facf9fc 5352+
8cdd5066
JR
5353+ /* i wonder if we had O_NO_DELAY_FPUT flag */
5354+ if (tsk->flags & PF_KTHREAD)
5355+ __fput_sync(file[DST].file);
5356+ else {
062440b3 5357+ /* it happened actually */
8cdd5066
JR
5358+ fput(file[DST].file);
5359+ /*
5360+ * too bad.
5361+ * we have to call both since we don't know which place the file
5362+ * was added to.
5363+ */
5364+ task_work_run();
5365+ flush_delayed_fput();
5366+ }
acd2b654
AM
5367+ br = au_sbr(sb, file[DST].bindex);
5368+ au_lcnt_dec(&br->br_nfiles);
523b37e3 5369+
4f0767ce 5370+out_src:
1facf9fc 5371+ fput(file[SRC].file);
acd2b654
AM
5372+ br = au_sbr(sb, file[SRC].bindex);
5373+ au_lcnt_dec(&br->br_nfiles);
4f0767ce 5374+out:
1facf9fc 5375+ return err;
5376+}
5377+
c2b27bf2 5378+static int au_do_cpup_regular(struct au_cp_generic *cpg,
86dc4139 5379+ struct au_cpup_reg_attr *h_src_attr)
1facf9fc 5380+{
5381+ int err, rerr;
5382+ loff_t l;
86dc4139 5383+ struct path h_path;
38d290e6 5384+ struct inode *h_src_inode, *h_dst_inode;
1facf9fc 5385+
5386+ err = 0;
5527c038 5387+ h_src_inode = au_h_iptr(d_inode(cpg->dentry), cpg->bsrc);
86dc4139 5388+ l = i_size_read(h_src_inode);
c2b27bf2
AM
5389+ if (cpg->len == -1 || l < cpg->len)
5390+ cpg->len = l;
5391+ if (cpg->len) {
86dc4139 5392+ /* try stopping to update while we are referencing */
be118d29 5393+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
c2b27bf2 5394+ au_pin_hdir_unlock(cpg->pin);
1facf9fc 5395+
c2b27bf2
AM
5396+ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bsrc);
5397+ h_path.mnt = au_sbr_mnt(cpg->dentry->d_sb, cpg->bsrc);
86dc4139 5398+ h_src_attr->iflags = h_src_inode->i_flags;
5527c038 5399+ if (!au_test_nfs(h_src_inode->i_sb))
521ced18 5400+ err = vfsub_getattr(&h_path, &h_src_attr->st);
5527c038 5401+ else {
3c1bdaff 5402+ inode_unlock_shared(h_src_inode);
521ced18 5403+ err = vfsub_getattr(&h_path, &h_src_attr->st);
be118d29 5404+ inode_lock_shared_nested(h_src_inode, AuLsc_I_CHILD);
5527c038 5405+ }
86dc4139 5406+ if (unlikely(err)) {
3c1bdaff 5407+ inode_unlock_shared(h_src_inode);
86dc4139
AM
5408+ goto out;
5409+ }
5410+ h_src_attr->valid = 1;
e2f27e51
AM
5411+ if (!au_test_nfs(h_src_inode->i_sb)) {
5412+ err = au_cp_regular(cpg);
3c1bdaff 5413+ inode_unlock_shared(h_src_inode);
e2f27e51 5414+ } else {
3c1bdaff 5415+ inode_unlock_shared(h_src_inode);
e2f27e51
AM
5416+ err = au_cp_regular(cpg);
5417+ }
c2b27bf2 5418+ rerr = au_pin_hdir_relock(cpg->pin);
86dc4139
AM
5419+ if (!err && rerr)
5420+ err = rerr;
1facf9fc 5421+ }
38d290e6
JR
5422+ if (!err && (h_src_inode->i_state & I_LINKABLE)) {
5423+ h_path.dentry = au_h_dptr(cpg->dentry, cpg->bdst);
5527c038 5424+ h_dst_inode = d_inode(h_path.dentry);
38d290e6
JR
5425+ spin_lock(&h_dst_inode->i_lock);
5426+ h_dst_inode->i_state |= I_LINKABLE;
5427+ spin_unlock(&h_dst_inode->i_lock);
5428+ }
1facf9fc 5429+
4f0767ce 5430+out:
1facf9fc 5431+ return err;
5432+}
5433+
5434+static int au_do_cpup_symlink(struct path *h_path, struct dentry *h_src,
5435+ struct inode *h_dir)
5436+{
5437+ int err, symlen;
5438+ mm_segment_t old_fs;
b752ccd1
AM
5439+ union {
5440+ char *k;
5441+ char __user *u;
5442+ } sym;
1facf9fc 5443+
5444+ err = -ENOMEM;
537831f9 5445+ sym.k = (void *)__get_free_page(GFP_NOFS);
b752ccd1 5446+ if (unlikely(!sym.k))
1facf9fc 5447+ goto out;
5448+
9dbd164d 5449+ /* unnecessary to support mmap_sem since symlink is not mmap-able */
1facf9fc 5450+ old_fs = get_fs();
5451+ set_fs(KERNEL_DS);
a2654f78 5452+ symlen = vfs_readlink(h_src, sym.u, PATH_MAX);
1facf9fc 5453+ err = symlen;
5454+ set_fs(old_fs);
5455+
5456+ if (symlen > 0) {
b752ccd1
AM
5457+ sym.k[symlen] = 0;
5458+ err = vfsub_symlink(h_dir, h_path, sym.k);
1facf9fc 5459+ }
1c60b727 5460+ free_page((unsigned long)sym.k);
1facf9fc 5461+
4f0767ce 5462+out:
1facf9fc 5463+ return err;
5464+}
5465+
8cdd5066
JR
5466+/*
5467+ * regardless 'acl' option, reset all ACL.
5468+ * All ACL will be copied up later from the original entry on the lower branch.
5469+ */
5470+static int au_reset_acl(struct inode *h_dir, struct path *h_path, umode_t mode)
5471+{
5472+ int err;
5473+ struct dentry *h_dentry;
5474+ struct inode *h_inode;
5475+
5476+ h_dentry = h_path->dentry;
5477+ h_inode = d_inode(h_dentry);
5478+ /* forget_all_cached_acls(h_inode)); */
5479+ err = vfsub_removexattr(h_dentry, XATTR_NAME_POSIX_ACL_ACCESS);
5480+ AuTraceErr(err);
5481+ if (err == -EOPNOTSUPP)
5482+ err = 0;
5483+ if (!err)
5484+ err = vfsub_acl_chmod(h_inode, mode);
5485+
5486+ AuTraceErr(err);
5487+ return err;
5488+}
5489+
5490+static int au_do_cpup_dir(struct au_cp_generic *cpg, struct dentry *dst_parent,
5491+ struct inode *h_dir, struct path *h_path)
5492+{
5493+ int err;
5494+ struct inode *dir, *inode;
5495+
5496+ err = vfsub_removexattr(h_path->dentry, XATTR_NAME_POSIX_ACL_DEFAULT);
5497+ AuTraceErr(err);
5498+ if (err == -EOPNOTSUPP)
5499+ err = 0;
5500+ if (unlikely(err))
5501+ goto out;
5502+
5503+ /*
5504+ * strange behaviour from the users view,
acd2b654 5505+ * particularly setattr case
8cdd5066
JR
5506+ */
5507+ dir = d_inode(dst_parent);
5afbbe0d 5508+ if (au_ibtop(dir) == cpg->bdst)
8cdd5066
JR
5509+ au_cpup_attr_nlink(dir, /*force*/1);
5510+ inode = d_inode(cpg->dentry);
5511+ au_cpup_attr_nlink(inode, /*force*/1);
5512+
5513+out:
5514+ return err;
5515+}
5516+
1facf9fc 5517+static noinline_for_stack
c2b27bf2 5518+int cpup_entry(struct au_cp_generic *cpg, struct dentry *dst_parent,
86dc4139 5519+ struct au_cpup_reg_attr *h_src_attr)
1facf9fc 5520+{
5521+ int err;
5522+ umode_t mode;
5523+ unsigned int mnt_flags;
076b876e 5524+ unsigned char isdir, isreg, force;
c2b27bf2 5525+ const unsigned char do_dt = !!au_ftest_cpup(cpg->flags, DTIME);
1facf9fc 5526+ struct au_dtime dt;
5527+ struct path h_path;
5528+ struct dentry *h_src, *h_dst, *h_parent;
8cdd5066 5529+ struct inode *h_inode, *h_dir;
1facf9fc 5530+ struct super_block *sb;
5531+
5532+ /* bsrc branch can be ro/rw. */
c2b27bf2 5533+ h_src = au_h_dptr(cpg->dentry, cpg->bsrc);
5527c038
JR
5534+ h_inode = d_inode(h_src);
5535+ AuDebugOn(h_inode != au_h_iptr(d_inode(cpg->dentry), cpg->bsrc));
1facf9fc 5536+
5537+ /* try stopping to be referenced while we are creating */
c2b27bf2
AM
5538+ h_dst = au_h_dptr(cpg->dentry, cpg->bdst);
5539+ if (au_ftest_cpup(cpg->flags, RENAME))
86dc4139
AM
5540+ AuDebugOn(strncmp(h_dst->d_name.name, AUFS_WH_PFX,
5541+ AUFS_WH_PFX_LEN));
1facf9fc 5542+ h_parent = h_dst->d_parent; /* dir inode is locked */
5527c038 5543+ h_dir = d_inode(h_parent);
1facf9fc 5544+ IMustLock(h_dir);
5545+ AuDebugOn(h_parent != h_dst->d_parent);
5546+
c2b27bf2
AM
5547+ sb = cpg->dentry->d_sb;
5548+ h_path.mnt = au_sbr_mnt(sb, cpg->bdst);
1facf9fc 5549+ if (do_dt) {
5550+ h_path.dentry = h_parent;
5551+ au_dtime_store(&dt, dst_parent, &h_path);
5552+ }
5553+ h_path.dentry = h_dst;
5554+
076b876e 5555+ isreg = 0;
1facf9fc 5556+ isdir = 0;
5557+ mode = h_inode->i_mode;
5558+ switch (mode & S_IFMT) {
5559+ case S_IFREG:
076b876e 5560+ isreg = 1;
cd7a4cd9 5561+ err = vfsub_create(h_dir, &h_path, 0600, /*want_excl*/true);
1facf9fc 5562+ if (!err)
c2b27bf2 5563+ err = au_do_cpup_regular(cpg, h_src_attr);
1facf9fc 5564+ break;
5565+ case S_IFDIR:
5566+ isdir = 1;
5567+ err = vfsub_mkdir(h_dir, &h_path, mode);
8cdd5066
JR
5568+ if (!err)
5569+ err = au_do_cpup_dir(cpg, dst_parent, h_dir, &h_path);
1facf9fc 5570+ break;
5571+ case S_IFLNK:
5572+ err = au_do_cpup_symlink(&h_path, h_src, h_dir);
5573+ break;
5574+ case S_IFCHR:
5575+ case S_IFBLK:
5576+ AuDebugOn(!capable(CAP_MKNOD));
5577+ /*FALLTHROUGH*/
5578+ case S_IFIFO:
5579+ case S_IFSOCK:
5580+ err = vfsub_mknod(h_dir, &h_path, mode, h_inode->i_rdev);
5581+ break;
5582+ default:
5583+ AuIOErr("Unknown inode type 0%o\n", mode);
5584+ err = -EIO;
5585+ }
8cdd5066
JR
5586+ if (!err)
5587+ err = au_reset_acl(h_dir, &h_path, mode);
1facf9fc 5588+
5589+ mnt_flags = au_mntflags(sb);
5590+ if (!au_opt_test(mnt_flags, UDBA_NONE)
5591+ && !isdir
5592+ && au_opt_test(mnt_flags, XINO)
38d290e6
JR
5593+ && (h_inode->i_nlink == 1
5594+ || (h_inode->i_state & I_LINKABLE))
1facf9fc 5595+ /* todo: unnecessary? */
5527c038 5596+ /* && d_inode(cpg->dentry)->i_nlink == 1 */
c2b27bf2
AM
5597+ && cpg->bdst < cpg->bsrc
5598+ && !au_ftest_cpup(cpg->flags, KEEPLINO))
5599+ au_xino_write(sb, cpg->bsrc, h_inode->i_ino, /*ino*/0);
1facf9fc 5600+ /* ignore this error */
5601+
076b876e
AM
5602+ if (!err) {
5603+ force = 0;
5604+ if (isreg) {
5605+ force = !!cpg->len;
5606+ if (cpg->len == -1)
5607+ force = !!i_size_read(h_inode);
5608+ }
5609+ au_fhsm_wrote(sb, cpg->bdst, force);
5610+ }
5611+
1facf9fc 5612+ if (do_dt)
5613+ au_dtime_revert(&dt);
5614+ return err;
5615+}
5616+
392086de 5617+static int au_do_ren_after_cpup(struct au_cp_generic *cpg, struct path *h_path)
86dc4139
AM
5618+{
5619+ int err;
392086de 5620+ struct dentry *dentry, *h_dentry, *h_parent, *parent;
86dc4139 5621+ struct inode *h_dir;
392086de 5622+ aufs_bindex_t bdst;
86dc4139 5623+
392086de
AM
5624+ dentry = cpg->dentry;
5625+ bdst = cpg->bdst;
5626+ h_dentry = au_h_dptr(dentry, bdst);
5627+ if (!au_ftest_cpup(cpg->flags, OVERWRITE)) {
5628+ dget(h_dentry);
5629+ au_set_h_dptr(dentry, bdst, NULL);
5630+ err = au_lkup_neg(dentry, bdst, /*wh*/0);
5631+ if (!err)
5632+ h_path->dentry = dget(au_h_dptr(dentry, bdst));
86dc4139 5633+ au_set_h_dptr(dentry, bdst, h_dentry);
392086de
AM
5634+ } else {
5635+ err = 0;
5636+ parent = dget_parent(dentry);
5637+ h_parent = au_h_dptr(parent, bdst);
5638+ dput(parent);
5639+ h_path->dentry = vfsub_lkup_one(&dentry->d_name, h_parent);
5640+ if (IS_ERR(h_path->dentry))
5641+ err = PTR_ERR(h_path->dentry);
86dc4139 5642+ }
392086de
AM
5643+ if (unlikely(err))
5644+ goto out;
86dc4139 5645+
86dc4139 5646+ h_parent = h_dentry->d_parent; /* dir inode is locked */
5527c038 5647+ h_dir = d_inode(h_parent);
86dc4139 5648+ IMustLock(h_dir);
523b37e3
AM
5649+ AuDbg("%pd %pd\n", h_dentry, h_path->dentry);
5650+ /* no delegation since it is just created */
f2c43d5f
AM
5651+ err = vfsub_rename(h_dir, h_dentry, h_dir, h_path, /*delegated*/NULL,
5652+ /*flags*/0);
86dc4139
AM
5653+ dput(h_path->dentry);
5654+
5655+out:
5656+ return err;
5657+}
5658+
1facf9fc 5659+/*
5660+ * copyup the @dentry from @bsrc to @bdst.
5661+ * the caller must set the both of lower dentries.
5662+ * @len is for truncating when it is -1 copyup the entire file.
5663+ * in link/rename cases, @dst_parent may be different from the real one.
c2b27bf2 5664+ * basic->bsrc can be larger than basic->bdst.
f2c43d5f 5665+ * aufs doesn't touch the credential so
acd2b654 5666+ * security_inode_copy_up{,_xattr}() are unnecessary.
1facf9fc 5667+ */
c2b27bf2 5668+static int au_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent)
1facf9fc 5669+{
5670+ int err, rerr;
5afbbe0d 5671+ aufs_bindex_t old_ibtop;
1facf9fc 5672+ unsigned char isdir, plink;
1facf9fc 5673+ struct dentry *h_src, *h_dst, *h_parent;
5527c038 5674+ struct inode *dst_inode, *h_dir, *inode, *delegated, *src_inode;
1facf9fc 5675+ struct super_block *sb;
86dc4139 5676+ struct au_branch *br;
acd2b654 5677+ /* to reduce stack size */
c2b27bf2
AM
5678+ struct {
5679+ struct au_dtime dt;
5680+ struct path h_path;
5681+ struct au_cpup_reg_attr h_src_attr;
5682+ } *a;
1facf9fc 5683+
c2b27bf2
AM
5684+ err = -ENOMEM;
5685+ a = kmalloc(sizeof(*a), GFP_NOFS);
5686+ if (unlikely(!a))
5687+ goto out;
5688+ a->h_src_attr.valid = 0;
1facf9fc 5689+
c2b27bf2
AM
5690+ sb = cpg->dentry->d_sb;
5691+ br = au_sbr(sb, cpg->bdst);
5692+ a->h_path.mnt = au_br_mnt(br);
5693+ h_dst = au_h_dptr(cpg->dentry, cpg->bdst);
1facf9fc 5694+ h_parent = h_dst->d_parent; /* dir inode is locked */
5527c038 5695+ h_dir = d_inode(h_parent);
1facf9fc 5696+ IMustLock(h_dir);
5697+
c2b27bf2 5698+ h_src = au_h_dptr(cpg->dentry, cpg->bsrc);
5527c038 5699+ inode = d_inode(cpg->dentry);
1facf9fc 5700+
5701+ if (!dst_parent)
c2b27bf2 5702+ dst_parent = dget_parent(cpg->dentry);
1facf9fc 5703+ else
5704+ dget(dst_parent);
5705+
5706+ plink = !!au_opt_test(au_mntflags(sb), PLINK);
c2b27bf2 5707+ dst_inode = au_h_iptr(inode, cpg->bdst);
1facf9fc 5708+ if (dst_inode) {
5709+ if (unlikely(!plink)) {
5710+ err = -EIO;
027c5e7a
AM
5711+ AuIOErr("hi%lu(i%lu) exists on b%d "
5712+ "but plink is disabled\n",
c2b27bf2
AM
5713+ dst_inode->i_ino, inode->i_ino, cpg->bdst);
5714+ goto out_parent;
1facf9fc 5715+ }
5716+
5717+ if (dst_inode->i_nlink) {
c2b27bf2 5718+ const int do_dt = au_ftest_cpup(cpg->flags, DTIME);
1facf9fc 5719+
c2b27bf2 5720+ h_src = au_plink_lkup(inode, cpg->bdst);
1facf9fc 5721+ err = PTR_ERR(h_src);
5722+ if (IS_ERR(h_src))
c2b27bf2 5723+ goto out_parent;
5527c038 5724+ if (unlikely(d_is_negative(h_src))) {
1facf9fc 5725+ err = -EIO;
79b8bda9 5726+ AuIOErr("i%lu exists on b%d "
027c5e7a 5727+ "but not pseudo-linked\n",
79b8bda9 5728+ inode->i_ino, cpg->bdst);
1facf9fc 5729+ dput(h_src);
c2b27bf2 5730+ goto out_parent;
1facf9fc 5731+ }
5732+
5733+ if (do_dt) {
c2b27bf2
AM
5734+ a->h_path.dentry = h_parent;
5735+ au_dtime_store(&a->dt, dst_parent, &a->h_path);
1facf9fc 5736+ }
86dc4139 5737+
c2b27bf2 5738+ a->h_path.dentry = h_dst;
523b37e3
AM
5739+ delegated = NULL;
5740+ err = vfsub_link(h_src, h_dir, &a->h_path, &delegated);
c2b27bf2 5741+ if (!err && au_ftest_cpup(cpg->flags, RENAME))
392086de 5742+ err = au_do_ren_after_cpup(cpg, &a->h_path);
1facf9fc 5743+ if (do_dt)
c2b27bf2 5744+ au_dtime_revert(&a->dt);
523b37e3
AM
5745+ if (unlikely(err == -EWOULDBLOCK)) {
5746+ pr_warn("cannot retry for NFSv4 delegation"
5747+ " for an internal link\n");
5748+ iput(delegated);
5749+ }
1facf9fc 5750+ dput(h_src);
c2b27bf2 5751+ goto out_parent;
1facf9fc 5752+ } else
5753+ /* todo: cpup_wh_file? */
5754+ /* udba work */
4a4d8108 5755+ au_update_ibrange(inode, /*do_put_zero*/1);
1facf9fc 5756+ }
5757+
86dc4139 5758+ isdir = S_ISDIR(inode->i_mode);
5afbbe0d 5759+ old_ibtop = au_ibtop(inode);
c2b27bf2 5760+ err = cpup_entry(cpg, dst_parent, &a->h_src_attr);
1facf9fc 5761+ if (unlikely(err))
86dc4139 5762+ goto out_rev;
5527c038 5763+ dst_inode = d_inode(h_dst);
febd17d6 5764+ inode_lock_nested(dst_inode, AuLsc_I_CHILD2);
86dc4139 5765+ /* todo: necessary? */
c2b27bf2 5766+ /* au_pin_hdir_unlock(cpg->pin); */
1facf9fc 5767+
c2b27bf2 5768+ err = cpup_iattr(cpg->dentry, cpg->bdst, h_src, &a->h_src_attr);
86dc4139
AM
5769+ if (unlikely(err)) {
5770+ /* todo: necessary? */
c2b27bf2 5771+ /* au_pin_hdir_relock(cpg->pin); */ /* ignore an error */
febd17d6 5772+ inode_unlock(dst_inode);
86dc4139
AM
5773+ goto out_rev;
5774+ }
5775+
5afbbe0d 5776+ if (cpg->bdst < old_ibtop) {
86dc4139 5777+ if (S_ISREG(inode->i_mode)) {
c2b27bf2 5778+ err = au_dy_iaop(inode, cpg->bdst, dst_inode);
86dc4139 5779+ if (unlikely(err)) {
c2b27bf2
AM
5780+ /* ignore an error */
5781+ /* au_pin_hdir_relock(cpg->pin); */
febd17d6 5782+ inode_unlock(dst_inode);
86dc4139 5783+ goto out_rev;
4a4d8108 5784+ }
4a4d8108 5785+ }
5afbbe0d 5786+ au_set_ibtop(inode, cpg->bdst);
c2b27bf2 5787+ } else
5afbbe0d 5788+ au_set_ibbot(inode, cpg->bdst);
c2b27bf2 5789+ au_set_h_iptr(inode, cpg->bdst, au_igrab(dst_inode),
86dc4139
AM
5790+ au_hi_flags(inode, isdir));
5791+
5792+ /* todo: necessary? */
c2b27bf2 5793+ /* err = au_pin_hdir_relock(cpg->pin); */
febd17d6 5794+ inode_unlock(dst_inode);
86dc4139
AM
5795+ if (unlikely(err))
5796+ goto out_rev;
5797+
5527c038 5798+ src_inode = d_inode(h_src);
86dc4139 5799+ if (!isdir
5527c038
JR
5800+ && (src_inode->i_nlink > 1
5801+ || src_inode->i_state & I_LINKABLE)
86dc4139 5802+ && plink)
c2b27bf2 5803+ au_plink_append(inode, cpg->bdst, h_dst);
86dc4139 5804+
c2b27bf2
AM
5805+ if (au_ftest_cpup(cpg->flags, RENAME)) {
5806+ a->h_path.dentry = h_dst;
392086de 5807+ err = au_do_ren_after_cpup(cpg, &a->h_path);
86dc4139
AM
5808+ }
5809+ if (!err)
c2b27bf2 5810+ goto out_parent; /* success */
1facf9fc 5811+
5812+ /* revert */
4a4d8108 5813+out_rev:
c2b27bf2
AM
5814+ a->h_path.dentry = h_parent;
5815+ au_dtime_store(&a->dt, dst_parent, &a->h_path);
5816+ a->h_path.dentry = h_dst;
86dc4139 5817+ rerr = 0;
5527c038 5818+ if (d_is_positive(h_dst)) {
523b37e3
AM
5819+ if (!isdir) {
5820+ /* no delegation since it is just created */
5821+ rerr = vfsub_unlink(h_dir, &a->h_path,
5822+ /*delegated*/NULL, /*force*/0);
5823+ } else
c2b27bf2 5824+ rerr = vfsub_rmdir(h_dir, &a->h_path);
86dc4139 5825+ }
c2b27bf2 5826+ au_dtime_revert(&a->dt);
1facf9fc 5827+ if (rerr) {
5828+ AuIOErr("failed removing broken entry(%d, %d)\n", err, rerr);
5829+ err = -EIO;
5830+ }
c2b27bf2 5831+out_parent:
1facf9fc 5832+ dput(dst_parent);
9f237c51 5833+ au_kfree_rcu(a);
c2b27bf2 5834+out:
1facf9fc 5835+ return err;
5836+}
5837+
7e9cd9fe 5838+#if 0 /* reserved */
1facf9fc 5839+struct au_cpup_single_args {
5840+ int *errp;
c2b27bf2 5841+ struct au_cp_generic *cpg;
1facf9fc 5842+ struct dentry *dst_parent;
5843+};
5844+
5845+static void au_call_cpup_single(void *args)
5846+{
5847+ struct au_cpup_single_args *a = args;
86dc4139 5848+
c2b27bf2
AM
5849+ au_pin_hdir_acquire_nest(a->cpg->pin);
5850+ *a->errp = au_cpup_single(a->cpg, a->dst_parent);
5851+ au_pin_hdir_release(a->cpg->pin);
1facf9fc 5852+}
c2b27bf2 5853+#endif
1facf9fc 5854+
53392da6
AM
5855+/*
5856+ * prevent SIGXFSZ in copy-up.
5857+ * testing CAP_MKNOD is for generic fs,
5858+ * but CAP_FSETID is for xfs only, currently.
5859+ */
86dc4139 5860+static int au_cpup_sio_test(struct au_pin *pin, umode_t mode)
53392da6
AM
5861+{
5862+ int do_sio;
86dc4139
AM
5863+ struct super_block *sb;
5864+ struct inode *h_dir;
53392da6
AM
5865+
5866+ do_sio = 0;
86dc4139 5867+ sb = au_pinned_parent(pin)->d_sb;
53392da6
AM
5868+ if (!au_wkq_test()
5869+ && (!au_sbi(sb)->si_plink_maint_pid
5870+ || au_plink_maint(sb, AuLock_NOPLM))) {
5871+ switch (mode & S_IFMT) {
5872+ case S_IFREG:
5873+ /* no condition about RLIMIT_FSIZE and the file size */
5874+ do_sio = 1;
5875+ break;
5876+ case S_IFCHR:
5877+ case S_IFBLK:
5878+ do_sio = !capable(CAP_MKNOD);
5879+ break;
5880+ }
5881+ if (!do_sio)
5882+ do_sio = ((mode & (S_ISUID | S_ISGID))
5883+ && !capable(CAP_FSETID));
86dc4139
AM
5884+ /* this workaround may be removed in the future */
5885+ if (!do_sio) {
5886+ h_dir = au_pinned_h_dir(pin);
5887+ do_sio = h_dir->i_mode & S_ISVTX;
5888+ }
53392da6
AM
5889+ }
5890+
5891+ return do_sio;
5892+}
5893+
7e9cd9fe 5894+#if 0 /* reserved */
c2b27bf2 5895+int au_sio_cpup_single(struct au_cp_generic *cpg, struct dentry *dst_parent)
1facf9fc 5896+{
5897+ int err, wkq_err;
1facf9fc 5898+ struct dentry *h_dentry;
5899+
c2b27bf2 5900+ h_dentry = au_h_dptr(cpg->dentry, cpg->bsrc);
5527c038 5901+ if (!au_cpup_sio_test(pin, d_inode(h_dentry)->i_mode))
c2b27bf2 5902+ err = au_cpup_single(cpg, dst_parent);
1facf9fc 5903+ else {
5904+ struct au_cpup_single_args args = {
5905+ .errp = &err,
c2b27bf2
AM
5906+ .cpg = cpg,
5907+ .dst_parent = dst_parent
1facf9fc 5908+ };
5909+ wkq_err = au_wkq_wait(au_call_cpup_single, &args);
5910+ if (unlikely(wkq_err))
5911+ err = wkq_err;
5912+ }
5913+
5914+ return err;
5915+}
c2b27bf2 5916+#endif
1facf9fc 5917+
5918+/*
5919+ * copyup the @dentry from the first active lower branch to @bdst,
5920+ * using au_cpup_single().
5921+ */
c2b27bf2 5922+static int au_cpup_simple(struct au_cp_generic *cpg)
1facf9fc 5923+{
5924+ int err;
c2b27bf2
AM
5925+ unsigned int flags_orig;
5926+ struct dentry *dentry;
5927+
5928+ AuDebugOn(cpg->bsrc < 0);
1facf9fc 5929+
c2b27bf2 5930+ dentry = cpg->dentry;
86dc4139 5931+ DiMustWriteLock(dentry);
1facf9fc 5932+
c2b27bf2 5933+ err = au_lkup_neg(dentry, cpg->bdst, /*wh*/1);
1facf9fc 5934+ if (!err) {
c2b27bf2
AM
5935+ flags_orig = cpg->flags;
5936+ au_fset_cpup(cpg->flags, RENAME);
5937+ err = au_cpup_single(cpg, NULL);
5938+ cpg->flags = flags_orig;
1facf9fc 5939+ if (!err)
5940+ return 0; /* success */
5941+
5942+ /* revert */
c2b27bf2 5943+ au_set_h_dptr(dentry, cpg->bdst, NULL);
5afbbe0d 5944+ au_set_dbtop(dentry, cpg->bsrc);
1facf9fc 5945+ }
5946+
5947+ return err;
5948+}
5949+
5950+struct au_cpup_simple_args {
5951+ int *errp;
c2b27bf2 5952+ struct au_cp_generic *cpg;
1facf9fc 5953+};
5954+
5955+static void au_call_cpup_simple(void *args)
5956+{
5957+ struct au_cpup_simple_args *a = args;
86dc4139 5958+
c2b27bf2
AM
5959+ au_pin_hdir_acquire_nest(a->cpg->pin);
5960+ *a->errp = au_cpup_simple(a->cpg);
5961+ au_pin_hdir_release(a->cpg->pin);
1facf9fc 5962+}
5963+
c2b27bf2 5964+static int au_do_sio_cpup_simple(struct au_cp_generic *cpg)
1facf9fc 5965+{
5966+ int err, wkq_err;
c2b27bf2
AM
5967+ struct dentry *dentry, *parent;
5968+ struct file *h_file;
1facf9fc 5969+ struct inode *h_dir;
5970+
c2b27bf2
AM
5971+ dentry = cpg->dentry;
5972+ h_file = NULL;
5973+ if (au_ftest_cpup(cpg->flags, HOPEN)) {
5974+ AuDebugOn(cpg->bsrc < 0);
392086de 5975+ h_file = au_h_open_pre(dentry, cpg->bsrc, /*force_wr*/0);
c2b27bf2
AM
5976+ err = PTR_ERR(h_file);
5977+ if (IS_ERR(h_file))
5978+ goto out;
5979+ }
5980+
1facf9fc 5981+ parent = dget_parent(dentry);
5527c038 5982+ h_dir = au_h_iptr(d_inode(parent), cpg->bdst);
53392da6 5983+ if (!au_test_h_perm_sio(h_dir, MAY_EXEC | MAY_WRITE)
5527c038 5984+ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode))
c2b27bf2 5985+ err = au_cpup_simple(cpg);
1facf9fc 5986+ else {
5987+ struct au_cpup_simple_args args = {
5988+ .errp = &err,
c2b27bf2 5989+ .cpg = cpg
1facf9fc 5990+ };
5991+ wkq_err = au_wkq_wait(au_call_cpup_simple, &args);
5992+ if (unlikely(wkq_err))
5993+ err = wkq_err;
5994+ }
5995+
5996+ dput(parent);
c2b27bf2
AM
5997+ if (h_file)
5998+ au_h_open_post(dentry, cpg->bsrc, h_file);
5999+
6000+out:
1facf9fc 6001+ return err;
6002+}
6003+
c2b27bf2 6004+int au_sio_cpup_simple(struct au_cp_generic *cpg)
367653fa 6005+{
5afbbe0d 6006+ aufs_bindex_t bsrc, bbot;
c2b27bf2 6007+ struct dentry *dentry, *h_dentry;
367653fa 6008+
c2b27bf2
AM
6009+ if (cpg->bsrc < 0) {
6010+ dentry = cpg->dentry;
5afbbe0d
AM
6011+ bbot = au_dbbot(dentry);
6012+ for (bsrc = cpg->bdst + 1; bsrc <= bbot; bsrc++) {
c2b27bf2
AM
6013+ h_dentry = au_h_dptr(dentry, bsrc);
6014+ if (h_dentry) {
5527c038 6015+ AuDebugOn(d_is_negative(h_dentry));
c2b27bf2
AM
6016+ break;
6017+ }
6018+ }
5afbbe0d 6019+ AuDebugOn(bsrc > bbot);
c2b27bf2 6020+ cpg->bsrc = bsrc;
367653fa 6021+ }
c2b27bf2
AM
6022+ AuDebugOn(cpg->bsrc <= cpg->bdst);
6023+ return au_do_sio_cpup_simple(cpg);
6024+}
367653fa 6025+
c2b27bf2
AM
6026+int au_sio_cpdown_simple(struct au_cp_generic *cpg)
6027+{
6028+ AuDebugOn(cpg->bdst <= cpg->bsrc);
6029+ return au_do_sio_cpup_simple(cpg);
367653fa
AM
6030+}
6031+
1facf9fc 6032+/* ---------------------------------------------------------------------- */
6033+
6034+/*
6035+ * copyup the deleted file for writing.
6036+ */
c2b27bf2
AM
6037+static int au_do_cpup_wh(struct au_cp_generic *cpg, struct dentry *wh_dentry,
6038+ struct file *file)
1facf9fc 6039+{
6040+ int err;
c2b27bf2
AM
6041+ unsigned int flags_orig;
6042+ aufs_bindex_t bsrc_orig;
c2b27bf2 6043+ struct au_dinfo *dinfo;
5afbbe0d
AM
6044+ struct {
6045+ struct au_hdentry *hd;
6046+ struct dentry *h_dentry;
6047+ } hdst, hsrc;
1facf9fc 6048+
c2b27bf2 6049+ dinfo = au_di(cpg->dentry);
1308ab2a 6050+ AuRwMustWriteLock(&dinfo->di_rwsem);
6051+
c2b27bf2 6052+ bsrc_orig = cpg->bsrc;
5afbbe0d
AM
6053+ cpg->bsrc = dinfo->di_btop;
6054+ hdst.hd = au_hdentry(dinfo, cpg->bdst);
6055+ hdst.h_dentry = hdst.hd->hd_dentry;
6056+ hdst.hd->hd_dentry = wh_dentry;
6057+ dinfo->di_btop = cpg->bdst;
6058+
6059+ hsrc.h_dentry = NULL;
027c5e7a 6060+ if (file) {
5afbbe0d
AM
6061+ hsrc.hd = au_hdentry(dinfo, cpg->bsrc);
6062+ hsrc.h_dentry = hsrc.hd->hd_dentry;
6063+ hsrc.hd->hd_dentry = au_hf_top(file)->f_path.dentry;
027c5e7a 6064+ }
c2b27bf2
AM
6065+ flags_orig = cpg->flags;
6066+ cpg->flags = !AuCpup_DTIME;
6067+ err = au_cpup_single(cpg, /*h_parent*/NULL);
6068+ cpg->flags = flags_orig;
027c5e7a
AM
6069+ if (file) {
6070+ if (!err)
6071+ err = au_reopen_nondir(file);
5afbbe0d 6072+ hsrc.hd->hd_dentry = hsrc.h_dentry;
1facf9fc 6073+ }
5afbbe0d
AM
6074+ hdst.hd->hd_dentry = hdst.h_dentry;
6075+ dinfo->di_btop = cpg->bsrc;
c2b27bf2 6076+ cpg->bsrc = bsrc_orig;
1facf9fc 6077+
6078+ return err;
6079+}
6080+
c2b27bf2 6081+static int au_cpup_wh(struct au_cp_generic *cpg, struct file *file)
1facf9fc 6082+{
6083+ int err;
c2b27bf2 6084+ aufs_bindex_t bdst;
1facf9fc 6085+ struct au_dtime dt;
c2b27bf2 6086+ struct dentry *dentry, *parent, *h_parent, *wh_dentry;
1facf9fc 6087+ struct au_branch *br;
6088+ struct path h_path;
6089+
c2b27bf2
AM
6090+ dentry = cpg->dentry;
6091+ bdst = cpg->bdst;
1facf9fc 6092+ br = au_sbr(dentry->d_sb, bdst);
6093+ parent = dget_parent(dentry);
6094+ h_parent = au_h_dptr(parent, bdst);
6095+ wh_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
6096+ err = PTR_ERR(wh_dentry);
6097+ if (IS_ERR(wh_dentry))
6098+ goto out;
6099+
6100+ h_path.dentry = h_parent;
86dc4139 6101+ h_path.mnt = au_br_mnt(br);
1facf9fc 6102+ au_dtime_store(&dt, parent, &h_path);
c2b27bf2 6103+ err = au_do_cpup_wh(cpg, wh_dentry, file);
1facf9fc 6104+ if (unlikely(err))
6105+ goto out_wh;
6106+
6107+ dget(wh_dentry);
6108+ h_path.dentry = wh_dentry;
2000de60 6109+ if (!d_is_dir(wh_dentry)) {
523b37e3 6110+ /* no delegation since it is just created */
5527c038 6111+ err = vfsub_unlink(d_inode(h_parent), &h_path,
523b37e3
AM
6112+ /*delegated*/NULL, /*force*/0);
6113+ } else
5527c038 6114+ err = vfsub_rmdir(d_inode(h_parent), &h_path);
1facf9fc 6115+ if (unlikely(err)) {
523b37e3
AM
6116+ AuIOErr("failed remove copied-up tmp file %pd(%d)\n",
6117+ wh_dentry, err);
1facf9fc 6118+ err = -EIO;
6119+ }
6120+ au_dtime_revert(&dt);
5527c038 6121+ au_set_hi_wh(d_inode(dentry), bdst, wh_dentry);
1facf9fc 6122+
4f0767ce 6123+out_wh:
1facf9fc 6124+ dput(wh_dentry);
4f0767ce 6125+out:
1facf9fc 6126+ dput(parent);
6127+ return err;
6128+}
6129+
6130+struct au_cpup_wh_args {
6131+ int *errp;
c2b27bf2 6132+ struct au_cp_generic *cpg;
1facf9fc 6133+ struct file *file;
6134+};
6135+
6136+static void au_call_cpup_wh(void *args)
6137+{
6138+ struct au_cpup_wh_args *a = args;
86dc4139 6139+
c2b27bf2
AM
6140+ au_pin_hdir_acquire_nest(a->cpg->pin);
6141+ *a->errp = au_cpup_wh(a->cpg, a->file);
6142+ au_pin_hdir_release(a->cpg->pin);
1facf9fc 6143+}
6144+
c2b27bf2 6145+int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file)
1facf9fc 6146+{
6147+ int err, wkq_err;
c2b27bf2 6148+ aufs_bindex_t bdst;
c1595e42 6149+ struct dentry *dentry, *parent, *h_orph, *h_parent;
86dc4139 6150+ struct inode *dir, *h_dir, *h_tmpdir;
1facf9fc 6151+ struct au_wbr *wbr;
c2b27bf2 6152+ struct au_pin wh_pin, *pin_orig;
1facf9fc 6153+
c2b27bf2
AM
6154+ dentry = cpg->dentry;
6155+ bdst = cpg->bdst;
1facf9fc 6156+ parent = dget_parent(dentry);
5527c038 6157+ dir = d_inode(parent);
1facf9fc 6158+ h_orph = NULL;
6159+ h_parent = NULL;
6160+ h_dir = au_igrab(au_h_iptr(dir, bdst));
6161+ h_tmpdir = h_dir;
c2b27bf2 6162+ pin_orig = NULL;
1facf9fc 6163+ if (!h_dir->i_nlink) {
6164+ wbr = au_sbr(dentry->d_sb, bdst)->br_wbr;
6165+ h_orph = wbr->wbr_orph;
6166+
6167+ h_parent = dget(au_h_dptr(parent, bdst));
1facf9fc 6168+ au_set_h_dptr(parent, bdst, dget(h_orph));
5527c038 6169+ h_tmpdir = d_inode(h_orph);
1facf9fc 6170+ au_set_h_iptr(dir, bdst, au_igrab(h_tmpdir), /*flags*/0);
6171+
febd17d6 6172+ inode_lock_nested(h_tmpdir, AuLsc_I_PARENT3);
4a4d8108 6173+ /* todo: au_h_open_pre()? */
86dc4139 6174+
c2b27bf2 6175+ pin_orig = cpg->pin;
86dc4139 6176+ au_pin_init(&wh_pin, dentry, bdst, AuLsc_DI_PARENT,
c2b27bf2
AM
6177+ AuLsc_I_PARENT3, cpg->pin->udba, AuPin_DI_LOCKED);
6178+ cpg->pin = &wh_pin;
1facf9fc 6179+ }
6180+
53392da6 6181+ if (!au_test_h_perm_sio(h_tmpdir, MAY_EXEC | MAY_WRITE)
5527c038 6182+ && !au_cpup_sio_test(cpg->pin, d_inode(dentry)->i_mode))
c2b27bf2 6183+ err = au_cpup_wh(cpg, file);
1facf9fc 6184+ else {
6185+ struct au_cpup_wh_args args = {
6186+ .errp = &err,
c2b27bf2
AM
6187+ .cpg = cpg,
6188+ .file = file
1facf9fc 6189+ };
6190+ wkq_err = au_wkq_wait(au_call_cpup_wh, &args);
6191+ if (unlikely(wkq_err))
6192+ err = wkq_err;
6193+ }
6194+
6195+ if (h_orph) {
febd17d6 6196+ inode_unlock(h_tmpdir);
4a4d8108 6197+ /* todo: au_h_open_post()? */
1facf9fc 6198+ au_set_h_iptr(dir, bdst, au_igrab(h_dir), /*flags*/0);
1facf9fc 6199+ au_set_h_dptr(parent, bdst, h_parent);
c2b27bf2
AM
6200+ AuDebugOn(!pin_orig);
6201+ cpg->pin = pin_orig;
1facf9fc 6202+ }
6203+ iput(h_dir);
6204+ dput(parent);
6205+
6206+ return err;
6207+}
6208+
6209+/* ---------------------------------------------------------------------- */
6210+
6211+/*
6212+ * generic routine for both of copy-up and copy-down.
6213+ */
6214+/* cf. revalidate function in file.c */
6215+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
6216+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 6217+ struct au_pin *pin,
1facf9fc 6218+ struct dentry *h_parent, void *arg),
6219+ void *arg)
6220+{
6221+ int err;
6222+ struct au_pin pin;
5527c038 6223+ struct dentry *d, *parent, *h_parent, *real_parent, *h_dentry;
1facf9fc 6224+
6225+ err = 0;
6226+ parent = dget_parent(dentry);
6227+ if (IS_ROOT(parent))
6228+ goto out;
6229+
6230+ au_pin_init(&pin, dentry, bdst, AuLsc_DI_PARENT2, AuLsc_I_PARENT2,
6231+ au_opt_udba(dentry->d_sb), AuPin_MNT_WRITE);
6232+
6233+ /* do not use au_dpage */
6234+ real_parent = parent;
6235+ while (1) {
6236+ dput(parent);
6237+ parent = dget_parent(dentry);
6238+ h_parent = au_h_dptr(parent, bdst);
6239+ if (h_parent)
6240+ goto out; /* success */
6241+
6242+ /* find top dir which is necessary to cpup */
6243+ do {
6244+ d = parent;
6245+ dput(parent);
6246+ parent = dget_parent(d);
6247+ di_read_lock_parent3(parent, !AuLock_IR);
6248+ h_parent = au_h_dptr(parent, bdst);
6249+ di_read_unlock(parent, !AuLock_IR);
6250+ } while (!h_parent);
6251+
6252+ if (d != real_parent)
6253+ di_write_lock_child3(d);
6254+
6255+ /* somebody else might create while we were sleeping */
5527c038
JR
6256+ h_dentry = au_h_dptr(d, bdst);
6257+ if (!h_dentry || d_is_negative(h_dentry)) {
6258+ if (h_dentry)
5afbbe0d 6259+ au_update_dbtop(d);
1facf9fc 6260+
6261+ au_pin_set_dentry(&pin, d);
6262+ err = au_do_pin(&pin);
6263+ if (!err) {
86dc4139 6264+ err = cp(d, bdst, &pin, h_parent, arg);
1facf9fc 6265+ au_unpin(&pin);
6266+ }
6267+ }
6268+
6269+ if (d != real_parent)
6270+ di_write_unlock(d);
6271+ if (unlikely(err))
6272+ break;
6273+ }
6274+
4f0767ce 6275+out:
1facf9fc 6276+ dput(parent);
6277+ return err;
6278+}
6279+
6280+static int au_cpup_dir(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 6281+ struct au_pin *pin,
2000de60 6282+ struct dentry *h_parent __maybe_unused,
1facf9fc 6283+ void *arg __maybe_unused)
6284+{
c2b27bf2
AM
6285+ struct au_cp_generic cpg = {
6286+ .dentry = dentry,
6287+ .bdst = bdst,
6288+ .bsrc = -1,
6289+ .len = 0,
6290+ .pin = pin,
6291+ .flags = AuCpup_DTIME
6292+ };
6293+ return au_sio_cpup_simple(&cpg);
1facf9fc 6294+}
6295+
6296+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
6297+{
6298+ return au_cp_dirs(dentry, bdst, au_cpup_dir, NULL);
6299+}
6300+
6301+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst)
6302+{
6303+ int err;
6304+ struct dentry *parent;
6305+ struct inode *dir;
6306+
6307+ parent = dget_parent(dentry);
5527c038 6308+ dir = d_inode(parent);
1facf9fc 6309+ err = 0;
6310+ if (au_h_iptr(dir, bdst))
6311+ goto out;
6312+
6313+ di_read_unlock(parent, AuLock_IR);
6314+ di_write_lock_parent(parent);
6315+ /* someone else might change our inode while we were sleeping */
6316+ if (!au_h_iptr(dir, bdst))
6317+ err = au_cpup_dirs(dentry, bdst);
6318+ di_downgrade_lock(parent, AuLock_IR);
6319+
4f0767ce 6320+out:
1facf9fc 6321+ dput(parent);
6322+ return err;
6323+}
7f207e10 6324diff -urN /usr/share/empty/fs/aufs/cpup.h linux/fs/aufs/cpup.h
eca34b5c 6325--- /usr/share/empty/fs/aufs/cpup.h 1970-01-01 01:00:00.000000000 +0100
016522bc 6326+++ linux/fs/aufs/cpup.h 2020-01-27 10:57:18.168871450 +0100
062440b3
AM
6327@@ -0,0 +1,100 @@
6328+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 6329+/*
016522bc 6330+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 6331+ *
6332+ * This program, aufs is free software; you can redistribute it and/or modify
6333+ * it under the terms of the GNU General Public License as published by
6334+ * the Free Software Foundation; either version 2 of the License, or
6335+ * (at your option) any later version.
dece6358
AM
6336+ *
6337+ * This program is distributed in the hope that it will be useful,
6338+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6339+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6340+ * GNU General Public License for more details.
6341+ *
6342+ * You should have received a copy of the GNU General Public License
523b37e3 6343+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 6344+ */
6345+
6346+/*
6347+ * copy-up/down functions
6348+ */
6349+
6350+#ifndef __AUFS_CPUP_H__
6351+#define __AUFS_CPUP_H__
6352+
6353+#ifdef __KERNEL__
6354+
dece6358 6355+#include <linux/path.h>
1facf9fc 6356+
dece6358
AM
6357+struct inode;
6358+struct file;
86dc4139 6359+struct au_pin;
dece6358 6360+
86dc4139 6361+void au_cpup_attr_flags(struct inode *dst, unsigned int iflags);
1facf9fc 6362+void au_cpup_attr_timesizes(struct inode *inode);
6363+void au_cpup_attr_nlink(struct inode *inode, int force);
6364+void au_cpup_attr_changeable(struct inode *inode);
6365+void au_cpup_igen(struct inode *inode, struct inode *h_inode);
6366+void au_cpup_attr_all(struct inode *inode, int force);
6367+
6368+/* ---------------------------------------------------------------------- */
6369+
c2b27bf2
AM
6370+struct au_cp_generic {
6371+ struct dentry *dentry;
6372+ aufs_bindex_t bdst, bsrc;
6373+ loff_t len;
6374+ struct au_pin *pin;
6375+ unsigned int flags;
6376+};
6377+
1facf9fc 6378+/* cpup flags */
392086de
AM
6379+#define AuCpup_DTIME 1 /* do dtime_store/revert */
6380+#define AuCpup_KEEPLINO (1 << 1) /* do not clear the lower xino,
6381+ for link(2) */
6382+#define AuCpup_RENAME (1 << 2) /* rename after cpup */
6383+#define AuCpup_HOPEN (1 << 3) /* call h_open_pre/post() in
6384+ cpup */
6385+#define AuCpup_OVERWRITE (1 << 4) /* allow overwriting the
6386+ existing entry */
6387+#define AuCpup_RWDST (1 << 5) /* force write target even if
6388+ the branch is marked as RO */
c2b27bf2 6389+
8b6a4947
AM
6390+#ifndef CONFIG_AUFS_BR_HFSPLUS
6391+#undef AuCpup_HOPEN
6392+#define AuCpup_HOPEN 0
6393+#endif
6394+
1facf9fc 6395+#define au_ftest_cpup(flags, name) ((flags) & AuCpup_##name)
7f207e10
AM
6396+#define au_fset_cpup(flags, name) \
6397+ do { (flags) |= AuCpup_##name; } while (0)
6398+#define au_fclr_cpup(flags, name) \
6399+ do { (flags) &= ~AuCpup_##name; } while (0)
1facf9fc 6400+
6401+int au_copy_file(struct file *dst, struct file *src, loff_t len);
c2b27bf2
AM
6402+int au_sio_cpup_simple(struct au_cp_generic *cpg);
6403+int au_sio_cpdown_simple(struct au_cp_generic *cpg);
6404+int au_sio_cpup_wh(struct au_cp_generic *cpg, struct file *file);
1facf9fc 6405+
6406+int au_cp_dirs(struct dentry *dentry, aufs_bindex_t bdst,
6407+ int (*cp)(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 6408+ struct au_pin *pin,
1facf9fc 6409+ struct dentry *h_parent, void *arg),
6410+ void *arg);
6411+int au_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
6412+int au_test_and_cpup_dirs(struct dentry *dentry, aufs_bindex_t bdst);
6413+
6414+/* ---------------------------------------------------------------------- */
6415+
6416+/* keep timestamps when copyup */
6417+struct au_dtime {
6418+ struct dentry *dt_dentry;
6419+ struct path dt_h_path;
cd7a4cd9 6420+ struct timespec64 dt_atime, dt_mtime;
1facf9fc 6421+};
6422+void au_dtime_store(struct au_dtime *dt, struct dentry *dentry,
6423+ struct path *h_path);
6424+void au_dtime_revert(struct au_dtime *dt);
6425+
6426+#endif /* __KERNEL__ */
6427+#endif /* __AUFS_CPUP_H__ */
7f207e10 6428diff -urN /usr/share/empty/fs/aufs/dbgaufs.c linux/fs/aufs/dbgaufs.c
eca34b5c 6429--- /usr/share/empty/fs/aufs/dbgaufs.c 1970-01-01 01:00:00.000000000 +0100
016522bc 6430+++ linux/fs/aufs/dbgaufs.c 2020-01-27 10:57:18.168871450 +0100
9f237c51 6431@@ -0,0 +1,526 @@
cd7a4cd9 6432+// SPDX-License-Identifier: GPL-2.0
1facf9fc 6433+/*
016522bc 6434+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 6435+ *
6436+ * This program, aufs is free software; you can redistribute it and/or modify
6437+ * it under the terms of the GNU General Public License as published by
6438+ * the Free Software Foundation; either version 2 of the License, or
6439+ * (at your option) any later version.
dece6358
AM
6440+ *
6441+ * This program is distributed in the hope that it will be useful,
6442+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6443+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6444+ * GNU General Public License for more details.
6445+ *
6446+ * You should have received a copy of the GNU General Public License
523b37e3 6447+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 6448+ */
6449+
6450+/*
6451+ * debugfs interface
6452+ */
6453+
6454+#include <linux/debugfs.h>
6455+#include "aufs.h"
6456+
6457+#ifndef CONFIG_SYSFS
6458+#error DEBUG_FS depends upon SYSFS
6459+#endif
6460+
6461+static struct dentry *dbgaufs;
cd7a4cd9 6462+static const mode_t dbgaufs_mode = 0444;
1facf9fc 6463+
6464+/* 20 is max digits length of ulong 64 */
6465+struct dbgaufs_arg {
6466+ int n;
6467+ char a[20 * 4];
6468+};
6469+
6470+/*
6471+ * common function for all XINO files
6472+ */
6473+static int dbgaufs_xi_release(struct inode *inode __maybe_unused,
6474+ struct file *file)
6475+{
9f237c51
AM
6476+ void *p;
6477+
6478+ p = file->private_data;
6479+ if (p) {
6480+ /* this is struct dbgaufs_arg */
6481+ AuDebugOn(!au_kfree_sz_test(p));
6482+ au_kfree_do_rcu(p);
6483+ }
1facf9fc 6484+ return 0;
6485+}
6486+
062440b3
AM
6487+static int dbgaufs_xi_open(struct file *xf, struct file *file, int do_fcnt,
6488+ int cnt)
1facf9fc 6489+{
6490+ int err;
6491+ struct kstat st;
6492+ struct dbgaufs_arg *p;
6493+
6494+ err = -ENOMEM;
6495+ p = kmalloc(sizeof(*p), GFP_NOFS);
6496+ if (unlikely(!p))
6497+ goto out;
6498+
6499+ err = 0;
6500+ p->n = 0;
6501+ file->private_data = p;
6502+ if (!xf)
6503+ goto out;
6504+
521ced18 6505+ err = vfsub_getattr(&xf->f_path, &st);
1facf9fc 6506+ if (!err) {
6507+ if (do_fcnt)
6508+ p->n = snprintf
062440b3
AM
6509+ (p->a, sizeof(p->a), "%d, %llux%u %lld\n",
6510+ cnt, st.blocks, st.blksize,
1facf9fc 6511+ (long long)st.size);
6512+ else
521ced18 6513+ p->n = snprintf(p->a, sizeof(p->a), "%llux%u %lld\n",
1facf9fc 6514+ st.blocks, st.blksize,
6515+ (long long)st.size);
6516+ AuDebugOn(p->n >= sizeof(p->a));
6517+ } else {
6518+ p->n = snprintf(p->a, sizeof(p->a), "err %d\n", err);
6519+ err = 0;
6520+ }
6521+
4f0767ce 6522+out:
1facf9fc 6523+ return err;
1facf9fc 6524+}
6525+
6526+static ssize_t dbgaufs_xi_read(struct file *file, char __user *buf,
6527+ size_t count, loff_t *ppos)
6528+{
6529+ struct dbgaufs_arg *p;
6530+
6531+ p = file->private_data;
6532+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
6533+}
6534+
6535+/* ---------------------------------------------------------------------- */
6536+
86dc4139
AM
6537+struct dbgaufs_plink_arg {
6538+ int n;
6539+ char a[];
6540+};
6541+
6542+static int dbgaufs_plink_release(struct inode *inode __maybe_unused,
6543+ struct file *file)
6544+{
1c60b727 6545+ free_page((unsigned long)file->private_data);
86dc4139
AM
6546+ return 0;
6547+}
6548+
6549+static int dbgaufs_plink_open(struct inode *inode, struct file *file)
6550+{
6551+ int err, i, limit;
6552+ unsigned long n, sum;
6553+ struct dbgaufs_plink_arg *p;
6554+ struct au_sbinfo *sbinfo;
6555+ struct super_block *sb;
8b6a4947 6556+ struct hlist_bl_head *hbl;
86dc4139
AM
6557+
6558+ err = -ENOMEM;
6559+ p = (void *)get_zeroed_page(GFP_NOFS);
6560+ if (unlikely(!p))
6561+ goto out;
6562+
6563+ err = -EFBIG;
6564+ sbinfo = inode->i_private;
6565+ sb = sbinfo->si_sb;
6566+ si_noflush_read_lock(sb);
6567+ if (au_opt_test(au_mntflags(sb), PLINK)) {
6568+ limit = PAGE_SIZE - sizeof(p->n);
6569+
6570+ /* the number of buckets */
6571+ n = snprintf(p->a + p->n, limit, "%d\n", AuPlink_NHASH);
6572+ p->n += n;
6573+ limit -= n;
6574+
6575+ sum = 0;
8b6a4947
AM
6576+ for (i = 0, hbl = sbinfo->si_plink; i < AuPlink_NHASH;
6577+ i++, hbl++) {
6578+ n = au_hbl_count(hbl);
86dc4139
AM
6579+ sum += n;
6580+
6581+ n = snprintf(p->a + p->n, limit, "%lu ", n);
6582+ p->n += n;
6583+ limit -= n;
6584+ if (unlikely(limit <= 0))
6585+ goto out_free;
6586+ }
6587+ p->a[p->n - 1] = '\n';
6588+
6589+ /* the sum of plinks */
6590+ n = snprintf(p->a + p->n, limit, "%lu\n", sum);
6591+ p->n += n;
6592+ limit -= n;
6593+ if (unlikely(limit <= 0))
6594+ goto out_free;
6595+ } else {
6596+#define str "1\n0\n0\n"
6597+ p->n = sizeof(str) - 1;
6598+ strcpy(p->a, str);
6599+#undef str
6600+ }
6601+ si_read_unlock(sb);
6602+
6603+ err = 0;
6604+ file->private_data = p;
6605+ goto out; /* success */
6606+
6607+out_free:
1c60b727 6608+ free_page((unsigned long)p);
86dc4139
AM
6609+out:
6610+ return err;
6611+}
6612+
6613+static ssize_t dbgaufs_plink_read(struct file *file, char __user *buf,
6614+ size_t count, loff_t *ppos)
6615+{
6616+ struct dbgaufs_plink_arg *p;
6617+
6618+ p = file->private_data;
6619+ return simple_read_from_buffer(buf, count, ppos, p->a, p->n);
6620+}
6621+
6622+static const struct file_operations dbgaufs_plink_fop = {
6623+ .owner = THIS_MODULE,
6624+ .open = dbgaufs_plink_open,
6625+ .release = dbgaufs_plink_release,
6626+ .read = dbgaufs_plink_read
6627+};
6628+
6629+/* ---------------------------------------------------------------------- */
6630+
1facf9fc 6631+static int dbgaufs_xib_open(struct inode *inode, struct file *file)
6632+{
6633+ int err;
6634+ struct au_sbinfo *sbinfo;
6635+ struct super_block *sb;
6636+
6637+ sbinfo = inode->i_private;
6638+ sb = sbinfo->si_sb;
6639+ si_noflush_read_lock(sb);
062440b3 6640+ err = dbgaufs_xi_open(sbinfo->si_xib, file, /*do_fcnt*/0, /*cnt*/0);
1facf9fc 6641+ si_read_unlock(sb);
6642+ return err;
6643+}
6644+
6645+static const struct file_operations dbgaufs_xib_fop = {
4a4d8108 6646+ .owner = THIS_MODULE,
1facf9fc 6647+ .open = dbgaufs_xib_open,
6648+ .release = dbgaufs_xi_release,
6649+ .read = dbgaufs_xi_read
6650+};
6651+
6652+/* ---------------------------------------------------------------------- */
6653+
6654+#define DbgaufsXi_PREFIX "xi"
6655+
6656+static int dbgaufs_xino_open(struct inode *inode, struct file *file)
6657+{
acd2b654 6658+ int err, idx;
1facf9fc 6659+ long l;
acd2b654
AM
6660+ aufs_bindex_t bindex;
6661+ char *p, a[sizeof(DbgaufsXi_PREFIX) + 8];
1facf9fc 6662+ struct au_sbinfo *sbinfo;
6663+ struct super_block *sb;
acd2b654 6664+ struct au_xino *xi;
1facf9fc 6665+ struct file *xf;
6666+ struct qstr *name;
062440b3 6667+ struct au_branch *br;
1facf9fc 6668+
6669+ err = -ENOENT;
2000de60 6670+ name = &file->f_path.dentry->d_name;
1facf9fc 6671+ if (unlikely(name->len < sizeof(DbgaufsXi_PREFIX)
6672+ || memcmp(name->name, DbgaufsXi_PREFIX,
6673+ sizeof(DbgaufsXi_PREFIX) - 1)))
6674+ goto out;
acd2b654
AM
6675+
6676+ AuDebugOn(name->len >= sizeof(a));
6677+ memcpy(a, name->name, name->len);
6678+ a[name->len] = '\0';
6679+ p = strchr(a, '-');
6680+ if (p)
6681+ *p = '\0';
6682+ err = kstrtol(a + sizeof(DbgaufsXi_PREFIX) - 1, 10, &l);
1facf9fc 6683+ if (unlikely(err))
6684+ goto out;
acd2b654
AM
6685+ bindex = l;
6686+ idx = 0;
6687+ if (p) {
6688+ err = kstrtol(p + 1, 10, &l);
6689+ if (unlikely(err))
6690+ goto out;
6691+ idx = l;
6692+ }
1facf9fc 6693+
acd2b654 6694+ err = -ENOENT;
1facf9fc 6695+ sbinfo = inode->i_private;
6696+ sb = sbinfo->si_sb;
6697+ si_noflush_read_lock(sb);
acd2b654
AM
6698+ if (unlikely(bindex < 0 || bindex > au_sbbot(sb)))
6699+ goto out_si;
6700+ br = au_sbr(sb, bindex);
6701+ xi = br->br_xino;
6702+ if (unlikely(idx >= xi->xi_nfile))
6703+ goto out_si;
6704+ xf = au_xino_file(xi, idx);
6705+ if (xf)
062440b3
AM
6706+ err = dbgaufs_xi_open(xf, file, /*do_fcnt*/1,
6707+ au_xino_count(br));
1facf9fc 6708+
acd2b654
AM
6709+out_si:
6710+ si_read_unlock(sb);
4f0767ce 6711+out:
acd2b654 6712+ AuTraceErr(err);
1facf9fc 6713+ return err;
6714+}
6715+
6716+static const struct file_operations dbgaufs_xino_fop = {
4a4d8108 6717+ .owner = THIS_MODULE,
1facf9fc 6718+ .open = dbgaufs_xino_open,
6719+ .release = dbgaufs_xi_release,
6720+ .read = dbgaufs_xi_read
6721+};
6722+
062440b3
AM
6723+void dbgaufs_xino_del(struct au_branch *br)
6724+{
6725+ struct dentry *dbgaufs;
6726+
6727+ dbgaufs = br->br_dbgaufs;
6728+ if (!dbgaufs)
6729+ return;
6730+
6731+ br->br_dbgaufs = NULL;
6732+ /* debugfs acquires the parent i_mutex */
6733+ lockdep_off();
6734+ debugfs_remove(dbgaufs);
6735+ lockdep_on();
6736+}
6737+
1facf9fc 6738+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
6739+{
5afbbe0d 6740+ aufs_bindex_t bbot;
1facf9fc 6741+ struct au_branch *br;
1facf9fc 6742+
6743+ if (!au_sbi(sb)->si_dbgaufs)
6744+ return;
6745+
5afbbe0d
AM
6746+ bbot = au_sbbot(sb);
6747+ for (; bindex <= bbot; bindex++) {
1facf9fc 6748+ br = au_sbr(sb, bindex);
062440b3
AM
6749+ dbgaufs_xino_del(br);
6750+ }
6751+}
6752+
acd2b654
AM
6753+static void dbgaufs_br_do_add(struct super_block *sb, aufs_bindex_t bindex,
6754+ unsigned int idx, struct dentry *parent,
6755+ struct au_sbinfo *sbinfo)
062440b3
AM
6756+{
6757+ struct au_branch *br;
6758+ struct dentry *d;
acd2b654
AM
6759+ /* "xi" bindex(5) "-" idx(2) NULL */
6760+ char name[sizeof(DbgaufsXi_PREFIX) + 8];
062440b3 6761+
acd2b654
AM
6762+ if (!idx)
6763+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d", bindex);
6764+ else
6765+ snprintf(name, sizeof(name), DbgaufsXi_PREFIX "%d-%u",
6766+ bindex, idx);
062440b3
AM
6767+ br = au_sbr(sb, bindex);
6768+ if (br->br_dbgaufs) {
6769+ struct qstr qstr = QSTR_INIT(name, strlen(name));
6770+
6771+ if (!au_qstreq(&br->br_dbgaufs->d_name, &qstr)) {
6772+ /* debugfs acquires the parent i_mutex */
6773+ lockdep_off();
6774+ d = debugfs_rename(parent, br->br_dbgaufs, parent,
6775+ name);
6776+ lockdep_on();
6777+ if (unlikely(!d))
6778+ pr_warn("failed renaming %pd/%s, ignored.\n",
6779+ parent, name);
6780+ }
6781+ } else {
e2f27e51 6782+ lockdep_off();
062440b3
AM
6783+ br->br_dbgaufs = debugfs_create_file(name, dbgaufs_mode, parent,
6784+ sbinfo, &dbgaufs_xino_fop);
e2f27e51 6785+ lockdep_on();
062440b3 6786+ if (unlikely(!br->br_dbgaufs))
acd2b654 6787+ pr_warn("failed creating %pd/%s, ignored.\n",
062440b3 6788+ parent, name);
1facf9fc 6789+ }
6790+}
6791+
acd2b654
AM
6792+static void dbgaufs_br_add(struct super_block *sb, aufs_bindex_t bindex,
6793+ struct dentry *parent, struct au_sbinfo *sbinfo)
6794+{
6795+ struct au_branch *br;
6796+ struct au_xino *xi;
6797+ unsigned int u;
6798+
6799+ br = au_sbr(sb, bindex);
6800+ xi = br->br_xino;
6801+ for (u = 0; u < xi->xi_nfile; u++)
6802+ dbgaufs_br_do_add(sb, bindex, u, parent, sbinfo);
6803+}
6804+
062440b3 6805+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex, int topdown)
1facf9fc 6806+{
6807+ struct au_sbinfo *sbinfo;
6808+ struct dentry *parent;
5afbbe0d 6809+ aufs_bindex_t bbot;
062440b3
AM
6810+
6811+ if (!au_opt_test(au_mntflags(sb), XINO))
6812+ return;
1facf9fc 6813+
6814+ sbinfo = au_sbi(sb);
6815+ parent = sbinfo->si_dbgaufs;
6816+ if (!parent)
6817+ return;
6818+
5afbbe0d 6819+ bbot = au_sbbot(sb);
062440b3
AM
6820+ if (topdown)
6821+ for (; bindex <= bbot; bindex++)
6822+ dbgaufs_br_add(sb, bindex, parent, sbinfo);
6823+ else
6824+ for (; bbot >= bindex; bbot--)
6825+ dbgaufs_br_add(sb, bbot, parent, sbinfo);
1facf9fc 6826+}
6827+
6828+/* ---------------------------------------------------------------------- */
6829+
6830+#ifdef CONFIG_AUFS_EXPORT
6831+static int dbgaufs_xigen_open(struct inode *inode, struct file *file)
6832+{
6833+ int err;
6834+ struct au_sbinfo *sbinfo;
6835+ struct super_block *sb;
6836+
6837+ sbinfo = inode->i_private;
6838+ sb = sbinfo->si_sb;
6839+ si_noflush_read_lock(sb);
062440b3 6840+ err = dbgaufs_xi_open(sbinfo->si_xigen, file, /*do_fcnt*/0, /*cnt*/0);
1facf9fc 6841+ si_read_unlock(sb);
6842+ return err;
6843+}
6844+
6845+static const struct file_operations dbgaufs_xigen_fop = {
4a4d8108 6846+ .owner = THIS_MODULE,
1facf9fc 6847+ .open = dbgaufs_xigen_open,
6848+ .release = dbgaufs_xi_release,
6849+ .read = dbgaufs_xi_read
6850+};
6851+
6852+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
6853+{
6854+ int err;
6855+
dece6358 6856+ /*
c1595e42 6857+ * This function is a dynamic '__init' function actually,
dece6358
AM
6858+ * so the tiny check for si_rwsem is unnecessary.
6859+ */
6860+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
6861+
1facf9fc 6862+ err = -EIO;
6863+ sbinfo->si_dbgaufs_xigen = debugfs_create_file
6864+ ("xigen", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
6865+ &dbgaufs_xigen_fop);
6866+ if (sbinfo->si_dbgaufs_xigen)
6867+ err = 0;
6868+
6869+ return err;
6870+}
6871+#else
6872+static int dbgaufs_xigen_init(struct au_sbinfo *sbinfo)
6873+{
6874+ return 0;
6875+}
6876+#endif /* CONFIG_AUFS_EXPORT */
6877+
6878+/* ---------------------------------------------------------------------- */
6879+
6880+void dbgaufs_si_fin(struct au_sbinfo *sbinfo)
6881+{
dece6358 6882+ /*
7e9cd9fe 6883+ * This function is a dynamic '__fin' function actually,
dece6358
AM
6884+ * so the tiny check for si_rwsem is unnecessary.
6885+ */
6886+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
6887+
1facf9fc 6888+ debugfs_remove_recursive(sbinfo->si_dbgaufs);
6889+ sbinfo->si_dbgaufs = NULL;
1facf9fc 6890+}
6891+
6892+int dbgaufs_si_init(struct au_sbinfo *sbinfo)
6893+{
6894+ int err;
6895+ char name[SysaufsSiNameLen];
6896+
dece6358 6897+ /*
c1595e42 6898+ * This function is a dynamic '__init' function actually,
dece6358
AM
6899+ * so the tiny check for si_rwsem is unnecessary.
6900+ */
6901+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
6902+
1facf9fc 6903+ err = -ENOENT;
6904+ if (!dbgaufs) {
6905+ AuErr1("/debug/aufs is uninitialized\n");
6906+ goto out;
6907+ }
6908+
6909+ err = -EIO;
6910+ sysaufs_name(sbinfo, name);
6911+ sbinfo->si_dbgaufs = debugfs_create_dir(name, dbgaufs);
6912+ if (unlikely(!sbinfo->si_dbgaufs))
6913+ goto out;
1facf9fc 6914+
062440b3 6915+ /* regardless plink/noplink option */
86dc4139
AM
6916+ sbinfo->si_dbgaufs_plink = debugfs_create_file
6917+ ("plink", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
6918+ &dbgaufs_plink_fop);
6919+ if (unlikely(!sbinfo->si_dbgaufs_plink))
6920+ goto out_dir;
6921+
062440b3
AM
6922+ /* regardless xino/noxino option */
6923+ sbinfo->si_dbgaufs_xib = debugfs_create_file
6924+ ("xib", dbgaufs_mode, sbinfo->si_dbgaufs, sbinfo,
6925+ &dbgaufs_xib_fop);
6926+ if (unlikely(!sbinfo->si_dbgaufs_xib))
6927+ goto out_dir;
6928+
1facf9fc 6929+ err = dbgaufs_xigen_init(sbinfo);
6930+ if (!err)
6931+ goto out; /* success */
6932+
4f0767ce 6933+out_dir:
1facf9fc 6934+ dbgaufs_si_fin(sbinfo);
4f0767ce 6935+out:
062440b3
AM
6936+ if (unlikely(err))
6937+ pr_err("debugfs/aufs failed\n");
1facf9fc 6938+ return err;
6939+}
6940+
6941+/* ---------------------------------------------------------------------- */
6942+
6943+void dbgaufs_fin(void)
6944+{
6945+ debugfs_remove(dbgaufs);
6946+}
6947+
6948+int __init dbgaufs_init(void)
6949+{
6950+ int err;
6951+
6952+ err = -EIO;
6953+ dbgaufs = debugfs_create_dir(AUFS_NAME, NULL);
6954+ if (dbgaufs)
6955+ err = 0;
6956+ return err;
6957+}
7f207e10 6958diff -urN /usr/share/empty/fs/aufs/dbgaufs.h linux/fs/aufs/dbgaufs.h
eca34b5c 6959--- /usr/share/empty/fs/aufs/dbgaufs.h 1970-01-01 01:00:00.000000000 +0100
016522bc 6960+++ linux/fs/aufs/dbgaufs.h 2020-01-27 10:57:18.168871450 +0100
062440b3
AM
6961@@ -0,0 +1,53 @@
6962+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 6963+/*
016522bc 6964+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 6965+ *
6966+ * This program, aufs is free software; you can redistribute it and/or modify
6967+ * it under the terms of the GNU General Public License as published by
6968+ * the Free Software Foundation; either version 2 of the License, or
6969+ * (at your option) any later version.
dece6358
AM
6970+ *
6971+ * This program is distributed in the hope that it will be useful,
6972+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6973+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6974+ * GNU General Public License for more details.
6975+ *
6976+ * You should have received a copy of the GNU General Public License
523b37e3 6977+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 6978+ */
6979+
6980+/*
6981+ * debugfs interface
6982+ */
6983+
6984+#ifndef __DBGAUFS_H__
6985+#define __DBGAUFS_H__
6986+
6987+#ifdef __KERNEL__
6988+
dece6358 6989+struct super_block;
1facf9fc 6990+struct au_sbinfo;
062440b3 6991+struct au_branch;
dece6358 6992+
1facf9fc 6993+#ifdef CONFIG_DEBUG_FS
6994+/* dbgaufs.c */
062440b3 6995+void dbgaufs_xino_del(struct au_branch *br);
1facf9fc 6996+void dbgaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
062440b3 6997+void dbgaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex, int topdown);
1facf9fc 6998+void dbgaufs_si_fin(struct au_sbinfo *sbinfo);
6999+int dbgaufs_si_init(struct au_sbinfo *sbinfo);
7000+void dbgaufs_fin(void);
7001+int __init dbgaufs_init(void);
1facf9fc 7002+#else
062440b3 7003+AuStubVoid(dbgaufs_xino_del, struct au_branch *br)
4a4d8108 7004+AuStubVoid(dbgaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
062440b3
AM
7005+AuStubVoid(dbgaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex,
7006+ int topdown)
4a4d8108
AM
7007+AuStubVoid(dbgaufs_si_fin, struct au_sbinfo *sbinfo)
7008+AuStubInt0(dbgaufs_si_init, struct au_sbinfo *sbinfo)
7009+AuStubVoid(dbgaufs_fin, void)
7010+AuStubInt0(__init dbgaufs_init, void)
1facf9fc 7011+#endif /* CONFIG_DEBUG_FS */
7012+
7013+#endif /* __KERNEL__ */
7014+#endif /* __DBGAUFS_H__ */
7f207e10 7015diff -urN /usr/share/empty/fs/aufs/dcsub.c linux/fs/aufs/dcsub.c
eca34b5c 7016--- /usr/share/empty/fs/aufs/dcsub.c 1970-01-01 01:00:00.000000000 +0100
016522bc 7017+++ linux/fs/aufs/dcsub.c 2020-01-27 10:57:18.168871450 +0100
cd7a4cd9
AM
7018@@ -0,0 +1,225 @@
7019+// SPDX-License-Identifier: GPL-2.0
1facf9fc 7020+/*
016522bc 7021+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 7022+ *
7023+ * This program, aufs is free software; you can redistribute it and/or modify
7024+ * it under the terms of the GNU General Public License as published by
7025+ * the Free Software Foundation; either version 2 of the License, or
7026+ * (at your option) any later version.
dece6358
AM
7027+ *
7028+ * This program is distributed in the hope that it will be useful,
7029+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7030+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7031+ * GNU General Public License for more details.
7032+ *
7033+ * You should have received a copy of the GNU General Public License
523b37e3 7034+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7035+ */
7036+
7037+/*
7038+ * sub-routines for dentry cache
7039+ */
7040+
7041+#include "aufs.h"
7042+
7043+static void au_dpage_free(struct au_dpage *dpage)
7044+{
7045+ int i;
7046+ struct dentry **p;
7047+
7048+ p = dpage->dentries;
7049+ for (i = 0; i < dpage->ndentry; i++)
7050+ dput(*p++);
1c60b727 7051+ free_page((unsigned long)dpage->dentries);
1facf9fc 7052+}
7053+
7054+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp)
7055+{
7056+ int err;
7057+ void *p;
7058+
7059+ err = -ENOMEM;
7060+ dpages->dpages = kmalloc(sizeof(*dpages->dpages), gfp);
7061+ if (unlikely(!dpages->dpages))
7062+ goto out;
7063+
7064+ p = (void *)__get_free_page(gfp);
7065+ if (unlikely(!p))
7066+ goto out_dpages;
7067+
7068+ dpages->dpages[0].ndentry = 0;
7069+ dpages->dpages[0].dentries = p;
7070+ dpages->ndpage = 1;
7071+ return 0; /* success */
7072+
4f0767ce 7073+out_dpages:
9f237c51 7074+ au_kfree_try_rcu(dpages->dpages);
4f0767ce 7075+out:
1facf9fc 7076+ return err;
7077+}
7078+
7079+void au_dpages_free(struct au_dcsub_pages *dpages)
7080+{
7081+ int i;
7082+ struct au_dpage *p;
7083+
7084+ p = dpages->dpages;
7085+ for (i = 0; i < dpages->ndpage; i++)
7086+ au_dpage_free(p++);
9f237c51 7087+ au_kfree_try_rcu(dpages->dpages);
1facf9fc 7088+}
7089+
7090+static int au_dpages_append(struct au_dcsub_pages *dpages,
7091+ struct dentry *dentry, gfp_t gfp)
7092+{
7093+ int err, sz;
7094+ struct au_dpage *dpage;
7095+ void *p;
7096+
7097+ dpage = dpages->dpages + dpages->ndpage - 1;
7098+ sz = PAGE_SIZE / sizeof(dentry);
7099+ if (unlikely(dpage->ndentry >= sz)) {
7100+ AuLabel(new dpage);
7101+ err = -ENOMEM;
7102+ sz = dpages->ndpage * sizeof(*dpages->dpages);
7103+ p = au_kzrealloc(dpages->dpages, sz,
e2f27e51
AM
7104+ sz + sizeof(*dpages->dpages), gfp,
7105+ /*may_shrink*/0);
1facf9fc 7106+ if (unlikely(!p))
7107+ goto out;
7108+
7109+ dpages->dpages = p;
7110+ dpage = dpages->dpages + dpages->ndpage;
7111+ p = (void *)__get_free_page(gfp);
7112+ if (unlikely(!p))
7113+ goto out;
7114+
7115+ dpage->ndentry = 0;
7116+ dpage->dentries = p;
7117+ dpages->ndpage++;
7118+ }
7119+
c1595e42 7120+ AuDebugOn(au_dcount(dentry) <= 0);
027c5e7a 7121+ dpage->dentries[dpage->ndentry++] = dget_dlock(dentry);
1facf9fc 7122+ return 0; /* success */
7123+
4f0767ce 7124+out:
1facf9fc 7125+ return err;
7126+}
7127+
c1595e42
JR
7128+/* todo: BAD approach */
7129+/* copied from linux/fs/dcache.c */
7130+enum d_walk_ret {
7131+ D_WALK_CONTINUE,
7132+ D_WALK_QUIT,
7133+ D_WALK_NORETRY,
7134+ D_WALK_SKIP,
7135+};
7136+
7137+extern void d_walk(struct dentry *parent, void *data,
cd7a4cd9 7138+ enum d_walk_ret (*enter)(void *, struct dentry *));
c1595e42
JR
7139+
7140+struct ac_dpages_arg {
1facf9fc 7141+ int err;
c1595e42
JR
7142+ struct au_dcsub_pages *dpages;
7143+ struct super_block *sb;
7144+ au_dpages_test test;
7145+ void *arg;
7146+};
1facf9fc 7147+
c1595e42
JR
7148+static enum d_walk_ret au_call_dpages_append(void *_arg, struct dentry *dentry)
7149+{
7150+ enum d_walk_ret ret;
7151+ struct ac_dpages_arg *arg = _arg;
1facf9fc 7152+
c1595e42
JR
7153+ ret = D_WALK_CONTINUE;
7154+ if (dentry->d_sb == arg->sb
7155+ && !IS_ROOT(dentry)
7156+ && au_dcount(dentry) > 0
7157+ && au_di(dentry)
7158+ && (!arg->test || arg->test(dentry, arg->arg))) {
7159+ arg->err = au_dpages_append(arg->dpages, dentry, GFP_ATOMIC);
7160+ if (unlikely(arg->err))
7161+ ret = D_WALK_QUIT;
1facf9fc 7162+ }
7163+
c1595e42
JR
7164+ return ret;
7165+}
027c5e7a 7166+
c1595e42
JR
7167+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
7168+ au_dpages_test test, void *arg)
7169+{
7170+ struct ac_dpages_arg args = {
7171+ .err = 0,
7172+ .dpages = dpages,
7173+ .sb = root->d_sb,
7174+ .test = test,
7175+ .arg = arg
7176+ };
027c5e7a 7177+
cd7a4cd9 7178+ d_walk(root, &args, au_call_dpages_append);
c1595e42
JR
7179+
7180+ return args.err;
1facf9fc 7181+}
7182+
7183+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
7184+ int do_include, au_dpages_test test, void *arg)
7185+{
7186+ int err;
7187+
7188+ err = 0;
027c5e7a
AM
7189+ write_seqlock(&rename_lock);
7190+ spin_lock(&dentry->d_lock);
7191+ if (do_include
c1595e42 7192+ && au_dcount(dentry) > 0
027c5e7a 7193+ && (!test || test(dentry, arg)))
1facf9fc 7194+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
7195+ spin_unlock(&dentry->d_lock);
7196+ if (unlikely(err))
7197+ goto out;
7198+
7199+ /*
523b37e3 7200+ * RCU for vfsmount is unnecessary since this is a traverse in a single
027c5e7a
AM
7201+ * mount
7202+ */
1facf9fc 7203+ while (!IS_ROOT(dentry)) {
027c5e7a
AM
7204+ dentry = dentry->d_parent; /* rename_lock is locked */
7205+ spin_lock(&dentry->d_lock);
c1595e42 7206+ if (au_dcount(dentry) > 0
027c5e7a 7207+ && (!test || test(dentry, arg)))
1facf9fc 7208+ err = au_dpages_append(dpages, dentry, GFP_ATOMIC);
027c5e7a
AM
7209+ spin_unlock(&dentry->d_lock);
7210+ if (unlikely(err))
7211+ break;
1facf9fc 7212+ }
7213+
4f0767ce 7214+out:
027c5e7a 7215+ write_sequnlock(&rename_lock);
1facf9fc 7216+ return err;
7217+}
7218+
027c5e7a
AM
7219+static inline int au_dcsub_dpages_aufs(struct dentry *dentry, void *arg)
7220+{
7221+ return au_di(dentry) && dentry->d_sb == arg;
7222+}
7223+
7224+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
7225+ struct dentry *dentry, int do_include)
7226+{
7227+ return au_dcsub_pages_rev(dpages, dentry, do_include,
7228+ au_dcsub_dpages_aufs, dentry->d_sb);
7229+}
7230+
4a4d8108 7231+int au_test_subdir(struct dentry *d1, struct dentry *d2)
1facf9fc 7232+{
4a4d8108
AM
7233+ struct path path[2] = {
7234+ {
7235+ .dentry = d1
7236+ },
7237+ {
7238+ .dentry = d2
7239+ }
7240+ };
1facf9fc 7241+
4a4d8108 7242+ return path_is_under(path + 0, path + 1);
1facf9fc 7243+}
7f207e10 7244diff -urN /usr/share/empty/fs/aufs/dcsub.h linux/fs/aufs/dcsub.h
eca34b5c 7245--- /usr/share/empty/fs/aufs/dcsub.h 1970-01-01 01:00:00.000000000 +0100
016522bc 7246+++ linux/fs/aufs/dcsub.h 2020-01-27 10:57:18.168871450 +0100
062440b3
AM
7247@@ -0,0 +1,137 @@
7248+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 7249+/*
016522bc 7250+ * Copyright (C) 2005-2020 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+ * sub-routines for dentry cache
7268+ */
7269+
7270+#ifndef __AUFS_DCSUB_H__
7271+#define __AUFS_DCSUB_H__
7272+
7273+#ifdef __KERNEL__
7274+
7f207e10 7275+#include <linux/dcache.h>
027c5e7a 7276+#include <linux/fs.h>
dece6358 7277+
1facf9fc 7278+struct au_dpage {
7279+ int ndentry;
7280+ struct dentry **dentries;
7281+};
7282+
7283+struct au_dcsub_pages {
7284+ int ndpage;
7285+ struct au_dpage *dpages;
7286+};
7287+
7288+/* ---------------------------------------------------------------------- */
7289+
7f207e10 7290+/* dcsub.c */
1facf9fc 7291+int au_dpages_init(struct au_dcsub_pages *dpages, gfp_t gfp);
7292+void au_dpages_free(struct au_dcsub_pages *dpages);
7293+typedef int (*au_dpages_test)(struct dentry *dentry, void *arg);
7294+int au_dcsub_pages(struct au_dcsub_pages *dpages, struct dentry *root,
7295+ au_dpages_test test, void *arg);
7296+int au_dcsub_pages_rev(struct au_dcsub_pages *dpages, struct dentry *dentry,
7297+ int do_include, au_dpages_test test, void *arg);
027c5e7a
AM
7298+int au_dcsub_pages_rev_aufs(struct au_dcsub_pages *dpages,
7299+ struct dentry *dentry, int do_include);
4a4d8108 7300+int au_test_subdir(struct dentry *d1, struct dentry *d2);
1facf9fc 7301+
7f207e10
AM
7302+/* ---------------------------------------------------------------------- */
7303+
523b37e3
AM
7304+/*
7305+ * todo: in linux-3.13, several similar (but faster) helpers are added to
7306+ * include/linux/dcache.h. Try them (in the future).
7307+ */
7308+
027c5e7a
AM
7309+static inline int au_d_hashed_positive(struct dentry *d)
7310+{
7311+ int err;
5527c038 7312+ struct inode *inode = d_inode(d);
076b876e 7313+
027c5e7a 7314+ err = 0;
5527c038
JR
7315+ if (unlikely(d_unhashed(d)
7316+ || d_is_negative(d)
7317+ || !inode->i_nlink))
027c5e7a
AM
7318+ err = -ENOENT;
7319+ return err;
7320+}
7321+
38d290e6
JR
7322+static inline int au_d_linkable(struct dentry *d)
7323+{
7324+ int err;
5527c038 7325+ struct inode *inode = d_inode(d);
076b876e 7326+
38d290e6
JR
7327+ err = au_d_hashed_positive(d);
7328+ if (err
5527c038 7329+ && d_is_positive(d)
38d290e6
JR
7330+ && (inode->i_state & I_LINKABLE))
7331+ err = 0;
7332+ return err;
7333+}
7334+
027c5e7a
AM
7335+static inline int au_d_alive(struct dentry *d)
7336+{
7337+ int err;
7338+ struct inode *inode;
076b876e 7339+
027c5e7a
AM
7340+ err = 0;
7341+ if (!IS_ROOT(d))
7342+ err = au_d_hashed_positive(d);
7343+ else {
5527c038
JR
7344+ inode = d_inode(d);
7345+ if (unlikely(d_unlinked(d)
7346+ || d_is_negative(d)
7347+ || !inode->i_nlink))
027c5e7a
AM
7348+ err = -ENOENT;
7349+ }
7350+ return err;
7351+}
7352+
7353+static inline int au_alive_dir(struct dentry *d)
7f207e10 7354+{
027c5e7a 7355+ int err;
076b876e 7356+
027c5e7a 7357+ err = au_d_alive(d);
5527c038 7358+ if (unlikely(err || IS_DEADDIR(d_inode(d))))
027c5e7a
AM
7359+ err = -ENOENT;
7360+ return err;
7f207e10
AM
7361+}
7362+
38d290e6
JR
7363+static inline int au_qstreq(struct qstr *a, struct qstr *b)
7364+{
7365+ return a->len == b->len
7366+ && !memcmp(a->name, b->name, a->len);
7367+}
7368+
7e9cd9fe
AM
7369+/*
7370+ * by the commit
7371+ * 360f547 2015-01-25 dcache: let the dentry count go down to zero without
7372+ * taking d_lock
7373+ * the type of d_lockref.count became int, but the inlined function d_count()
7374+ * still returns unsigned int.
7375+ * I don't know why. Maybe it is for every d_count() users?
7376+ * Anyway au_dcount() lives on.
7377+ */
c1595e42
JR
7378+static inline int au_dcount(struct dentry *d)
7379+{
7380+ return (int)d_count(d);
7381+}
7382+
1facf9fc 7383+#endif /* __KERNEL__ */
7384+#endif /* __AUFS_DCSUB_H__ */
7f207e10 7385diff -urN /usr/share/empty/fs/aufs/debug.c linux/fs/aufs/debug.c
eca34b5c 7386--- /usr/share/empty/fs/aufs/debug.c 1970-01-01 01:00:00.000000000 +0100
016522bc 7387+++ linux/fs/aufs/debug.c 2020-01-27 10:57:18.168871450 +0100
eca801bf 7388@@ -0,0 +1,441 @@
cd7a4cd9 7389+// SPDX-License-Identifier: GPL-2.0
1facf9fc 7390+/*
016522bc 7391+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 7392+ *
7393+ * This program, aufs is free software; you can redistribute it and/or modify
7394+ * it under the terms of the GNU General Public License as published by
7395+ * the Free Software Foundation; either version 2 of the License, or
7396+ * (at your option) any later version.
dece6358
AM
7397+ *
7398+ * This program is distributed in the hope that it will be useful,
7399+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7400+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7401+ * GNU General Public License for more details.
7402+ *
7403+ * You should have received a copy of the GNU General Public License
523b37e3 7404+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7405+ */
7406+
7407+/*
7408+ * debug print functions
7409+ */
7410+
eca801bf 7411+#include <linux/iversion.h>
1facf9fc 7412+#include "aufs.h"
7413+
392086de
AM
7414+/* Returns 0, or -errno. arg is in kp->arg. */
7415+static int param_atomic_t_set(const char *val, const struct kernel_param *kp)
7416+{
7417+ int err, n;
7418+
7419+ err = kstrtoint(val, 0, &n);
7420+ if (!err) {
7421+ if (n > 0)
7422+ au_debug_on();
7423+ else
7424+ au_debug_off();
7425+ }
7426+ return err;
7427+}
7428+
7429+/* Returns length written or -errno. Buffer is 4k (ie. be short!) */
7430+static int param_atomic_t_get(char *buffer, const struct kernel_param *kp)
7431+{
7432+ atomic_t *a;
7433+
7434+ a = kp->arg;
7435+ return sprintf(buffer, "%d", atomic_read(a));
7436+}
7437+
7438+static struct kernel_param_ops param_ops_atomic_t = {
7439+ .set = param_atomic_t_set,
7440+ .get = param_atomic_t_get
7441+ /* void (*free)(void *arg) */
7442+};
7443+
7444+atomic_t aufs_debug = ATOMIC_INIT(0);
1facf9fc 7445+MODULE_PARM_DESC(debug, "debug print");
cd7a4cd9 7446+module_param_named(debug, aufs_debug, atomic_t, 0664);
1facf9fc 7447+
c1595e42 7448+DEFINE_MUTEX(au_dbg_mtx); /* just to serialize the dbg msgs */
1facf9fc 7449+char *au_plevel = KERN_DEBUG;
e49829fe
JR
7450+#define dpri(fmt, ...) do { \
7451+ if ((au_plevel \
7452+ && strcmp(au_plevel, KERN_DEBUG)) \
7453+ || au_debug_test()) \
7454+ printk("%s" fmt, au_plevel, ##__VA_ARGS__); \
1facf9fc 7455+} while (0)
7456+
7457+/* ---------------------------------------------------------------------- */
7458+
7459+void au_dpri_whlist(struct au_nhash *whlist)
7460+{
7461+ unsigned long ul, n;
7462+ struct hlist_head *head;
c06a8ce3 7463+ struct au_vdir_wh *pos;
1facf9fc 7464+
7465+ n = whlist->nh_num;
7466+ head = whlist->nh_head;
7467+ for (ul = 0; ul < n; ul++) {
c06a8ce3 7468+ hlist_for_each_entry(pos, head, wh_hash)
1facf9fc 7469+ dpri("b%d, %.*s, %d\n",
c06a8ce3
AM
7470+ pos->wh_bindex,
7471+ pos->wh_str.len, pos->wh_str.name,
7472+ pos->wh_str.len);
1facf9fc 7473+ head++;
7474+ }
7475+}
7476+
7477+void au_dpri_vdir(struct au_vdir *vdir)
7478+{
7479+ unsigned long ul;
7480+ union au_vdir_deblk_p p;
7481+ unsigned char *o;
7482+
7483+ if (!vdir || IS_ERR(vdir)) {
7484+ dpri("err %ld\n", PTR_ERR(vdir));
7485+ return;
7486+ }
7487+
be118d29 7488+ dpri("deblk %u, nblk %lu, deblk %p, last{%lu, %p}, ver %llu\n",
1facf9fc 7489+ vdir->vd_deblk_sz, vdir->vd_nblk, vdir->vd_deblk,
7490+ vdir->vd_last.ul, vdir->vd_last.p.deblk, vdir->vd_version);
7491+ for (ul = 0; ul < vdir->vd_nblk; ul++) {
7492+ p.deblk = vdir->vd_deblk[ul];
7493+ o = p.deblk;
7494+ dpri("[%lu]: %p\n", ul, o);
7495+ }
7496+}
7497+
53392da6 7498+static int do_pri_inode(aufs_bindex_t bindex, struct inode *inode, int hn,
1facf9fc 7499+ struct dentry *wh)
7500+{
7501+ char *n = NULL;
7502+ int l = 0;
7503+
7504+ if (!inode || IS_ERR(inode)) {
7505+ dpri("i%d: err %ld\n", bindex, PTR_ERR(inode));
7506+ return -1;
7507+ }
7508+
c2b27bf2 7509+ /* the type of i_blocks depends upon CONFIG_LBDAF */
1facf9fc 7510+ BUILD_BUG_ON(sizeof(inode->i_blocks) != sizeof(unsigned long)
7511+ && sizeof(inode->i_blocks) != sizeof(u64));
7512+ if (wh) {
7513+ n = (void *)wh->d_name.name;
7514+ l = wh->d_name.len;
7515+ }
7516+
53392da6
AM
7517+ dpri("i%d: %p, i%lu, %s, cnt %d, nl %u, 0%o, sz %llu, blk %llu,"
7518+ " hn %d, ct %lld, np %lu, st 0x%lx, f 0x%x, v %llu, g %x%s%.*s\n",
7519+ bindex, inode,
1facf9fc 7520+ inode->i_ino, inode->i_sb ? au_sbtype(inode->i_sb) : "??",
7521+ atomic_read(&inode->i_count), inode->i_nlink, inode->i_mode,
7522+ i_size_read(inode), (unsigned long long)inode->i_blocks,
cd7a4cd9 7523+ hn, (long long)timespec64_to_ns(&inode->i_ctime) & 0x0ffff,
1facf9fc 7524+ inode->i_mapping ? inode->i_mapping->nrpages : 0,
be118d29 7525+ inode->i_state, inode->i_flags, inode_peek_iversion(inode),
b752ccd1 7526+ inode->i_generation,
1facf9fc 7527+ l ? ", wh " : "", l, n);
7528+ return 0;
7529+}
7530+
7531+void au_dpri_inode(struct inode *inode)
7532+{
7533+ struct au_iinfo *iinfo;
5afbbe0d 7534+ struct au_hinode *hi;
1facf9fc 7535+ aufs_bindex_t bindex;
53392da6 7536+ int err, hn;
1facf9fc 7537+
53392da6 7538+ err = do_pri_inode(-1, inode, -1, NULL);
5afbbe0d 7539+ if (err || !au_test_aufs(inode->i_sb) || au_is_bad_inode(inode))
1facf9fc 7540+ return;
7541+
7542+ iinfo = au_ii(inode);
5afbbe0d
AM
7543+ dpri("i-1: btop %d, bbot %d, gen %d\n",
7544+ iinfo->ii_btop, iinfo->ii_bbot, au_iigen(inode, NULL));
7545+ if (iinfo->ii_btop < 0)
1facf9fc 7546+ return;
53392da6 7547+ hn = 0;
5afbbe0d
AM
7548+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot; bindex++) {
7549+ hi = au_hinode(iinfo, bindex);
7550+ hn = !!au_hn(hi);
7551+ do_pri_inode(bindex, hi->hi_inode, hn, hi->hi_whdentry);
53392da6 7552+ }
1facf9fc 7553+}
7554+
2cbb1c4b
JR
7555+void au_dpri_dalias(struct inode *inode)
7556+{
7557+ struct dentry *d;
7558+
7559+ spin_lock(&inode->i_lock);
c1595e42 7560+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias)
2cbb1c4b
JR
7561+ au_dpri_dentry(d);
7562+ spin_unlock(&inode->i_lock);
7563+}
7564+
1facf9fc 7565+static int do_pri_dentry(aufs_bindex_t bindex, struct dentry *dentry)
7566+{
7567+ struct dentry *wh = NULL;
53392da6 7568+ int hn;
5afbbe0d 7569+ struct inode *inode;
076b876e 7570+ struct au_iinfo *iinfo;
5afbbe0d 7571+ struct au_hinode *hi;
1facf9fc 7572+
7573+ if (!dentry || IS_ERR(dentry)) {
7574+ dpri("d%d: err %ld\n", bindex, PTR_ERR(dentry));
7575+ return -1;
7576+ }
7577+ /* do not call dget_parent() here */
027c5e7a 7578+ /* note: access d_xxx without d_lock */
523b37e3
AM
7579+ dpri("d%d: %p, %pd2?, %s, cnt %d, flags 0x%x, %shashed\n",
7580+ bindex, dentry, dentry,
1facf9fc 7581+ dentry->d_sb ? au_sbtype(dentry->d_sb) : "??",
c1595e42 7582+ au_dcount(dentry), dentry->d_flags,
523b37e3 7583+ d_unhashed(dentry) ? "un" : "");
53392da6 7584+ hn = -1;
5afbbe0d
AM
7585+ inode = NULL;
7586+ if (d_is_positive(dentry))
7587+ inode = d_inode(dentry);
7588+ if (inode
7589+ && au_test_aufs(dentry->d_sb)
7590+ && bindex >= 0
7591+ && !au_is_bad_inode(inode)) {
7592+ iinfo = au_ii(inode);
7593+ hi = au_hinode(iinfo, bindex);
7594+ hn = !!au_hn(hi);
7595+ wh = hi->hi_whdentry;
7596+ }
7597+ do_pri_inode(bindex, inode, hn, wh);
1facf9fc 7598+ return 0;
7599+}
7600+
7601+void au_dpri_dentry(struct dentry *dentry)
7602+{
7603+ struct au_dinfo *dinfo;
7604+ aufs_bindex_t bindex;
7605+ int err;
7606+
7607+ err = do_pri_dentry(-1, dentry);
7608+ if (err || !au_test_aufs(dentry->d_sb))
7609+ return;
7610+
7611+ dinfo = au_di(dentry);
7612+ if (!dinfo)
7613+ return;
5afbbe0d
AM
7614+ dpri("d-1: btop %d, bbot %d, bwh %d, bdiropq %d, gen %d, tmp %d\n",
7615+ dinfo->di_btop, dinfo->di_bbot,
38d290e6
JR
7616+ dinfo->di_bwh, dinfo->di_bdiropq, au_digen(dentry),
7617+ dinfo->di_tmpfile);
5afbbe0d 7618+ if (dinfo->di_btop < 0)
1facf9fc 7619+ return;
5afbbe0d
AM
7620+ for (bindex = dinfo->di_btop; bindex <= dinfo->di_bbot; bindex++)
7621+ do_pri_dentry(bindex, au_hdentry(dinfo, bindex)->hd_dentry);
1facf9fc 7622+}
7623+
7624+static int do_pri_file(aufs_bindex_t bindex, struct file *file)
7625+{
7626+ char a[32];
7627+
7628+ if (!file || IS_ERR(file)) {
7629+ dpri("f%d: err %ld\n", bindex, PTR_ERR(file));
7630+ return -1;
7631+ }
7632+ a[0] = 0;
7633+ if (bindex < 0
b912730e 7634+ && !IS_ERR_OR_NULL(file->f_path.dentry)
2000de60 7635+ && au_test_aufs(file->f_path.dentry->d_sb)
1facf9fc 7636+ && au_fi(file))
e49829fe 7637+ snprintf(a, sizeof(a), ", gen %d, mmapped %d",
2cbb1c4b 7638+ au_figen(file), atomic_read(&au_fi(file)->fi_mmapped));
b752ccd1 7639+ dpri("f%d: mode 0x%x, flags 0%o, cnt %ld, v %llu, pos %llu%s\n",
1facf9fc 7640+ bindex, file->f_mode, file->f_flags, (long)file_count(file),
b752ccd1 7641+ file->f_version, file->f_pos, a);
b912730e 7642+ if (!IS_ERR_OR_NULL(file->f_path.dentry))
2000de60 7643+ do_pri_dentry(bindex, file->f_path.dentry);
1facf9fc 7644+ return 0;
7645+}
7646+
7647+void au_dpri_file(struct file *file)
7648+{
7649+ struct au_finfo *finfo;
4a4d8108
AM
7650+ struct au_fidir *fidir;
7651+ struct au_hfile *hfile;
1facf9fc 7652+ aufs_bindex_t bindex;
7653+ int err;
7654+
7655+ err = do_pri_file(-1, file);
2000de60 7656+ if (err
b912730e 7657+ || IS_ERR_OR_NULL(file->f_path.dentry)
2000de60 7658+ || !au_test_aufs(file->f_path.dentry->d_sb))
1facf9fc 7659+ return;
7660+
7661+ finfo = au_fi(file);
7662+ if (!finfo)
7663+ return;
4a4d8108 7664+ if (finfo->fi_btop < 0)
1facf9fc 7665+ return;
4a4d8108
AM
7666+ fidir = finfo->fi_hdir;
7667+ if (!fidir)
7668+ do_pri_file(finfo->fi_btop, finfo->fi_htop.hf_file);
7669+ else
e49829fe
JR
7670+ for (bindex = finfo->fi_btop;
7671+ bindex >= 0 && bindex <= fidir->fd_bbot;
4a4d8108
AM
7672+ bindex++) {
7673+ hfile = fidir->fd_hfile + bindex;
7674+ do_pri_file(bindex, hfile ? hfile->hf_file : NULL);
7675+ }
1facf9fc 7676+}
7677+
7678+static int do_pri_br(aufs_bindex_t bindex, struct au_branch *br)
7679+{
7680+ struct vfsmount *mnt;
7681+ struct super_block *sb;
7682+
7683+ if (!br || IS_ERR(br))
7684+ goto out;
86dc4139 7685+ mnt = au_br_mnt(br);
1facf9fc 7686+ if (!mnt || IS_ERR(mnt))
7687+ goto out;
7688+ sb = mnt->mnt_sb;
7689+ if (!sb || IS_ERR(sb))
7690+ goto out;
7691+
acd2b654 7692+ dpri("s%d: {perm 0x%x, id %d, wbr %p}, "
b752ccd1 7693+ "%s, dev 0x%02x%02x, flags 0x%lx, cnt %d, active %d, "
1facf9fc 7694+ "xino %d\n",
acd2b654
AM
7695+ bindex, br->br_perm, br->br_id, br->br_wbr,
7696+ au_sbtype(sb), MAJOR(sb->s_dev), MINOR(sb->s_dev),
b752ccd1 7697+ sb->s_flags, sb->s_count,
acd2b654
AM
7698+ atomic_read(&sb->s_active),
7699+ !!au_xino_file(br->br_xino, /*idx*/-1));
1facf9fc 7700+ return 0;
7701+
4f0767ce 7702+out:
1facf9fc 7703+ dpri("s%d: err %ld\n", bindex, PTR_ERR(br));
7704+ return -1;
7705+}
7706+
7707+void au_dpri_sb(struct super_block *sb)
7708+{
7709+ struct au_sbinfo *sbinfo;
7710+ aufs_bindex_t bindex;
7711+ int err;
acd2b654 7712+ /* to reduce stack size */
1facf9fc 7713+ struct {
7714+ struct vfsmount mnt;
7715+ struct au_branch fake;
7716+ } *a;
7717+
7718+ /* this function can be called from magic sysrq */
7719+ a = kzalloc(sizeof(*a), GFP_ATOMIC);
7720+ if (unlikely(!a)) {
7721+ dpri("no memory\n");
7722+ return;
7723+ }
7724+
7725+ a->mnt.mnt_sb = sb;
86dc4139 7726+ a->fake.br_path.mnt = &a->mnt;
1facf9fc 7727+ err = do_pri_br(-1, &a->fake);
9f237c51 7728+ au_kfree_rcu(a);
1facf9fc 7729+ dpri("dev 0x%x\n", sb->s_dev);
7730+ if (err || !au_test_aufs(sb))
7731+ return;
7732+
7733+ sbinfo = au_sbi(sb);
7734+ if (!sbinfo)
7735+ return;
f0c0a007
AM
7736+ dpri("nw %d, gen %u, kobj %d\n",
7737+ atomic_read(&sbinfo->si_nowait.nw_len), sbinfo->si_generation,
521ced18 7738+ kref_read(&sbinfo->si_kobj.kref));
5afbbe0d 7739+ for (bindex = 0; bindex <= sbinfo->si_bbot; bindex++)
1facf9fc 7740+ do_pri_br(bindex, sbinfo->si_branch[0 + bindex]);
7741+}
7742+
7743+/* ---------------------------------------------------------------------- */
7744+
027c5e7a
AM
7745+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line)
7746+{
5527c038 7747+ struct inode *h_inode, *inode = d_inode(dentry);
027c5e7a 7748+ struct dentry *h_dentry;
5afbbe0d 7749+ aufs_bindex_t bindex, bbot, bi;
027c5e7a
AM
7750+
7751+ if (!inode /* || au_di(dentry)->di_lsc == AuLsc_DI_TMP */)
7752+ return;
7753+
5afbbe0d
AM
7754+ bbot = au_dbbot(dentry);
7755+ bi = au_ibbot(inode);
7756+ if (bi < bbot)
7757+ bbot = bi;
7758+ bindex = au_dbtop(dentry);
7759+ bi = au_ibtop(inode);
027c5e7a
AM
7760+ if (bi > bindex)
7761+ bindex = bi;
7762+
5afbbe0d 7763+ for (; bindex <= bbot; bindex++) {
027c5e7a
AM
7764+ h_dentry = au_h_dptr(dentry, bindex);
7765+ if (!h_dentry)
7766+ continue;
7767+ h_inode = au_h_iptr(inode, bindex);
5527c038 7768+ if (unlikely(h_inode != d_inode(h_dentry))) {
392086de 7769+ au_debug_on();
027c5e7a
AM
7770+ AuDbg("b%d, %s:%d\n", bindex, func, line);
7771+ AuDbgDentry(dentry);
7772+ AuDbgInode(inode);
392086de 7773+ au_debug_off();
027c5e7a
AM
7774+ BUG();
7775+ }
7776+ }
7777+}
7778+
1facf9fc 7779+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen)
7780+{
7781+ int err, i, j;
7782+ struct au_dcsub_pages dpages;
7783+ struct au_dpage *dpage;
7784+ struct dentry **dentries;
7785+
7786+ err = au_dpages_init(&dpages, GFP_NOFS);
7787+ AuDebugOn(err);
027c5e7a 7788+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/1);
1facf9fc 7789+ AuDebugOn(err);
7790+ for (i = dpages.ndpage - 1; !err && i >= 0; i--) {
7791+ dpage = dpages.dpages + i;
7792+ dentries = dpage->dentries;
7793+ for (j = dpage->ndentry - 1; !err && j >= 0; j--)
027c5e7a 7794+ AuDebugOn(au_digen_test(dentries[j], sigen));
1facf9fc 7795+ }
7796+ au_dpages_free(&dpages);
7797+}
7798+
1facf9fc 7799+void au_dbg_verify_kthread(void)
7800+{
53392da6 7801+ if (au_wkq_test()) {
1facf9fc 7802+ au_dbg_blocked();
1e00d052
AM
7803+ /*
7804+ * It may be recursive, but udba=notify between two aufs mounts,
7805+ * where a single ro branch is shared, is not a problem.
7806+ */
7807+ /* WARN_ON(1); */
1facf9fc 7808+ }
7809+}
7810+
7811+/* ---------------------------------------------------------------------- */
7812+
1facf9fc 7813+int __init au_debug_init(void)
7814+{
7815+ aufs_bindex_t bindex;
7816+ struct au_vdir_destr destr;
7817+
7818+ bindex = -1;
7819+ AuDebugOn(bindex >= 0);
7820+
7821+ destr.len = -1;
7822+ AuDebugOn(destr.len < NAME_MAX);
7823+
7824+#ifdef CONFIG_4KSTACKS
0c3ec466 7825+ pr_warn("CONFIG_4KSTACKS is defined.\n");
1facf9fc 7826+#endif
7827+
1facf9fc 7828+ return 0;
7829+}
7f207e10 7830diff -urN /usr/share/empty/fs/aufs/debug.h linux/fs/aufs/debug.h
eca34b5c 7831--- /usr/share/empty/fs/aufs/debug.h 1970-01-01 01:00:00.000000000 +0100
016522bc 7832+++ linux/fs/aufs/debug.h 2020-01-27 10:57:18.168871450 +0100
062440b3
AM
7833@@ -0,0 +1,226 @@
7834+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 7835+/*
016522bc 7836+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 7837+ *
7838+ * This program, aufs is free software; you can redistribute it and/or modify
7839+ * it under the terms of the GNU General Public License as published by
7840+ * the Free Software Foundation; either version 2 of the License, or
7841+ * (at your option) any later version.
dece6358
AM
7842+ *
7843+ * This program is distributed in the hope that it will be useful,
7844+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
7845+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7846+ * GNU General Public License for more details.
7847+ *
7848+ * You should have received a copy of the GNU General Public License
523b37e3 7849+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 7850+ */
7851+
7852+/*
7853+ * debug print functions
7854+ */
7855+
7856+#ifndef __AUFS_DEBUG_H__
7857+#define __AUFS_DEBUG_H__
7858+
7859+#ifdef __KERNEL__
7860+
392086de 7861+#include <linux/atomic.h>
4a4d8108
AM
7862+#include <linux/module.h>
7863+#include <linux/kallsyms.h>
1facf9fc 7864+#include <linux/sysrq.h>
4a4d8108 7865+
1facf9fc 7866+#ifdef CONFIG_AUFS_DEBUG
7867+#define AuDebugOn(a) BUG_ON(a)
7868+
7869+/* module parameter */
392086de
AM
7870+extern atomic_t aufs_debug;
7871+static inline void au_debug_on(void)
1facf9fc 7872+{
392086de
AM
7873+ atomic_inc(&aufs_debug);
7874+}
7875+static inline void au_debug_off(void)
7876+{
7877+ atomic_dec_if_positive(&aufs_debug);
1facf9fc 7878+}
7879+
7880+static inline int au_debug_test(void)
7881+{
392086de 7882+ return atomic_read(&aufs_debug) > 0;
1facf9fc 7883+}
7884+#else
7885+#define AuDebugOn(a) do {} while (0)
392086de
AM
7886+AuStubVoid(au_debug_on, void)
7887+AuStubVoid(au_debug_off, void)
4a4d8108 7888+AuStubInt0(au_debug_test, void)
1facf9fc 7889+#endif /* CONFIG_AUFS_DEBUG */
7890+
392086de
AM
7891+#define param_check_atomic_t(name, p) __param_check(name, p, atomic_t)
7892+
1facf9fc 7893+/* ---------------------------------------------------------------------- */
7894+
7895+/* debug print */
7896+
4a4d8108 7897+#define AuDbg(fmt, ...) do { \
1facf9fc 7898+ if (au_debug_test()) \
4a4d8108 7899+ pr_debug("DEBUG: " fmt, ##__VA_ARGS__); \
1facf9fc 7900+} while (0)
4a4d8108
AM
7901+#define AuLabel(l) AuDbg(#l "\n")
7902+#define AuIOErr(fmt, ...) pr_err("I/O Error, " fmt, ##__VA_ARGS__)
7903+#define AuWarn1(fmt, ...) do { \
1facf9fc 7904+ static unsigned char _c; \
7905+ if (!_c++) \
0c3ec466 7906+ pr_warn(fmt, ##__VA_ARGS__); \
1facf9fc 7907+} while (0)
7908+
4a4d8108 7909+#define AuErr1(fmt, ...) do { \
1facf9fc 7910+ static unsigned char _c; \
7911+ if (!_c++) \
4a4d8108 7912+ pr_err(fmt, ##__VA_ARGS__); \
1facf9fc 7913+} while (0)
7914+
4a4d8108 7915+#define AuIOErr1(fmt, ...) do { \
1facf9fc 7916+ static unsigned char _c; \
7917+ if (!_c++) \
4a4d8108 7918+ AuIOErr(fmt, ##__VA_ARGS__); \
1facf9fc 7919+} while (0)
7920+
7921+#define AuUnsupportMsg "This operation is not supported." \
7922+ " Please report this application to aufs-users ML."
4a4d8108
AM
7923+#define AuUnsupport(fmt, ...) do { \
7924+ pr_err(AuUnsupportMsg "\n" fmt, ##__VA_ARGS__); \
1facf9fc 7925+ dump_stack(); \
7926+} while (0)
7927+
7928+#define AuTraceErr(e) do { \
7929+ if (unlikely((e) < 0)) \
7930+ AuDbg("err %d\n", (int)(e)); \
7931+} while (0)
7932+
7933+#define AuTraceErrPtr(p) do { \
7934+ if (IS_ERR(p)) \
7935+ AuDbg("err %ld\n", PTR_ERR(p)); \
7936+} while (0)
7937+
7938+/* dirty macros for debug print, use with "%.*s" and caution */
7939+#define AuLNPair(qstr) (qstr)->len, (qstr)->name
1facf9fc 7940+
7941+/* ---------------------------------------------------------------------- */
7942+
dece6358 7943+struct dentry;
1facf9fc 7944+#ifdef CONFIG_AUFS_DEBUG
c1595e42 7945+extern struct mutex au_dbg_mtx;
1facf9fc 7946+extern char *au_plevel;
7947+struct au_nhash;
7948+void au_dpri_whlist(struct au_nhash *whlist);
7949+struct au_vdir;
7950+void au_dpri_vdir(struct au_vdir *vdir);
dece6358 7951+struct inode;
1facf9fc 7952+void au_dpri_inode(struct inode *inode);
2cbb1c4b 7953+void au_dpri_dalias(struct inode *inode);
1facf9fc 7954+void au_dpri_dentry(struct dentry *dentry);
dece6358 7955+struct file;
1facf9fc 7956+void au_dpri_file(struct file *filp);
dece6358 7957+struct super_block;
1facf9fc 7958+void au_dpri_sb(struct super_block *sb);
7959+
027c5e7a
AM
7960+#define au_dbg_verify_dinode(d) __au_dbg_verify_dinode(d, __func__, __LINE__)
7961+void __au_dbg_verify_dinode(struct dentry *dentry, const char *func, int line);
1facf9fc 7962+void au_dbg_verify_gen(struct dentry *parent, unsigned int sigen);
1facf9fc 7963+void au_dbg_verify_kthread(void);
7964+
7965+int __init au_debug_init(void);
7e9cd9fe 7966+
1facf9fc 7967+#define AuDbgWhlist(w) do { \
c1595e42 7968+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7969+ AuDbg(#w "\n"); \
7970+ au_dpri_whlist(w); \
c1595e42 7971+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7972+} while (0)
7973+
7974+#define AuDbgVdir(v) do { \
c1595e42 7975+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7976+ AuDbg(#v "\n"); \
7977+ au_dpri_vdir(v); \
c1595e42 7978+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7979+} while (0)
7980+
7981+#define AuDbgInode(i) do { \
c1595e42 7982+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7983+ AuDbg(#i "\n"); \
7984+ au_dpri_inode(i); \
c1595e42 7985+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 7986+} while (0)
7987+
2cbb1c4b 7988+#define AuDbgDAlias(i) do { \
c1595e42 7989+ mutex_lock(&au_dbg_mtx); \
2cbb1c4b
JR
7990+ AuDbg(#i "\n"); \
7991+ au_dpri_dalias(i); \
c1595e42 7992+ mutex_unlock(&au_dbg_mtx); \
2cbb1c4b
JR
7993+} while (0)
7994+
1facf9fc 7995+#define AuDbgDentry(d) do { \
c1595e42 7996+ mutex_lock(&au_dbg_mtx); \
1facf9fc 7997+ AuDbg(#d "\n"); \
7998+ au_dpri_dentry(d); \
c1595e42 7999+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 8000+} while (0)
8001+
8002+#define AuDbgFile(f) do { \
c1595e42 8003+ mutex_lock(&au_dbg_mtx); \
1facf9fc 8004+ AuDbg(#f "\n"); \
8005+ au_dpri_file(f); \
c1595e42 8006+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 8007+} while (0)
8008+
8009+#define AuDbgSb(sb) do { \
c1595e42 8010+ mutex_lock(&au_dbg_mtx); \
1facf9fc 8011+ AuDbg(#sb "\n"); \
8012+ au_dpri_sb(sb); \
c1595e42 8013+ mutex_unlock(&au_dbg_mtx); \
1facf9fc 8014+} while (0)
8015+
4a4d8108
AM
8016+#define AuDbgSym(addr) do { \
8017+ char sym[KSYM_SYMBOL_LEN]; \
8018+ sprint_symbol(sym, (unsigned long)addr); \
8019+ AuDbg("%s\n", sym); \
8020+} while (0)
1facf9fc 8021+#else
027c5e7a 8022+AuStubVoid(au_dbg_verify_dinode, struct dentry *dentry)
4a4d8108
AM
8023+AuStubVoid(au_dbg_verify_gen, struct dentry *parent, unsigned int sigen)
8024+AuStubVoid(au_dbg_verify_kthread, void)
8025+AuStubInt0(__init au_debug_init, void)
1facf9fc 8026+
1facf9fc 8027+#define AuDbgWhlist(w) do {} while (0)
8028+#define AuDbgVdir(v) do {} while (0)
8029+#define AuDbgInode(i) do {} while (0)
2cbb1c4b 8030+#define AuDbgDAlias(i) do {} while (0)
1facf9fc 8031+#define AuDbgDentry(d) do {} while (0)
8032+#define AuDbgFile(f) do {} while (0)
8033+#define AuDbgSb(sb) do {} while (0)
4a4d8108 8034+#define AuDbgSym(addr) do {} while (0)
1facf9fc 8035+#endif /* CONFIG_AUFS_DEBUG */
8036+
8037+/* ---------------------------------------------------------------------- */
8038+
8039+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
8040+int __init au_sysrq_init(void);
8041+void au_sysrq_fin(void);
8042+
8043+#ifdef CONFIG_HW_CONSOLE
8044+#define au_dbg_blocked() do { \
8045+ WARN_ON(1); \
0c5527e5 8046+ handle_sysrq('w'); \
1facf9fc 8047+} while (0)
8048+#else
4a4d8108 8049+AuStubVoid(au_dbg_blocked, void)
1facf9fc 8050+#endif
8051+
8052+#else
4a4d8108
AM
8053+AuStubInt0(__init au_sysrq_init, void)
8054+AuStubVoid(au_sysrq_fin, void)
8055+AuStubVoid(au_dbg_blocked, void)
1facf9fc 8056+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
8057+
8058+#endif /* __KERNEL__ */
8059+#endif /* __AUFS_DEBUG_H__ */
7f207e10 8060diff -urN /usr/share/empty/fs/aufs/dentry.c linux/fs/aufs/dentry.c
eca34b5c 8061--- /usr/share/empty/fs/aufs/dentry.c 1970-01-01 01:00:00.000000000 +0100
016522bc 8062+++ linux/fs/aufs/dentry.c 2020-01-27 10:57:18.168871450 +0100
eca801bf 8063@@ -0,0 +1,1154 @@
cd7a4cd9 8064+// SPDX-License-Identifier: GPL-2.0
1facf9fc 8065+/*
016522bc 8066+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 8067+ *
8068+ * This program, aufs is free software; you can redistribute it and/or modify
8069+ * it under the terms of the GNU General Public License as published by
8070+ * the Free Software Foundation; either version 2 of the License, or
8071+ * (at your option) any later version.
dece6358
AM
8072+ *
8073+ * This program is distributed in the hope that it will be useful,
8074+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
8075+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8076+ * GNU General Public License for more details.
8077+ *
8078+ * You should have received a copy of the GNU General Public License
523b37e3 8079+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 8080+ */
8081+
8082+/*
8083+ * lookup and dentry operations
8084+ */
8085+
eca801bf 8086+#include <linux/iversion.h>
dece6358 8087+#include <linux/namei.h>
1facf9fc 8088+#include "aufs.h"
8089+
1facf9fc 8090+/*
8091+ * returns positive/negative dentry, NULL or an error.
8092+ * NULL means whiteout-ed or not-found.
8093+ */
8094+static struct dentry*
8095+au_do_lookup(struct dentry *h_parent, struct dentry *dentry,
8b6a4947 8096+ aufs_bindex_t bindex, struct au_do_lookup_args *args)
1facf9fc 8097+{
8098+ struct dentry *h_dentry;
2000de60 8099+ struct inode *h_inode;
1facf9fc 8100+ struct au_branch *br;
8101+ int wh_found, opq;
8102+ unsigned char wh_able;
8103+ const unsigned char allow_neg = !!au_ftest_lkup(args->flags, ALLOW_NEG);
076b876e
AM
8104+ const unsigned char ignore_perm = !!au_ftest_lkup(args->flags,
8105+ IGNORE_PERM);
1facf9fc 8106+
1facf9fc 8107+ wh_found = 0;
8108+ br = au_sbr(dentry->d_sb, bindex);
8109+ wh_able = !!au_br_whable(br->br_perm);
8110+ if (wh_able)
8b6a4947 8111+ wh_found = au_wh_test(h_parent, &args->whname, ignore_perm);
1facf9fc 8112+ h_dentry = ERR_PTR(wh_found);
8113+ if (!wh_found)
8114+ goto real_lookup;
8115+ if (unlikely(wh_found < 0))
8116+ goto out;
8117+
8118+ /* We found a whiteout */
5afbbe0d 8119+ /* au_set_dbbot(dentry, bindex); */
1facf9fc 8120+ au_set_dbwh(dentry, bindex);
8121+ if (!allow_neg)
8122+ return NULL; /* success */
8123+
4f0767ce 8124+real_lookup:
076b876e 8125+ if (!ignore_perm)
8b6a4947 8126+ h_dentry = vfsub_lkup_one(args->name, h_parent);
076b876e 8127+ else
8b6a4947 8128+ h_dentry = au_sio_lkup_one(args->name, h_parent);
2000de60
JR
8129+ if (IS_ERR(h_dentry)) {
8130+ if (PTR_ERR(h_dentry) == -ENAMETOOLONG
8131+ && !allow_neg)
8132+ h_dentry = NULL;
1facf9fc 8133+ goto out;
2000de60 8134+ }
1facf9fc 8135+
5527c038
JR
8136+ h_inode = d_inode(h_dentry);
8137+ if (d_is_negative(h_dentry)) {
1facf9fc 8138+ if (!allow_neg)
8139+ goto out_neg;
8140+ } else if (wh_found
8141+ || (args->type && args->type != (h_inode->i_mode & S_IFMT)))
8142+ goto out_neg;
8b6a4947
AM
8143+ else if (au_ftest_lkup(args->flags, DIRREN)
8144+ /* && h_inode */
8145+ && !au_dr_lkup_h_ino(args, bindex, h_inode->i_ino)) {
8146+ AuDbg("b%d %pd ignored hi%llu\n", bindex, h_dentry,
8147+ (unsigned long long)h_inode->i_ino);
8148+ goto out_neg;
8149+ }
1facf9fc 8150+
5afbbe0d
AM
8151+ if (au_dbbot(dentry) <= bindex)
8152+ au_set_dbbot(dentry, bindex);
8153+ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry))
8154+ au_set_dbtop(dentry, bindex);
1facf9fc 8155+ au_set_h_dptr(dentry, bindex, h_dentry);
8156+
2000de60
JR
8157+ if (!d_is_dir(h_dentry)
8158+ || !wh_able
5527c038 8159+ || (d_really_is_positive(dentry) && !d_is_dir(dentry)))
1facf9fc 8160+ goto out; /* success */
8161+
be118d29 8162+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD);
076b876e 8163+ opq = au_diropq_test(h_dentry);
3c1bdaff 8164+ inode_unlock_shared(h_inode);
1facf9fc 8165+ if (opq > 0)
8166+ au_set_dbdiropq(dentry, bindex);
8167+ else if (unlikely(opq < 0)) {
8168+ au_set_h_dptr(dentry, bindex, NULL);
8169+ h_dentry = ERR_PTR(opq);
8170+ }
8171+ goto out;
8172+
4f0767ce 8173+out_neg:
1facf9fc 8174+ dput(h_dentry);
8175+ h_dentry = NULL;
4f0767ce 8176+out:
1facf9fc 8177+ return h_dentry;
8178+}
8179+
dece6358
AM
8180+static int au_test_shwh(struct super_block *sb, const struct qstr *name)
8181+{
8182+ if (unlikely(!au_opt_test(au_mntflags(sb), SHWH)
8183+ && !strncmp(name->name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)))
8184+ return -EPERM;
8185+ return 0;
8186+}
8187+
1facf9fc 8188+/*
8189+ * returns the number of lower positive dentries,
8190+ * otherwise an error.
8191+ * can be called at unlinking with @type is zero.
8192+ */
5afbbe0d
AM
8193+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop,
8194+ unsigned int flags)
1facf9fc 8195+{
8196+ int npositive, err;
8197+ aufs_bindex_t bindex, btail, bdiropq;
8b6a4947 8198+ unsigned char isdir, dirperm1, dirren;
1facf9fc 8199+ struct au_do_lookup_args args = {
8b6a4947
AM
8200+ .flags = flags,
8201+ .name = &dentry->d_name
1facf9fc 8202+ };
1facf9fc 8203+ struct dentry *parent;
076b876e 8204+ struct super_block *sb;
1facf9fc 8205+
076b876e 8206+ sb = dentry->d_sb;
8b6a4947 8207+ err = au_test_shwh(sb, args.name);
dece6358 8208+ if (unlikely(err))
1facf9fc 8209+ goto out;
8210+
8b6a4947 8211+ err = au_wh_name_alloc(&args.whname, args.name);
1facf9fc 8212+ if (unlikely(err))
8213+ goto out;
8214+
2000de60 8215+ isdir = !!d_is_dir(dentry);
076b876e 8216+ dirperm1 = !!au_opt_test(au_mntflags(sb), DIRPERM1);
8b6a4947
AM
8217+ dirren = !!au_opt_test(au_mntflags(sb), DIRREN);
8218+ if (dirren)
8219+ au_fset_lkup(args.flags, DIRREN);
1facf9fc 8220+
8221+ npositive = 0;
4a4d8108 8222+ parent = dget_parent(dentry);
1facf9fc 8223+ btail = au_dbtaildir(parent);
5afbbe0d 8224+ for (bindex = btop; bindex <= btail; bindex++) {
1facf9fc 8225+ struct dentry *h_parent, *h_dentry;
8226+ struct inode *h_inode, *h_dir;
8b6a4947 8227+ struct au_branch *br;
1facf9fc 8228+
8229+ h_dentry = au_h_dptr(dentry, bindex);
8230+ if (h_dentry) {
5527c038 8231+ if (d_is_positive(h_dentry))
1facf9fc 8232+ npositive++;
5afbbe0d 8233+ break;
1facf9fc 8234+ }
8235+ h_parent = au_h_dptr(parent, bindex);
2000de60 8236+ if (!h_parent || !d_is_dir(h_parent))
1facf9fc 8237+ continue;
8238+
8b6a4947
AM
8239+ if (dirren) {
8240+ /* if the inum matches, then use the prepared name */
8241+ err = au_dr_lkup_name(&args, bindex);
8242+ if (unlikely(err))
8243+ goto out_parent;
8244+ }
8245+
5527c038 8246+ h_dir = d_inode(h_parent);
be118d29 8247+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
8b6a4947 8248+ h_dentry = au_do_lookup(h_parent, dentry, bindex, &args);
3c1bdaff 8249+ inode_unlock_shared(h_dir);
1facf9fc 8250+ err = PTR_ERR(h_dentry);
8251+ if (IS_ERR(h_dentry))
4a4d8108 8252+ goto out_parent;
2000de60
JR
8253+ if (h_dentry)
8254+ au_fclr_lkup(args.flags, ALLOW_NEG);
076b876e
AM
8255+ if (dirperm1)
8256+ au_fset_lkup(args.flags, IGNORE_PERM);
1facf9fc 8257+
79b8bda9 8258+ if (au_dbwh(dentry) == bindex)
1facf9fc 8259+ break;
8260+ if (!h_dentry)
8261+ continue;
5527c038 8262+ if (d_is_negative(h_dentry))
1facf9fc 8263+ continue;
5527c038 8264+ h_inode = d_inode(h_dentry);
1facf9fc 8265+ npositive++;
8266+ if (!args.type)
8267+ args.type = h_inode->i_mode & S_IFMT;
8268+ if (args.type != S_IFDIR)
8269+ break;
8270+ else if (isdir) {
8271+ /* the type of lower may be different */
8272+ bdiropq = au_dbdiropq(dentry);
8273+ if (bdiropq >= 0 && bdiropq <= bindex)
8274+ break;
8275+ }
8b6a4947
AM
8276+ br = au_sbr(sb, bindex);
8277+ if (dirren
8278+ && au_dr_hino_test_add(&br->br_dirren, h_inode->i_ino,
8279+ /*add_ent*/NULL)) {
8280+ /* prepare next name to lookup */
8281+ err = au_dr_lkup(&args, dentry, bindex);
8282+ if (unlikely(err))
8283+ goto out_parent;
8284+ }
1facf9fc 8285+ }
8286+
8287+ if (npositive) {
8288+ AuLabel(positive);
5afbbe0d 8289+ au_update_dbtop(dentry);
1facf9fc 8290+ }
8291+ err = npositive;
076b876e 8292+ if (unlikely(!au_opt_test(au_mntflags(sb), UDBA_NONE)
5afbbe0d 8293+ && au_dbtop(dentry) < 0)) {
1facf9fc 8294+ err = -EIO;
523b37e3
AM
8295+ AuIOErr("both of real entry and whiteout found, %pd, err %d\n",
8296+ dentry, err);
027c5e7a 8297+ }
1facf9fc 8298+
4f0767ce 8299+out_parent:
4a4d8108 8300+ dput(parent);
9f237c51 8301+ au_kfree_try_rcu(args.whname.name);
8b6a4947
AM
8302+ if (dirren)
8303+ au_dr_lkup_fin(&args);
4f0767ce 8304+out:
1facf9fc 8305+ return err;
8306+}
8307+
076b876e 8308+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent)
1facf9fc 8309+{
8310+ struct dentry *dentry;
8311+ int wkq_err;
8312+
5527c038 8313+ if (!au_test_h_perm_sio(d_inode(parent), MAY_EXEC))
b4510431 8314+ dentry = vfsub_lkup_one(name, parent);
1facf9fc 8315+ else {
b4510431
AM
8316+ struct vfsub_lkup_one_args args = {
8317+ .errp = &dentry,
8318+ .name = name,
8319+ .parent = parent
1facf9fc 8320+ };
8321+
b4510431 8322+ wkq_err = au_wkq_wait(vfsub_call_lkup_one, &args);
1facf9fc 8323+ if (unlikely(wkq_err))
8324+ dentry = ERR_PTR(wkq_err);
8325+ }
8326+
8327+ return dentry;
8328+}
8329+
8330+/*
8331+ * lookup @dentry on @bindex which should be negative.
8332+ */
86dc4139 8333+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh)
1facf9fc 8334+{
8335+ int err;
8336+ struct dentry *parent, *h_parent, *h_dentry;
86dc4139 8337+ struct au_branch *br;
1facf9fc 8338+
1facf9fc 8339+ parent = dget_parent(dentry);
8340+ h_parent = au_h_dptr(parent, bindex);
86dc4139
AM
8341+ br = au_sbr(dentry->d_sb, bindex);
8342+ if (wh)
8343+ h_dentry = au_whtmp_lkup(h_parent, br, &dentry->d_name);
8344+ else
076b876e 8345+ h_dentry = au_sio_lkup_one(&dentry->d_name, h_parent);
1facf9fc 8346+ err = PTR_ERR(h_dentry);
8347+ if (IS_ERR(h_dentry))
8348+ goto out;
5527c038 8349+ if (unlikely(d_is_positive(h_dentry))) {
1facf9fc 8350+ err = -EIO;
523b37e3 8351+ AuIOErr("%pd should be negative on b%d.\n", h_dentry, bindex);
1facf9fc 8352+ dput(h_dentry);
8353+ goto out;
8354+ }
8355+
4a4d8108 8356+ err = 0;
5afbbe0d
AM
8357+ if (bindex < au_dbtop(dentry))
8358+ au_set_dbtop(dentry, bindex);
8359+ if (au_dbbot(dentry) < bindex)
8360+ au_set_dbbot(dentry, bindex);
1facf9fc 8361+ au_set_h_dptr(dentry, bindex, h_dentry);
1facf9fc 8362+
4f0767ce 8363+out:
1facf9fc 8364+ dput(parent);
8365+ return err;
8366+}
8367+
8368+/* ---------------------------------------------------------------------- */
8369+
8370+/* subset of struct inode */
8371+struct au_iattr {
8372+ unsigned long i_ino;
8373+ /* unsigned int i_nlink; */
0c3ec466
AM
8374+ kuid_t i_uid;
8375+ kgid_t i_gid;
1facf9fc 8376+ u64 i_version;
8377+/*
8378+ loff_t i_size;
8379+ blkcnt_t i_blocks;
8380+*/
8381+ umode_t i_mode;
8382+};
8383+
8384+static void au_iattr_save(struct au_iattr *ia, struct inode *h_inode)
8385+{
8386+ ia->i_ino = h_inode->i_ino;
8387+ /* ia->i_nlink = h_inode->i_nlink; */
8388+ ia->i_uid = h_inode->i_uid;
8389+ ia->i_gid = h_inode->i_gid;
be118d29 8390+ ia->i_version = inode_query_iversion(h_inode);
1facf9fc 8391+/*
8392+ ia->i_size = h_inode->i_size;
8393+ ia->i_blocks = h_inode->i_blocks;
8394+*/
8395+ ia->i_mode = (h_inode->i_mode & S_IFMT);
8396+}
8397+
8398+static int au_iattr_test(struct au_iattr *ia, struct inode *h_inode)
8399+{
8400+ return ia->i_ino != h_inode->i_ino
8401+ /* || ia->i_nlink != h_inode->i_nlink */
0c3ec466 8402+ || !uid_eq(ia->i_uid, h_inode->i_uid)
2dfbb274 8403+ || !gid_eq(ia->i_gid, h_inode->i_gid)
be118d29 8404+ || !inode_eq_iversion(h_inode, ia->i_version)
1facf9fc 8405+/*
8406+ || ia->i_size != h_inode->i_size
8407+ || ia->i_blocks != h_inode->i_blocks
8408+*/
8409+ || ia->i_mode != (h_inode->i_mode & S_IFMT);
8410+}
8411+
8412+static int au_h_verify_dentry(struct dentry *h_dentry, struct dentry *h_parent,
8413+ struct au_branch *br)
8414+{
8415+ int err;
8416+ struct au_iattr ia;
8417+ struct inode *h_inode;
8418+ struct dentry *h_d;
8419+ struct super_block *h_sb;
8420+
8421+ err = 0;
8422+ memset(&ia, -1, sizeof(ia));
8423+ h_sb = h_dentry->d_sb;
5527c038
JR
8424+ h_inode = NULL;
8425+ if (d_is_positive(h_dentry)) {
8426+ h_inode = d_inode(h_dentry);
1facf9fc 8427+ au_iattr_save(&ia, h_inode);
5527c038 8428+ } else if (au_test_nfs(h_sb) || au_test_fuse(h_sb))
1facf9fc 8429+ /* nfs d_revalidate may return 0 for negative dentry */
8430+ /* fuse d_revalidate always return 0 for negative dentry */
8431+ goto out;
8432+
8433+ /* main purpose is namei.c:cached_lookup() and d_revalidate */
b4510431 8434+ h_d = vfsub_lkup_one(&h_dentry->d_name, h_parent);
1facf9fc 8435+ err = PTR_ERR(h_d);
8436+ if (IS_ERR(h_d))
8437+ goto out;
8438+
8439+ err = 0;
8440+ if (unlikely(h_d != h_dentry
5527c038 8441+ || d_inode(h_d) != h_inode
1facf9fc 8442+ || (h_inode && au_iattr_test(&ia, h_inode))))
8443+ err = au_busy_or_stale();
8444+ dput(h_d);
8445+
4f0767ce 8446+out:
1facf9fc 8447+ AuTraceErr(err);
8448+ return err;
8449+}
8450+
8451+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
8452+ struct dentry *h_parent, struct au_branch *br)
8453+{
8454+ int err;
8455+
8456+ err = 0;
027c5e7a
AM
8457+ if (udba == AuOpt_UDBA_REVAL
8458+ && !au_test_fs_remote(h_dentry->d_sb)) {
1facf9fc 8459+ IMustLock(h_dir);
5527c038 8460+ err = (d_inode(h_dentry->d_parent) != h_dir);
027c5e7a 8461+ } else if (udba != AuOpt_UDBA_NONE)
1facf9fc 8462+ err = au_h_verify_dentry(h_dentry, h_parent, br);
8463+
8464+ return err;
8465+}
8466+
8467+/* ---------------------------------------------------------------------- */
8468+
027c5e7a 8469+static int au_do_refresh_hdentry(struct dentry *dentry, struct dentry *parent)
1facf9fc 8470+{
027c5e7a 8471+ int err;
5afbbe0d 8472+ aufs_bindex_t new_bindex, bindex, bbot, bwh, bdiropq;
027c5e7a
AM
8473+ struct au_hdentry tmp, *p, *q;
8474+ struct au_dinfo *dinfo;
8475+ struct super_block *sb;
1facf9fc 8476+
027c5e7a 8477+ DiMustWriteLock(dentry);
1308ab2a 8478+
027c5e7a
AM
8479+ sb = dentry->d_sb;
8480+ dinfo = au_di(dentry);
5afbbe0d 8481+ bbot = dinfo->di_bbot;
1facf9fc 8482+ bwh = dinfo->di_bwh;
8483+ bdiropq = dinfo->di_bdiropq;
5afbbe0d
AM
8484+ bindex = dinfo->di_btop;
8485+ p = au_hdentry(dinfo, bindex);
8486+ for (; bindex <= bbot; bindex++, p++) {
027c5e7a 8487+ if (!p->hd_dentry)
1facf9fc 8488+ continue;
8489+
027c5e7a
AM
8490+ new_bindex = au_br_index(sb, p->hd_id);
8491+ if (new_bindex == bindex)
1facf9fc 8492+ continue;
1facf9fc 8493+
1facf9fc 8494+ if (dinfo->di_bwh == bindex)
8495+ bwh = new_bindex;
8496+ if (dinfo->di_bdiropq == bindex)
8497+ bdiropq = new_bindex;
8498+ if (new_bindex < 0) {
8499+ au_hdput(p);
8500+ p->hd_dentry = NULL;
8501+ continue;
8502+ }
8503+
8504+ /* swap two lower dentries, and loop again */
5afbbe0d 8505+ q = au_hdentry(dinfo, new_bindex);
1facf9fc 8506+ tmp = *q;
8507+ *q = *p;
8508+ *p = tmp;
8509+ if (tmp.hd_dentry) {
8510+ bindex--;
8511+ p--;
8512+ }
8513+ }
8514+
1facf9fc 8515+ dinfo->di_bwh = -1;
5afbbe0d 8516+ if (bwh >= 0 && bwh <= au_sbbot(sb) && au_sbr_whable(sb, bwh))
1facf9fc 8517+ dinfo->di_bwh = bwh;
8518+
8519+ dinfo->di_bdiropq = -1;
8520+ if (bdiropq >= 0
5afbbe0d 8521+ && bdiropq <= au_sbbot(sb)
1facf9fc 8522+ && au_sbr_whable(sb, bdiropq))
8523+ dinfo->di_bdiropq = bdiropq;
8524+
027c5e7a 8525+ err = -EIO;
5afbbe0d
AM
8526+ dinfo->di_btop = -1;
8527+ dinfo->di_bbot = -1;
8528+ bbot = au_dbbot(parent);
8529+ bindex = 0;
8530+ p = au_hdentry(dinfo, bindex);
8531+ for (; bindex <= bbot; bindex++, p++)
1facf9fc 8532+ if (p->hd_dentry) {
5afbbe0d 8533+ dinfo->di_btop = bindex;
1facf9fc 8534+ break;
8535+ }
8536+
5afbbe0d
AM
8537+ if (dinfo->di_btop >= 0) {
8538+ bindex = bbot;
8539+ p = au_hdentry(dinfo, bindex);
8540+ for (; bindex >= 0; bindex--, p--)
027c5e7a 8541+ if (p->hd_dentry) {
5afbbe0d 8542+ dinfo->di_bbot = bindex;
027c5e7a
AM
8543+ err = 0;
8544+ break;
8545+ }
8546+ }
8547+
8548+ return err;
1facf9fc 8549+}
8550+
027c5e7a 8551+static void au_do_hide(struct dentry *dentry)
1facf9fc 8552+{
027c5e7a 8553+ struct inode *inode;
1facf9fc 8554+
5527c038
JR
8555+ if (d_really_is_positive(dentry)) {
8556+ inode = d_inode(dentry);
8557+ if (!d_is_dir(dentry)) {
027c5e7a
AM
8558+ if (inode->i_nlink && !d_unhashed(dentry))
8559+ drop_nlink(inode);
8560+ } else {
8561+ clear_nlink(inode);
8562+ /* stop next lookup */
8563+ inode->i_flags |= S_DEAD;
8564+ }
8565+ smp_mb(); /* necessary? */
8566+ }
8567+ d_drop(dentry);
8568+}
1308ab2a 8569+
027c5e7a
AM
8570+static int au_hide_children(struct dentry *parent)
8571+{
8572+ int err, i, j, ndentry;
8573+ struct au_dcsub_pages dpages;
8574+ struct au_dpage *dpage;
8575+ struct dentry *dentry;
1facf9fc 8576+
027c5e7a 8577+ err = au_dpages_init(&dpages, GFP_NOFS);
1facf9fc 8578+ if (unlikely(err))
8579+ goto out;
027c5e7a
AM
8580+ err = au_dcsub_pages(&dpages, parent, NULL, NULL);
8581+ if (unlikely(err))
8582+ goto out_dpages;
1facf9fc 8583+
027c5e7a
AM
8584+ /* in reverse order */
8585+ for (i = dpages.ndpage - 1; i >= 0; i--) {
8586+ dpage = dpages.dpages + i;
8587+ ndentry = dpage->ndentry;
8588+ for (j = ndentry - 1; j >= 0; j--) {
8589+ dentry = dpage->dentries[j];
8590+ if (dentry != parent)
8591+ au_do_hide(dentry);
8592+ }
8593+ }
1facf9fc 8594+
027c5e7a
AM
8595+out_dpages:
8596+ au_dpages_free(&dpages);
4f0767ce 8597+out:
027c5e7a 8598+ return err;
1facf9fc 8599+}
8600+
027c5e7a 8601+static void au_hide(struct dentry *dentry)
1facf9fc 8602+{
027c5e7a 8603+ int err;
1facf9fc 8604+
027c5e7a 8605+ AuDbgDentry(dentry);
2000de60 8606+ if (d_is_dir(dentry)) {
027c5e7a
AM
8607+ /* shrink_dcache_parent(dentry); */
8608+ err = au_hide_children(dentry);
8609+ if (unlikely(err))
523b37e3
AM
8610+ AuIOErr("%pd, failed hiding children, ignored %d\n",
8611+ dentry, err);
027c5e7a
AM
8612+ }
8613+ au_do_hide(dentry);
8614+}
1facf9fc 8615+
027c5e7a
AM
8616+/*
8617+ * By adding a dirty branch, a cached dentry may be affected in various ways.
8618+ *
8619+ * a dirty branch is added
8620+ * - on the top of layers
8621+ * - in the middle of layers
8622+ * - to the bottom of layers
8623+ *
8624+ * on the added branch there exists
8625+ * - a whiteout
8626+ * - a diropq
8627+ * - a same named entry
8628+ * + exist
8629+ * * negative --> positive
8630+ * * positive --> positive
8631+ * - type is unchanged
8632+ * - type is changed
8633+ * + doesn't exist
8634+ * * negative --> negative
8635+ * * positive --> negative (rejected by au_br_del() for non-dir case)
8636+ * - none
8637+ */
8638+static int au_refresh_by_dinfo(struct dentry *dentry, struct au_dinfo *dinfo,
8639+ struct au_dinfo *tmp)
8640+{
8641+ int err;
5afbbe0d 8642+ aufs_bindex_t bindex, bbot;
027c5e7a
AM
8643+ struct {
8644+ struct dentry *dentry;
8645+ struct inode *inode;
8646+ mode_t mode;
be52b249
AM
8647+ } orig_h, tmp_h = {
8648+ .dentry = NULL
8649+ };
027c5e7a
AM
8650+ struct au_hdentry *hd;
8651+ struct inode *inode, *h_inode;
8652+ struct dentry *h_dentry;
8653+
8654+ err = 0;
5afbbe0d 8655+ AuDebugOn(dinfo->di_btop < 0);
027c5e7a 8656+ orig_h.mode = 0;
5afbbe0d 8657+ orig_h.dentry = au_hdentry(dinfo, dinfo->di_btop)->hd_dentry;
5527c038
JR
8658+ orig_h.inode = NULL;
8659+ if (d_is_positive(orig_h.dentry)) {
8660+ orig_h.inode = d_inode(orig_h.dentry);
027c5e7a 8661+ orig_h.mode = orig_h.inode->i_mode & S_IFMT;
5527c038 8662+ }
5afbbe0d
AM
8663+ if (tmp->di_btop >= 0) {
8664+ tmp_h.dentry = au_hdentry(tmp, tmp->di_btop)->hd_dentry;
5527c038
JR
8665+ if (d_is_positive(tmp_h.dentry)) {
8666+ tmp_h.inode = d_inode(tmp_h.dentry);
027c5e7a 8667+ tmp_h.mode = tmp_h.inode->i_mode & S_IFMT;
5527c038 8668+ }
027c5e7a
AM
8669+ }
8670+
5527c038
JR
8671+ inode = NULL;
8672+ if (d_really_is_positive(dentry))
8673+ inode = d_inode(dentry);
027c5e7a 8674+ if (!orig_h.inode) {
acd2b654 8675+ AuDbg("negative originally\n");
027c5e7a
AM
8676+ if (inode) {
8677+ au_hide(dentry);
8678+ goto out;
8679+ }
8680+ AuDebugOn(inode);
5afbbe0d 8681+ AuDebugOn(dinfo->di_btop != dinfo->di_bbot);
027c5e7a
AM
8682+ AuDebugOn(dinfo->di_bdiropq != -1);
8683+
8684+ if (!tmp_h.inode) {
8685+ AuDbg("negative --> negative\n");
8686+ /* should have only one negative lower */
5afbbe0d
AM
8687+ if (tmp->di_btop >= 0
8688+ && tmp->di_btop < dinfo->di_btop) {
8689+ AuDebugOn(tmp->di_btop != tmp->di_bbot);
8690+ AuDebugOn(dinfo->di_btop != dinfo->di_bbot);
8691+ au_set_h_dptr(dentry, dinfo->di_btop, NULL);
027c5e7a 8692+ au_di_cp(dinfo, tmp);
5afbbe0d
AM
8693+ hd = au_hdentry(tmp, tmp->di_btop);
8694+ au_set_h_dptr(dentry, tmp->di_btop,
027c5e7a
AM
8695+ dget(hd->hd_dentry));
8696+ }
8697+ au_dbg_verify_dinode(dentry);
8698+ } else {
8699+ AuDbg("negative --> positive\n");
8700+ /*
8701+ * similar to the behaviour of creating with bypassing
8702+ * aufs.
8703+ * unhash it in order to force an error in the
8704+ * succeeding create operation.
8705+ * we should not set S_DEAD here.
8706+ */
8707+ d_drop(dentry);
8708+ /* au_di_swap(tmp, dinfo); */
8709+ au_dbg_verify_dinode(dentry);
8710+ }
8711+ } else {
8712+ AuDbg("positive originally\n");
8713+ /* inode may be NULL */
8714+ AuDebugOn(inode && (inode->i_mode & S_IFMT) != orig_h.mode);
8715+ if (!tmp_h.inode) {
8716+ AuDbg("positive --> negative\n");
8717+ /* or bypassing aufs */
8718+ au_hide(dentry);
5afbbe0d 8719+ if (tmp->di_bwh >= 0 && tmp->di_bwh <= dinfo->di_btop)
027c5e7a
AM
8720+ dinfo->di_bwh = tmp->di_bwh;
8721+ if (inode)
8722+ err = au_refresh_hinode_self(inode);
8723+ au_dbg_verify_dinode(dentry);
8724+ } else if (orig_h.mode == tmp_h.mode) {
8725+ AuDbg("positive --> positive, same type\n");
8726+ if (!S_ISDIR(orig_h.mode)
5afbbe0d 8727+ && dinfo->di_btop > tmp->di_btop) {
027c5e7a
AM
8728+ /*
8729+ * similar to the behaviour of removing and
8730+ * creating.
8731+ */
8732+ au_hide(dentry);
8733+ if (inode)
8734+ err = au_refresh_hinode_self(inode);
8735+ au_dbg_verify_dinode(dentry);
8736+ } else {
8737+ /* fill empty slots */
5afbbe0d
AM
8738+ if (dinfo->di_btop > tmp->di_btop)
8739+ dinfo->di_btop = tmp->di_btop;
8740+ if (dinfo->di_bbot < tmp->di_bbot)
8741+ dinfo->di_bbot = tmp->di_bbot;
027c5e7a
AM
8742+ dinfo->di_bwh = tmp->di_bwh;
8743+ dinfo->di_bdiropq = tmp->di_bdiropq;
5afbbe0d
AM
8744+ bbot = dinfo->di_bbot;
8745+ bindex = tmp->di_btop;
8746+ hd = au_hdentry(tmp, bindex);
8747+ for (; bindex <= bbot; bindex++, hd++) {
027c5e7a
AM
8748+ if (au_h_dptr(dentry, bindex))
8749+ continue;
5afbbe0d 8750+ h_dentry = hd->hd_dentry;
027c5e7a
AM
8751+ if (!h_dentry)
8752+ continue;
5527c038
JR
8753+ AuDebugOn(d_is_negative(h_dentry));
8754+ h_inode = d_inode(h_dentry);
027c5e7a
AM
8755+ AuDebugOn(orig_h.mode
8756+ != (h_inode->i_mode
8757+ & S_IFMT));
8758+ au_set_h_dptr(dentry, bindex,
8759+ dget(h_dentry));
8760+ }
5afbbe0d
AM
8761+ if (inode)
8762+ err = au_refresh_hinode(inode, dentry);
027c5e7a
AM
8763+ au_dbg_verify_dinode(dentry);
8764+ }
8765+ } else {
8766+ AuDbg("positive --> positive, different type\n");
8767+ /* similar to the behaviour of removing and creating */
8768+ au_hide(dentry);
8769+ if (inode)
8770+ err = au_refresh_hinode_self(inode);
8771+ au_dbg_verify_dinode(dentry);
8772+ }
8773+ }
8774+
8775+out:
8776+ return err;
8777+}
8778+
79b8bda9
AM
8779+void au_refresh_dop(struct dentry *dentry, int force_reval)
8780+{
8781+ const struct dentry_operations *dop
8782+ = force_reval ? &aufs_dop : dentry->d_sb->s_d_op;
8783+ static const unsigned int mask
8784+ = DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE;
8785+
8786+ BUILD_BUG_ON(sizeof(mask) != sizeof(dentry->d_flags));
8787+
8788+ if (dentry->d_op == dop)
8789+ return;
8790+
8791+ AuDbg("%pd\n", dentry);
8792+ spin_lock(&dentry->d_lock);
8793+ if (dop == &aufs_dop)
8794+ dentry->d_flags |= mask;
8795+ else
8796+ dentry->d_flags &= ~mask;
8797+ dentry->d_op = dop;
8798+ spin_unlock(&dentry->d_lock);
8799+}
8800+
027c5e7a
AM
8801+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent)
8802+{
e2f27e51 8803+ int err, ebrange, nbr;
027c5e7a
AM
8804+ unsigned int sigen;
8805+ struct au_dinfo *dinfo, *tmp;
8806+ struct super_block *sb;
8807+ struct inode *inode;
8808+
8809+ DiMustWriteLock(dentry);
8810+ AuDebugOn(IS_ROOT(dentry));
5527c038 8811+ AuDebugOn(d_really_is_negative(parent));
027c5e7a
AM
8812+
8813+ sb = dentry->d_sb;
027c5e7a
AM
8814+ sigen = au_sigen(sb);
8815+ err = au_digen_test(parent, sigen);
8816+ if (unlikely(err))
8817+ goto out;
8818+
e2f27e51 8819+ nbr = au_sbbot(sb) + 1;
027c5e7a 8820+ dinfo = au_di(dentry);
e2f27e51 8821+ err = au_di_realloc(dinfo, nbr, /*may_shrink*/0);
027c5e7a
AM
8822+ if (unlikely(err))
8823+ goto out;
8824+ ebrange = au_dbrange_test(dentry);
8825+ if (!ebrange)
8826+ ebrange = au_do_refresh_hdentry(dentry, parent);
8827+
38d290e6 8828+ if (d_unhashed(dentry) || ebrange /* || dinfo->di_tmpfile */) {
5afbbe0d 8829+ AuDebugOn(au_dbtop(dentry) < 0 && au_dbbot(dentry) >= 0);
5527c038
JR
8830+ if (d_really_is_positive(dentry)) {
8831+ inode = d_inode(dentry);
027c5e7a 8832+ err = au_refresh_hinode_self(inode);
5527c038 8833+ }
027c5e7a
AM
8834+ au_dbg_verify_dinode(dentry);
8835+ if (!err)
8836+ goto out_dgen; /* success */
8837+ goto out;
8838+ }
8839+
8840+ /* temporary dinfo */
8841+ AuDbgDentry(dentry);
8842+ err = -ENOMEM;
8843+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
8844+ if (unlikely(!tmp))
8845+ goto out;
8846+ au_di_swap(tmp, dinfo);
8847+ /* returns the number of positive dentries */
8848+ /*
8849+ * if current working dir is removed, it returns an error.
8850+ * but the dentry is legal.
8851+ */
5afbbe0d 8852+ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG);
027c5e7a
AM
8853+ AuDbgDentry(dentry);
8854+ au_di_swap(tmp, dinfo);
8855+ if (err == -ENOENT)
8856+ err = 0;
8857+ if (err >= 0) {
8858+ /* compare/refresh by dinfo */
8859+ AuDbgDentry(dentry);
8860+ err = au_refresh_by_dinfo(dentry, dinfo, tmp);
8861+ au_dbg_verify_dinode(dentry);
8862+ AuTraceErr(err);
8863+ }
e2f27e51 8864+ au_di_realloc(dinfo, nbr, /*may_shrink*/1); /* harmless if err */
027c5e7a
AM
8865+ au_rw_write_unlock(&tmp->di_rwsem);
8866+ au_di_free(tmp);
8867+ if (unlikely(err))
8868+ goto out;
8869+
8870+out_dgen:
8871+ au_update_digen(dentry);
8872+out:
8873+ if (unlikely(err && !(dentry->d_flags & DCACHE_NFSFS_RENAMED))) {
523b37e3 8874+ AuIOErr("failed refreshing %pd, %d\n", dentry, err);
027c5e7a
AM
8875+ AuDbgDentry(dentry);
8876+ }
8877+ AuTraceErr(err);
8878+ return err;
8879+}
8880+
b4510431
AM
8881+static int au_do_h_d_reval(struct dentry *h_dentry, unsigned int flags,
8882+ struct dentry *dentry, aufs_bindex_t bindex)
027c5e7a
AM
8883+{
8884+ int err, valid;
027c5e7a
AM
8885+
8886+ err = 0;
8887+ if (!(h_dentry->d_flags & DCACHE_OP_REVALIDATE))
8888+ goto out;
027c5e7a
AM
8889+
8890+ AuDbg("b%d\n", bindex);
b4510431
AM
8891+ /*
8892+ * gave up supporting LOOKUP_CREATE/OPEN for lower fs,
8893+ * due to whiteout and branch permission.
8894+ */
8895+ flags &= ~(/*LOOKUP_PARENT |*/ LOOKUP_OPEN | LOOKUP_CREATE
8896+ | LOOKUP_FOLLOW | LOOKUP_EXCL);
8897+ /* it may return tri-state */
8898+ valid = h_dentry->d_op->d_revalidate(h_dentry, flags);
1facf9fc 8899+
8900+ if (unlikely(valid < 0))
8901+ err = valid;
8902+ else if (!valid)
8903+ err = -EINVAL;
8904+
4f0767ce 8905+out:
1facf9fc 8906+ AuTraceErr(err);
8907+ return err;
8908+}
8909+
8910+/* todo: remove this */
8911+static int h_d_revalidate(struct dentry *dentry, struct inode *inode,
8b6a4947 8912+ unsigned int flags, int do_udba, int dirren)
1facf9fc 8913+{
8914+ int err;
8915+ umode_t mode, h_mode;
5afbbe0d 8916+ aufs_bindex_t bindex, btail, btop, ibs, ibe;
38d290e6 8917+ unsigned char plus, unhashed, is_root, h_plus, h_nfs, tmpfile;
4a4d8108 8918+ struct inode *h_inode, *h_cached_inode;
1facf9fc 8919+ struct dentry *h_dentry;
8920+ struct qstr *name, *h_name;
8921+
8922+ err = 0;
8923+ plus = 0;
8924+ mode = 0;
1facf9fc 8925+ ibs = -1;
8926+ ibe = -1;
8927+ unhashed = !!d_unhashed(dentry);
8928+ is_root = !!IS_ROOT(dentry);
8929+ name = &dentry->d_name;
38d290e6 8930+ tmpfile = au_di(dentry)->di_tmpfile;
1facf9fc 8931+
8932+ /*
7f207e10
AM
8933+ * Theoretically, REVAL test should be unnecessary in case of
8934+ * {FS,I}NOTIFY.
8935+ * But {fs,i}notify doesn't fire some necessary events,
1facf9fc 8936+ * IN_ATTRIB for atime/nlink/pageio
1facf9fc 8937+ * Let's do REVAL test too.
8938+ */
8939+ if (do_udba && inode) {
8940+ mode = (inode->i_mode & S_IFMT);
8941+ plus = (inode->i_nlink > 0);
5afbbe0d
AM
8942+ ibs = au_ibtop(inode);
8943+ ibe = au_ibbot(inode);
1facf9fc 8944+ }
8945+
5afbbe0d
AM
8946+ btop = au_dbtop(dentry);
8947+ btail = btop;
1facf9fc 8948+ if (inode && S_ISDIR(inode->i_mode))
8949+ btail = au_dbtaildir(dentry);
5afbbe0d 8950+ for (bindex = btop; bindex <= btail; bindex++) {
1facf9fc 8951+ h_dentry = au_h_dptr(dentry, bindex);
8952+ if (!h_dentry)
8953+ continue;
8954+
523b37e3
AM
8955+ AuDbg("b%d, %pd\n", bindex, h_dentry);
8956+ h_nfs = !!au_test_nfs(h_dentry->d_sb);
027c5e7a 8957+ spin_lock(&h_dentry->d_lock);
1facf9fc 8958+ h_name = &h_dentry->d_name;
8959+ if (unlikely(do_udba
8960+ && !is_root
523b37e3
AM
8961+ && ((!h_nfs
8962+ && (unhashed != !!d_unhashed(h_dentry)
8b6a4947 8963+ || (!tmpfile && !dirren
38d290e6
JR
8964+ && !au_qstreq(name, h_name))
8965+ ))
523b37e3
AM
8966+ || (h_nfs
8967+ && !(flags & LOOKUP_OPEN)
8968+ && (h_dentry->d_flags
8969+ & DCACHE_NFSFS_RENAMED)))
1facf9fc 8970+ )) {
38d290e6
JR
8971+ int h_unhashed;
8972+
8973+ h_unhashed = d_unhashed(h_dentry);
027c5e7a 8974+ spin_unlock(&h_dentry->d_lock);
38d290e6
JR
8975+ AuDbg("unhash 0x%x 0x%x, %pd %pd\n",
8976+ unhashed, h_unhashed, dentry, h_dentry);
1facf9fc 8977+ goto err;
8978+ }
027c5e7a 8979+ spin_unlock(&h_dentry->d_lock);
1facf9fc 8980+
b4510431 8981+ err = au_do_h_d_reval(h_dentry, flags, dentry, bindex);
1facf9fc 8982+ if (unlikely(err))
8983+ /* do not goto err, to keep the errno */
8984+ break;
8985+
8986+ /* todo: plink too? */
8987+ if (!do_udba)
8988+ continue;
8989+
8990+ /* UDBA tests */
5527c038 8991+ if (unlikely(!!inode != d_is_positive(h_dentry)))
1facf9fc 8992+ goto err;
8993+
5527c038
JR
8994+ h_inode = NULL;
8995+ if (d_is_positive(h_dentry))
8996+ h_inode = d_inode(h_dentry);
1facf9fc 8997+ h_plus = plus;
8998+ h_mode = mode;
8999+ h_cached_inode = h_inode;
9000+ if (h_inode) {
9001+ h_mode = (h_inode->i_mode & S_IFMT);
9002+ h_plus = (h_inode->i_nlink > 0);
9003+ }
9004+ if (inode && ibs <= bindex && bindex <= ibe)
9005+ h_cached_inode = au_h_iptr(inode, bindex);
9006+
523b37e3 9007+ if (!h_nfs) {
38d290e6 9008+ if (unlikely(plus != h_plus && !tmpfile))
523b37e3
AM
9009+ goto err;
9010+ } else {
9011+ if (unlikely(!(h_dentry->d_flags & DCACHE_NFSFS_RENAMED)
9012+ && !is_root
9013+ && !IS_ROOT(h_dentry)
9014+ && unhashed != d_unhashed(h_dentry)))
9015+ goto err;
9016+ }
9017+ if (unlikely(mode != h_mode
1facf9fc 9018+ || h_cached_inode != h_inode))
9019+ goto err;
9020+ continue;
9021+
f6b6e03d 9022+err:
1facf9fc 9023+ err = -EINVAL;
9024+ break;
9025+ }
9026+
523b37e3 9027+ AuTraceErr(err);
1facf9fc 9028+ return err;
9029+}
9030+
027c5e7a 9031+/* todo: consolidate with do_refresh() and au_reval_for_attr() */
1facf9fc 9032+static int simple_reval_dpath(struct dentry *dentry, unsigned int sigen)
9033+{
9034+ int err;
9035+ struct dentry *parent;
1facf9fc 9036+
027c5e7a 9037+ if (!au_digen_test(dentry, sigen))
1facf9fc 9038+ return 0;
9039+
9040+ parent = dget_parent(dentry);
9041+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 9042+ AuDebugOn(au_digen_test(parent, sigen));
1facf9fc 9043+ au_dbg_verify_gen(parent, sigen);
027c5e7a 9044+ err = au_refresh_dentry(dentry, parent);
1facf9fc 9045+ di_read_unlock(parent, AuLock_IR);
9046+ dput(parent);
027c5e7a 9047+ AuTraceErr(err);
1facf9fc 9048+ return err;
9049+}
9050+
9051+int au_reval_dpath(struct dentry *dentry, unsigned int sigen)
9052+{
9053+ int err;
9054+ struct dentry *d, *parent;
1facf9fc 9055+
027c5e7a 9056+ if (!au_ftest_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR))
1facf9fc 9057+ return simple_reval_dpath(dentry, sigen);
9058+
9059+ /* slow loop, keep it simple and stupid */
9060+ /* cf: au_cpup_dirs() */
9061+ err = 0;
9062+ parent = NULL;
027c5e7a 9063+ while (au_digen_test(dentry, sigen)) {
1facf9fc 9064+ d = dentry;
9065+ while (1) {
9066+ dput(parent);
9067+ parent = dget_parent(d);
027c5e7a 9068+ if (!au_digen_test(parent, sigen))
1facf9fc 9069+ break;
9070+ d = parent;
9071+ }
9072+
1facf9fc 9073+ if (d != dentry)
027c5e7a 9074+ di_write_lock_child2(d);
1facf9fc 9075+
9076+ /* someone might update our dentry while we were sleeping */
027c5e7a
AM
9077+ if (au_digen_test(d, sigen)) {
9078+ /*
9079+ * todo: consolidate with simple_reval_dpath(),
9080+ * do_refresh() and au_reval_for_attr().
9081+ */
1facf9fc 9082+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 9083+ err = au_refresh_dentry(d, parent);
1facf9fc 9084+ di_read_unlock(parent, AuLock_IR);
9085+ }
9086+
9087+ if (d != dentry)
9088+ di_write_unlock(d);
9089+ dput(parent);
9090+ if (unlikely(err))
9091+ break;
9092+ }
9093+
9094+ return err;
9095+}
9096+
9097+/*
9098+ * if valid returns 1, otherwise 0.
9099+ */
b4510431 9100+static int aufs_d_revalidate(struct dentry *dentry, unsigned int flags)
1facf9fc 9101+{
9102+ int valid, err;
9103+ unsigned int sigen;
8b6a4947 9104+ unsigned char do_udba, dirren;
1facf9fc 9105+ struct super_block *sb;
9106+ struct inode *inode;
9107+
027c5e7a 9108+ /* todo: support rcu-walk? */
b4510431 9109+ if (flags & LOOKUP_RCU)
027c5e7a
AM
9110+ return -ECHILD;
9111+
9112+ valid = 0;
9113+ if (unlikely(!au_di(dentry)))
9114+ goto out;
9115+
e49829fe 9116+ valid = 1;
1facf9fc 9117+ sb = dentry->d_sb;
e49829fe
JR
9118+ /*
9119+ * todo: very ugly
9120+ * i_mutex of parent dir may be held,
9121+ * but we should not return 'invalid' due to busy.
9122+ */
9123+ err = aufs_read_lock(dentry, AuLock_FLUSH | AuLock_DW | AuLock_NOPLM);
9124+ if (unlikely(err)) {
9125+ valid = err;
027c5e7a 9126+ AuTraceErr(err);
e49829fe
JR
9127+ goto out;
9128+ }
5527c038
JR
9129+ inode = NULL;
9130+ if (d_really_is_positive(dentry))
9131+ inode = d_inode(dentry);
5afbbe0d 9132+ if (unlikely(inode && au_is_bad_inode(inode))) {
c1595e42
JR
9133+ err = -EINVAL;
9134+ AuTraceErr(err);
9135+ goto out_dgrade;
9136+ }
027c5e7a
AM
9137+ if (unlikely(au_dbrange_test(dentry))) {
9138+ err = -EINVAL;
9139+ AuTraceErr(err);
9140+ goto out_dgrade;
1facf9fc 9141+ }
027c5e7a
AM
9142+
9143+ sigen = au_sigen(sb);
9144+ if (au_digen_test(dentry, sigen)) {
1facf9fc 9145+ AuDebugOn(IS_ROOT(dentry));
027c5e7a
AM
9146+ err = au_reval_dpath(dentry, sigen);
9147+ if (unlikely(err)) {
9148+ AuTraceErr(err);
1facf9fc 9149+ goto out_dgrade;
027c5e7a 9150+ }
1facf9fc 9151+ }
9152+ di_downgrade_lock(dentry, AuLock_IR);
9153+
1facf9fc 9154+ err = -EINVAL;
c1595e42 9155+ if (!(flags & (LOOKUP_OPEN | LOOKUP_EMPTY))
523b37e3 9156+ && inode
38d290e6 9157+ && !(inode->i_state && I_LINKABLE)
79b8bda9
AM
9158+ && (IS_DEADDIR(inode) || !inode->i_nlink)) {
9159+ AuTraceErr(err);
027c5e7a 9160+ goto out_inval;
79b8bda9 9161+ }
027c5e7a 9162+
1facf9fc 9163+ do_udba = !au_opt_test(au_mntflags(sb), UDBA_NONE);
9164+ if (do_udba && inode) {
5afbbe0d 9165+ aufs_bindex_t btop = au_ibtop(inode);
027c5e7a 9166+ struct inode *h_inode;
1facf9fc 9167+
5afbbe0d
AM
9168+ if (btop >= 0) {
9169+ h_inode = au_h_iptr(inode, btop);
79b8bda9
AM
9170+ if (h_inode && au_test_higen(inode, h_inode)) {
9171+ AuTraceErr(err);
027c5e7a 9172+ goto out_inval;
79b8bda9 9173+ }
027c5e7a 9174+ }
1facf9fc 9175+ }
9176+
8b6a4947
AM
9177+ dirren = !!au_opt_test(au_mntflags(sb), DIRREN);
9178+ err = h_d_revalidate(dentry, inode, flags, do_udba, dirren);
5afbbe0d 9179+ if (unlikely(!err && do_udba && au_dbtop(dentry) < 0)) {
1facf9fc 9180+ err = -EIO;
523b37e3
AM
9181+ AuDbg("both of real entry and whiteout found, %p, err %d\n",
9182+ dentry, err);
027c5e7a 9183+ }
e49829fe 9184+ goto out_inval;
1facf9fc 9185+
4f0767ce 9186+out_dgrade:
1facf9fc 9187+ di_downgrade_lock(dentry, AuLock_IR);
e49829fe 9188+out_inval:
1facf9fc 9189+ aufs_read_unlock(dentry, AuLock_IR);
9190+ AuTraceErr(err);
9191+ valid = !err;
e49829fe 9192+out:
027c5e7a 9193+ if (!valid) {
523b37e3 9194+ AuDbg("%pd invalid, %d\n", dentry, valid);
027c5e7a
AM
9195+ d_drop(dentry);
9196+ }
1facf9fc 9197+ return valid;
9198+}
9199+
9200+static void aufs_d_release(struct dentry *dentry)
9201+{
027c5e7a 9202+ if (au_di(dentry)) {
4a4d8108
AM
9203+ au_di_fin(dentry);
9204+ au_hn_di_reinit(dentry);
1facf9fc 9205+ }
1facf9fc 9206+}
9207+
4a4d8108 9208+const struct dentry_operations aufs_dop = {
c06a8ce3
AM
9209+ .d_revalidate = aufs_d_revalidate,
9210+ .d_weak_revalidate = aufs_d_revalidate,
9211+ .d_release = aufs_d_release
1facf9fc 9212+};
79b8bda9
AM
9213+
9214+/* aufs_dop without d_revalidate */
9215+const struct dentry_operations aufs_dop_noreval = {
9216+ .d_release = aufs_d_release
9217+};
7f207e10 9218diff -urN /usr/share/empty/fs/aufs/dentry.h linux/fs/aufs/dentry.h
eca34b5c 9219--- /usr/share/empty/fs/aufs/dentry.h 1970-01-01 01:00:00.000000000 +0100
016522bc 9220+++ linux/fs/aufs/dentry.h 2020-01-27 10:57:18.168871450 +0100
9f237c51 9221@@ -0,0 +1,268 @@
062440b3 9222+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 9223+/*
016522bc 9224+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 9225+ *
9226+ * This program, aufs is free software; you can redistribute it and/or modify
9227+ * it under the terms of the GNU General Public License as published by
9228+ * the Free Software Foundation; either version 2 of the License, or
9229+ * (at your option) any later version.
dece6358
AM
9230+ *
9231+ * This program is distributed in the hope that it will be useful,
9232+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9233+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9234+ * GNU General Public License for more details.
9235+ *
9236+ * You should have received a copy of the GNU General Public License
523b37e3 9237+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 9238+ */
9239+
9240+/*
9241+ * lookup and dentry operations
9242+ */
9243+
9244+#ifndef __AUFS_DENTRY_H__
9245+#define __AUFS_DENTRY_H__
9246+
9247+#ifdef __KERNEL__
9248+
dece6358 9249+#include <linux/dcache.h>
8b6a4947 9250+#include "dirren.h"
1facf9fc 9251+#include "rwsem.h"
9252+
1facf9fc 9253+struct au_hdentry {
9254+ struct dentry *hd_dentry;
027c5e7a 9255+ aufs_bindex_t hd_id;
1facf9fc 9256+};
9257+
9258+struct au_dinfo {
9259+ atomic_t di_generation;
9260+
dece6358 9261+ struct au_rwsem di_rwsem;
5afbbe0d 9262+ aufs_bindex_t di_btop, di_bbot, di_bwh, di_bdiropq;
38d290e6 9263+ unsigned char di_tmpfile; /* to allow the different name */
1c60b727 9264+ struct au_hdentry *di_hdentry;
9f237c51 9265+ struct rcu_head rcu;
4a4d8108 9266+} ____cacheline_aligned_in_smp;
1facf9fc 9267+
9268+/* ---------------------------------------------------------------------- */
9269+
5afbbe0d
AM
9270+/* flags for au_lkup_dentry() */
9271+#define AuLkup_ALLOW_NEG 1
9272+#define AuLkup_IGNORE_PERM (1 << 1)
8b6a4947 9273+#define AuLkup_DIRREN (1 << 2)
5afbbe0d
AM
9274+#define au_ftest_lkup(flags, name) ((flags) & AuLkup_##name)
9275+#define au_fset_lkup(flags, name) \
9276+ do { (flags) |= AuLkup_##name; } while (0)
9277+#define au_fclr_lkup(flags, name) \
9278+ do { (flags) &= ~AuLkup_##name; } while (0)
9279+
8b6a4947
AM
9280+#ifndef CONFIG_AUFS_DIRREN
9281+#undef AuLkup_DIRREN
9282+#define AuLkup_DIRREN 0
9283+#endif
9284+
9285+struct au_do_lookup_args {
9286+ unsigned int flags;
9287+ mode_t type;
9288+ struct qstr whname, *name;
9289+ struct au_dr_lookup dirren;
9290+};
9291+
5afbbe0d
AM
9292+/* ---------------------------------------------------------------------- */
9293+
1facf9fc 9294+/* dentry.c */
79b8bda9 9295+extern const struct dentry_operations aufs_dop, aufs_dop_noreval;
1facf9fc 9296+struct au_branch;
076b876e 9297+struct dentry *au_sio_lkup_one(struct qstr *name, struct dentry *parent);
1facf9fc 9298+int au_h_verify(struct dentry *h_dentry, unsigned int udba, struct inode *h_dir,
9299+ struct dentry *h_parent, struct au_branch *br);
9300+
5afbbe0d
AM
9301+int au_lkup_dentry(struct dentry *dentry, aufs_bindex_t btop,
9302+ unsigned int flags);
86dc4139 9303+int au_lkup_neg(struct dentry *dentry, aufs_bindex_t bindex, int wh);
027c5e7a 9304+int au_refresh_dentry(struct dentry *dentry, struct dentry *parent);
1facf9fc 9305+int au_reval_dpath(struct dentry *dentry, unsigned int sigen);
79b8bda9 9306+void au_refresh_dop(struct dentry *dentry, int force_reval);
1facf9fc 9307+
9308+/* dinfo.c */
4a4d8108 9309+void au_di_init_once(void *_di);
027c5e7a
AM
9310+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc);
9311+void au_di_free(struct au_dinfo *dinfo);
9312+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b);
9313+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src);
4a4d8108
AM
9314+int au_di_init(struct dentry *dentry);
9315+void au_di_fin(struct dentry *dentry);
e2f27e51 9316+int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink);
1facf9fc 9317+
9318+void di_read_lock(struct dentry *d, int flags, unsigned int lsc);
9319+void di_read_unlock(struct dentry *d, int flags);
9320+void di_downgrade_lock(struct dentry *d, int flags);
9321+void di_write_lock(struct dentry *d, unsigned int lsc);
9322+void di_write_unlock(struct dentry *d);
9323+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir);
9324+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir);
9325+void di_write_unlock2(struct dentry *d1, struct dentry *d2);
9326+
9327+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex);
2cbb1c4b 9328+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex);
1facf9fc 9329+aufs_bindex_t au_dbtail(struct dentry *dentry);
9330+aufs_bindex_t au_dbtaildir(struct dentry *dentry);
9331+
9332+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
9333+ struct dentry *h_dentry);
027c5e7a
AM
9334+int au_digen_test(struct dentry *dentry, unsigned int sigen);
9335+int au_dbrange_test(struct dentry *dentry);
1facf9fc 9336+void au_update_digen(struct dentry *dentry);
9337+void au_update_dbrange(struct dentry *dentry, int do_put_zero);
5afbbe0d
AM
9338+void au_update_dbtop(struct dentry *dentry);
9339+void au_update_dbbot(struct dentry *dentry);
1facf9fc 9340+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry);
9341+
9342+/* ---------------------------------------------------------------------- */
9343+
9344+static inline struct au_dinfo *au_di(struct dentry *dentry)
9345+{
9346+ return dentry->d_fsdata;
9347+}
9348+
9349+/* ---------------------------------------------------------------------- */
9350+
9351+/* lock subclass for dinfo */
9352+enum {
9353+ AuLsc_DI_CHILD, /* child first */
4a4d8108 9354+ AuLsc_DI_CHILD2, /* rename(2), link(2), and cpup at hnotify */
1facf9fc 9355+ AuLsc_DI_CHILD3, /* copyup dirs */
9356+ AuLsc_DI_PARENT,
9357+ AuLsc_DI_PARENT2,
027c5e7a
AM
9358+ AuLsc_DI_PARENT3,
9359+ AuLsc_DI_TMP /* temp for replacing dinfo */
1facf9fc 9360+};
9361+
9362+/*
9363+ * di_read_lock_child, di_write_lock_child,
9364+ * di_read_lock_child2, di_write_lock_child2,
9365+ * di_read_lock_child3, di_write_lock_child3,
9366+ * di_read_lock_parent, di_write_lock_parent,
9367+ * di_read_lock_parent2, di_write_lock_parent2,
9368+ * di_read_lock_parent3, di_write_lock_parent3,
9369+ */
9370+#define AuReadLockFunc(name, lsc) \
9371+static inline void di_read_lock_##name(struct dentry *d, int flags) \
9372+{ di_read_lock(d, flags, AuLsc_DI_##lsc); }
9373+
9374+#define AuWriteLockFunc(name, lsc) \
9375+static inline void di_write_lock_##name(struct dentry *d) \
9376+{ di_write_lock(d, AuLsc_DI_##lsc); }
9377+
9378+#define AuRWLockFuncs(name, lsc) \
9379+ AuReadLockFunc(name, lsc) \
9380+ AuWriteLockFunc(name, lsc)
9381+
9382+AuRWLockFuncs(child, CHILD);
9383+AuRWLockFuncs(child2, CHILD2);
9384+AuRWLockFuncs(child3, CHILD3);
9385+AuRWLockFuncs(parent, PARENT);
9386+AuRWLockFuncs(parent2, PARENT2);
9387+AuRWLockFuncs(parent3, PARENT3);
9388+
9389+#undef AuReadLockFunc
9390+#undef AuWriteLockFunc
9391+#undef AuRWLockFuncs
9392+
9393+#define DiMustNoWaiters(d) AuRwMustNoWaiters(&au_di(d)->di_rwsem)
dece6358
AM
9394+#define DiMustAnyLock(d) AuRwMustAnyLock(&au_di(d)->di_rwsem)
9395+#define DiMustWriteLock(d) AuRwMustWriteLock(&au_di(d)->di_rwsem)
1facf9fc 9396+
9397+/* ---------------------------------------------------------------------- */
9398+
9399+/* todo: memory barrier? */
9400+static inline unsigned int au_digen(struct dentry *d)
9401+{
9402+ return atomic_read(&au_di(d)->di_generation);
9403+}
9404+
9405+static inline void au_h_dentry_init(struct au_hdentry *hdentry)
9406+{
9407+ hdentry->hd_dentry = NULL;
9408+}
9409+
5afbbe0d
AM
9410+static inline struct au_hdentry *au_hdentry(struct au_dinfo *di,
9411+ aufs_bindex_t bindex)
9412+{
9413+ return di->di_hdentry + bindex;
9414+}
9415+
1facf9fc 9416+static inline void au_hdput(struct au_hdentry *hd)
9417+{
4a4d8108
AM
9418+ if (hd)
9419+ dput(hd->hd_dentry);
1facf9fc 9420+}
9421+
5afbbe0d 9422+static inline aufs_bindex_t au_dbtop(struct dentry *dentry)
1facf9fc 9423+{
1308ab2a 9424+ DiMustAnyLock(dentry);
5afbbe0d 9425+ return au_di(dentry)->di_btop;
1facf9fc 9426+}
9427+
5afbbe0d 9428+static inline aufs_bindex_t au_dbbot(struct dentry *dentry)
1facf9fc 9429+{
1308ab2a 9430+ DiMustAnyLock(dentry);
5afbbe0d 9431+ return au_di(dentry)->di_bbot;
1facf9fc 9432+}
9433+
9434+static inline aufs_bindex_t au_dbwh(struct dentry *dentry)
9435+{
1308ab2a 9436+ DiMustAnyLock(dentry);
1facf9fc 9437+ return au_di(dentry)->di_bwh;
9438+}
9439+
9440+static inline aufs_bindex_t au_dbdiropq(struct dentry *dentry)
9441+{
1308ab2a 9442+ DiMustAnyLock(dentry);
1facf9fc 9443+ return au_di(dentry)->di_bdiropq;
9444+}
9445+
9446+/* todo: hard/soft set? */
5afbbe0d 9447+static inline void au_set_dbtop(struct dentry *dentry, aufs_bindex_t bindex)
1facf9fc 9448+{
1308ab2a 9449+ DiMustWriteLock(dentry);
5afbbe0d 9450+ au_di(dentry)->di_btop = bindex;
1facf9fc 9451+}
9452+
5afbbe0d 9453+static inline void au_set_dbbot(struct dentry *dentry, aufs_bindex_t bindex)
1facf9fc 9454+{
1308ab2a 9455+ DiMustWriteLock(dentry);
5afbbe0d 9456+ au_di(dentry)->di_bbot = bindex;
1facf9fc 9457+}
9458+
9459+static inline void au_set_dbwh(struct dentry *dentry, aufs_bindex_t bindex)
9460+{
1308ab2a 9461+ DiMustWriteLock(dentry);
5afbbe0d 9462+ /* dbwh can be outside of btop - bbot range */
1facf9fc 9463+ au_di(dentry)->di_bwh = bindex;
9464+}
9465+
9466+static inline void au_set_dbdiropq(struct dentry *dentry, aufs_bindex_t bindex)
9467+{
1308ab2a 9468+ DiMustWriteLock(dentry);
1facf9fc 9469+ au_di(dentry)->di_bdiropq = bindex;
9470+}
9471+
9472+/* ---------------------------------------------------------------------- */
9473+
4a4d8108 9474+#ifdef CONFIG_AUFS_HNOTIFY
1facf9fc 9475+static inline void au_digen_dec(struct dentry *d)
9476+{
e49829fe 9477+ atomic_dec(&au_di(d)->di_generation);
1facf9fc 9478+}
9479+
4a4d8108 9480+static inline void au_hn_di_reinit(struct dentry *dentry)
1facf9fc 9481+{
9482+ dentry->d_fsdata = NULL;
9483+}
9484+#else
4a4d8108
AM
9485+AuStubVoid(au_hn_di_reinit, struct dentry *dentry __maybe_unused)
9486+#endif /* CONFIG_AUFS_HNOTIFY */
1facf9fc 9487+
9488+#endif /* __KERNEL__ */
9489+#endif /* __AUFS_DENTRY_H__ */
7f207e10 9490diff -urN /usr/share/empty/fs/aufs/dinfo.c linux/fs/aufs/dinfo.c
eca34b5c 9491--- /usr/share/empty/fs/aufs/dinfo.c 1970-01-01 01:00:00.000000000 +0100
016522bc 9492+++ linux/fs/aufs/dinfo.c 2020-01-27 10:57:18.168871450 +0100
062440b3 9493@@ -0,0 +1,554 @@
cd7a4cd9 9494+// SPDX-License-Identifier: GPL-2.0
1facf9fc 9495+/*
016522bc 9496+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 9497+ *
9498+ * This program, aufs is free software; you can redistribute it and/or modify
9499+ * it under the terms of the GNU General Public License as published by
9500+ * the Free Software Foundation; either version 2 of the License, or
9501+ * (at your option) any later version.
dece6358
AM
9502+ *
9503+ * This program is distributed in the hope that it will be useful,
9504+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9505+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9506+ * GNU General Public License for more details.
9507+ *
9508+ * You should have received a copy of the GNU General Public License
523b37e3 9509+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 9510+ */
9511+
9512+/*
9513+ * dentry private data
9514+ */
9515+
9516+#include "aufs.h"
9517+
e49829fe 9518+void au_di_init_once(void *_dinfo)
4a4d8108 9519+{
e49829fe 9520+ struct au_dinfo *dinfo = _dinfo;
4a4d8108 9521+
e49829fe 9522+ au_rw_init(&dinfo->di_rwsem);
4a4d8108
AM
9523+}
9524+
027c5e7a 9525+struct au_dinfo *au_di_alloc(struct super_block *sb, unsigned int lsc)
1facf9fc 9526+{
9527+ struct au_dinfo *dinfo;
027c5e7a 9528+ int nbr, i;
1facf9fc 9529+
9530+ dinfo = au_cache_alloc_dinfo();
9531+ if (unlikely(!dinfo))
9532+ goto out;
9533+
5afbbe0d 9534+ nbr = au_sbbot(sb) + 1;
1facf9fc 9535+ if (nbr <= 0)
9536+ nbr = 1;
9537+ dinfo->di_hdentry = kcalloc(nbr, sizeof(*dinfo->di_hdentry), GFP_NOFS);
027c5e7a
AM
9538+ if (dinfo->di_hdentry) {
9539+ au_rw_write_lock_nested(&dinfo->di_rwsem, lsc);
5afbbe0d
AM
9540+ dinfo->di_btop = -1;
9541+ dinfo->di_bbot = -1;
027c5e7a
AM
9542+ dinfo->di_bwh = -1;
9543+ dinfo->di_bdiropq = -1;
38d290e6 9544+ dinfo->di_tmpfile = 0;
027c5e7a
AM
9545+ for (i = 0; i < nbr; i++)
9546+ dinfo->di_hdentry[i].hd_id = -1;
9547+ goto out;
9548+ }
1facf9fc 9549+
1c60b727 9550+ au_cache_free_dinfo(dinfo);
027c5e7a
AM
9551+ dinfo = NULL;
9552+
4f0767ce 9553+out:
027c5e7a 9554+ return dinfo;
1facf9fc 9555+}
9556+
027c5e7a 9557+void au_di_free(struct au_dinfo *dinfo)
4a4d8108 9558+{
4a4d8108 9559+ struct au_hdentry *p;
5afbbe0d 9560+ aufs_bindex_t bbot, bindex;
4a4d8108
AM
9561+
9562+ /* dentry may not be revalidated */
5afbbe0d 9563+ bindex = dinfo->di_btop;
4a4d8108 9564+ if (bindex >= 0) {
5afbbe0d
AM
9565+ bbot = dinfo->di_bbot;
9566+ p = au_hdentry(dinfo, bindex);
9567+ while (bindex++ <= bbot)
4a4d8108
AM
9568+ au_hdput(p++);
9569+ }
9f237c51 9570+ au_kfree_try_rcu(dinfo->di_hdentry);
1c60b727 9571+ au_cache_free_dinfo(dinfo);
027c5e7a
AM
9572+}
9573+
9574+void au_di_swap(struct au_dinfo *a, struct au_dinfo *b)
9575+{
9576+ struct au_hdentry *p;
9577+ aufs_bindex_t bi;
9578+
9579+ AuRwMustWriteLock(&a->di_rwsem);
9580+ AuRwMustWriteLock(&b->di_rwsem);
9581+
9582+#define DiSwap(v, name) \
9583+ do { \
9584+ v = a->di_##name; \
9585+ a->di_##name = b->di_##name; \
9586+ b->di_##name = v; \
9587+ } while (0)
9588+
9589+ DiSwap(p, hdentry);
5afbbe0d
AM
9590+ DiSwap(bi, btop);
9591+ DiSwap(bi, bbot);
027c5e7a
AM
9592+ DiSwap(bi, bwh);
9593+ DiSwap(bi, bdiropq);
9594+ /* smp_mb(); */
9595+
9596+#undef DiSwap
9597+}
9598+
9599+void au_di_cp(struct au_dinfo *dst, struct au_dinfo *src)
9600+{
9601+ AuRwMustWriteLock(&dst->di_rwsem);
9602+ AuRwMustWriteLock(&src->di_rwsem);
9603+
5afbbe0d
AM
9604+ dst->di_btop = src->di_btop;
9605+ dst->di_bbot = src->di_bbot;
027c5e7a
AM
9606+ dst->di_bwh = src->di_bwh;
9607+ dst->di_bdiropq = src->di_bdiropq;
9608+ /* smp_mb(); */
9609+}
9610+
9611+int au_di_init(struct dentry *dentry)
9612+{
9613+ int err;
9614+ struct super_block *sb;
9615+ struct au_dinfo *dinfo;
9616+
9617+ err = 0;
9618+ sb = dentry->d_sb;
9619+ dinfo = au_di_alloc(sb, AuLsc_DI_CHILD);
9620+ if (dinfo) {
9621+ atomic_set(&dinfo->di_generation, au_sigen(sb));
9622+ /* smp_mb(); */ /* atomic_set */
9623+ dentry->d_fsdata = dinfo;
9624+ } else
9625+ err = -ENOMEM;
9626+
9627+ return err;
9628+}
9629+
9630+void au_di_fin(struct dentry *dentry)
9631+{
9632+ struct au_dinfo *dinfo;
9633+
9634+ dinfo = au_di(dentry);
9635+ AuRwDestroy(&dinfo->di_rwsem);
9636+ au_di_free(dinfo);
4a4d8108
AM
9637+}
9638+
e2f27e51 9639+int au_di_realloc(struct au_dinfo *dinfo, int nbr, int may_shrink)
1facf9fc 9640+{
9641+ int err, sz;
9642+ struct au_hdentry *hdp;
9643+
1308ab2a 9644+ AuRwMustWriteLock(&dinfo->di_rwsem);
9645+
1facf9fc 9646+ err = -ENOMEM;
5afbbe0d 9647+ sz = sizeof(*hdp) * (dinfo->di_bbot + 1);
1facf9fc 9648+ if (!sz)
9649+ sz = sizeof(*hdp);
e2f27e51
AM
9650+ hdp = au_kzrealloc(dinfo->di_hdentry, sz, sizeof(*hdp) * nbr, GFP_NOFS,
9651+ may_shrink);
1facf9fc 9652+ if (hdp) {
9653+ dinfo->di_hdentry = hdp;
9654+ err = 0;
9655+ }
9656+
9657+ return err;
9658+}
9659+
9660+/* ---------------------------------------------------------------------- */
9661+
9662+static void do_ii_write_lock(struct inode *inode, unsigned int lsc)
9663+{
9664+ switch (lsc) {
9665+ case AuLsc_DI_CHILD:
9666+ ii_write_lock_child(inode);
9667+ break;
9668+ case AuLsc_DI_CHILD2:
9669+ ii_write_lock_child2(inode);
9670+ break;
9671+ case AuLsc_DI_CHILD3:
9672+ ii_write_lock_child3(inode);
9673+ break;
9674+ case AuLsc_DI_PARENT:
9675+ ii_write_lock_parent(inode);
9676+ break;
9677+ case AuLsc_DI_PARENT2:
9678+ ii_write_lock_parent2(inode);
9679+ break;
9680+ case AuLsc_DI_PARENT3:
9681+ ii_write_lock_parent3(inode);
9682+ break;
9683+ default:
9684+ BUG();
9685+ }
9686+}
9687+
9688+static void do_ii_read_lock(struct inode *inode, unsigned int lsc)
9689+{
9690+ switch (lsc) {
9691+ case AuLsc_DI_CHILD:
9692+ ii_read_lock_child(inode);
9693+ break;
9694+ case AuLsc_DI_CHILD2:
9695+ ii_read_lock_child2(inode);
9696+ break;
9697+ case AuLsc_DI_CHILD3:
9698+ ii_read_lock_child3(inode);
9699+ break;
9700+ case AuLsc_DI_PARENT:
9701+ ii_read_lock_parent(inode);
9702+ break;
9703+ case AuLsc_DI_PARENT2:
9704+ ii_read_lock_parent2(inode);
9705+ break;
9706+ case AuLsc_DI_PARENT3:
9707+ ii_read_lock_parent3(inode);
9708+ break;
9709+ default:
9710+ BUG();
9711+ }
9712+}
9713+
9714+void di_read_lock(struct dentry *d, int flags, unsigned int lsc)
9715+{
5527c038
JR
9716+ struct inode *inode;
9717+
dece6358 9718+ au_rw_read_lock_nested(&au_di(d)->di_rwsem, lsc);
5527c038
JR
9719+ if (d_really_is_positive(d)) {
9720+ inode = d_inode(d);
1facf9fc 9721+ if (au_ftest_lock(flags, IW))
5527c038 9722+ do_ii_write_lock(inode, lsc);
1facf9fc 9723+ else if (au_ftest_lock(flags, IR))
5527c038 9724+ do_ii_read_lock(inode, lsc);
1facf9fc 9725+ }
9726+}
9727+
9728+void di_read_unlock(struct dentry *d, int flags)
9729+{
5527c038
JR
9730+ struct inode *inode;
9731+
9732+ if (d_really_is_positive(d)) {
9733+ inode = d_inode(d);
027c5e7a
AM
9734+ if (au_ftest_lock(flags, IW)) {
9735+ au_dbg_verify_dinode(d);
5527c038 9736+ ii_write_unlock(inode);
027c5e7a
AM
9737+ } else if (au_ftest_lock(flags, IR)) {
9738+ au_dbg_verify_dinode(d);
5527c038 9739+ ii_read_unlock(inode);
027c5e7a 9740+ }
1facf9fc 9741+ }
dece6358 9742+ au_rw_read_unlock(&au_di(d)->di_rwsem);
1facf9fc 9743+}
9744+
9745+void di_downgrade_lock(struct dentry *d, int flags)
9746+{
5527c038
JR
9747+ if (d_really_is_positive(d) && au_ftest_lock(flags, IR))
9748+ ii_downgrade_lock(d_inode(d));
dece6358 9749+ au_rw_dgrade_lock(&au_di(d)->di_rwsem);
1facf9fc 9750+}
9751+
9752+void di_write_lock(struct dentry *d, unsigned int lsc)
9753+{
dece6358 9754+ au_rw_write_lock_nested(&au_di(d)->di_rwsem, lsc);
5527c038
JR
9755+ if (d_really_is_positive(d))
9756+ do_ii_write_lock(d_inode(d), lsc);
1facf9fc 9757+}
9758+
9759+void di_write_unlock(struct dentry *d)
9760+{
027c5e7a 9761+ au_dbg_verify_dinode(d);
5527c038
JR
9762+ if (d_really_is_positive(d))
9763+ ii_write_unlock(d_inode(d));
dece6358 9764+ au_rw_write_unlock(&au_di(d)->di_rwsem);
1facf9fc 9765+}
9766+
9767+void di_write_lock2_child(struct dentry *d1, struct dentry *d2, int isdir)
9768+{
9769+ AuDebugOn(d1 == d2
5527c038 9770+ || d_inode(d1) == d_inode(d2)
1facf9fc 9771+ || d1->d_sb != d2->d_sb);
9772+
521ced18
JR
9773+ if ((isdir && au_test_subdir(d1, d2))
9774+ || d1 < d2) {
1facf9fc 9775+ di_write_lock_child(d1);
9776+ di_write_lock_child2(d2);
9777+ } else {
1facf9fc 9778+ di_write_lock_child(d2);
9779+ di_write_lock_child2(d1);
9780+ }
9781+}
9782+
9783+void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir)
9784+{
9785+ AuDebugOn(d1 == d2
5527c038 9786+ || d_inode(d1) == d_inode(d2)
1facf9fc 9787+ || d1->d_sb != d2->d_sb);
9788+
521ced18
JR
9789+ if ((isdir && au_test_subdir(d1, d2))
9790+ || d1 < d2) {
1facf9fc 9791+ di_write_lock_parent(d1);
9792+ di_write_lock_parent2(d2);
9793+ } else {
1facf9fc 9794+ di_write_lock_parent(d2);
9795+ di_write_lock_parent2(d1);
9796+ }
9797+}
9798+
9799+void di_write_unlock2(struct dentry *d1, struct dentry *d2)
9800+{
9801+ di_write_unlock(d1);
5527c038 9802+ if (d_inode(d1) == d_inode(d2))
dece6358 9803+ au_rw_write_unlock(&au_di(d2)->di_rwsem);
1facf9fc 9804+ else
9805+ di_write_unlock(d2);
9806+}
9807+
9808+/* ---------------------------------------------------------------------- */
9809+
9810+struct dentry *au_h_dptr(struct dentry *dentry, aufs_bindex_t bindex)
9811+{
9812+ struct dentry *d;
9813+
1308ab2a 9814+ DiMustAnyLock(dentry);
9815+
5afbbe0d 9816+ if (au_dbtop(dentry) < 0 || bindex < au_dbtop(dentry))
1facf9fc 9817+ return NULL;
9818+ AuDebugOn(bindex < 0);
5afbbe0d 9819+ d = au_hdentry(au_di(dentry), bindex)->hd_dentry;
c1595e42 9820+ AuDebugOn(d && au_dcount(d) <= 0);
1facf9fc 9821+ return d;
9822+}
9823+
2cbb1c4b
JR
9824+/*
9825+ * extended version of au_h_dptr().
38d290e6
JR
9826+ * returns a hashed and positive (or linkable) h_dentry in bindex, NULL, or
9827+ * error.
2cbb1c4b
JR
9828+ */
9829+struct dentry *au_h_d_alias(struct dentry *dentry, aufs_bindex_t bindex)
9830+{
9831+ struct dentry *h_dentry;
9832+ struct inode *inode, *h_inode;
9833+
5527c038 9834+ AuDebugOn(d_really_is_negative(dentry));
2cbb1c4b
JR
9835+
9836+ h_dentry = NULL;
5afbbe0d
AM
9837+ if (au_dbtop(dentry) <= bindex
9838+ && bindex <= au_dbbot(dentry))
2cbb1c4b 9839+ h_dentry = au_h_dptr(dentry, bindex);
38d290e6 9840+ if (h_dentry && !au_d_linkable(h_dentry)) {
2cbb1c4b
JR
9841+ dget(h_dentry);
9842+ goto out; /* success */
9843+ }
9844+
5527c038 9845+ inode = d_inode(dentry);
5afbbe0d
AM
9846+ AuDebugOn(bindex < au_ibtop(inode));
9847+ AuDebugOn(au_ibbot(inode) < bindex);
2cbb1c4b
JR
9848+ h_inode = au_h_iptr(inode, bindex);
9849+ h_dentry = d_find_alias(h_inode);
9850+ if (h_dentry) {
9851+ if (!IS_ERR(h_dentry)) {
38d290e6 9852+ if (!au_d_linkable(h_dentry))
2cbb1c4b
JR
9853+ goto out; /* success */
9854+ dput(h_dentry);
9855+ } else
9856+ goto out;
9857+ }
9858+
9859+ if (au_opt_test(au_mntflags(dentry->d_sb), PLINK)) {
9860+ h_dentry = au_plink_lkup(inode, bindex);
9861+ AuDebugOn(!h_dentry);
9862+ if (!IS_ERR(h_dentry)) {
9863+ if (!au_d_hashed_positive(h_dentry))
9864+ goto out; /* success */
9865+ dput(h_dentry);
9866+ h_dentry = NULL;
9867+ }
9868+ }
9869+
9870+out:
9871+ AuDbgDentry(h_dentry);
9872+ return h_dentry;
9873+}
9874+
1facf9fc 9875+aufs_bindex_t au_dbtail(struct dentry *dentry)
9876+{
5afbbe0d 9877+ aufs_bindex_t bbot, bwh;
1facf9fc 9878+
5afbbe0d
AM
9879+ bbot = au_dbbot(dentry);
9880+ if (0 <= bbot) {
1facf9fc 9881+ bwh = au_dbwh(dentry);
9882+ if (!bwh)
9883+ return bwh;
5afbbe0d 9884+ if (0 < bwh && bwh < bbot)
1facf9fc 9885+ return bwh - 1;
9886+ }
5afbbe0d 9887+ return bbot;
1facf9fc 9888+}
9889+
9890+aufs_bindex_t au_dbtaildir(struct dentry *dentry)
9891+{
5afbbe0d 9892+ aufs_bindex_t bbot, bopq;
1facf9fc 9893+
5afbbe0d
AM
9894+ bbot = au_dbtail(dentry);
9895+ if (0 <= bbot) {
1facf9fc 9896+ bopq = au_dbdiropq(dentry);
5afbbe0d
AM
9897+ if (0 <= bopq && bopq < bbot)
9898+ bbot = bopq;
1facf9fc 9899+ }
5afbbe0d 9900+ return bbot;
1facf9fc 9901+}
9902+
9903+/* ---------------------------------------------------------------------- */
9904+
9905+void au_set_h_dptr(struct dentry *dentry, aufs_bindex_t bindex,
9906+ struct dentry *h_dentry)
9907+{
5afbbe0d
AM
9908+ struct au_dinfo *dinfo;
9909+ struct au_hdentry *hd;
027c5e7a 9910+ struct au_branch *br;
1facf9fc 9911+
1308ab2a 9912+ DiMustWriteLock(dentry);
9913+
5afbbe0d
AM
9914+ dinfo = au_di(dentry);
9915+ hd = au_hdentry(dinfo, bindex);
4a4d8108 9916+ au_hdput(hd);
1facf9fc 9917+ hd->hd_dentry = h_dentry;
027c5e7a
AM
9918+ if (h_dentry) {
9919+ br = au_sbr(dentry->d_sb, bindex);
9920+ hd->hd_id = br->br_id;
9921+ }
9922+}
9923+
9924+int au_dbrange_test(struct dentry *dentry)
9925+{
9926+ int err;
5afbbe0d 9927+ aufs_bindex_t btop, bbot;
027c5e7a
AM
9928+
9929+ err = 0;
5afbbe0d
AM
9930+ btop = au_dbtop(dentry);
9931+ bbot = au_dbbot(dentry);
9932+ if (btop >= 0)
9933+ AuDebugOn(bbot < 0 && btop > bbot);
027c5e7a
AM
9934+ else {
9935+ err = -EIO;
5afbbe0d 9936+ AuDebugOn(bbot >= 0);
027c5e7a
AM
9937+ }
9938+
9939+ return err;
9940+}
9941+
9942+int au_digen_test(struct dentry *dentry, unsigned int sigen)
9943+{
9944+ int err;
9945+
9946+ err = 0;
9947+ if (unlikely(au_digen(dentry) != sigen
5527c038 9948+ || au_iigen_test(d_inode(dentry), sigen)))
027c5e7a
AM
9949+ err = -EIO;
9950+
9951+ return err;
1facf9fc 9952+}
9953+
9954+void au_update_digen(struct dentry *dentry)
9955+{
9956+ atomic_set(&au_di(dentry)->di_generation, au_sigen(dentry->d_sb));
9957+ /* smp_mb(); */ /* atomic_set */
9958+}
9959+
9960+void au_update_dbrange(struct dentry *dentry, int do_put_zero)
9961+{
9962+ struct au_dinfo *dinfo;
9963+ struct dentry *h_d;
4a4d8108 9964+ struct au_hdentry *hdp;
5afbbe0d 9965+ aufs_bindex_t bindex, bbot;
1facf9fc 9966+
1308ab2a 9967+ DiMustWriteLock(dentry);
9968+
1facf9fc 9969+ dinfo = au_di(dentry);
5afbbe0d 9970+ if (!dinfo || dinfo->di_btop < 0)
1facf9fc 9971+ return;
9972+
9973+ if (do_put_zero) {
5afbbe0d
AM
9974+ bbot = dinfo->di_bbot;
9975+ bindex = dinfo->di_btop;
9976+ hdp = au_hdentry(dinfo, bindex);
9977+ for (; bindex <= bbot; bindex++, hdp++) {
9978+ h_d = hdp->hd_dentry;
5527c038 9979+ if (h_d && d_is_negative(h_d))
1facf9fc 9980+ au_set_h_dptr(dentry, bindex, NULL);
9981+ }
9982+ }
9983+
5afbbe0d
AM
9984+ dinfo->di_btop = 0;
9985+ hdp = au_hdentry(dinfo, dinfo->di_btop);
9986+ for (; dinfo->di_btop <= dinfo->di_bbot; dinfo->di_btop++, hdp++)
9987+ if (hdp->hd_dentry)
1facf9fc 9988+ break;
5afbbe0d
AM
9989+ if (dinfo->di_btop > dinfo->di_bbot) {
9990+ dinfo->di_btop = -1;
9991+ dinfo->di_bbot = -1;
1facf9fc 9992+ return;
9993+ }
9994+
5afbbe0d
AM
9995+ hdp = au_hdentry(dinfo, dinfo->di_bbot);
9996+ for (; dinfo->di_bbot >= 0; dinfo->di_bbot--, hdp--)
9997+ if (hdp->hd_dentry)
1facf9fc 9998+ break;
5afbbe0d 9999+ AuDebugOn(dinfo->di_btop > dinfo->di_bbot || dinfo->di_bbot < 0);
1facf9fc 10000+}
10001+
5afbbe0d 10002+void au_update_dbtop(struct dentry *dentry)
1facf9fc 10003+{
5afbbe0d 10004+ aufs_bindex_t bindex, bbot;
1facf9fc 10005+ struct dentry *h_dentry;
10006+
5afbbe0d
AM
10007+ bbot = au_dbbot(dentry);
10008+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) {
1facf9fc 10009+ h_dentry = au_h_dptr(dentry, bindex);
10010+ if (!h_dentry)
10011+ continue;
5527c038 10012+ if (d_is_positive(h_dentry)) {
5afbbe0d 10013+ au_set_dbtop(dentry, bindex);
1facf9fc 10014+ return;
10015+ }
10016+ au_set_h_dptr(dentry, bindex, NULL);
10017+ }
10018+}
10019+
5afbbe0d 10020+void au_update_dbbot(struct dentry *dentry)
1facf9fc 10021+{
5afbbe0d 10022+ aufs_bindex_t bindex, btop;
1facf9fc 10023+ struct dentry *h_dentry;
10024+
5afbbe0d
AM
10025+ btop = au_dbtop(dentry);
10026+ for (bindex = au_dbbot(dentry); bindex >= btop; bindex--) {
1facf9fc 10027+ h_dentry = au_h_dptr(dentry, bindex);
10028+ if (!h_dentry)
10029+ continue;
5527c038 10030+ if (d_is_positive(h_dentry)) {
5afbbe0d 10031+ au_set_dbbot(dentry, bindex);
1facf9fc 10032+ return;
10033+ }
10034+ au_set_h_dptr(dentry, bindex, NULL);
10035+ }
10036+}
10037+
10038+int au_find_dbindex(struct dentry *dentry, struct dentry *h_dentry)
10039+{
5afbbe0d 10040+ aufs_bindex_t bindex, bbot;
1facf9fc 10041+
5afbbe0d
AM
10042+ bbot = au_dbbot(dentry);
10043+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++)
1facf9fc 10044+ if (au_h_dptr(dentry, bindex) == h_dentry)
10045+ return bindex;
10046+ return -1;
10047+}
7f207e10 10048diff -urN /usr/share/empty/fs/aufs/dir.c linux/fs/aufs/dir.c
eca34b5c 10049--- /usr/share/empty/fs/aufs/dir.c 1970-01-01 01:00:00.000000000 +0100
016522bc 10050+++ linux/fs/aufs/dir.c 2020-01-27 10:57:18.168871450 +0100
eca801bf 10051@@ -0,0 +1,763 @@
cd7a4cd9 10052+// SPDX-License-Identifier: GPL-2.0
1facf9fc 10053+/*
016522bc 10054+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 10055+ *
10056+ * This program, aufs is free software; you can redistribute it and/or modify
10057+ * it under the terms of the GNU General Public License as published by
10058+ * the Free Software Foundation; either version 2 of the License, or
10059+ * (at your option) any later version.
dece6358
AM
10060+ *
10061+ * This program is distributed in the hope that it will be useful,
10062+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10063+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10064+ * GNU General Public License for more details.
10065+ *
10066+ * You should have received a copy of the GNU General Public License
523b37e3 10067+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 10068+ */
10069+
10070+/*
10071+ * directory operations
10072+ */
10073+
10074+#include <linux/fs_stack.h>
eca801bf 10075+#include <linux/iversion.h>
1facf9fc 10076+#include "aufs.h"
10077+
10078+void au_add_nlink(struct inode *dir, struct inode *h_dir)
10079+{
9dbd164d
AM
10080+ unsigned int nlink;
10081+
1facf9fc 10082+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
10083+
9dbd164d
AM
10084+ nlink = dir->i_nlink;
10085+ nlink += h_dir->i_nlink - 2;
1facf9fc 10086+ if (h_dir->i_nlink < 2)
9dbd164d 10087+ nlink += 2;
f6b6e03d 10088+ smp_mb(); /* for i_nlink */
7eafdf33 10089+ /* 0 can happen in revaliding */
92d182d2 10090+ set_nlink(dir, nlink);
1facf9fc 10091+}
10092+
10093+void au_sub_nlink(struct inode *dir, struct inode *h_dir)
10094+{
9dbd164d
AM
10095+ unsigned int nlink;
10096+
1facf9fc 10097+ AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
10098+
9dbd164d
AM
10099+ nlink = dir->i_nlink;
10100+ nlink -= h_dir->i_nlink - 2;
1facf9fc 10101+ if (h_dir->i_nlink < 2)
9dbd164d 10102+ nlink -= 2;
f6b6e03d 10103+ smp_mb(); /* for i_nlink */
92d182d2 10104+ /* nlink == 0 means the branch-fs is broken */
9dbd164d 10105+ set_nlink(dir, nlink);
1facf9fc 10106+}
10107+
1308ab2a 10108+loff_t au_dir_size(struct file *file, struct dentry *dentry)
10109+{
10110+ loff_t sz;
5afbbe0d 10111+ aufs_bindex_t bindex, bbot;
1308ab2a 10112+ struct file *h_file;
10113+ struct dentry *h_dentry;
10114+
10115+ sz = 0;
10116+ if (file) {
2000de60 10117+ AuDebugOn(!d_is_dir(file->f_path.dentry));
1308ab2a 10118+
5afbbe0d
AM
10119+ bbot = au_fbbot_dir(file);
10120+ for (bindex = au_fbtop(file);
10121+ bindex <= bbot && sz < KMALLOC_MAX_SIZE;
1308ab2a 10122+ bindex++) {
4a4d8108 10123+ h_file = au_hf_dir(file, bindex);
c06a8ce3
AM
10124+ if (h_file && file_inode(h_file))
10125+ sz += vfsub_f_size_read(h_file);
1308ab2a 10126+ }
10127+ } else {
10128+ AuDebugOn(!dentry);
2000de60 10129+ AuDebugOn(!d_is_dir(dentry));
1308ab2a 10130+
5afbbe0d
AM
10131+ bbot = au_dbtaildir(dentry);
10132+ for (bindex = au_dbtop(dentry);
10133+ bindex <= bbot && sz < KMALLOC_MAX_SIZE;
1308ab2a 10134+ bindex++) {
10135+ h_dentry = au_h_dptr(dentry, bindex);
5527c038
JR
10136+ if (h_dentry && d_is_positive(h_dentry))
10137+ sz += i_size_read(d_inode(h_dentry));
1308ab2a 10138+ }
10139+ }
10140+ if (sz < KMALLOC_MAX_SIZE)
10141+ sz = roundup_pow_of_two(sz);
10142+ if (sz > KMALLOC_MAX_SIZE)
10143+ sz = KMALLOC_MAX_SIZE;
10144+ else if (sz < NAME_MAX) {
10145+ BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
10146+ sz = AUFS_RDBLK_DEF;
10147+ }
10148+ return sz;
10149+}
10150+
b912730e
AM
10151+struct au_dir_ts_arg {
10152+ struct dentry *dentry;
10153+ aufs_bindex_t brid;
10154+};
10155+
10156+static void au_do_dir_ts(void *arg)
10157+{
10158+ struct au_dir_ts_arg *a = arg;
10159+ struct au_dtime dt;
10160+ struct path h_path;
10161+ struct inode *dir, *h_dir;
10162+ struct super_block *sb;
10163+ struct au_branch *br;
10164+ struct au_hinode *hdir;
10165+ int err;
5afbbe0d 10166+ aufs_bindex_t btop, bindex;
b912730e
AM
10167+
10168+ sb = a->dentry->d_sb;
5527c038 10169+ if (d_really_is_negative(a->dentry))
b912730e 10170+ goto out;
5527c038 10171+ /* no dir->i_mutex lock */
b95c5147
AM
10172+ aufs_read_lock(a->dentry, AuLock_DW); /* noflush */
10173+
5527c038 10174+ dir = d_inode(a->dentry);
5afbbe0d 10175+ btop = au_ibtop(dir);
b912730e 10176+ bindex = au_br_index(sb, a->brid);
5afbbe0d 10177+ if (bindex < btop)
b912730e
AM
10178+ goto out_unlock;
10179+
10180+ br = au_sbr(sb, bindex);
10181+ h_path.dentry = au_h_dptr(a->dentry, bindex);
10182+ if (!h_path.dentry)
10183+ goto out_unlock;
10184+ h_path.mnt = au_br_mnt(br);
10185+ au_dtime_store(&dt, a->dentry, &h_path);
10186+
5afbbe0d 10187+ br = au_sbr(sb, btop);
b912730e
AM
10188+ if (!au_br_writable(br->br_perm))
10189+ goto out_unlock;
5afbbe0d 10190+ h_path.dentry = au_h_dptr(a->dentry, btop);
b912730e
AM
10191+ h_path.mnt = au_br_mnt(br);
10192+ err = vfsub_mnt_want_write(h_path.mnt);
10193+ if (err)
10194+ goto out_unlock;
5afbbe0d
AM
10195+ hdir = au_hi(dir, btop);
10196+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
10197+ h_dir = au_h_iptr(dir, btop);
b912730e 10198+ if (h_dir->i_nlink
cd7a4cd9 10199+ && timespec64_compare(&h_dir->i_mtime, &dt.dt_mtime) < 0) {
b912730e
AM
10200+ dt.dt_h_path = h_path;
10201+ au_dtime_revert(&dt);
10202+ }
5afbbe0d 10203+ au_hn_inode_unlock(hdir);
b912730e
AM
10204+ vfsub_mnt_drop_write(h_path.mnt);
10205+ au_cpup_attr_timesizes(dir);
10206+
10207+out_unlock:
10208+ aufs_read_unlock(a->dentry, AuLock_DW);
10209+out:
10210+ dput(a->dentry);
10211+ au_nwt_done(&au_sbi(sb)->si_nowait);
9f237c51 10212+ au_kfree_try_rcu(arg);
b912730e
AM
10213+}
10214+
10215+void au_dir_ts(struct inode *dir, aufs_bindex_t bindex)
10216+{
10217+ int perm, wkq_err;
5afbbe0d 10218+ aufs_bindex_t btop;
b912730e
AM
10219+ struct au_dir_ts_arg *arg;
10220+ struct dentry *dentry;
10221+ struct super_block *sb;
10222+
10223+ IMustLock(dir);
10224+
10225+ dentry = d_find_any_alias(dir);
10226+ AuDebugOn(!dentry);
10227+ sb = dentry->d_sb;
5afbbe0d
AM
10228+ btop = au_ibtop(dir);
10229+ if (btop == bindex) {
b912730e
AM
10230+ au_cpup_attr_timesizes(dir);
10231+ goto out;
10232+ }
10233+
5afbbe0d 10234+ perm = au_sbr_perm(sb, btop);
b912730e
AM
10235+ if (!au_br_writable(perm))
10236+ goto out;
10237+
10238+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
10239+ if (!arg)
10240+ goto out;
10241+
10242+ arg->dentry = dget(dentry); /* will be dput-ted by au_do_dir_ts() */
10243+ arg->brid = au_sbr_id(sb, bindex);
10244+ wkq_err = au_wkq_nowait(au_do_dir_ts, arg, sb, /*flags*/0);
10245+ if (unlikely(wkq_err)) {
10246+ pr_err("wkq %d\n", wkq_err);
10247+ dput(dentry);
9f237c51 10248+ au_kfree_try_rcu(arg);
b912730e
AM
10249+ }
10250+
10251+out:
10252+ dput(dentry);
10253+}
10254+
1facf9fc 10255+/* ---------------------------------------------------------------------- */
10256+
10257+static int reopen_dir(struct file *file)
10258+{
10259+ int err;
10260+ unsigned int flags;
5afbbe0d 10261+ aufs_bindex_t bindex, btail, btop;
1facf9fc 10262+ struct dentry *dentry, *h_dentry;
10263+ struct file *h_file;
10264+
10265+ /* open all lower dirs */
2000de60 10266+ dentry = file->f_path.dentry;
5afbbe0d
AM
10267+ btop = au_dbtop(dentry);
10268+ for (bindex = au_fbtop(file); bindex < btop; bindex++)
1facf9fc 10269+ au_set_h_fptr(file, bindex, NULL);
5afbbe0d 10270+ au_set_fbtop(file, btop);
1facf9fc 10271+
10272+ btail = au_dbtaildir(dentry);
5afbbe0d 10273+ for (bindex = au_fbbot_dir(file); btail < bindex; bindex--)
1facf9fc 10274+ au_set_h_fptr(file, bindex, NULL);
5afbbe0d 10275+ au_set_fbbot_dir(file, btail);
1facf9fc 10276+
4a4d8108 10277+ flags = vfsub_file_flags(file);
5afbbe0d 10278+ for (bindex = btop; bindex <= btail; bindex++) {
1facf9fc 10279+ h_dentry = au_h_dptr(dentry, bindex);
10280+ if (!h_dentry)
10281+ continue;
4a4d8108 10282+ h_file = au_hf_dir(file, bindex);
1facf9fc 10283+ if (h_file)
10284+ continue;
10285+
392086de 10286+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0);
1facf9fc 10287+ err = PTR_ERR(h_file);
10288+ if (IS_ERR(h_file))
10289+ goto out; /* close all? */
10290+ au_set_h_fptr(file, bindex, h_file);
10291+ }
10292+ au_update_figen(file);
10293+ /* todo: necessary? */
10294+ /* file->f_ra = h_file->f_ra; */
10295+ err = 0;
10296+
4f0767ce 10297+out:
1facf9fc 10298+ return err;
10299+}
10300+
b912730e 10301+static int do_open_dir(struct file *file, int flags, struct file *h_file)
1facf9fc 10302+{
10303+ int err;
10304+ aufs_bindex_t bindex, btail;
10305+ struct dentry *dentry, *h_dentry;
8cdd5066 10306+ struct vfsmount *mnt;
1facf9fc 10307+
1308ab2a 10308+ FiMustWriteLock(file);
b912730e 10309+ AuDebugOn(h_file);
1308ab2a 10310+
523b37e3 10311+ err = 0;
8cdd5066 10312+ mnt = file->f_path.mnt;
2000de60 10313+ dentry = file->f_path.dentry;
be118d29 10314+ file->f_version = inode_query_iversion(d_inode(dentry));
5afbbe0d
AM
10315+ bindex = au_dbtop(dentry);
10316+ au_set_fbtop(file, bindex);
1facf9fc 10317+ btail = au_dbtaildir(dentry);
5afbbe0d 10318+ au_set_fbbot_dir(file, btail);
1facf9fc 10319+ for (; !err && bindex <= btail; bindex++) {
10320+ h_dentry = au_h_dptr(dentry, bindex);
10321+ if (!h_dentry)
10322+ continue;
10323+
8cdd5066
JR
10324+ err = vfsub_test_mntns(mnt, h_dentry->d_sb);
10325+ if (unlikely(err))
10326+ break;
392086de 10327+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0);
1facf9fc 10328+ if (IS_ERR(h_file)) {
10329+ err = PTR_ERR(h_file);
10330+ break;
10331+ }
10332+ au_set_h_fptr(file, bindex, h_file);
10333+ }
10334+ au_update_figen(file);
10335+ /* todo: necessary? */
10336+ /* file->f_ra = h_file->f_ra; */
10337+ if (!err)
10338+ return 0; /* success */
10339+
10340+ /* close all */
5afbbe0d 10341+ for (bindex = au_fbtop(file); bindex <= btail; bindex++)
1facf9fc 10342+ au_set_h_fptr(file, bindex, NULL);
5afbbe0d
AM
10343+ au_set_fbtop(file, -1);
10344+ au_set_fbbot_dir(file, -1);
4a4d8108 10345+
1facf9fc 10346+ return err;
10347+}
10348+
10349+static int aufs_open_dir(struct inode *inode __maybe_unused,
10350+ struct file *file)
10351+{
4a4d8108
AM
10352+ int err;
10353+ struct super_block *sb;
10354+ struct au_fidir *fidir;
10355+
10356+ err = -ENOMEM;
2000de60 10357+ sb = file->f_path.dentry->d_sb;
4a4d8108 10358+ si_read_lock(sb, AuLock_FLUSH);
e49829fe 10359+ fidir = au_fidir_alloc(sb);
4a4d8108 10360+ if (fidir) {
b912730e
AM
10361+ struct au_do_open_args args = {
10362+ .open = do_open_dir,
10363+ .fidir = fidir
10364+ };
10365+ err = au_do_open(file, &args);
4a4d8108 10366+ if (unlikely(err))
9f237c51 10367+ au_kfree_rcu(fidir);
4a4d8108
AM
10368+ }
10369+ si_read_unlock(sb);
10370+ return err;
1facf9fc 10371+}
10372+
10373+static int aufs_release_dir(struct inode *inode __maybe_unused,
10374+ struct file *file)
10375+{
10376+ struct au_vdir *vdir_cache;
4a4d8108
AM
10377+ struct au_finfo *finfo;
10378+ struct au_fidir *fidir;
f0c0a007 10379+ struct au_hfile *hf;
5afbbe0d 10380+ aufs_bindex_t bindex, bbot;
1facf9fc 10381+
4a4d8108
AM
10382+ finfo = au_fi(file);
10383+ fidir = finfo->fi_hdir;
10384+ if (fidir) {
8b6a4947
AM
10385+ au_hbl_del(&finfo->fi_hlist,
10386+ &au_sbi(file->f_path.dentry->d_sb)->si_files);
4a4d8108
AM
10387+ vdir_cache = fidir->fd_vdir_cache; /* lock-free */
10388+ if (vdir_cache)
1c60b727 10389+ au_vdir_free(vdir_cache);
4a4d8108
AM
10390+
10391+ bindex = finfo->fi_btop;
10392+ if (bindex >= 0) {
f0c0a007 10393+ hf = fidir->fd_hfile + bindex;
4a4d8108
AM
10394+ /*
10395+ * calls fput() instead of filp_close(),
10396+ * since no dnotify or lock for the lower file.
10397+ */
5afbbe0d 10398+ bbot = fidir->fd_bbot;
f0c0a007
AM
10399+ for (; bindex <= bbot; bindex++, hf++)
10400+ if (hf->hf_file)
1c60b727 10401+ au_hfput(hf, /*execed*/0);
4a4d8108 10402+ }
9f237c51 10403+ au_kfree_rcu(fidir);
4a4d8108 10404+ finfo->fi_hdir = NULL;
1facf9fc 10405+ }
1c60b727 10406+ au_finfo_fin(file);
1facf9fc 10407+ return 0;
10408+}
10409+
10410+/* ---------------------------------------------------------------------- */
10411+
4a4d8108
AM
10412+static int au_do_flush_dir(struct file *file, fl_owner_t id)
10413+{
10414+ int err;
5afbbe0d 10415+ aufs_bindex_t bindex, bbot;
4a4d8108
AM
10416+ struct file *h_file;
10417+
10418+ err = 0;
5afbbe0d
AM
10419+ bbot = au_fbbot_dir(file);
10420+ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) {
4a4d8108
AM
10421+ h_file = au_hf_dir(file, bindex);
10422+ if (h_file)
10423+ err = vfsub_flush(h_file, id);
10424+ }
10425+ return err;
10426+}
10427+
10428+static int aufs_flush_dir(struct file *file, fl_owner_t id)
10429+{
10430+ return au_do_flush(file, id, au_do_flush_dir);
10431+}
10432+
10433+/* ---------------------------------------------------------------------- */
10434+
1facf9fc 10435+static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
10436+{
10437+ int err;
5afbbe0d 10438+ aufs_bindex_t bbot, bindex;
1facf9fc 10439+ struct inode *inode;
10440+ struct super_block *sb;
10441+
10442+ err = 0;
10443+ sb = dentry->d_sb;
5527c038 10444+ inode = d_inode(dentry);
1facf9fc 10445+ IMustLock(inode);
5afbbe0d
AM
10446+ bbot = au_dbbot(dentry);
10447+ for (bindex = au_dbtop(dentry); !err && bindex <= bbot; bindex++) {
1facf9fc 10448+ struct path h_path;
1facf9fc 10449+
10450+ if (au_test_ro(sb, bindex, inode))
10451+ continue;
10452+ h_path.dentry = au_h_dptr(dentry, bindex);
10453+ if (!h_path.dentry)
10454+ continue;
1facf9fc 10455+
1facf9fc 10456+ h_path.mnt = au_sbr_mnt(sb, bindex);
53392da6 10457+ err = vfsub_fsync(NULL, &h_path, datasync);
1facf9fc 10458+ }
10459+
10460+ return err;
10461+}
10462+
10463+static int au_do_fsync_dir(struct file *file, int datasync)
10464+{
10465+ int err;
5afbbe0d 10466+ aufs_bindex_t bbot, bindex;
1facf9fc 10467+ struct file *h_file;
10468+ struct super_block *sb;
10469+ struct inode *inode;
1facf9fc 10470+
521ced18 10471+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0);
1facf9fc 10472+ if (unlikely(err))
10473+ goto out;
10474+
c06a8ce3 10475+ inode = file_inode(file);
b912730e 10476+ sb = inode->i_sb;
5afbbe0d
AM
10477+ bbot = au_fbbot_dir(file);
10478+ for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) {
4a4d8108 10479+ h_file = au_hf_dir(file, bindex);
1facf9fc 10480+ if (!h_file || au_test_ro(sb, bindex, inode))
10481+ continue;
10482+
53392da6 10483+ err = vfsub_fsync(h_file, &h_file->f_path, datasync);
1facf9fc 10484+ }
10485+
4f0767ce 10486+out:
1facf9fc 10487+ return err;
10488+}
10489+
10490+/*
10491+ * @file may be NULL
10492+ */
1e00d052
AM
10493+static int aufs_fsync_dir(struct file *file, loff_t start, loff_t end,
10494+ int datasync)
1facf9fc 10495+{
10496+ int err;
b752ccd1 10497+ struct dentry *dentry;
5527c038 10498+ struct inode *inode;
1facf9fc 10499+ struct super_block *sb;
1facf9fc 10500+
10501+ err = 0;
2000de60 10502+ dentry = file->f_path.dentry;
5527c038 10503+ inode = d_inode(dentry);
febd17d6 10504+ inode_lock(inode);
1facf9fc 10505+ sb = dentry->d_sb;
10506+ si_noflush_read_lock(sb);
10507+ if (file)
10508+ err = au_do_fsync_dir(file, datasync);
10509+ else {
10510+ di_write_lock_child(dentry);
10511+ err = au_do_fsync_dir_no_file(dentry, datasync);
10512+ }
5527c038 10513+ au_cpup_attr_timesizes(inode);
1facf9fc 10514+ di_write_unlock(dentry);
10515+ if (file)
10516+ fi_write_unlock(file);
10517+
10518+ si_read_unlock(sb);
febd17d6 10519+ inode_unlock(inode);
1facf9fc 10520+ return err;
10521+}
10522+
10523+/* ---------------------------------------------------------------------- */
10524+
5afbbe0d 10525+static int aufs_iterate_shared(struct file *file, struct dir_context *ctx)
1facf9fc 10526+{
10527+ int err;
10528+ struct dentry *dentry;
9dbd164d 10529+ struct inode *inode, *h_inode;
1facf9fc 10530+ struct super_block *sb;
10531+
062440b3 10532+ AuDbg("%pD, ctx{%ps, %llu}\n", file, ctx->actor, ctx->pos);
392086de 10533+
2000de60 10534+ dentry = file->f_path.dentry;
5527c038 10535+ inode = d_inode(dentry);
1facf9fc 10536+ IMustLock(inode);
10537+
10538+ sb = dentry->d_sb;
10539+ si_read_lock(sb, AuLock_FLUSH);
521ced18 10540+ err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0);
1facf9fc 10541+ if (unlikely(err))
10542+ goto out;
027c5e7a
AM
10543+ err = au_alive_dir(dentry);
10544+ if (!err)
10545+ err = au_vdir_init(file);
1facf9fc 10546+ di_downgrade_lock(dentry, AuLock_IR);
10547+ if (unlikely(err))
10548+ goto out_unlock;
10549+
5afbbe0d 10550+ h_inode = au_h_iptr(inode, au_ibtop(inode));
b752ccd1 10551+ if (!au_test_nfsd()) {
392086de 10552+ err = au_vdir_fill_de(file, ctx);
9dbd164d 10553+ fsstack_copy_attr_atime(inode, h_inode);
1facf9fc 10554+ } else {
10555+ /*
10556+ * nfsd filldir may call lookup_one_len(), vfs_getattr(),
10557+ * encode_fh() and others.
10558+ */
9dbd164d 10559+ atomic_inc(&h_inode->i_count);
1facf9fc 10560+ di_read_unlock(dentry, AuLock_IR);
10561+ si_read_unlock(sb);
392086de 10562+ err = au_vdir_fill_de(file, ctx);
1facf9fc 10563+ fsstack_copy_attr_atime(inode, h_inode);
10564+ fi_write_unlock(file);
9dbd164d 10565+ iput(h_inode);
1facf9fc 10566+
10567+ AuTraceErr(err);
10568+ return err;
10569+ }
10570+
4f0767ce 10571+out_unlock:
1facf9fc 10572+ di_read_unlock(dentry, AuLock_IR);
10573+ fi_write_unlock(file);
4f0767ce 10574+out:
1facf9fc 10575+ si_read_unlock(sb);
10576+ return err;
10577+}
10578+
10579+/* ---------------------------------------------------------------------- */
10580+
10581+#define AuTestEmpty_WHONLY 1
dece6358
AM
10582+#define AuTestEmpty_CALLED (1 << 1)
10583+#define AuTestEmpty_SHWH (1 << 2)
1facf9fc 10584+#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
7f207e10
AM
10585+#define au_fset_testempty(flags, name) \
10586+ do { (flags) |= AuTestEmpty_##name; } while (0)
10587+#define au_fclr_testempty(flags, name) \
10588+ do { (flags) &= ~AuTestEmpty_##name; } while (0)
1facf9fc 10589+
dece6358
AM
10590+#ifndef CONFIG_AUFS_SHWH
10591+#undef AuTestEmpty_SHWH
10592+#define AuTestEmpty_SHWH 0
10593+#endif
10594+
1facf9fc 10595+struct test_empty_arg {
392086de 10596+ struct dir_context ctx;
1308ab2a 10597+ struct au_nhash *whlist;
1facf9fc 10598+ unsigned int flags;
10599+ int err;
10600+ aufs_bindex_t bindex;
10601+};
10602+
392086de
AM
10603+static int test_empty_cb(struct dir_context *ctx, const char *__name,
10604+ int namelen, loff_t offset __maybe_unused, u64 ino,
dece6358 10605+ unsigned int d_type)
1facf9fc 10606+{
392086de
AM
10607+ struct test_empty_arg *arg = container_of(ctx, struct test_empty_arg,
10608+ ctx);
1facf9fc 10609+ char *name = (void *)__name;
10610+
10611+ arg->err = 0;
10612+ au_fset_testempty(arg->flags, CALLED);
10613+ /* smp_mb(); */
10614+ if (name[0] == '.'
10615+ && (namelen == 1 || (name[1] == '.' && namelen == 2)))
10616+ goto out; /* success */
10617+
10618+ if (namelen <= AUFS_WH_PFX_LEN
10619+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
10620+ if (au_ftest_testempty(arg->flags, WHONLY)
1308ab2a 10621+ && !au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 10622+ arg->err = -ENOTEMPTY;
10623+ goto out;
10624+ }
10625+
10626+ name += AUFS_WH_PFX_LEN;
10627+ namelen -= AUFS_WH_PFX_LEN;
1308ab2a 10628+ if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
1facf9fc 10629+ arg->err = au_nhash_append_wh
1308ab2a 10630+ (arg->whlist, name, namelen, ino, d_type, arg->bindex,
dece6358 10631+ au_ftest_testempty(arg->flags, SHWH));
1facf9fc 10632+
4f0767ce 10633+out:
1facf9fc 10634+ /* smp_mb(); */
10635+ AuTraceErr(arg->err);
10636+ return arg->err;
10637+}
10638+
10639+static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
10640+{
10641+ int err;
10642+ struct file *h_file;
acd2b654 10643+ struct au_branch *br;
1facf9fc 10644+
10645+ h_file = au_h_open(dentry, arg->bindex,
10646+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
392086de 10647+ /*file*/NULL, /*force_wr*/0);
1facf9fc 10648+ err = PTR_ERR(h_file);
10649+ if (IS_ERR(h_file))
10650+ goto out;
10651+
10652+ err = 0;
10653+ if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
c06a8ce3 10654+ && !file_inode(h_file)->i_nlink)
1facf9fc 10655+ goto out_put;
10656+
10657+ do {
10658+ arg->err = 0;
10659+ au_fclr_testempty(arg->flags, CALLED);
10660+ /* smp_mb(); */
392086de 10661+ err = vfsub_iterate_dir(h_file, &arg->ctx);
1facf9fc 10662+ if (err >= 0)
10663+ err = arg->err;
10664+ } while (!err && au_ftest_testempty(arg->flags, CALLED));
10665+
4f0767ce 10666+out_put:
1facf9fc 10667+ fput(h_file);
acd2b654
AM
10668+ br = au_sbr(dentry->d_sb, arg->bindex);
10669+ au_lcnt_dec(&br->br_nfiles);
4f0767ce 10670+out:
1facf9fc 10671+ return err;
10672+}
10673+
10674+struct do_test_empty_args {
10675+ int *errp;
10676+ struct dentry *dentry;
10677+ struct test_empty_arg *arg;
10678+};
10679+
10680+static void call_do_test_empty(void *args)
10681+{
10682+ struct do_test_empty_args *a = args;
10683+ *a->errp = do_test_empty(a->dentry, a->arg);
10684+}
10685+
10686+static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
10687+{
10688+ int err, wkq_err;
10689+ struct dentry *h_dentry;
10690+ struct inode *h_inode;
10691+
10692+ h_dentry = au_h_dptr(dentry, arg->bindex);
5527c038 10693+ h_inode = d_inode(h_dentry);
53392da6 10694+ /* todo: i_mode changes anytime? */
be118d29 10695+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD);
1facf9fc 10696+ err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
3c1bdaff 10697+ inode_unlock_shared(h_inode);
1facf9fc 10698+ if (!err)
10699+ err = do_test_empty(dentry, arg);
10700+ else {
10701+ struct do_test_empty_args args = {
10702+ .errp = &err,
10703+ .dentry = dentry,
10704+ .arg = arg
10705+ };
10706+ unsigned int flags = arg->flags;
10707+
10708+ wkq_err = au_wkq_wait(call_do_test_empty, &args);
10709+ if (unlikely(wkq_err))
10710+ err = wkq_err;
10711+ arg->flags = flags;
10712+ }
10713+
10714+ return err;
10715+}
10716+
10717+int au_test_empty_lower(struct dentry *dentry)
10718+{
10719+ int err;
1308ab2a 10720+ unsigned int rdhash;
5afbbe0d 10721+ aufs_bindex_t bindex, btop, btail;
1308ab2a 10722+ struct au_nhash whlist;
392086de
AM
10723+ struct test_empty_arg arg = {
10724+ .ctx = {
2000de60 10725+ .actor = test_empty_cb
392086de
AM
10726+ }
10727+ };
076b876e 10728+ int (*test_empty)(struct dentry *dentry, struct test_empty_arg *arg);
1facf9fc 10729+
dece6358
AM
10730+ SiMustAnyLock(dentry->d_sb);
10731+
1308ab2a 10732+ rdhash = au_sbi(dentry->d_sb)->si_rdhash;
10733+ if (!rdhash)
10734+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
10735+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
dece6358 10736+ if (unlikely(err))
1facf9fc 10737+ goto out;
10738+
1facf9fc 10739+ arg.flags = 0;
1308ab2a 10740+ arg.whlist = &whlist;
5afbbe0d 10741+ btop = au_dbtop(dentry);
dece6358
AM
10742+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
10743+ au_fset_testempty(arg.flags, SHWH);
076b876e
AM
10744+ test_empty = do_test_empty;
10745+ if (au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1))
10746+ test_empty = sio_test_empty;
5afbbe0d 10747+ arg.bindex = btop;
076b876e 10748+ err = test_empty(dentry, &arg);
1facf9fc 10749+ if (unlikely(err))
10750+ goto out_whlist;
10751+
10752+ au_fset_testempty(arg.flags, WHONLY);
10753+ btail = au_dbtaildir(dentry);
5afbbe0d 10754+ for (bindex = btop + 1; !err && bindex <= btail; bindex++) {
1facf9fc 10755+ struct dentry *h_dentry;
10756+
10757+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 10758+ if (h_dentry && d_is_positive(h_dentry)) {
1facf9fc 10759+ arg.bindex = bindex;
076b876e 10760+ err = test_empty(dentry, &arg);
1facf9fc 10761+ }
10762+ }
10763+
4f0767ce 10764+out_whlist:
1308ab2a 10765+ au_nhash_wh_free(&whlist);
4f0767ce 10766+out:
1facf9fc 10767+ return err;
10768+}
10769+
10770+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
10771+{
10772+ int err;
392086de
AM
10773+ struct test_empty_arg arg = {
10774+ .ctx = {
2000de60 10775+ .actor = test_empty_cb
392086de
AM
10776+ }
10777+ };
1facf9fc 10778+ aufs_bindex_t bindex, btail;
10779+
10780+ err = 0;
1308ab2a 10781+ arg.whlist = whlist;
1facf9fc 10782+ arg.flags = AuTestEmpty_WHONLY;
dece6358
AM
10783+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
10784+ au_fset_testempty(arg.flags, SHWH);
1facf9fc 10785+ btail = au_dbtaildir(dentry);
5afbbe0d 10786+ for (bindex = au_dbtop(dentry); !err && bindex <= btail; bindex++) {
1facf9fc 10787+ struct dentry *h_dentry;
10788+
10789+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 10790+ if (h_dentry && d_is_positive(h_dentry)) {
1facf9fc 10791+ arg.bindex = bindex;
10792+ err = sio_test_empty(dentry, &arg);
10793+ }
10794+ }
10795+
10796+ return err;
10797+}
10798+
10799+/* ---------------------------------------------------------------------- */
10800+
10801+const struct file_operations aufs_dir_fop = {
4a4d8108 10802+ .owner = THIS_MODULE,
027c5e7a 10803+ .llseek = default_llseek,
1facf9fc 10804+ .read = generic_read_dir,
5afbbe0d 10805+ .iterate_shared = aufs_iterate_shared,
1facf9fc 10806+ .unlocked_ioctl = aufs_ioctl_dir,
b752ccd1
AM
10807+#ifdef CONFIG_COMPAT
10808+ .compat_ioctl = aufs_compat_ioctl_dir,
10809+#endif
1facf9fc 10810+ .open = aufs_open_dir,
10811+ .release = aufs_release_dir,
4a4d8108 10812+ .flush = aufs_flush_dir,
1facf9fc 10813+ .fsync = aufs_fsync_dir
10814+};
7f207e10 10815diff -urN /usr/share/empty/fs/aufs/dir.h linux/fs/aufs/dir.h
eca34b5c 10816--- /usr/share/empty/fs/aufs/dir.h 1970-01-01 01:00:00.000000000 +0100
016522bc 10817+++ linux/fs/aufs/dir.h 2020-01-27 10:57:18.168871450 +0100
9f237c51 10818@@ -0,0 +1,134 @@
062440b3 10819+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 10820+/*
016522bc 10821+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 10822+ *
10823+ * This program, aufs is free software; you can redistribute it and/or modify
10824+ * it under the terms of the GNU General Public License as published by
10825+ * the Free Software Foundation; either version 2 of the License, or
10826+ * (at your option) any later version.
dece6358
AM
10827+ *
10828+ * This program is distributed in the hope that it will be useful,
10829+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10830+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10831+ * GNU General Public License for more details.
10832+ *
10833+ * You should have received a copy of the GNU General Public License
523b37e3 10834+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 10835+ */
10836+
10837+/*
10838+ * directory operations
10839+ */
10840+
10841+#ifndef __AUFS_DIR_H__
10842+#define __AUFS_DIR_H__
10843+
10844+#ifdef __KERNEL__
10845+
10846+#include <linux/fs.h>
1facf9fc 10847+
10848+/* ---------------------------------------------------------------------- */
10849+
10850+/* need to be faster and smaller */
10851+
10852+struct au_nhash {
dece6358
AM
10853+ unsigned int nh_num;
10854+ struct hlist_head *nh_head;
1facf9fc 10855+};
10856+
10857+struct au_vdir_destr {
10858+ unsigned char len;
10859+ unsigned char name[0];
10860+} __packed;
10861+
10862+struct au_vdir_dehstr {
10863+ struct hlist_node hash;
1c60b727 10864+ struct au_vdir_destr *str;
9f237c51 10865+ struct rcu_head rcu;
4a4d8108 10866+} ____cacheline_aligned_in_smp;
1facf9fc 10867+
10868+struct au_vdir_de {
10869+ ino_t de_ino;
10870+ unsigned char de_type;
10871+ /* caution: packed */
10872+ struct au_vdir_destr de_str;
10873+} __packed;
10874+
10875+struct au_vdir_wh {
10876+ struct hlist_node wh_hash;
dece6358
AM
10877+#ifdef CONFIG_AUFS_SHWH
10878+ ino_t wh_ino;
1facf9fc 10879+ aufs_bindex_t wh_bindex;
dece6358
AM
10880+ unsigned char wh_type;
10881+#else
10882+ aufs_bindex_t wh_bindex;
10883+#endif
10884+ /* caution: packed */
1facf9fc 10885+ struct au_vdir_destr wh_str;
10886+} __packed;
10887+
10888+union au_vdir_deblk_p {
10889+ unsigned char *deblk;
10890+ struct au_vdir_de *de;
10891+};
10892+
10893+struct au_vdir {
10894+ unsigned char **vd_deblk;
10895+ unsigned long vd_nblk;
1facf9fc 10896+ struct {
10897+ unsigned long ul;
10898+ union au_vdir_deblk_p p;
10899+ } vd_last;
10900+
be118d29 10901+ u64 vd_version;
dece6358 10902+ unsigned int vd_deblk_sz;
9f237c51
AM
10903+ unsigned long vd_jiffy;
10904+ struct rcu_head rcu;
4a4d8108 10905+} ____cacheline_aligned_in_smp;
1facf9fc 10906+
10907+/* ---------------------------------------------------------------------- */
10908+
10909+/* dir.c */
10910+extern const struct file_operations aufs_dir_fop;
10911+void au_add_nlink(struct inode *dir, struct inode *h_dir);
10912+void au_sub_nlink(struct inode *dir, struct inode *h_dir);
1308ab2a 10913+loff_t au_dir_size(struct file *file, struct dentry *dentry);
b912730e 10914+void au_dir_ts(struct inode *dir, aufs_bindex_t bsrc);
1facf9fc 10915+int au_test_empty_lower(struct dentry *dentry);
10916+int au_test_empty(struct dentry *dentry, struct au_nhash *whlist);
10917+
10918+/* vdir.c */
1308ab2a 10919+unsigned int au_rdhash_est(loff_t sz);
dece6358
AM
10920+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp);
10921+void au_nhash_wh_free(struct au_nhash *whlist);
1facf9fc 10922+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
10923+ int limit);
dece6358
AM
10924+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen);
10925+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
10926+ unsigned int d_type, aufs_bindex_t bindex,
10927+ unsigned char shwh);
1c60b727 10928+void au_vdir_free(struct au_vdir *vdir);
1facf9fc 10929+int au_vdir_init(struct file *file);
392086de 10930+int au_vdir_fill_de(struct file *file, struct dir_context *ctx);
1facf9fc 10931+
10932+/* ioctl.c */
10933+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg);
10934+
1308ab2a 10935+#ifdef CONFIG_AUFS_RDU
10936+/* rdu.c */
10937+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
10938+#ifdef CONFIG_COMPAT
10939+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd,
10940+ unsigned long arg);
10941+#endif
1308ab2a 10942+#else
c1595e42
JR
10943+AuStub(long, au_rdu_ioctl, return -EINVAL, struct file *file,
10944+ unsigned int cmd, unsigned long arg)
b752ccd1 10945+#ifdef CONFIG_COMPAT
c1595e42
JR
10946+AuStub(long, au_rdu_compat_ioctl, return -EINVAL, struct file *file,
10947+ unsigned int cmd, unsigned long arg)
b752ccd1 10948+#endif
1308ab2a 10949+#endif
10950+
1facf9fc 10951+#endif /* __KERNEL__ */
10952+#endif /* __AUFS_DIR_H__ */
8b6a4947 10953diff -urN /usr/share/empty/fs/aufs/dirren.c linux/fs/aufs/dirren.c
eca34b5c 10954--- /usr/share/empty/fs/aufs/dirren.c 1970-01-01 01:00:00.000000000 +0100
016522bc 10955+++ linux/fs/aufs/dirren.c 2020-01-27 10:57:18.168871450 +0100
062440b3 10956@@ -0,0 +1,1316 @@
cd7a4cd9 10957+// SPDX-License-Identifier: GPL-2.0
8b6a4947 10958+/*
016522bc 10959+ * Copyright (C) 2017-2020 Junjiro R. Okajima
8b6a4947
AM
10960+ *
10961+ * This program, aufs is free software; you can redistribute it and/or modify
10962+ * it under the terms of the GNU General Public License as published by
10963+ * the Free Software Foundation; either version 2 of the License, or
10964+ * (at your option) any later version.
10965+ *
10966+ * This program is distributed in the hope that it will be useful,
10967+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10968+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10969+ * GNU General Public License for more details.
10970+ *
10971+ * You should have received a copy of the GNU General Public License
10972+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
10973+ */
10974+
10975+/*
acd2b654 10976+ * special handling in renaming a directory
8b6a4947
AM
10977+ * in order to support looking-up the before-renamed name on the lower readonly
10978+ * branches
10979+ */
10980+
10981+#include <linux/byteorder/generic.h>
10982+#include "aufs.h"
10983+
10984+static void au_dr_hino_del(struct au_dr_br *dr, struct au_dr_hino *ent)
10985+{
10986+ int idx;
10987+
10988+ idx = au_dr_ihash(ent->dr_h_ino);
10989+ au_hbl_del(&ent->dr_hnode, dr->dr_h_ino + idx);
10990+}
10991+
10992+static int au_dr_hino_test_empty(struct au_dr_br *dr)
10993+{
10994+ int ret, i;
10995+ struct hlist_bl_head *hbl;
10996+
10997+ ret = 1;
10998+ for (i = 0; ret && i < AuDirren_NHASH; i++) {
10999+ hbl = dr->dr_h_ino + i;
11000+ hlist_bl_lock(hbl);
11001+ ret &= hlist_bl_empty(hbl);
11002+ hlist_bl_unlock(hbl);
11003+ }
11004+
11005+ return ret;
11006+}
11007+
11008+static struct au_dr_hino *au_dr_hino_find(struct au_dr_br *dr, ino_t ino)
11009+{
11010+ struct au_dr_hino *found, *ent;
11011+ struct hlist_bl_head *hbl;
11012+ struct hlist_bl_node *pos;
11013+ int idx;
11014+
11015+ found = NULL;
11016+ idx = au_dr_ihash(ino);
11017+ hbl = dr->dr_h_ino + idx;
11018+ hlist_bl_lock(hbl);
11019+ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode)
11020+ if (ent->dr_h_ino == ino) {
11021+ found = ent;
11022+ break;
11023+ }
11024+ hlist_bl_unlock(hbl);
11025+
11026+ return found;
11027+}
11028+
11029+int au_dr_hino_test_add(struct au_dr_br *dr, ino_t ino,
11030+ struct au_dr_hino *add_ent)
11031+{
11032+ int found, idx;
11033+ struct hlist_bl_head *hbl;
11034+ struct hlist_bl_node *pos;
11035+ struct au_dr_hino *ent;
11036+
11037+ found = 0;
11038+ idx = au_dr_ihash(ino);
11039+ hbl = dr->dr_h_ino + idx;
43982f53 11040+#if 0 /* debug print */
8b6a4947
AM
11041+ {
11042+ struct hlist_bl_node *tmp;
11043+
11044+ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode)
11045+ AuDbg("hi%llu\n", (unsigned long long)ent->dr_h_ino);
11046+ }
11047+#endif
11048+ hlist_bl_lock(hbl);
11049+ hlist_bl_for_each_entry(ent, pos, hbl, dr_hnode)
11050+ if (ent->dr_h_ino == ino) {
11051+ found = 1;
11052+ break;
11053+ }
11054+ if (!found && add_ent)
11055+ hlist_bl_add_head(&add_ent->dr_hnode, hbl);
11056+ hlist_bl_unlock(hbl);
11057+
11058+ if (!found && add_ent)
11059+ AuDbg("i%llu added\n", (unsigned long long)add_ent->dr_h_ino);
11060+
11061+ return found;
11062+}
11063+
11064+void au_dr_hino_free(struct au_dr_br *dr)
11065+{
11066+ int i;
11067+ struct hlist_bl_head *hbl;
11068+ struct hlist_bl_node *pos, *tmp;
11069+ struct au_dr_hino *ent;
11070+
11071+ /* SiMustWriteLock(sb); */
11072+
11073+ for (i = 0; i < AuDirren_NHASH; i++) {
11074+ hbl = dr->dr_h_ino + i;
11075+ /* no spinlock since sbinfo must be write-locked */
11076+ hlist_bl_for_each_entry_safe(ent, pos, tmp, hbl, dr_hnode)
9f237c51 11077+ au_kfree_rcu(ent);
8b6a4947
AM
11078+ INIT_HLIST_BL_HEAD(hbl);
11079+ }
11080+}
11081+
11082+/* returns the number of inodes or an error */
11083+static int au_dr_hino_store(struct super_block *sb, struct au_branch *br,
11084+ struct file *hinofile)
11085+{
11086+ int err, i;
11087+ ssize_t ssz;
11088+ loff_t pos, oldsize;
11089+ __be64 u64;
11090+ struct inode *hinoinode;
11091+ struct hlist_bl_head *hbl;
11092+ struct hlist_bl_node *n1, *n2;
11093+ struct au_dr_hino *ent;
11094+
11095+ SiMustWriteLock(sb);
11096+ AuDebugOn(!au_br_writable(br->br_perm));
11097+
11098+ hinoinode = file_inode(hinofile);
11099+ oldsize = i_size_read(hinoinode);
11100+
11101+ err = 0;
11102+ pos = 0;
11103+ hbl = br->br_dirren.dr_h_ino;
11104+ for (i = 0; !err && i < AuDirren_NHASH; i++, hbl++) {
11105+ /* no bit-lock since sbinfo must be write-locked */
11106+ hlist_bl_for_each_entry_safe(ent, n1, n2, hbl, dr_hnode) {
11107+ AuDbg("hi%llu, %pD2\n",
11108+ (unsigned long long)ent->dr_h_ino, hinofile);
11109+ u64 = cpu_to_be64(ent->dr_h_ino);
11110+ ssz = vfsub_write_k(hinofile, &u64, sizeof(u64), &pos);
11111+ if (ssz == sizeof(u64))
11112+ continue;
11113+
11114+ /* write error */
11115+ pr_err("ssz %zd, %pD2\n", ssz, hinofile);
11116+ err = -ENOSPC;
11117+ if (ssz < 0)
11118+ err = ssz;
11119+ break;
11120+ }
11121+ }
11122+ /* regardless the error */
11123+ if (pos < oldsize) {
11124+ err = vfsub_trunc(&hinofile->f_path, pos, /*attr*/0, hinofile);
11125+ AuTraceErr(err);
11126+ }
11127+
11128+ AuTraceErr(err);
11129+ return err;
11130+}
11131+
11132+static int au_dr_hino_load(struct au_dr_br *dr, struct file *hinofile)
11133+{
11134+ int err, hidx;
11135+ ssize_t ssz;
11136+ size_t sz, n;
11137+ loff_t pos;
11138+ uint64_t u64;
11139+ struct au_dr_hino *ent;
11140+ struct inode *hinoinode;
11141+ struct hlist_bl_head *hbl;
11142+
11143+ err = 0;
11144+ pos = 0;
11145+ hbl = dr->dr_h_ino;
11146+ hinoinode = file_inode(hinofile);
11147+ sz = i_size_read(hinoinode);
11148+ AuDebugOn(sz % sizeof(u64));
11149+ n = sz / sizeof(u64);
11150+ while (n--) {
11151+ ssz = vfsub_read_k(hinofile, &u64, sizeof(u64), &pos);
11152+ if (unlikely(ssz != sizeof(u64))) {
11153+ pr_err("ssz %zd, %pD2\n", ssz, hinofile);
11154+ err = -EINVAL;
11155+ if (ssz < 0)
11156+ err = ssz;
11157+ goto out_free;
11158+ }
11159+
11160+ ent = kmalloc(sizeof(*ent), GFP_NOFS);
11161+ if (!ent) {
11162+ err = -ENOMEM;
11163+ AuTraceErr(err);
11164+ goto out_free;
11165+ }
11166+ ent->dr_h_ino = be64_to_cpu((__force __be64)u64);
11167+ AuDbg("hi%llu, %pD2\n",
11168+ (unsigned long long)ent->dr_h_ino, hinofile);
11169+ hidx = au_dr_ihash(ent->dr_h_ino);
11170+ au_hbl_add(&ent->dr_hnode, hbl + hidx);
11171+ }
11172+ goto out; /* success */
11173+
11174+out_free:
11175+ au_dr_hino_free(dr);
11176+out:
11177+ AuTraceErr(err);
11178+ return err;
11179+}
11180+
11181+/*
11182+ * @bindex/@br is a switch to distinguish whether suspending hnotify or not.
11183+ * @path is a switch to distinguish load and store.
11184+ */
11185+static int au_dr_hino(struct super_block *sb, aufs_bindex_t bindex,
11186+ struct au_branch *br, const struct path *path)
11187+{
11188+ int err, flags;
11189+ unsigned char load, suspend;
11190+ struct file *hinofile;
11191+ struct au_hinode *hdir;
11192+ struct inode *dir, *delegated;
11193+ struct path hinopath;
11194+ struct qstr hinoname = QSTR_INIT(AUFS_WH_DR_BRHINO,
11195+ sizeof(AUFS_WH_DR_BRHINO) - 1);
11196+
11197+ AuDebugOn(bindex < 0 && !br);
11198+ AuDebugOn(bindex >= 0 && br);
11199+
11200+ err = -EINVAL;
11201+ suspend = !br;
11202+ if (suspend)
11203+ br = au_sbr(sb, bindex);
11204+ load = !!path;
11205+ if (!load) {
11206+ path = &br->br_path;
11207+ AuDebugOn(!au_br_writable(br->br_perm));
11208+ if (unlikely(!au_br_writable(br->br_perm)))
11209+ goto out;
11210+ }
11211+
11212+ hdir = NULL;
11213+ if (suspend) {
11214+ dir = d_inode(sb->s_root);
11215+ hdir = au_hinode(au_ii(dir), bindex);
11216+ dir = hdir->hi_inode;
11217+ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD);
11218+ } else {
11219+ dir = d_inode(path->dentry);
11220+ inode_lock_nested(dir, AuLsc_I_CHILD);
11221+ }
11222+ hinopath.dentry = vfsub_lkup_one(&hinoname, path->dentry);
11223+ err = PTR_ERR(hinopath.dentry);
11224+ if (IS_ERR(hinopath.dentry))
11225+ goto out_unlock;
11226+
11227+ err = 0;
11228+ flags = O_RDONLY;
11229+ if (load) {
11230+ if (d_is_negative(hinopath.dentry))
11231+ goto out_dput; /* success */
11232+ } else {
11233+ if (au_dr_hino_test_empty(&br->br_dirren)) {
11234+ if (d_is_positive(hinopath.dentry)) {
11235+ delegated = NULL;
11236+ err = vfsub_unlink(dir, &hinopath, &delegated,
11237+ /*force*/0);
11238+ AuTraceErr(err);
11239+ if (unlikely(err))
11240+ pr_err("ignored err %d, %pd2\n",
11241+ err, hinopath.dentry);
11242+ if (unlikely(err == -EWOULDBLOCK))
11243+ iput(delegated);
11244+ err = 0;
11245+ }
11246+ goto out_dput;
11247+ } else if (!d_is_positive(hinopath.dentry)) {
11248+ err = vfsub_create(dir, &hinopath, 0600,
11249+ /*want_excl*/false);
11250+ AuTraceErr(err);
11251+ if (unlikely(err))
11252+ goto out_dput;
11253+ }
11254+ flags = O_WRONLY;
11255+ }
11256+ hinopath.mnt = path->mnt;
11257+ hinofile = vfsub_dentry_open(&hinopath, flags);
11258+ if (suspend)
11259+ au_hn_inode_unlock(hdir);
11260+ else
11261+ inode_unlock(dir);
11262+ dput(hinopath.dentry);
11263+ AuTraceErrPtr(hinofile);
11264+ if (IS_ERR(hinofile)) {
11265+ err = PTR_ERR(hinofile);
11266+ goto out;
11267+ }
11268+
11269+ if (load)
11270+ err = au_dr_hino_load(&br->br_dirren, hinofile);
11271+ else
11272+ err = au_dr_hino_store(sb, br, hinofile);
11273+ fput(hinofile);
11274+ goto out;
11275+
11276+out_dput:
11277+ dput(hinopath.dentry);
11278+out_unlock:
11279+ if (suspend)
11280+ au_hn_inode_unlock(hdir);
11281+ else
11282+ inode_unlock(dir);
11283+out:
11284+ AuTraceErr(err);
11285+ return err;
11286+}
11287+
11288+/* ---------------------------------------------------------------------- */
11289+
11290+static int au_dr_brid_init(struct au_dr_brid *brid, const struct path *path)
11291+{
11292+ int err;
11293+ struct kstatfs kstfs;
11294+ dev_t dev;
11295+ struct dentry *dentry;
11296+ struct super_block *sb;
11297+
11298+ err = vfs_statfs((void *)path, &kstfs);
11299+ AuTraceErr(err);
11300+ if (unlikely(err))
11301+ goto out;
11302+
11303+ /* todo: support for UUID */
11304+
11305+ if (kstfs.f_fsid.val[0] || kstfs.f_fsid.val[1]) {
11306+ brid->type = AuBrid_FSID;
11307+ brid->fsid = kstfs.f_fsid;
11308+ } else {
11309+ dentry = path->dentry;
11310+ sb = dentry->d_sb;
11311+ dev = sb->s_dev;
11312+ if (dev) {
11313+ brid->type = AuBrid_DEV;
11314+ brid->dev = dev;
11315+ }
11316+ }
11317+
11318+out:
11319+ return err;
11320+}
11321+
11322+int au_dr_br_init(struct super_block *sb, struct au_branch *br,
11323+ const struct path *path)
11324+{
11325+ int err, i;
11326+ struct au_dr_br *dr;
11327+ struct hlist_bl_head *hbl;
11328+
11329+ dr = &br->br_dirren;
11330+ hbl = dr->dr_h_ino;
11331+ for (i = 0; i < AuDirren_NHASH; i++, hbl++)
11332+ INIT_HLIST_BL_HEAD(hbl);
11333+
11334+ err = au_dr_brid_init(&dr->dr_brid, path);
11335+ if (unlikely(err))
11336+ goto out;
11337+
11338+ if (au_opt_test(au_mntflags(sb), DIRREN))
11339+ err = au_dr_hino(sb, /*bindex*/-1, br, path);
11340+
11341+out:
11342+ AuTraceErr(err);
11343+ return err;
11344+}
11345+
11346+int au_dr_br_fin(struct super_block *sb, struct au_branch *br)
11347+{
11348+ int err;
11349+
11350+ err = 0;
11351+ if (au_br_writable(br->br_perm))
11352+ err = au_dr_hino(sb, /*bindex*/-1, br, /*path*/NULL);
11353+ if (!err)
11354+ au_dr_hino_free(&br->br_dirren);
11355+
11356+ return err;
11357+}
11358+
11359+/* ---------------------------------------------------------------------- */
11360+
11361+static int au_brid_str(struct au_dr_brid *brid, struct inode *h_inode,
11362+ char *buf, size_t sz)
11363+{
11364+ int err;
11365+ unsigned int major, minor;
11366+ char *p;
11367+
11368+ p = buf;
11369+ err = snprintf(p, sz, "%d_", brid->type);
11370+ AuDebugOn(err > sz);
11371+ p += err;
11372+ sz -= err;
11373+ switch (brid->type) {
11374+ case AuBrid_Unset:
11375+ return -EINVAL;
11376+ case AuBrid_UUID:
11377+ err = snprintf(p, sz, "%pU", brid->uuid.b);
11378+ break;
11379+ case AuBrid_FSID:
11380+ err = snprintf(p, sz, "%08x-%08x",
11381+ brid->fsid.val[0], brid->fsid.val[1]);
11382+ break;
11383+ case AuBrid_DEV:
11384+ major = MAJOR(brid->dev);
11385+ minor = MINOR(brid->dev);
11386+ if (major <= 0xff && minor <= 0xff)
11387+ err = snprintf(p, sz, "%02x%02x", major, minor);
11388+ else
11389+ err = snprintf(p, sz, "%03x:%05x", major, minor);
11390+ break;
11391+ }
11392+ AuDebugOn(err > sz);
11393+ p += err;
11394+ sz -= err;
11395+ err = snprintf(p, sz, "_%llu", (unsigned long long)h_inode->i_ino);
11396+ AuDebugOn(err > sz);
11397+ p += err;
11398+ sz -= err;
11399+
11400+ return p - buf;
11401+}
11402+
11403+static int au_drinfo_name(struct au_branch *br, char *name, int len)
11404+{
11405+ int rlen;
11406+ struct dentry *br_dentry;
11407+ struct inode *br_inode;
11408+
11409+ br_dentry = au_br_dentry(br);
11410+ br_inode = d_inode(br_dentry);
11411+ rlen = au_brid_str(&br->br_dirren.dr_brid, br_inode, name, len);
11412+ AuDebugOn(rlen >= AUFS_DIRREN_ENV_VAL_SZ);
11413+ AuDebugOn(rlen > len);
11414+
11415+ return rlen;
11416+}
11417+
11418+/* ---------------------------------------------------------------------- */
11419+
11420+/*
11421+ * from the given @h_dentry, construct drinfo at @*fdata.
11422+ * when the size of @*fdata is not enough, reallocate and return new @fdata and
11423+ * @allocated.
11424+ */
11425+static int au_drinfo_construct(struct au_drinfo_fdata **fdata,
11426+ struct dentry *h_dentry,
11427+ unsigned char *allocated)
11428+{
11429+ int err, v;
11430+ struct au_drinfo_fdata *f, *p;
11431+ struct au_drinfo *drinfo;
11432+ struct inode *h_inode;
11433+ struct qstr *qname;
11434+
11435+ err = 0;
11436+ f = *fdata;
11437+ h_inode = d_inode(h_dentry);
11438+ qname = &h_dentry->d_name;
11439+ drinfo = &f->drinfo;
11440+ drinfo->ino = (__force uint64_t)cpu_to_be64(h_inode->i_ino);
11441+ drinfo->oldnamelen = qname->len;
11442+ if (*allocated < sizeof(*f) + qname->len) {
11443+ v = roundup_pow_of_two(*allocated + qname->len);
11444+ p = au_krealloc(f, v, GFP_NOFS, /*may_shrink*/0);
11445+ if (unlikely(!p)) {
11446+ err = -ENOMEM;
11447+ AuTraceErr(err);
11448+ goto out;
11449+ }
11450+ f = p;
11451+ *fdata = f;
11452+ *allocated = v;
11453+ drinfo = &f->drinfo;
11454+ }
11455+ memcpy(drinfo->oldname, qname->name, qname->len);
11456+ AuDbg("i%llu, %.*s\n",
11457+ be64_to_cpu((__force __be64)drinfo->ino), drinfo->oldnamelen,
11458+ drinfo->oldname);
11459+
11460+out:
11461+ AuTraceErr(err);
11462+ return err;
11463+}
11464+
11465+/* callers have to free the return value */
11466+static struct au_drinfo *au_drinfo_read_k(struct file *file, ino_t h_ino)
11467+{
11468+ struct au_drinfo *ret, *drinfo;
11469+ struct au_drinfo_fdata fdata;
11470+ int len;
11471+ loff_t pos;
11472+ ssize_t ssz;
11473+
11474+ ret = ERR_PTR(-EIO);
11475+ pos = 0;
11476+ ssz = vfsub_read_k(file, &fdata, sizeof(fdata), &pos);
11477+ if (unlikely(ssz != sizeof(fdata))) {
11478+ AuIOErr("ssz %zd, %u, %pD2\n",
11479+ ssz, (unsigned int)sizeof(fdata), file);
11480+ goto out;
11481+ }
11482+
11483+ fdata.magic = ntohl((__force __be32)fdata.magic);
11484+ switch (fdata.magic) {
11485+ case AUFS_DRINFO_MAGIC_V1:
11486+ break;
11487+ default:
11488+ AuIOErr("magic-num 0x%x, 0x%x, %pD2\n",
11489+ fdata.magic, AUFS_DRINFO_MAGIC_V1, file);
11490+ goto out;
11491+ }
11492+
11493+ drinfo = &fdata.drinfo;
11494+ len = drinfo->oldnamelen;
11495+ if (!len) {
11496+ AuIOErr("broken drinfo %pD2\n", file);
11497+ goto out;
11498+ }
11499+
11500+ ret = NULL;
11501+ drinfo->ino = be64_to_cpu((__force __be64)drinfo->ino);
11502+ if (unlikely(h_ino && drinfo->ino != h_ino)) {
11503+ AuDbg("ignored i%llu, i%llu, %pD2\n",
11504+ (unsigned long long)drinfo->ino,
11505+ (unsigned long long)h_ino, file);
11506+ goto out; /* success */
11507+ }
11508+
11509+ ret = kmalloc(sizeof(*ret) + len, GFP_NOFS);
11510+ if (unlikely(!ret)) {
11511+ ret = ERR_PTR(-ENOMEM);
11512+ AuTraceErrPtr(ret);
11513+ goto out;
11514+ }
11515+
11516+ *ret = *drinfo;
11517+ ssz = vfsub_read_k(file, (void *)ret->oldname, len, &pos);
11518+ if (unlikely(ssz != len)) {
9f237c51 11519+ au_kfree_rcu(ret);
8b6a4947
AM
11520+ ret = ERR_PTR(-EIO);
11521+ AuIOErr("ssz %zd, %u, %pD2\n", ssz, len, file);
11522+ goto out;
11523+ }
11524+
11525+ AuDbg("oldname %.*s\n", ret->oldnamelen, ret->oldname);
11526+
11527+out:
11528+ return ret;
11529+}
11530+
11531+/* ---------------------------------------------------------------------- */
11532+
11533+/* in order to be revertible */
11534+struct au_drinfo_rev_elm {
11535+ int created;
11536+ struct dentry *info_dentry;
11537+ struct au_drinfo *info_last;
11538+};
11539+
11540+struct au_drinfo_rev {
11541+ unsigned char already;
11542+ aufs_bindex_t nelm;
11543+ struct au_drinfo_rev_elm elm[0];
11544+};
11545+
11546+/* todo: isn't it too large? */
11547+struct au_drinfo_store {
11548+ struct path h_ppath;
11549+ struct dentry *h_dentry;
11550+ struct au_drinfo_fdata *fdata;
11551+ char *infoname; /* inside of whname, just after PFX */
11552+ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ];
11553+ aufs_bindex_t btgt, btail;
11554+ unsigned char no_sio,
11555+ allocated, /* current size of *fdata */
11556+ infonamelen, /* room size for p */
acd2b654 11557+ whnamelen, /* length of the generated name */
8b6a4947
AM
11558+ renameback; /* renamed back */
11559+};
11560+
11561+/* on rename(2) error, the caller should revert it using @elm */
11562+static int au_drinfo_do_store(struct au_drinfo_store *w,
11563+ struct au_drinfo_rev_elm *elm)
11564+{
11565+ int err, len;
11566+ ssize_t ssz;
11567+ loff_t pos;
11568+ struct path infopath = {
11569+ .mnt = w->h_ppath.mnt
11570+ };
11571+ struct inode *h_dir, *h_inode, *delegated;
11572+ struct file *infofile;
11573+ struct qstr *qname;
11574+
11575+ AuDebugOn(elm
11576+ && memcmp(elm, page_address(ZERO_PAGE(0)), sizeof(*elm)));
11577+
11578+ infopath.dentry = vfsub_lookup_one_len(w->whname, w->h_ppath.dentry,
11579+ w->whnamelen);
11580+ AuTraceErrPtr(infopath.dentry);
11581+ if (IS_ERR(infopath.dentry)) {
11582+ err = PTR_ERR(infopath.dentry);
11583+ goto out;
11584+ }
11585+
11586+ err = 0;
11587+ h_dir = d_inode(w->h_ppath.dentry);
11588+ if (elm && d_is_negative(infopath.dentry)) {
11589+ err = vfsub_create(h_dir, &infopath, 0600, /*want_excl*/true);
11590+ AuTraceErr(err);
11591+ if (unlikely(err))
11592+ goto out_dput;
11593+ elm->created = 1;
11594+ elm->info_dentry = dget(infopath.dentry);
11595+ }
11596+
11597+ infofile = vfsub_dentry_open(&infopath, O_RDWR);
11598+ AuTraceErrPtr(infofile);
11599+ if (IS_ERR(infofile)) {
11600+ err = PTR_ERR(infofile);
11601+ goto out_dput;
11602+ }
11603+
11604+ h_inode = d_inode(infopath.dentry);
11605+ if (elm && i_size_read(h_inode)) {
11606+ h_inode = d_inode(w->h_dentry);
11607+ elm->info_last = au_drinfo_read_k(infofile, h_inode->i_ino);
11608+ AuTraceErrPtr(elm->info_last);
11609+ if (IS_ERR(elm->info_last)) {
11610+ err = PTR_ERR(elm->info_last);
11611+ elm->info_last = NULL;
11612+ AuDebugOn(elm->info_dentry);
11613+ goto out_fput;
11614+ }
11615+ }
11616+
11617+ if (elm && w->renameback) {
11618+ delegated = NULL;
11619+ err = vfsub_unlink(h_dir, &infopath, &delegated, /*force*/0);
11620+ AuTraceErr(err);
11621+ if (unlikely(err == -EWOULDBLOCK))
11622+ iput(delegated);
11623+ goto out_fput;
11624+ }
11625+
11626+ pos = 0;
11627+ qname = &w->h_dentry->d_name;
11628+ len = sizeof(*w->fdata) + qname->len;
11629+ if (!elm)
11630+ len = sizeof(*w->fdata) + w->fdata->drinfo.oldnamelen;
11631+ ssz = vfsub_write_k(infofile, w->fdata, len, &pos);
11632+ if (ssz == len) {
11633+ AuDbg("hi%llu, %.*s\n", w->fdata->drinfo.ino,
11634+ w->fdata->drinfo.oldnamelen, w->fdata->drinfo.oldname);
11635+ goto out_fput; /* success */
11636+ } else {
11637+ err = -EIO;
11638+ if (ssz < 0)
11639+ err = ssz;
11640+ /* the caller should revert it using @elm */
11641+ }
11642+
11643+out_fput:
11644+ fput(infofile);
11645+out_dput:
11646+ dput(infopath.dentry);
11647+out:
11648+ AuTraceErr(err);
11649+ return err;
11650+}
11651+
11652+struct au_call_drinfo_do_store_args {
11653+ int *errp;
11654+ struct au_drinfo_store *w;
11655+ struct au_drinfo_rev_elm *elm;
11656+};
11657+
11658+static void au_call_drinfo_do_store(void *args)
11659+{
11660+ struct au_call_drinfo_do_store_args *a = args;
11661+
11662+ *a->errp = au_drinfo_do_store(a->w, a->elm);
11663+}
11664+
11665+static int au_drinfo_store_sio(struct au_drinfo_store *w,
11666+ struct au_drinfo_rev_elm *elm)
11667+{
11668+ int err, wkq_err;
11669+
11670+ if (w->no_sio)
11671+ err = au_drinfo_do_store(w, elm);
11672+ else {
11673+ struct au_call_drinfo_do_store_args a = {
11674+ .errp = &err,
11675+ .w = w,
11676+ .elm = elm
11677+ };
11678+ wkq_err = au_wkq_wait(au_call_drinfo_do_store, &a);
11679+ if (unlikely(wkq_err))
11680+ err = wkq_err;
11681+ }
11682+ AuTraceErr(err);
11683+
11684+ return err;
11685+}
11686+
11687+static int au_drinfo_store_work_init(struct au_drinfo_store *w,
11688+ aufs_bindex_t btgt)
11689+{
11690+ int err;
11691+
11692+ memset(w, 0, sizeof(*w));
11693+ w->allocated = roundup_pow_of_two(sizeof(*w->fdata) + 40);
11694+ strcpy(w->whname, AUFS_WH_DR_INFO_PFX);
11695+ w->infoname = w->whname + sizeof(AUFS_WH_DR_INFO_PFX) - 1;
11696+ w->infonamelen = sizeof(w->whname) - sizeof(AUFS_WH_DR_INFO_PFX);
11697+ w->btgt = btgt;
11698+ w->no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID);
11699+
11700+ err = -ENOMEM;
11701+ w->fdata = kcalloc(1, w->allocated, GFP_NOFS);
11702+ if (unlikely(!w->fdata)) {
11703+ AuTraceErr(err);
11704+ goto out;
11705+ }
11706+ w->fdata->magic = (__force uint32_t)htonl(AUFS_DRINFO_MAGIC_V1);
11707+ err = 0;
11708+
11709+out:
11710+ return err;
11711+}
11712+
11713+static void au_drinfo_store_work_fin(struct au_drinfo_store *w)
11714+{
9f237c51 11715+ au_kfree_rcu(w->fdata);
8b6a4947
AM
11716+}
11717+
11718+static void au_drinfo_store_rev(struct au_drinfo_rev *rev,
11719+ struct au_drinfo_store *w)
11720+{
11721+ struct au_drinfo_rev_elm *elm;
11722+ struct inode *h_dir, *delegated;
11723+ int err, nelm;
11724+ struct path infopath = {
11725+ .mnt = w->h_ppath.mnt
11726+ };
11727+
11728+ h_dir = d_inode(w->h_ppath.dentry);
11729+ IMustLock(h_dir);
11730+
11731+ err = 0;
11732+ elm = rev->elm;
11733+ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) {
11734+ AuDebugOn(elm->created && elm->info_last);
11735+ if (elm->created) {
11736+ AuDbg("here\n");
11737+ delegated = NULL;
11738+ infopath.dentry = elm->info_dentry;
11739+ err = vfsub_unlink(h_dir, &infopath, &delegated,
11740+ !w->no_sio);
11741+ AuTraceErr(err);
11742+ if (unlikely(err == -EWOULDBLOCK))
11743+ iput(delegated);
11744+ dput(elm->info_dentry);
11745+ } else if (elm->info_last) {
11746+ AuDbg("here\n");
11747+ w->fdata->drinfo = *elm->info_last;
11748+ memcpy(w->fdata->drinfo.oldname,
11749+ elm->info_last->oldname,
11750+ elm->info_last->oldnamelen);
11751+ err = au_drinfo_store_sio(w, /*elm*/NULL);
9f237c51 11752+ au_kfree_rcu(elm->info_last);
8b6a4947
AM
11753+ }
11754+ if (unlikely(err))
11755+ AuIOErr("%d, %s\n", err, w->whname);
11756+ /* go on even if err */
11757+ }
11758+}
11759+
11760+/* caller has to call au_dr_rename_fin() later */
11761+static int au_drinfo_store(struct dentry *dentry, aufs_bindex_t btgt,
11762+ struct qstr *dst_name, void *_rev)
11763+{
11764+ int err, sz, nelm;
11765+ aufs_bindex_t bindex, btail;
11766+ struct au_drinfo_store work;
11767+ struct au_drinfo_rev *rev, **p;
11768+ struct au_drinfo_rev_elm *elm;
11769+ struct super_block *sb;
11770+ struct au_branch *br;
11771+ struct au_hinode *hdir;
11772+
11773+ err = au_drinfo_store_work_init(&work, btgt);
11774+ AuTraceErr(err);
11775+ if (unlikely(err))
11776+ goto out;
11777+
11778+ err = -ENOMEM;
11779+ btail = au_dbtaildir(dentry);
11780+ nelm = btail - btgt;
11781+ sz = sizeof(*rev) + sizeof(*elm) * nelm;
11782+ rev = kcalloc(1, sz, GFP_NOFS);
11783+ if (unlikely(!rev)) {
11784+ AuTraceErr(err);
11785+ goto out_args;
11786+ }
11787+ rev->nelm = nelm;
11788+ elm = rev->elm;
11789+ p = _rev;
11790+ *p = rev;
11791+
11792+ err = 0;
11793+ sb = dentry->d_sb;
11794+ work.h_ppath.dentry = au_h_dptr(dentry, btgt);
11795+ work.h_ppath.mnt = au_sbr_mnt(sb, btgt);
11796+ hdir = au_hi(d_inode(dentry), btgt);
11797+ au_hn_inode_lock_nested(hdir, AuLsc_I_CHILD);
11798+ for (bindex = btgt + 1; bindex <= btail; bindex++, elm++) {
11799+ work.h_dentry = au_h_dptr(dentry, bindex);
11800+ if (!work.h_dentry)
11801+ continue;
11802+
11803+ err = au_drinfo_construct(&work.fdata, work.h_dentry,
11804+ &work.allocated);
11805+ AuTraceErr(err);
11806+ if (unlikely(err))
11807+ break;
11808+
11809+ work.renameback = au_qstreq(&work.h_dentry->d_name, dst_name);
11810+ br = au_sbr(sb, bindex);
11811+ work.whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1;
11812+ work.whnamelen += au_drinfo_name(br, work.infoname,
11813+ work.infonamelen);
11814+ AuDbg("whname %.*s, i%llu, %.*s\n",
11815+ work.whnamelen, work.whname,
11816+ be64_to_cpu((__force __be64)work.fdata->drinfo.ino),
11817+ work.fdata->drinfo.oldnamelen,
11818+ work.fdata->drinfo.oldname);
11819+
11820+ err = au_drinfo_store_sio(&work, elm);
11821+ AuTraceErr(err);
11822+ if (unlikely(err))
11823+ break;
11824+ }
11825+ if (unlikely(err)) {
11826+ /* revert all drinfo */
11827+ au_drinfo_store_rev(rev, &work);
9f237c51 11828+ au_kfree_try_rcu(rev);
8b6a4947
AM
11829+ *p = NULL;
11830+ }
11831+ au_hn_inode_unlock(hdir);
11832+
11833+out_args:
11834+ au_drinfo_store_work_fin(&work);
11835+out:
11836+ return err;
11837+}
11838+
11839+/* ---------------------------------------------------------------------- */
11840+
11841+int au_dr_rename(struct dentry *src, aufs_bindex_t bindex,
11842+ struct qstr *dst_name, void *_rev)
11843+{
11844+ int err, already;
11845+ ino_t ino;
11846+ struct super_block *sb;
11847+ struct au_branch *br;
11848+ struct au_dr_br *dr;
11849+ struct dentry *h_dentry;
11850+ struct inode *h_inode;
11851+ struct au_dr_hino *ent;
11852+ struct au_drinfo_rev *rev, **p;
11853+
11854+ AuDbg("bindex %d\n", bindex);
11855+
11856+ err = -ENOMEM;
11857+ ent = kmalloc(sizeof(*ent), GFP_NOFS);
11858+ if (unlikely(!ent))
11859+ goto out;
11860+
11861+ sb = src->d_sb;
11862+ br = au_sbr(sb, bindex);
11863+ dr = &br->br_dirren;
11864+ h_dentry = au_h_dptr(src, bindex);
11865+ h_inode = d_inode(h_dentry);
11866+ ino = h_inode->i_ino;
11867+ ent->dr_h_ino = ino;
11868+ already = au_dr_hino_test_add(dr, ino, ent);
11869+ AuDbg("b%d, hi%llu, already %d\n",
11870+ bindex, (unsigned long long)ino, already);
11871+
11872+ err = au_drinfo_store(src, bindex, dst_name, _rev);
11873+ AuTraceErr(err);
11874+ if (!err) {
11875+ p = _rev;
11876+ rev = *p;
11877+ rev->already = already;
11878+ goto out; /* success */
11879+ }
11880+
11881+ /* revert */
11882+ if (!already)
11883+ au_dr_hino_del(dr, ent);
9f237c51 11884+ au_kfree_rcu(ent);
8b6a4947
AM
11885+
11886+out:
11887+ AuTraceErr(err);
11888+ return err;
11889+}
11890+
11891+void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *_rev)
11892+{
11893+ struct au_drinfo_rev *rev;
11894+ struct au_drinfo_rev_elm *elm;
11895+ int nelm;
11896+
11897+ rev = _rev;
11898+ elm = rev->elm;
11899+ for (nelm = rev->nelm; nelm > 0; nelm--, elm++) {
11900+ dput(elm->info_dentry);
9f237c51 11901+ au_kfree_rcu(elm->info_last);
8b6a4947 11902+ }
9f237c51 11903+ au_kfree_try_rcu(rev);
8b6a4947
AM
11904+}
11905+
11906+void au_dr_rename_rev(struct dentry *src, aufs_bindex_t btgt, void *_rev)
11907+{
11908+ int err;
11909+ struct au_drinfo_store work;
11910+ struct au_drinfo_rev *rev = _rev;
11911+ struct super_block *sb;
11912+ struct au_branch *br;
11913+ struct inode *h_inode;
11914+ struct au_dr_br *dr;
11915+ struct au_dr_hino *ent;
11916+
11917+ err = au_drinfo_store_work_init(&work, btgt);
11918+ if (unlikely(err))
11919+ goto out;
11920+
11921+ sb = src->d_sb;
11922+ br = au_sbr(sb, btgt);
11923+ work.h_ppath.dentry = au_h_dptr(src, btgt);
11924+ work.h_ppath.mnt = au_br_mnt(br);
11925+ au_drinfo_store_rev(rev, &work);
11926+ au_drinfo_store_work_fin(&work);
11927+ if (rev->already)
11928+ goto out;
11929+
11930+ dr = &br->br_dirren;
11931+ h_inode = d_inode(work.h_ppath.dentry);
11932+ ent = au_dr_hino_find(dr, h_inode->i_ino);
11933+ BUG_ON(!ent);
11934+ au_dr_hino_del(dr, ent);
9f237c51 11935+ au_kfree_rcu(ent);
8b6a4947
AM
11936+
11937+out:
9f237c51 11938+ au_kfree_try_rcu(rev);
8b6a4947
AM
11939+ if (unlikely(err))
11940+ pr_err("failed to remove dirren info\n");
11941+}
11942+
11943+/* ---------------------------------------------------------------------- */
11944+
11945+static struct au_drinfo *au_drinfo_do_load(struct path *h_ppath,
11946+ char *whname, int whnamelen,
11947+ struct dentry **info_dentry)
11948+{
11949+ struct au_drinfo *drinfo;
11950+ struct file *f;
11951+ struct inode *h_dir;
11952+ struct path infopath;
11953+ int unlocked;
11954+
11955+ AuDbg("%pd/%.*s\n", h_ppath->dentry, whnamelen, whname);
11956+
11957+ *info_dentry = NULL;
11958+ drinfo = NULL;
11959+ unlocked = 0;
11960+ h_dir = d_inode(h_ppath->dentry);
be118d29 11961+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
8b6a4947
AM
11962+ infopath.dentry = vfsub_lookup_one_len(whname, h_ppath->dentry,
11963+ whnamelen);
11964+ if (IS_ERR(infopath.dentry)) {
11965+ drinfo = (void *)infopath.dentry;
11966+ goto out;
11967+ }
11968+
11969+ if (d_is_negative(infopath.dentry))
11970+ goto out_dput; /* success */
11971+
11972+ infopath.mnt = h_ppath->mnt;
11973+ f = vfsub_dentry_open(&infopath, O_RDONLY);
11974+ inode_unlock_shared(h_dir);
11975+ unlocked = 1;
11976+ if (IS_ERR(f)) {
11977+ drinfo = (void *)f;
11978+ goto out_dput;
11979+ }
11980+
11981+ drinfo = au_drinfo_read_k(f, /*h_ino*/0);
11982+ if (IS_ERR_OR_NULL(drinfo))
11983+ goto out_fput;
11984+
11985+ AuDbg("oldname %.*s\n", drinfo->oldnamelen, drinfo->oldname);
11986+ *info_dentry = dget(infopath.dentry); /* keep it alive */
11987+
11988+out_fput:
11989+ fput(f);
11990+out_dput:
11991+ dput(infopath.dentry);
11992+out:
11993+ if (!unlocked)
11994+ inode_unlock_shared(h_dir);
11995+ AuTraceErrPtr(drinfo);
11996+ return drinfo;
11997+}
11998+
11999+struct au_drinfo_do_load_args {
12000+ struct au_drinfo **drinfop;
12001+ struct path *h_ppath;
12002+ char *whname;
12003+ int whnamelen;
12004+ struct dentry **info_dentry;
12005+};
12006+
12007+static void au_call_drinfo_do_load(void *args)
12008+{
12009+ struct au_drinfo_do_load_args *a = args;
12010+
12011+ *a->drinfop = au_drinfo_do_load(a->h_ppath, a->whname, a->whnamelen,
12012+ a->info_dentry);
12013+}
12014+
12015+struct au_drinfo_load {
12016+ struct path h_ppath;
12017+ struct qstr *qname;
12018+ unsigned char no_sio;
12019+
12020+ aufs_bindex_t ninfo;
12021+ struct au_drinfo **drinfo;
12022+};
12023+
12024+static int au_drinfo_load(struct au_drinfo_load *w, aufs_bindex_t bindex,
12025+ struct au_branch *br)
12026+{
12027+ int err, wkq_err, whnamelen, e;
12028+ char whname[sizeof(AUFS_WH_DR_INFO_PFX) + AUFS_DIRREN_ENV_VAL_SZ]
12029+ = AUFS_WH_DR_INFO_PFX;
12030+ struct au_drinfo *drinfo;
12031+ struct qstr oldname;
12032+ struct inode *h_dir, *delegated;
12033+ struct dentry *info_dentry;
12034+ struct path infopath;
12035+
12036+ whnamelen = sizeof(AUFS_WH_DR_INFO_PFX) - 1;
12037+ whnamelen += au_drinfo_name(br, whname + whnamelen,
12038+ sizeof(whname) - whnamelen);
12039+ if (w->no_sio)
12040+ drinfo = au_drinfo_do_load(&w->h_ppath, whname, whnamelen,
12041+ &info_dentry);
12042+ else {
12043+ struct au_drinfo_do_load_args args = {
12044+ .drinfop = &drinfo,
12045+ .h_ppath = &w->h_ppath,
12046+ .whname = whname,
12047+ .whnamelen = whnamelen,
12048+ .info_dentry = &info_dentry
12049+ };
12050+ wkq_err = au_wkq_wait(au_call_drinfo_do_load, &args);
12051+ if (unlikely(wkq_err))
12052+ drinfo = ERR_PTR(wkq_err);
12053+ }
12054+ err = PTR_ERR(drinfo);
12055+ if (IS_ERR_OR_NULL(drinfo))
12056+ goto out;
12057+
12058+ err = 0;
12059+ oldname.len = drinfo->oldnamelen;
12060+ oldname.name = drinfo->oldname;
12061+ if (au_qstreq(w->qname, &oldname)) {
12062+ /* the name is renamed back */
9f237c51 12063+ au_kfree_rcu(drinfo);
8b6a4947
AM
12064+ drinfo = NULL;
12065+
12066+ infopath.dentry = info_dentry;
12067+ infopath.mnt = w->h_ppath.mnt;
12068+ h_dir = d_inode(w->h_ppath.dentry);
12069+ delegated = NULL;
12070+ inode_lock_nested(h_dir, AuLsc_I_PARENT);
12071+ e = vfsub_unlink(h_dir, &infopath, &delegated, !w->no_sio);
12072+ inode_unlock(h_dir);
12073+ if (unlikely(e))
12074+ AuIOErr("ignored %d, %pd2\n", e, &infopath.dentry);
12075+ if (unlikely(e == -EWOULDBLOCK))
12076+ iput(delegated);
12077+ }
9f237c51 12078+ au_kfree_rcu(w->drinfo[bindex]);
8b6a4947
AM
12079+ w->drinfo[bindex] = drinfo;
12080+ dput(info_dentry);
12081+
12082+out:
12083+ AuTraceErr(err);
12084+ return err;
12085+}
12086+
12087+/* ---------------------------------------------------------------------- */
12088+
12089+static void au_dr_lkup_free(struct au_drinfo **drinfo, int n)
12090+{
12091+ struct au_drinfo **p = drinfo;
12092+
12093+ while (n-- > 0)
9f237c51
AM
12094+ au_kfree_rcu(*drinfo++);
12095+ au_kfree_try_rcu(p);
8b6a4947
AM
12096+}
12097+
12098+int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry,
12099+ aufs_bindex_t btgt)
12100+{
12101+ int err, ninfo;
12102+ struct au_drinfo_load w;
12103+ aufs_bindex_t bindex, bbot;
12104+ struct au_branch *br;
12105+ struct inode *h_dir;
12106+ struct au_dr_hino *ent;
12107+ struct super_block *sb;
12108+
12109+ AuDbg("%.*s, name %.*s, whname %.*s, b%d\n",
12110+ AuLNPair(&dentry->d_name), AuLNPair(&lkup->dirren.dr_name),
12111+ AuLNPair(&lkup->whname), btgt);
12112+
12113+ sb = dentry->d_sb;
12114+ bbot = au_sbbot(sb);
12115+ w.ninfo = bbot + 1;
12116+ if (!lkup->dirren.drinfo) {
12117+ lkup->dirren.drinfo = kcalloc(w.ninfo,
12118+ sizeof(*lkup->dirren.drinfo),
12119+ GFP_NOFS);
12120+ if (unlikely(!lkup->dirren.drinfo)) {
12121+ err = -ENOMEM;
12122+ goto out;
12123+ }
12124+ lkup->dirren.ninfo = w.ninfo;
12125+ }
12126+ w.drinfo = lkup->dirren.drinfo;
12127+ w.no_sio = !!uid_eq(current_fsuid(), GLOBAL_ROOT_UID);
12128+ w.h_ppath.dentry = au_h_dptr(dentry, btgt);
12129+ AuDebugOn(!w.h_ppath.dentry);
12130+ w.h_ppath.mnt = au_sbr_mnt(sb, btgt);
12131+ w.qname = &dentry->d_name;
12132+
12133+ ninfo = 0;
12134+ for (bindex = btgt + 1; bindex <= bbot; bindex++) {
12135+ br = au_sbr(sb, bindex);
12136+ err = au_drinfo_load(&w, bindex, br);
12137+ if (unlikely(err))
12138+ goto out_free;
12139+ if (w.drinfo[bindex])
12140+ ninfo++;
12141+ }
12142+ if (!ninfo) {
12143+ br = au_sbr(sb, btgt);
12144+ h_dir = d_inode(w.h_ppath.dentry);
12145+ ent = au_dr_hino_find(&br->br_dirren, h_dir->i_ino);
12146+ AuDebugOn(!ent);
12147+ au_dr_hino_del(&br->br_dirren, ent);
9f237c51 12148+ au_kfree_rcu(ent);
8b6a4947
AM
12149+ }
12150+ goto out; /* success */
12151+
12152+out_free:
12153+ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo);
12154+ lkup->dirren.ninfo = 0;
12155+ lkup->dirren.drinfo = NULL;
12156+out:
12157+ AuTraceErr(err);
12158+ return err;
12159+}
12160+
12161+void au_dr_lkup_fin(struct au_do_lookup_args *lkup)
12162+{
12163+ au_dr_lkup_free(lkup->dirren.drinfo, lkup->dirren.ninfo);
12164+}
12165+
12166+int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt)
12167+{
12168+ int err;
12169+ struct au_drinfo *drinfo;
12170+
12171+ err = 0;
12172+ if (!lkup->dirren.drinfo)
12173+ goto out;
43982f53
AM
12174+ AuDebugOn(lkup->dirren.ninfo <= btgt);
12175+ drinfo = lkup->dirren.drinfo[btgt];
8b6a4947
AM
12176+ if (!drinfo)
12177+ goto out;
12178+
9f237c51 12179+ au_kfree_try_rcu(lkup->whname.name);
8b6a4947
AM
12180+ lkup->whname.name = NULL;
12181+ lkup->dirren.dr_name.len = drinfo->oldnamelen;
12182+ lkup->dirren.dr_name.name = drinfo->oldname;
12183+ lkup->name = &lkup->dirren.dr_name;
12184+ err = au_wh_name_alloc(&lkup->whname, lkup->name);
12185+ if (!err)
12186+ AuDbg("name %.*s, whname %.*s, b%d\n",
12187+ AuLNPair(lkup->name), AuLNPair(&lkup->whname),
12188+ btgt);
12189+
12190+out:
12191+ AuTraceErr(err);
12192+ return err;
12193+}
12194+
12195+int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex,
12196+ ino_t h_ino)
12197+{
12198+ int match;
12199+ struct au_drinfo *drinfo;
12200+
12201+ match = 1;
12202+ if (!lkup->dirren.drinfo)
12203+ goto out;
43982f53
AM
12204+ AuDebugOn(lkup->dirren.ninfo <= bindex);
12205+ drinfo = lkup->dirren.drinfo[bindex];
8b6a4947
AM
12206+ if (!drinfo)
12207+ goto out;
12208+
12209+ match = (drinfo->ino == h_ino);
12210+ AuDbg("match %d\n", match);
12211+
12212+out:
12213+ return match;
12214+}
12215+
12216+/* ---------------------------------------------------------------------- */
12217+
12218+int au_dr_opt_set(struct super_block *sb)
12219+{
12220+ int err;
12221+ aufs_bindex_t bindex, bbot;
12222+ struct au_branch *br;
12223+
12224+ err = 0;
12225+ bbot = au_sbbot(sb);
12226+ for (bindex = 0; !err && bindex <= bbot; bindex++) {
12227+ br = au_sbr(sb, bindex);
12228+ err = au_dr_hino(sb, bindex, /*br*/NULL, &br->br_path);
12229+ }
12230+
12231+ return err;
12232+}
12233+
12234+int au_dr_opt_flush(struct super_block *sb)
12235+{
12236+ int err;
12237+ aufs_bindex_t bindex, bbot;
12238+ struct au_branch *br;
12239+
12240+ err = 0;
12241+ bbot = au_sbbot(sb);
12242+ for (bindex = 0; !err && bindex <= bbot; bindex++) {
12243+ br = au_sbr(sb, bindex);
12244+ if (au_br_writable(br->br_perm))
12245+ err = au_dr_hino(sb, bindex, /*br*/NULL, /*path*/NULL);
12246+ }
12247+
12248+ return err;
12249+}
12250+
12251+int au_dr_opt_clr(struct super_block *sb, int no_flush)
12252+{
12253+ int err;
12254+ aufs_bindex_t bindex, bbot;
12255+ struct au_branch *br;
12256+
12257+ err = 0;
12258+ if (!no_flush) {
12259+ err = au_dr_opt_flush(sb);
12260+ if (unlikely(err))
12261+ goto out;
12262+ }
12263+
12264+ bbot = au_sbbot(sb);
12265+ for (bindex = 0; bindex <= bbot; bindex++) {
12266+ br = au_sbr(sb, bindex);
12267+ au_dr_hino_free(&br->br_dirren);
12268+ }
12269+
12270+out:
12271+ return err;
12272+}
12273diff -urN /usr/share/empty/fs/aufs/dirren.h linux/fs/aufs/dirren.h
eca34b5c 12274--- /usr/share/empty/fs/aufs/dirren.h 1970-01-01 01:00:00.000000000 +0100
016522bc 12275+++ linux/fs/aufs/dirren.h 2020-01-27 10:57:18.168871450 +0100
062440b3
AM
12276@@ -0,0 +1,140 @@
12277+/* SPDX-License-Identifier: GPL-2.0 */
8b6a4947 12278+/*
016522bc 12279+ * Copyright (C) 2017-2020 Junjiro R. Okajima
8b6a4947
AM
12280+ *
12281+ * This program, aufs is free software; you can redistribute it and/or modify
12282+ * it under the terms of the GNU General Public License as published by
12283+ * the Free Software Foundation; either version 2 of the License, or
12284+ * (at your option) any later version.
12285+ *
12286+ * This program is distributed in the hope that it will be useful,
12287+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12288+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12289+ * GNU General Public License for more details.
12290+ *
12291+ * You should have received a copy of the GNU General Public License
12292+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
12293+ */
12294+
12295+/*
12296+ * renamed dir info
12297+ */
12298+
12299+#ifndef __AUFS_DIRREN_H__
12300+#define __AUFS_DIRREN_H__
12301+
12302+#ifdef __KERNEL__
12303+
12304+#include <linux/dcache.h>
12305+#include <linux/statfs.h>
12306+#include <linux/uuid.h>
12307+#include "hbl.h"
12308+
12309+#define AuDirren_NHASH 100
12310+
12311+#ifdef CONFIG_AUFS_DIRREN
12312+enum au_brid_type {
12313+ AuBrid_Unset,
12314+ AuBrid_UUID,
12315+ AuBrid_FSID,
12316+ AuBrid_DEV
12317+};
12318+
12319+struct au_dr_brid {
12320+ enum au_brid_type type;
12321+ union {
12322+ uuid_t uuid; /* unimplemented yet */
12323+ fsid_t fsid;
12324+ dev_t dev;
12325+ };
12326+};
12327+
12328+/* 20 is the max digits length of ulong 64 */
12329+/* brid-type "_" uuid "_" inum */
12330+#define AUFS_DIRREN_FNAME_SZ (1 + 1 + UUID_STRING_LEN + 20)
12331+#define AUFS_DIRREN_ENV_VAL_SZ (AUFS_DIRREN_FNAME_SZ + 1 + 20)
12332+
12333+struct au_dr_hino {
12334+ struct hlist_bl_node dr_hnode;
12335+ ino_t dr_h_ino;
12336+};
12337+
12338+struct au_dr_br {
12339+ struct hlist_bl_head dr_h_ino[AuDirren_NHASH];
12340+ struct au_dr_brid dr_brid;
12341+};
12342+
12343+struct au_dr_lookup {
12344+ /* dr_name is pointed by struct au_do_lookup_args.name */
12345+ struct qstr dr_name; /* subset of dr_info */
12346+ aufs_bindex_t ninfo;
12347+ struct au_drinfo **drinfo;
12348+};
12349+#else
12350+struct au_dr_hino;
12351+/* empty */
12352+struct au_dr_br { };
12353+struct au_dr_lookup { };
12354+#endif
12355+
12356+/* ---------------------------------------------------------------------- */
12357+
12358+struct au_branch;
12359+struct au_do_lookup_args;
12360+struct au_hinode;
12361+#ifdef CONFIG_AUFS_DIRREN
12362+int au_dr_hino_test_add(struct au_dr_br *dr, ino_t h_ino,
12363+ struct au_dr_hino *add_ent);
12364+void au_dr_hino_free(struct au_dr_br *dr);
12365+int au_dr_br_init(struct super_block *sb, struct au_branch *br,
12366+ const struct path *path);
12367+int au_dr_br_fin(struct super_block *sb, struct au_branch *br);
12368+int au_dr_rename(struct dentry *src, aufs_bindex_t bindex,
12369+ struct qstr *dst_name, void *_rev);
12370+void au_dr_rename_fin(struct dentry *src, aufs_bindex_t btgt, void *rev);
12371+void au_dr_rename_rev(struct dentry *src, aufs_bindex_t bindex, void *rev);
12372+int au_dr_lkup(struct au_do_lookup_args *lkup, struct dentry *dentry,
12373+ aufs_bindex_t bindex);
12374+int au_dr_lkup_name(struct au_do_lookup_args *lkup, aufs_bindex_t btgt);
12375+int au_dr_lkup_h_ino(struct au_do_lookup_args *lkup, aufs_bindex_t bindex,
12376+ ino_t h_ino);
12377+void au_dr_lkup_fin(struct au_do_lookup_args *lkup);
12378+int au_dr_opt_set(struct super_block *sb);
12379+int au_dr_opt_flush(struct super_block *sb);
12380+int au_dr_opt_clr(struct super_block *sb, int no_flush);
12381+#else
12382+AuStubInt0(au_dr_hino_test_add, struct au_dr_br *dr, ino_t h_ino,
12383+ struct au_dr_hino *add_ent);
12384+AuStubVoid(au_dr_hino_free, struct au_dr_br *dr);
12385+AuStubInt0(au_dr_br_init, struct super_block *sb, struct au_branch *br,
12386+ const struct path *path);
12387+AuStubInt0(au_dr_br_fin, struct super_block *sb, struct au_branch *br);
12388+AuStubInt0(au_dr_rename, struct dentry *src, aufs_bindex_t bindex,
12389+ struct qstr *dst_name, void *_rev);
12390+AuStubVoid(au_dr_rename_fin, struct dentry *src, aufs_bindex_t btgt, void *rev);
12391+AuStubVoid(au_dr_rename_rev, struct dentry *src, aufs_bindex_t bindex,
12392+ void *rev);
12393+AuStubInt0(au_dr_lkup, struct au_do_lookup_args *lkup, struct dentry *dentry,
12394+ aufs_bindex_t bindex);
12395+AuStubInt0(au_dr_lkup_name, struct au_do_lookup_args *lkup, aufs_bindex_t btgt);
12396+AuStubInt0(au_dr_lkup_h_ino, struct au_do_lookup_args *lkup,
12397+ aufs_bindex_t bindex, ino_t h_ino);
12398+AuStubVoid(au_dr_lkup_fin, struct au_do_lookup_args *lkup);
12399+AuStubInt0(au_dr_opt_set, struct super_block *sb);
12400+AuStubInt0(au_dr_opt_flush, struct super_block *sb);
12401+AuStubInt0(au_dr_opt_clr, struct super_block *sb, int no_flush);
12402+#endif
12403+
12404+/* ---------------------------------------------------------------------- */
12405+
12406+#ifdef CONFIG_AUFS_DIRREN
12407+static inline int au_dr_ihash(ino_t h_ino)
12408+{
12409+ return h_ino % AuDirren_NHASH;
12410+}
12411+#else
12412+AuStubInt0(au_dr_ihash, ino_t h_ino);
12413+#endif
12414+
12415+#endif /* __KERNEL__ */
12416+#endif /* __AUFS_DIRREN_H__ */
7f207e10 12417diff -urN /usr/share/empty/fs/aufs/dynop.c linux/fs/aufs/dynop.c
eca34b5c 12418--- /usr/share/empty/fs/aufs/dynop.c 1970-01-01 01:00:00.000000000 +0100
016522bc 12419+++ linux/fs/aufs/dynop.c 2020-01-27 10:57:18.168871450 +0100
fbc438ed 12420@@ -0,0 +1,367 @@
cd7a4cd9 12421+// SPDX-License-Identifier: GPL-2.0
1facf9fc 12422+/*
016522bc 12423+ * Copyright (C) 2010-2020 Junjiro R. Okajima
1facf9fc 12424+ *
12425+ * This program, aufs is free software; you can redistribute it and/or modify
12426+ * it under the terms of the GNU General Public License as published by
12427+ * the Free Software Foundation; either version 2 of the License, or
12428+ * (at your option) any later version.
dece6358
AM
12429+ *
12430+ * This program is distributed in the hope that it will be useful,
12431+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12432+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12433+ * GNU General Public License for more details.
12434+ *
12435+ * You should have received a copy of the GNU General Public License
523b37e3 12436+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 12437+ */
12438+
12439+/*
4a4d8108 12440+ * dynamically customizable operations for regular files
1facf9fc 12441+ */
12442+
1facf9fc 12443+#include "aufs.h"
12444+
4a4d8108 12445+#define DyPrSym(key) AuDbgSym(key->dk_op.dy_hop)
1facf9fc 12446+
4a4d8108
AM
12447+/*
12448+ * How large will these lists be?
12449+ * Usually just a few elements, 20-30 at most for each, I guess.
12450+ */
8b6a4947 12451+static struct hlist_bl_head dynop[AuDyLast];
4a4d8108 12452+
8b6a4947
AM
12453+static struct au_dykey *dy_gfind_get(struct hlist_bl_head *hbl,
12454+ const void *h_op)
1facf9fc 12455+{
4a4d8108 12456+ struct au_dykey *key, *tmp;
8b6a4947 12457+ struct hlist_bl_node *pos;
1facf9fc 12458+
4a4d8108 12459+ key = NULL;
8b6a4947
AM
12460+ hlist_bl_lock(hbl);
12461+ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode)
4a4d8108 12462+ if (tmp->dk_op.dy_hop == h_op) {
83b672a5
AM
12463+ if (kref_get_unless_zero(&tmp->dk_kref))
12464+ key = tmp;
4a4d8108
AM
12465+ break;
12466+ }
8b6a4947 12467+ hlist_bl_unlock(hbl);
4a4d8108
AM
12468+
12469+ return key;
1facf9fc 12470+}
12471+
4a4d8108 12472+static struct au_dykey *dy_bradd(struct au_branch *br, struct au_dykey *key)
1facf9fc 12473+{
4a4d8108
AM
12474+ struct au_dykey **k, *found;
12475+ const void *h_op = key->dk_op.dy_hop;
12476+ int i;
1facf9fc 12477+
4a4d8108
AM
12478+ found = NULL;
12479+ k = br->br_dykey;
12480+ for (i = 0; i < AuBrDynOp; i++)
12481+ if (k[i]) {
12482+ if (k[i]->dk_op.dy_hop == h_op) {
12483+ found = k[i];
12484+ break;
12485+ }
12486+ } else
12487+ break;
12488+ if (!found) {
12489+ spin_lock(&br->br_dykey_lock);
12490+ for (; i < AuBrDynOp; i++)
12491+ if (k[i]) {
12492+ if (k[i]->dk_op.dy_hop == h_op) {
12493+ found = k[i];
12494+ break;
12495+ }
12496+ } else {
12497+ k[i] = key;
12498+ break;
12499+ }
12500+ spin_unlock(&br->br_dykey_lock);
12501+ BUG_ON(i == AuBrDynOp); /* expand the array */
12502+ }
12503+
12504+ return found;
1facf9fc 12505+}
12506+
4a4d8108 12507+/* kref_get() if @key is already added */
8b6a4947 12508+static struct au_dykey *dy_gadd(struct hlist_bl_head *hbl, struct au_dykey *key)
4a4d8108
AM
12509+{
12510+ struct au_dykey *tmp, *found;
8b6a4947 12511+ struct hlist_bl_node *pos;
4a4d8108 12512+ const void *h_op = key->dk_op.dy_hop;
1facf9fc 12513+
4a4d8108 12514+ found = NULL;
8b6a4947
AM
12515+ hlist_bl_lock(hbl);
12516+ hlist_bl_for_each_entry(tmp, pos, hbl, dk_hnode)
4a4d8108 12517+ if (tmp->dk_op.dy_hop == h_op) {
83b672a5
AM
12518+ if (kref_get_unless_zero(&tmp->dk_kref))
12519+ found = tmp;
4a4d8108
AM
12520+ break;
12521+ }
12522+ if (!found)
8b6a4947
AM
12523+ hlist_bl_add_head(&key->dk_hnode, hbl);
12524+ hlist_bl_unlock(hbl);
1facf9fc 12525+
4a4d8108
AM
12526+ if (!found)
12527+ DyPrSym(key);
12528+ return found;
12529+}
12530+
12531+static void dy_free_rcu(struct rcu_head *rcu)
1facf9fc 12532+{
4a4d8108
AM
12533+ struct au_dykey *key;
12534+
12535+ key = container_of(rcu, struct au_dykey, dk_rcu);
12536+ DyPrSym(key);
83b672a5 12537+ kfree(key);
1facf9fc 12538+}
12539+
4a4d8108
AM
12540+static void dy_free(struct kref *kref)
12541+{
12542+ struct au_dykey *key;
8b6a4947 12543+ struct hlist_bl_head *hbl;
1facf9fc 12544+
4a4d8108 12545+ key = container_of(kref, struct au_dykey, dk_kref);
8b6a4947
AM
12546+ hbl = dynop + key->dk_op.dy_type;
12547+ au_hbl_del(&key->dk_hnode, hbl);
4a4d8108
AM
12548+ call_rcu(&key->dk_rcu, dy_free_rcu);
12549+}
12550+
12551+void au_dy_put(struct au_dykey *key)
1facf9fc 12552+{
4a4d8108
AM
12553+ kref_put(&key->dk_kref, dy_free);
12554+}
1facf9fc 12555+
4a4d8108
AM
12556+/* ---------------------------------------------------------------------- */
12557+
12558+#define DyDbgSize(cnt, op) AuDebugOn(cnt != sizeof(op)/sizeof(void *))
12559+
12560+#ifdef CONFIG_AUFS_DEBUG
12561+#define DyDbgDeclare(cnt) unsigned int cnt = 0
4f0767ce 12562+#define DyDbgInc(cnt) do { cnt++; } while (0)
4a4d8108
AM
12563+#else
12564+#define DyDbgDeclare(cnt) do {} while (0)
12565+#define DyDbgInc(cnt) do {} while (0)
12566+#endif
12567+
12568+#define DySet(func, dst, src, h_op, h_sb) do { \
12569+ DyDbgInc(cnt); \
12570+ if (h_op->func) { \
12571+ if (src.func) \
12572+ dst.func = src.func; \
12573+ else \
12574+ AuDbg("%s %s\n", au_sbtype(h_sb), #func); \
12575+ } \
12576+} while (0)
12577+
12578+#define DySetForce(func, dst, src) do { \
12579+ AuDebugOn(!src.func); \
12580+ DyDbgInc(cnt); \
12581+ dst.func = src.func; \
12582+} while (0)
12583+
12584+#define DySetAop(func) \
12585+ DySet(func, dyaop->da_op, aufs_aop, h_aop, h_sb)
12586+#define DySetAopForce(func) \
12587+ DySetForce(func, dyaop->da_op, aufs_aop)
12588+
12589+static void dy_aop(struct au_dykey *key, const void *h_op,
12590+ struct super_block *h_sb __maybe_unused)
12591+{
12592+ struct au_dyaop *dyaop = (void *)key;
12593+ const struct address_space_operations *h_aop = h_op;
12594+ DyDbgDeclare(cnt);
12595+
12596+ AuDbg("%s\n", au_sbtype(h_sb));
12597+
12598+ DySetAop(writepage);
12599+ DySetAopForce(readpage); /* force */
4a4d8108
AM
12600+ DySetAop(writepages);
12601+ DySetAop(set_page_dirty);
12602+ DySetAop(readpages);
12603+ DySetAop(write_begin);
12604+ DySetAop(write_end);
12605+ DySetAop(bmap);
12606+ DySetAop(invalidatepage);
12607+ DySetAop(releasepage);
027c5e7a 12608+ DySetAop(freepage);
7e9cd9fe 12609+ /* this one will be changed according to an aufs mount option */
4a4d8108 12610+ DySetAop(direct_IO);
4a4d8108 12611+ DySetAop(migratepage);
e2f27e51
AM
12612+ DySetAop(isolate_page);
12613+ DySetAop(putback_page);
4a4d8108
AM
12614+ DySetAop(launder_page);
12615+ DySetAop(is_partially_uptodate);
392086de 12616+ DySetAop(is_dirty_writeback);
4a4d8108 12617+ DySetAop(error_remove_page);
b4510431
AM
12618+ DySetAop(swap_activate);
12619+ DySetAop(swap_deactivate);
4a4d8108
AM
12620+
12621+ DyDbgSize(cnt, *h_aop);
4a4d8108
AM
12622+}
12623+
4a4d8108
AM
12624+/* ---------------------------------------------------------------------- */
12625+
12626+static void dy_bug(struct kref *kref)
12627+{
12628+ BUG();
12629+}
12630+
12631+static struct au_dykey *dy_get(struct au_dynop *op, struct au_branch *br)
12632+{
12633+ struct au_dykey *key, *old;
8b6a4947 12634+ struct hlist_bl_head *hbl;
b752ccd1 12635+ struct op {
4a4d8108 12636+ unsigned int sz;
b752ccd1
AM
12637+ void (*set)(struct au_dykey *key, const void *h_op,
12638+ struct super_block *h_sb __maybe_unused);
12639+ };
12640+ static const struct op a[] = {
4a4d8108
AM
12641+ [AuDy_AOP] = {
12642+ .sz = sizeof(struct au_dyaop),
b752ccd1 12643+ .set = dy_aop
4a4d8108 12644+ }
b752ccd1
AM
12645+ };
12646+ const struct op *p;
4a4d8108 12647+
8b6a4947
AM
12648+ hbl = dynop + op->dy_type;
12649+ key = dy_gfind_get(hbl, op->dy_hop);
4a4d8108
AM
12650+ if (key)
12651+ goto out_add; /* success */
12652+
12653+ p = a + op->dy_type;
12654+ key = kzalloc(p->sz, GFP_NOFS);
12655+ if (unlikely(!key)) {
12656+ key = ERR_PTR(-ENOMEM);
12657+ goto out;
12658+ }
12659+
12660+ key->dk_op.dy_hop = op->dy_hop;
12661+ kref_init(&key->dk_kref);
86dc4139 12662+ p->set(key, op->dy_hop, au_br_sb(br));
8b6a4947 12663+ old = dy_gadd(hbl, key);
4a4d8108 12664+ if (old) {
9f237c51 12665+ au_kfree_rcu(key);
4a4d8108
AM
12666+ key = old;
12667+ }
12668+
12669+out_add:
12670+ old = dy_bradd(br, key);
12671+ if (old)
12672+ /* its ref-count should never be zero here */
12673+ kref_put(&key->dk_kref, dy_bug);
12674+out:
12675+ return key;
12676+}
12677+
12678+/* ---------------------------------------------------------------------- */
12679+/*
acd2b654 12680+ * Aufs prohibits O_DIRECT by default even if the branch supports it.
c1595e42 12681+ * This behaviour is necessary to return an error from open(O_DIRECT) instead
4a4d8108
AM
12682+ * of the succeeding I/O. The dio mount option enables O_DIRECT and makes
12683+ * open(O_DIRECT) always succeed, but the succeeding I/O may return an error.
12684+ * See the aufs manual in detail.
4a4d8108
AM
12685+ */
12686+static void dy_adx(struct au_dyaop *dyaop, int do_dx)
12687+{
7e9cd9fe 12688+ if (!do_dx)
4a4d8108 12689+ dyaop->da_op.direct_IO = NULL;
7e9cd9fe 12690+ else
4a4d8108 12691+ dyaop->da_op.direct_IO = aufs_aop.direct_IO;
4a4d8108
AM
12692+}
12693+
12694+static struct au_dyaop *dy_aget(struct au_branch *br,
12695+ const struct address_space_operations *h_aop,
12696+ int do_dx)
12697+{
12698+ struct au_dyaop *dyaop;
12699+ struct au_dynop op;
12700+
12701+ op.dy_type = AuDy_AOP;
12702+ op.dy_haop = h_aop;
12703+ dyaop = (void *)dy_get(&op, br);
12704+ if (IS_ERR(dyaop))
12705+ goto out;
12706+ dy_adx(dyaop, do_dx);
12707+
12708+out:
12709+ return dyaop;
12710+}
12711+
12712+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
12713+ struct inode *h_inode)
12714+{
12715+ int err, do_dx;
12716+ struct super_block *sb;
12717+ struct au_branch *br;
12718+ struct au_dyaop *dyaop;
12719+
12720+ AuDebugOn(!S_ISREG(h_inode->i_mode));
12721+ IiMustWriteLock(inode);
12722+
12723+ sb = inode->i_sb;
12724+ br = au_sbr(sb, bindex);
12725+ do_dx = !!au_opt_test(au_mntflags(sb), DIO);
12726+ dyaop = dy_aget(br, h_inode->i_mapping->a_ops, do_dx);
12727+ err = PTR_ERR(dyaop);
12728+ if (IS_ERR(dyaop))
12729+ /* unnecessary to call dy_fput() */
12730+ goto out;
12731+
12732+ err = 0;
12733+ inode->i_mapping->a_ops = &dyaop->da_op;
12734+
12735+out:
12736+ return err;
12737+}
12738+
b752ccd1
AM
12739+/*
12740+ * Is it safe to replace a_ops during the inode/file is in operation?
12741+ * Yes, I hope so.
12742+ */
12743+int au_dy_irefresh(struct inode *inode)
12744+{
12745+ int err;
5afbbe0d 12746+ aufs_bindex_t btop;
b752ccd1
AM
12747+ struct inode *h_inode;
12748+
12749+ err = 0;
12750+ if (S_ISREG(inode->i_mode)) {
5afbbe0d
AM
12751+ btop = au_ibtop(inode);
12752+ h_inode = au_h_iptr(inode, btop);
12753+ err = au_dy_iaop(inode, btop, h_inode);
b752ccd1
AM
12754+ }
12755+ return err;
12756+}
12757+
4a4d8108
AM
12758+void au_dy_arefresh(int do_dx)
12759+{
8b6a4947
AM
12760+ struct hlist_bl_head *hbl;
12761+ struct hlist_bl_node *pos;
4a4d8108
AM
12762+ struct au_dykey *key;
12763+
8b6a4947
AM
12764+ hbl = dynop + AuDy_AOP;
12765+ hlist_bl_lock(hbl);
12766+ hlist_bl_for_each_entry(key, pos, hbl, dk_hnode)
4a4d8108 12767+ dy_adx((void *)key, do_dx);
8b6a4947 12768+ hlist_bl_unlock(hbl);
4a4d8108
AM
12769+}
12770+
4a4d8108
AM
12771+/* ---------------------------------------------------------------------- */
12772+
12773+void __init au_dy_init(void)
12774+{
12775+ int i;
12776+
4a4d8108 12777+ for (i = 0; i < AuDyLast; i++)
8b6a4947 12778+ INIT_HLIST_BL_HEAD(dynop + i);
4a4d8108
AM
12779+}
12780+
12781+void au_dy_fin(void)
12782+{
12783+ int i;
12784+
12785+ for (i = 0; i < AuDyLast; i++)
8b6a4947 12786+ WARN_ON(!hlist_bl_empty(dynop + i));
4a4d8108 12787+}
7f207e10 12788diff -urN /usr/share/empty/fs/aufs/dynop.h linux/fs/aufs/dynop.h
eca34b5c 12789--- /usr/share/empty/fs/aufs/dynop.h 1970-01-01 01:00:00.000000000 +0100
016522bc 12790+++ linux/fs/aufs/dynop.h 2020-01-27 10:57:18.168871450 +0100
fbc438ed 12791@@ -0,0 +1,77 @@
062440b3 12792+/* SPDX-License-Identifier: GPL-2.0 */
4a4d8108 12793+/*
016522bc 12794+ * Copyright (C) 2010-2020 Junjiro R. Okajima
4a4d8108
AM
12795+ *
12796+ * This program, aufs is free software; you can redistribute it and/or modify
12797+ * it under the terms of the GNU General Public License as published by
12798+ * the Free Software Foundation; either version 2 of the License, or
12799+ * (at your option) any later version.
12800+ *
12801+ * This program is distributed in the hope that it will be useful,
12802+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12803+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12804+ * GNU General Public License for more details.
12805+ *
12806+ * You should have received a copy of the GNU General Public License
523b37e3 12807+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
12808+ */
12809+
12810+/*
12811+ * dynamically customizable operations (for regular files only)
12812+ */
12813+
12814+#ifndef __AUFS_DYNOP_H__
12815+#define __AUFS_DYNOP_H__
12816+
12817+#ifdef __KERNEL__
12818+
7e9cd9fe
AM
12819+#include <linux/fs.h>
12820+#include <linux/kref.h>
4a4d8108 12821+
2cbb1c4b 12822+enum {AuDy_AOP, AuDyLast};
4a4d8108
AM
12823+
12824+struct au_dynop {
12825+ int dy_type;
12826+ union {
12827+ const void *dy_hop;
12828+ const struct address_space_operations *dy_haop;
4a4d8108
AM
12829+ };
12830+};
12831+
12832+struct au_dykey {
12833+ union {
8b6a4947 12834+ struct hlist_bl_node dk_hnode;
4a4d8108
AM
12835+ struct rcu_head dk_rcu;
12836+ };
12837+ struct au_dynop dk_op;
12838+
12839+ /*
12840+ * during I am in the branch local array, kref is gotten. when the
12841+ * branch is removed, kref is put.
12842+ */
12843+ struct kref dk_kref;
12844+};
12845+
12846+/* stop unioning since their sizes are very different from each other */
12847+struct au_dyaop {
12848+ struct au_dykey da_key;
12849+ struct address_space_operations da_op; /* not const */
4a4d8108 12850+};
fbc438ed
JR
12851+/* make sure that 'struct au_dykey *' can be any type */
12852+static_assert(!offsetof(struct au_dyaop, da_key));
4a4d8108 12853+
4a4d8108
AM
12854+/* ---------------------------------------------------------------------- */
12855+
12856+/* dynop.c */
12857+struct au_branch;
12858+void au_dy_put(struct au_dykey *key);
12859+int au_dy_iaop(struct inode *inode, aufs_bindex_t bindex,
12860+ struct inode *h_inode);
b752ccd1 12861+int au_dy_irefresh(struct inode *inode);
4a4d8108 12862+void au_dy_arefresh(int do_dio);
4a4d8108
AM
12863+
12864+void __init au_dy_init(void);
12865+void au_dy_fin(void);
12866+
4a4d8108
AM
12867+#endif /* __KERNEL__ */
12868+#endif /* __AUFS_DYNOP_H__ */
7f207e10 12869diff -urN /usr/share/empty/fs/aufs/export.c linux/fs/aufs/export.c
eca34b5c 12870--- /usr/share/empty/fs/aufs/export.c 1970-01-01 01:00:00.000000000 +0100
016522bc 12871+++ linux/fs/aufs/export.c 2020-01-27 10:57:18.168871450 +0100
062440b3 12872@@ -0,0 +1,838 @@
cd7a4cd9 12873+// SPDX-License-Identifier: GPL-2.0
4a4d8108 12874+/*
016522bc 12875+ * Copyright (C) 2005-2020 Junjiro R. Okajima
4a4d8108
AM
12876+ *
12877+ * This program, aufs is free software; you can redistribute it and/or modify
12878+ * it under the terms of the GNU General Public License as published by
12879+ * the Free Software Foundation; either version 2 of the License, or
12880+ * (at your option) any later version.
12881+ *
12882+ * This program is distributed in the hope that it will be useful,
12883+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12884+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12885+ * GNU General Public License for more details.
12886+ *
12887+ * You should have received a copy of the GNU General Public License
523b37e3 12888+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
12889+ */
12890+
12891+/*
12892+ * export via nfs
12893+ */
12894+
12895+#include <linux/exportfs.h>
7eafdf33 12896+#include <linux/fs_struct.h>
4a4d8108
AM
12897+#include <linux/namei.h>
12898+#include <linux/nsproxy.h>
12899+#include <linux/random.h>
12900+#include <linux/writeback.h>
12901+#include "aufs.h"
12902+
12903+union conv {
12904+#ifdef CONFIG_AUFS_INO_T_64
12905+ __u32 a[2];
12906+#else
12907+ __u32 a[1];
12908+#endif
12909+ ino_t ino;
12910+};
12911+
12912+static ino_t decode_ino(__u32 *a)
12913+{
12914+ union conv u;
12915+
12916+ BUILD_BUG_ON(sizeof(u.ino) != sizeof(u.a));
12917+ u.a[0] = a[0];
12918+#ifdef CONFIG_AUFS_INO_T_64
12919+ u.a[1] = a[1];
12920+#endif
12921+ return u.ino;
12922+}
12923+
12924+static void encode_ino(__u32 *a, ino_t ino)
12925+{
12926+ union conv u;
12927+
12928+ u.ino = ino;
12929+ a[0] = u.a[0];
12930+#ifdef CONFIG_AUFS_INO_T_64
12931+ a[1] = u.a[1];
12932+#endif
12933+}
12934+
12935+/* NFS file handle */
12936+enum {
12937+ Fh_br_id,
12938+ Fh_sigen,
12939+#ifdef CONFIG_AUFS_INO_T_64
12940+ /* support 64bit inode number */
12941+ Fh_ino1,
12942+ Fh_ino2,
12943+ Fh_dir_ino1,
12944+ Fh_dir_ino2,
12945+#else
12946+ Fh_ino1,
12947+ Fh_dir_ino1,
12948+#endif
12949+ Fh_igen,
12950+ Fh_h_type,
12951+ Fh_tail,
12952+
12953+ Fh_ino = Fh_ino1,
12954+ Fh_dir_ino = Fh_dir_ino1
12955+};
12956+
12957+static int au_test_anon(struct dentry *dentry)
12958+{
027c5e7a 12959+ /* note: read d_flags without d_lock */
4a4d8108
AM
12960+ return !!(dentry->d_flags & DCACHE_DISCONNECTED);
12961+}
12962+
a2a7ad62
AM
12963+int au_test_nfsd(void)
12964+{
12965+ int ret;
12966+ struct task_struct *tsk = current;
12967+ char comm[sizeof(tsk->comm)];
12968+
12969+ ret = 0;
12970+ if (tsk->flags & PF_KTHREAD) {
12971+ get_task_comm(comm, tsk);
12972+ ret = !strcmp(comm, "nfsd");
12973+ }
12974+
12975+ return ret;
12976+}
12977+
4a4d8108
AM
12978+/* ---------------------------------------------------------------------- */
12979+/* inode generation external table */
12980+
b752ccd1 12981+void au_xigen_inc(struct inode *inode)
4a4d8108 12982+{
4a4d8108
AM
12983+ loff_t pos;
12984+ ssize_t sz;
12985+ __u32 igen;
12986+ struct super_block *sb;
12987+ struct au_sbinfo *sbinfo;
12988+
4a4d8108 12989+ sb = inode->i_sb;
b752ccd1 12990+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
1facf9fc 12991+
b752ccd1 12992+ sbinfo = au_sbi(sb);
1facf9fc 12993+ pos = inode->i_ino;
12994+ pos *= sizeof(igen);
12995+ igen = inode->i_generation + 1;
1facf9fc 12996+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xigen, &igen,
12997+ sizeof(igen), &pos);
12998+ if (sz == sizeof(igen))
b752ccd1 12999+ return; /* success */
1facf9fc 13000+
b752ccd1 13001+ if (unlikely(sz >= 0))
1facf9fc 13002+ AuIOErr("xigen error (%zd)\n", sz);
1facf9fc 13003+}
13004+
13005+int au_xigen_new(struct inode *inode)
13006+{
13007+ int err;
13008+ loff_t pos;
13009+ ssize_t sz;
13010+ struct super_block *sb;
13011+ struct au_sbinfo *sbinfo;
13012+ struct file *file;
13013+
13014+ err = 0;
13015+ /* todo: dirty, at mount time */
13016+ if (inode->i_ino == AUFS_ROOT_INO)
13017+ goto out;
13018+ sb = inode->i_sb;
dece6358 13019+ SiMustAnyLock(sb);
1facf9fc 13020+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
13021+ goto out;
13022+
13023+ err = -EFBIG;
13024+ pos = inode->i_ino;
13025+ if (unlikely(au_loff_max / sizeof(inode->i_generation) - 1 < pos)) {
13026+ AuIOErr1("too large i%lld\n", pos);
13027+ goto out;
13028+ }
13029+ pos *= sizeof(inode->i_generation);
13030+
13031+ err = 0;
13032+ sbinfo = au_sbi(sb);
13033+ file = sbinfo->si_xigen;
13034+ BUG_ON(!file);
13035+
c06a8ce3 13036+ if (vfsub_f_size_read(file)
1facf9fc 13037+ < pos + sizeof(inode->i_generation)) {
13038+ inode->i_generation = atomic_inc_return(&sbinfo->si_xigen_next);
13039+ sz = xino_fwrite(sbinfo->si_xwrite, file, &inode->i_generation,
13040+ sizeof(inode->i_generation), &pos);
13041+ } else
13042+ sz = xino_fread(sbinfo->si_xread, file, &inode->i_generation,
13043+ sizeof(inode->i_generation), &pos);
13044+ if (sz == sizeof(inode->i_generation))
13045+ goto out; /* success */
13046+
13047+ err = sz;
13048+ if (unlikely(sz >= 0)) {
13049+ err = -EIO;
13050+ AuIOErr("xigen error (%zd)\n", sz);
13051+ }
13052+
4f0767ce 13053+out:
1facf9fc 13054+ return err;
13055+}
13056+
062440b3 13057+int au_xigen_set(struct super_block *sb, struct path *path)
1facf9fc 13058+{
13059+ int err;
13060+ struct au_sbinfo *sbinfo;
13061+ struct file *file;
13062+
dece6358
AM
13063+ SiMustWriteLock(sb);
13064+
1facf9fc 13065+ sbinfo = au_sbi(sb);
062440b3 13066+ file = au_xino_create2(sb, path, sbinfo->si_xigen);
1facf9fc 13067+ err = PTR_ERR(file);
13068+ if (IS_ERR(file))
13069+ goto out;
13070+ err = 0;
13071+ if (sbinfo->si_xigen)
13072+ fput(sbinfo->si_xigen);
13073+ sbinfo->si_xigen = file;
13074+
4f0767ce 13075+out:
062440b3 13076+ AuTraceErr(err);
1facf9fc 13077+ return err;
13078+}
13079+
13080+void au_xigen_clr(struct super_block *sb)
13081+{
13082+ struct au_sbinfo *sbinfo;
13083+
dece6358
AM
13084+ SiMustWriteLock(sb);
13085+
1facf9fc 13086+ sbinfo = au_sbi(sb);
13087+ if (sbinfo->si_xigen) {
13088+ fput(sbinfo->si_xigen);
13089+ sbinfo->si_xigen = NULL;
13090+ }
13091+}
13092+
13093+/* ---------------------------------------------------------------------- */
13094+
13095+static struct dentry *decode_by_ino(struct super_block *sb, ino_t ino,
13096+ ino_t dir_ino)
13097+{
13098+ struct dentry *dentry, *d;
13099+ struct inode *inode;
13100+ unsigned int sigen;
13101+
13102+ dentry = NULL;
13103+ inode = ilookup(sb, ino);
13104+ if (!inode)
13105+ goto out;
13106+
13107+ dentry = ERR_PTR(-ESTALE);
13108+ sigen = au_sigen(sb);
5afbbe0d 13109+ if (unlikely(au_is_bad_inode(inode)
1facf9fc 13110+ || IS_DEADDIR(inode)
537831f9 13111+ || sigen != au_iigen(inode, NULL)))
1facf9fc 13112+ goto out_iput;
13113+
13114+ dentry = NULL;
13115+ if (!dir_ino || S_ISDIR(inode->i_mode))
13116+ dentry = d_find_alias(inode);
13117+ else {
027c5e7a 13118+ spin_lock(&inode->i_lock);
c1595e42 13119+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) {
027c5e7a 13120+ spin_lock(&d->d_lock);
1facf9fc 13121+ if (!au_test_anon(d)
5527c038 13122+ && d_inode(d->d_parent)->i_ino == dir_ino) {
027c5e7a
AM
13123+ dentry = dget_dlock(d);
13124+ spin_unlock(&d->d_lock);
1facf9fc 13125+ break;
13126+ }
027c5e7a
AM
13127+ spin_unlock(&d->d_lock);
13128+ }
13129+ spin_unlock(&inode->i_lock);
1facf9fc 13130+ }
027c5e7a 13131+ if (unlikely(dentry && au_digen_test(dentry, sigen))) {
2cbb1c4b 13132+ /* need to refresh */
1facf9fc 13133+ dput(dentry);
2cbb1c4b 13134+ dentry = NULL;
1facf9fc 13135+ }
13136+
4f0767ce 13137+out_iput:
1facf9fc 13138+ iput(inode);
4f0767ce 13139+out:
2cbb1c4b 13140+ AuTraceErrPtr(dentry);
1facf9fc 13141+ return dentry;
13142+}
13143+
13144+/* ---------------------------------------------------------------------- */
13145+
13146+/* todo: dirty? */
13147+/* if exportfs_decode_fh() passed vfsmount*, we could be happy */
4a4d8108
AM
13148+
13149+struct au_compare_mnt_args {
13150+ /* input */
13151+ struct super_block *sb;
13152+
13153+ /* output */
13154+ struct vfsmount *mnt;
13155+};
13156+
13157+static int au_compare_mnt(struct vfsmount *mnt, void *arg)
13158+{
13159+ struct au_compare_mnt_args *a = arg;
13160+
13161+ if (mnt->mnt_sb != a->sb)
13162+ return 0;
13163+ a->mnt = mntget(mnt);
13164+ return 1;
13165+}
13166+
1facf9fc 13167+static struct vfsmount *au_mnt_get(struct super_block *sb)
13168+{
4a4d8108 13169+ int err;
7eafdf33 13170+ struct path root;
4a4d8108
AM
13171+ struct au_compare_mnt_args args = {
13172+ .sb = sb
13173+ };
1facf9fc 13174+
7eafdf33 13175+ get_fs_root(current->fs, &root);
523b37e3 13176+ rcu_read_lock();
7eafdf33 13177+ err = iterate_mounts(au_compare_mnt, &args, root.mnt);
523b37e3 13178+ rcu_read_unlock();
7eafdf33 13179+ path_put(&root);
4a4d8108
AM
13180+ AuDebugOn(!err);
13181+ AuDebugOn(!args.mnt);
13182+ return args.mnt;
1facf9fc 13183+}
13184+
13185+struct au_nfsd_si_lock {
4a4d8108 13186+ unsigned int sigen;
027c5e7a 13187+ aufs_bindex_t bindex, br_id;
1facf9fc 13188+ unsigned char force_lock;
13189+};
13190+
027c5e7a
AM
13191+static int si_nfsd_read_lock(struct super_block *sb,
13192+ struct au_nfsd_si_lock *nsi_lock)
1facf9fc 13193+{
027c5e7a 13194+ int err;
1facf9fc 13195+ aufs_bindex_t bindex;
13196+
13197+ si_read_lock(sb, AuLock_FLUSH);
13198+
13199+ /* branch id may be wrapped around */
027c5e7a 13200+ err = 0;
1facf9fc 13201+ bindex = au_br_index(sb, nsi_lock->br_id);
13202+ if (bindex >= 0 && nsi_lock->sigen + AUFS_BRANCH_MAX > au_sigen(sb))
13203+ goto out; /* success */
13204+
027c5e7a
AM
13205+ err = -ESTALE;
13206+ bindex = -1;
1facf9fc 13207+ if (!nsi_lock->force_lock)
13208+ si_read_unlock(sb);
1facf9fc 13209+
4f0767ce 13210+out:
027c5e7a
AM
13211+ nsi_lock->bindex = bindex;
13212+ return err;
1facf9fc 13213+}
13214+
13215+struct find_name_by_ino {
392086de 13216+ struct dir_context ctx;
1facf9fc 13217+ int called, found;
13218+ ino_t ino;
13219+ char *name;
13220+ int namelen;
13221+};
13222+
13223+static int
392086de
AM
13224+find_name_by_ino(struct dir_context *ctx, const char *name, int namelen,
13225+ loff_t offset, u64 ino, unsigned int d_type)
1facf9fc 13226+{
392086de
AM
13227+ struct find_name_by_ino *a = container_of(ctx, struct find_name_by_ino,
13228+ ctx);
1facf9fc 13229+
13230+ a->called++;
13231+ if (a->ino != ino)
13232+ return 0;
13233+
13234+ memcpy(a->name, name, namelen);
13235+ a->namelen = namelen;
13236+ a->found = 1;
13237+ return 1;
13238+}
13239+
13240+static struct dentry *au_lkup_by_ino(struct path *path, ino_t ino,
13241+ struct au_nfsd_si_lock *nsi_lock)
13242+{
13243+ struct dentry *dentry, *parent;
13244+ struct file *file;
13245+ struct inode *dir;
392086de
AM
13246+ struct find_name_by_ino arg = {
13247+ .ctx = {
2000de60 13248+ .actor = find_name_by_ino
392086de
AM
13249+ }
13250+ };
1facf9fc 13251+ int err;
13252+
13253+ parent = path->dentry;
13254+ if (nsi_lock)
13255+ si_read_unlock(parent->d_sb);
4a4d8108 13256+ file = vfsub_dentry_open(path, au_dir_roflags);
1facf9fc 13257+ dentry = (void *)file;
13258+ if (IS_ERR(file))
13259+ goto out;
13260+
13261+ dentry = ERR_PTR(-ENOMEM);
537831f9 13262+ arg.name = (void *)__get_free_page(GFP_NOFS);
1facf9fc 13263+ if (unlikely(!arg.name))
13264+ goto out_file;
13265+ arg.ino = ino;
13266+ arg.found = 0;
13267+ do {
13268+ arg.called = 0;
13269+ /* smp_mb(); */
392086de 13270+ err = vfsub_iterate_dir(file, &arg.ctx);
1facf9fc 13271+ } while (!err && !arg.found && arg.called);
13272+ dentry = ERR_PTR(err);
13273+ if (unlikely(err))
13274+ goto out_name;
1716fcea
AM
13275+ /* instead of ENOENT */
13276+ dentry = ERR_PTR(-ESTALE);
1facf9fc 13277+ if (!arg.found)
13278+ goto out_name;
13279+
b4510431 13280+ /* do not call vfsub_lkup_one() */
5527c038 13281+ dir = d_inode(parent);
febd17d6 13282+ dentry = vfsub_lookup_one_len_unlocked(arg.name, parent, arg.namelen);
1facf9fc 13283+ AuTraceErrPtr(dentry);
13284+ if (IS_ERR(dentry))
13285+ goto out_name;
13286+ AuDebugOn(au_test_anon(dentry));
5527c038 13287+ if (unlikely(d_really_is_negative(dentry))) {
1facf9fc 13288+ dput(dentry);
13289+ dentry = ERR_PTR(-ENOENT);
13290+ }
13291+
4f0767ce 13292+out_name:
1c60b727 13293+ free_page((unsigned long)arg.name);
4f0767ce 13294+out_file:
1facf9fc 13295+ fput(file);
4f0767ce 13296+out:
1facf9fc 13297+ if (unlikely(nsi_lock
13298+ && si_nfsd_read_lock(parent->d_sb, nsi_lock) < 0))
13299+ if (!IS_ERR(dentry)) {
13300+ dput(dentry);
13301+ dentry = ERR_PTR(-ESTALE);
13302+ }
13303+ AuTraceErrPtr(dentry);
13304+ return dentry;
13305+}
13306+
13307+static struct dentry *decode_by_dir_ino(struct super_block *sb, ino_t ino,
13308+ ino_t dir_ino,
13309+ struct au_nfsd_si_lock *nsi_lock)
13310+{
13311+ struct dentry *dentry;
13312+ struct path path;
13313+
13314+ if (dir_ino != AUFS_ROOT_INO) {
13315+ path.dentry = decode_by_ino(sb, dir_ino, 0);
13316+ dentry = path.dentry;
13317+ if (!path.dentry || IS_ERR(path.dentry))
13318+ goto out;
13319+ AuDebugOn(au_test_anon(path.dentry));
13320+ } else
13321+ path.dentry = dget(sb->s_root);
13322+
13323+ path.mnt = au_mnt_get(sb);
13324+ dentry = au_lkup_by_ino(&path, ino, nsi_lock);
13325+ path_put(&path);
13326+
4f0767ce 13327+out:
1facf9fc 13328+ AuTraceErrPtr(dentry);
13329+ return dentry;
13330+}
13331+
13332+/* ---------------------------------------------------------------------- */
13333+
13334+static int h_acceptable(void *expv, struct dentry *dentry)
13335+{
13336+ return 1;
13337+}
13338+
13339+static char *au_build_path(struct dentry *h_parent, struct path *h_rootpath,
13340+ char *buf, int len, struct super_block *sb)
13341+{
13342+ char *p;
13343+ int n;
13344+ struct path path;
13345+
13346+ p = d_path(h_rootpath, buf, len);
13347+ if (IS_ERR(p))
13348+ goto out;
13349+ n = strlen(p);
13350+
13351+ path.mnt = h_rootpath->mnt;
13352+ path.dentry = h_parent;
13353+ p = d_path(&path, buf, len);
13354+ if (IS_ERR(p))
13355+ goto out;
13356+ if (n != 1)
13357+ p += n;
13358+
13359+ path.mnt = au_mnt_get(sb);
13360+ path.dentry = sb->s_root;
13361+ p = d_path(&path, buf, len - strlen(p));
13362+ mntput(path.mnt);
13363+ if (IS_ERR(p))
13364+ goto out;
13365+ if (n != 1)
13366+ p[strlen(p)] = '/';
13367+
4f0767ce 13368+out:
1facf9fc 13369+ AuTraceErrPtr(p);
13370+ return p;
13371+}
13372+
13373+static
027c5e7a
AM
13374+struct dentry *decode_by_path(struct super_block *sb, ino_t ino, __u32 *fh,
13375+ int fh_len, struct au_nfsd_si_lock *nsi_lock)
1facf9fc 13376+{
13377+ struct dentry *dentry, *h_parent, *root;
13378+ struct super_block *h_sb;
13379+ char *pathname, *p;
13380+ struct vfsmount *h_mnt;
13381+ struct au_branch *br;
13382+ int err;
13383+ struct path path;
13384+
027c5e7a 13385+ br = au_sbr(sb, nsi_lock->bindex);
86dc4139 13386+ h_mnt = au_br_mnt(br);
1facf9fc 13387+ h_sb = h_mnt->mnt_sb;
13388+ /* todo: call lower fh_to_dentry()? fh_to_parent()? */
5afbbe0d 13389+ lockdep_off();
1facf9fc 13390+ h_parent = exportfs_decode_fh(h_mnt, (void *)(fh + Fh_tail),
13391+ fh_len - Fh_tail, fh[Fh_h_type],
13392+ h_acceptable, /*context*/NULL);
5afbbe0d 13393+ lockdep_on();
1facf9fc 13394+ dentry = h_parent;
13395+ if (unlikely(!h_parent || IS_ERR(h_parent))) {
13396+ AuWarn1("%s decode_fh failed, %ld\n",
13397+ au_sbtype(h_sb), PTR_ERR(h_parent));
13398+ goto out;
13399+ }
13400+ dentry = NULL;
13401+ if (unlikely(au_test_anon(h_parent))) {
13402+ AuWarn1("%s decode_fh returned a disconnected dentry\n",
13403+ au_sbtype(h_sb));
13404+ goto out_h_parent;
13405+ }
13406+
13407+ dentry = ERR_PTR(-ENOMEM);
13408+ pathname = (void *)__get_free_page(GFP_NOFS);
13409+ if (unlikely(!pathname))
13410+ goto out_h_parent;
13411+
13412+ root = sb->s_root;
13413+ path.mnt = h_mnt;
13414+ di_read_lock_parent(root, !AuLock_IR);
027c5e7a 13415+ path.dentry = au_h_dptr(root, nsi_lock->bindex);
1facf9fc 13416+ di_read_unlock(root, !AuLock_IR);
13417+ p = au_build_path(h_parent, &path, pathname, PAGE_SIZE, sb);
13418+ dentry = (void *)p;
13419+ if (IS_ERR(p))
13420+ goto out_pathname;
13421+
13422+ si_read_unlock(sb);
13423+ err = vfsub_kern_path(p, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path);
13424+ dentry = ERR_PTR(err);
13425+ if (unlikely(err))
13426+ goto out_relock;
13427+
13428+ dentry = ERR_PTR(-ENOENT);
13429+ AuDebugOn(au_test_anon(path.dentry));
5527c038 13430+ if (unlikely(d_really_is_negative(path.dentry)))
1facf9fc 13431+ goto out_path;
13432+
5527c038 13433+ if (ino != d_inode(path.dentry)->i_ino)
1facf9fc 13434+ dentry = au_lkup_by_ino(&path, ino, /*nsi_lock*/NULL);
13435+ else
13436+ dentry = dget(path.dentry);
13437+
4f0767ce 13438+out_path:
1facf9fc 13439+ path_put(&path);
4f0767ce 13440+out_relock:
1facf9fc 13441+ if (unlikely(si_nfsd_read_lock(sb, nsi_lock) < 0))
13442+ if (!IS_ERR(dentry)) {
13443+ dput(dentry);
13444+ dentry = ERR_PTR(-ESTALE);
13445+ }
4f0767ce 13446+out_pathname:
1c60b727 13447+ free_page((unsigned long)pathname);
4f0767ce 13448+out_h_parent:
1facf9fc 13449+ dput(h_parent);
4f0767ce 13450+out:
1facf9fc 13451+ AuTraceErrPtr(dentry);
13452+ return dentry;
13453+}
13454+
13455+/* ---------------------------------------------------------------------- */
13456+
13457+static struct dentry *
13458+aufs_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len,
13459+ int fh_type)
13460+{
13461+ struct dentry *dentry;
13462+ __u32 *fh = fid->raw;
027c5e7a 13463+ struct au_branch *br;
1facf9fc 13464+ ino_t ino, dir_ino;
1facf9fc 13465+ struct au_nfsd_si_lock nsi_lock = {
1facf9fc 13466+ .force_lock = 0
13467+ };
13468+
1facf9fc 13469+ dentry = ERR_PTR(-ESTALE);
4a4d8108
AM
13470+ /* it should never happen, but the file handle is unreliable */
13471+ if (unlikely(fh_len < Fh_tail))
13472+ goto out;
13473+ nsi_lock.sigen = fh[Fh_sigen];
13474+ nsi_lock.br_id = fh[Fh_br_id];
13475+
1facf9fc 13476+ /* branch id may be wrapped around */
027c5e7a
AM
13477+ br = NULL;
13478+ if (unlikely(si_nfsd_read_lock(sb, &nsi_lock)))
1facf9fc 13479+ goto out;
13480+ nsi_lock.force_lock = 1;
13481+
13482+ /* is this inode still cached? */
13483+ ino = decode_ino(fh + Fh_ino);
4a4d8108
AM
13484+ /* it should never happen */
13485+ if (unlikely(ino == AUFS_ROOT_INO))
8cdd5066 13486+ goto out_unlock;
4a4d8108 13487+
1facf9fc 13488+ dir_ino = decode_ino(fh + Fh_dir_ino);
13489+ dentry = decode_by_ino(sb, ino, dir_ino);
13490+ if (IS_ERR(dentry))
13491+ goto out_unlock;
13492+ if (dentry)
13493+ goto accept;
13494+
13495+ /* is the parent dir cached? */
027c5e7a 13496+ br = au_sbr(sb, nsi_lock.bindex);
acd2b654 13497+ au_lcnt_inc(&br->br_nfiles);
1facf9fc 13498+ dentry = decode_by_dir_ino(sb, ino, dir_ino, &nsi_lock);
13499+ if (IS_ERR(dentry))
13500+ goto out_unlock;
13501+ if (dentry)
13502+ goto accept;
13503+
13504+ /* lookup path */
027c5e7a 13505+ dentry = decode_by_path(sb, ino, fh, fh_len, &nsi_lock);
1facf9fc 13506+ if (IS_ERR(dentry))
13507+ goto out_unlock;
13508+ if (unlikely(!dentry))
13509+ /* todo?: make it ESTALE */
13510+ goto out_unlock;
13511+
4f0767ce 13512+accept:
027c5e7a 13513+ if (!au_digen_test(dentry, au_sigen(sb))
5527c038 13514+ && d_inode(dentry)->i_generation == fh[Fh_igen])
1facf9fc 13515+ goto out_unlock; /* success */
13516+
13517+ dput(dentry);
13518+ dentry = ERR_PTR(-ESTALE);
4f0767ce 13519+out_unlock:
027c5e7a 13520+ if (br)
acd2b654 13521+ au_lcnt_dec(&br->br_nfiles);
1facf9fc 13522+ si_read_unlock(sb);
4f0767ce 13523+out:
1facf9fc 13524+ AuTraceErrPtr(dentry);
13525+ return dentry;
13526+}
13527+
13528+#if 0 /* reserved for future use */
13529+/* support subtreecheck option */
13530+static struct dentry *aufs_fh_to_parent(struct super_block *sb, struct fid *fid,
13531+ int fh_len, int fh_type)
13532+{
13533+ struct dentry *parent;
13534+ __u32 *fh = fid->raw;
13535+ ino_t dir_ino;
13536+
13537+ dir_ino = decode_ino(fh + Fh_dir_ino);
13538+ parent = decode_by_ino(sb, dir_ino, 0);
13539+ if (IS_ERR(parent))
13540+ goto out;
13541+ if (!parent)
13542+ parent = decode_by_path(sb, au_br_index(sb, fh[Fh_br_id]),
13543+ dir_ino, fh, fh_len);
13544+
4f0767ce 13545+out:
1facf9fc 13546+ AuTraceErrPtr(parent);
13547+ return parent;
13548+}
13549+#endif
13550+
13551+/* ---------------------------------------------------------------------- */
13552+
0c3ec466
AM
13553+static int aufs_encode_fh(struct inode *inode, __u32 *fh, int *max_len,
13554+ struct inode *dir)
1facf9fc 13555+{
13556+ int err;
0c3ec466 13557+ aufs_bindex_t bindex;
1facf9fc 13558+ struct super_block *sb, *h_sb;
0c3ec466
AM
13559+ struct dentry *dentry, *parent, *h_parent;
13560+ struct inode *h_dir;
1facf9fc 13561+ struct au_branch *br;
13562+
1facf9fc 13563+ err = -ENOSPC;
13564+ if (unlikely(*max_len <= Fh_tail)) {
13565+ AuWarn1("NFSv2 client (max_len %d)?\n", *max_len);
13566+ goto out;
13567+ }
13568+
13569+ err = FILEID_ROOT;
0c3ec466
AM
13570+ if (inode->i_ino == AUFS_ROOT_INO) {
13571+ AuDebugOn(inode->i_ino != AUFS_ROOT_INO);
1facf9fc 13572+ goto out;
13573+ }
13574+
1facf9fc 13575+ h_parent = NULL;
0c3ec466
AM
13576+ sb = inode->i_sb;
13577+ err = si_read_lock(sb, AuLock_FLUSH);
027c5e7a
AM
13578+ if (unlikely(err))
13579+ goto out;
13580+
1facf9fc 13581+#ifdef CONFIG_AUFS_DEBUG
13582+ if (unlikely(!au_opt_test(au_mntflags(sb), XINO)))
13583+ AuWarn1("NFS-exporting requires xino\n");
13584+#endif
027c5e7a 13585+ err = -EIO;
0c3ec466
AM
13586+ parent = NULL;
13587+ ii_read_lock_child(inode);
5afbbe0d 13588+ bindex = au_ibtop(inode);
0c3ec466 13589+ if (!dir) {
c1595e42 13590+ dentry = d_find_any_alias(inode);
0c3ec466
AM
13591+ if (unlikely(!dentry))
13592+ goto out_unlock;
13593+ AuDebugOn(au_test_anon(dentry));
13594+ parent = dget_parent(dentry);
13595+ dput(dentry);
13596+ if (unlikely(!parent))
13597+ goto out_unlock;
5527c038
JR
13598+ if (d_really_is_positive(parent))
13599+ dir = d_inode(parent);
1facf9fc 13600+ }
0c3ec466
AM
13601+
13602+ ii_read_lock_parent(dir);
13603+ h_dir = au_h_iptr(dir, bindex);
13604+ ii_read_unlock(dir);
13605+ if (unlikely(!h_dir))
13606+ goto out_parent;
c1595e42 13607+ h_parent = d_find_any_alias(h_dir);
1facf9fc 13608+ if (unlikely(!h_parent))
0c3ec466 13609+ goto out_hparent;
1facf9fc 13610+
13611+ err = -EPERM;
13612+ br = au_sbr(sb, bindex);
86dc4139 13613+ h_sb = au_br_sb(br);
1facf9fc 13614+ if (unlikely(!h_sb->s_export_op)) {
13615+ AuErr1("%s branch is not exportable\n", au_sbtype(h_sb));
0c3ec466 13616+ goto out_hparent;
1facf9fc 13617+ }
13618+
13619+ fh[Fh_br_id] = br->br_id;
13620+ fh[Fh_sigen] = au_sigen(sb);
13621+ encode_ino(fh + Fh_ino, inode->i_ino);
0c3ec466 13622+ encode_ino(fh + Fh_dir_ino, dir->i_ino);
1facf9fc 13623+ fh[Fh_igen] = inode->i_generation;
13624+
13625+ *max_len -= Fh_tail;
13626+ fh[Fh_h_type] = exportfs_encode_fh(h_parent, (void *)(fh + Fh_tail),
13627+ max_len,
13628+ /*connectable or subtreecheck*/0);
13629+ err = fh[Fh_h_type];
13630+ *max_len += Fh_tail;
13631+ /* todo: macros? */
1716fcea 13632+ if (err != FILEID_INVALID)
1facf9fc 13633+ err = 99;
13634+ else
13635+ AuWarn1("%s encode_fh failed\n", au_sbtype(h_sb));
13636+
0c3ec466 13637+out_hparent:
1facf9fc 13638+ dput(h_parent);
0c3ec466 13639+out_parent:
1facf9fc 13640+ dput(parent);
0c3ec466
AM
13641+out_unlock:
13642+ ii_read_unlock(inode);
13643+ si_read_unlock(sb);
4f0767ce 13644+out:
1facf9fc 13645+ if (unlikely(err < 0))
1716fcea 13646+ err = FILEID_INVALID;
1facf9fc 13647+ return err;
13648+}
13649+
13650+/* ---------------------------------------------------------------------- */
13651+
4a4d8108
AM
13652+static int aufs_commit_metadata(struct inode *inode)
13653+{
13654+ int err;
13655+ aufs_bindex_t bindex;
13656+ struct super_block *sb;
13657+ struct inode *h_inode;
13658+ int (*f)(struct inode *inode);
13659+
13660+ sb = inode->i_sb;
e49829fe 13661+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 13662+ ii_write_lock_child(inode);
5afbbe0d 13663+ bindex = au_ibtop(inode);
4a4d8108
AM
13664+ AuDebugOn(bindex < 0);
13665+ h_inode = au_h_iptr(inode, bindex);
13666+
13667+ f = h_inode->i_sb->s_export_op->commit_metadata;
13668+ if (f)
13669+ err = f(h_inode);
13670+ else {
13671+ struct writeback_control wbc = {
13672+ .sync_mode = WB_SYNC_ALL,
13673+ .nr_to_write = 0 /* metadata only */
13674+ };
13675+
13676+ err = sync_inode(h_inode, &wbc);
13677+ }
13678+
13679+ au_cpup_attr_timesizes(inode);
13680+ ii_write_unlock(inode);
13681+ si_read_unlock(sb);
13682+ return err;
13683+}
13684+
13685+/* ---------------------------------------------------------------------- */
13686+
1facf9fc 13687+static struct export_operations aufs_export_op = {
4a4d8108 13688+ .fh_to_dentry = aufs_fh_to_dentry,
1facf9fc 13689+ /* .fh_to_parent = aufs_fh_to_parent, */
4a4d8108
AM
13690+ .encode_fh = aufs_encode_fh,
13691+ .commit_metadata = aufs_commit_metadata
1facf9fc 13692+};
13693+
13694+void au_export_init(struct super_block *sb)
13695+{
13696+ struct au_sbinfo *sbinfo;
13697+ __u32 u;
13698+
5afbbe0d
AM
13699+ BUILD_BUG_ON_MSG(IS_BUILTIN(CONFIG_AUFS_FS)
13700+ && IS_MODULE(CONFIG_EXPORTFS),
13701+ AUFS_NAME ": unsupported configuration "
13702+ "CONFIG_EXPORTFS=m and CONFIG_AUFS_FS=y");
13703+
1facf9fc 13704+ sb->s_export_op = &aufs_export_op;
13705+ sbinfo = au_sbi(sb);
13706+ sbinfo->si_xigen = NULL;
13707+ get_random_bytes(&u, sizeof(u));
13708+ BUILD_BUG_ON(sizeof(u) != sizeof(int));
13709+ atomic_set(&sbinfo->si_xigen_next, u);
13710+}
076b876e 13711diff -urN /usr/share/empty/fs/aufs/fhsm.c linux/fs/aufs/fhsm.c
eca34b5c 13712--- /usr/share/empty/fs/aufs/fhsm.c 1970-01-01 01:00:00.000000000 +0100
016522bc 13713+++ linux/fs/aufs/fhsm.c 2020-01-27 10:57:18.172204883 +0100
062440b3 13714@@ -0,0 +1,427 @@
cd7a4cd9 13715+// SPDX-License-Identifier: GPL-2.0
076b876e 13716+/*
016522bc 13717+ * Copyright (C) 2011-2020 Junjiro R. Okajima
076b876e
AM
13718+ *
13719+ * This program, aufs is free software; you can redistribute it and/or modify
13720+ * it under the terms of the GNU General Public License as published by
13721+ * the Free Software Foundation; either version 2 of the License, or
13722+ * (at your option) any later version.
13723+ *
13724+ * This program is distributed in the hope that it will be useful,
13725+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13726+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13727+ * GNU General Public License for more details.
13728+ *
13729+ * You should have received a copy of the GNU General Public License
13730+ * along with this program; if not, write to the Free Software
13731+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
13732+ */
13733+
13734+/*
13735+ * File-based Hierarchy Storage Management
13736+ */
13737+
13738+#include <linux/anon_inodes.h>
13739+#include <linux/poll.h>
13740+#include <linux/seq_file.h>
13741+#include <linux/statfs.h>
13742+#include "aufs.h"
13743+
c1595e42
JR
13744+static aufs_bindex_t au_fhsm_bottom(struct super_block *sb)
13745+{
13746+ struct au_sbinfo *sbinfo;
13747+ struct au_fhsm *fhsm;
13748+
13749+ SiMustAnyLock(sb);
13750+
13751+ sbinfo = au_sbi(sb);
13752+ fhsm = &sbinfo->si_fhsm;
13753+ AuDebugOn(!fhsm);
13754+ return fhsm->fhsm_bottom;
13755+}
13756+
13757+void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex)
13758+{
13759+ struct au_sbinfo *sbinfo;
13760+ struct au_fhsm *fhsm;
13761+
13762+ SiMustWriteLock(sb);
13763+
13764+ sbinfo = au_sbi(sb);
13765+ fhsm = &sbinfo->si_fhsm;
13766+ AuDebugOn(!fhsm);
13767+ fhsm->fhsm_bottom = bindex;
13768+}
13769+
13770+/* ---------------------------------------------------------------------- */
13771+
076b876e
AM
13772+static int au_fhsm_test_jiffy(struct au_sbinfo *sbinfo, struct au_branch *br)
13773+{
13774+ struct au_br_fhsm *bf;
13775+
13776+ bf = br->br_fhsm;
13777+ MtxMustLock(&bf->bf_lock);
13778+
13779+ return !bf->bf_readable
13780+ || time_after(jiffies,
13781+ bf->bf_jiffy + sbinfo->si_fhsm.fhsm_expire);
13782+}
13783+
13784+/* ---------------------------------------------------------------------- */
13785+
13786+static void au_fhsm_notify(struct super_block *sb, int val)
13787+{
13788+ struct au_sbinfo *sbinfo;
13789+ struct au_fhsm *fhsm;
13790+
13791+ SiMustAnyLock(sb);
13792+
13793+ sbinfo = au_sbi(sb);
13794+ fhsm = &sbinfo->si_fhsm;
13795+ if (au_fhsm_pid(fhsm)
13796+ && atomic_read(&fhsm->fhsm_readable) != -1) {
13797+ atomic_set(&fhsm->fhsm_readable, val);
13798+ if (val)
13799+ wake_up(&fhsm->fhsm_wqh);
13800+ }
13801+}
13802+
13803+static int au_fhsm_stfs(struct super_block *sb, aufs_bindex_t bindex,
13804+ struct aufs_stfs *rstfs, int do_lock, int do_notify)
13805+{
13806+ int err;
13807+ struct au_branch *br;
13808+ struct au_br_fhsm *bf;
13809+
13810+ br = au_sbr(sb, bindex);
13811+ AuDebugOn(au_br_rdonly(br));
13812+ bf = br->br_fhsm;
13813+ AuDebugOn(!bf);
13814+
13815+ if (do_lock)
13816+ mutex_lock(&bf->bf_lock);
13817+ else
13818+ MtxMustLock(&bf->bf_lock);
13819+
13820+ /* sb->s_root for NFS is unreliable */
13821+ err = au_br_stfs(br, &bf->bf_stfs);
13822+ if (unlikely(err)) {
13823+ AuErr1("FHSM failed (%d), b%d, ignored.\n", bindex, err);
13824+ goto out;
13825+ }
13826+
13827+ bf->bf_jiffy = jiffies;
13828+ bf->bf_readable = 1;
13829+ if (do_notify)
13830+ au_fhsm_notify(sb, /*val*/1);
13831+ if (rstfs)
13832+ *rstfs = bf->bf_stfs;
13833+
13834+out:
13835+ if (do_lock)
13836+ mutex_unlock(&bf->bf_lock);
13837+ au_fhsm_notify(sb, /*val*/1);
13838+
13839+ return err;
13840+}
13841+
13842+void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force)
13843+{
13844+ int err;
076b876e
AM
13845+ struct au_sbinfo *sbinfo;
13846+ struct au_fhsm *fhsm;
13847+ struct au_branch *br;
13848+ struct au_br_fhsm *bf;
13849+
13850+ AuDbg("b%d, force %d\n", bindex, force);
13851+ SiMustAnyLock(sb);
13852+
13853+ sbinfo = au_sbi(sb);
13854+ fhsm = &sbinfo->si_fhsm;
c1595e42
JR
13855+ if (!au_ftest_si(sbinfo, FHSM)
13856+ || fhsm->fhsm_bottom == bindex)
076b876e
AM
13857+ return;
13858+
13859+ br = au_sbr(sb, bindex);
13860+ bf = br->br_fhsm;
13861+ AuDebugOn(!bf);
13862+ mutex_lock(&bf->bf_lock);
13863+ if (force
13864+ || au_fhsm_pid(fhsm)
13865+ || au_fhsm_test_jiffy(sbinfo, br))
13866+ err = au_fhsm_stfs(sb, bindex, /*rstfs*/NULL, /*do_lock*/0,
13867+ /*do_notify*/1);
13868+ mutex_unlock(&bf->bf_lock);
13869+}
13870+
13871+void au_fhsm_wrote_all(struct super_block *sb, int force)
13872+{
5afbbe0d 13873+ aufs_bindex_t bindex, bbot;
076b876e
AM
13874+ struct au_branch *br;
13875+
13876+ /* exclude the bottom */
5afbbe0d
AM
13877+ bbot = au_fhsm_bottom(sb);
13878+ for (bindex = 0; bindex < bbot; bindex++) {
076b876e
AM
13879+ br = au_sbr(sb, bindex);
13880+ if (au_br_fhsm(br->br_perm))
13881+ au_fhsm_wrote(sb, bindex, force);
13882+ }
13883+}
13884+
13885+/* ---------------------------------------------------------------------- */
13886+
be118d29 13887+static __poll_t au_fhsm_poll(struct file *file, struct poll_table_struct *wait)
076b876e 13888+{
be118d29 13889+ __poll_t mask;
076b876e
AM
13890+ struct au_sbinfo *sbinfo;
13891+ struct au_fhsm *fhsm;
13892+
13893+ mask = 0;
13894+ sbinfo = file->private_data;
13895+ fhsm = &sbinfo->si_fhsm;
13896+ poll_wait(file, &fhsm->fhsm_wqh, wait);
13897+ if (atomic_read(&fhsm->fhsm_readable))
be118d29 13898+ mask = EPOLLIN /* | EPOLLRDNORM */;
076b876e 13899+
b00004a5
AM
13900+ if (!mask)
13901+ AuDbg("mask 0x%x\n", mask);
076b876e
AM
13902+ return mask;
13903+}
13904+
13905+static int au_fhsm_do_read_one(struct aufs_stbr __user *stbr,
13906+ struct aufs_stfs *stfs, __s16 brid)
13907+{
13908+ int err;
13909+
13910+ err = copy_to_user(&stbr->stfs, stfs, sizeof(*stfs));
13911+ if (!err)
13912+ err = __put_user(brid, &stbr->brid);
13913+ if (unlikely(err))
13914+ err = -EFAULT;
13915+
13916+ return err;
13917+}
13918+
13919+static ssize_t au_fhsm_do_read(struct super_block *sb,
13920+ struct aufs_stbr __user *stbr, size_t count)
13921+{
13922+ ssize_t err;
13923+ int nstbr;
5afbbe0d 13924+ aufs_bindex_t bindex, bbot;
076b876e
AM
13925+ struct au_branch *br;
13926+ struct au_br_fhsm *bf;
13927+
13928+ /* except the bottom branch */
13929+ err = 0;
13930+ nstbr = 0;
5afbbe0d
AM
13931+ bbot = au_fhsm_bottom(sb);
13932+ for (bindex = 0; !err && bindex < bbot; bindex++) {
076b876e
AM
13933+ br = au_sbr(sb, bindex);
13934+ if (!au_br_fhsm(br->br_perm))
13935+ continue;
13936+
13937+ bf = br->br_fhsm;
13938+ mutex_lock(&bf->bf_lock);
13939+ if (bf->bf_readable) {
13940+ err = -EFAULT;
13941+ if (count >= sizeof(*stbr))
13942+ err = au_fhsm_do_read_one(stbr++, &bf->bf_stfs,
13943+ br->br_id);
13944+ if (!err) {
13945+ bf->bf_readable = 0;
13946+ count -= sizeof(*stbr);
13947+ nstbr++;
13948+ }
13949+ }
13950+ mutex_unlock(&bf->bf_lock);
13951+ }
13952+ if (!err)
13953+ err = sizeof(*stbr) * nstbr;
13954+
13955+ return err;
13956+}
13957+
13958+static ssize_t au_fhsm_read(struct file *file, char __user *buf, size_t count,
13959+ loff_t *pos)
13960+{
13961+ ssize_t err;
13962+ int readable;
5afbbe0d 13963+ aufs_bindex_t nfhsm, bindex, bbot;
076b876e
AM
13964+ struct au_sbinfo *sbinfo;
13965+ struct au_fhsm *fhsm;
13966+ struct au_branch *br;
13967+ struct super_block *sb;
13968+
13969+ err = 0;
13970+ sbinfo = file->private_data;
13971+ fhsm = &sbinfo->si_fhsm;
13972+need_data:
13973+ spin_lock_irq(&fhsm->fhsm_wqh.lock);
13974+ if (!atomic_read(&fhsm->fhsm_readable)) {
13975+ if (vfsub_file_flags(file) & O_NONBLOCK)
13976+ err = -EAGAIN;
13977+ else
13978+ err = wait_event_interruptible_locked_irq
13979+ (fhsm->fhsm_wqh,
13980+ atomic_read(&fhsm->fhsm_readable));
13981+ }
13982+ spin_unlock_irq(&fhsm->fhsm_wqh.lock);
13983+ if (unlikely(err))
13984+ goto out;
13985+
13986+ /* sb may already be dead */
13987+ au_rw_read_lock(&sbinfo->si_rwsem);
13988+ readable = atomic_read(&fhsm->fhsm_readable);
13989+ if (readable > 0) {
13990+ sb = sbinfo->si_sb;
13991+ AuDebugOn(!sb);
13992+ /* exclude the bottom branch */
13993+ nfhsm = 0;
5afbbe0d
AM
13994+ bbot = au_fhsm_bottom(sb);
13995+ for (bindex = 0; bindex < bbot; bindex++) {
076b876e
AM
13996+ br = au_sbr(sb, bindex);
13997+ if (au_br_fhsm(br->br_perm))
13998+ nfhsm++;
13999+ }
14000+ err = -EMSGSIZE;
14001+ if (nfhsm * sizeof(struct aufs_stbr) <= count) {
14002+ atomic_set(&fhsm->fhsm_readable, 0);
14003+ err = au_fhsm_do_read(sbinfo->si_sb, (void __user *)buf,
14004+ count);
14005+ }
14006+ }
14007+ au_rw_read_unlock(&sbinfo->si_rwsem);
14008+ if (!readable)
14009+ goto need_data;
14010+
14011+out:
14012+ return err;
14013+}
14014+
14015+static int au_fhsm_release(struct inode *inode, struct file *file)
14016+{
14017+ struct au_sbinfo *sbinfo;
14018+ struct au_fhsm *fhsm;
14019+
14020+ /* sb may already be dead */
14021+ sbinfo = file->private_data;
14022+ fhsm = &sbinfo->si_fhsm;
14023+ spin_lock(&fhsm->fhsm_spin);
14024+ fhsm->fhsm_pid = 0;
14025+ spin_unlock(&fhsm->fhsm_spin);
14026+ kobject_put(&sbinfo->si_kobj);
14027+
14028+ return 0;
14029+}
14030+
14031+static const struct file_operations au_fhsm_fops = {
14032+ .owner = THIS_MODULE,
14033+ .llseek = noop_llseek,
14034+ .read = au_fhsm_read,
14035+ .poll = au_fhsm_poll,
14036+ .release = au_fhsm_release
14037+};
14038+
14039+int au_fhsm_fd(struct super_block *sb, int oflags)
14040+{
14041+ int err, fd;
14042+ struct au_sbinfo *sbinfo;
14043+ struct au_fhsm *fhsm;
14044+
14045+ err = -EPERM;
14046+ if (unlikely(!capable(CAP_SYS_ADMIN)))
14047+ goto out;
14048+
14049+ err = -EINVAL;
14050+ if (unlikely(oflags & ~(O_CLOEXEC | O_NONBLOCK)))
14051+ goto out;
14052+
14053+ err = 0;
14054+ sbinfo = au_sbi(sb);
14055+ fhsm = &sbinfo->si_fhsm;
14056+ spin_lock(&fhsm->fhsm_spin);
14057+ if (!fhsm->fhsm_pid)
14058+ fhsm->fhsm_pid = current->pid;
14059+ else
14060+ err = -EBUSY;
14061+ spin_unlock(&fhsm->fhsm_spin);
14062+ if (unlikely(err))
14063+ goto out;
14064+
14065+ oflags |= O_RDONLY;
14066+ /* oflags |= FMODE_NONOTIFY; */
14067+ fd = anon_inode_getfd("[aufs_fhsm]", &au_fhsm_fops, sbinfo, oflags);
14068+ err = fd;
14069+ if (unlikely(fd < 0))
14070+ goto out_pid;
14071+
acd2b654 14072+ /* succeed regardless 'fhsm' status */
076b876e
AM
14073+ kobject_get(&sbinfo->si_kobj);
14074+ si_noflush_read_lock(sb);
14075+ if (au_ftest_si(sbinfo, FHSM))
14076+ au_fhsm_wrote_all(sb, /*force*/0);
14077+ si_read_unlock(sb);
14078+ goto out; /* success */
14079+
14080+out_pid:
14081+ spin_lock(&fhsm->fhsm_spin);
14082+ fhsm->fhsm_pid = 0;
14083+ spin_unlock(&fhsm->fhsm_spin);
14084+out:
14085+ AuTraceErr(err);
14086+ return err;
14087+}
14088+
14089+/* ---------------------------------------------------------------------- */
14090+
14091+int au_fhsm_br_alloc(struct au_branch *br)
14092+{
14093+ int err;
14094+
14095+ err = 0;
14096+ br->br_fhsm = kmalloc(sizeof(*br->br_fhsm), GFP_NOFS);
14097+ if (br->br_fhsm)
14098+ au_br_fhsm_init(br->br_fhsm);
14099+ else
14100+ err = -ENOMEM;
14101+
14102+ return err;
14103+}
14104+
14105+/* ---------------------------------------------------------------------- */
14106+
14107+void au_fhsm_fin(struct super_block *sb)
14108+{
14109+ au_fhsm_notify(sb, /*val*/-1);
14110+}
14111+
14112+void au_fhsm_init(struct au_sbinfo *sbinfo)
14113+{
14114+ struct au_fhsm *fhsm;
14115+
14116+ fhsm = &sbinfo->si_fhsm;
14117+ spin_lock_init(&fhsm->fhsm_spin);
14118+ init_waitqueue_head(&fhsm->fhsm_wqh);
14119+ atomic_set(&fhsm->fhsm_readable, 0);
14120+ fhsm->fhsm_expire
14121+ = msecs_to_jiffies(AUFS_FHSM_CACHE_DEF_SEC * MSEC_PER_SEC);
c1595e42 14122+ fhsm->fhsm_bottom = -1;
076b876e
AM
14123+}
14124+
14125+void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec)
14126+{
14127+ sbinfo->si_fhsm.fhsm_expire
14128+ = msecs_to_jiffies(sec * MSEC_PER_SEC);
14129+}
14130+
14131+void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo)
14132+{
14133+ unsigned int u;
14134+
14135+ if (!au_ftest_si(sbinfo, FHSM))
14136+ return;
14137+
14138+ u = jiffies_to_msecs(sbinfo->si_fhsm.fhsm_expire) / MSEC_PER_SEC;
14139+ if (u != AUFS_FHSM_CACHE_DEF_SEC)
14140+ seq_printf(seq, ",fhsm_sec=%u", u);
14141+}
7f207e10 14142diff -urN /usr/share/empty/fs/aufs/file.c linux/fs/aufs/file.c
eca34b5c 14143--- /usr/share/empty/fs/aufs/file.c 1970-01-01 01:00:00.000000000 +0100
016522bc 14144+++ linux/fs/aufs/file.c 2020-01-27 10:57:18.172204883 +0100
acd2b654 14145@@ -0,0 +1,863 @@
cd7a4cd9 14146+// SPDX-License-Identifier: GPL-2.0
1facf9fc 14147+/*
016522bc 14148+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 14149+ *
14150+ * This program, aufs is free software; you can redistribute it and/or modify
14151+ * it under the terms of the GNU General Public License as published by
14152+ * the Free Software Foundation; either version 2 of the License, or
14153+ * (at your option) any later version.
dece6358
AM
14154+ *
14155+ * This program is distributed in the hope that it will be useful,
14156+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14157+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14158+ * GNU General Public License for more details.
14159+ *
14160+ * You should have received a copy of the GNU General Public License
523b37e3 14161+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 14162+ */
14163+
14164+/*
4a4d8108 14165+ * handling file/dir, and address_space operation
1facf9fc 14166+ */
14167+
7eafdf33
AM
14168+#ifdef CONFIG_AUFS_DEBUG
14169+#include <linux/migrate.h>
14170+#endif
4a4d8108 14171+#include <linux/pagemap.h>
1facf9fc 14172+#include "aufs.h"
14173+
4a4d8108
AM
14174+/* drop flags for writing */
14175+unsigned int au_file_roflags(unsigned int flags)
14176+{
14177+ flags &= ~(O_WRONLY | O_RDWR | O_APPEND | O_CREAT | O_TRUNC);
14178+ flags |= O_RDONLY | O_NOATIME;
14179+ return flags;
14180+}
14181+
14182+/* common functions to regular file and dir */
14183+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
392086de 14184+ struct file *file, int force_wr)
1facf9fc 14185+{
1308ab2a 14186+ struct file *h_file;
4a4d8108
AM
14187+ struct dentry *h_dentry;
14188+ struct inode *h_inode;
14189+ struct super_block *sb;
14190+ struct au_branch *br;
14191+ struct path h_path;
b912730e 14192+ int err;
1facf9fc 14193+
4a4d8108
AM
14194+ /* a race condition can happen between open and unlink/rmdir */
14195+ h_file = ERR_PTR(-ENOENT);
14196+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 14197+ if (au_test_nfsd() && (!h_dentry || d_is_negative(h_dentry)))
4a4d8108 14198+ goto out;
5527c038 14199+ h_inode = d_inode(h_dentry);
027c5e7a
AM
14200+ spin_lock(&h_dentry->d_lock);
14201+ err = (!d_unhashed(dentry) && d_unlinked(h_dentry))
5527c038 14202+ /* || !d_inode(dentry)->i_nlink */
027c5e7a
AM
14203+ ;
14204+ spin_unlock(&h_dentry->d_lock);
14205+ if (unlikely(err))
4a4d8108 14206+ goto out;
1facf9fc 14207+
4a4d8108
AM
14208+ sb = dentry->d_sb;
14209+ br = au_sbr(sb, bindex);
b912730e
AM
14210+ err = au_br_test_oflag(flags, br);
14211+ h_file = ERR_PTR(err);
14212+ if (unlikely(err))
027c5e7a 14213+ goto out;
1facf9fc 14214+
4a4d8108 14215+ /* drop flags for writing */
5527c038 14216+ if (au_test_ro(sb, bindex, d_inode(dentry))) {
392086de
AM
14217+ if (force_wr && !(flags & O_WRONLY))
14218+ force_wr = 0;
4a4d8108 14219+ flags = au_file_roflags(flags);
392086de
AM
14220+ if (force_wr) {
14221+ h_file = ERR_PTR(-EROFS);
14222+ flags = au_file_roflags(flags);
14223+ if (unlikely(vfsub_native_ro(h_inode)
14224+ || IS_APPEND(h_inode)))
14225+ goto out;
14226+ flags &= ~O_ACCMODE;
14227+ flags |= O_WRONLY;
14228+ }
14229+ }
4a4d8108 14230+ flags &= ~O_CREAT;
acd2b654 14231+ au_lcnt_inc(&br->br_nfiles);
4a4d8108 14232+ h_path.dentry = h_dentry;
86dc4139 14233+ h_path.mnt = au_br_mnt(br);
38d290e6 14234+ h_file = vfsub_dentry_open(&h_path, flags);
4a4d8108
AM
14235+ if (IS_ERR(h_file))
14236+ goto out_br;
dece6358 14237+
b912730e 14238+ if (flags & __FMODE_EXEC) {
4a4d8108
AM
14239+ err = deny_write_access(h_file);
14240+ if (unlikely(err)) {
14241+ fput(h_file);
14242+ h_file = ERR_PTR(err);
14243+ goto out_br;
14244+ }
14245+ }
953406b4 14246+ fsnotify_open(h_file);
4a4d8108 14247+ goto out; /* success */
1facf9fc 14248+
4f0767ce 14249+out_br:
acd2b654 14250+ au_lcnt_dec(&br->br_nfiles);
4f0767ce 14251+out:
4a4d8108
AM
14252+ return h_file;
14253+}
1308ab2a 14254+
076b876e
AM
14255+static int au_cmoo(struct dentry *dentry)
14256+{
8b6a4947 14257+ int err, cmoo, matched;
076b876e
AM
14258+ unsigned int udba;
14259+ struct path h_path;
14260+ struct au_pin pin;
14261+ struct au_cp_generic cpg = {
14262+ .dentry = dentry,
14263+ .bdst = -1,
14264+ .bsrc = -1,
14265+ .len = -1,
14266+ .pin = &pin,
14267+ .flags = AuCpup_DTIME | AuCpup_HOPEN
14268+ };
7e9cd9fe 14269+ struct inode *delegated;
076b876e
AM
14270+ struct super_block *sb;
14271+ struct au_sbinfo *sbinfo;
14272+ struct au_fhsm *fhsm;
14273+ pid_t pid;
14274+ struct au_branch *br;
14275+ struct dentry *parent;
14276+ struct au_hinode *hdir;
14277+
14278+ DiMustWriteLock(dentry);
5527c038 14279+ IiMustWriteLock(d_inode(dentry));
076b876e
AM
14280+
14281+ err = 0;
14282+ if (IS_ROOT(dentry))
14283+ goto out;
5afbbe0d 14284+ cpg.bsrc = au_dbtop(dentry);
076b876e
AM
14285+ if (!cpg.bsrc)
14286+ goto out;
14287+
14288+ sb = dentry->d_sb;
14289+ sbinfo = au_sbi(sb);
14290+ fhsm = &sbinfo->si_fhsm;
14291+ pid = au_fhsm_pid(fhsm);
8b6a4947
AM
14292+ rcu_read_lock();
14293+ matched = (pid
14294+ && (current->pid == pid
14295+ || rcu_dereference(current->real_parent)->pid == pid));
14296+ rcu_read_unlock();
14297+ if (matched)
076b876e
AM
14298+ goto out;
14299+
14300+ br = au_sbr(sb, cpg.bsrc);
14301+ cmoo = au_br_cmoo(br->br_perm);
14302+ if (!cmoo)
14303+ goto out;
7e9cd9fe 14304+ if (!d_is_reg(dentry))
076b876e
AM
14305+ cmoo &= AuBrAttr_COO_ALL;
14306+ if (!cmoo)
14307+ goto out;
14308+
14309+ parent = dget_parent(dentry);
14310+ di_write_lock_parent(parent);
14311+ err = au_wbr_do_copyup_bu(dentry, cpg.bsrc - 1);
14312+ cpg.bdst = err;
14313+ if (unlikely(err < 0)) {
14314+ err = 0; /* there is no upper writable branch */
14315+ goto out_dgrade;
14316+ }
14317+ AuDbg("bsrc %d, bdst %d\n", cpg.bsrc, cpg.bdst);
14318+
14319+ /* do not respect the coo attrib for the target branch */
14320+ err = au_cpup_dirs(dentry, cpg.bdst);
14321+ if (unlikely(err))
14322+ goto out_dgrade;
14323+
14324+ di_downgrade_lock(parent, AuLock_IR);
14325+ udba = au_opt_udba(sb);
14326+ err = au_pin(&pin, dentry, cpg.bdst, udba,
14327+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14328+ if (unlikely(err))
14329+ goto out_parent;
14330+
14331+ err = au_sio_cpup_simple(&cpg);
14332+ au_unpin(&pin);
14333+ if (unlikely(err))
14334+ goto out_parent;
14335+ if (!(cmoo & AuBrWAttr_MOO))
14336+ goto out_parent; /* success */
14337+
14338+ err = au_pin(&pin, dentry, cpg.bsrc, udba,
14339+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14340+ if (unlikely(err))
14341+ goto out_parent;
14342+
14343+ h_path.mnt = au_br_mnt(br);
14344+ h_path.dentry = au_h_dptr(dentry, cpg.bsrc);
5527c038 14345+ hdir = au_hi(d_inode(parent), cpg.bsrc);
076b876e
AM
14346+ delegated = NULL;
14347+ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated, /*force*/1);
14348+ au_unpin(&pin);
14349+ /* todo: keep h_dentry or not? */
14350+ if (unlikely(err == -EWOULDBLOCK)) {
14351+ pr_warn("cannot retry for NFSv4 delegation"
14352+ " for an internal unlink\n");
14353+ iput(delegated);
14354+ }
14355+ if (unlikely(err)) {
14356+ pr_err("unlink %pd after coo failed (%d), ignored\n",
14357+ dentry, err);
14358+ err = 0;
14359+ }
14360+ goto out_parent; /* success */
14361+
14362+out_dgrade:
14363+ di_downgrade_lock(parent, AuLock_IR);
14364+out_parent:
14365+ di_read_unlock(parent, AuLock_IR);
14366+ dput(parent);
14367+out:
14368+ AuTraceErr(err);
14369+ return err;
14370+}
14371+
b912730e 14372+int au_do_open(struct file *file, struct au_do_open_args *args)
1facf9fc 14373+{
8b6a4947 14374+ int err, aopen = args->aopen;
1facf9fc 14375+ struct dentry *dentry;
076b876e 14376+ struct au_finfo *finfo;
1308ab2a 14377+
8b6a4947 14378+ if (!aopen)
b912730e
AM
14379+ err = au_finfo_init(file, args->fidir);
14380+ else {
14381+ lockdep_off();
14382+ err = au_finfo_init(file, args->fidir);
14383+ lockdep_on();
14384+ }
4a4d8108
AM
14385+ if (unlikely(err))
14386+ goto out;
1facf9fc 14387+
2000de60 14388+ dentry = file->f_path.dentry;
b912730e 14389+ AuDebugOn(IS_ERR_OR_NULL(dentry));
8b6a4947
AM
14390+ di_write_lock_child(dentry);
14391+ err = au_cmoo(dentry);
14392+ di_downgrade_lock(dentry, AuLock_IR);
14393+ if (!err) {
14394+ if (!aopen)
b912730e 14395+ err = args->open(file, vfsub_file_flags(file), NULL);
8b6a4947
AM
14396+ else {
14397+ lockdep_off();
acd2b654
AM
14398+ err = args->open(file, vfsub_file_flags(file),
14399+ args->h_file);
8b6a4947
AM
14400+ lockdep_on();
14401+ }
b912730e 14402+ }
8b6a4947 14403+ di_read_unlock(dentry, AuLock_IR);
1facf9fc 14404+
076b876e
AM
14405+ finfo = au_fi(file);
14406+ if (!err) {
14407+ finfo->fi_file = file;
8b6a4947
AM
14408+ au_hbl_add(&finfo->fi_hlist,
14409+ &au_sbi(file->f_path.dentry->d_sb)->si_files);
076b876e 14410+ }
8b6a4947 14411+ if (!aopen)
b912730e
AM
14412+ fi_write_unlock(file);
14413+ else {
14414+ lockdep_off();
14415+ fi_write_unlock(file);
14416+ lockdep_on();
14417+ }
4a4d8108 14418+ if (unlikely(err)) {
076b876e 14419+ finfo->fi_hdir = NULL;
1c60b727 14420+ au_finfo_fin(file);
1308ab2a 14421+ }
4a4d8108 14422+
4f0767ce 14423+out:
8b6a4947 14424+ AuTraceErr(err);
1308ab2a 14425+ return err;
14426+}
dece6358 14427+
4a4d8108 14428+int au_reopen_nondir(struct file *file)
1308ab2a 14429+{
4a4d8108 14430+ int err;
5afbbe0d 14431+ aufs_bindex_t btop;
4a4d8108 14432+ struct dentry *dentry;
acd2b654 14433+ struct au_branch *br;
4a4d8108 14434+ struct file *h_file, *h_file_tmp;
1308ab2a 14435+
2000de60 14436+ dentry = file->f_path.dentry;
5afbbe0d 14437+ btop = au_dbtop(dentry);
acd2b654 14438+ br = au_sbr(dentry->d_sb, btop);
4a4d8108 14439+ h_file_tmp = NULL;
5afbbe0d 14440+ if (au_fbtop(file) == btop) {
4a4d8108
AM
14441+ h_file = au_hf_top(file);
14442+ if (file->f_mode == h_file->f_mode)
14443+ return 0; /* success */
14444+ h_file_tmp = h_file;
14445+ get_file(h_file_tmp);
acd2b654 14446+ au_lcnt_inc(&br->br_nfiles);
5afbbe0d 14447+ au_set_h_fptr(file, btop, NULL);
4a4d8108
AM
14448+ }
14449+ AuDebugOn(au_fi(file)->fi_hdir);
86dc4139
AM
14450+ /*
14451+ * it can happen
14452+ * file exists on both of rw and ro
5afbbe0d 14453+ * open --> dbtop and fbtop are both 0
86dc4139
AM
14454+ * prepend a branch as rw, "rw" become ro
14455+ * remove rw/file
14456+ * delete the top branch, "rw" becomes rw again
5afbbe0d
AM
14457+ * --> dbtop is 1, fbtop is still 0
14458+ * write --> fbtop is 0 but dbtop is 1
86dc4139 14459+ */
5afbbe0d 14460+ /* AuDebugOn(au_fbtop(file) < btop); */
1308ab2a 14461+
5afbbe0d 14462+ h_file = au_h_open(dentry, btop, vfsub_file_flags(file) & ~O_TRUNC,
392086de 14463+ file, /*force_wr*/0);
4a4d8108 14464+ err = PTR_ERR(h_file);
86dc4139
AM
14465+ if (IS_ERR(h_file)) {
14466+ if (h_file_tmp) {
acd2b654 14467+ /* revert */
5afbbe0d 14468+ au_set_h_fptr(file, btop, h_file_tmp);
86dc4139
AM
14469+ h_file_tmp = NULL;
14470+ }
4a4d8108 14471+ goto out; /* todo: close all? */
86dc4139 14472+ }
4a4d8108
AM
14473+
14474+ err = 0;
5afbbe0d
AM
14475+ au_set_fbtop(file, btop);
14476+ au_set_h_fptr(file, btop, h_file);
4a4d8108
AM
14477+ au_update_figen(file);
14478+ /* todo: necessary? */
14479+ /* file->f_ra = h_file->f_ra; */
14480+
4f0767ce 14481+out:
acd2b654 14482+ if (h_file_tmp) {
4a4d8108 14483+ fput(h_file_tmp);
acd2b654
AM
14484+ au_lcnt_dec(&br->br_nfiles);
14485+ }
4a4d8108 14486+ return err;
1facf9fc 14487+}
14488+
1308ab2a 14489+/* ---------------------------------------------------------------------- */
14490+
4a4d8108
AM
14491+static int au_reopen_wh(struct file *file, aufs_bindex_t btgt,
14492+ struct dentry *hi_wh)
1facf9fc 14493+{
4a4d8108 14494+ int err;
5afbbe0d 14495+ aufs_bindex_t btop;
4a4d8108
AM
14496+ struct au_dinfo *dinfo;
14497+ struct dentry *h_dentry;
14498+ struct au_hdentry *hdp;
1facf9fc 14499+
2000de60 14500+ dinfo = au_di(file->f_path.dentry);
4a4d8108 14501+ AuRwMustWriteLock(&dinfo->di_rwsem);
dece6358 14502+
5afbbe0d
AM
14503+ btop = dinfo->di_btop;
14504+ dinfo->di_btop = btgt;
14505+ hdp = au_hdentry(dinfo, btgt);
14506+ h_dentry = hdp->hd_dentry;
14507+ hdp->hd_dentry = hi_wh;
4a4d8108 14508+ err = au_reopen_nondir(file);
5afbbe0d
AM
14509+ hdp->hd_dentry = h_dentry;
14510+ dinfo->di_btop = btop;
1facf9fc 14511+
1facf9fc 14512+ return err;
14513+}
14514+
4a4d8108 14515+static int au_ready_to_write_wh(struct file *file, loff_t len,
86dc4139 14516+ aufs_bindex_t bcpup, struct au_pin *pin)
1facf9fc 14517+{
4a4d8108 14518+ int err;
027c5e7a 14519+ struct inode *inode, *h_inode;
c2b27bf2
AM
14520+ struct dentry *h_dentry, *hi_wh;
14521+ struct au_cp_generic cpg = {
2000de60 14522+ .dentry = file->f_path.dentry,
c2b27bf2
AM
14523+ .bdst = bcpup,
14524+ .bsrc = -1,
14525+ .len = len,
14526+ .pin = pin
14527+ };
1facf9fc 14528+
5afbbe0d 14529+ au_update_dbtop(cpg.dentry);
5527c038 14530+ inode = d_inode(cpg.dentry);
027c5e7a 14531+ h_inode = NULL;
5afbbe0d
AM
14532+ if (au_dbtop(cpg.dentry) <= bcpup
14533+ && au_dbbot(cpg.dentry) >= bcpup) {
c2b27bf2 14534+ h_dentry = au_h_dptr(cpg.dentry, bcpup);
5527c038
JR
14535+ if (h_dentry && d_is_positive(h_dentry))
14536+ h_inode = d_inode(h_dentry);
027c5e7a 14537+ }
4a4d8108 14538+ hi_wh = au_hi_wh(inode, bcpup);
027c5e7a 14539+ if (!hi_wh && !h_inode)
c2b27bf2 14540+ err = au_sio_cpup_wh(&cpg, file);
4a4d8108
AM
14541+ else
14542+ /* already copied-up after unlink */
14543+ err = au_reopen_wh(file, bcpup, hi_wh);
1facf9fc 14544+
4a4d8108 14545+ if (!err
38d290e6
JR
14546+ && (inode->i_nlink > 1
14547+ || (inode->i_state & I_LINKABLE))
c2b27bf2
AM
14548+ && au_opt_test(au_mntflags(cpg.dentry->d_sb), PLINK))
14549+ au_plink_append(inode, bcpup, au_h_dptr(cpg.dentry, bcpup));
1308ab2a 14550+
dece6358 14551+ return err;
1facf9fc 14552+}
14553+
4a4d8108
AM
14554+/*
14555+ * prepare the @file for writing.
14556+ */
14557+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin)
1facf9fc 14558+{
4a4d8108 14559+ int err;
5afbbe0d 14560+ aufs_bindex_t dbtop;
c1595e42 14561+ struct dentry *parent;
86dc4139 14562+ struct inode *inode;
1facf9fc 14563+ struct super_block *sb;
4a4d8108 14564+ struct file *h_file;
c2b27bf2 14565+ struct au_cp_generic cpg = {
2000de60 14566+ .dentry = file->f_path.dentry,
c2b27bf2
AM
14567+ .bdst = -1,
14568+ .bsrc = -1,
14569+ .len = len,
14570+ .pin = pin,
14571+ .flags = AuCpup_DTIME
14572+ };
1facf9fc 14573+
c2b27bf2 14574+ sb = cpg.dentry->d_sb;
5527c038 14575+ inode = d_inode(cpg.dentry);
5afbbe0d 14576+ cpg.bsrc = au_fbtop(file);
c2b27bf2 14577+ err = au_test_ro(sb, cpg.bsrc, inode);
4a4d8108 14578+ if (!err && (au_hf_top(file)->f_mode & FMODE_WRITE)) {
c2b27bf2
AM
14579+ err = au_pin(pin, cpg.dentry, cpg.bsrc, AuOpt_UDBA_NONE,
14580+ /*flags*/0);
1facf9fc 14581+ goto out;
4a4d8108 14582+ }
1facf9fc 14583+
027c5e7a 14584+ /* need to cpup or reopen */
c2b27bf2 14585+ parent = dget_parent(cpg.dentry);
4a4d8108 14586+ di_write_lock_parent(parent);
c2b27bf2
AM
14587+ err = AuWbrCopyup(au_sbi(sb), cpg.dentry);
14588+ cpg.bdst = err;
4a4d8108
AM
14589+ if (unlikely(err < 0))
14590+ goto out_dgrade;
14591+ err = 0;
14592+
c2b27bf2
AM
14593+ if (!d_unhashed(cpg.dentry) && !au_h_dptr(parent, cpg.bdst)) {
14594+ err = au_cpup_dirs(cpg.dentry, cpg.bdst);
1facf9fc 14595+ if (unlikely(err))
4a4d8108
AM
14596+ goto out_dgrade;
14597+ }
14598+
c2b27bf2 14599+ err = au_pin(pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE,
4a4d8108
AM
14600+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
14601+ if (unlikely(err))
14602+ goto out_dgrade;
14603+
5afbbe0d
AM
14604+ dbtop = au_dbtop(cpg.dentry);
14605+ if (dbtop <= cpg.bdst)
c2b27bf2 14606+ cpg.bsrc = cpg.bdst;
027c5e7a 14607+
5afbbe0d 14608+ if (dbtop <= cpg.bdst /* just reopen */
c2b27bf2 14609+ || !d_unhashed(cpg.dentry) /* copyup and reopen */
027c5e7a 14610+ ) {
392086de 14611+ h_file = au_h_open_pre(cpg.dentry, cpg.bsrc, /*force_wr*/0);
86dc4139 14612+ if (IS_ERR(h_file))
027c5e7a 14613+ err = PTR_ERR(h_file);
86dc4139 14614+ else {
027c5e7a 14615+ di_downgrade_lock(parent, AuLock_IR);
5afbbe0d 14616+ if (dbtop > cpg.bdst)
c2b27bf2 14617+ err = au_sio_cpup_simple(&cpg);
027c5e7a
AM
14618+ if (!err)
14619+ err = au_reopen_nondir(file);
c2b27bf2 14620+ au_h_open_post(cpg.dentry, cpg.bsrc, h_file);
027c5e7a 14621+ }
027c5e7a
AM
14622+ } else { /* copyup as wh and reopen */
14623+ /*
14624+ * since writable hfsplus branch is not supported,
14625+ * h_open_pre/post() are unnecessary.
14626+ */
c2b27bf2 14627+ err = au_ready_to_write_wh(file, len, cpg.bdst, pin);
4a4d8108 14628+ di_downgrade_lock(parent, AuLock_IR);
4a4d8108 14629+ }
4a4d8108
AM
14630+
14631+ if (!err) {
14632+ au_pin_set_parent_lflag(pin, /*lflag*/0);
14633+ goto out_dput; /* success */
14634+ }
14635+ au_unpin(pin);
14636+ goto out_unlock;
1facf9fc 14637+
4f0767ce 14638+out_dgrade:
4a4d8108 14639+ di_downgrade_lock(parent, AuLock_IR);
4f0767ce 14640+out_unlock:
4a4d8108 14641+ di_read_unlock(parent, AuLock_IR);
4f0767ce 14642+out_dput:
4a4d8108 14643+ dput(parent);
4f0767ce 14644+out:
1facf9fc 14645+ return err;
14646+}
14647+
4a4d8108
AM
14648+/* ---------------------------------------------------------------------- */
14649+
14650+int au_do_flush(struct file *file, fl_owner_t id,
14651+ int (*flush)(struct file *file, fl_owner_t id))
1facf9fc 14652+{
4a4d8108 14653+ int err;
1facf9fc 14654+ struct super_block *sb;
4a4d8108 14655+ struct inode *inode;
1facf9fc 14656+
c06a8ce3
AM
14657+ inode = file_inode(file);
14658+ sb = inode->i_sb;
4a4d8108
AM
14659+ si_noflush_read_lock(sb);
14660+ fi_read_lock(file);
b752ccd1 14661+ ii_read_lock_child(inode);
1facf9fc 14662+
4a4d8108
AM
14663+ err = flush(file, id);
14664+ au_cpup_attr_timesizes(inode);
1facf9fc 14665+
b752ccd1 14666+ ii_read_unlock(inode);
4a4d8108 14667+ fi_read_unlock(file);
1308ab2a 14668+ si_read_unlock(sb);
dece6358 14669+ return err;
1facf9fc 14670+}
14671+
4a4d8108
AM
14672+/* ---------------------------------------------------------------------- */
14673+
14674+static int au_file_refresh_by_inode(struct file *file, int *need_reopen)
1facf9fc 14675+{
4a4d8108 14676+ int err;
4a4d8108
AM
14677+ struct au_pin pin;
14678+ struct au_finfo *finfo;
c2b27bf2 14679+ struct dentry *parent, *hi_wh;
4a4d8108 14680+ struct inode *inode;
1facf9fc 14681+ struct super_block *sb;
c2b27bf2 14682+ struct au_cp_generic cpg = {
2000de60 14683+ .dentry = file->f_path.dentry,
c2b27bf2
AM
14684+ .bdst = -1,
14685+ .bsrc = -1,
14686+ .len = -1,
14687+ .pin = &pin,
14688+ .flags = AuCpup_DTIME
14689+ };
1facf9fc 14690+
4a4d8108
AM
14691+ FiMustWriteLock(file);
14692+
14693+ err = 0;
14694+ finfo = au_fi(file);
c2b27bf2 14695+ sb = cpg.dentry->d_sb;
5527c038 14696+ inode = d_inode(cpg.dentry);
5afbbe0d 14697+ cpg.bdst = au_ibtop(inode);
c2b27bf2 14698+ if (cpg.bdst == finfo->fi_btop || IS_ROOT(cpg.dentry))
1308ab2a 14699+ goto out;
dece6358 14700+
c2b27bf2
AM
14701+ parent = dget_parent(cpg.dentry);
14702+ if (au_test_ro(sb, cpg.bdst, inode)) {
4a4d8108 14703+ di_read_lock_parent(parent, !AuLock_IR);
c2b27bf2
AM
14704+ err = AuWbrCopyup(au_sbi(sb), cpg.dentry);
14705+ cpg.bdst = err;
4a4d8108
AM
14706+ di_read_unlock(parent, !AuLock_IR);
14707+ if (unlikely(err < 0))
14708+ goto out_parent;
14709+ err = 0;
1facf9fc 14710+ }
1facf9fc 14711+
4a4d8108 14712+ di_read_lock_parent(parent, AuLock_IR);
c2b27bf2 14713+ hi_wh = au_hi_wh(inode, cpg.bdst);
7f207e10
AM
14714+ if (!S_ISDIR(inode->i_mode)
14715+ && au_opt_test(au_mntflags(sb), PLINK)
4a4d8108 14716+ && au_plink_test(inode)
c2b27bf2 14717+ && !d_unhashed(cpg.dentry)
5afbbe0d 14718+ && cpg.bdst < au_dbtop(cpg.dentry)) {
c2b27bf2 14719+ err = au_test_and_cpup_dirs(cpg.dentry, cpg.bdst);
4a4d8108
AM
14720+ if (unlikely(err))
14721+ goto out_unlock;
14722+
14723+ /* always superio. */
c2b27bf2 14724+ err = au_pin(&pin, cpg.dentry, cpg.bdst, AuOpt_UDBA_NONE,
4a4d8108 14725+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
367653fa 14726+ if (!err) {
c2b27bf2 14727+ err = au_sio_cpup_simple(&cpg);
367653fa
AM
14728+ au_unpin(&pin);
14729+ }
4a4d8108
AM
14730+ } else if (hi_wh) {
14731+ /* already copied-up after unlink */
c2b27bf2 14732+ err = au_reopen_wh(file, cpg.bdst, hi_wh);
4a4d8108
AM
14733+ *need_reopen = 0;
14734+ }
1facf9fc 14735+
4f0767ce 14736+out_unlock:
4a4d8108 14737+ di_read_unlock(parent, AuLock_IR);
4f0767ce 14738+out_parent:
4a4d8108 14739+ dput(parent);
4f0767ce 14740+out:
1308ab2a 14741+ return err;
dece6358 14742+}
1facf9fc 14743+
4a4d8108 14744+static void au_do_refresh_dir(struct file *file)
dece6358 14745+{
5afbbe0d 14746+ aufs_bindex_t bindex, bbot, new_bindex, brid;
4a4d8108
AM
14747+ struct au_hfile *p, tmp, *q;
14748+ struct au_finfo *finfo;
1308ab2a 14749+ struct super_block *sb;
4a4d8108 14750+ struct au_fidir *fidir;
1facf9fc 14751+
4a4d8108 14752+ FiMustWriteLock(file);
1facf9fc 14753+
2000de60 14754+ sb = file->f_path.dentry->d_sb;
4a4d8108
AM
14755+ finfo = au_fi(file);
14756+ fidir = finfo->fi_hdir;
14757+ AuDebugOn(!fidir);
14758+ p = fidir->fd_hfile + finfo->fi_btop;
14759+ brid = p->hf_br->br_id;
5afbbe0d
AM
14760+ bbot = fidir->fd_bbot;
14761+ for (bindex = finfo->fi_btop; bindex <= bbot; bindex++, p++) {
4a4d8108
AM
14762+ if (!p->hf_file)
14763+ continue;
1308ab2a 14764+
4a4d8108
AM
14765+ new_bindex = au_br_index(sb, p->hf_br->br_id);
14766+ if (new_bindex == bindex)
14767+ continue;
14768+ if (new_bindex < 0) {
14769+ au_set_h_fptr(file, bindex, NULL);
14770+ continue;
14771+ }
1308ab2a 14772+
4a4d8108
AM
14773+ /* swap two lower inode, and loop again */
14774+ q = fidir->fd_hfile + new_bindex;
14775+ tmp = *q;
14776+ *q = *p;
14777+ *p = tmp;
14778+ if (tmp.hf_file) {
14779+ bindex--;
14780+ p--;
14781+ }
14782+ }
1308ab2a 14783+
4a4d8108 14784+ p = fidir->fd_hfile;
2000de60 14785+ if (!au_test_mmapped(file) && !d_unlinked(file->f_path.dentry)) {
5afbbe0d
AM
14786+ bbot = au_sbbot(sb);
14787+ for (finfo->fi_btop = 0; finfo->fi_btop <= bbot;
4a4d8108
AM
14788+ finfo->fi_btop++, p++)
14789+ if (p->hf_file) {
c06a8ce3 14790+ if (file_inode(p->hf_file))
4a4d8108 14791+ break;
1c60b727 14792+ au_hfput(p, /*execed*/0);
4a4d8108
AM
14793+ }
14794+ } else {
5afbbe0d
AM
14795+ bbot = au_br_index(sb, brid);
14796+ for (finfo->fi_btop = 0; finfo->fi_btop < bbot;
4a4d8108
AM
14797+ finfo->fi_btop++, p++)
14798+ if (p->hf_file)
1c60b727 14799+ au_hfput(p, /*execed*/0);
5afbbe0d 14800+ bbot = au_sbbot(sb);
4a4d8108 14801+ }
1308ab2a 14802+
5afbbe0d
AM
14803+ p = fidir->fd_hfile + bbot;
14804+ for (fidir->fd_bbot = bbot; fidir->fd_bbot >= finfo->fi_btop;
4a4d8108
AM
14805+ fidir->fd_bbot--, p--)
14806+ if (p->hf_file) {
c06a8ce3 14807+ if (file_inode(p->hf_file))
4a4d8108 14808+ break;
1c60b727 14809+ au_hfput(p, /*execed*/0);
4a4d8108
AM
14810+ }
14811+ AuDebugOn(fidir->fd_bbot < finfo->fi_btop);
1308ab2a 14812+}
14813+
4a4d8108
AM
14814+/*
14815+ * after branch manipulating, refresh the file.
14816+ */
14817+static int refresh_file(struct file *file, int (*reopen)(struct file *file))
1facf9fc 14818+{
e2f27e51 14819+ int err, need_reopen, nbr;
5afbbe0d 14820+ aufs_bindex_t bbot, bindex;
4a4d8108 14821+ struct dentry *dentry;
e2f27e51 14822+ struct super_block *sb;
1308ab2a 14823+ struct au_finfo *finfo;
4a4d8108 14824+ struct au_hfile *hfile;
1facf9fc 14825+
2000de60 14826+ dentry = file->f_path.dentry;
e2f27e51
AM
14827+ sb = dentry->d_sb;
14828+ nbr = au_sbbot(sb) + 1;
1308ab2a 14829+ finfo = au_fi(file);
4a4d8108
AM
14830+ if (!finfo->fi_hdir) {
14831+ hfile = &finfo->fi_htop;
14832+ AuDebugOn(!hfile->hf_file);
e2f27e51 14833+ bindex = au_br_index(sb, hfile->hf_br->br_id);
4a4d8108
AM
14834+ AuDebugOn(bindex < 0);
14835+ if (bindex != finfo->fi_btop)
5afbbe0d 14836+ au_set_fbtop(file, bindex);
4a4d8108 14837+ } else {
e2f27e51 14838+ err = au_fidir_realloc(finfo, nbr, /*may_shrink*/0);
4a4d8108
AM
14839+ if (unlikely(err))
14840+ goto out;
14841+ au_do_refresh_dir(file);
14842+ }
1facf9fc 14843+
4a4d8108
AM
14844+ err = 0;
14845+ need_reopen = 1;
14846+ if (!au_test_mmapped(file))
14847+ err = au_file_refresh_by_inode(file, &need_reopen);
e2f27e51
AM
14848+ if (finfo->fi_hdir)
14849+ /* harmless if err */
14850+ au_fidir_realloc(finfo, nbr, /*may_shrink*/1);
027c5e7a 14851+ if (!err && need_reopen && !d_unlinked(dentry))
4a4d8108
AM
14852+ err = reopen(file);
14853+ if (!err) {
14854+ au_update_figen(file);
14855+ goto out; /* success */
14856+ }
14857+
14858+ /* error, close all lower files */
14859+ if (finfo->fi_hdir) {
5afbbe0d
AM
14860+ bbot = au_fbbot_dir(file);
14861+ for (bindex = au_fbtop(file); bindex <= bbot; bindex++)
4a4d8108
AM
14862+ au_set_h_fptr(file, bindex, NULL);
14863+ }
1facf9fc 14864+
4f0767ce 14865+out:
1facf9fc 14866+ return err;
14867+}
14868+
4a4d8108
AM
14869+/* common function to regular file and dir */
14870+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
521ced18 14871+ int wlock, unsigned int fi_lsc)
dece6358 14872+{
1308ab2a 14873+ int err;
4a4d8108 14874+ unsigned int sigen, figen;
5afbbe0d 14875+ aufs_bindex_t btop;
4a4d8108
AM
14876+ unsigned char pseudo_link;
14877+ struct dentry *dentry;
14878+ struct inode *inode;
1facf9fc 14879+
4a4d8108 14880+ err = 0;
2000de60 14881+ dentry = file->f_path.dentry;
5527c038 14882+ inode = d_inode(dentry);
4a4d8108 14883+ sigen = au_sigen(dentry->d_sb);
521ced18 14884+ fi_write_lock_nested(file, fi_lsc);
4a4d8108 14885+ figen = au_figen(file);
521ced18
JR
14886+ if (!fi_lsc)
14887+ di_write_lock_child(dentry);
14888+ else
14889+ di_write_lock_child2(dentry);
5afbbe0d
AM
14890+ btop = au_dbtop(dentry);
14891+ pseudo_link = (btop != au_ibtop(inode));
14892+ if (sigen == figen && !pseudo_link && au_fbtop(file) == btop) {
4a4d8108
AM
14893+ if (!wlock) {
14894+ di_downgrade_lock(dentry, AuLock_IR);
14895+ fi_downgrade_lock(file);
14896+ }
14897+ goto out; /* success */
14898+ }
dece6358 14899+
4a4d8108 14900+ AuDbg("sigen %d, figen %d\n", sigen, figen);
027c5e7a 14901+ if (au_digen_test(dentry, sigen)) {
4a4d8108 14902+ err = au_reval_dpath(dentry, sigen);
027c5e7a 14903+ AuDebugOn(!err && au_digen_test(dentry, sigen));
4a4d8108 14904+ }
dece6358 14905+
027c5e7a
AM
14906+ if (!err)
14907+ err = refresh_file(file, reopen);
4a4d8108
AM
14908+ if (!err) {
14909+ if (!wlock) {
14910+ di_downgrade_lock(dentry, AuLock_IR);
14911+ fi_downgrade_lock(file);
14912+ }
14913+ } else {
14914+ di_write_unlock(dentry);
14915+ fi_write_unlock(file);
14916+ }
1facf9fc 14917+
4f0767ce 14918+out:
1308ab2a 14919+ return err;
14920+}
1facf9fc 14921+
4a4d8108
AM
14922+/* ---------------------------------------------------------------------- */
14923+
14924+/* cf. aufs_nopage() */
14925+/* for madvise(2) */
14926+static int aufs_readpage(struct file *file __maybe_unused, struct page *page)
1308ab2a 14927+{
4a4d8108
AM
14928+ unlock_page(page);
14929+ return 0;
14930+}
1facf9fc 14931+
4a4d8108 14932+/* it will never be called, but necessary to support O_DIRECT */
5afbbe0d 14933+static ssize_t aufs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
4a4d8108 14934+{ BUG(); return 0; }
1facf9fc 14935+
4a4d8108
AM
14936+/* they will never be called. */
14937+#ifdef CONFIG_AUFS_DEBUG
14938+static int aufs_write_begin(struct file *file, struct address_space *mapping,
14939+ loff_t pos, unsigned len, unsigned flags,
14940+ struct page **pagep, void **fsdata)
14941+{ AuUnsupport(); return 0; }
14942+static int aufs_write_end(struct file *file, struct address_space *mapping,
14943+ loff_t pos, unsigned len, unsigned copied,
14944+ struct page *page, void *fsdata)
14945+{ AuUnsupport(); return 0; }
14946+static int aufs_writepage(struct page *page, struct writeback_control *wbc)
14947+{ AuUnsupport(); return 0; }
1308ab2a 14948+
4a4d8108
AM
14949+static int aufs_set_page_dirty(struct page *page)
14950+{ AuUnsupport(); return 0; }
392086de
AM
14951+static void aufs_invalidatepage(struct page *page, unsigned int offset,
14952+ unsigned int length)
4a4d8108
AM
14953+{ AuUnsupport(); }
14954+static int aufs_releasepage(struct page *page, gfp_t gfp)
14955+{ AuUnsupport(); return 0; }
79b8bda9 14956+#if 0 /* called by memory compaction regardless file */
4a4d8108 14957+static int aufs_migratepage(struct address_space *mapping, struct page *newpage,
7eafdf33 14958+ struct page *page, enum migrate_mode mode)
4a4d8108 14959+{ AuUnsupport(); return 0; }
79b8bda9 14960+#endif
e2f27e51
AM
14961+static bool aufs_isolate_page(struct page *page, isolate_mode_t mode)
14962+{ AuUnsupport(); return true; }
14963+static void aufs_putback_page(struct page *page)
14964+{ AuUnsupport(); }
4a4d8108
AM
14965+static int aufs_launder_page(struct page *page)
14966+{ AuUnsupport(); return 0; }
14967+static int aufs_is_partially_uptodate(struct page *page,
38d290e6
JR
14968+ unsigned long from,
14969+ unsigned long count)
4a4d8108 14970+{ AuUnsupport(); return 0; }
392086de
AM
14971+static void aufs_is_dirty_writeback(struct page *page, bool *dirty,
14972+ bool *writeback)
14973+{ AuUnsupport(); }
4a4d8108
AM
14974+static int aufs_error_remove_page(struct address_space *mapping,
14975+ struct page *page)
14976+{ AuUnsupport(); return 0; }
b4510431
AM
14977+static int aufs_swap_activate(struct swap_info_struct *sis, struct file *file,
14978+ sector_t *span)
14979+{ AuUnsupport(); return 0; }
14980+static void aufs_swap_deactivate(struct file *file)
14981+{ AuUnsupport(); }
4a4d8108
AM
14982+#endif /* CONFIG_AUFS_DEBUG */
14983+
14984+const struct address_space_operations aufs_aop = {
14985+ .readpage = aufs_readpage,
14986+ .direct_IO = aufs_direct_IO,
4a4d8108
AM
14987+#ifdef CONFIG_AUFS_DEBUG
14988+ .writepage = aufs_writepage,
4a4d8108
AM
14989+ /* no writepages, because of writepage */
14990+ .set_page_dirty = aufs_set_page_dirty,
14991+ /* no readpages, because of readpage */
14992+ .write_begin = aufs_write_begin,
14993+ .write_end = aufs_write_end,
14994+ /* no bmap, no block device */
14995+ .invalidatepage = aufs_invalidatepage,
14996+ .releasepage = aufs_releasepage,
79b8bda9
AM
14997+ /* is fallback_migrate_page ok? */
14998+ /* .migratepage = aufs_migratepage, */
e2f27e51
AM
14999+ .isolate_page = aufs_isolate_page,
15000+ .putback_page = aufs_putback_page,
4a4d8108
AM
15001+ .launder_page = aufs_launder_page,
15002+ .is_partially_uptodate = aufs_is_partially_uptodate,
392086de 15003+ .is_dirty_writeback = aufs_is_dirty_writeback,
b4510431
AM
15004+ .error_remove_page = aufs_error_remove_page,
15005+ .swap_activate = aufs_swap_activate,
15006+ .swap_deactivate = aufs_swap_deactivate
4a4d8108 15007+#endif /* CONFIG_AUFS_DEBUG */
dece6358 15008+};
7f207e10 15009diff -urN /usr/share/empty/fs/aufs/file.h linux/fs/aufs/file.h
eca34b5c 15010--- /usr/share/empty/fs/aufs/file.h 1970-01-01 01:00:00.000000000 +0100
016522bc 15011+++ linux/fs/aufs/file.h 2020-01-27 10:57:18.172204883 +0100
9f237c51 15012@@ -0,0 +1,342 @@
062440b3 15013+/* SPDX-License-Identifier: GPL-2.0 */
4a4d8108 15014+/*
016522bc 15015+ * Copyright (C) 2005-2020 Junjiro R. Okajima
4a4d8108
AM
15016+ *
15017+ * This program, aufs is free software; you can redistribute it and/or modify
15018+ * it under the terms of the GNU General Public License as published by
15019+ * the Free Software Foundation; either version 2 of the License, or
15020+ * (at your option) any later version.
15021+ *
15022+ * This program is distributed in the hope that it will be useful,
15023+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15024+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15025+ * GNU General Public License for more details.
15026+ *
15027+ * You should have received a copy of the GNU General Public License
523b37e3 15028+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 15029+ */
1facf9fc 15030+
4a4d8108
AM
15031+/*
15032+ * file operations
15033+ */
1facf9fc 15034+
4a4d8108
AM
15035+#ifndef __AUFS_FILE_H__
15036+#define __AUFS_FILE_H__
1facf9fc 15037+
4a4d8108 15038+#ifdef __KERNEL__
1facf9fc 15039+
2cbb1c4b 15040+#include <linux/file.h>
4a4d8108 15041+#include <linux/fs.h>
3c1bdaff 15042+#include <linux/mm_types.h>
4a4d8108 15043+#include <linux/poll.h>
4a4d8108 15044+#include "rwsem.h"
1facf9fc 15045+
4a4d8108
AM
15046+struct au_branch;
15047+struct au_hfile {
15048+ struct file *hf_file;
15049+ struct au_branch *hf_br;
15050+};
1facf9fc 15051+
4a4d8108
AM
15052+struct au_vdir;
15053+struct au_fidir {
15054+ aufs_bindex_t fd_bbot;
15055+ aufs_bindex_t fd_nent;
15056+ struct au_vdir *fd_vdir_cache;
15057+ struct au_hfile fd_hfile[];
15058+};
1facf9fc 15059+
4a4d8108 15060+static inline int au_fidir_sz(int nent)
dece6358 15061+{
4f0767ce
JR
15062+ AuDebugOn(nent < 0);
15063+ return sizeof(struct au_fidir) + sizeof(struct au_hfile) * nent;
4a4d8108 15064+}
1facf9fc 15065+
4a4d8108
AM
15066+struct au_finfo {
15067+ atomic_t fi_generation;
dece6358 15068+
4a4d8108
AM
15069+ struct au_rwsem fi_rwsem;
15070+ aufs_bindex_t fi_btop;
15071+
15072+ /* do not union them */
15073+ struct { /* for non-dir */
15074+ struct au_hfile fi_htop;
2cbb1c4b 15075+ atomic_t fi_mmapped;
4a4d8108
AM
15076+ };
15077+ struct au_fidir *fi_hdir; /* for dir only */
523b37e3 15078+
8b6a4947 15079+ struct hlist_bl_node fi_hlist;
1c60b727 15080+ struct file *fi_file; /* very ugly */
9f237c51 15081+ struct rcu_head rcu;
4a4d8108 15082+} ____cacheline_aligned_in_smp;
1facf9fc 15083+
4a4d8108 15084+/* ---------------------------------------------------------------------- */
1facf9fc 15085+
4a4d8108
AM
15086+/* file.c */
15087+extern const struct address_space_operations aufs_aop;
15088+unsigned int au_file_roflags(unsigned int flags);
15089+struct file *au_h_open(struct dentry *dentry, aufs_bindex_t bindex, int flags,
392086de 15090+ struct file *file, int force_wr);
b912730e 15091+struct au_do_open_args {
8b6a4947 15092+ int aopen;
b912730e
AM
15093+ int (*open)(struct file *file, int flags,
15094+ struct file *h_file);
15095+ struct au_fidir *fidir;
15096+ struct file *h_file;
15097+};
15098+int au_do_open(struct file *file, struct au_do_open_args *args);
4a4d8108
AM
15099+int au_reopen_nondir(struct file *file);
15100+struct au_pin;
15101+int au_ready_to_write(struct file *file, loff_t len, struct au_pin *pin);
15102+int au_reval_and_lock_fdi(struct file *file, int (*reopen)(struct file *file),
521ced18 15103+ int wlock, unsigned int fi_lsc);
4a4d8108
AM
15104+int au_do_flush(struct file *file, fl_owner_t id,
15105+ int (*flush)(struct file *file, fl_owner_t id));
1facf9fc 15106+
4a4d8108
AM
15107+/* poll.c */
15108+#ifdef CONFIG_AUFS_POLL
cd7a4cd9 15109+__poll_t aufs_poll(struct file *file, struct poll_table_struct *pt);
4a4d8108 15110+#endif
1facf9fc 15111+
4a4d8108
AM
15112+#ifdef CONFIG_AUFS_BR_HFSPLUS
15113+/* hfsplus.c */
392086de
AM
15114+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex,
15115+ int force_wr);
4a4d8108
AM
15116+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
15117+ struct file *h_file);
15118+#else
c1595e42
JR
15119+AuStub(struct file *, au_h_open_pre, return NULL, struct dentry *dentry,
15120+ aufs_bindex_t bindex, int force_wr)
4a4d8108
AM
15121+AuStubVoid(au_h_open_post, struct dentry *dentry, aufs_bindex_t bindex,
15122+ struct file *h_file);
15123+#endif
1facf9fc 15124+
4a4d8108
AM
15125+/* f_op.c */
15126+extern const struct file_operations aufs_file_fop;
b912730e 15127+int au_do_open_nondir(struct file *file, int flags, struct file *h_file);
4a4d8108 15128+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file);
521ced18 15129+struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc);
4a4d8108 15130+
4a4d8108 15131+/* finfo.c */
f0c0a007 15132+void au_hfput(struct au_hfile *hf, int execed);
4a4d8108
AM
15133+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex,
15134+ struct file *h_file);
1facf9fc 15135+
4a4d8108 15136+void au_update_figen(struct file *file);
4a4d8108 15137+struct au_fidir *au_fidir_alloc(struct super_block *sb);
e2f27e51 15138+int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink);
1facf9fc 15139+
4a4d8108 15140+void au_fi_init_once(void *_fi);
1c60b727 15141+void au_finfo_fin(struct file *file);
4a4d8108 15142+int au_finfo_init(struct file *file, struct au_fidir *fidir);
1facf9fc 15143+
4a4d8108
AM
15144+/* ioctl.c */
15145+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg);
b752ccd1
AM
15146+#ifdef CONFIG_COMPAT
15147+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
15148+ unsigned long arg);
c2b27bf2
AM
15149+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
15150+ unsigned long arg);
b752ccd1 15151+#endif
1facf9fc 15152+
4a4d8108 15153+/* ---------------------------------------------------------------------- */
1facf9fc 15154+
4a4d8108
AM
15155+static inline struct au_finfo *au_fi(struct file *file)
15156+{
38d290e6 15157+ return file->private_data;
4a4d8108 15158+}
1facf9fc 15159+
4a4d8108 15160+/* ---------------------------------------------------------------------- */
1facf9fc 15161+
8b6a4947
AM
15162+#define fi_read_lock(f) au_rw_read_lock(&au_fi(f)->fi_rwsem)
15163+#define fi_write_lock(f) au_rw_write_lock(&au_fi(f)->fi_rwsem)
15164+#define fi_read_trylock(f) au_rw_read_trylock(&au_fi(f)->fi_rwsem)
15165+#define fi_write_trylock(f) au_rw_write_trylock(&au_fi(f)->fi_rwsem)
4a4d8108 15166+/*
8b6a4947
AM
15167+#define fi_read_trylock_nested(f) \
15168+ au_rw_read_trylock_nested(&au_fi(f)->fi_rwsem)
15169+#define fi_write_trylock_nested(f) \
15170+ au_rw_write_trylock_nested(&au_fi(f)->fi_rwsem)
15171+*/
15172+
15173+#define fi_read_unlock(f) au_rw_read_unlock(&au_fi(f)->fi_rwsem)
15174+#define fi_write_unlock(f) au_rw_write_unlock(&au_fi(f)->fi_rwsem)
15175+#define fi_downgrade_lock(f) au_rw_dgrade_lock(&au_fi(f)->fi_rwsem)
1308ab2a 15176+
521ced18
JR
15177+/* lock subclass for finfo */
15178+enum {
15179+ AuLsc_FI_1,
15180+ AuLsc_FI_2
15181+};
15182+
15183+static inline void fi_read_lock_nested(struct file *f, unsigned int lsc)
15184+{
15185+ au_rw_read_lock_nested(&au_fi(f)->fi_rwsem, lsc);
15186+}
15187+
15188+static inline void fi_write_lock_nested(struct file *f, unsigned int lsc)
15189+{
15190+ au_rw_write_lock_nested(&au_fi(f)->fi_rwsem, lsc);
15191+}
15192+
15193+/*
15194+ * fi_read_lock_1, fi_write_lock_1,
15195+ * fi_read_lock_2, fi_write_lock_2
15196+ */
15197+#define AuReadLockFunc(name) \
15198+static inline void fi_read_lock_##name(struct file *f) \
15199+{ fi_read_lock_nested(f, AuLsc_FI_##name); }
15200+
15201+#define AuWriteLockFunc(name) \
15202+static inline void fi_write_lock_##name(struct file *f) \
15203+{ fi_write_lock_nested(f, AuLsc_FI_##name); }
15204+
15205+#define AuRWLockFuncs(name) \
15206+ AuReadLockFunc(name) \
15207+ AuWriteLockFunc(name)
15208+
15209+AuRWLockFuncs(1);
15210+AuRWLockFuncs(2);
15211+
15212+#undef AuReadLockFunc
15213+#undef AuWriteLockFunc
15214+#undef AuRWLockFuncs
15215+
4a4d8108
AM
15216+#define FiMustNoWaiters(f) AuRwMustNoWaiters(&au_fi(f)->fi_rwsem)
15217+#define FiMustAnyLock(f) AuRwMustAnyLock(&au_fi(f)->fi_rwsem)
15218+#define FiMustWriteLock(f) AuRwMustWriteLock(&au_fi(f)->fi_rwsem)
1facf9fc 15219+
1308ab2a 15220+/* ---------------------------------------------------------------------- */
15221+
4a4d8108 15222+/* todo: hard/soft set? */
5afbbe0d 15223+static inline aufs_bindex_t au_fbtop(struct file *file)
dece6358 15224+{
4a4d8108
AM
15225+ FiMustAnyLock(file);
15226+ return au_fi(file)->fi_btop;
15227+}
dece6358 15228+
5afbbe0d 15229+static inline aufs_bindex_t au_fbbot_dir(struct file *file)
4a4d8108
AM
15230+{
15231+ FiMustAnyLock(file);
15232+ AuDebugOn(!au_fi(file)->fi_hdir);
15233+ return au_fi(file)->fi_hdir->fd_bbot;
15234+}
1facf9fc 15235+
4a4d8108
AM
15236+static inline struct au_vdir *au_fvdir_cache(struct file *file)
15237+{
15238+ FiMustAnyLock(file);
15239+ AuDebugOn(!au_fi(file)->fi_hdir);
15240+ return au_fi(file)->fi_hdir->fd_vdir_cache;
15241+}
1facf9fc 15242+
5afbbe0d 15243+static inline void au_set_fbtop(struct file *file, aufs_bindex_t bindex)
4a4d8108
AM
15244+{
15245+ FiMustWriteLock(file);
15246+ au_fi(file)->fi_btop = bindex;
15247+}
1facf9fc 15248+
5afbbe0d 15249+static inline void au_set_fbbot_dir(struct file *file, aufs_bindex_t bindex)
4a4d8108
AM
15250+{
15251+ FiMustWriteLock(file);
15252+ AuDebugOn(!au_fi(file)->fi_hdir);
15253+ au_fi(file)->fi_hdir->fd_bbot = bindex;
15254+}
1308ab2a 15255+
4a4d8108
AM
15256+static inline void au_set_fvdir_cache(struct file *file,
15257+ struct au_vdir *vdir_cache)
15258+{
15259+ FiMustWriteLock(file);
15260+ AuDebugOn(!au_fi(file)->fi_hdir);
15261+ au_fi(file)->fi_hdir->fd_vdir_cache = vdir_cache;
15262+}
dece6358 15263+
4a4d8108
AM
15264+static inline struct file *au_hf_top(struct file *file)
15265+{
15266+ FiMustAnyLock(file);
15267+ AuDebugOn(au_fi(file)->fi_hdir);
15268+ return au_fi(file)->fi_htop.hf_file;
15269+}
1facf9fc 15270+
4a4d8108
AM
15271+static inline struct file *au_hf_dir(struct file *file, aufs_bindex_t bindex)
15272+{
15273+ FiMustAnyLock(file);
15274+ AuDebugOn(!au_fi(file)->fi_hdir);
15275+ return au_fi(file)->fi_hdir->fd_hfile[0 + bindex].hf_file;
dece6358
AM
15276+}
15277+
4a4d8108
AM
15278+/* todo: memory barrier? */
15279+static inline unsigned int au_figen(struct file *f)
dece6358 15280+{
4a4d8108
AM
15281+ return atomic_read(&au_fi(f)->fi_generation);
15282+}
dece6358 15283+
2cbb1c4b
JR
15284+static inline void au_set_mmapped(struct file *f)
15285+{
15286+ if (atomic_inc_return(&au_fi(f)->fi_mmapped))
15287+ return;
0c3ec466 15288+ pr_warn("fi_mmapped wrapped around\n");
2cbb1c4b
JR
15289+ while (!atomic_inc_return(&au_fi(f)->fi_mmapped))
15290+ ;
15291+}
15292+
15293+static inline void au_unset_mmapped(struct file *f)
15294+{
15295+ atomic_dec(&au_fi(f)->fi_mmapped);
15296+}
15297+
4a4d8108
AM
15298+static inline int au_test_mmapped(struct file *f)
15299+{
2cbb1c4b
JR
15300+ return atomic_read(&au_fi(f)->fi_mmapped);
15301+}
15302+
15303+/* customize vma->vm_file */
15304+
15305+static inline void au_do_vm_file_reset(struct vm_area_struct *vma,
15306+ struct file *file)
15307+{
53392da6
AM
15308+ struct file *f;
15309+
15310+ f = vma->vm_file;
2cbb1c4b
JR
15311+ get_file(file);
15312+ vma->vm_file = file;
53392da6 15313+ fput(f);
2cbb1c4b
JR
15314+}
15315+
15316+#ifdef CONFIG_MMU
15317+#define AuDbgVmRegion(file, vma) do {} while (0)
15318+
15319+static inline void au_vm_file_reset(struct vm_area_struct *vma,
15320+ struct file *file)
15321+{
15322+ au_do_vm_file_reset(vma, file);
15323+}
15324+#else
15325+#define AuDbgVmRegion(file, vma) \
15326+ AuDebugOn((vma)->vm_region && (vma)->vm_region->vm_file != (file))
15327+
15328+static inline void au_vm_file_reset(struct vm_area_struct *vma,
15329+ struct file *file)
15330+{
53392da6
AM
15331+ struct file *f;
15332+
2cbb1c4b 15333+ au_do_vm_file_reset(vma, file);
53392da6 15334+ f = vma->vm_region->vm_file;
2cbb1c4b
JR
15335+ get_file(file);
15336+ vma->vm_region->vm_file = file;
53392da6 15337+ fput(f);
2cbb1c4b
JR
15338+}
15339+#endif /* CONFIG_MMU */
15340+
15341+/* handle vma->vm_prfile */
fb47a38f 15342+static inline void au_vm_prfile_set(struct vm_area_struct *vma,
2cbb1c4b
JR
15343+ struct file *file)
15344+{
2cbb1c4b
JR
15345+ get_file(file);
15346+ vma->vm_prfile = file;
15347+#ifndef CONFIG_MMU
15348+ get_file(file);
15349+ vma->vm_region->vm_prfile = file;
15350+#endif
fb47a38f 15351+}
1308ab2a 15352+
4a4d8108
AM
15353+#endif /* __KERNEL__ */
15354+#endif /* __AUFS_FILE_H__ */
7f207e10 15355diff -urN /usr/share/empty/fs/aufs/finfo.c linux/fs/aufs/finfo.c
eca34b5c 15356--- /usr/share/empty/fs/aufs/finfo.c 1970-01-01 01:00:00.000000000 +0100
016522bc 15357+++ linux/fs/aufs/finfo.c 2020-01-27 10:57:18.172204883 +0100
062440b3 15358@@ -0,0 +1,149 @@
cd7a4cd9 15359+// SPDX-License-Identifier: GPL-2.0
4a4d8108 15360+/*
016522bc 15361+ * Copyright (C) 2005-2020 Junjiro R. Okajima
4a4d8108
AM
15362+ *
15363+ * This program, aufs is free software; you can redistribute it and/or modify
15364+ * it under the terms of the GNU General Public License as published by
15365+ * the Free Software Foundation; either version 2 of the License, or
15366+ * (at your option) any later version.
15367+ *
15368+ * This program is distributed in the hope that it will be useful,
15369+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15370+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15371+ * GNU General Public License for more details.
15372+ *
15373+ * You should have received a copy of the GNU General Public License
523b37e3 15374+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 15375+ */
1308ab2a 15376+
4a4d8108
AM
15377+/*
15378+ * file private data
15379+ */
1facf9fc 15380+
4a4d8108 15381+#include "aufs.h"
1facf9fc 15382+
f0c0a007 15383+void au_hfput(struct au_hfile *hf, int execed)
4a4d8108 15384+{
f0c0a007 15385+ if (execed)
4a4d8108
AM
15386+ allow_write_access(hf->hf_file);
15387+ fput(hf->hf_file);
15388+ hf->hf_file = NULL;
acd2b654 15389+ au_lcnt_dec(&hf->hf_br->br_nfiles);
4a4d8108
AM
15390+ hf->hf_br = NULL;
15391+}
1facf9fc 15392+
4a4d8108
AM
15393+void au_set_h_fptr(struct file *file, aufs_bindex_t bindex, struct file *val)
15394+{
15395+ struct au_finfo *finfo = au_fi(file);
15396+ struct au_hfile *hf;
15397+ struct au_fidir *fidir;
15398+
15399+ fidir = finfo->fi_hdir;
15400+ if (!fidir) {
15401+ AuDebugOn(finfo->fi_btop != bindex);
15402+ hf = &finfo->fi_htop;
15403+ } else
15404+ hf = fidir->fd_hfile + bindex;
15405+
15406+ if (hf && hf->hf_file)
f0c0a007 15407+ au_hfput(hf, vfsub_file_execed(file));
4a4d8108
AM
15408+ if (val) {
15409+ FiMustWriteLock(file);
b912730e 15410+ AuDebugOn(IS_ERR_OR_NULL(file->f_path.dentry));
4a4d8108 15411+ hf->hf_file = val;
2000de60 15412+ hf->hf_br = au_sbr(file->f_path.dentry->d_sb, bindex);
1308ab2a 15413+ }
4a4d8108 15414+}
1facf9fc 15415+
4a4d8108
AM
15416+void au_update_figen(struct file *file)
15417+{
2000de60 15418+ atomic_set(&au_fi(file)->fi_generation, au_digen(file->f_path.dentry));
4a4d8108 15419+ /* smp_mb(); */ /* atomic_set */
1facf9fc 15420+}
15421+
4a4d8108
AM
15422+/* ---------------------------------------------------------------------- */
15423+
4a4d8108
AM
15424+struct au_fidir *au_fidir_alloc(struct super_block *sb)
15425+{
15426+ struct au_fidir *fidir;
15427+ int nbr;
15428+
5afbbe0d 15429+ nbr = au_sbbot(sb) + 1;
4a4d8108
AM
15430+ if (nbr < 2)
15431+ nbr = 2; /* initial allocate for 2 branches */
15432+ fidir = kzalloc(au_fidir_sz(nbr), GFP_NOFS);
15433+ if (fidir) {
15434+ fidir->fd_bbot = -1;
15435+ fidir->fd_nent = nbr;
4a4d8108
AM
15436+ }
15437+
15438+ return fidir;
15439+}
15440+
e2f27e51 15441+int au_fidir_realloc(struct au_finfo *finfo, int nbr, int may_shrink)
4a4d8108
AM
15442+{
15443+ int err;
15444+ struct au_fidir *fidir, *p;
15445+
15446+ AuRwMustWriteLock(&finfo->fi_rwsem);
15447+ fidir = finfo->fi_hdir;
15448+ AuDebugOn(!fidir);
15449+
15450+ err = -ENOMEM;
15451+ p = au_kzrealloc(fidir, au_fidir_sz(fidir->fd_nent), au_fidir_sz(nbr),
e2f27e51 15452+ GFP_NOFS, may_shrink);
4a4d8108
AM
15453+ if (p) {
15454+ p->fd_nent = nbr;
15455+ finfo->fi_hdir = p;
15456+ err = 0;
15457+ }
1facf9fc 15458+
dece6358 15459+ return err;
1facf9fc 15460+}
1308ab2a 15461+
15462+/* ---------------------------------------------------------------------- */
15463+
1c60b727 15464+void au_finfo_fin(struct file *file)
1308ab2a 15465+{
4a4d8108
AM
15466+ struct au_finfo *finfo;
15467+
acd2b654 15468+ au_lcnt_dec(&au_sbi(file->f_path.dentry->d_sb)->si_nfiles);
7f207e10 15469+
4a4d8108
AM
15470+ finfo = au_fi(file);
15471+ AuDebugOn(finfo->fi_hdir);
15472+ AuRwDestroy(&finfo->fi_rwsem);
1c60b727 15473+ au_cache_free_finfo(finfo);
1308ab2a 15474+}
1308ab2a 15475+
e49829fe 15476+void au_fi_init_once(void *_finfo)
4a4d8108 15477+{
e49829fe 15478+ struct au_finfo *finfo = _finfo;
1308ab2a 15479+
e49829fe 15480+ au_rw_init(&finfo->fi_rwsem);
4a4d8108 15481+}
1308ab2a 15482+
4a4d8108
AM
15483+int au_finfo_init(struct file *file, struct au_fidir *fidir)
15484+{
1716fcea 15485+ int err;
4a4d8108
AM
15486+ struct au_finfo *finfo;
15487+ struct dentry *dentry;
15488+
15489+ err = -ENOMEM;
2000de60 15490+ dentry = file->f_path.dentry;
4a4d8108
AM
15491+ finfo = au_cache_alloc_finfo();
15492+ if (unlikely(!finfo))
15493+ goto out;
15494+
15495+ err = 0;
acd2b654 15496+ au_lcnt_inc(&au_sbi(dentry->d_sb)->si_nfiles);
4a4d8108
AM
15497+ au_rw_write_lock(&finfo->fi_rwsem);
15498+ finfo->fi_btop = -1;
15499+ finfo->fi_hdir = fidir;
15500+ atomic_set(&finfo->fi_generation, au_digen(dentry));
15501+ /* smp_mb(); */ /* atomic_set */
15502+
15503+ file->private_data = finfo;
15504+
15505+out:
15506+ return err;
15507+}
7f207e10 15508diff -urN /usr/share/empty/fs/aufs/f_op.c linux/fs/aufs/f_op.c
eca34b5c 15509--- /usr/share/empty/fs/aufs/f_op.c 1970-01-01 01:00:00.000000000 +0100
016522bc 15510+++ linux/fs/aufs/f_op.c 2020-01-27 10:57:18.172204883 +0100
acd2b654 15511@@ -0,0 +1,819 @@
cd7a4cd9 15512+// SPDX-License-Identifier: GPL-2.0
dece6358 15513+/*
016522bc 15514+ * Copyright (C) 2005-2020 Junjiro R. Okajima
dece6358
AM
15515+ *
15516+ * This program, aufs is free software; you can redistribute it and/or modify
15517+ * it under the terms of the GNU General Public License as published by
15518+ * the Free Software Foundation; either version 2 of the License, or
15519+ * (at your option) any later version.
15520+ *
15521+ * This program is distributed in the hope that it will be useful,
15522+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15523+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15524+ * GNU General Public License for more details.
15525+ *
15526+ * You should have received a copy of the GNU General Public License
523b37e3 15527+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
dece6358 15528+ */
1facf9fc 15529+
15530+/*
4a4d8108 15531+ * file and vm operations
1facf9fc 15532+ */
dece6358 15533+
86dc4139 15534+#include <linux/aio.h>
4a4d8108
AM
15535+#include <linux/fs_stack.h>
15536+#include <linux/mman.h>
4a4d8108 15537+#include <linux/security.h>
dece6358
AM
15538+#include "aufs.h"
15539+
b912730e 15540+int au_do_open_nondir(struct file *file, int flags, struct file *h_file)
1facf9fc 15541+{
4a4d8108
AM
15542+ int err;
15543+ aufs_bindex_t bindex;
8cdd5066 15544+ struct dentry *dentry, *h_dentry;
4a4d8108 15545+ struct au_finfo *finfo;
38d290e6 15546+ struct inode *h_inode;
4a4d8108
AM
15547+
15548+ FiMustWriteLock(file);
15549+
523b37e3 15550+ err = 0;
2000de60 15551+ dentry = file->f_path.dentry;
b912730e 15552+ AuDebugOn(IS_ERR_OR_NULL(dentry));
4a4d8108
AM
15553+ finfo = au_fi(file);
15554+ memset(&finfo->fi_htop, 0, sizeof(finfo->fi_htop));
2cbb1c4b 15555+ atomic_set(&finfo->fi_mmapped, 0);
5afbbe0d 15556+ bindex = au_dbtop(dentry);
8cdd5066
JR
15557+ if (!h_file) {
15558+ h_dentry = au_h_dptr(dentry, bindex);
15559+ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb);
15560+ if (unlikely(err))
15561+ goto out;
b912730e 15562+ h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0);
acd2b654
AM
15563+ if (IS_ERR(h_file)) {
15564+ err = PTR_ERR(h_file);
15565+ goto out;
15566+ }
8cdd5066
JR
15567+ } else {
15568+ h_dentry = h_file->f_path.dentry;
15569+ err = vfsub_test_mntns(file->f_path.mnt, h_dentry->d_sb);
15570+ if (unlikely(err))
15571+ goto out;
acd2b654 15572+ /* br ref is already inc-ed */
8cdd5066 15573+ }
acd2b654
AM
15574+
15575+ if ((flags & __O_TMPFILE)
15576+ && !(flags & O_EXCL)) {
15577+ h_inode = file_inode(h_file);
15578+ spin_lock(&h_inode->i_lock);
15579+ h_inode->i_state |= I_LINKABLE;
15580+ spin_unlock(&h_inode->i_lock);
4a4d8108 15581+ }
acd2b654
AM
15582+ au_set_fbtop(file, bindex);
15583+ au_set_h_fptr(file, bindex, h_file);
15584+ au_update_figen(file);
15585+ /* todo: necessary? */
15586+ /* file->f_ra = h_file->f_ra; */
027c5e7a 15587+
8cdd5066 15588+out:
4a4d8108 15589+ return err;
1facf9fc 15590+}
15591+
4a4d8108
AM
15592+static int aufs_open_nondir(struct inode *inode __maybe_unused,
15593+ struct file *file)
1facf9fc 15594+{
4a4d8108 15595+ int err;
1308ab2a 15596+ struct super_block *sb;
b912730e
AM
15597+ struct au_do_open_args args = {
15598+ .open = au_do_open_nondir
15599+ };
1facf9fc 15600+
523b37e3
AM
15601+ AuDbg("%pD, f_flags 0x%x, f_mode 0x%x\n",
15602+ file, vfsub_file_flags(file), file->f_mode);
1facf9fc 15603+
2000de60 15604+ sb = file->f_path.dentry->d_sb;
4a4d8108 15605+ si_read_lock(sb, AuLock_FLUSH);
b912730e 15606+ err = au_do_open(file, &args);
4a4d8108
AM
15607+ si_read_unlock(sb);
15608+ return err;
15609+}
1facf9fc 15610+
4a4d8108
AM
15611+int aufs_release_nondir(struct inode *inode __maybe_unused, struct file *file)
15612+{
15613+ struct au_finfo *finfo;
15614+ aufs_bindex_t bindex;
1facf9fc 15615+
4a4d8108 15616+ finfo = au_fi(file);
8b6a4947
AM
15617+ au_hbl_del(&finfo->fi_hlist,
15618+ &au_sbi(file->f_path.dentry->d_sb)->si_files);
4a4d8108 15619+ bindex = finfo->fi_btop;
b4510431 15620+ if (bindex >= 0)
4a4d8108 15621+ au_set_h_fptr(file, bindex, NULL);
7f207e10 15622+
1c60b727 15623+ au_finfo_fin(file);
4a4d8108 15624+ return 0;
1facf9fc 15625+}
15626+
4a4d8108
AM
15627+/* ---------------------------------------------------------------------- */
15628+
15629+static int au_do_flush_nondir(struct file *file, fl_owner_t id)
dece6358 15630+{
1308ab2a 15631+ int err;
4a4d8108
AM
15632+ struct file *h_file;
15633+
15634+ err = 0;
15635+ h_file = au_hf_top(file);
15636+ if (h_file)
15637+ err = vfsub_flush(h_file, id);
15638+ return err;
15639+}
15640+
15641+static int aufs_flush_nondir(struct file *file, fl_owner_t id)
15642+{
15643+ return au_do_flush(file, id, au_do_flush_nondir);
15644+}
15645+
15646+/* ---------------------------------------------------------------------- */
9dbd164d
AM
15647+/*
15648+ * read and write functions acquire [fdi]_rwsem once, but release before
15649+ * mmap_sem. This is because to stop a race condition between mmap(2).
acd2b654 15650+ * Releasing these aufs-rwsem should be safe, no branch-management (by keeping
9dbd164d
AM
15651+ * si_rwsem), no harmful copy-up should happen. Actually copy-up may happen in
15652+ * read functions after [fdi]_rwsem are released, but it should be harmless.
15653+ */
4a4d8108 15654+
b912730e 15655+/* Callers should call au_read_post() or fput() in the end */
521ced18 15656+struct file *au_read_pre(struct file *file, int keep_fi, unsigned int lsc)
4a4d8108 15657+{
4a4d8108 15658+ struct file *h_file;
b912730e 15659+ int err;
1facf9fc 15660+
521ced18 15661+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/0, lsc);
b912730e
AM
15662+ if (!err) {
15663+ di_read_unlock(file->f_path.dentry, AuLock_IR);
15664+ h_file = au_hf_top(file);
15665+ get_file(h_file);
15666+ if (!keep_fi)
15667+ fi_read_unlock(file);
15668+ } else
15669+ h_file = ERR_PTR(err);
15670+
15671+ return h_file;
15672+}
15673+
15674+static void au_read_post(struct inode *inode, struct file *h_file)
15675+{
15676+ /* update without lock, I don't think it a problem */
15677+ fsstack_copy_attr_atime(inode, file_inode(h_file));
15678+ fput(h_file);
15679+}
15680+
15681+struct au_write_pre {
521ced18
JR
15682+ /* input */
15683+ unsigned int lsc;
15684+
15685+ /* output */
b912730e 15686+ blkcnt_t blks;
5afbbe0d 15687+ aufs_bindex_t btop;
b912730e
AM
15688+};
15689+
15690+/*
15691+ * return with iinfo is write-locked
15692+ * callers should call au_write_post() or iinfo_write_unlock() + fput() in the
15693+ * end
15694+ */
15695+static struct file *au_write_pre(struct file *file, int do_ready,
15696+ struct au_write_pre *wpre)
15697+{
15698+ struct file *h_file;
15699+ struct dentry *dentry;
15700+ int err;
521ced18 15701+ unsigned int lsc;
b912730e
AM
15702+ struct au_pin pin;
15703+
521ced18
JR
15704+ lsc = 0;
15705+ if (wpre)
15706+ lsc = wpre->lsc;
15707+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1, lsc);
b912730e 15708+ h_file = ERR_PTR(err);
dece6358
AM
15709+ if (unlikely(err))
15710+ goto out;
1facf9fc 15711+
b912730e
AM
15712+ dentry = file->f_path.dentry;
15713+ if (do_ready) {
15714+ err = au_ready_to_write(file, -1, &pin);
15715+ if (unlikely(err)) {
15716+ h_file = ERR_PTR(err);
15717+ di_write_unlock(dentry);
15718+ goto out_fi;
15719+ }
15720+ }
15721+
15722+ di_downgrade_lock(dentry, /*flags*/0);
15723+ if (wpre)
5afbbe0d 15724+ wpre->btop = au_fbtop(file);
4a4d8108 15725+ h_file = au_hf_top(file);
9dbd164d 15726+ get_file(h_file);
b912730e
AM
15727+ if (wpre)
15728+ wpre->blks = file_inode(h_file)->i_blocks;
15729+ if (do_ready)
15730+ au_unpin(&pin);
15731+ di_read_unlock(dentry, /*flags*/0);
15732+
15733+out_fi:
15734+ fi_write_unlock(file);
15735+out:
15736+ return h_file;
15737+}
15738+
15739+static void au_write_post(struct inode *inode, struct file *h_file,
15740+ struct au_write_pre *wpre, ssize_t written)
15741+{
15742+ struct inode *h_inode;
15743+
15744+ au_cpup_attr_timesizes(inode);
5afbbe0d 15745+ AuDebugOn(au_ibtop(inode) != wpre->btop);
b912730e
AM
15746+ h_inode = file_inode(h_file);
15747+ inode->i_mode = h_inode->i_mode;
15748+ ii_write_unlock(inode);
b912730e
AM
15749+ /* AuDbg("blks %llu, %llu\n", (u64)blks, (u64)h_inode->i_blocks); */
15750+ if (written > 0)
5afbbe0d 15751+ au_fhsm_wrote(inode->i_sb, wpre->btop,
b912730e 15752+ /*force*/h_inode->i_blocks > wpre->blks);
1c60b727 15753+ fput(h_file);
b912730e
AM
15754+}
15755+
15756+static ssize_t aufs_read(struct file *file, char __user *buf, size_t count,
15757+ loff_t *ppos)
15758+{
15759+ ssize_t err;
15760+ struct inode *inode;
15761+ struct file *h_file;
15762+ struct super_block *sb;
15763+
15764+ inode = file_inode(file);
15765+ sb = inode->i_sb;
15766+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
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))
15771+ goto out;
9dbd164d
AM
15772+
15773+ /* filedata may be obsoleted by concurrent copyup, but no problem */
4a4d8108
AM
15774+ err = vfsub_read_u(h_file, buf, count, ppos);
15775+ /* todo: necessary? */
15776+ /* file->f_ra = h_file->f_ra; */
b912730e 15777+ au_read_post(inode, h_file);
1308ab2a 15778+
4f0767ce 15779+out:
dece6358
AM
15780+ si_read_unlock(sb);
15781+ return err;
15782+}
1facf9fc 15783+
e49829fe
JR
15784+/*
15785+ * todo: very ugly
15786+ * it locks both of i_mutex and si_rwsem for read in safe.
15787+ * if the plink maintenance mode continues forever (that is the problem),
15788+ * may loop forever.
15789+ */
15790+static void au_mtx_and_read_lock(struct inode *inode)
15791+{
15792+ int err;
15793+ struct super_block *sb = inode->i_sb;
15794+
15795+ while (1) {
febd17d6 15796+ inode_lock(inode);
e49829fe
JR
15797+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
15798+ if (!err)
15799+ break;
febd17d6 15800+ inode_unlock(inode);
e49829fe
JR
15801+ si_read_lock(sb, AuLock_NOPLMW);
15802+ si_read_unlock(sb);
15803+ }
15804+}
15805+
4a4d8108
AM
15806+static ssize_t aufs_write(struct file *file, const char __user *ubuf,
15807+ size_t count, loff_t *ppos)
dece6358 15808+{
4a4d8108 15809+ ssize_t err;
b912730e
AM
15810+ struct au_write_pre wpre;
15811+ struct inode *inode;
4a4d8108
AM
15812+ struct file *h_file;
15813+ char __user *buf = (char __user *)ubuf;
1facf9fc 15814+
b912730e 15815+ inode = file_inode(file);
e49829fe 15816+ au_mtx_and_read_lock(inode);
1facf9fc 15817+
521ced18 15818+ wpre.lsc = 0;
b912730e
AM
15819+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
15820+ err = PTR_ERR(h_file);
15821+ if (IS_ERR(h_file))
9dbd164d 15822+ goto out;
9dbd164d 15823+
4a4d8108 15824+ err = vfsub_write_u(h_file, buf, count, ppos);
b912730e 15825+ au_write_post(inode, h_file, &wpre, err);
1facf9fc 15826+
4f0767ce 15827+out:
b912730e 15828+ si_read_unlock(inode->i_sb);
febd17d6 15829+ inode_unlock(inode);
dece6358
AM
15830+ return err;
15831+}
1facf9fc 15832+
076b876e
AM
15833+static ssize_t au_do_iter(struct file *h_file, int rw, struct kiocb *kio,
15834+ struct iov_iter *iov_iter)
dece6358 15835+{
4a4d8108
AM
15836+ ssize_t err;
15837+ struct file *file;
076b876e 15838+ ssize_t (*iter)(struct kiocb *, struct iov_iter *);
1facf9fc 15839+
4a4d8108
AM
15840+ err = security_file_permission(h_file, rw);
15841+ if (unlikely(err))
15842+ goto out;
1facf9fc 15843+
43982f53 15844+ err = -ENOSYS; /* the branch doesn't have its ->(read|write)_iter() */
076b876e 15845+ iter = NULL;
5527c038 15846+ if (rw == MAY_READ)
076b876e 15847+ iter = h_file->f_op->read_iter;
5527c038 15848+ else if (rw == MAY_WRITE)
076b876e 15849+ iter = h_file->f_op->write_iter;
076b876e
AM
15850+
15851+ file = kio->ki_filp;
15852+ kio->ki_filp = h_file;
15853+ if (iter) {
2cbb1c4b 15854+ lockdep_off();
076b876e
AM
15855+ err = iter(kio, iov_iter);
15856+ lockdep_on();
4a4d8108
AM
15857+ } else
15858+ /* currently there is no such fs */
15859+ WARN_ON_ONCE(1);
076b876e 15860+ kio->ki_filp = file;
1facf9fc 15861+
4f0767ce 15862+out:
dece6358
AM
15863+ return err;
15864+}
1facf9fc 15865+
076b876e 15866+static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter)
1facf9fc 15867+{
4a4d8108
AM
15868+ ssize_t err;
15869+ struct file *file, *h_file;
b912730e 15870+ struct inode *inode;
dece6358 15871+ struct super_block *sb;
1facf9fc 15872+
4a4d8108 15873+ file = kio->ki_filp;
b912730e
AM
15874+ inode = file_inode(file);
15875+ sb = inode->i_sb;
e49829fe 15876+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
4a4d8108 15877+
521ced18 15878+ h_file = au_read_pre(file, /*keep_fi*/1, /*lsc*/0);
b912730e
AM
15879+ err = PTR_ERR(h_file);
15880+ if (IS_ERR(h_file))
15881+ goto out;
9dbd164d 15882+
5afbbe0d
AM
15883+ if (au_test_loopback_kthread()) {
15884+ au_warn_loopback(h_file->f_path.dentry->d_sb);
15885+ if (file->f_mapping != h_file->f_mapping) {
15886+ file->f_mapping = h_file->f_mapping;
15887+ smp_mb(); /* unnecessary? */
15888+ }
15889+ }
15890+ fi_read_unlock(file);
15891+
076b876e 15892+ err = au_do_iter(h_file, MAY_READ, kio, iov_iter);
4a4d8108
AM
15893+ /* todo: necessary? */
15894+ /* file->f_ra = h_file->f_ra; */
b912730e 15895+ au_read_post(inode, h_file);
1facf9fc 15896+
4f0767ce 15897+out:
4a4d8108 15898+ si_read_unlock(sb);
1308ab2a 15899+ return err;
15900+}
1facf9fc 15901+
076b876e 15902+static ssize_t aufs_write_iter(struct kiocb *kio, struct iov_iter *iov_iter)
1308ab2a 15903+{
4a4d8108 15904+ ssize_t err;
b912730e
AM
15905+ struct au_write_pre wpre;
15906+ struct inode *inode;
4a4d8108 15907+ struct file *file, *h_file;
1308ab2a 15908+
4a4d8108 15909+ file = kio->ki_filp;
b912730e 15910+ inode = file_inode(file);
e49829fe
JR
15911+ au_mtx_and_read_lock(inode);
15912+
521ced18 15913+ wpre.lsc = 0;
b912730e
AM
15914+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
15915+ err = PTR_ERR(h_file);
15916+ if (IS_ERR(h_file))
9dbd164d 15917+ goto out;
9dbd164d 15918+
076b876e 15919+ err = au_do_iter(h_file, MAY_WRITE, kio, iov_iter);
b912730e 15920+ au_write_post(inode, h_file, &wpre, err);
1facf9fc 15921+
4f0767ce 15922+out:
b912730e 15923+ si_read_unlock(inode->i_sb);
febd17d6 15924+ inode_unlock(inode);
dece6358 15925+ return err;
1facf9fc 15926+}
15927+
4a4d8108
AM
15928+static ssize_t aufs_splice_read(struct file *file, loff_t *ppos,
15929+ struct pipe_inode_info *pipe, size_t len,
15930+ unsigned int flags)
1facf9fc 15931+{
4a4d8108
AM
15932+ ssize_t err;
15933+ struct file *h_file;
b912730e 15934+ struct inode *inode;
dece6358 15935+ struct super_block *sb;
1facf9fc 15936+
b912730e
AM
15937+ inode = file_inode(file);
15938+ sb = inode->i_sb;
e49829fe 15939+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
b912730e 15940+
521ced18 15941+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
b912730e
AM
15942+ err = PTR_ERR(h_file);
15943+ if (IS_ERR(h_file))
dece6358 15944+ goto out;
1facf9fc 15945+
4a4d8108 15946+ err = vfsub_splice_to(h_file, ppos, pipe, len, flags);
acd2b654 15947+ /* todo: necessary? */
4a4d8108 15948+ /* file->f_ra = h_file->f_ra; */
b912730e 15949+ au_read_post(inode, h_file);
1facf9fc 15950+
4f0767ce 15951+out:
4a4d8108 15952+ si_read_unlock(sb);
dece6358 15953+ return err;
1facf9fc 15954+}
15955+
4a4d8108
AM
15956+static ssize_t
15957+aufs_splice_write(struct pipe_inode_info *pipe, struct file *file, loff_t *ppos,
15958+ size_t len, unsigned int flags)
1facf9fc 15959+{
4a4d8108 15960+ ssize_t err;
b912730e
AM
15961+ struct au_write_pre wpre;
15962+ struct inode *inode;
076b876e 15963+ struct file *h_file;
1facf9fc 15964+
b912730e 15965+ inode = file_inode(file);
e49829fe 15966+ au_mtx_and_read_lock(inode);
9dbd164d 15967+
521ced18 15968+ wpre.lsc = 0;
b912730e
AM
15969+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
15970+ err = PTR_ERR(h_file);
15971+ if (IS_ERR(h_file))
9dbd164d 15972+ goto out;
9dbd164d 15973+
4a4d8108 15974+ err = vfsub_splice_from(pipe, h_file, ppos, len, flags);
b912730e 15975+ au_write_post(inode, h_file, &wpre, err);
1facf9fc 15976+
4f0767ce 15977+out:
b912730e 15978+ si_read_unlock(inode->i_sb);
febd17d6 15979+ inode_unlock(inode);
4a4d8108
AM
15980+ return err;
15981+}
1facf9fc 15982+
38d290e6
JR
15983+static long aufs_fallocate(struct file *file, int mode, loff_t offset,
15984+ loff_t len)
15985+{
15986+ long err;
b912730e 15987+ struct au_write_pre wpre;
38d290e6
JR
15988+ struct inode *inode;
15989+ struct file *h_file;
15990+
b912730e 15991+ inode = file_inode(file);
38d290e6
JR
15992+ au_mtx_and_read_lock(inode);
15993+
521ced18 15994+ wpre.lsc = 0;
b912730e
AM
15995+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
15996+ err = PTR_ERR(h_file);
15997+ if (IS_ERR(h_file))
38d290e6 15998+ goto out;
38d290e6
JR
15999+
16000+ lockdep_off();
03673fb0 16001+ err = vfs_fallocate(h_file, mode, offset, len);
38d290e6 16002+ lockdep_on();
b912730e 16003+ au_write_post(inode, h_file, &wpre, /*written*/1);
38d290e6
JR
16004+
16005+out:
b912730e 16006+ si_read_unlock(inode->i_sb);
febd17d6 16007+ inode_unlock(inode);
38d290e6
JR
16008+ return err;
16009+}
16010+
521ced18
JR
16011+static ssize_t aufs_copy_file_range(struct file *src, loff_t src_pos,
16012+ struct file *dst, loff_t dst_pos,
16013+ size_t len, unsigned int flags)
16014+{
16015+ ssize_t err;
16016+ struct au_write_pre wpre;
16017+ enum { SRC, DST };
16018+ struct {
16019+ struct inode *inode;
16020+ struct file *h_file;
16021+ struct super_block *h_sb;
16022+ } a[2];
16023+#define a_src a[SRC]
16024+#define a_dst a[DST]
16025+
16026+ err = -EINVAL;
16027+ a_src.inode = file_inode(src);
16028+ if (unlikely(!S_ISREG(a_src.inode->i_mode)))
16029+ goto out;
16030+ a_dst.inode = file_inode(dst);
16031+ if (unlikely(!S_ISREG(a_dst.inode->i_mode)))
16032+ goto out;
16033+
16034+ au_mtx_and_read_lock(a_dst.inode);
16035+ /*
16036+ * in order to match the order in di_write_lock2_{child,parent}(),
acd2b654 16037+ * use f_path.dentry for this comparison.
521ced18
JR
16038+ */
16039+ if (src->f_path.dentry < dst->f_path.dentry) {
16040+ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_1);
16041+ err = PTR_ERR(a_src.h_file);
16042+ if (IS_ERR(a_src.h_file))
16043+ goto out_si;
16044+
16045+ wpre.lsc = AuLsc_FI_2;
16046+ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre);
16047+ err = PTR_ERR(a_dst.h_file);
16048+ if (IS_ERR(a_dst.h_file)) {
16049+ au_read_post(a_src.inode, a_src.h_file);
16050+ goto out_si;
16051+ }
16052+ } else {
16053+ wpre.lsc = AuLsc_FI_1;
16054+ a_dst.h_file = au_write_pre(dst, /*do_ready*/1, &wpre);
16055+ err = PTR_ERR(a_dst.h_file);
16056+ if (IS_ERR(a_dst.h_file))
16057+ goto out_si;
16058+
16059+ a_src.h_file = au_read_pre(src, /*keep_fi*/1, AuLsc_FI_2);
16060+ err = PTR_ERR(a_src.h_file);
16061+ if (IS_ERR(a_src.h_file)) {
16062+ au_write_post(a_dst.inode, a_dst.h_file, &wpre,
16063+ /*written*/0);
16064+ goto out_si;
16065+ }
16066+ }
16067+
16068+ err = -EXDEV;
16069+ a_src.h_sb = file_inode(a_src.h_file)->i_sb;
16070+ a_dst.h_sb = file_inode(a_dst.h_file)->i_sb;
16071+ if (unlikely(a_src.h_sb != a_dst.h_sb)) {
16072+ AuDbgFile(src);
16073+ AuDbgFile(dst);
16074+ goto out_file;
16075+ }
16076+
16077+ err = vfsub_copy_file_range(a_src.h_file, src_pos, a_dst.h_file,
16078+ dst_pos, len, flags);
16079+
16080+out_file:
16081+ au_write_post(a_dst.inode, a_dst.h_file, &wpre, err);
16082+ fi_read_unlock(src);
16083+ au_read_post(a_src.inode, a_src.h_file);
16084+out_si:
16085+ si_read_unlock(a_dst.inode->i_sb);
16086+ inode_unlock(a_dst.inode);
16087+out:
16088+ return err;
16089+#undef a_src
16090+#undef a_dst
16091+}
16092+
4a4d8108
AM
16093+/* ---------------------------------------------------------------------- */
16094+
9dbd164d
AM
16095+/*
16096+ * The locking order around current->mmap_sem.
16097+ * - in most and regular cases
16098+ * file I/O syscall -- aufs_read() or something
16099+ * -- si_rwsem for read -- mmap_sem
16100+ * (Note that [fdi]i_rwsem are released before mmap_sem).
16101+ * - in mmap case
16102+ * mmap(2) -- mmap_sem -- aufs_mmap() -- si_rwsem for read -- [fdi]i_rwsem
acd2b654
AM
16103+ * This AB-BA order is definitely bad, but is not a problem since "si_rwsem for
16104+ * read" allows multiple processes to acquire it and [fdi]i_rwsem are not held
16105+ * in file I/O. Aufs needs to stop lockdep in aufs_mmap() though.
9dbd164d
AM
16106+ * It means that when aufs acquires si_rwsem for write, the process should never
16107+ * acquire mmap_sem.
16108+ *
392086de 16109+ * Actually aufs_iterate() holds [fdi]i_rwsem before mmap_sem, but this is not a
9dbd164d
AM
16110+ * problem either since any directory is not able to be mmap-ed.
16111+ * The similar scenario is applied to aufs_readlink() too.
16112+ */
16113+
38d290e6 16114+#if 0 /* stop calling security_file_mmap() */
2dfbb274
AM
16115+/* cf. linux/include/linux/mman.h: calc_vm_prot_bits() */
16116+#define AuConv_VM_PROT(f, b) _calc_vm_trans(f, VM_##b, PROT_##b)
16117+
16118+static unsigned long au_arch_prot_conv(unsigned long flags)
16119+{
16120+ /* currently ppc64 only */
16121+#ifdef CONFIG_PPC64
16122+ /* cf. linux/arch/powerpc/include/asm/mman.h */
16123+ AuDebugOn(arch_calc_vm_prot_bits(-1) != VM_SAO);
16124+ return AuConv_VM_PROT(flags, SAO);
16125+#else
16126+ AuDebugOn(arch_calc_vm_prot_bits(-1));
16127+ return 0;
16128+#endif
16129+}
16130+
16131+static unsigned long au_prot_conv(unsigned long flags)
16132+{
16133+ return AuConv_VM_PROT(flags, READ)
16134+ | AuConv_VM_PROT(flags, WRITE)
16135+ | AuConv_VM_PROT(flags, EXEC)
16136+ | au_arch_prot_conv(flags);
16137+}
16138+
16139+/* cf. linux/include/linux/mman.h: calc_vm_flag_bits() */
16140+#define AuConv_VM_MAP(f, b) _calc_vm_trans(f, VM_##b, MAP_##b)
16141+
16142+static unsigned long au_flag_conv(unsigned long flags)
16143+{
16144+ return AuConv_VM_MAP(flags, GROWSDOWN)
16145+ | AuConv_VM_MAP(flags, DENYWRITE)
2dfbb274
AM
16146+ | AuConv_VM_MAP(flags, LOCKED);
16147+}
38d290e6 16148+#endif
2dfbb274 16149+
9dbd164d 16150+static int aufs_mmap(struct file *file, struct vm_area_struct *vma)
dece6358 16151+{
4a4d8108 16152+ int err;
4a4d8108 16153+ const unsigned char wlock
9dbd164d 16154+ = (file->f_mode & FMODE_WRITE) && (vma->vm_flags & VM_SHARED);
4a4d8108 16155+ struct super_block *sb;
9dbd164d 16156+ struct file *h_file;
b912730e 16157+ struct inode *inode;
9dbd164d
AM
16158+
16159+ AuDbgVmRegion(file, vma);
1308ab2a 16160+
b912730e
AM
16161+ inode = file_inode(file);
16162+ sb = inode->i_sb;
9dbd164d 16163+ lockdep_off();
e49829fe 16164+ si_read_lock(sb, AuLock_NOPLMW);
4a4d8108 16165+
b912730e 16166+ h_file = au_write_pre(file, wlock, /*wpre*/NULL);
9dbd164d 16167+ lockdep_on();
b912730e
AM
16168+ err = PTR_ERR(h_file);
16169+ if (IS_ERR(h_file))
16170+ goto out;
1308ab2a 16171+
b912730e
AM
16172+ err = 0;
16173+ au_set_mmapped(file);
9dbd164d 16174+ au_vm_file_reset(vma, h_file);
38d290e6
JR
16175+ /*
16176+ * we cannot call security_mmap_file() here since it may acquire
16177+ * mmap_sem or i_mutex.
16178+ *
16179+ * err = security_mmap_file(h_file, au_prot_conv(vma->vm_flags),
16180+ * au_flag_conv(vma->vm_flags));
16181+ */
9dbd164d 16182+ if (!err)
521ced18 16183+ err = call_mmap(h_file, vma);
b912730e
AM
16184+ if (!err) {
16185+ au_vm_prfile_set(vma, file);
16186+ fsstack_copy_attr_atime(inode, file_inode(h_file));
16187+ goto out_fput; /* success */
16188+ }
2cbb1c4b
JR
16189+ au_unset_mmapped(file);
16190+ au_vm_file_reset(vma, file);
b912730e 16191+
2cbb1c4b 16192+out_fput:
9dbd164d 16193+ lockdep_off();
b912730e
AM
16194+ ii_write_unlock(inode);
16195+ lockdep_on();
16196+ fput(h_file);
4f0767ce 16197+out:
b912730e 16198+ lockdep_off();
9dbd164d
AM
16199+ si_read_unlock(sb);
16200+ lockdep_on();
16201+ AuTraceErr(err);
4a4d8108
AM
16202+ return err;
16203+}
16204+
16205+/* ---------------------------------------------------------------------- */
16206+
1e00d052
AM
16207+static int aufs_fsync_nondir(struct file *file, loff_t start, loff_t end,
16208+ int datasync)
4a4d8108
AM
16209+{
16210+ int err;
b912730e 16211+ struct au_write_pre wpre;
4a4d8108
AM
16212+ struct inode *inode;
16213+ struct file *h_file;
4a4d8108
AM
16214+
16215+ err = 0; /* -EBADF; */ /* posix? */
16216+ if (unlikely(!(file->f_mode & FMODE_WRITE)))
b912730e 16217+ goto out;
4a4d8108 16218+
b912730e
AM
16219+ inode = file_inode(file);
16220+ au_mtx_and_read_lock(inode);
16221+
521ced18 16222+ wpre.lsc = 0;
b912730e
AM
16223+ h_file = au_write_pre(file, /*do_ready*/1, &wpre);
16224+ err = PTR_ERR(h_file);
16225+ if (IS_ERR(h_file))
4a4d8108 16226+ goto out_unlock;
4a4d8108 16227+
53392da6 16228+ err = vfsub_fsync(h_file, &h_file->f_path, datasync);
b912730e 16229+ au_write_post(inode, h_file, &wpre, /*written*/0);
4a4d8108 16230+
4f0767ce 16231+out_unlock:
b912730e 16232+ si_read_unlock(inode->i_sb);
febd17d6 16233+ inode_unlock(inode);
b912730e 16234+out:
4a4d8108 16235+ return err;
dece6358
AM
16236+}
16237+
4a4d8108 16238+static int aufs_fasync(int fd, struct file *file, int flag)
dece6358 16239+{
4a4d8108
AM
16240+ int err;
16241+ struct file *h_file;
4a4d8108 16242+ struct super_block *sb;
1308ab2a 16243+
b912730e 16244+ sb = file->f_path.dentry->d_sb;
e49829fe 16245+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
b912730e 16246+
521ced18 16247+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
b912730e
AM
16248+ err = PTR_ERR(h_file);
16249+ if (IS_ERR(h_file))
4a4d8108
AM
16250+ goto out;
16251+
523b37e3 16252+ if (h_file->f_op->fasync)
4a4d8108 16253+ err = h_file->f_op->fasync(fd, h_file, flag);
b912730e 16254+ fput(h_file); /* instead of au_read_post() */
1308ab2a 16255+
4f0767ce 16256+out:
4a4d8108 16257+ si_read_unlock(sb);
1308ab2a 16258+ return err;
dece6358 16259+}
4a4d8108 16260+
febd17d6
JR
16261+static int aufs_setfl(struct file *file, unsigned long arg)
16262+{
16263+ int err;
16264+ struct file *h_file;
16265+ struct super_block *sb;
16266+
16267+ sb = file->f_path.dentry->d_sb;
16268+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
16269+
521ced18 16270+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
febd17d6
JR
16271+ err = PTR_ERR(h_file);
16272+ if (IS_ERR(h_file))
16273+ goto out;
16274+
1c60b727
AM
16275+ /* stop calling h_file->fasync */
16276+ arg |= vfsub_file_flags(file) & FASYNC;
febd17d6
JR
16277+ err = setfl(/*unused fd*/-1, h_file, arg);
16278+ fput(h_file); /* instead of au_read_post() */
16279+
16280+out:
16281+ si_read_unlock(sb);
16282+ return err;
16283+}
16284+
4a4d8108
AM
16285+/* ---------------------------------------------------------------------- */
16286+
16287+/* no one supports this operation, currently */
43982f53 16288+#if 0 /* reserved for future use */
4a4d8108 16289+static ssize_t aufs_sendpage(struct file *file, struct page *page, int offset,
2000de60 16290+ size_t len, loff_t *pos, int more)
4a4d8108
AM
16291+{
16292+}
16293+#endif
16294+
16295+/* ---------------------------------------------------------------------- */
16296+
16297+const struct file_operations aufs_file_fop = {
16298+ .owner = THIS_MODULE,
2cbb1c4b 16299+
027c5e7a 16300+ .llseek = default_llseek,
4a4d8108
AM
16301+
16302+ .read = aufs_read,
16303+ .write = aufs_write,
076b876e
AM
16304+ .read_iter = aufs_read_iter,
16305+ .write_iter = aufs_write_iter,
16306+
4a4d8108
AM
16307+#ifdef CONFIG_AUFS_POLL
16308+ .poll = aufs_poll,
16309+#endif
16310+ .unlocked_ioctl = aufs_ioctl_nondir,
b752ccd1 16311+#ifdef CONFIG_COMPAT
c2b27bf2 16312+ .compat_ioctl = aufs_compat_ioctl_nondir,
b752ccd1 16313+#endif
4a4d8108
AM
16314+ .mmap = aufs_mmap,
16315+ .open = aufs_open_nondir,
16316+ .flush = aufs_flush_nondir,
16317+ .release = aufs_release_nondir,
16318+ .fsync = aufs_fsync_nondir,
4a4d8108
AM
16319+ .fasync = aufs_fasync,
16320+ /* .sendpage = aufs_sendpage, */
febd17d6 16321+ .setfl = aufs_setfl,
4a4d8108
AM
16322+ .splice_write = aufs_splice_write,
16323+ .splice_read = aufs_splice_read,
43982f53 16324+#if 0 /* reserved for future use */
4a4d8108 16325+ .aio_splice_write = aufs_aio_splice_write,
38d290e6 16326+ .aio_splice_read = aufs_aio_splice_read,
4a4d8108 16327+#endif
521ced18
JR
16328+ .fallocate = aufs_fallocate,
16329+ .copy_file_range = aufs_copy_file_range
4a4d8108 16330+};
7f207e10 16331diff -urN /usr/share/empty/fs/aufs/fstype.h linux/fs/aufs/fstype.h
eca34b5c 16332--- /usr/share/empty/fs/aufs/fstype.h 1970-01-01 01:00:00.000000000 +0100
016522bc 16333+++ linux/fs/aufs/fstype.h 2020-01-27 10:57:18.172204883 +0100
062440b3
AM
16334@@ -0,0 +1,401 @@
16335+/* SPDX-License-Identifier: GPL-2.0 */
4a4d8108 16336+/*
016522bc 16337+ * Copyright (C) 2005-2020 Junjiro R. Okajima
4a4d8108
AM
16338+ *
16339+ * This program, aufs is free software; you can redistribute it and/or modify
16340+ * it under the terms of the GNU General Public License as published by
16341+ * the Free Software Foundation; either version 2 of the License, or
16342+ * (at your option) any later version.
16343+ *
16344+ * This program is distributed in the hope that it will be useful,
16345+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16346+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16347+ * GNU General Public License for more details.
16348+ *
16349+ * You should have received a copy of the GNU General Public License
523b37e3 16350+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
16351+ */
16352+
16353+/*
16354+ * judging filesystem type
16355+ */
16356+
16357+#ifndef __AUFS_FSTYPE_H__
16358+#define __AUFS_FSTYPE_H__
16359+
16360+#ifdef __KERNEL__
16361+
16362+#include <linux/fs.h>
16363+#include <linux/magic.h>
b912730e 16364+#include <linux/nfs_fs.h>
b95c5147 16365+#include <linux/romfs_fs.h>
4a4d8108
AM
16366+
16367+static inline int au_test_aufs(struct super_block *sb)
16368+{
16369+ return sb->s_magic == AUFS_SUPER_MAGIC;
16370+}
16371+
16372+static inline const char *au_sbtype(struct super_block *sb)
16373+{
16374+ return sb->s_type->name;
16375+}
1308ab2a 16376+
16377+static inline int au_test_iso9660(struct super_block *sb __maybe_unused)
16378+{
f0c0a007 16379+#if IS_ENABLED(CONFIG_ISO9660_FS)
2000de60 16380+ return sb->s_magic == ISOFS_SUPER_MAGIC;
dece6358
AM
16381+#else
16382+ return 0;
16383+#endif
16384+}
16385+
1308ab2a 16386+static inline int au_test_romfs(struct super_block *sb __maybe_unused)
dece6358 16387+{
f0c0a007 16388+#if IS_ENABLED(CONFIG_ROMFS_FS)
2000de60 16389+ return sb->s_magic == ROMFS_MAGIC;
dece6358
AM
16390+#else
16391+ return 0;
16392+#endif
16393+}
16394+
1308ab2a 16395+static inline int au_test_cramfs(struct super_block *sb __maybe_unused)
dece6358 16396+{
f0c0a007 16397+#if IS_ENABLED(CONFIG_CRAMFS)
1308ab2a 16398+ return sb->s_magic == CRAMFS_MAGIC;
16399+#endif
16400+ return 0;
16401+}
16402+
16403+static inline int au_test_nfs(struct super_block *sb __maybe_unused)
16404+{
f0c0a007 16405+#if IS_ENABLED(CONFIG_NFS_FS)
1308ab2a 16406+ return sb->s_magic == NFS_SUPER_MAGIC;
dece6358
AM
16407+#else
16408+ return 0;
16409+#endif
16410+}
16411+
1308ab2a 16412+static inline int au_test_fuse(struct super_block *sb __maybe_unused)
dece6358 16413+{
f0c0a007 16414+#if IS_ENABLED(CONFIG_FUSE_FS)
1308ab2a 16415+ return sb->s_magic == FUSE_SUPER_MAGIC;
dece6358
AM
16416+#else
16417+ return 0;
16418+#endif
16419+}
16420+
1308ab2a 16421+static inline int au_test_xfs(struct super_block *sb __maybe_unused)
dece6358 16422+{
f0c0a007 16423+#if IS_ENABLED(CONFIG_XFS_FS)
1308ab2a 16424+ return sb->s_magic == XFS_SB_MAGIC;
dece6358
AM
16425+#else
16426+ return 0;
16427+#endif
16428+}
16429+
1308ab2a 16430+static inline int au_test_tmpfs(struct super_block *sb __maybe_unused)
dece6358 16431+{
1308ab2a 16432+#ifdef CONFIG_TMPFS
16433+ return sb->s_magic == TMPFS_MAGIC;
16434+#else
16435+ return 0;
dece6358 16436+#endif
dece6358
AM
16437+}
16438+
1308ab2a 16439+static inline int au_test_ecryptfs(struct super_block *sb __maybe_unused)
1facf9fc 16440+{
f0c0a007 16441+#if IS_ENABLED(CONFIG_ECRYPT_FS)
1308ab2a 16442+ return !strcmp(au_sbtype(sb), "ecryptfs");
16443+#else
16444+ return 0;
16445+#endif
1facf9fc 16446+}
16447+
1308ab2a 16448+static inline int au_test_ramfs(struct super_block *sb)
16449+{
16450+ return sb->s_magic == RAMFS_MAGIC;
16451+}
16452+
16453+static inline int au_test_ubifs(struct super_block *sb __maybe_unused)
16454+{
f0c0a007 16455+#if IS_ENABLED(CONFIG_UBIFS_FS)
1308ab2a 16456+ return sb->s_magic == UBIFS_SUPER_MAGIC;
16457+#else
16458+ return 0;
16459+#endif
16460+}
16461+
16462+static inline int au_test_procfs(struct super_block *sb __maybe_unused)
16463+{
16464+#ifdef CONFIG_PROC_FS
16465+ return sb->s_magic == PROC_SUPER_MAGIC;
16466+#else
16467+ return 0;
16468+#endif
16469+}
16470+
16471+static inline int au_test_sysfs(struct super_block *sb __maybe_unused)
16472+{
16473+#ifdef CONFIG_SYSFS
16474+ return sb->s_magic == SYSFS_MAGIC;
16475+#else
16476+ return 0;
16477+#endif
16478+}
16479+
16480+static inline int au_test_configfs(struct super_block *sb __maybe_unused)
16481+{
f0c0a007 16482+#if IS_ENABLED(CONFIG_CONFIGFS_FS)
1308ab2a 16483+ return sb->s_magic == CONFIGFS_MAGIC;
16484+#else
16485+ return 0;
16486+#endif
16487+}
16488+
16489+static inline int au_test_minix(struct super_block *sb __maybe_unused)
16490+{
f0c0a007 16491+#if IS_ENABLED(CONFIG_MINIX_FS)
1308ab2a 16492+ return sb->s_magic == MINIX3_SUPER_MAGIC
16493+ || sb->s_magic == MINIX2_SUPER_MAGIC
16494+ || sb->s_magic == MINIX2_SUPER_MAGIC2
16495+ || sb->s_magic == MINIX_SUPER_MAGIC
16496+ || sb->s_magic == MINIX_SUPER_MAGIC2;
16497+#else
16498+ return 0;
16499+#endif
16500+}
16501+
1308ab2a 16502+static inline int au_test_fat(struct super_block *sb __maybe_unused)
16503+{
f0c0a007 16504+#if IS_ENABLED(CONFIG_FAT_FS)
1308ab2a 16505+ return sb->s_magic == MSDOS_SUPER_MAGIC;
16506+#else
16507+ return 0;
16508+#endif
16509+}
16510+
16511+static inline int au_test_msdos(struct super_block *sb)
16512+{
16513+ return au_test_fat(sb);
16514+}
16515+
16516+static inline int au_test_vfat(struct super_block *sb)
16517+{
16518+ return au_test_fat(sb);
16519+}
16520+
16521+static inline int au_test_securityfs(struct super_block *sb __maybe_unused)
16522+{
16523+#ifdef CONFIG_SECURITYFS
16524+ return sb->s_magic == SECURITYFS_MAGIC;
16525+#else
16526+ return 0;
16527+#endif
16528+}
16529+
16530+static inline int au_test_squashfs(struct super_block *sb __maybe_unused)
16531+{
f0c0a007 16532+#if IS_ENABLED(CONFIG_SQUASHFS)
1308ab2a 16533+ return sb->s_magic == SQUASHFS_MAGIC;
16534+#else
16535+ return 0;
16536+#endif
16537+}
16538+
16539+static inline int au_test_btrfs(struct super_block *sb __maybe_unused)
16540+{
f0c0a007 16541+#if IS_ENABLED(CONFIG_BTRFS_FS)
1308ab2a 16542+ return sb->s_magic == BTRFS_SUPER_MAGIC;
16543+#else
16544+ return 0;
16545+#endif
16546+}
16547+
16548+static inline int au_test_xenfs(struct super_block *sb __maybe_unused)
16549+{
f0c0a007 16550+#if IS_ENABLED(CONFIG_XENFS)
1308ab2a 16551+ return sb->s_magic == XENFS_SUPER_MAGIC;
16552+#else
16553+ return 0;
16554+#endif
16555+}
16556+
16557+static inline int au_test_debugfs(struct super_block *sb __maybe_unused)
16558+{
16559+#ifdef CONFIG_DEBUG_FS
16560+ return sb->s_magic == DEBUGFS_MAGIC;
16561+#else
16562+ return 0;
16563+#endif
16564+}
16565+
16566+static inline int au_test_nilfs(struct super_block *sb __maybe_unused)
16567+{
f0c0a007 16568+#if IS_ENABLED(CONFIG_NILFS)
1308ab2a 16569+ return sb->s_magic == NILFS_SUPER_MAGIC;
16570+#else
16571+ return 0;
16572+#endif
16573+}
16574+
4a4d8108
AM
16575+static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
16576+{
f0c0a007 16577+#if IS_ENABLED(CONFIG_HFSPLUS_FS)
4a4d8108
AM
16578+ return sb->s_magic == HFSPLUS_SUPER_MAGIC;
16579+#else
16580+ return 0;
16581+#endif
16582+}
16583+
1308ab2a 16584+/* ---------------------------------------------------------------------- */
16585+/*
16586+ * they can't be an aufs branch.
16587+ */
16588+static inline int au_test_fs_unsuppoted(struct super_block *sb)
16589+{
16590+ return
16591+#ifndef CONFIG_AUFS_BR_RAMFS
16592+ au_test_ramfs(sb) ||
16593+#endif
16594+ au_test_procfs(sb)
16595+ || au_test_sysfs(sb)
16596+ || au_test_configfs(sb)
16597+ || au_test_debugfs(sb)
16598+ || au_test_securityfs(sb)
16599+ || au_test_xenfs(sb)
16600+ || au_test_ecryptfs(sb)
16601+ /* || !strcmp(au_sbtype(sb), "unionfs") */
16602+ || au_test_aufs(sb); /* will be supported in next version */
16603+}
16604+
1308ab2a 16605+static inline int au_test_fs_remote(struct super_block *sb)
16606+{
16607+ return !au_test_tmpfs(sb)
16608+#ifdef CONFIG_AUFS_BR_RAMFS
16609+ && !au_test_ramfs(sb)
16610+#endif
16611+ && !(sb->s_type->fs_flags & FS_REQUIRES_DEV);
16612+}
16613+
16614+/* ---------------------------------------------------------------------- */
16615+
16616+/*
16617+ * Note: these functions (below) are created after reading ->getattr() in all
16618+ * filesystems under linux/fs. it means we have to do so in every update...
16619+ */
16620+
16621+/*
16622+ * some filesystems require getattr to refresh the inode attributes before
16623+ * referencing.
16624+ * in most cases, we can rely on the inode attribute in NFS (or every remote fs)
16625+ * and leave the work for d_revalidate()
16626+ */
16627+static inline int au_test_fs_refresh_iattr(struct super_block *sb)
16628+{
16629+ return au_test_nfs(sb)
16630+ || au_test_fuse(sb)
1308ab2a 16631+ /* || au_test_btrfs(sb) */ /* untested */
1308ab2a 16632+ ;
16633+}
16634+
16635+/*
16636+ * filesystems which don't maintain i_size or i_blocks.
16637+ */
16638+static inline int au_test_fs_bad_iattr_size(struct super_block *sb)
16639+{
16640+ return au_test_xfs(sb)
4a4d8108
AM
16641+ || au_test_btrfs(sb)
16642+ || au_test_ubifs(sb)
16643+ || au_test_hfsplus(sb) /* maintained, but incorrect */
1308ab2a 16644+ /* || au_test_minix(sb) */ /* untested */
16645+ ;
16646+}
16647+
16648+/*
16649+ * filesystems which don't store the correct value in some of their inode
16650+ * attributes.
16651+ */
16652+static inline int au_test_fs_bad_iattr(struct super_block *sb)
16653+{
16654+ return au_test_fs_bad_iattr_size(sb)
1308ab2a 16655+ || au_test_fat(sb)
16656+ || au_test_msdos(sb)
16657+ || au_test_vfat(sb);
1facf9fc 16658+}
16659+
16660+/* they don't check i_nlink in link(2) */
16661+static inline int au_test_fs_no_limit_nlink(struct super_block *sb)
16662+{
16663+ return au_test_tmpfs(sb)
16664+#ifdef CONFIG_AUFS_BR_RAMFS
16665+ || au_test_ramfs(sb)
16666+#endif
4a4d8108 16667+ || au_test_ubifs(sb)
4a4d8108 16668+ || au_test_hfsplus(sb);
1facf9fc 16669+}
16670+
16671+/*
16672+ * filesystems which sets S_NOATIME and S_NOCMTIME.
16673+ */
16674+static inline int au_test_fs_notime(struct super_block *sb)
16675+{
16676+ return au_test_nfs(sb)
16677+ || au_test_fuse(sb)
dece6358 16678+ || au_test_ubifs(sb)
1facf9fc 16679+ ;
16680+}
16681+
1facf9fc 16682+/* temporary support for i#1 in cramfs */
16683+static inline int au_test_fs_unique_ino(struct inode *inode)
16684+{
16685+ if (au_test_cramfs(inode->i_sb))
16686+ return inode->i_ino != 1;
16687+ return 1;
16688+}
16689+
16690+/* ---------------------------------------------------------------------- */
16691+
16692+/*
16693+ * the filesystem where the xino files placed must support i/o after unlink and
16694+ * maintain i_size and i_blocks.
16695+ */
16696+static inline int au_test_fs_bad_xino(struct super_block *sb)
16697+{
16698+ return au_test_fs_remote(sb)
16699+ || au_test_fs_bad_iattr_size(sb)
1facf9fc 16700+ /* don't want unnecessary work for xino */
16701+ || au_test_aufs(sb)
1308ab2a 16702+ || au_test_ecryptfs(sb)
16703+ || au_test_nilfs(sb);
1facf9fc 16704+}
16705+
16706+static inline int au_test_fs_trunc_xino(struct super_block *sb)
16707+{
16708+ return au_test_tmpfs(sb)
16709+ || au_test_ramfs(sb);
16710+}
16711+
16712+/*
16713+ * test if the @sb is real-readonly.
16714+ */
16715+static inline int au_test_fs_rr(struct super_block *sb)
16716+{
16717+ return au_test_squashfs(sb)
16718+ || au_test_iso9660(sb)
16719+ || au_test_cramfs(sb)
16720+ || au_test_romfs(sb);
16721+}
16722+
b912730e
AM
16723+/*
16724+ * test if the @inode is nfs with 'noacl' option
2121bcd9 16725+ * NFS always sets SB_POSIXACL regardless its mount option 'noacl.'
b912730e
AM
16726+ */
16727+static inline int au_test_nfs_noacl(struct inode *inode)
16728+{
16729+ return au_test_nfs(inode->i_sb)
16730+ /* && IS_POSIXACL(inode) */
16731+ && !nfs_server_capable(inode, NFS_CAP_ACLS);
16732+}
16733+
1facf9fc 16734+#endif /* __KERNEL__ */
16735+#endif /* __AUFS_FSTYPE_H__ */
8b6a4947 16736diff -urN /usr/share/empty/fs/aufs/hbl.h linux/fs/aufs/hbl.h
eca34b5c 16737--- /usr/share/empty/fs/aufs/hbl.h 1970-01-01 01:00:00.000000000 +0100
016522bc 16738+++ linux/fs/aufs/hbl.h 2020-01-27 10:57:18.172204883 +0100
062440b3
AM
16739@@ -0,0 +1,65 @@
16740+/* SPDX-License-Identifier: GPL-2.0 */
8b6a4947 16741+/*
016522bc 16742+ * Copyright (C) 2017-2020 Junjiro R. Okajima
8b6a4947
AM
16743+ *
16744+ * This program, aufs is free software; you can redistribute it and/or modify
16745+ * it under the terms of the GNU General Public License as published by
16746+ * the Free Software Foundation; either version 2 of the License, or
16747+ * (at your option) any later version.
16748+ *
16749+ * This program is distributed in the hope that it will be useful,
16750+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16751+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16752+ * GNU General Public License for more details.
16753+ *
16754+ * You should have received a copy of the GNU General Public License
16755+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
16756+ */
16757+
16758+/*
16759+ * helpers for hlist_bl.h
16760+ */
16761+
16762+#ifndef __AUFS_HBL_H__
16763+#define __AUFS_HBL_H__
16764+
16765+#ifdef __KERNEL__
16766+
16767+#include <linux/list_bl.h>
16768+
16769+static inline void au_hbl_add(struct hlist_bl_node *node,
16770+ struct hlist_bl_head *hbl)
16771+{
16772+ hlist_bl_lock(hbl);
16773+ hlist_bl_add_head(node, hbl);
16774+ hlist_bl_unlock(hbl);
16775+}
16776+
16777+static inline void au_hbl_del(struct hlist_bl_node *node,
16778+ struct hlist_bl_head *hbl)
16779+{
16780+ hlist_bl_lock(hbl);
16781+ hlist_bl_del(node);
16782+ hlist_bl_unlock(hbl);
16783+}
16784+
16785+#define au_hbl_for_each(pos, head) \
16786+ for (pos = hlist_bl_first(head); \
16787+ pos; \
16788+ pos = pos->next)
16789+
16790+static inline unsigned long au_hbl_count(struct hlist_bl_head *hbl)
16791+{
16792+ unsigned long cnt;
16793+ struct hlist_bl_node *pos;
16794+
16795+ cnt = 0;
16796+ hlist_bl_lock(hbl);
16797+ au_hbl_for_each(pos, hbl)
16798+ cnt++;
16799+ hlist_bl_unlock(hbl);
16800+ return cnt;
16801+}
16802+
16803+#endif /* __KERNEL__ */
16804+#endif /* __AUFS_HBL_H__ */
7f207e10 16805diff -urN /usr/share/empty/fs/aufs/hfsnotify.c linux/fs/aufs/hfsnotify.c
eca34b5c 16806--- /usr/share/empty/fs/aufs/hfsnotify.c 1970-01-01 01:00:00.000000000 +0100
016522bc 16807+++ linux/fs/aufs/hfsnotify.c 2020-01-27 10:57:18.172204883 +0100
fbc438ed 16808@@ -0,0 +1,288 @@
cd7a4cd9 16809+// SPDX-License-Identifier: GPL-2.0
1facf9fc 16810+/*
016522bc 16811+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 16812+ *
16813+ * This program, aufs is free software; you can redistribute it and/or modify
16814+ * it under the terms of the GNU General Public License as published by
16815+ * the Free Software Foundation; either version 2 of the License, or
16816+ * (at your option) any later version.
dece6358
AM
16817+ *
16818+ * This program is distributed in the hope that it will be useful,
16819+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16820+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16821+ * GNU General Public License for more details.
16822+ *
16823+ * You should have received a copy of the GNU General Public License
523b37e3 16824+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 16825+ */
16826+
16827+/*
4a4d8108 16828+ * fsnotify for the lower directories
1facf9fc 16829+ */
16830+
16831+#include "aufs.h"
16832+
4a4d8108
AM
16833+/* FS_IN_IGNORED is unnecessary */
16834+static const __u32 AuHfsnMask = (FS_MOVED_TO | FS_MOVED_FROM | FS_DELETE
16835+ | FS_CREATE | FS_EVENT_ON_CHILD);
7f207e10 16836+static DECLARE_WAIT_QUEUE_HEAD(au_hfsn_wq);
7eafdf33 16837+static __cacheline_aligned_in_smp atomic64_t au_hfsn_ifree = ATOMIC64_INIT(0);
1facf9fc 16838+
0c5527e5 16839+static void au_hfsn_free_mark(struct fsnotify_mark *mark)
1facf9fc 16840+{
0c5527e5
AM
16841+ struct au_hnotify *hn = container_of(mark, struct au_hnotify,
16842+ hn_mark);
5afbbe0d 16843+ /* AuDbg("here\n"); */
1c60b727 16844+ au_cache_free_hnotify(hn);
8b6a4947 16845+ smp_mb__before_atomic(); /* for atomic64_dec */
1716fcea
AM
16846+ if (atomic64_dec_and_test(&au_hfsn_ifree))
16847+ wake_up(&au_hfsn_wq);
4a4d8108 16848+}
1facf9fc 16849+
027c5e7a 16850+static int au_hfsn_alloc(struct au_hinode *hinode)
4a4d8108 16851+{
1716fcea 16852+ int err;
027c5e7a
AM
16853+ struct au_hnotify *hn;
16854+ struct super_block *sb;
16855+ struct au_branch *br;
0c5527e5 16856+ struct fsnotify_mark *mark;
027c5e7a 16857+ aufs_bindex_t bindex;
1facf9fc 16858+
027c5e7a
AM
16859+ hn = hinode->hi_notify;
16860+ sb = hn->hn_aufs_inode->i_sb;
16861+ bindex = au_br_index(sb, hinode->hi_id);
16862+ br = au_sbr(sb, bindex);
1716fcea
AM
16863+ AuDebugOn(!br->br_hfsn);
16864+
0c5527e5 16865+ mark = &hn->hn_mark;
ffa93bbd 16866+ fsnotify_init_mark(mark, br->br_hfsn->hfsn_group);
0c5527e5 16867+ mark->mask = AuHfsnMask;
7f207e10
AM
16868+ /*
16869+ * by udba rename or rmdir, aufs assign a new inode to the known
16870+ * h_inode, so specify 1 to allow dups.
16871+ */
c1595e42 16872+ lockdep_off();
acd2b654 16873+ err = fsnotify_add_inode_mark(mark, hinode->hi_inode, /*allow_dups*/1);
c1595e42 16874+ lockdep_on();
1716fcea
AM
16875+
16876+ return err;
1facf9fc 16877+}
16878+
7eafdf33 16879+static int au_hfsn_free(struct au_hinode *hinode, struct au_hnotify *hn)
1facf9fc 16880+{
0c5527e5 16881+ struct fsnotify_mark *mark;
7eafdf33 16882+ unsigned long long ull;
1716fcea 16883+ struct fsnotify_group *group;
7eafdf33
AM
16884+
16885+ ull = atomic64_inc_return(&au_hfsn_ifree);
16886+ BUG_ON(!ull);
953406b4 16887+
0c5527e5 16888+ mark = &hn->hn_mark;
1716fcea
AM
16889+ spin_lock(&mark->lock);
16890+ group = mark->group;
16891+ fsnotify_get_group(group);
16892+ spin_unlock(&mark->lock);
c1595e42 16893+ lockdep_off();
1716fcea 16894+ fsnotify_destroy_mark(mark, group);
5afbbe0d 16895+ fsnotify_put_mark(mark);
1716fcea 16896+ fsnotify_put_group(group);
c1595e42 16897+ lockdep_on();
7f207e10 16898+
7eafdf33
AM
16899+ /* free hn by myself */
16900+ return 0;
1facf9fc 16901+}
16902+
16903+/* ---------------------------------------------------------------------- */
16904+
4a4d8108 16905+static void au_hfsn_ctl(struct au_hinode *hinode, int do_set)
1facf9fc 16906+{
0c5527e5 16907+ struct fsnotify_mark *mark;
1facf9fc 16908+
0c5527e5
AM
16909+ mark = &hinode->hi_notify->hn_mark;
16910+ spin_lock(&mark->lock);
1facf9fc 16911+ if (do_set) {
0c5527e5
AM
16912+ AuDebugOn(mark->mask & AuHfsnMask);
16913+ mark->mask |= AuHfsnMask;
1facf9fc 16914+ } else {
0c5527e5
AM
16915+ AuDebugOn(!(mark->mask & AuHfsnMask));
16916+ mark->mask &= ~AuHfsnMask;
1facf9fc 16917+ }
0c5527e5 16918+ spin_unlock(&mark->lock);
4a4d8108 16919+ /* fsnotify_recalc_inode_mask(hinode->hi_inode); */
1facf9fc 16920+}
16921+
4a4d8108 16922+/* ---------------------------------------------------------------------- */
1facf9fc 16923+
4a4d8108
AM
16924+/* #define AuDbgHnotify */
16925+#ifdef AuDbgHnotify
16926+static char *au_hfsn_name(u32 mask)
16927+{
16928+#ifdef CONFIG_AUFS_DEBUG
c06a8ce3
AM
16929+#define test_ret(flag) \
16930+ do { \
16931+ if (mask & flag) \
16932+ return #flag; \
16933+ } while (0)
4a4d8108
AM
16934+ test_ret(FS_ACCESS);
16935+ test_ret(FS_MODIFY);
16936+ test_ret(FS_ATTRIB);
16937+ test_ret(FS_CLOSE_WRITE);
16938+ test_ret(FS_CLOSE_NOWRITE);
16939+ test_ret(FS_OPEN);
16940+ test_ret(FS_MOVED_FROM);
16941+ test_ret(FS_MOVED_TO);
16942+ test_ret(FS_CREATE);
16943+ test_ret(FS_DELETE);
16944+ test_ret(FS_DELETE_SELF);
16945+ test_ret(FS_MOVE_SELF);
16946+ test_ret(FS_UNMOUNT);
16947+ test_ret(FS_Q_OVERFLOW);
16948+ test_ret(FS_IN_IGNORED);
b912730e 16949+ test_ret(FS_ISDIR);
4a4d8108
AM
16950+ test_ret(FS_IN_ONESHOT);
16951+ test_ret(FS_EVENT_ON_CHILD);
16952+ return "";
16953+#undef test_ret
16954+#else
16955+ return "??";
16956+#endif
1facf9fc 16957+}
4a4d8108 16958+#endif
1facf9fc 16959+
16960+/* ---------------------------------------------------------------------- */
16961+
1716fcea
AM
16962+static void au_hfsn_free_group(struct fsnotify_group *group)
16963+{
16964+ struct au_br_hfsnotify *hfsn = group->private;
16965+
5afbbe0d 16966+ /* AuDbg("here\n"); */
9f237c51 16967+ au_kfree_try_rcu(hfsn);
1716fcea
AM
16968+}
16969+
4a4d8108 16970+static int au_hfsn_handle_event(struct fsnotify_group *group,
fb47a38f 16971+ struct inode *inode,
a2654f78 16972+ u32 mask, const void *data, int data_type,
83b672a5 16973+ const struct qstr *file_name, u32 cookie,
ffa93bbd 16974+ struct fsnotify_iter_info *iter_info)
1facf9fc 16975+{
16976+ int err;
4a4d8108
AM
16977+ struct au_hnotify *hnotify;
16978+ struct inode *h_dir, *h_inode;
cd7a4cd9 16979+ struct fsnotify_mark *inode_mark;
4a4d8108 16980+
fb47a38f 16981+ AuDebugOn(data_type != FSNOTIFY_EVENT_INODE);
1facf9fc 16982+
16983+ err = 0;
0c5527e5 16984+ /* if FS_UNMOUNT happens, there must be another bug */
4a4d8108 16985+ AuDebugOn(mask & FS_UNMOUNT);
0c5527e5 16986+ if (mask & (FS_IN_IGNORED | FS_UNMOUNT))
1facf9fc 16987+ goto out;
1facf9fc 16988+
fb47a38f
JR
16989+ h_dir = inode;
16990+ h_inode = NULL;
4a4d8108 16991+#ifdef AuDbgHnotify
392086de 16992+ au_debug_on();
fbc438ed
JR
16993+ if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1
16994+ || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) {
4a4d8108
AM
16995+ AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n",
16996+ h_dir->i_ino, mask, au_hfsn_name(mask),
fbc438ed 16997+ AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0);
4a4d8108 16998+ /* WARN_ON(1); */
1facf9fc 16999+ }
392086de 17000+ au_debug_off();
1facf9fc 17001+#endif
4a4d8108 17002+
cd7a4cd9 17003+ inode_mark = fsnotify_iter_inode_mark(iter_info);
0c5527e5
AM
17004+ AuDebugOn(!inode_mark);
17005+ hnotify = container_of(inode_mark, struct au_hnotify, hn_mark);
b62f1e65 17006+ err = au_hnotify(h_dir, hnotify, mask, file_name, h_inode);
1facf9fc 17007+
4a4d8108
AM
17008+out:
17009+ return err;
17010+}
1facf9fc 17011+
4a4d8108 17012+static struct fsnotify_ops au_hfsn_ops = {
1716fcea 17013+ .handle_event = au_hfsn_handle_event,
ffa93bbd
AM
17014+ .free_group_priv = au_hfsn_free_group,
17015+ .free_mark = au_hfsn_free_mark
4a4d8108
AM
17016+};
17017+
17018+/* ---------------------------------------------------------------------- */
17019+
027c5e7a
AM
17020+static void au_hfsn_fin_br(struct au_branch *br)
17021+{
1716fcea 17022+ struct au_br_hfsnotify *hfsn;
027c5e7a 17023+
1716fcea 17024+ hfsn = br->br_hfsn;
c1595e42
JR
17025+ if (hfsn) {
17026+ lockdep_off();
1716fcea 17027+ fsnotify_put_group(hfsn->hfsn_group);
c1595e42
JR
17028+ lockdep_on();
17029+ }
027c5e7a
AM
17030+}
17031+
1716fcea 17032+static int au_hfsn_init_br(struct au_branch *br, int perm)
4a4d8108
AM
17033+{
17034+ int err;
1716fcea
AM
17035+ struct fsnotify_group *group;
17036+ struct au_br_hfsnotify *hfsn;
1facf9fc 17037+
4a4d8108 17038+ err = 0;
1716fcea
AM
17039+ br->br_hfsn = NULL;
17040+ if (!au_br_hnotifyable(perm))
027c5e7a 17041+ goto out;
027c5e7a 17042+
1716fcea
AM
17043+ err = -ENOMEM;
17044+ hfsn = kmalloc(sizeof(*hfsn), GFP_NOFS);
17045+ if (unlikely(!hfsn))
027c5e7a
AM
17046+ goto out;
17047+
1716fcea
AM
17048+ err = 0;
17049+ group = fsnotify_alloc_group(&au_hfsn_ops);
17050+ if (IS_ERR(group)) {
17051+ err = PTR_ERR(group);
0c5527e5 17052+ pr_err("fsnotify_alloc_group() failed, %d\n", err);
1716fcea 17053+ goto out_hfsn;
4a4d8108 17054+ }
1facf9fc 17055+
1716fcea
AM
17056+ group->private = hfsn;
17057+ hfsn->hfsn_group = group;
17058+ br->br_hfsn = hfsn;
17059+ goto out; /* success */
17060+
17061+out_hfsn:
9f237c51 17062+ au_kfree_try_rcu(hfsn);
027c5e7a 17063+out:
1716fcea
AM
17064+ return err;
17065+}
17066+
17067+static int au_hfsn_reset_br(unsigned int udba, struct au_branch *br, int perm)
17068+{
17069+ int err;
17070+
17071+ err = 0;
17072+ if (!br->br_hfsn)
17073+ err = au_hfsn_init_br(br, perm);
17074+
1facf9fc 17075+ return err;
17076+}
17077+
7eafdf33
AM
17078+/* ---------------------------------------------------------------------- */
17079+
17080+static void au_hfsn_fin(void)
17081+{
17082+ AuDbg("au_hfsn_ifree %lld\n", (long long)atomic64_read(&au_hfsn_ifree));
17083+ wait_event(au_hfsn_wq, !atomic64_read(&au_hfsn_ifree));
17084+}
17085+
4a4d8108
AM
17086+const struct au_hnotify_op au_hnotify_op = {
17087+ .ctl = au_hfsn_ctl,
17088+ .alloc = au_hfsn_alloc,
17089+ .free = au_hfsn_free,
1facf9fc 17090+
7eafdf33
AM
17091+ .fin = au_hfsn_fin,
17092+
027c5e7a
AM
17093+ .reset_br = au_hfsn_reset_br,
17094+ .fin_br = au_hfsn_fin_br,
17095+ .init_br = au_hfsn_init_br
4a4d8108 17096+};
7f207e10 17097diff -urN /usr/share/empty/fs/aufs/hfsplus.c linux/fs/aufs/hfsplus.c
eca34b5c 17098--- /usr/share/empty/fs/aufs/hfsplus.c 1970-01-01 01:00:00.000000000 +0100
016522bc 17099+++ linux/fs/aufs/hfsplus.c 2020-01-27 10:57:18.172204883 +0100
acd2b654 17100@@ -0,0 +1,60 @@
cd7a4cd9 17101+// SPDX-License-Identifier: GPL-2.0
4a4d8108 17102+/*
016522bc 17103+ * Copyright (C) 2010-2020 Junjiro R. Okajima
4a4d8108
AM
17104+ *
17105+ * This program, aufs is free software; you can redistribute it and/or modify
17106+ * it under the terms of the GNU General Public License as published by
17107+ * the Free Software Foundation; either version 2 of the License, or
17108+ * (at your option) any later version.
17109+ *
17110+ * This program is distributed in the hope that it will be useful,
17111+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17112+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17113+ * GNU General Public License for more details.
17114+ *
17115+ * You should have received a copy of the GNU General Public License
523b37e3 17116+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 17117+ */
1facf9fc 17118+
4a4d8108 17119+/*
acd2b654 17120+ * special support for filesystems which acquires an inode mutex
4a4d8108
AM
17121+ * at final closing a file, eg, hfsplus.
17122+ *
17123+ * This trick is very simple and stupid, just to open the file before really
acd2b654 17124+ * necessary open to tell hfsplus that this is not the final closing.
4a4d8108
AM
17125+ * The caller should call au_h_open_pre() after acquiring the inode mutex,
17126+ * and au_h_open_post() after releasing it.
17127+ */
1facf9fc 17128+
4a4d8108 17129+#include "aufs.h"
1facf9fc 17130+
392086de
AM
17131+struct file *au_h_open_pre(struct dentry *dentry, aufs_bindex_t bindex,
17132+ int force_wr)
4a4d8108
AM
17133+{
17134+ struct file *h_file;
17135+ struct dentry *h_dentry;
1facf9fc 17136+
4a4d8108
AM
17137+ h_dentry = au_h_dptr(dentry, bindex);
17138+ AuDebugOn(!h_dentry);
5527c038 17139+ AuDebugOn(d_is_negative(h_dentry));
4a4d8108
AM
17140+
17141+ h_file = NULL;
17142+ if (au_test_hfsplus(h_dentry->d_sb)
7e9cd9fe 17143+ && d_is_reg(h_dentry))
4a4d8108
AM
17144+ h_file = au_h_open(dentry, bindex,
17145+ O_RDONLY | O_NOATIME | O_LARGEFILE,
392086de 17146+ /*file*/NULL, force_wr);
4a4d8108 17147+ return h_file;
1facf9fc 17148+}
17149+
4a4d8108
AM
17150+void au_h_open_post(struct dentry *dentry, aufs_bindex_t bindex,
17151+ struct file *h_file)
17152+{
acd2b654
AM
17153+ struct au_branch *br;
17154+
4a4d8108
AM
17155+ if (h_file) {
17156+ fput(h_file);
acd2b654
AM
17157+ br = au_sbr(dentry->d_sb, bindex);
17158+ au_lcnt_dec(&br->br_nfiles);
4a4d8108
AM
17159+ }
17160+}
7f207e10 17161diff -urN /usr/share/empty/fs/aufs/hnotify.c linux/fs/aufs/hnotify.c
eca34b5c 17162--- /usr/share/empty/fs/aufs/hnotify.c 1970-01-01 01:00:00.000000000 +0100
016522bc 17163+++ linux/fs/aufs/hnotify.c 2020-01-27 10:57:18.172204883 +0100
43982f53 17164@@ -0,0 +1,715 @@
cd7a4cd9 17165+// SPDX-License-Identifier: GPL-2.0
e49829fe 17166+/*
016522bc 17167+ * Copyright (C) 2005-2020 Junjiro R. Okajima
e49829fe
JR
17168+ *
17169+ * This program, aufs is free software; you can redistribute it and/or modify
17170+ * it under the terms of the GNU General Public License as published by
17171+ * the Free Software Foundation; either version 2 of the License, or
17172+ * (at your option) any later version.
17173+ *
17174+ * This program is distributed in the hope that it will be useful,
17175+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17176+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17177+ * GNU General Public License for more details.
17178+ *
17179+ * You should have received a copy of the GNU General Public License
523b37e3 17180+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
e49829fe
JR
17181+ */
17182+
17183+/*
7f207e10 17184+ * abstraction to notify the direct changes on lower directories
e49829fe
JR
17185+ */
17186+
eca801bf 17187+/* #include <linux/iversion.h> */
e49829fe
JR
17188+#include "aufs.h"
17189+
027c5e7a 17190+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode)
e49829fe
JR
17191+{
17192+ int err;
7f207e10 17193+ struct au_hnotify *hn;
1facf9fc 17194+
4a4d8108
AM
17195+ err = -ENOMEM;
17196+ hn = au_cache_alloc_hnotify();
17197+ if (hn) {
17198+ hn->hn_aufs_inode = inode;
027c5e7a
AM
17199+ hinode->hi_notify = hn;
17200+ err = au_hnotify_op.alloc(hinode);
17201+ AuTraceErr(err);
17202+ if (unlikely(err)) {
17203+ hinode->hi_notify = NULL;
1c60b727 17204+ au_cache_free_hnotify(hn);
4a4d8108
AM
17205+ /*
17206+ * The upper dir was removed by udba, but the same named
acd2b654 17207+ * dir left. In this case, aufs assigns a new inode
4a4d8108 17208+ * number and set the monitor again.
acd2b654 17209+ * For the lower dir, the old monitor is still left.
4a4d8108
AM
17210+ */
17211+ if (err == -EEXIST)
17212+ err = 0;
17213+ }
1308ab2a 17214+ }
1308ab2a 17215+
027c5e7a 17216+ AuTraceErr(err);
1308ab2a 17217+ return err;
dece6358 17218+}
1facf9fc 17219+
4a4d8108 17220+void au_hn_free(struct au_hinode *hinode)
dece6358 17221+{
4a4d8108 17222+ struct au_hnotify *hn;
1facf9fc 17223+
4a4d8108
AM
17224+ hn = hinode->hi_notify;
17225+ if (hn) {
4a4d8108 17226+ hinode->hi_notify = NULL;
7eafdf33 17227+ if (au_hnotify_op.free(hinode, hn))
1c60b727 17228+ au_cache_free_hnotify(hn);
4a4d8108
AM
17229+ }
17230+}
dece6358 17231+
4a4d8108 17232+/* ---------------------------------------------------------------------- */
dece6358 17233+
4a4d8108
AM
17234+void au_hn_ctl(struct au_hinode *hinode, int do_set)
17235+{
17236+ if (hinode->hi_notify)
17237+ au_hnotify_op.ctl(hinode, do_set);
17238+}
17239+
17240+void au_hn_reset(struct inode *inode, unsigned int flags)
17241+{
5afbbe0d 17242+ aufs_bindex_t bindex, bbot;
4a4d8108
AM
17243+ struct inode *hi;
17244+ struct dentry *iwhdentry;
1facf9fc 17245+
5afbbe0d
AM
17246+ bbot = au_ibbot(inode);
17247+ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) {
4a4d8108
AM
17248+ hi = au_h_iptr(inode, bindex);
17249+ if (!hi)
17250+ continue;
1308ab2a 17251+
febd17d6 17252+ /* inode_lock_nested(hi, AuLsc_I_CHILD); */
4a4d8108
AM
17253+ iwhdentry = au_hi_wh(inode, bindex);
17254+ if (iwhdentry)
17255+ dget(iwhdentry);
17256+ au_igrab(hi);
17257+ au_set_h_iptr(inode, bindex, NULL, 0);
17258+ au_set_h_iptr(inode, bindex, au_igrab(hi),
17259+ flags & ~AuHi_XINO);
17260+ iput(hi);
17261+ dput(iwhdentry);
febd17d6 17262+ /* inode_unlock(hi); */
1facf9fc 17263+ }
1facf9fc 17264+}
17265+
1308ab2a 17266+/* ---------------------------------------------------------------------- */
1facf9fc 17267+
4a4d8108 17268+static int hn_xino(struct inode *inode, struct inode *h_inode)
1facf9fc 17269+{
4a4d8108 17270+ int err;
5afbbe0d 17271+ aufs_bindex_t bindex, bbot, bfound, btop;
4a4d8108 17272+ struct inode *h_i;
1facf9fc 17273+
4a4d8108
AM
17274+ err = 0;
17275+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 17276+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
17277+ goto out;
17278+ }
1facf9fc 17279+
4a4d8108 17280+ bfound = -1;
5afbbe0d
AM
17281+ bbot = au_ibbot(inode);
17282+ btop = au_ibtop(inode);
4a4d8108 17283+#if 0 /* reserved for future use */
5afbbe0d 17284+ if (bindex == bbot) {
4a4d8108
AM
17285+ /* keep this ino in rename case */
17286+ goto out;
17287+ }
17288+#endif
5afbbe0d 17289+ for (bindex = btop; bindex <= bbot; bindex++)
4a4d8108
AM
17290+ if (au_h_iptr(inode, bindex) == h_inode) {
17291+ bfound = bindex;
17292+ break;
17293+ }
17294+ if (bfound < 0)
1308ab2a 17295+ goto out;
1facf9fc 17296+
5afbbe0d 17297+ for (bindex = btop; bindex <= bbot; bindex++) {
4a4d8108
AM
17298+ h_i = au_h_iptr(inode, bindex);
17299+ if (!h_i)
17300+ continue;
1facf9fc 17301+
4a4d8108
AM
17302+ err = au_xino_write(inode->i_sb, bindex, h_i->i_ino, /*ino*/0);
17303+ /* ignore this error */
17304+ /* bad action? */
1facf9fc 17305+ }
1facf9fc 17306+
4a4d8108 17307+ /* children inode number will be broken */
1facf9fc 17308+
4f0767ce 17309+out:
4a4d8108
AM
17310+ AuTraceErr(err);
17311+ return err;
1facf9fc 17312+}
17313+
4a4d8108 17314+static int hn_gen_tree(struct dentry *dentry)
1facf9fc 17315+{
4a4d8108
AM
17316+ int err, i, j, ndentry;
17317+ struct au_dcsub_pages dpages;
17318+ struct au_dpage *dpage;
17319+ struct dentry **dentries;
1facf9fc 17320+
4a4d8108
AM
17321+ err = au_dpages_init(&dpages, GFP_NOFS);
17322+ if (unlikely(err))
17323+ goto out;
17324+ err = au_dcsub_pages(&dpages, dentry, NULL, NULL);
17325+ if (unlikely(err))
17326+ goto out_dpages;
1facf9fc 17327+
4a4d8108
AM
17328+ for (i = 0; i < dpages.ndpage; i++) {
17329+ dpage = dpages.dpages + i;
17330+ dentries = dpage->dentries;
17331+ ndentry = dpage->ndentry;
17332+ for (j = 0; j < ndentry; j++) {
17333+ struct dentry *d;
17334+
17335+ d = dentries[j];
17336+ if (IS_ROOT(d))
17337+ continue;
17338+
4a4d8108 17339+ au_digen_dec(d);
5527c038 17340+ if (d_really_is_positive(d))
4a4d8108
AM
17341+ /* todo: reset children xino?
17342+ cached children only? */
5527c038 17343+ au_iigen_dec(d_inode(d));
1308ab2a 17344+ }
dece6358 17345+ }
1facf9fc 17346+
4f0767ce 17347+out_dpages:
4a4d8108 17348+ au_dpages_free(&dpages);
4f0767ce 17349+out:
dece6358
AM
17350+ return err;
17351+}
17352+
1308ab2a 17353+/*
4a4d8108 17354+ * return 0 if processed.
1308ab2a 17355+ */
4a4d8108
AM
17356+static int hn_gen_by_inode(char *name, unsigned int nlen, struct inode *inode,
17357+ const unsigned int isdir)
dece6358 17358+{
1308ab2a 17359+ int err;
4a4d8108
AM
17360+ struct dentry *d;
17361+ struct qstr *dname;
1facf9fc 17362+
4a4d8108
AM
17363+ err = 1;
17364+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 17365+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
17366+ err = 0;
17367+ goto out;
17368+ }
dece6358 17369+
4a4d8108
AM
17370+ if (!isdir) {
17371+ AuDebugOn(!name);
17372+ au_iigen_dec(inode);
027c5e7a 17373+ spin_lock(&inode->i_lock);
c1595e42 17374+ hlist_for_each_entry(d, &inode->i_dentry, d_u.d_alias) {
027c5e7a 17375+ spin_lock(&d->d_lock);
4a4d8108
AM
17376+ dname = &d->d_name;
17377+ if (dname->len != nlen
027c5e7a
AM
17378+ && memcmp(dname->name, name, nlen)) {
17379+ spin_unlock(&d->d_lock);
4a4d8108 17380+ continue;
027c5e7a 17381+ }
4a4d8108 17382+ err = 0;
4a4d8108
AM
17383+ au_digen_dec(d);
17384+ spin_unlock(&d->d_lock);
17385+ break;
1facf9fc 17386+ }
027c5e7a 17387+ spin_unlock(&inode->i_lock);
1308ab2a 17388+ } else {
027c5e7a 17389+ au_fset_si(au_sbi(inode->i_sb), FAILED_REFRESH_DIR);
c1595e42 17390+ d = d_find_any_alias(inode);
4a4d8108
AM
17391+ if (!d) {
17392+ au_iigen_dec(inode);
17393+ goto out;
17394+ }
1facf9fc 17395+
027c5e7a 17396+ spin_lock(&d->d_lock);
4a4d8108 17397+ dname = &d->d_name;
027c5e7a
AM
17398+ if (dname->len == nlen && !memcmp(dname->name, name, nlen)) {
17399+ spin_unlock(&d->d_lock);
4a4d8108 17400+ err = hn_gen_tree(d);
027c5e7a
AM
17401+ spin_lock(&d->d_lock);
17402+ }
17403+ spin_unlock(&d->d_lock);
4a4d8108
AM
17404+ dput(d);
17405+ }
1facf9fc 17406+
4f0767ce 17407+out:
4a4d8108 17408+ AuTraceErr(err);
1308ab2a 17409+ return err;
17410+}
dece6358 17411+
4a4d8108 17412+static int hn_gen_by_name(struct dentry *dentry, const unsigned int isdir)
1facf9fc 17413+{
4a4d8108 17414+ int err;
1facf9fc 17415+
5527c038 17416+ if (IS_ROOT(dentry)) {
0c3ec466 17417+ pr_warn("branch root dir was changed\n");
4a4d8108
AM
17418+ return 0;
17419+ }
1308ab2a 17420+
4a4d8108
AM
17421+ err = 0;
17422+ if (!isdir) {
4a4d8108 17423+ au_digen_dec(dentry);
5527c038
JR
17424+ if (d_really_is_positive(dentry))
17425+ au_iigen_dec(d_inode(dentry));
4a4d8108 17426+ } else {
027c5e7a 17427+ au_fset_si(au_sbi(dentry->d_sb), FAILED_REFRESH_DIR);
5527c038 17428+ if (d_really_is_positive(dentry))
4a4d8108
AM
17429+ err = hn_gen_tree(dentry);
17430+ }
17431+
17432+ AuTraceErr(err);
17433+ return err;
1facf9fc 17434+}
17435+
4a4d8108 17436+/* ---------------------------------------------------------------------- */
1facf9fc 17437+
4a4d8108
AM
17438+/* hnotify job flags */
17439+#define AuHnJob_XINO0 1
17440+#define AuHnJob_GEN (1 << 1)
17441+#define AuHnJob_DIRENT (1 << 2)
17442+#define AuHnJob_ISDIR (1 << 3)
17443+#define AuHnJob_TRYXINO0 (1 << 4)
17444+#define AuHnJob_MNTPNT (1 << 5)
17445+#define au_ftest_hnjob(flags, name) ((flags) & AuHnJob_##name)
7f207e10
AM
17446+#define au_fset_hnjob(flags, name) \
17447+ do { (flags) |= AuHnJob_##name; } while (0)
17448+#define au_fclr_hnjob(flags, name) \
17449+ do { (flags) &= ~AuHnJob_##name; } while (0)
1facf9fc 17450+
4a4d8108
AM
17451+enum {
17452+ AuHn_CHILD,
17453+ AuHn_PARENT,
17454+ AuHnLast
17455+};
1facf9fc 17456+
4a4d8108
AM
17457+struct au_hnotify_args {
17458+ struct inode *h_dir, *dir, *h_child_inode;
17459+ u32 mask;
17460+ unsigned int flags[AuHnLast];
17461+ unsigned int h_child_nlen;
17462+ char h_child_name[];
17463+};
1facf9fc 17464+
4a4d8108
AM
17465+struct hn_job_args {
17466+ unsigned int flags;
17467+ struct inode *inode, *h_inode, *dir, *h_dir;
17468+ struct dentry *dentry;
17469+ char *h_name;
17470+ int h_nlen;
17471+};
1308ab2a 17472+
4a4d8108
AM
17473+static int hn_job(struct hn_job_args *a)
17474+{
17475+ const unsigned int isdir = au_ftest_hnjob(a->flags, ISDIR);
076b876e 17476+ int e;
1308ab2a 17477+
4a4d8108
AM
17478+ /* reset xino */
17479+ if (au_ftest_hnjob(a->flags, XINO0) && a->inode)
17480+ hn_xino(a->inode, a->h_inode); /* ignore this error */
1308ab2a 17481+
4a4d8108
AM
17482+ if (au_ftest_hnjob(a->flags, TRYXINO0)
17483+ && a->inode
17484+ && a->h_inode) {
be118d29 17485+ inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD);
38d290e6
JR
17486+ if (!a->h_inode->i_nlink
17487+ && !(a->h_inode->i_state & I_LINKABLE))
4a4d8108 17488+ hn_xino(a->inode, a->h_inode); /* ignore this error */
3c1bdaff 17489+ inode_unlock_shared(a->h_inode);
1308ab2a 17490+ }
1facf9fc 17491+
4a4d8108
AM
17492+ /* make the generation obsolete */
17493+ if (au_ftest_hnjob(a->flags, GEN)) {
076b876e 17494+ e = -1;
4a4d8108 17495+ if (a->inode)
076b876e 17496+ e = hn_gen_by_inode(a->h_name, a->h_nlen, a->inode,
4a4d8108 17497+ isdir);
076b876e 17498+ if (e && a->dentry)
4a4d8108
AM
17499+ hn_gen_by_name(a->dentry, isdir);
17500+ /* ignore this error */
1facf9fc 17501+ }
1facf9fc 17502+
4a4d8108
AM
17503+ /* make dir entries obsolete */
17504+ if (au_ftest_hnjob(a->flags, DIRENT) && a->inode) {
17505+ struct au_vdir *vdir;
1facf9fc 17506+
4a4d8108
AM
17507+ vdir = au_ivdir(a->inode);
17508+ if (vdir)
17509+ vdir->vd_jiffy = 0;
17510+ /* IMustLock(a->inode); */
be118d29 17511+ /* inode_inc_iversion(a->inode); */
4a4d8108 17512+ }
1facf9fc 17513+
4a4d8108
AM
17514+ /* can do nothing but warn */
17515+ if (au_ftest_hnjob(a->flags, MNTPNT)
17516+ && a->dentry
17517+ && d_mountpoint(a->dentry))
523b37e3 17518+ pr_warn("mount-point %pd is removed or renamed\n", a->dentry);
1facf9fc 17519+
4a4d8108 17520+ return 0;
1308ab2a 17521+}
1facf9fc 17522+
1308ab2a 17523+/* ---------------------------------------------------------------------- */
1facf9fc 17524+
4a4d8108
AM
17525+static struct dentry *lookup_wlock_by_name(char *name, unsigned int nlen,
17526+ struct inode *dir)
1308ab2a 17527+{
4a4d8108
AM
17528+ struct dentry *dentry, *d, *parent;
17529+ struct qstr *dname;
1308ab2a 17530+
c1595e42 17531+ parent = d_find_any_alias(dir);
4a4d8108
AM
17532+ if (!parent)
17533+ return NULL;
1308ab2a 17534+
4a4d8108 17535+ dentry = NULL;
027c5e7a 17536+ spin_lock(&parent->d_lock);
c1595e42 17537+ list_for_each_entry(d, &parent->d_subdirs, d_child) {
523b37e3 17538+ /* AuDbg("%pd\n", d); */
027c5e7a 17539+ spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
4a4d8108
AM
17540+ dname = &d->d_name;
17541+ if (dname->len != nlen || memcmp(dname->name, name, nlen))
027c5e7a
AM
17542+ goto cont_unlock;
17543+ if (au_di(d))
17544+ au_digen_dec(d);
17545+ else
17546+ goto cont_unlock;
c1595e42 17547+ if (au_dcount(d) > 0) {
027c5e7a 17548+ dentry = dget_dlock(d);
4a4d8108 17549+ spin_unlock(&d->d_lock);
027c5e7a 17550+ break;
dece6358 17551+ }
1facf9fc 17552+
f6b6e03d 17553+cont_unlock:
027c5e7a 17554+ spin_unlock(&d->d_lock);
1308ab2a 17555+ }
027c5e7a 17556+ spin_unlock(&parent->d_lock);
4a4d8108 17557+ dput(parent);
1facf9fc 17558+
4a4d8108
AM
17559+ if (dentry)
17560+ di_write_lock_child(dentry);
1308ab2a 17561+
4a4d8108
AM
17562+ return dentry;
17563+}
dece6358 17564+
4a4d8108
AM
17565+static struct inode *lookup_wlock_by_ino(struct super_block *sb,
17566+ aufs_bindex_t bindex, ino_t h_ino)
17567+{
17568+ struct inode *inode;
17569+ ino_t ino;
17570+ int err;
17571+
17572+ inode = NULL;
17573+ err = au_xino_read(sb, bindex, h_ino, &ino);
17574+ if (!err && ino)
17575+ inode = ilookup(sb, ino);
17576+ if (!inode)
17577+ goto out;
17578+
17579+ if (unlikely(inode->i_ino == AUFS_ROOT_INO)) {
0c3ec466 17580+ pr_warn("wrong root branch\n");
4a4d8108
AM
17581+ iput(inode);
17582+ inode = NULL;
17583+ goto out;
1308ab2a 17584+ }
17585+
4a4d8108 17586+ ii_write_lock_child(inode);
1308ab2a 17587+
4f0767ce 17588+out:
4a4d8108 17589+ return inode;
dece6358
AM
17590+}
17591+
4a4d8108 17592+static void au_hn_bh(void *_args)
1facf9fc 17593+{
4a4d8108
AM
17594+ struct au_hnotify_args *a = _args;
17595+ struct super_block *sb;
5afbbe0d 17596+ aufs_bindex_t bindex, bbot, bfound;
4a4d8108 17597+ unsigned char xino, try_iput;
1facf9fc 17598+ int err;
1308ab2a 17599+ struct inode *inode;
4a4d8108
AM
17600+ ino_t h_ino;
17601+ struct hn_job_args args;
17602+ struct dentry *dentry;
17603+ struct au_sbinfo *sbinfo;
1facf9fc 17604+
4a4d8108
AM
17605+ AuDebugOn(!_args);
17606+ AuDebugOn(!a->h_dir);
17607+ AuDebugOn(!a->dir);
17608+ AuDebugOn(!a->mask);
17609+ AuDbg("mask 0x%x, i%lu, hi%lu, hci%lu\n",
17610+ a->mask, a->dir->i_ino, a->h_dir->i_ino,
17611+ a->h_child_inode ? a->h_child_inode->i_ino : 0);
1facf9fc 17612+
4a4d8108
AM
17613+ inode = NULL;
17614+ dentry = NULL;
17615+ /*
17616+ * do not lock a->dir->i_mutex here
17617+ * because of d_revalidate() may cause a deadlock.
17618+ */
17619+ sb = a->dir->i_sb;
17620+ AuDebugOn(!sb);
17621+ sbinfo = au_sbi(sb);
17622+ AuDebugOn(!sbinfo);
7f207e10 17623+ si_write_lock(sb, AuLock_NOPLMW);
1facf9fc 17624+
8b6a4947
AM
17625+ if (au_opt_test(sbinfo->si_mntflags, DIRREN))
17626+ switch (a->mask & FS_EVENTS_POSS_ON_CHILD) {
17627+ case FS_MOVED_FROM:
17628+ case FS_MOVED_TO:
17629+ AuWarn1("DIRREN with UDBA may not work correctly "
17630+ "for the direct rename(2)\n");
17631+ }
17632+
4a4d8108
AM
17633+ ii_read_lock_parent(a->dir);
17634+ bfound = -1;
5afbbe0d
AM
17635+ bbot = au_ibbot(a->dir);
17636+ for (bindex = au_ibtop(a->dir); bindex <= bbot; bindex++)
4a4d8108
AM
17637+ if (au_h_iptr(a->dir, bindex) == a->h_dir) {
17638+ bfound = bindex;
17639+ break;
17640+ }
17641+ ii_read_unlock(a->dir);
17642+ if (unlikely(bfound < 0))
17643+ goto out;
1facf9fc 17644+
4a4d8108
AM
17645+ xino = !!au_opt_test(au_mntflags(sb), XINO);
17646+ h_ino = 0;
17647+ if (a->h_child_inode)
17648+ h_ino = a->h_child_inode->i_ino;
1facf9fc 17649+
4a4d8108
AM
17650+ if (a->h_child_nlen
17651+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], GEN)
17652+ || au_ftest_hnjob(a->flags[AuHn_CHILD], MNTPNT)))
17653+ dentry = lookup_wlock_by_name(a->h_child_name, a->h_child_nlen,
17654+ a->dir);
17655+ try_iput = 0;
5527c038
JR
17656+ if (dentry && d_really_is_positive(dentry))
17657+ inode = d_inode(dentry);
4a4d8108
AM
17658+ if (xino && !inode && h_ino
17659+ && (au_ftest_hnjob(a->flags[AuHn_CHILD], XINO0)
17660+ || au_ftest_hnjob(a->flags[AuHn_CHILD], TRYXINO0)
17661+ || au_ftest_hnjob(a->flags[AuHn_CHILD], GEN))) {
17662+ inode = lookup_wlock_by_ino(sb, bfound, h_ino);
17663+ try_iput = 1;
f0c0a007 17664+ }
1facf9fc 17665+
4a4d8108
AM
17666+ args.flags = a->flags[AuHn_CHILD];
17667+ args.dentry = dentry;
17668+ args.inode = inode;
17669+ args.h_inode = a->h_child_inode;
17670+ args.dir = a->dir;
17671+ args.h_dir = a->h_dir;
17672+ args.h_name = a->h_child_name;
17673+ args.h_nlen = a->h_child_nlen;
17674+ err = hn_job(&args);
17675+ if (dentry) {
027c5e7a 17676+ if (au_di(dentry))
4a4d8108
AM
17677+ di_write_unlock(dentry);
17678+ dput(dentry);
17679+ }
17680+ if (inode && try_iput) {
17681+ ii_write_unlock(inode);
17682+ iput(inode);
17683+ }
1facf9fc 17684+
4a4d8108
AM
17685+ ii_write_lock_parent(a->dir);
17686+ args.flags = a->flags[AuHn_PARENT];
17687+ args.dentry = NULL;
17688+ args.inode = a->dir;
17689+ args.h_inode = a->h_dir;
17690+ args.dir = NULL;
17691+ args.h_dir = NULL;
17692+ args.h_name = NULL;
17693+ args.h_nlen = 0;
17694+ err = hn_job(&args);
17695+ ii_write_unlock(a->dir);
1facf9fc 17696+
4f0767ce 17697+out:
4a4d8108
AM
17698+ iput(a->h_child_inode);
17699+ iput(a->h_dir);
17700+ iput(a->dir);
027c5e7a
AM
17701+ si_write_unlock(sb);
17702+ au_nwt_done(&sbinfo->si_nowait);
9f237c51 17703+ au_kfree_rcu(a);
dece6358 17704+}
1facf9fc 17705+
4a4d8108
AM
17706+/* ---------------------------------------------------------------------- */
17707+
17708+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
b62f1e65 17709+ const struct qstr *h_child_qstr, struct inode *h_child_inode)
dece6358 17710+{
4a4d8108 17711+ int err, len;
53392da6 17712+ unsigned int flags[AuHnLast], f;
4a4d8108
AM
17713+ unsigned char isdir, isroot, wh;
17714+ struct inode *dir;
17715+ struct au_hnotify_args *args;
17716+ char *p, *h_child_name;
dece6358 17717+
1308ab2a 17718+ err = 0;
4a4d8108
AM
17719+ AuDebugOn(!hnotify || !hnotify->hn_aufs_inode);
17720+ dir = igrab(hnotify->hn_aufs_inode);
17721+ if (!dir)
17722+ goto out;
1facf9fc 17723+
4a4d8108
AM
17724+ isroot = (dir->i_ino == AUFS_ROOT_INO);
17725+ wh = 0;
17726+ h_child_name = (void *)h_child_qstr->name;
17727+ len = h_child_qstr->len;
17728+ if (h_child_name) {
17729+ if (len > AUFS_WH_PFX_LEN
17730+ && !memcmp(h_child_name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
17731+ h_child_name += AUFS_WH_PFX_LEN;
17732+ len -= AUFS_WH_PFX_LEN;
17733+ wh = 1;
17734+ }
1facf9fc 17735+ }
dece6358 17736+
4a4d8108
AM
17737+ isdir = 0;
17738+ if (h_child_inode)
17739+ isdir = !!S_ISDIR(h_child_inode->i_mode);
17740+ flags[AuHn_PARENT] = AuHnJob_ISDIR;
17741+ flags[AuHn_CHILD] = 0;
17742+ if (isdir)
17743+ flags[AuHn_CHILD] = AuHnJob_ISDIR;
17744+ au_fset_hnjob(flags[AuHn_PARENT], DIRENT);
17745+ au_fset_hnjob(flags[AuHn_CHILD], GEN);
fbc438ed 17746+ switch (mask & ALL_FSNOTIFY_DIRENT_EVENTS) {
4a4d8108
AM
17747+ case FS_MOVED_FROM:
17748+ case FS_MOVED_TO:
17749+ au_fset_hnjob(flags[AuHn_CHILD], XINO0);
17750+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
17751+ /*FALLTHROUGH*/
17752+ case FS_CREATE:
fb47a38f 17753+ AuDebugOn(!h_child_name);
4a4d8108 17754+ break;
1facf9fc 17755+
4a4d8108
AM
17756+ case FS_DELETE:
17757+ /*
17758+ * aufs never be able to get this child inode.
17759+ * revalidation should be in d_revalidate()
17760+ * by checking i_nlink, i_generation or d_unhashed().
17761+ */
17762+ AuDebugOn(!h_child_name);
17763+ au_fset_hnjob(flags[AuHn_CHILD], TRYXINO0);
17764+ au_fset_hnjob(flags[AuHn_CHILD], MNTPNT);
17765+ break;
dece6358 17766+
4a4d8108
AM
17767+ default:
17768+ AuDebugOn(1);
17769+ }
1308ab2a 17770+
4a4d8108
AM
17771+ if (wh)
17772+ h_child_inode = NULL;
1308ab2a 17773+
4a4d8108
AM
17774+ err = -ENOMEM;
17775+ /* iput() and kfree() will be called in au_hnotify() */
4a4d8108 17776+ args = kmalloc(sizeof(*args) + len + 1, GFP_NOFS);
4a4d8108
AM
17777+ if (unlikely(!args)) {
17778+ AuErr1("no memory\n");
17779+ iput(dir);
17780+ goto out;
17781+ }
17782+ args->flags[AuHn_PARENT] = flags[AuHn_PARENT];
17783+ args->flags[AuHn_CHILD] = flags[AuHn_CHILD];
17784+ args->mask = mask;
17785+ args->dir = dir;
17786+ args->h_dir = igrab(h_dir);
17787+ if (h_child_inode)
17788+ h_child_inode = igrab(h_child_inode); /* can be NULL */
17789+ args->h_child_inode = h_child_inode;
17790+ args->h_child_nlen = len;
17791+ if (len) {
17792+ p = (void *)args;
17793+ p += sizeof(*args);
17794+ memcpy(p, h_child_name, len);
17795+ p[len] = 0;
1308ab2a 17796+ }
1308ab2a 17797+
38d290e6 17798+ /* NFS fires the event for silly-renamed one from kworker */
53392da6 17799+ f = 0;
38d290e6
JR
17800+ if (!dir->i_nlink
17801+ || (au_test_nfs(h_dir->i_sb) && (mask & FS_DELETE)))
53392da6
AM
17802+ f = AuWkq_NEST;
17803+ err = au_wkq_nowait(au_hn_bh, args, dir->i_sb, f);
4a4d8108
AM
17804+ if (unlikely(err)) {
17805+ pr_err("wkq %d\n", err);
17806+ iput(args->h_child_inode);
17807+ iput(args->h_dir);
17808+ iput(args->dir);
9f237c51 17809+ au_kfree_rcu(args);
1facf9fc 17810+ }
1facf9fc 17811+
4a4d8108 17812+out:
1facf9fc 17813+ return err;
17814+}
17815+
027c5e7a
AM
17816+/* ---------------------------------------------------------------------- */
17817+
17818+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm)
17819+{
17820+ int err;
17821+
17822+ AuDebugOn(!(udba & AuOptMask_UDBA));
17823+
17824+ err = 0;
17825+ if (au_hnotify_op.reset_br)
17826+ err = au_hnotify_op.reset_br(udba, br, perm);
17827+
17828+ return err;
17829+}
17830+
17831+int au_hnotify_init_br(struct au_branch *br, int perm)
17832+{
17833+ int err;
17834+
17835+ err = 0;
17836+ if (au_hnotify_op.init_br)
17837+ err = au_hnotify_op.init_br(br, perm);
17838+
17839+ return err;
17840+}
17841+
17842+void au_hnotify_fin_br(struct au_branch *br)
17843+{
17844+ if (au_hnotify_op.fin_br)
17845+ au_hnotify_op.fin_br(br);
17846+}
17847+
4a4d8108
AM
17848+static void au_hn_destroy_cache(void)
17849+{
1c60b727
AM
17850+ kmem_cache_destroy(au_cache[AuCache_HNOTIFY]);
17851+ au_cache[AuCache_HNOTIFY] = NULL;
4a4d8108 17852+}
1308ab2a 17853+
4a4d8108 17854+int __init au_hnotify_init(void)
1facf9fc 17855+{
1308ab2a 17856+ int err;
1308ab2a 17857+
4a4d8108 17858+ err = -ENOMEM;
1c60b727
AM
17859+ au_cache[AuCache_HNOTIFY] = AuCache(au_hnotify);
17860+ if (au_cache[AuCache_HNOTIFY]) {
027c5e7a
AM
17861+ err = 0;
17862+ if (au_hnotify_op.init)
17863+ err = au_hnotify_op.init();
4a4d8108
AM
17864+ if (unlikely(err))
17865+ au_hn_destroy_cache();
1308ab2a 17866+ }
1308ab2a 17867+ AuTraceErr(err);
4a4d8108 17868+ return err;
1308ab2a 17869+}
17870+
4a4d8108 17871+void au_hnotify_fin(void)
1308ab2a 17872+{
027c5e7a
AM
17873+ if (au_hnotify_op.fin)
17874+ au_hnotify_op.fin();
f0c0a007 17875+
4a4d8108 17876+ /* cf. au_cache_fin() */
1c60b727 17877+ if (au_cache[AuCache_HNOTIFY])
4a4d8108 17878+ au_hn_destroy_cache();
dece6358 17879+}
7f207e10 17880diff -urN /usr/share/empty/fs/aufs/iinfo.c linux/fs/aufs/iinfo.c
eca34b5c 17881--- /usr/share/empty/fs/aufs/iinfo.c 1970-01-01 01:00:00.000000000 +0100
016522bc 17882+++ linux/fs/aufs/iinfo.c 2020-01-27 10:57:18.175538316 +0100
062440b3 17883@@ -0,0 +1,286 @@
cd7a4cd9 17884+// SPDX-License-Identifier: GPL-2.0
dece6358 17885+/*
016522bc 17886+ * Copyright (C) 2005-2020 Junjiro R. Okajima
dece6358
AM
17887+ *
17888+ * This program, aufs is free software; you can redistribute it and/or modify
17889+ * it under the terms of the GNU General Public License as published by
17890+ * the Free Software Foundation; either version 2 of the License, or
17891+ * (at your option) any later version.
17892+ *
17893+ * This program is distributed in the hope that it will be useful,
17894+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17895+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17896+ * GNU General Public License for more details.
17897+ *
17898+ * You should have received a copy of the GNU General Public License
523b37e3 17899+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
dece6358 17900+ */
1facf9fc 17901+
dece6358 17902+/*
4a4d8108 17903+ * inode private data
dece6358 17904+ */
1facf9fc 17905+
1308ab2a 17906+#include "aufs.h"
1facf9fc 17907+
4a4d8108 17908+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 17909+{
4a4d8108 17910+ struct inode *h_inode;
5afbbe0d 17911+ struct au_hinode *hinode;
1facf9fc 17912+
4a4d8108 17913+ IiMustAnyLock(inode);
1facf9fc 17914+
5afbbe0d
AM
17915+ hinode = au_hinode(au_ii(inode), bindex);
17916+ h_inode = hinode->hi_inode;
4a4d8108
AM
17917+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
17918+ return h_inode;
17919+}
1facf9fc 17920+
4a4d8108
AM
17921+/* todo: hard/soft set? */
17922+void au_hiput(struct au_hinode *hinode)
17923+{
17924+ au_hn_free(hinode);
17925+ dput(hinode->hi_whdentry);
17926+ iput(hinode->hi_inode);
17927+}
1facf9fc 17928+
4a4d8108
AM
17929+unsigned int au_hi_flags(struct inode *inode, int isdir)
17930+{
17931+ unsigned int flags;
17932+ const unsigned int mnt_flags = au_mntflags(inode->i_sb);
1facf9fc 17933+
4a4d8108
AM
17934+ flags = 0;
17935+ if (au_opt_test(mnt_flags, XINO))
17936+ au_fset_hi(flags, XINO);
17937+ if (isdir && au_opt_test(mnt_flags, UDBA_HNOTIFY))
17938+ au_fset_hi(flags, HNOTIFY);
17939+ return flags;
1facf9fc 17940+}
17941+
4a4d8108
AM
17942+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
17943+ struct inode *h_inode, unsigned int flags)
1308ab2a 17944+{
4a4d8108
AM
17945+ struct au_hinode *hinode;
17946+ struct inode *hi;
17947+ struct au_iinfo *iinfo = au_ii(inode);
1facf9fc 17948+
4a4d8108 17949+ IiMustWriteLock(inode);
dece6358 17950+
5afbbe0d 17951+ hinode = au_hinode(iinfo, bindex);
4a4d8108
AM
17952+ hi = hinode->hi_inode;
17953+ AuDebugOn(h_inode && atomic_read(&h_inode->i_count) <= 0);
17954+
17955+ if (hi)
17956+ au_hiput(hinode);
17957+ hinode->hi_inode = h_inode;
17958+ if (h_inode) {
17959+ int err;
17960+ struct super_block *sb = inode->i_sb;
17961+ struct au_branch *br;
17962+
027c5e7a
AM
17963+ AuDebugOn(inode->i_mode
17964+ && (h_inode->i_mode & S_IFMT)
17965+ != (inode->i_mode & S_IFMT));
5afbbe0d 17966+ if (bindex == iinfo->ii_btop)
4a4d8108
AM
17967+ au_cpup_igen(inode, h_inode);
17968+ br = au_sbr(sb, bindex);
17969+ hinode->hi_id = br->br_id;
17970+ if (au_ftest_hi(flags, XINO)) {
17971+ err = au_xino_write(sb, bindex, h_inode->i_ino,
17972+ inode->i_ino);
17973+ if (unlikely(err))
17974+ AuIOErr1("failed au_xino_write() %d\n", err);
17975+ }
17976+
17977+ if (au_ftest_hi(flags, HNOTIFY)
17978+ && au_br_hnotifyable(br->br_perm)) {
027c5e7a 17979+ err = au_hn_alloc(hinode, inode);
4a4d8108
AM
17980+ if (unlikely(err))
17981+ AuIOErr1("au_hn_alloc() %d\n", err);
1308ab2a 17982+ }
17983+ }
4a4d8108 17984+}
dece6358 17985+
4a4d8108
AM
17986+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
17987+ struct dentry *h_wh)
17988+{
17989+ struct au_hinode *hinode;
dece6358 17990+
4a4d8108
AM
17991+ IiMustWriteLock(inode);
17992+
5afbbe0d 17993+ hinode = au_hinode(au_ii(inode), bindex);
4a4d8108
AM
17994+ AuDebugOn(hinode->hi_whdentry);
17995+ hinode->hi_whdentry = h_wh;
1facf9fc 17996+}
17997+
537831f9 17998+void au_update_iigen(struct inode *inode, int half)
1308ab2a 17999+{
537831f9
AM
18000+ struct au_iinfo *iinfo;
18001+ struct au_iigen *iigen;
18002+ unsigned int sigen;
18003+
18004+ sigen = au_sigen(inode->i_sb);
18005+ iinfo = au_ii(inode);
18006+ iigen = &iinfo->ii_generation;
be52b249 18007+ spin_lock(&iigen->ig_spin);
537831f9
AM
18008+ iigen->ig_generation = sigen;
18009+ if (half)
18010+ au_ig_fset(iigen->ig_flags, HALF_REFRESHED);
18011+ else
18012+ au_ig_fclr(iigen->ig_flags, HALF_REFRESHED);
be52b249 18013+ spin_unlock(&iigen->ig_spin);
4a4d8108 18014+}
1facf9fc 18015+
4a4d8108
AM
18016+/* it may be called at remount time, too */
18017+void au_update_ibrange(struct inode *inode, int do_put_zero)
18018+{
18019+ struct au_iinfo *iinfo;
5afbbe0d 18020+ aufs_bindex_t bindex, bbot;
1facf9fc 18021+
5afbbe0d 18022+ AuDebugOn(au_is_bad_inode(inode));
4a4d8108 18023+ IiMustWriteLock(inode);
1facf9fc 18024+
5afbbe0d
AM
18025+ iinfo = au_ii(inode);
18026+ if (do_put_zero && iinfo->ii_btop >= 0) {
18027+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot;
4a4d8108
AM
18028+ bindex++) {
18029+ struct inode *h_i;
1facf9fc 18030+
5afbbe0d 18031+ h_i = au_hinode(iinfo, bindex)->hi_inode;
38d290e6
JR
18032+ if (h_i
18033+ && !h_i->i_nlink
18034+ && !(h_i->i_state & I_LINKABLE))
027c5e7a
AM
18035+ au_set_h_iptr(inode, bindex, NULL, 0);
18036+ }
4a4d8108
AM
18037+ }
18038+
5afbbe0d
AM
18039+ iinfo->ii_btop = -1;
18040+ iinfo->ii_bbot = -1;
18041+ bbot = au_sbbot(inode->i_sb);
18042+ for (bindex = 0; bindex <= bbot; bindex++)
18043+ if (au_hinode(iinfo, bindex)->hi_inode) {
18044+ iinfo->ii_btop = bindex;
4a4d8108 18045+ break;
027c5e7a 18046+ }
5afbbe0d
AM
18047+ if (iinfo->ii_btop >= 0)
18048+ for (bindex = bbot; bindex >= iinfo->ii_btop; bindex--)
18049+ if (au_hinode(iinfo, bindex)->hi_inode) {
18050+ iinfo->ii_bbot = bindex;
027c5e7a
AM
18051+ break;
18052+ }
5afbbe0d 18053+ AuDebugOn(iinfo->ii_btop > iinfo->ii_bbot);
1308ab2a 18054+}
1facf9fc 18055+
dece6358 18056+/* ---------------------------------------------------------------------- */
1facf9fc 18057+
4a4d8108 18058+void au_icntnr_init_once(void *_c)
dece6358 18059+{
4a4d8108
AM
18060+ struct au_icntnr *c = _c;
18061+ struct au_iinfo *iinfo = &c->iinfo;
1facf9fc 18062+
be52b249 18063+ spin_lock_init(&iinfo->ii_generation.ig_spin);
4a4d8108
AM
18064+ au_rw_init(&iinfo->ii_rwsem);
18065+ inode_init_once(&c->vfs_inode);
18066+}
1facf9fc 18067+
5afbbe0d
AM
18068+void au_hinode_init(struct au_hinode *hinode)
18069+{
18070+ hinode->hi_inode = NULL;
18071+ hinode->hi_id = -1;
18072+ au_hn_init(hinode);
18073+ hinode->hi_whdentry = NULL;
18074+}
18075+
4a4d8108
AM
18076+int au_iinfo_init(struct inode *inode)
18077+{
18078+ struct au_iinfo *iinfo;
18079+ struct super_block *sb;
5afbbe0d 18080+ struct au_hinode *hi;
4a4d8108 18081+ int nbr, i;
1facf9fc 18082+
4a4d8108
AM
18083+ sb = inode->i_sb;
18084+ iinfo = &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
5afbbe0d 18085+ nbr = au_sbbot(sb) + 1;
4a4d8108
AM
18086+ if (unlikely(nbr <= 0))
18087+ nbr = 1;
5afbbe0d
AM
18088+ hi = kmalloc_array(nbr, sizeof(*iinfo->ii_hinode), GFP_NOFS);
18089+ if (hi) {
acd2b654 18090+ au_lcnt_inc(&au_sbi(sb)->si_ninodes);
5afbbe0d
AM
18091+
18092+ iinfo->ii_hinode = hi;
18093+ for (i = 0; i < nbr; i++, hi++)
18094+ au_hinode_init(hi);
1facf9fc 18095+
537831f9 18096+ iinfo->ii_generation.ig_generation = au_sigen(sb);
5afbbe0d
AM
18097+ iinfo->ii_btop = -1;
18098+ iinfo->ii_bbot = -1;
4a4d8108
AM
18099+ iinfo->ii_vdir = NULL;
18100+ return 0;
1308ab2a 18101+ }
4a4d8108
AM
18102+ return -ENOMEM;
18103+}
1facf9fc 18104+
e2f27e51 18105+int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink)
4a4d8108 18106+{
5afbbe0d 18107+ int err, i;
4a4d8108 18108+ struct au_hinode *hip;
1facf9fc 18109+
4a4d8108
AM
18110+ AuRwMustWriteLock(&iinfo->ii_rwsem);
18111+
18112+ err = -ENOMEM;
e2f27e51
AM
18113+ hip = au_krealloc(iinfo->ii_hinode, sizeof(*hip) * nbr, GFP_NOFS,
18114+ may_shrink);
4a4d8108
AM
18115+ if (hip) {
18116+ iinfo->ii_hinode = hip;
5afbbe0d
AM
18117+ i = iinfo->ii_bbot + 1;
18118+ hip += i;
18119+ for (; i < nbr; i++, hip++)
18120+ au_hinode_init(hip);
4a4d8108 18121+ err = 0;
1308ab2a 18122+ }
4a4d8108 18123+
1308ab2a 18124+ return err;
1facf9fc 18125+}
18126+
4a4d8108 18127+void au_iinfo_fin(struct inode *inode)
1facf9fc 18128+{
4a4d8108
AM
18129+ struct au_iinfo *iinfo;
18130+ struct au_hinode *hi;
18131+ struct super_block *sb;
5afbbe0d 18132+ aufs_bindex_t bindex, bbot;
b752ccd1 18133+ const unsigned char unlinked = !inode->i_nlink;
1308ab2a 18134+
5afbbe0d 18135+ AuDebugOn(au_is_bad_inode(inode));
1308ab2a 18136+
b752ccd1 18137+ sb = inode->i_sb;
acd2b654 18138+ au_lcnt_dec(&au_sbi(sb)->si_ninodes);
b752ccd1
AM
18139+ if (si_pid_test(sb))
18140+ au_xino_delete_inode(inode, unlinked);
18141+ else {
18142+ /*
18143+ * it is safe to hide the dependency between sbinfo and
18144+ * sb->s_umount.
18145+ */
18146+ lockdep_off();
18147+ si_noflush_read_lock(sb);
18148+ au_xino_delete_inode(inode, unlinked);
18149+ si_read_unlock(sb);
18150+ lockdep_on();
18151+ }
18152+
5afbbe0d 18153+ iinfo = au_ii(inode);
4a4d8108 18154+ if (iinfo->ii_vdir)
1c60b727 18155+ au_vdir_free(iinfo->ii_vdir);
1308ab2a 18156+
5afbbe0d 18157+ bindex = iinfo->ii_btop;
b752ccd1 18158+ if (bindex >= 0) {
5afbbe0d
AM
18159+ hi = au_hinode(iinfo, bindex);
18160+ bbot = iinfo->ii_bbot;
18161+ while (bindex++ <= bbot) {
b752ccd1 18162+ if (hi->hi_inode)
4a4d8108 18163+ au_hiput(hi);
4a4d8108
AM
18164+ hi++;
18165+ }
18166+ }
9f237c51 18167+ au_kfree_rcu(iinfo->ii_hinode);
4a4d8108 18168+ AuRwDestroy(&iinfo->ii_rwsem);
dece6358 18169+}
7f207e10 18170diff -urN /usr/share/empty/fs/aufs/inode.c linux/fs/aufs/inode.c
eca34b5c 18171--- /usr/share/empty/fs/aufs/inode.c 1970-01-01 01:00:00.000000000 +0100
016522bc 18172+++ linux/fs/aufs/inode.c 2020-01-27 10:57:18.175538316 +0100
eca801bf 18173@@ -0,0 +1,529 @@
cd7a4cd9 18174+// SPDX-License-Identifier: GPL-2.0
4a4d8108 18175+/*
016522bc 18176+ * Copyright (C) 2005-2020 Junjiro R. Okajima
4a4d8108
AM
18177+ *
18178+ * This program, aufs is free software; you can redistribute it and/or modify
18179+ * it under the terms of the GNU General Public License as published by
18180+ * the Free Software Foundation; either version 2 of the License, or
18181+ * (at your option) any later version.
18182+ *
18183+ * This program is distributed in the hope that it will be useful,
18184+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18185+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18186+ * GNU General Public License for more details.
18187+ *
18188+ * You should have received a copy of the GNU General Public License
523b37e3 18189+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 18190+ */
1facf9fc 18191+
4a4d8108
AM
18192+/*
18193+ * inode functions
18194+ */
1facf9fc 18195+
eca801bf 18196+#include <linux/iversion.h>
4a4d8108 18197+#include "aufs.h"
1308ab2a 18198+
4a4d8108
AM
18199+struct inode *au_igrab(struct inode *inode)
18200+{
18201+ if (inode) {
18202+ AuDebugOn(!atomic_read(&inode->i_count));
027c5e7a 18203+ ihold(inode);
1facf9fc 18204+ }
4a4d8108
AM
18205+ return inode;
18206+}
1facf9fc 18207+
4a4d8108
AM
18208+static void au_refresh_hinode_attr(struct inode *inode, int do_version)
18209+{
18210+ au_cpup_attr_all(inode, /*force*/0);
537831f9 18211+ au_update_iigen(inode, /*half*/1);
4a4d8108 18212+ if (do_version)
be118d29 18213+ inode_inc_iversion(inode);
dece6358 18214+}
1facf9fc 18215+
027c5e7a 18216+static int au_ii_refresh(struct inode *inode, int *update)
dece6358 18217+{
e2f27e51 18218+ int err, e, nbr;
027c5e7a 18219+ umode_t type;
4a4d8108 18220+ aufs_bindex_t bindex, new_bindex;
1308ab2a 18221+ struct super_block *sb;
4a4d8108 18222+ struct au_iinfo *iinfo;
027c5e7a 18223+ struct au_hinode *p, *q, tmp;
1facf9fc 18224+
5afbbe0d 18225+ AuDebugOn(au_is_bad_inode(inode));
4a4d8108 18226+ IiMustWriteLock(inode);
1facf9fc 18227+
027c5e7a 18228+ *update = 0;
4a4d8108 18229+ sb = inode->i_sb;
e2f27e51 18230+ nbr = au_sbbot(sb) + 1;
027c5e7a 18231+ type = inode->i_mode & S_IFMT;
4a4d8108 18232+ iinfo = au_ii(inode);
e2f27e51 18233+ err = au_hinode_realloc(iinfo, nbr, /*may_shrink*/0);
4a4d8108 18234+ if (unlikely(err))
1308ab2a 18235+ goto out;
1facf9fc 18236+
5afbbe0d
AM
18237+ AuDebugOn(iinfo->ii_btop < 0);
18238+ p = au_hinode(iinfo, iinfo->ii_btop);
18239+ for (bindex = iinfo->ii_btop; bindex <= iinfo->ii_bbot;
4a4d8108
AM
18240+ bindex++, p++) {
18241+ if (!p->hi_inode)
18242+ continue;
1facf9fc 18243+
027c5e7a 18244+ AuDebugOn(type != (p->hi_inode->i_mode & S_IFMT));
4a4d8108
AM
18245+ new_bindex = au_br_index(sb, p->hi_id);
18246+ if (new_bindex == bindex)
18247+ continue;
1facf9fc 18248+
4a4d8108 18249+ if (new_bindex < 0) {
027c5e7a 18250+ *update = 1;
4a4d8108
AM
18251+ au_hiput(p);
18252+ p->hi_inode = NULL;
18253+ continue;
1308ab2a 18254+ }
4a4d8108 18255+
5afbbe0d
AM
18256+ if (new_bindex < iinfo->ii_btop)
18257+ iinfo->ii_btop = new_bindex;
18258+ if (iinfo->ii_bbot < new_bindex)
18259+ iinfo->ii_bbot = new_bindex;
4a4d8108 18260+ /* swap two lower inode, and loop again */
5afbbe0d 18261+ q = au_hinode(iinfo, new_bindex);
4a4d8108
AM
18262+ tmp = *q;
18263+ *q = *p;
18264+ *p = tmp;
18265+ if (tmp.hi_inode) {
18266+ bindex--;
18267+ p--;
1308ab2a 18268+ }
18269+ }
4a4d8108 18270+ au_update_ibrange(inode, /*do_put_zero*/0);
e2f27e51 18271+ au_hinode_realloc(iinfo, nbr, /*may_shrink*/1); /* harmless if err */
4a4d8108
AM
18272+ e = au_dy_irefresh(inode);
18273+ if (unlikely(e && !err))
18274+ err = e;
1facf9fc 18275+
4f0767ce 18276+out:
027c5e7a
AM
18277+ AuTraceErr(err);
18278+ return err;
18279+}
18280+
b95c5147
AM
18281+void au_refresh_iop(struct inode *inode, int force_getattr)
18282+{
18283+ int type;
18284+ struct au_sbinfo *sbi = au_sbi(inode->i_sb);
18285+ const struct inode_operations *iop
18286+ = force_getattr ? aufs_iop : sbi->si_iop_array;
18287+
18288+ if (inode->i_op == iop)
18289+ return;
18290+
18291+ switch (inode->i_mode & S_IFMT) {
18292+ case S_IFDIR:
18293+ type = AuIop_DIR;
18294+ break;
18295+ case S_IFLNK:
18296+ type = AuIop_SYMLINK;
18297+ break;
18298+ default:
18299+ type = AuIop_OTHER;
18300+ break;
18301+ }
18302+
18303+ inode->i_op = iop + type;
18304+ /* unnecessary smp_wmb() */
18305+}
18306+
027c5e7a
AM
18307+int au_refresh_hinode_self(struct inode *inode)
18308+{
18309+ int err, update;
18310+
18311+ err = au_ii_refresh(inode, &update);
18312+ if (!err)
18313+ au_refresh_hinode_attr(inode, update && S_ISDIR(inode->i_mode));
18314+
18315+ AuTraceErr(err);
4a4d8108
AM
18316+ return err;
18317+}
1facf9fc 18318+
4a4d8108
AM
18319+int au_refresh_hinode(struct inode *inode, struct dentry *dentry)
18320+{
027c5e7a 18321+ int err, e, update;
4a4d8108 18322+ unsigned int flags;
027c5e7a 18323+ umode_t mode;
5afbbe0d 18324+ aufs_bindex_t bindex, bbot;
027c5e7a 18325+ unsigned char isdir;
4a4d8108
AM
18326+ struct au_hinode *p;
18327+ struct au_iinfo *iinfo;
1facf9fc 18328+
027c5e7a 18329+ err = au_ii_refresh(inode, &update);
4a4d8108
AM
18330+ if (unlikely(err))
18331+ goto out;
18332+
18333+ update = 0;
18334+ iinfo = au_ii(inode);
5afbbe0d 18335+ p = au_hinode(iinfo, iinfo->ii_btop);
027c5e7a
AM
18336+ mode = (inode->i_mode & S_IFMT);
18337+ isdir = S_ISDIR(mode);
4a4d8108 18338+ flags = au_hi_flags(inode, isdir);
5afbbe0d
AM
18339+ bbot = au_dbbot(dentry);
18340+ for (bindex = au_dbtop(dentry); bindex <= bbot; bindex++) {
5527c038 18341+ struct inode *h_i, *h_inode;
4a4d8108
AM
18342+ struct dentry *h_d;
18343+
18344+ h_d = au_h_dptr(dentry, bindex);
5527c038 18345+ if (!h_d || d_is_negative(h_d))
4a4d8108
AM
18346+ continue;
18347+
5527c038
JR
18348+ h_inode = d_inode(h_d);
18349+ AuDebugOn(mode != (h_inode->i_mode & S_IFMT));
5afbbe0d 18350+ if (iinfo->ii_btop <= bindex && bindex <= iinfo->ii_bbot) {
4a4d8108
AM
18351+ h_i = au_h_iptr(inode, bindex);
18352+ if (h_i) {
5527c038 18353+ if (h_i == h_inode)
4a4d8108
AM
18354+ continue;
18355+ err = -EIO;
18356+ break;
18357+ }
18358+ }
5afbbe0d
AM
18359+ if (bindex < iinfo->ii_btop)
18360+ iinfo->ii_btop = bindex;
18361+ if (iinfo->ii_bbot < bindex)
18362+ iinfo->ii_bbot = bindex;
5527c038 18363+ au_set_h_iptr(inode, bindex, au_igrab(h_inode), flags);
4a4d8108 18364+ update = 1;
1308ab2a 18365+ }
4a4d8108
AM
18366+ au_update_ibrange(inode, /*do_put_zero*/0);
18367+ e = au_dy_irefresh(inode);
18368+ if (unlikely(e && !err))
18369+ err = e;
027c5e7a
AM
18370+ if (!err)
18371+ au_refresh_hinode_attr(inode, update && isdir);
4a4d8108 18372+
4f0767ce 18373+out:
4a4d8108 18374+ AuTraceErr(err);
1308ab2a 18375+ return err;
dece6358
AM
18376+}
18377+
4a4d8108 18378+static int set_inode(struct inode *inode, struct dentry *dentry)
dece6358 18379+{
4a4d8108
AM
18380+ int err;
18381+ unsigned int flags;
18382+ umode_t mode;
5afbbe0d 18383+ aufs_bindex_t bindex, btop, btail;
4a4d8108
AM
18384+ unsigned char isdir;
18385+ struct dentry *h_dentry;
18386+ struct inode *h_inode;
18387+ struct au_iinfo *iinfo;
43982f53 18388+ const struct inode_operations *iop;
dece6358 18389+
4a4d8108 18390+ IiMustWriteLock(inode);
dece6358 18391+
4a4d8108
AM
18392+ err = 0;
18393+ isdir = 0;
b95c5147 18394+ iop = au_sbi(inode->i_sb)->si_iop_array;
5afbbe0d
AM
18395+ btop = au_dbtop(dentry);
18396+ h_dentry = au_h_dptr(dentry, btop);
5527c038 18397+ h_inode = d_inode(h_dentry);
4a4d8108
AM
18398+ mode = h_inode->i_mode;
18399+ switch (mode & S_IFMT) {
18400+ case S_IFREG:
18401+ btail = au_dbtail(dentry);
b95c5147 18402+ inode->i_op = iop + AuIop_OTHER;
4a4d8108 18403+ inode->i_fop = &aufs_file_fop;
5afbbe0d 18404+ err = au_dy_iaop(inode, btop, h_inode);
4a4d8108
AM
18405+ if (unlikely(err))
18406+ goto out;
18407+ break;
18408+ case S_IFDIR:
18409+ isdir = 1;
18410+ btail = au_dbtaildir(dentry);
b95c5147 18411+ inode->i_op = iop + AuIop_DIR;
4a4d8108
AM
18412+ inode->i_fop = &aufs_dir_fop;
18413+ break;
18414+ case S_IFLNK:
18415+ btail = au_dbtail(dentry);
b95c5147 18416+ inode->i_op = iop + AuIop_SYMLINK;
4a4d8108
AM
18417+ break;
18418+ case S_IFBLK:
18419+ case S_IFCHR:
18420+ case S_IFIFO:
18421+ case S_IFSOCK:
18422+ btail = au_dbtail(dentry);
b95c5147 18423+ inode->i_op = iop + AuIop_OTHER;
38d290e6 18424+ init_special_inode(inode, mode, h_inode->i_rdev);
4a4d8108
AM
18425+ break;
18426+ default:
18427+ AuIOErr("Unknown file type 0%o\n", mode);
18428+ err = -EIO;
1308ab2a 18429+ goto out;
4a4d8108 18430+ }
dece6358 18431+
4a4d8108
AM
18432+ /* do not set hnotify for whiteouted dirs (SHWH mode) */
18433+ flags = au_hi_flags(inode, isdir);
18434+ if (au_opt_test(au_mntflags(dentry->d_sb), SHWH)
18435+ && au_ftest_hi(flags, HNOTIFY)
18436+ && dentry->d_name.len > AUFS_WH_PFX_LEN
18437+ && !memcmp(dentry->d_name.name, AUFS_WH_PFX, AUFS_WH_PFX_LEN))
18438+ au_fclr_hi(flags, HNOTIFY);
18439+ iinfo = au_ii(inode);
5afbbe0d
AM
18440+ iinfo->ii_btop = btop;
18441+ iinfo->ii_bbot = btail;
18442+ for (bindex = btop; bindex <= btail; bindex++) {
4a4d8108
AM
18443+ h_dentry = au_h_dptr(dentry, bindex);
18444+ if (h_dentry)
18445+ au_set_h_iptr(inode, bindex,
5527c038 18446+ au_igrab(d_inode(h_dentry)), flags);
4a4d8108
AM
18447+ }
18448+ au_cpup_attr_all(inode, /*force*/1);
c1595e42
JR
18449+ /*
18450+ * to force calling aufs_get_acl() every time,
18451+ * do not call cache_no_acl() for aufs inode.
18452+ */
dece6358 18453+
4f0767ce 18454+out:
4a4d8108
AM
18455+ return err;
18456+}
dece6358 18457+
027c5e7a
AM
18458+/*
18459+ * successful returns with iinfo write_locked
18460+ * minus: errno
18461+ * zero: success, matched
18462+ * plus: no error, but unmatched
18463+ */
18464+static int reval_inode(struct inode *inode, struct dentry *dentry)
4a4d8108
AM
18465+{
18466+ int err;
cfc41e69 18467+ unsigned int gen, igflags;
5afbbe0d 18468+ aufs_bindex_t bindex, bbot;
4a4d8108 18469+ struct inode *h_inode, *h_dinode;
5527c038 18470+ struct dentry *h_dentry;
dece6358 18471+
4a4d8108
AM
18472+ /*
18473+ * before this function, if aufs got any iinfo lock, it must be only
18474+ * one, the parent dir.
18475+ * it can happen by UDBA and the obsoleted inode number.
18476+ */
18477+ err = -EIO;
18478+ if (unlikely(inode->i_ino == parent_ino(dentry)))
18479+ goto out;
18480+
027c5e7a 18481+ err = 1;
4a4d8108 18482+ ii_write_lock_new_child(inode);
5afbbe0d 18483+ h_dentry = au_h_dptr(dentry, au_dbtop(dentry));
5527c038 18484+ h_dinode = d_inode(h_dentry);
5afbbe0d
AM
18485+ bbot = au_ibbot(inode);
18486+ for (bindex = au_ibtop(inode); bindex <= bbot; bindex++) {
4a4d8108 18487+ h_inode = au_h_iptr(inode, bindex);
537831f9
AM
18488+ if (!h_inode || h_inode != h_dinode)
18489+ continue;
18490+
18491+ err = 0;
cfc41e69 18492+ gen = au_iigen(inode, &igflags);
537831f9 18493+ if (gen == au_digen(dentry)
cfc41e69 18494+ && !au_ig_ftest(igflags, HALF_REFRESHED))
4a4d8108 18495+ break;
537831f9
AM
18496+
18497+ /* fully refresh inode using dentry */
18498+ err = au_refresh_hinode(inode, dentry);
18499+ if (!err)
18500+ au_update_iigen(inode, /*half*/0);
18501+ break;
1facf9fc 18502+ }
dece6358 18503+
4a4d8108
AM
18504+ if (unlikely(err))
18505+ ii_write_unlock(inode);
4f0767ce 18506+out:
1facf9fc 18507+ return err;
18508+}
1facf9fc 18509+
4a4d8108
AM
18510+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
18511+ unsigned int d_type, ino_t *ino)
1facf9fc 18512+{
521ced18
JR
18513+ int err, idx;
18514+ const int isnondir = d_type != DT_DIR;
1facf9fc 18515+
b752ccd1 18516+ /* prevent hardlinked inode number from race condition */
521ced18
JR
18517+ if (isnondir) {
18518+ err = au_xinondir_enter(sb, bindex, h_ino, &idx);
18519+ if (unlikely(err))
18520+ goto out;
4a4d8108 18521+ }
521ced18 18522+
4a4d8108
AM
18523+ err = au_xino_read(sb, bindex, h_ino, ino);
18524+ if (unlikely(err))
521ced18 18525+ goto out_xinondir;
1308ab2a 18526+
4a4d8108
AM
18527+ if (!*ino) {
18528+ err = -EIO;
18529+ *ino = au_xino_new_ino(sb);
18530+ if (unlikely(!*ino))
521ced18 18531+ goto out_xinondir;
4a4d8108
AM
18532+ err = au_xino_write(sb, bindex, h_ino, *ino);
18533+ if (unlikely(err))
521ced18 18534+ goto out_xinondir;
1308ab2a 18535+ }
1facf9fc 18536+
521ced18
JR
18537+out_xinondir:
18538+ if (isnondir && idx >= 0)
18539+ au_xinondir_leave(sb, bindex, h_ino, idx);
4f0767ce 18540+out:
1facf9fc 18541+ return err;
18542+}
18543+
4a4d8108
AM
18544+/* successful returns with iinfo write_locked */
18545+/* todo: return with unlocked? */
18546+struct inode *au_new_inode(struct dentry *dentry, int must_new)
1facf9fc 18547+{
5527c038 18548+ struct inode *inode, *h_inode;
4a4d8108
AM
18549+ struct dentry *h_dentry;
18550+ struct super_block *sb;
18551+ ino_t h_ino, ino;
521ced18 18552+ int err, idx, hlinked;
5afbbe0d 18553+ aufs_bindex_t btop;
1facf9fc 18554+
4a4d8108 18555+ sb = dentry->d_sb;
5afbbe0d
AM
18556+ btop = au_dbtop(dentry);
18557+ h_dentry = au_h_dptr(dentry, btop);
5527c038
JR
18558+ h_inode = d_inode(h_dentry);
18559+ h_ino = h_inode->i_ino;
521ced18 18560+ hlinked = !d_is_dir(h_dentry) && h_inode->i_nlink > 1;
b752ccd1 18561+
521ced18 18562+new_ino:
b752ccd1
AM
18563+ /*
18564+ * stop 'race'-ing between hardlinks under different
18565+ * parents.
18566+ */
521ced18
JR
18567+ if (hlinked) {
18568+ err = au_xinondir_enter(sb, btop, h_ino, &idx);
18569+ inode = ERR_PTR(err);
18570+ if (unlikely(err))
18571+ goto out;
18572+ }
b752ccd1 18573+
5afbbe0d 18574+ err = au_xino_read(sb, btop, h_ino, &ino);
4a4d8108
AM
18575+ inode = ERR_PTR(err);
18576+ if (unlikely(err))
521ced18 18577+ goto out_xinondir;
b752ccd1 18578+
4a4d8108
AM
18579+ if (!ino) {
18580+ ino = au_xino_new_ino(sb);
18581+ if (unlikely(!ino)) {
18582+ inode = ERR_PTR(-EIO);
521ced18 18583+ goto out_xinondir;
dece6358
AM
18584+ }
18585+ }
1facf9fc 18586+
4a4d8108
AM
18587+ AuDbg("i%lu\n", (unsigned long)ino);
18588+ inode = au_iget_locked(sb, ino);
18589+ err = PTR_ERR(inode);
18590+ if (IS_ERR(inode))
521ced18 18591+ goto out_xinondir;
1facf9fc 18592+
4a4d8108
AM
18593+ AuDbg("%lx, new %d\n", inode->i_state, !!(inode->i_state & I_NEW));
18594+ if (inode->i_state & I_NEW) {
18595+ ii_write_lock_new_child(inode);
18596+ err = set_inode(inode, dentry);
18597+ if (!err) {
18598+ unlock_new_inode(inode);
521ced18 18599+ goto out_xinondir; /* success */
4a4d8108 18600+ }
1308ab2a 18601+
027c5e7a
AM
18602+ /*
18603+ * iget_failed() calls iput(), but we need to call
18604+ * ii_write_unlock() after iget_failed(). so dirty hack for
18605+ * i_count.
18606+ */
18607+ atomic_inc(&inode->i_count);
4a4d8108 18608+ iget_failed(inode);
027c5e7a 18609+ ii_write_unlock(inode);
5afbbe0d 18610+ au_xino_write(sb, btop, h_ino, /*ino*/0);
027c5e7a
AM
18611+ /* ignore this error */
18612+ goto out_iput;
18613+ } else if (!must_new && !IS_DEADDIR(inode) && inode->i_nlink) {
b752ccd1
AM
18614+ /*
18615+ * horrible race condition between lookup, readdir and copyup
18616+ * (or something).
18617+ */
521ced18
JR
18618+ if (hlinked && idx >= 0)
18619+ au_xinondir_leave(sb, btop, h_ino, idx);
027c5e7a
AM
18620+ err = reval_inode(inode, dentry);
18621+ if (unlikely(err < 0)) {
521ced18 18622+ hlinked = 0;
027c5e7a
AM
18623+ goto out_iput;
18624+ }
521ced18 18625+ if (!err)
4a4d8108 18626+ goto out; /* success */
521ced18
JR
18627+ else if (hlinked && idx >= 0) {
18628+ err = au_xinondir_enter(sb, btop, h_ino, &idx);
18629+ if (unlikely(err)) {
18630+ iput(inode);
18631+ inode = ERR_PTR(err);
18632+ goto out;
18633+ }
18634+ }
4a4d8108
AM
18635+ }
18636+
5527c038 18637+ if (unlikely(au_test_fs_unique_ino(h_inode)))
4a4d8108 18638+ AuWarn1("Warning: Un-notified UDBA or repeatedly renamed dir,"
523b37e3 18639+ " b%d, %s, %pd, hi%lu, i%lu.\n",
5afbbe0d 18640+ btop, au_sbtype(h_dentry->d_sb), dentry,
4a4d8108
AM
18641+ (unsigned long)h_ino, (unsigned long)ino);
18642+ ino = 0;
5afbbe0d 18643+ err = au_xino_write(sb, btop, h_ino, /*ino*/0);
4a4d8108
AM
18644+ if (!err) {
18645+ iput(inode);
521ced18
JR
18646+ if (hlinked && idx >= 0)
18647+ au_xinondir_leave(sb, btop, h_ino, idx);
4a4d8108
AM
18648+ goto new_ino;
18649+ }
1308ab2a 18650+
4f0767ce 18651+out_iput:
4a4d8108 18652+ iput(inode);
4a4d8108 18653+ inode = ERR_PTR(err);
521ced18
JR
18654+out_xinondir:
18655+ if (hlinked && idx >= 0)
18656+ au_xinondir_leave(sb, btop, h_ino, idx);
4f0767ce 18657+out:
4a4d8108 18658+ return inode;
1facf9fc 18659+}
18660+
4a4d8108 18661+/* ---------------------------------------------------------------------- */
1facf9fc 18662+
4a4d8108
AM
18663+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
18664+ struct inode *inode)
18665+{
18666+ int err;
076b876e 18667+ struct inode *hi;
1facf9fc 18668+
4a4d8108 18669+ err = au_br_rdonly(au_sbr(sb, bindex));
1facf9fc 18670+
4a4d8108
AM
18671+ /* pseudo-link after flushed may happen out of bounds */
18672+ if (!err
18673+ && inode
5afbbe0d
AM
18674+ && au_ibtop(inode) <= bindex
18675+ && bindex <= au_ibbot(inode)) {
4a4d8108
AM
18676+ /*
18677+ * permission check is unnecessary since vfsub routine
18678+ * will be called later
18679+ */
076b876e 18680+ hi = au_h_iptr(inode, bindex);
4a4d8108
AM
18681+ if (hi)
18682+ err = IS_IMMUTABLE(hi) ? -EROFS : 0;
1facf9fc 18683+ }
18684+
4a4d8108
AM
18685+ return err;
18686+}
dece6358 18687+
4a4d8108
AM
18688+int au_test_h_perm(struct inode *h_inode, int mask)
18689+{
2dfbb274 18690+ if (uid_eq(current_fsuid(), GLOBAL_ROOT_UID))
4a4d8108
AM
18691+ return 0;
18692+ return inode_permission(h_inode, mask);
18693+}
1facf9fc 18694+
4a4d8108
AM
18695+int au_test_h_perm_sio(struct inode *h_inode, int mask)
18696+{
18697+ if (au_test_nfs(h_inode->i_sb)
18698+ && (mask & MAY_WRITE)
18699+ && S_ISDIR(h_inode->i_mode))
18700+ mask |= MAY_READ; /* force permission check */
18701+ return au_test_h_perm(h_inode, mask);
1facf9fc 18702+}
7f207e10 18703diff -urN /usr/share/empty/fs/aufs/inode.h linux/fs/aufs/inode.h
eca34b5c 18704--- /usr/share/empty/fs/aufs/inode.h 1970-01-01 01:00:00.000000000 +0100
016522bc 18705+++ linux/fs/aufs/inode.h 2020-01-27 10:57:18.175538316 +0100
9f237c51 18706@@ -0,0 +1,698 @@
062440b3 18707+/* SPDX-License-Identifier: GPL-2.0 */
4a4d8108 18708+/*
016522bc 18709+ * Copyright (C) 2005-2020 Junjiro R. Okajima
4a4d8108
AM
18710+ *
18711+ * This program, aufs is free software; you can redistribute it and/or modify
18712+ * it under the terms of the GNU General Public License as published by
18713+ * the Free Software Foundation; either version 2 of the License, or
18714+ * (at your option) any later version.
18715+ *
18716+ * This program is distributed in the hope that it will be useful,
18717+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
18718+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18719+ * GNU General Public License for more details.
18720+ *
18721+ * You should have received a copy of the GNU General Public License
523b37e3 18722+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 18723+ */
1facf9fc 18724+
1308ab2a 18725+/*
4a4d8108 18726+ * inode operations
1308ab2a 18727+ */
dece6358 18728+
4a4d8108
AM
18729+#ifndef __AUFS_INODE_H__
18730+#define __AUFS_INODE_H__
dece6358 18731+
4a4d8108 18732+#ifdef __KERNEL__
1308ab2a 18733+
4a4d8108 18734+#include <linux/fsnotify.h>
4a4d8108 18735+#include "rwsem.h"
1308ab2a 18736+
4a4d8108 18737+struct vfsmount;
1facf9fc 18738+
4a4d8108
AM
18739+struct au_hnotify {
18740+#ifdef CONFIG_AUFS_HNOTIFY
18741+#ifdef CONFIG_AUFS_HFSNOTIFY
7f207e10 18742+ /* never use fsnotify_add_vfsmount_mark() */
0c5527e5 18743+ struct fsnotify_mark hn_mark;
4a4d8108 18744+#endif
1c60b727 18745+ struct inode *hn_aufs_inode; /* no get/put */
9f237c51 18746+ struct rcu_head rcu;
4a4d8108
AM
18747+#endif
18748+} ____cacheline_aligned_in_smp;
1facf9fc 18749+
4a4d8108
AM
18750+struct au_hinode {
18751+ struct inode *hi_inode;
18752+ aufs_bindex_t hi_id;
18753+#ifdef CONFIG_AUFS_HNOTIFY
18754+ struct au_hnotify *hi_notify;
18755+#endif
dece6358 18756+
4a4d8108
AM
18757+ /* reference to the copied-up whiteout with get/put */
18758+ struct dentry *hi_whdentry;
18759+};
dece6358 18760+
537831f9
AM
18761+/* ig_flags */
18762+#define AuIG_HALF_REFRESHED 1
18763+#define au_ig_ftest(flags, name) ((flags) & AuIG_##name)
18764+#define au_ig_fset(flags, name) \
18765+ do { (flags) |= AuIG_##name; } while (0)
18766+#define au_ig_fclr(flags, name) \
18767+ do { (flags) &= ~AuIG_##name; } while (0)
18768+
18769+struct au_iigen {
be52b249 18770+ spinlock_t ig_spin;
537831f9
AM
18771+ __u32 ig_generation, ig_flags;
18772+};
18773+
4a4d8108
AM
18774+struct au_vdir;
18775+struct au_iinfo {
7a9e40b8 18776+ struct au_iigen ii_generation;
4a4d8108 18777+ struct super_block *ii_hsb1; /* no get/put */
1facf9fc 18778+
4a4d8108 18779+ struct au_rwsem ii_rwsem;
5afbbe0d 18780+ aufs_bindex_t ii_btop, ii_bbot;
4a4d8108
AM
18781+ __u32 ii_higen;
18782+ struct au_hinode *ii_hinode;
18783+ struct au_vdir *ii_vdir;
18784+};
1facf9fc 18785+
4a4d8108 18786+struct au_icntnr {
9f237c51
AM
18787+ struct au_iinfo iinfo;
18788+ struct inode vfs_inode;
18789+ struct hlist_bl_node plink;
18790+ struct rcu_head rcu;
4a4d8108 18791+} ____cacheline_aligned_in_smp;
1308ab2a 18792+
4a4d8108
AM
18793+/* au_pin flags */
18794+#define AuPin_DI_LOCKED 1
18795+#define AuPin_MNT_WRITE (1 << 1)
18796+#define au_ftest_pin(flags, name) ((flags) & AuPin_##name)
7f207e10
AM
18797+#define au_fset_pin(flags, name) \
18798+ do { (flags) |= AuPin_##name; } while (0)
18799+#define au_fclr_pin(flags, name) \
18800+ do { (flags) &= ~AuPin_##name; } while (0)
4a4d8108
AM
18801+
18802+struct au_pin {
18803+ /* input */
18804+ struct dentry *dentry;
18805+ unsigned int udba;
18806+ unsigned char lsc_di, lsc_hi, flags;
18807+ aufs_bindex_t bindex;
18808+
18809+ /* output */
18810+ struct dentry *parent;
18811+ struct au_hinode *hdir;
18812+ struct vfsmount *h_mnt;
86dc4139
AM
18813+
18814+ /* temporary unlock/relock for copyup */
18815+ struct dentry *h_dentry, *h_parent;
18816+ struct au_branch *br;
18817+ struct task_struct *task;
4a4d8108 18818+};
1facf9fc 18819+
86dc4139 18820+void au_pin_hdir_unlock(struct au_pin *p);
c1595e42 18821+int au_pin_hdir_lock(struct au_pin *p);
86dc4139 18822+int au_pin_hdir_relock(struct au_pin *p);
86dc4139
AM
18823+void au_pin_hdir_acquire_nest(struct au_pin *p);
18824+void au_pin_hdir_release(struct au_pin *p);
18825+
1308ab2a 18826+/* ---------------------------------------------------------------------- */
18827+
4a4d8108 18828+static inline struct au_iinfo *au_ii(struct inode *inode)
1facf9fc 18829+{
5afbbe0d
AM
18830+ BUG_ON(is_bad_inode(inode));
18831+ return &(container_of(inode, struct au_icntnr, vfs_inode)->iinfo);
4a4d8108 18832+}
1facf9fc 18833+
4a4d8108 18834+/* ---------------------------------------------------------------------- */
1facf9fc 18835+
4a4d8108
AM
18836+/* inode.c */
18837+struct inode *au_igrab(struct inode *inode);
b95c5147 18838+void au_refresh_iop(struct inode *inode, int force_getattr);
027c5e7a 18839+int au_refresh_hinode_self(struct inode *inode);
4a4d8108
AM
18840+int au_refresh_hinode(struct inode *inode, struct dentry *dentry);
18841+int au_ino(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
18842+ unsigned int d_type, ino_t *ino);
18843+struct inode *au_new_inode(struct dentry *dentry, int must_new);
18844+int au_test_ro(struct super_block *sb, aufs_bindex_t bindex,
18845+ struct inode *inode);
18846+int au_test_h_perm(struct inode *h_inode, int mask);
18847+int au_test_h_perm_sio(struct inode *h_inode, int mask);
1facf9fc 18848+
4a4d8108
AM
18849+static inline int au_wh_ino(struct super_block *sb, aufs_bindex_t bindex,
18850+ ino_t h_ino, unsigned int d_type, ino_t *ino)
18851+{
18852+#ifdef CONFIG_AUFS_SHWH
18853+ return au_ino(sb, bindex, h_ino, d_type, ino);
18854+#else
18855+ return 0;
18856+#endif
18857+}
1facf9fc 18858+
4a4d8108 18859+/* i_op.c */
b95c5147
AM
18860+enum {
18861+ AuIop_SYMLINK,
18862+ AuIop_DIR,
18863+ AuIop_OTHER,
18864+ AuIop_Last
18865+};
43982f53 18866+extern struct inode_operations aufs_iop[AuIop_Last], /* not const */
b95c5147 18867+ aufs_iop_nogetattr[AuIop_Last];
1308ab2a 18868+
4a4d8108
AM
18869+/* au_wr_dir flags */
18870+#define AuWrDir_ADD_ENTRY 1
7e9cd9fe
AM
18871+#define AuWrDir_ISDIR (1 << 1)
18872+#define AuWrDir_TMPFILE (1 << 2)
4a4d8108 18873+#define au_ftest_wrdir(flags, name) ((flags) & AuWrDir_##name)
7f207e10
AM
18874+#define au_fset_wrdir(flags, name) \
18875+ do { (flags) |= AuWrDir_##name; } while (0)
18876+#define au_fclr_wrdir(flags, name) \
18877+ do { (flags) &= ~AuWrDir_##name; } while (0)
1facf9fc 18878+
4a4d8108
AM
18879+struct au_wr_dir_args {
18880+ aufs_bindex_t force_btgt;
18881+ unsigned char flags;
18882+};
18883+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
18884+ struct au_wr_dir_args *args);
dece6358 18885+
4a4d8108
AM
18886+struct dentry *au_pinned_h_parent(struct au_pin *pin);
18887+void au_pin_init(struct au_pin *pin, struct dentry *dentry,
18888+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
18889+ unsigned int udba, unsigned char flags);
18890+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
18891+ unsigned int udba, unsigned char flags) __must_check;
18892+int au_do_pin(struct au_pin *pin) __must_check;
18893+void au_unpin(struct au_pin *pin);
c1595e42
JR
18894+int au_reval_for_attr(struct dentry *dentry, unsigned int sigen);
18895+
18896+#define AuIcpup_DID_CPUP 1
18897+#define au_ftest_icpup(flags, name) ((flags) & AuIcpup_##name)
18898+#define au_fset_icpup(flags, name) \
18899+ do { (flags) |= AuIcpup_##name; } while (0)
18900+#define au_fclr_icpup(flags, name) \
18901+ do { (flags) &= ~AuIcpup_##name; } while (0)
18902+
18903+struct au_icpup_args {
18904+ unsigned char flags;
18905+ unsigned char pin_flags;
18906+ aufs_bindex_t btgt;
18907+ unsigned int udba;
18908+ struct au_pin pin;
18909+ struct path h_path;
18910+ struct inode *h_inode;
18911+};
18912+
18913+int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
18914+ struct au_icpup_args *a);
18915+
a2654f78
AM
18916+int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path,
18917+ int locked);
1facf9fc 18918+
4a4d8108
AM
18919+/* i_op_add.c */
18920+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
18921+ struct dentry *h_parent, int isdir);
7eafdf33
AM
18922+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
18923+ dev_t dev);
4a4d8108 18924+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname);
7eafdf33 18925+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
b4510431 18926+ bool want_excl);
b912730e
AM
18927+struct vfsub_aopen_args;
18928+int au_aopen_or_create(struct inode *dir, struct dentry *dentry,
18929+ struct vfsub_aopen_args *args);
38d290e6 18930+int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode);
4a4d8108
AM
18931+int aufs_link(struct dentry *src_dentry, struct inode *dir,
18932+ struct dentry *dentry);
7eafdf33 18933+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
1facf9fc 18934+
4a4d8108
AM
18935+/* i_op_del.c */
18936+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup);
18937+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
18938+ struct dentry *h_parent, int isdir);
18939+int aufs_unlink(struct inode *dir, struct dentry *dentry);
18940+int aufs_rmdir(struct inode *dir, struct dentry *dentry);
1308ab2a 18941+
4a4d8108
AM
18942+/* i_op_ren.c */
18943+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt);
18944+int aufs_rename(struct inode *src_dir, struct dentry *src_dentry,
f2c43d5f
AM
18945+ struct inode *dir, struct dentry *dentry,
18946+ unsigned int flags);
1facf9fc 18947+
4a4d8108
AM
18948+/* iinfo.c */
18949+struct inode *au_h_iptr(struct inode *inode, aufs_bindex_t bindex);
18950+void au_hiput(struct au_hinode *hinode);
18951+void au_set_hi_wh(struct inode *inode, aufs_bindex_t bindex,
18952+ struct dentry *h_wh);
18953+unsigned int au_hi_flags(struct inode *inode, int isdir);
1308ab2a 18954+
4a4d8108
AM
18955+/* hinode flags */
18956+#define AuHi_XINO 1
18957+#define AuHi_HNOTIFY (1 << 1)
18958+#define au_ftest_hi(flags, name) ((flags) & AuHi_##name)
7f207e10
AM
18959+#define au_fset_hi(flags, name) \
18960+ do { (flags) |= AuHi_##name; } while (0)
18961+#define au_fclr_hi(flags, name) \
18962+ do { (flags) &= ~AuHi_##name; } while (0)
1facf9fc 18963+
4a4d8108
AM
18964+#ifndef CONFIG_AUFS_HNOTIFY
18965+#undef AuHi_HNOTIFY
18966+#define AuHi_HNOTIFY 0
18967+#endif
1facf9fc 18968+
4a4d8108
AM
18969+void au_set_h_iptr(struct inode *inode, aufs_bindex_t bindex,
18970+ struct inode *h_inode, unsigned int flags);
1facf9fc 18971+
537831f9 18972+void au_update_iigen(struct inode *inode, int half);
4a4d8108 18973+void au_update_ibrange(struct inode *inode, int do_put_zero);
1facf9fc 18974+
4a4d8108 18975+void au_icntnr_init_once(void *_c);
5afbbe0d 18976+void au_hinode_init(struct au_hinode *hinode);
4a4d8108
AM
18977+int au_iinfo_init(struct inode *inode);
18978+void au_iinfo_fin(struct inode *inode);
e2f27e51 18979+int au_hinode_realloc(struct au_iinfo *iinfo, int nbr, int may_shrink);
1308ab2a 18980+
e49829fe 18981+#ifdef CONFIG_PROC_FS
4a4d8108 18982+/* plink.c */
e49829fe 18983+int au_plink_maint(struct super_block *sb, int flags);
7e9cd9fe 18984+struct au_sbinfo;
e49829fe
JR
18985+void au_plink_maint_leave(struct au_sbinfo *sbinfo);
18986+int au_plink_maint_enter(struct super_block *sb);
4a4d8108
AM
18987+#ifdef CONFIG_AUFS_DEBUG
18988+void au_plink_list(struct super_block *sb);
18989+#else
18990+AuStubVoid(au_plink_list, struct super_block *sb)
18991+#endif
18992+int au_plink_test(struct inode *inode);
18993+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex);
18994+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
18995+ struct dentry *h_dentry);
e49829fe
JR
18996+void au_plink_put(struct super_block *sb, int verbose);
18997+void au_plink_clean(struct super_block *sb, int verbose);
4a4d8108 18998+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id);
e49829fe
JR
18999+#else
19000+AuStubInt0(au_plink_maint, struct super_block *sb, int flags);
19001+AuStubVoid(au_plink_maint_leave, struct au_sbinfo *sbinfo);
19002+AuStubInt0(au_plink_maint_enter, struct super_block *sb);
19003+AuStubVoid(au_plink_list, struct super_block *sb);
19004+AuStubInt0(au_plink_test, struct inode *inode);
19005+AuStub(struct dentry *, au_plink_lkup, return NULL,
19006+ struct inode *inode, aufs_bindex_t bindex);
19007+AuStubVoid(au_plink_append, struct inode *inode, aufs_bindex_t bindex,
19008+ struct dentry *h_dentry);
19009+AuStubVoid(au_plink_put, struct super_block *sb, int verbose);
19010+AuStubVoid(au_plink_clean, struct super_block *sb, int verbose);
19011+AuStubVoid(au_plink_half_refresh, struct super_block *sb, aufs_bindex_t br_id);
19012+#endif /* CONFIG_PROC_FS */
1facf9fc 19013+
c1595e42
JR
19014+#ifdef CONFIG_AUFS_XATTR
19015+/* xattr.c */
7e9cd9fe
AM
19016+int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags,
19017+ unsigned int verbose);
c1595e42 19018+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size);
f2c43d5f 19019+void au_xattr_init(struct super_block *sb);
c1595e42
JR
19020+#else
19021+AuStubInt0(au_cpup_xattr, struct dentry *h_dst, struct dentry *h_src,
7e9cd9fe 19022+ int ignore_flags, unsigned int verbose);
f2c43d5f 19023+AuStubVoid(au_xattr_init, struct super_block *sb);
c1595e42
JR
19024+#endif
19025+
19026+#ifdef CONFIG_FS_POSIX_ACL
19027+struct posix_acl *aufs_get_acl(struct inode *inode, int type);
19028+int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
19029+#endif
19030+
19031+#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL)
19032+enum {
19033+ AU_XATTR_SET,
c1595e42
JR
19034+ AU_ACL_SET
19035+};
19036+
f2c43d5f 19037+struct au_sxattr {
c1595e42
JR
19038+ int type;
19039+ union {
19040+ struct {
19041+ const char *name;
19042+ const void *value;
19043+ size_t size;
19044+ int flags;
19045+ } set;
19046+ struct {
c1595e42
JR
19047+ struct posix_acl *acl;
19048+ int type;
19049+ } acl_set;
19050+ } u;
19051+};
f2c43d5f
AM
19052+ssize_t au_sxattr(struct dentry *dentry, struct inode *inode,
19053+ struct au_sxattr *arg);
c1595e42
JR
19054+#endif
19055+
4a4d8108 19056+/* ---------------------------------------------------------------------- */
1308ab2a 19057+
4a4d8108
AM
19058+/* lock subclass for iinfo */
19059+enum {
19060+ AuLsc_II_CHILD, /* child first */
19061+ AuLsc_II_CHILD2, /* rename(2), link(2), and cpup at hnotify */
19062+ AuLsc_II_CHILD3, /* copyup dirs */
19063+ AuLsc_II_PARENT, /* see AuLsc_I_PARENT in vfsub.h */
19064+ AuLsc_II_PARENT2,
19065+ AuLsc_II_PARENT3, /* copyup dirs */
19066+ AuLsc_II_NEW_CHILD
19067+};
1308ab2a 19068+
1facf9fc 19069+/*
4a4d8108
AM
19070+ * ii_read_lock_child, ii_write_lock_child,
19071+ * ii_read_lock_child2, ii_write_lock_child2,
19072+ * ii_read_lock_child3, ii_write_lock_child3,
19073+ * ii_read_lock_parent, ii_write_lock_parent,
19074+ * ii_read_lock_parent2, ii_write_lock_parent2,
19075+ * ii_read_lock_parent3, ii_write_lock_parent3,
19076+ * ii_read_lock_new_child, ii_write_lock_new_child,
1facf9fc 19077+ */
4a4d8108
AM
19078+#define AuReadLockFunc(name, lsc) \
19079+static inline void ii_read_lock_##name(struct inode *i) \
19080+{ \
19081+ au_rw_read_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
19082+}
19083+
19084+#define AuWriteLockFunc(name, lsc) \
19085+static inline void ii_write_lock_##name(struct inode *i) \
19086+{ \
19087+ au_rw_write_lock_nested(&au_ii(i)->ii_rwsem, AuLsc_II_##lsc); \
19088+}
19089+
19090+#define AuRWLockFuncs(name, lsc) \
19091+ AuReadLockFunc(name, lsc) \
19092+ AuWriteLockFunc(name, lsc)
19093+
19094+AuRWLockFuncs(child, CHILD);
19095+AuRWLockFuncs(child2, CHILD2);
19096+AuRWLockFuncs(child3, CHILD3);
19097+AuRWLockFuncs(parent, PARENT);
19098+AuRWLockFuncs(parent2, PARENT2);
19099+AuRWLockFuncs(parent3, PARENT3);
19100+AuRWLockFuncs(new_child, NEW_CHILD);
19101+
19102+#undef AuReadLockFunc
19103+#undef AuWriteLockFunc
19104+#undef AuRWLockFuncs
1facf9fc 19105+
8b6a4947
AM
19106+#define ii_read_unlock(i) au_rw_read_unlock(&au_ii(i)->ii_rwsem)
19107+#define ii_write_unlock(i) au_rw_write_unlock(&au_ii(i)->ii_rwsem)
19108+#define ii_downgrade_lock(i) au_rw_dgrade_lock(&au_ii(i)->ii_rwsem)
1facf9fc 19109+
4a4d8108
AM
19110+#define IiMustNoWaiters(i) AuRwMustNoWaiters(&au_ii(i)->ii_rwsem)
19111+#define IiMustAnyLock(i) AuRwMustAnyLock(&au_ii(i)->ii_rwsem)
19112+#define IiMustWriteLock(i) AuRwMustWriteLock(&au_ii(i)->ii_rwsem)
1facf9fc 19113+
4a4d8108 19114+/* ---------------------------------------------------------------------- */
1308ab2a 19115+
027c5e7a
AM
19116+static inline void au_icntnr_init(struct au_icntnr *c)
19117+{
19118+#ifdef CONFIG_AUFS_DEBUG
19119+ c->vfs_inode.i_mode = 0;
19120+#endif
19121+}
19122+
cfc41e69 19123+static inline unsigned int au_iigen(struct inode *inode, unsigned int *igflags)
4a4d8108 19124+{
537831f9
AM
19125+ unsigned int gen;
19126+ struct au_iinfo *iinfo;
be52b249 19127+ struct au_iigen *iigen;
537831f9
AM
19128+
19129+ iinfo = au_ii(inode);
be52b249
AM
19130+ iigen = &iinfo->ii_generation;
19131+ spin_lock(&iigen->ig_spin);
cfc41e69
AM
19132+ if (igflags)
19133+ *igflags = iigen->ig_flags;
be52b249
AM
19134+ gen = iigen->ig_generation;
19135+ spin_unlock(&iigen->ig_spin);
537831f9
AM
19136+
19137+ return gen;
4a4d8108 19138+}
1308ab2a 19139+
4a4d8108
AM
19140+/* tiny test for inode number */
19141+/* tmpfs generation is too rough */
19142+static inline int au_test_higen(struct inode *inode, struct inode *h_inode)
19143+{
19144+ struct au_iinfo *iinfo;
1308ab2a 19145+
4a4d8108
AM
19146+ iinfo = au_ii(inode);
19147+ AuRwMustAnyLock(&iinfo->ii_rwsem);
19148+ return !(iinfo->ii_hsb1 == h_inode->i_sb
19149+ && iinfo->ii_higen == h_inode->i_generation);
19150+}
1308ab2a 19151+
4a4d8108
AM
19152+static inline void au_iigen_dec(struct inode *inode)
19153+{
537831f9 19154+ struct au_iinfo *iinfo;
be52b249 19155+ struct au_iigen *iigen;
537831f9
AM
19156+
19157+ iinfo = au_ii(inode);
be52b249
AM
19158+ iigen = &iinfo->ii_generation;
19159+ spin_lock(&iigen->ig_spin);
19160+ iigen->ig_generation--;
19161+ spin_unlock(&iigen->ig_spin);
027c5e7a
AM
19162+}
19163+
19164+static inline int au_iigen_test(struct inode *inode, unsigned int sigen)
19165+{
19166+ int err;
19167+
19168+ err = 0;
537831f9 19169+ if (unlikely(inode && au_iigen(inode, NULL) != sigen))
027c5e7a
AM
19170+ err = -EIO;
19171+
19172+ return err;
4a4d8108 19173+}
1308ab2a 19174+
4a4d8108 19175+/* ---------------------------------------------------------------------- */
1308ab2a 19176+
5afbbe0d
AM
19177+static inline struct au_hinode *au_hinode(struct au_iinfo *iinfo,
19178+ aufs_bindex_t bindex)
19179+{
19180+ return iinfo->ii_hinode + bindex;
19181+}
19182+
19183+static inline int au_is_bad_inode(struct inode *inode)
19184+{
19185+ return !!(is_bad_inode(inode) || !au_hinode(au_ii(inode), 0));
19186+}
19187+
4a4d8108
AM
19188+static inline aufs_bindex_t au_ii_br_id(struct inode *inode,
19189+ aufs_bindex_t bindex)
19190+{
19191+ IiMustAnyLock(inode);
5afbbe0d 19192+ return au_hinode(au_ii(inode), bindex)->hi_id;
4a4d8108 19193+}
1308ab2a 19194+
5afbbe0d 19195+static inline aufs_bindex_t au_ibtop(struct inode *inode)
4a4d8108
AM
19196+{
19197+ IiMustAnyLock(inode);
5afbbe0d 19198+ return au_ii(inode)->ii_btop;
4a4d8108 19199+}
1308ab2a 19200+
5afbbe0d 19201+static inline aufs_bindex_t au_ibbot(struct inode *inode)
4a4d8108
AM
19202+{
19203+ IiMustAnyLock(inode);
5afbbe0d 19204+ return au_ii(inode)->ii_bbot;
4a4d8108 19205+}
1308ab2a 19206+
4a4d8108
AM
19207+static inline struct au_vdir *au_ivdir(struct inode *inode)
19208+{
19209+ IiMustAnyLock(inode);
19210+ return au_ii(inode)->ii_vdir;
19211+}
1308ab2a 19212+
4a4d8108
AM
19213+static inline struct dentry *au_hi_wh(struct inode *inode, aufs_bindex_t bindex)
19214+{
19215+ IiMustAnyLock(inode);
5afbbe0d 19216+ return au_hinode(au_ii(inode), bindex)->hi_whdentry;
4a4d8108 19217+}
1308ab2a 19218+
5afbbe0d 19219+static inline void au_set_ibtop(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 19220+{
4a4d8108 19221+ IiMustWriteLock(inode);
5afbbe0d 19222+ au_ii(inode)->ii_btop = bindex;
4a4d8108 19223+}
1308ab2a 19224+
5afbbe0d 19225+static inline void au_set_ibbot(struct inode *inode, aufs_bindex_t bindex)
4a4d8108
AM
19226+{
19227+ IiMustWriteLock(inode);
5afbbe0d 19228+ au_ii(inode)->ii_bbot = bindex;
1308ab2a 19229+}
19230+
4a4d8108
AM
19231+static inline void au_set_ivdir(struct inode *inode, struct au_vdir *vdir)
19232+{
19233+ IiMustWriteLock(inode);
19234+ au_ii(inode)->ii_vdir = vdir;
19235+}
1facf9fc 19236+
4a4d8108 19237+static inline struct au_hinode *au_hi(struct inode *inode, aufs_bindex_t bindex)
1308ab2a 19238+{
4a4d8108 19239+ IiMustAnyLock(inode);
5afbbe0d 19240+ return au_hinode(au_ii(inode), bindex);
4a4d8108 19241+}
dece6358 19242+
4a4d8108 19243+/* ---------------------------------------------------------------------- */
1facf9fc 19244+
4a4d8108
AM
19245+static inline struct dentry *au_pinned_parent(struct au_pin *pin)
19246+{
19247+ if (pin)
19248+ return pin->parent;
19249+ return NULL;
1facf9fc 19250+}
19251+
4a4d8108 19252+static inline struct inode *au_pinned_h_dir(struct au_pin *pin)
1facf9fc 19253+{
4a4d8108
AM
19254+ if (pin && pin->hdir)
19255+ return pin->hdir->hi_inode;
19256+ return NULL;
1308ab2a 19257+}
1facf9fc 19258+
4a4d8108
AM
19259+static inline struct au_hinode *au_pinned_hdir(struct au_pin *pin)
19260+{
19261+ if (pin)
19262+ return pin->hdir;
19263+ return NULL;
19264+}
1facf9fc 19265+
4a4d8108 19266+static inline void au_pin_set_dentry(struct au_pin *pin, struct dentry *dentry)
1308ab2a 19267+{
4a4d8108
AM
19268+ if (pin)
19269+ pin->dentry = dentry;
19270+}
1308ab2a 19271+
4a4d8108
AM
19272+static inline void au_pin_set_parent_lflag(struct au_pin *pin,
19273+ unsigned char lflag)
19274+{
19275+ if (pin) {
7f207e10 19276+ if (lflag)
4a4d8108 19277+ au_fset_pin(pin->flags, DI_LOCKED);
7f207e10 19278+ else
4a4d8108 19279+ au_fclr_pin(pin->flags, DI_LOCKED);
1308ab2a 19280+ }
4a4d8108
AM
19281+}
19282+
7e9cd9fe 19283+#if 0 /* reserved */
4a4d8108
AM
19284+static inline void au_pin_set_parent(struct au_pin *pin, struct dentry *parent)
19285+{
19286+ if (pin) {
19287+ dput(pin->parent);
19288+ pin->parent = dget(parent);
1facf9fc 19289+ }
4a4d8108 19290+}
7e9cd9fe 19291+#endif
1facf9fc 19292+
4a4d8108
AM
19293+/* ---------------------------------------------------------------------- */
19294+
027c5e7a 19295+struct au_branch;
4a4d8108
AM
19296+#ifdef CONFIG_AUFS_HNOTIFY
19297+struct au_hnotify_op {
19298+ void (*ctl)(struct au_hinode *hinode, int do_set);
027c5e7a 19299+ int (*alloc)(struct au_hinode *hinode);
7eafdf33
AM
19300+
19301+ /*
19302+ * if it returns true, the the caller should free hinode->hi_notify,
19303+ * otherwise ->free() frees it.
19304+ */
19305+ int (*free)(struct au_hinode *hinode,
19306+ struct au_hnotify *hn) __must_check;
4a4d8108
AM
19307+
19308+ void (*fin)(void);
19309+ int (*init)(void);
027c5e7a
AM
19310+
19311+ int (*reset_br)(unsigned int udba, struct au_branch *br, int perm);
19312+ void (*fin_br)(struct au_branch *br);
19313+ int (*init_br)(struct au_branch *br, int perm);
4a4d8108
AM
19314+};
19315+
19316+/* hnotify.c */
027c5e7a 19317+int au_hn_alloc(struct au_hinode *hinode, struct inode *inode);
4a4d8108
AM
19318+void au_hn_free(struct au_hinode *hinode);
19319+void au_hn_ctl(struct au_hinode *hinode, int do_set);
19320+void au_hn_reset(struct inode *inode, unsigned int flags);
19321+int au_hnotify(struct inode *h_dir, struct au_hnotify *hnotify, u32 mask,
fbc438ed 19322+ const struct qstr *h_child_qstr, struct inode *h_child_inode);
027c5e7a
AM
19323+int au_hnotify_reset_br(unsigned int udba, struct au_branch *br, int perm);
19324+int au_hnotify_init_br(struct au_branch *br, int perm);
19325+void au_hnotify_fin_br(struct au_branch *br);
4a4d8108
AM
19326+int __init au_hnotify_init(void);
19327+void au_hnotify_fin(void);
19328+
7f207e10 19329+/* hfsnotify.c */
4a4d8108
AM
19330+extern const struct au_hnotify_op au_hnotify_op;
19331+
19332+static inline
19333+void au_hn_init(struct au_hinode *hinode)
19334+{
19335+ hinode->hi_notify = NULL;
1308ab2a 19336+}
19337+
53392da6
AM
19338+static inline struct au_hnotify *au_hn(struct au_hinode *hinode)
19339+{
19340+ return hinode->hi_notify;
19341+}
19342+
4a4d8108 19343+#else
c1595e42
JR
19344+AuStub(int, au_hn_alloc, return -EOPNOTSUPP,
19345+ struct au_hinode *hinode __maybe_unused,
19346+ struct inode *inode __maybe_unused)
19347+AuStub(struct au_hnotify *, au_hn, return NULL, struct au_hinode *hinode)
4a4d8108
AM
19348+AuStubVoid(au_hn_free, struct au_hinode *hinode __maybe_unused)
19349+AuStubVoid(au_hn_ctl, struct au_hinode *hinode __maybe_unused,
19350+ int do_set __maybe_unused)
19351+AuStubVoid(au_hn_reset, struct inode *inode __maybe_unused,
19352+ unsigned int flags __maybe_unused)
027c5e7a
AM
19353+AuStubInt0(au_hnotify_reset_br, unsigned int udba __maybe_unused,
19354+ struct au_branch *br __maybe_unused,
19355+ int perm __maybe_unused)
19356+AuStubInt0(au_hnotify_init_br, struct au_branch *br __maybe_unused,
19357+ int perm __maybe_unused)
19358+AuStubVoid(au_hnotify_fin_br, struct au_branch *br __maybe_unused)
4a4d8108
AM
19359+AuStubInt0(__init au_hnotify_init, void)
19360+AuStubVoid(au_hnotify_fin, void)
19361+AuStubVoid(au_hn_init, struct au_hinode *hinode __maybe_unused)
19362+#endif /* CONFIG_AUFS_HNOTIFY */
19363+
19364+static inline void au_hn_suspend(struct au_hinode *hdir)
19365+{
19366+ au_hn_ctl(hdir, /*do_set*/0);
1308ab2a 19367+}
19368+
4a4d8108 19369+static inline void au_hn_resume(struct au_hinode *hdir)
1308ab2a 19370+{
4a4d8108
AM
19371+ au_hn_ctl(hdir, /*do_set*/1);
19372+}
1308ab2a 19373+
5afbbe0d 19374+static inline void au_hn_inode_lock(struct au_hinode *hdir)
4a4d8108 19375+{
febd17d6 19376+ inode_lock(hdir->hi_inode);
4a4d8108
AM
19377+ au_hn_suspend(hdir);
19378+}
dece6358 19379+
5afbbe0d 19380+static inline void au_hn_inode_lock_nested(struct au_hinode *hdir,
4a4d8108
AM
19381+ unsigned int sc __maybe_unused)
19382+{
febd17d6 19383+ inode_lock_nested(hdir->hi_inode, sc);
4a4d8108 19384+ au_hn_suspend(hdir);
1facf9fc 19385+}
1facf9fc 19386+
8b6a4947
AM
19387+#if 0 /* unused */
19388+#include "vfsub.h"
3c1bdaff
AM
19389+static inline void au_hn_inode_lock_shared_nested(struct au_hinode *hdir,
19390+ unsigned int sc)
19391+{
be118d29 19392+ inode_lock_shared_nested(hdir->hi_inode, sc);
3c1bdaff
AM
19393+ au_hn_suspend(hdir);
19394+}
8b6a4947 19395+#endif
3c1bdaff 19396+
5afbbe0d 19397+static inline void au_hn_inode_unlock(struct au_hinode *hdir)
4a4d8108
AM
19398+{
19399+ au_hn_resume(hdir);
febd17d6 19400+ inode_unlock(hdir->hi_inode);
4a4d8108
AM
19401+}
19402+
19403+#endif /* __KERNEL__ */
19404+#endif /* __AUFS_INODE_H__ */
7f207e10 19405diff -urN /usr/share/empty/fs/aufs/ioctl.c linux/fs/aufs/ioctl.c
eca34b5c 19406--- /usr/share/empty/fs/aufs/ioctl.c 1970-01-01 01:00:00.000000000 +0100
016522bc 19407+++ linux/fs/aufs/ioctl.c 2020-01-27 10:57:18.175538316 +0100
062440b3 19408@@ -0,0 +1,220 @@
cd7a4cd9 19409+// SPDX-License-Identifier: GPL-2.0
4a4d8108 19410+/*
016522bc 19411+ * Copyright (C) 2005-2020 Junjiro R. Okajima
4a4d8108
AM
19412+ *
19413+ * This program, aufs is free software; you can redistribute it and/or modify
19414+ * it under the terms of the GNU General Public License as published by
19415+ * the Free Software Foundation; either version 2 of the License, or
19416+ * (at your option) any later version.
19417+ *
19418+ * This program is distributed in the hope that it will be useful,
19419+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19420+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19421+ * GNU General Public License for more details.
19422+ *
19423+ * You should have received a copy of the GNU General Public License
523b37e3 19424+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
19425+ */
19426+
19427+/*
19428+ * ioctl
19429+ * plink-management and readdir in userspace.
19430+ * assist the pathconf(3) wrapper library.
c2b27bf2 19431+ * move-down
076b876e 19432+ * File-based Hierarchical Storage Management.
4a4d8108
AM
19433+ */
19434+
c2b27bf2
AM
19435+#include <linux/compat.h>
19436+#include <linux/file.h>
4a4d8108
AM
19437+#include "aufs.h"
19438+
1e00d052 19439+static int au_wbr_fd(struct path *path, struct aufs_wbr_fd __user *arg)
4a4d8108
AM
19440+{
19441+ int err, fd;
5afbbe0d 19442+ aufs_bindex_t wbi, bindex, bbot;
4a4d8108
AM
19443+ struct file *h_file;
19444+ struct super_block *sb;
19445+ struct dentry *root;
1e00d052
AM
19446+ struct au_branch *br;
19447+ struct aufs_wbr_fd wbrfd = {
19448+ .oflags = au_dir_roflags,
19449+ .brid = -1
19450+ };
19451+ const int valid = O_RDONLY | O_NONBLOCK | O_LARGEFILE | O_DIRECTORY
19452+ | O_NOATIME | O_CLOEXEC;
4a4d8108 19453+
1e00d052
AM
19454+ AuDebugOn(wbrfd.oflags & ~valid);
19455+
19456+ if (arg) {
19457+ err = copy_from_user(&wbrfd, arg, sizeof(wbrfd));
19458+ if (unlikely(err)) {
19459+ err = -EFAULT;
19460+ goto out;
19461+ }
19462+
19463+ err = -EINVAL;
19464+ AuDbg("wbrfd{0%o, %d}\n", wbrfd.oflags, wbrfd.brid);
19465+ wbrfd.oflags |= au_dir_roflags;
19466+ AuDbg("0%o\n", wbrfd.oflags);
19467+ if (unlikely(wbrfd.oflags & ~valid))
19468+ goto out;
19469+ }
19470+
2000de60 19471+ fd = get_unused_fd_flags(0);
1e00d052
AM
19472+ err = fd;
19473+ if (unlikely(fd < 0))
4a4d8108 19474+ goto out;
4a4d8108 19475+
1e00d052 19476+ h_file = ERR_PTR(-EINVAL);
4a4d8108 19477+ wbi = 0;
1e00d052 19478+ br = NULL;
4a4d8108
AM
19479+ sb = path->dentry->d_sb;
19480+ root = sb->s_root;
19481+ aufs_read_lock(root, AuLock_IR);
5afbbe0d 19482+ bbot = au_sbbot(sb);
1e00d052
AM
19483+ if (wbrfd.brid >= 0) {
19484+ wbi = au_br_index(sb, wbrfd.brid);
5afbbe0d 19485+ if (unlikely(wbi < 0 || wbi > bbot))
1e00d052
AM
19486+ goto out_unlock;
19487+ }
19488+
19489+ h_file = ERR_PTR(-ENOENT);
19490+ br = au_sbr(sb, wbi);
19491+ if (!au_br_writable(br->br_perm)) {
19492+ if (arg)
19493+ goto out_unlock;
19494+
19495+ bindex = wbi + 1;
19496+ wbi = -1;
5afbbe0d 19497+ for (; bindex <= bbot; bindex++) {
1e00d052
AM
19498+ br = au_sbr(sb, bindex);
19499+ if (au_br_writable(br->br_perm)) {
4a4d8108 19500+ wbi = bindex;
1e00d052 19501+ br = au_sbr(sb, wbi);
4a4d8108
AM
19502+ break;
19503+ }
19504+ }
4a4d8108
AM
19505+ }
19506+ AuDbg("wbi %d\n", wbi);
1e00d052 19507+ if (wbi >= 0)
392086de
AM
19508+ h_file = au_h_open(root, wbi, wbrfd.oflags, NULL,
19509+ /*force_wr*/0);
1e00d052
AM
19510+
19511+out_unlock:
4a4d8108
AM
19512+ aufs_read_unlock(root, AuLock_IR);
19513+ err = PTR_ERR(h_file);
19514+ if (IS_ERR(h_file))
19515+ goto out_fd;
19516+
acd2b654 19517+ au_lcnt_dec(&br->br_nfiles); /* cf. au_h_open() */
4a4d8108
AM
19518+ fd_install(fd, h_file);
19519+ err = fd;
19520+ goto out; /* success */
19521+
4f0767ce 19522+out_fd:
4a4d8108 19523+ put_unused_fd(fd);
4f0767ce 19524+out:
1e00d052 19525+ AuTraceErr(err);
4a4d8108
AM
19526+ return err;
19527+}
19528+
19529+/* ---------------------------------------------------------------------- */
19530+
19531+long aufs_ioctl_dir(struct file *file, unsigned int cmd, unsigned long arg)
19532+{
19533+ long err;
c1595e42 19534+ struct dentry *dentry;
4a4d8108
AM
19535+
19536+ switch (cmd) {
4a4d8108
AM
19537+ case AUFS_CTL_RDU:
19538+ case AUFS_CTL_RDU_INO:
19539+ err = au_rdu_ioctl(file, cmd, arg);
19540+ break;
19541+
19542+ case AUFS_CTL_WBR_FD:
1e00d052 19543+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
4a4d8108
AM
19544+ break;
19545+
027c5e7a
AM
19546+ case AUFS_CTL_IBUSY:
19547+ err = au_ibusy_ioctl(file, arg);
19548+ break;
19549+
076b876e
AM
19550+ case AUFS_CTL_BRINFO:
19551+ err = au_brinfo_ioctl(file, arg);
19552+ break;
19553+
19554+ case AUFS_CTL_FHSM_FD:
2000de60 19555+ dentry = file->f_path.dentry;
c1595e42
JR
19556+ if (IS_ROOT(dentry))
19557+ err = au_fhsm_fd(dentry->d_sb, arg);
19558+ else
19559+ err = -ENOTTY;
076b876e
AM
19560+ break;
19561+
4a4d8108
AM
19562+ default:
19563+ /* do not call the lower */
19564+ AuDbg("0x%x\n", cmd);
19565+ err = -ENOTTY;
19566+ }
19567+
19568+ AuTraceErr(err);
19569+ return err;
19570+}
19571+
19572+long aufs_ioctl_nondir(struct file *file, unsigned int cmd, unsigned long arg)
19573+{
19574+ long err;
19575+
19576+ switch (cmd) {
c2b27bf2 19577+ case AUFS_CTL_MVDOWN:
2000de60 19578+ err = au_mvdown(file->f_path.dentry, (void __user *)arg);
c2b27bf2
AM
19579+ break;
19580+
4a4d8108 19581+ case AUFS_CTL_WBR_FD:
1e00d052 19582+ err = au_wbr_fd(&file->f_path, (void __user *)arg);
4a4d8108
AM
19583+ break;
19584+
19585+ default:
19586+ /* do not call the lower */
19587+ AuDbg("0x%x\n", cmd);
19588+ err = -ENOTTY;
19589+ }
19590+
19591+ AuTraceErr(err);
19592+ return err;
19593+}
b752ccd1
AM
19594+
19595+#ifdef CONFIG_COMPAT
19596+long aufs_compat_ioctl_dir(struct file *file, unsigned int cmd,
19597+ unsigned long arg)
19598+{
19599+ long err;
19600+
19601+ switch (cmd) {
19602+ case AUFS_CTL_RDU:
19603+ case AUFS_CTL_RDU_INO:
19604+ err = au_rdu_compat_ioctl(file, cmd, arg);
19605+ break;
19606+
027c5e7a
AM
19607+ case AUFS_CTL_IBUSY:
19608+ err = au_ibusy_compat_ioctl(file, arg);
19609+ break;
19610+
076b876e
AM
19611+ case AUFS_CTL_BRINFO:
19612+ err = au_brinfo_compat_ioctl(file, arg);
19613+ break;
19614+
b752ccd1
AM
19615+ default:
19616+ err = aufs_ioctl_dir(file, cmd, arg);
19617+ }
19618+
19619+ AuTraceErr(err);
19620+ return err;
19621+}
19622+
b752ccd1
AM
19623+long aufs_compat_ioctl_nondir(struct file *file, unsigned int cmd,
19624+ unsigned long arg)
19625+{
19626+ return aufs_ioctl_nondir(file, cmd, (unsigned long)compat_ptr(arg));
19627+}
19628+#endif
7f207e10 19629diff -urN /usr/share/empty/fs/aufs/i_op_add.c linux/fs/aufs/i_op_add.c
eca34b5c 19630--- /usr/share/empty/fs/aufs/i_op_add.c 1970-01-01 01:00:00.000000000 +0100
016522bc 19631+++ linux/fs/aufs/i_op_add.c 2020-01-27 10:57:18.172204883 +0100
eca801bf 19632@@ -0,0 +1,936 @@
cd7a4cd9 19633+// SPDX-License-Identifier: GPL-2.0
4a4d8108 19634+/*
016522bc 19635+ * Copyright (C) 2005-2020 Junjiro R. Okajima
4a4d8108
AM
19636+ *
19637+ * This program, aufs is free software; you can redistribute it and/or modify
19638+ * it under the terms of the GNU General Public License as published by
19639+ * the Free Software Foundation; either version 2 of the License, or
19640+ * (at your option) any later version.
19641+ *
19642+ * This program is distributed in the hope that it will be useful,
19643+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19644+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19645+ * GNU General Public License for more details.
19646+ *
19647+ * You should have received a copy of the GNU General Public License
523b37e3 19648+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108
AM
19649+ */
19650+
19651+/*
19652+ * inode operations (add entry)
19653+ */
19654+
eca801bf 19655+#include <linux/iversion.h>
4a4d8108
AM
19656+#include "aufs.h"
19657+
19658+/*
19659+ * final procedure of adding a new entry, except link(2).
19660+ * remove whiteout, instantiate, copyup the parent dir's times and size
19661+ * and update version.
19662+ * if it failed, re-create the removed whiteout.
19663+ */
19664+static int epilog(struct inode *dir, aufs_bindex_t bindex,
19665+ struct dentry *wh_dentry, struct dentry *dentry)
19666+{
19667+ int err, rerr;
19668+ aufs_bindex_t bwh;
19669+ struct path h_path;
076b876e 19670+ struct super_block *sb;
4a4d8108
AM
19671+ struct inode *inode, *h_dir;
19672+ struct dentry *wh;
19673+
19674+ bwh = -1;
076b876e 19675+ sb = dir->i_sb;
4a4d8108 19676+ if (wh_dentry) {
5527c038 19677+ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */
4a4d8108
AM
19678+ IMustLock(h_dir);
19679+ AuDebugOn(au_h_iptr(dir, bindex) != h_dir);
19680+ bwh = au_dbwh(dentry);
19681+ h_path.dentry = wh_dentry;
076b876e 19682+ h_path.mnt = au_sbr_mnt(sb, bindex);
4a4d8108
AM
19683+ err = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path,
19684+ dentry);
19685+ if (unlikely(err))
19686+ goto out;
19687+ }
19688+
19689+ inode = au_new_inode(dentry, /*must_new*/1);
19690+ if (!IS_ERR(inode)) {
19691+ d_instantiate(dentry, inode);
5527c038 19692+ dir = d_inode(dentry->d_parent); /* dir inode is locked */
4a4d8108 19693+ IMustLock(dir);
b912730e 19694+ au_dir_ts(dir, bindex);
be118d29 19695+ inode_inc_iversion(dir);
076b876e 19696+ au_fhsm_wrote(sb, bindex, /*force*/0);
4a4d8108
AM
19697+ return 0; /* success */
19698+ }
19699+
19700+ err = PTR_ERR(inode);
19701+ if (!wh_dentry)
19702+ goto out;
19703+
19704+ /* revert */
19705+ /* dir inode is locked */
19706+ wh = au_wh_create(dentry, bwh, wh_dentry->d_parent);
19707+ rerr = PTR_ERR(wh);
19708+ if (IS_ERR(wh)) {
523b37e3
AM
19709+ AuIOErr("%pd reverting whiteout failed(%d, %d)\n",
19710+ dentry, err, rerr);
4a4d8108
AM
19711+ err = -EIO;
19712+ } else
19713+ dput(wh);
19714+
4f0767ce 19715+out:
4a4d8108
AM
19716+ return err;
19717+}
19718+
027c5e7a
AM
19719+static int au_d_may_add(struct dentry *dentry)
19720+{
19721+ int err;
19722+
19723+ err = 0;
19724+ if (unlikely(d_unhashed(dentry)))
19725+ err = -ENOENT;
5527c038 19726+ if (unlikely(d_really_is_positive(dentry)))
027c5e7a
AM
19727+ err = -EEXIST;
19728+ return err;
19729+}
19730+
4a4d8108
AM
19731+/*
19732+ * simple tests for the adding inode operations.
19733+ * following the checks in vfs, plus the parent-child relationship.
19734+ */
19735+int au_may_add(struct dentry *dentry, aufs_bindex_t bindex,
19736+ struct dentry *h_parent, int isdir)
19737+{
19738+ int err;
19739+ umode_t h_mode;
19740+ struct dentry *h_dentry;
19741+ struct inode *h_inode;
19742+
19743+ err = -ENAMETOOLONG;
19744+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
19745+ goto out;
19746+
19747+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 19748+ if (d_really_is_negative(dentry)) {
4a4d8108 19749+ err = -EEXIST;
5527c038 19750+ if (unlikely(d_is_positive(h_dentry)))
4a4d8108
AM
19751+ goto out;
19752+ } else {
19753+ /* rename(2) case */
19754+ err = -EIO;
5527c038
JR
19755+ if (unlikely(d_is_negative(h_dentry)))
19756+ goto out;
19757+ h_inode = d_inode(h_dentry);
19758+ if (unlikely(!h_inode->i_nlink))
4a4d8108
AM
19759+ goto out;
19760+
19761+ h_mode = h_inode->i_mode;
19762+ if (!isdir) {
19763+ err = -EISDIR;
19764+ if (unlikely(S_ISDIR(h_mode)))
19765+ goto out;
19766+ } else if (unlikely(!S_ISDIR(h_mode))) {
19767+ err = -ENOTDIR;
19768+ goto out;
19769+ }
19770+ }
19771+
19772+ err = 0;
19773+ /* expected parent dir is locked */
19774+ if (unlikely(h_parent != h_dentry->d_parent))
19775+ err = -EIO;
19776+
4f0767ce 19777+out:
4a4d8108
AM
19778+ AuTraceErr(err);
19779+ return err;
19780+}
19781+
19782+/*
19783+ * initial procedure of adding a new entry.
19784+ * prepare writable branch and the parent dir, lock it,
19785+ * and lookup whiteout for the new entry.
19786+ */
19787+static struct dentry*
19788+lock_hdir_lkup_wh(struct dentry *dentry, struct au_dtime *dt,
19789+ struct dentry *src_dentry, struct au_pin *pin,
19790+ struct au_wr_dir_args *wr_dir_args)
19791+{
19792+ struct dentry *wh_dentry, *h_parent;
19793+ struct super_block *sb;
19794+ struct au_branch *br;
19795+ int err;
19796+ unsigned int udba;
19797+ aufs_bindex_t bcpup;
19798+
523b37e3 19799+ AuDbg("%pd\n", dentry);
4a4d8108
AM
19800+
19801+ err = au_wr_dir(dentry, src_dentry, wr_dir_args);
19802+ bcpup = err;
19803+ wh_dentry = ERR_PTR(err);
19804+ if (unlikely(err < 0))
19805+ goto out;
19806+
19807+ sb = dentry->d_sb;
19808+ udba = au_opt_udba(sb);
19809+ err = au_pin(pin, dentry, bcpup, udba,
19810+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
19811+ wh_dentry = ERR_PTR(err);
19812+ if (unlikely(err))
19813+ goto out;
19814+
19815+ h_parent = au_pinned_h_parent(pin);
19816+ if (udba != AuOpt_UDBA_NONE
5afbbe0d 19817+ && au_dbtop(dentry) == bcpup)
4a4d8108
AM
19818+ err = au_may_add(dentry, bcpup, h_parent,
19819+ au_ftest_wrdir(wr_dir_args->flags, ISDIR));
19820+ else if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
19821+ err = -ENAMETOOLONG;
19822+ wh_dentry = ERR_PTR(err);
19823+ if (unlikely(err))
19824+ goto out_unpin;
19825+
19826+ br = au_sbr(sb, bcpup);
19827+ if (dt) {
19828+ struct path tmp = {
19829+ .dentry = h_parent,
86dc4139 19830+ .mnt = au_br_mnt(br)
4a4d8108
AM
19831+ };
19832+ au_dtime_store(dt, au_pinned_parent(pin), &tmp);
19833+ }
19834+
19835+ wh_dentry = NULL;
19836+ if (bcpup != au_dbwh(dentry))
19837+ goto out; /* success */
19838+
2000de60
JR
19839+ /*
19840+ * ENAMETOOLONG here means that if we allowed create such name, then it
19841+ * would not be able to removed in the future. So we don't allow such
19842+ * name here and we don't handle ENAMETOOLONG differently here.
19843+ */
4a4d8108
AM
19844+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
19845+
4f0767ce 19846+out_unpin:
4a4d8108
AM
19847+ if (IS_ERR(wh_dentry))
19848+ au_unpin(pin);
4f0767ce 19849+out:
4a4d8108
AM
19850+ return wh_dentry;
19851+}
19852+
19853+/* ---------------------------------------------------------------------- */
19854+
19855+enum { Mknod, Symlink, Creat };
19856+struct simple_arg {
19857+ int type;
19858+ union {
19859+ struct {
b912730e
AM
19860+ umode_t mode;
19861+ bool want_excl;
19862+ bool try_aopen;
19863+ struct vfsub_aopen_args *aopen;
4a4d8108
AM
19864+ } c;
19865+ struct {
19866+ const char *symname;
19867+ } s;
19868+ struct {
7eafdf33 19869+ umode_t mode;
4a4d8108
AM
19870+ dev_t dev;
19871+ } m;
19872+ } u;
19873+};
19874+
19875+static int add_simple(struct inode *dir, struct dentry *dentry,
19876+ struct simple_arg *arg)
19877+{
076b876e 19878+ int err, rerr;
5afbbe0d 19879+ aufs_bindex_t btop;
4a4d8108 19880+ unsigned char created;
b912730e
AM
19881+ const unsigned char try_aopen
19882+ = (arg->type == Creat && arg->u.c.try_aopen);
acd2b654 19883+ struct vfsub_aopen_args *aopen = arg->u.c.aopen;
4a4d8108
AM
19884+ struct dentry *wh_dentry, *parent;
19885+ struct inode *h_dir;
b912730e
AM
19886+ struct super_block *sb;
19887+ struct au_branch *br;
acd2b654 19888+ /* to reduce stack size */
c2b27bf2
AM
19889+ struct {
19890+ struct au_dtime dt;
19891+ struct au_pin pin;
19892+ struct path h_path;
19893+ struct au_wr_dir_args wr_dir_args;
19894+ } *a;
4a4d8108 19895+
523b37e3 19896+ AuDbg("%pd\n", dentry);
4a4d8108
AM
19897+ IMustLock(dir);
19898+
c2b27bf2
AM
19899+ err = -ENOMEM;
19900+ a = kmalloc(sizeof(*a), GFP_NOFS);
19901+ if (unlikely(!a))
19902+ goto out;
19903+ a->wr_dir_args.force_btgt = -1;
19904+ a->wr_dir_args.flags = AuWrDir_ADD_ENTRY;
19905+
4a4d8108 19906+ parent = dentry->d_parent; /* dir inode is locked */
b912730e
AM
19907+ if (!try_aopen) {
19908+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
19909+ if (unlikely(err))
19910+ goto out_free;
19911+ }
027c5e7a
AM
19912+ err = au_d_may_add(dentry);
19913+ if (unlikely(err))
19914+ goto out_unlock;
b912730e
AM
19915+ if (!try_aopen)
19916+ di_write_lock_parent(parent);
c2b27bf2
AM
19917+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
19918+ &a->pin, &a->wr_dir_args);
4a4d8108
AM
19919+ err = PTR_ERR(wh_dentry);
19920+ if (IS_ERR(wh_dentry))
027c5e7a 19921+ goto out_parent;
4a4d8108 19922+
5afbbe0d 19923+ btop = au_dbtop(dentry);
b912730e 19924+ sb = dentry->d_sb;
5afbbe0d
AM
19925+ br = au_sbr(sb, btop);
19926+ a->h_path.dentry = au_h_dptr(dentry, btop);
b912730e 19927+ a->h_path.mnt = au_br_mnt(br);
c2b27bf2 19928+ h_dir = au_pinned_h_dir(&a->pin);
4a4d8108
AM
19929+ switch (arg->type) {
19930+ case Creat:
acd2b654 19931+ if (!try_aopen || !h_dir->i_op->atomic_open) {
b912730e
AM
19932+ err = vfsub_create(h_dir, &a->h_path, arg->u.c.mode,
19933+ arg->u.c.want_excl);
acd2b654
AM
19934+ created = !err;
19935+ if (!err && try_aopen)
19936+ aopen->file->f_mode |= FMODE_CREATED;
19937+ } else {
19938+ aopen->br = br;
19939+ err = vfsub_atomic_open(h_dir, a->h_path.dentry, aopen);
19940+ AuDbg("err %d\n", err);
19941+ AuDbgFile(aopen->file);
19942+ created = err >= 0
19943+ && !!(aopen->file->f_mode & FMODE_CREATED);
19944+ }
4a4d8108
AM
19945+ break;
19946+ case Symlink:
c2b27bf2 19947+ err = vfsub_symlink(h_dir, &a->h_path, arg->u.s.symname);
acd2b654 19948+ created = !err;
4a4d8108
AM
19949+ break;
19950+ case Mknod:
c2b27bf2
AM
19951+ err = vfsub_mknod(h_dir, &a->h_path, arg->u.m.mode,
19952+ arg->u.m.dev);
acd2b654 19953+ created = !err;
4a4d8108
AM
19954+ break;
19955+ default:
19956+ BUG();
19957+ }
acd2b654
AM
19958+ if (unlikely(err < 0))
19959+ goto out_unpin;
19960+
19961+ err = epilog(dir, btop, wh_dentry, dentry);
4a4d8108 19962+ if (!err)
acd2b654 19963+ goto out_unpin; /* success */
4a4d8108
AM
19964+
19965+ /* revert */
acd2b654 19966+ if (created /* && d_is_positive(a->h_path.dentry) */) {
523b37e3
AM
19967+ /* no delegation since it is just created */
19968+ rerr = vfsub_unlink(h_dir, &a->h_path, /*delegated*/NULL,
19969+ /*force*/0);
4a4d8108 19970+ if (rerr) {
523b37e3
AM
19971+ AuIOErr("%pd revert failure(%d, %d)\n",
19972+ dentry, err, rerr);
4a4d8108
AM
19973+ err = -EIO;
19974+ }
c2b27bf2 19975+ au_dtime_revert(&a->dt);
4a4d8108 19976+ }
acd2b654
AM
19977+ if (try_aopen && h_dir->i_op->atomic_open
19978+ && (aopen->file->f_mode & FMODE_OPENED))
19979+ /* aopen->file is still opened */
19980+ au_lcnt_dec(&aopen->br->br_nfiles);
4a4d8108 19981+
acd2b654 19982+out_unpin:
c2b27bf2 19983+ au_unpin(&a->pin);
4a4d8108 19984+ dput(wh_dentry);
027c5e7a 19985+out_parent:
b912730e
AM
19986+ if (!try_aopen)
19987+ di_write_unlock(parent);
027c5e7a 19988+out_unlock:
4a4d8108 19989+ if (unlikely(err)) {
5afbbe0d 19990+ au_update_dbtop(dentry);
4a4d8108
AM
19991+ d_drop(dentry);
19992+ }
b912730e
AM
19993+ if (!try_aopen)
19994+ aufs_read_unlock(dentry, AuLock_DW);
c2b27bf2 19995+out_free:
9f237c51 19996+ au_kfree_rcu(a);
027c5e7a 19997+out:
4a4d8108
AM
19998+ return err;
19999+}
20000+
7eafdf33
AM
20001+int aufs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
20002+ dev_t dev)
4a4d8108
AM
20003+{
20004+ struct simple_arg arg = {
20005+ .type = Mknod,
20006+ .u.m = {
20007+ .mode = mode,
20008+ .dev = dev
20009+ }
20010+ };
20011+ return add_simple(dir, dentry, &arg);
20012+}
20013+
20014+int aufs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
20015+{
20016+ struct simple_arg arg = {
20017+ .type = Symlink,
20018+ .u.s.symname = symname
20019+ };
20020+ return add_simple(dir, dentry, &arg);
20021+}
20022+
7eafdf33 20023+int aufs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
b4510431 20024+ bool want_excl)
4a4d8108
AM
20025+{
20026+ struct simple_arg arg = {
20027+ .type = Creat,
20028+ .u.c = {
b4510431
AM
20029+ .mode = mode,
20030+ .want_excl = want_excl
4a4d8108
AM
20031+ }
20032+ };
20033+ return add_simple(dir, dentry, &arg);
20034+}
20035+
b912730e
AM
20036+int au_aopen_or_create(struct inode *dir, struct dentry *dentry,
20037+ struct vfsub_aopen_args *aopen_args)
20038+{
20039+ struct simple_arg arg = {
20040+ .type = Creat,
20041+ .u.c = {
20042+ .mode = aopen_args->create_mode,
20043+ .want_excl = aopen_args->open_flag & O_EXCL,
20044+ .try_aopen = true,
20045+ .aopen = aopen_args
20046+ }
20047+ };
20048+ return add_simple(dir, dentry, &arg);
20049+}
20050+
38d290e6
JR
20051+int aufs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
20052+{
20053+ int err;
20054+ aufs_bindex_t bindex;
20055+ struct super_block *sb;
20056+ struct dentry *parent, *h_parent, *h_dentry;
20057+ struct inode *h_dir, *inode;
20058+ struct vfsmount *h_mnt;
20059+ struct au_wr_dir_args wr_dir_args = {
20060+ .force_btgt = -1,
20061+ .flags = AuWrDir_TMPFILE
20062+ };
20063+
20064+ /* copy-up may happen */
febd17d6 20065+ inode_lock(dir);
38d290e6
JR
20066+
20067+ sb = dir->i_sb;
20068+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
20069+ if (unlikely(err))
20070+ goto out;
20071+
20072+ err = au_di_init(dentry);
20073+ if (unlikely(err))
20074+ goto out_si;
20075+
20076+ err = -EBUSY;
20077+ parent = d_find_any_alias(dir);
20078+ AuDebugOn(!parent);
20079+ di_write_lock_parent(parent);
5527c038 20080+ if (unlikely(d_inode(parent) != dir))
38d290e6
JR
20081+ goto out_parent;
20082+
20083+ err = au_digen_test(parent, au_sigen(sb));
20084+ if (unlikely(err))
20085+ goto out_parent;
20086+
5afbbe0d
AM
20087+ bindex = au_dbtop(parent);
20088+ au_set_dbtop(dentry, bindex);
20089+ au_set_dbbot(dentry, bindex);
38d290e6
JR
20090+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
20091+ bindex = err;
20092+ if (unlikely(err < 0))
20093+ goto out_parent;
20094+
20095+ err = -EOPNOTSUPP;
20096+ h_dir = au_h_iptr(dir, bindex);
20097+ if (unlikely(!h_dir->i_op->tmpfile))
20098+ goto out_parent;
20099+
20100+ h_mnt = au_sbr_mnt(sb, bindex);
20101+ err = vfsub_mnt_want_write(h_mnt);
20102+ if (unlikely(err))
20103+ goto out_parent;
20104+
20105+ h_parent = au_h_dptr(parent, bindex);
521ced18
JR
20106+ h_dentry = vfs_tmpfile(h_parent, mode, /*open_flag*/0);
20107+ if (IS_ERR(h_dentry)) {
20108+ err = PTR_ERR(h_dentry);
38d290e6 20109+ goto out_mnt;
521ced18 20110+ }
38d290e6 20111+
5afbbe0d
AM
20112+ au_set_dbtop(dentry, bindex);
20113+ au_set_dbbot(dentry, bindex);
38d290e6
JR
20114+ au_set_h_dptr(dentry, bindex, dget(h_dentry));
20115+ inode = au_new_inode(dentry, /*must_new*/1);
20116+ if (IS_ERR(inode)) {
20117+ err = PTR_ERR(inode);
20118+ au_set_h_dptr(dentry, bindex, NULL);
5afbbe0d
AM
20119+ au_set_dbtop(dentry, -1);
20120+ au_set_dbbot(dentry, -1);
38d290e6
JR
20121+ } else {
20122+ if (!inode->i_nlink)
20123+ set_nlink(inode, 1);
20124+ d_tmpfile(dentry, inode);
20125+ au_di(dentry)->di_tmpfile = 1;
20126+
20127+ /* update without i_mutex */
5afbbe0d 20128+ if (au_ibtop(dir) == au_dbtop(dentry))
38d290e6
JR
20129+ au_cpup_attr_timesizes(dir);
20130+ }
38d290e6 20131+ dput(h_dentry);
521ced18 20132+
38d290e6
JR
20133+out_mnt:
20134+ vfsub_mnt_drop_write(h_mnt);
20135+out_parent:
20136+ di_write_unlock(parent);
20137+ dput(parent);
20138+ di_write_unlock(dentry);
5afbbe0d 20139+ if (unlikely(err)) {
38d290e6
JR
20140+ au_di_fin(dentry);
20141+ dentry->d_fsdata = NULL;
20142+ }
20143+out_si:
20144+ si_read_unlock(sb);
20145+out:
febd17d6 20146+ inode_unlock(dir);
38d290e6
JR
20147+ return err;
20148+}
20149+
4a4d8108
AM
20150+/* ---------------------------------------------------------------------- */
20151+
20152+struct au_link_args {
20153+ aufs_bindex_t bdst, bsrc;
20154+ struct au_pin pin;
20155+ struct path h_path;
20156+ struct dentry *src_parent, *parent;
20157+};
20158+
20159+static int au_cpup_before_link(struct dentry *src_dentry,
20160+ struct au_link_args *a)
20161+{
20162+ int err;
20163+ struct dentry *h_src_dentry;
c2b27bf2
AM
20164+ struct au_cp_generic cpg = {
20165+ .dentry = src_dentry,
20166+ .bdst = a->bdst,
20167+ .bsrc = a->bsrc,
20168+ .len = -1,
20169+ .pin = &a->pin,
20170+ .flags = AuCpup_DTIME | AuCpup_HOPEN /* | AuCpup_KEEPLINO */
20171+ };
4a4d8108
AM
20172+
20173+ di_read_lock_parent(a->src_parent, AuLock_IR);
20174+ err = au_test_and_cpup_dirs(src_dentry, a->bdst);
20175+ if (unlikely(err))
20176+ goto out;
20177+
20178+ h_src_dentry = au_h_dptr(src_dentry, a->bsrc);
4a4d8108
AM
20179+ err = au_pin(&a->pin, src_dentry, a->bdst,
20180+ au_opt_udba(src_dentry->d_sb),
20181+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
20182+ if (unlikely(err))
20183+ goto out;
367653fa 20184+
c2b27bf2 20185+ err = au_sio_cpup_simple(&cpg);
4a4d8108
AM
20186+ au_unpin(&a->pin);
20187+
4f0767ce 20188+out:
4a4d8108
AM
20189+ di_read_unlock(a->src_parent, AuLock_IR);
20190+ return err;
20191+}
20192+
86dc4139
AM
20193+static int au_cpup_or_link(struct dentry *src_dentry, struct dentry *dentry,
20194+ struct au_link_args *a)
4a4d8108
AM
20195+{
20196+ int err;
20197+ unsigned char plink;
5afbbe0d 20198+ aufs_bindex_t bbot;
4a4d8108 20199+ struct dentry *h_src_dentry;
523b37e3 20200+ struct inode *h_inode, *inode, *delegated;
4a4d8108
AM
20201+ struct super_block *sb;
20202+ struct file *h_file;
20203+
20204+ plink = 0;
20205+ h_inode = NULL;
20206+ sb = src_dentry->d_sb;
5527c038 20207+ inode = d_inode(src_dentry);
5afbbe0d 20208+ if (au_ibtop(inode) <= a->bdst)
4a4d8108
AM
20209+ h_inode = au_h_iptr(inode, a->bdst);
20210+ if (!h_inode || !h_inode->i_nlink) {
20211+ /* copyup src_dentry as the name of dentry. */
5afbbe0d
AM
20212+ bbot = au_dbbot(dentry);
20213+ if (bbot < a->bsrc)
20214+ au_set_dbbot(dentry, a->bsrc);
86dc4139
AM
20215+ au_set_h_dptr(dentry, a->bsrc,
20216+ dget(au_h_dptr(src_dentry, a->bsrc)));
20217+ dget(a->h_path.dentry);
20218+ au_set_h_dptr(dentry, a->bdst, NULL);
c1595e42
JR
20219+ AuDbg("temporary d_inode...\n");
20220+ spin_lock(&dentry->d_lock);
5527c038 20221+ dentry->d_inode = d_inode(src_dentry); /* tmp */
c1595e42 20222+ spin_unlock(&dentry->d_lock);
392086de 20223+ h_file = au_h_open_pre(dentry, a->bsrc, /*force_wr*/0);
86dc4139 20224+ if (IS_ERR(h_file))
4a4d8108 20225+ err = PTR_ERR(h_file);
86dc4139 20226+ else {
c2b27bf2
AM
20227+ struct au_cp_generic cpg = {
20228+ .dentry = dentry,
20229+ .bdst = a->bdst,
20230+ .bsrc = -1,
20231+ .len = -1,
20232+ .pin = &a->pin,
20233+ .flags = AuCpup_KEEPLINO
20234+ };
20235+ err = au_sio_cpup_simple(&cpg);
86dc4139
AM
20236+ au_h_open_post(dentry, a->bsrc, h_file);
20237+ if (!err) {
20238+ dput(a->h_path.dentry);
20239+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
20240+ } else
20241+ au_set_h_dptr(dentry, a->bdst,
20242+ a->h_path.dentry);
20243+ }
c1595e42 20244+ spin_lock(&dentry->d_lock);
86dc4139 20245+ dentry->d_inode = NULL; /* restore */
c1595e42
JR
20246+ spin_unlock(&dentry->d_lock);
20247+ AuDbg("temporary d_inode...done\n");
86dc4139 20248+ au_set_h_dptr(dentry, a->bsrc, NULL);
5afbbe0d 20249+ au_set_dbbot(dentry, bbot);
4a4d8108
AM
20250+ } else {
20251+ /* the inode of src_dentry already exists on a.bdst branch */
20252+ h_src_dentry = d_find_alias(h_inode);
20253+ if (!h_src_dentry && au_plink_test(inode)) {
20254+ plink = 1;
20255+ h_src_dentry = au_plink_lkup(inode, a->bdst);
20256+ err = PTR_ERR(h_src_dentry);
20257+ if (IS_ERR(h_src_dentry))
20258+ goto out;
20259+
5527c038 20260+ if (unlikely(d_is_negative(h_src_dentry))) {
4a4d8108
AM
20261+ dput(h_src_dentry);
20262+ h_src_dentry = NULL;
20263+ }
20264+
20265+ }
20266+ if (h_src_dentry) {
523b37e3 20267+ delegated = NULL;
4a4d8108 20268+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
523b37e3
AM
20269+ &a->h_path, &delegated);
20270+ if (unlikely(err == -EWOULDBLOCK)) {
20271+ pr_warn("cannot retry for NFSv4 delegation"
20272+ " for an internal link\n");
20273+ iput(delegated);
20274+ }
4a4d8108
AM
20275+ dput(h_src_dentry);
20276+ } else {
20277+ AuIOErr("no dentry found for hi%lu on b%d\n",
20278+ h_inode->i_ino, a->bdst);
20279+ err = -EIO;
20280+ }
20281+ }
20282+
20283+ if (!err && !plink)
20284+ au_plink_append(inode, a->bdst, a->h_path.dentry);
20285+
20286+out:
2cbb1c4b 20287+ AuTraceErr(err);
4a4d8108
AM
20288+ return err;
20289+}
20290+
20291+int aufs_link(struct dentry *src_dentry, struct inode *dir,
20292+ struct dentry *dentry)
20293+{
20294+ int err, rerr;
20295+ struct au_dtime dt;
20296+ struct au_link_args *a;
20297+ struct dentry *wh_dentry, *h_src_dentry;
523b37e3 20298+ struct inode *inode, *delegated;
4a4d8108
AM
20299+ struct super_block *sb;
20300+ struct au_wr_dir_args wr_dir_args = {
20301+ /* .force_btgt = -1, */
20302+ .flags = AuWrDir_ADD_ENTRY
20303+ };
20304+
20305+ IMustLock(dir);
5527c038 20306+ inode = d_inode(src_dentry);
4a4d8108
AM
20307+ IMustLock(inode);
20308+
4a4d8108
AM
20309+ err = -ENOMEM;
20310+ a = kzalloc(sizeof(*a), GFP_NOFS);
20311+ if (unlikely(!a))
20312+ goto out;
20313+
20314+ a->parent = dentry->d_parent; /* dir inode is locked */
027c5e7a
AM
20315+ err = aufs_read_and_write_lock2(dentry, src_dentry,
20316+ AuLock_NOPLM | AuLock_GEN);
e49829fe
JR
20317+ if (unlikely(err))
20318+ goto out_kfree;
38d290e6 20319+ err = au_d_linkable(src_dentry);
027c5e7a
AM
20320+ if (unlikely(err))
20321+ goto out_unlock;
20322+ err = au_d_may_add(dentry);
20323+ if (unlikely(err))
20324+ goto out_unlock;
e49829fe 20325+
4a4d8108 20326+ a->src_parent = dget_parent(src_dentry);
5afbbe0d 20327+ wr_dir_args.force_btgt = au_ibtop(inode);
4a4d8108
AM
20328+
20329+ di_write_lock_parent(a->parent);
20330+ wr_dir_args.force_btgt = au_wbr(dentry, wr_dir_args.force_btgt);
20331+ wh_dentry = lock_hdir_lkup_wh(dentry, &dt, src_dentry, &a->pin,
20332+ &wr_dir_args);
20333+ err = PTR_ERR(wh_dentry);
20334+ if (IS_ERR(wh_dentry))
027c5e7a 20335+ goto out_parent;
4a4d8108
AM
20336+
20337+ err = 0;
20338+ sb = dentry->d_sb;
5afbbe0d 20339+ a->bdst = au_dbtop(dentry);
4a4d8108
AM
20340+ a->h_path.dentry = au_h_dptr(dentry, a->bdst);
20341+ a->h_path.mnt = au_sbr_mnt(sb, a->bdst);
5afbbe0d 20342+ a->bsrc = au_ibtop(inode);
2cbb1c4b 20343+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
38d290e6
JR
20344+ if (!h_src_dentry && au_di(src_dentry)->di_tmpfile)
20345+ h_src_dentry = dget(au_hi_wh(inode, a->bsrc));
2cbb1c4b 20346+ if (!h_src_dentry) {
5afbbe0d 20347+ a->bsrc = au_dbtop(src_dentry);
2cbb1c4b
JR
20348+ h_src_dentry = au_h_d_alias(src_dentry, a->bsrc);
20349+ AuDebugOn(!h_src_dentry);
38d290e6
JR
20350+ } else if (IS_ERR(h_src_dentry)) {
20351+ err = PTR_ERR(h_src_dentry);
2cbb1c4b 20352+ goto out_parent;
38d290e6 20353+ }
2cbb1c4b 20354+
f2c43d5f
AM
20355+ /*
20356+ * aufs doesn't touch the credential so
acd2b654 20357+ * security_dentry_create_files_as() is unnecessary.
f2c43d5f 20358+ */
4a4d8108
AM
20359+ if (au_opt_test(au_mntflags(sb), PLINK)) {
20360+ if (a->bdst < a->bsrc
20361+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */)
86dc4139 20362+ err = au_cpup_or_link(src_dentry, dentry, a);
523b37e3
AM
20363+ else {
20364+ delegated = NULL;
4a4d8108 20365+ err = vfsub_link(h_src_dentry, au_pinned_h_dir(&a->pin),
523b37e3
AM
20366+ &a->h_path, &delegated);
20367+ if (unlikely(err == -EWOULDBLOCK)) {
20368+ pr_warn("cannot retry for NFSv4 delegation"
20369+ " for an internal link\n");
20370+ iput(delegated);
20371+ }
20372+ }
2cbb1c4b 20373+ dput(h_src_dentry);
4a4d8108
AM
20374+ } else {
20375+ /*
20376+ * copyup src_dentry to the branch we process,
20377+ * and then link(2) to it.
20378+ */
2cbb1c4b 20379+ dput(h_src_dentry);
4a4d8108
AM
20380+ if (a->bdst < a->bsrc
20381+ /* && h_src_dentry->d_sb != a->h_path.dentry->d_sb */) {
20382+ au_unpin(&a->pin);
20383+ di_write_unlock(a->parent);
20384+ err = au_cpup_before_link(src_dentry, a);
20385+ di_write_lock_parent(a->parent);
20386+ if (!err)
20387+ err = au_pin(&a->pin, dentry, a->bdst,
20388+ au_opt_udba(sb),
20389+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
20390+ if (unlikely(err))
20391+ goto out_wh;
20392+ }
20393+ if (!err) {
20394+ h_src_dentry = au_h_dptr(src_dentry, a->bdst);
20395+ err = -ENOENT;
5527c038 20396+ if (h_src_dentry && d_is_positive(h_src_dentry)) {
523b37e3 20397+ delegated = NULL;
4a4d8108
AM
20398+ err = vfsub_link(h_src_dentry,
20399+ au_pinned_h_dir(&a->pin),
523b37e3
AM
20400+ &a->h_path, &delegated);
20401+ if (unlikely(err == -EWOULDBLOCK)) {
20402+ pr_warn("cannot retry"
20403+ " for NFSv4 delegation"
20404+ " for an internal link\n");
20405+ iput(delegated);
20406+ }
20407+ }
4a4d8108
AM
20408+ }
20409+ }
20410+ if (unlikely(err))
20411+ goto out_unpin;
20412+
20413+ if (wh_dentry) {
20414+ a->h_path.dentry = wh_dentry;
20415+ err = au_wh_unlink_dentry(au_pinned_h_dir(&a->pin), &a->h_path,
20416+ dentry);
20417+ if (unlikely(err))
20418+ goto out_revert;
20419+ }
20420+
b912730e 20421+ au_dir_ts(dir, a->bdst);
be118d29 20422+ inode_inc_iversion(dir);
4a4d8108
AM
20423+ inc_nlink(inode);
20424+ inode->i_ctime = dir->i_ctime;
027c5e7a
AM
20425+ d_instantiate(dentry, au_igrab(inode));
20426+ if (d_unhashed(a->h_path.dentry))
4a4d8108
AM
20427+ /* some filesystem calls d_drop() */
20428+ d_drop(dentry);
076b876e
AM
20429+ /* some filesystems consume an inode even hardlink */
20430+ au_fhsm_wrote(sb, a->bdst, /*force*/0);
4a4d8108
AM
20431+ goto out_unpin; /* success */
20432+
4f0767ce 20433+out_revert:
523b37e3
AM
20434+ /* no delegation since it is just created */
20435+ rerr = vfsub_unlink(au_pinned_h_dir(&a->pin), &a->h_path,
20436+ /*delegated*/NULL, /*force*/0);
027c5e7a 20437+ if (unlikely(rerr)) {
523b37e3 20438+ AuIOErr("%pd reverting failed(%d, %d)\n", dentry, err, rerr);
027c5e7a
AM
20439+ err = -EIO;
20440+ }
4a4d8108 20441+ au_dtime_revert(&dt);
4f0767ce 20442+out_unpin:
4a4d8108 20443+ au_unpin(&a->pin);
4f0767ce 20444+out_wh:
4a4d8108 20445+ dput(wh_dentry);
027c5e7a
AM
20446+out_parent:
20447+ di_write_unlock(a->parent);
20448+ dput(a->src_parent);
4f0767ce 20449+out_unlock:
4a4d8108 20450+ if (unlikely(err)) {
5afbbe0d 20451+ au_update_dbtop(dentry);
4a4d8108
AM
20452+ d_drop(dentry);
20453+ }
4a4d8108 20454+ aufs_read_and_write_unlock2(dentry, src_dentry);
e49829fe 20455+out_kfree:
9f237c51 20456+ au_kfree_rcu(a);
4f0767ce 20457+out:
86dc4139 20458+ AuTraceErr(err);
4a4d8108
AM
20459+ return err;
20460+}
20461+
7eafdf33 20462+int aufs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
4a4d8108
AM
20463+{
20464+ int err, rerr;
20465+ aufs_bindex_t bindex;
20466+ unsigned char diropq;
20467+ struct path h_path;
20468+ struct dentry *wh_dentry, *parent, *opq_dentry;
febd17d6 20469+ struct inode *h_inode;
4a4d8108
AM
20470+ struct super_block *sb;
20471+ struct {
20472+ struct au_pin pin;
20473+ struct au_dtime dt;
20474+ } *a; /* reduce the stack usage */
20475+ struct au_wr_dir_args wr_dir_args = {
20476+ .force_btgt = -1,
20477+ .flags = AuWrDir_ADD_ENTRY | AuWrDir_ISDIR
20478+ };
20479+
20480+ IMustLock(dir);
20481+
20482+ err = -ENOMEM;
20483+ a = kmalloc(sizeof(*a), GFP_NOFS);
20484+ if (unlikely(!a))
20485+ goto out;
20486+
027c5e7a
AM
20487+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
20488+ if (unlikely(err))
20489+ goto out_free;
20490+ err = au_d_may_add(dentry);
20491+ if (unlikely(err))
20492+ goto out_unlock;
20493+
4a4d8108
AM
20494+ parent = dentry->d_parent; /* dir inode is locked */
20495+ di_write_lock_parent(parent);
20496+ wh_dentry = lock_hdir_lkup_wh(dentry, &a->dt, /*src_dentry*/NULL,
20497+ &a->pin, &wr_dir_args);
20498+ err = PTR_ERR(wh_dentry);
20499+ if (IS_ERR(wh_dentry))
027c5e7a 20500+ goto out_parent;
4a4d8108
AM
20501+
20502+ sb = dentry->d_sb;
5afbbe0d 20503+ bindex = au_dbtop(dentry);
4a4d8108
AM
20504+ h_path.dentry = au_h_dptr(dentry, bindex);
20505+ h_path.mnt = au_sbr_mnt(sb, bindex);
20506+ err = vfsub_mkdir(au_pinned_h_dir(&a->pin), &h_path, mode);
20507+ if (unlikely(err))
027c5e7a 20508+ goto out_unpin;
4a4d8108
AM
20509+
20510+ /* make the dir opaque */
20511+ diropq = 0;
febd17d6 20512+ h_inode = d_inode(h_path.dentry);
4a4d8108
AM
20513+ if (wh_dentry
20514+ || au_opt_test(au_mntflags(sb), ALWAYS_DIROPQ)) {
febd17d6 20515+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 20516+ opq_dentry = au_diropq_create(dentry, bindex);
febd17d6 20517+ inode_unlock(h_inode);
4a4d8108
AM
20518+ err = PTR_ERR(opq_dentry);
20519+ if (IS_ERR(opq_dentry))
20520+ goto out_dir;
20521+ dput(opq_dentry);
20522+ diropq = 1;
20523+ }
20524+
20525+ err = epilog(dir, bindex, wh_dentry, dentry);
20526+ if (!err) {
20527+ inc_nlink(dir);
027c5e7a 20528+ goto out_unpin; /* success */
4a4d8108
AM
20529+ }
20530+
20531+ /* revert */
20532+ if (diropq) {
20533+ AuLabel(revert opq);
febd17d6 20534+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 20535+ rerr = au_diropq_remove(dentry, bindex);
febd17d6 20536+ inode_unlock(h_inode);
4a4d8108 20537+ if (rerr) {
523b37e3
AM
20538+ AuIOErr("%pd reverting diropq failed(%d, %d)\n",
20539+ dentry, err, rerr);
4a4d8108
AM
20540+ err = -EIO;
20541+ }
20542+ }
20543+
4f0767ce 20544+out_dir:
4a4d8108
AM
20545+ AuLabel(revert dir);
20546+ rerr = vfsub_rmdir(au_pinned_h_dir(&a->pin), &h_path);
20547+ if (rerr) {
523b37e3
AM
20548+ AuIOErr("%pd reverting dir failed(%d, %d)\n",
20549+ dentry, err, rerr);
4a4d8108
AM
20550+ err = -EIO;
20551+ }
4a4d8108 20552+ au_dtime_revert(&a->dt);
027c5e7a 20553+out_unpin:
4a4d8108
AM
20554+ au_unpin(&a->pin);
20555+ dput(wh_dentry);
027c5e7a
AM
20556+out_parent:
20557+ di_write_unlock(parent);
20558+out_unlock:
4a4d8108 20559+ if (unlikely(err)) {
5afbbe0d 20560+ au_update_dbtop(dentry);
4a4d8108
AM
20561+ d_drop(dentry);
20562+ }
4a4d8108 20563+ aufs_read_unlock(dentry, AuLock_DW);
027c5e7a 20564+out_free:
9f237c51 20565+ au_kfree_rcu(a);
4f0767ce 20566+out:
4a4d8108
AM
20567+ return err;
20568+}
7f207e10 20569diff -urN /usr/share/empty/fs/aufs/i_op.c linux/fs/aufs/i_op.c
eca34b5c 20570--- /usr/share/empty/fs/aufs/i_op.c 1970-01-01 01:00:00.000000000 +0100
016522bc 20571+++ linux/fs/aufs/i_op.c 2020-04-03 08:16:47.547461775 +0200
43982f53 20572@@ -0,0 +1,1498 @@
cd7a4cd9 20573+// SPDX-License-Identifier: GPL-2.0
4a4d8108 20574+/*
016522bc 20575+ * Copyright (C) 2005-2020 Junjiro R. Okajima
4a4d8108
AM
20576+ *
20577+ * This program, aufs is free software; you can redistribute it and/or modify
20578+ * it under the terms of the GNU General Public License as published by
20579+ * the Free Software Foundation; either version 2 of the License, or
20580+ * (at your option) any later version.
20581+ *
20582+ * This program is distributed in the hope that it will be useful,
20583+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20584+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20585+ * GNU General Public License for more details.
20586+ *
20587+ * You should have received a copy of the GNU General Public License
523b37e3 20588+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4a4d8108 20589+ */
1facf9fc 20590+
1308ab2a 20591+/*
4a4d8108 20592+ * inode operations (except add/del/rename)
1308ab2a 20593+ */
4a4d8108
AM
20594+
20595+#include <linux/device_cgroup.h>
20596+#include <linux/fs_stack.h>
eca801bf 20597+#include <linux/iversion.h>
4a4d8108
AM
20598+#include <linux/namei.h>
20599+#include <linux/security.h>
4a4d8108
AM
20600+#include "aufs.h"
20601+
1e00d052 20602+static int h_permission(struct inode *h_inode, int mask,
79b8bda9 20603+ struct path *h_path, int brperm)
1facf9fc 20604+{
1308ab2a 20605+ int err;
4a4d8108 20606+ const unsigned char write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
1facf9fc 20607+
e2f27e51
AM
20608+ err = -EPERM;
20609+ if (write_mask && IS_IMMUTABLE(h_inode))
20610+ goto out;
20611+
4a4d8108 20612+ err = -EACCES;
e2f27e51
AM
20613+ if (((mask & MAY_EXEC)
20614+ && S_ISREG(h_inode->i_mode)
20615+ && (path_noexec(h_path)
cd7a4cd9 20616+ || !(h_inode->i_mode & 0111))))
4a4d8108
AM
20617+ goto out;
20618+
20619+ /*
20620+ * - skip the lower fs test in the case of write to ro branch.
20621+ * - nfs dir permission write check is optimized, but a policy for
20622+ * link/rename requires a real check.
2121bcd9 20623+ * - nfs always sets SB_POSIXACL regardless its mount option 'noacl.'
b912730e 20624+ * in this case, generic_permission() returns -EOPNOTSUPP.
4a4d8108
AM
20625+ */
20626+ if ((write_mask && !au_br_writable(brperm))
20627+ || (au_test_nfs(h_inode->i_sb) && S_ISDIR(h_inode->i_mode)
20628+ && write_mask && !(mask & MAY_READ))
20629+ || !h_inode->i_op->permission) {
20630+ /* AuLabel(generic_permission); */
062440b3 20631+ /* AuDbg("get_acl %ps\n", h_inode->i_op->get_acl); */
1e00d052 20632+ err = generic_permission(h_inode, mask);
b912730e
AM
20633+ if (err == -EOPNOTSUPP && au_test_nfs_noacl(h_inode))
20634+ err = h_inode->i_op->permission(h_inode, mask);
20635+ AuTraceErr(err);
1308ab2a 20636+ } else {
4a4d8108 20637+ /* AuLabel(h_inode->permission); */
1e00d052 20638+ err = h_inode->i_op->permission(h_inode, mask);
4a4d8108
AM
20639+ AuTraceErr(err);
20640+ }
1facf9fc 20641+
4a4d8108
AM
20642+ if (!err)
20643+ err = devcgroup_inode_permission(h_inode, mask);
7f207e10 20644+ if (!err)
4a4d8108 20645+ err = security_inode_permission(h_inode, mask);
4a4d8108 20646+
4f0767ce 20647+out:
1308ab2a 20648+ return err;
20649+}
dece6358 20650+
1e00d052 20651+static int aufs_permission(struct inode *inode, int mask)
1308ab2a 20652+{
20653+ int err;
5afbbe0d 20654+ aufs_bindex_t bindex, bbot;
4a4d8108
AM
20655+ const unsigned char isdir = !!S_ISDIR(inode->i_mode),
20656+ write_mask = !!(mask & (MAY_WRITE | MAY_APPEND));
20657+ struct inode *h_inode;
20658+ struct super_block *sb;
20659+ struct au_branch *br;
1facf9fc 20660+
027c5e7a 20661+ /* todo: support rcu-walk? */
1e00d052 20662+ if (mask & MAY_NOT_BLOCK)
027c5e7a
AM
20663+ return -ECHILD;
20664+
4a4d8108
AM
20665+ sb = inode->i_sb;
20666+ si_read_lock(sb, AuLock_FLUSH);
20667+ ii_read_lock_child(inode);
43982f53
AM
20668+#if 0 /* reserved for future use */
20669+ /*
20670+ * This test may be rather 'too much' since the test is essentially done
20671+ * in the aufs_lookup(). Theoretically it is possible that the inode
20672+ * generation doesn't match to the superblock's here. But it isn't a
20673+ * big deal I suppose.
20674+ */
027c5e7a
AM
20675+ err = au_iigen_test(inode, au_sigen(sb));
20676+ if (unlikely(err))
20677+ goto out;
20678+#endif
dece6358 20679+
076b876e
AM
20680+ if (!isdir
20681+ || write_mask
20682+ || au_opt_test(au_mntflags(sb), DIRPERM1)) {
4a4d8108 20683+ err = au_busy_or_stale();
5afbbe0d 20684+ h_inode = au_h_iptr(inode, au_ibtop(inode));
4a4d8108
AM
20685+ if (unlikely(!h_inode
20686+ || (h_inode->i_mode & S_IFMT)
20687+ != (inode->i_mode & S_IFMT)))
20688+ goto out;
1facf9fc 20689+
4a4d8108 20690+ err = 0;
5afbbe0d 20691+ bindex = au_ibtop(inode);
4a4d8108 20692+ br = au_sbr(sb, bindex);
79b8bda9 20693+ err = h_permission(h_inode, mask, &br->br_path, br->br_perm);
4a4d8108
AM
20694+ if (write_mask
20695+ && !err
20696+ && !special_file(h_inode->i_mode)) {
20697+ /* test whether the upper writable branch exists */
20698+ err = -EROFS;
20699+ for (; bindex >= 0; bindex--)
20700+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
20701+ err = 0;
20702+ break;
20703+ }
20704+ }
20705+ goto out;
20706+ }
dece6358 20707+
4a4d8108 20708+ /* non-write to dir */
1308ab2a 20709+ err = 0;
5afbbe0d
AM
20710+ bbot = au_ibbot(inode);
20711+ for (bindex = au_ibtop(inode); !err && bindex <= bbot; bindex++) {
4a4d8108
AM
20712+ h_inode = au_h_iptr(inode, bindex);
20713+ if (h_inode) {
20714+ err = au_busy_or_stale();
20715+ if (unlikely(!S_ISDIR(h_inode->i_mode)))
20716+ break;
20717+
20718+ br = au_sbr(sb, bindex);
79b8bda9 20719+ err = h_permission(h_inode, mask, &br->br_path,
4a4d8108
AM
20720+ br->br_perm);
20721+ }
20722+ }
1308ab2a 20723+
4f0767ce 20724+out:
4a4d8108
AM
20725+ ii_read_unlock(inode);
20726+ si_read_unlock(sb);
1308ab2a 20727+ return err;
20728+}
20729+
4a4d8108 20730+/* ---------------------------------------------------------------------- */
1facf9fc 20731+
4a4d8108 20732+static struct dentry *aufs_lookup(struct inode *dir, struct dentry *dentry,
b4510431 20733+ unsigned int flags)
4a4d8108
AM
20734+{
20735+ struct dentry *ret, *parent;
b752ccd1 20736+ struct inode *inode;
4a4d8108 20737+ struct super_block *sb;
1716fcea 20738+ int err, npositive;
dece6358 20739+
4a4d8108 20740+ IMustLock(dir);
1308ab2a 20741+
537831f9
AM
20742+ /* todo: support rcu-walk? */
20743+ ret = ERR_PTR(-ECHILD);
20744+ if (flags & LOOKUP_RCU)
20745+ goto out;
20746+
20747+ ret = ERR_PTR(-ENAMETOOLONG);
20748+ if (unlikely(dentry->d_name.len > AUFS_MAX_NAMELEN))
20749+ goto out;
20750+
4a4d8108 20751+ sb = dir->i_sb;
7f207e10
AM
20752+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
20753+ ret = ERR_PTR(err);
20754+ if (unlikely(err))
20755+ goto out;
20756+
4a4d8108
AM
20757+ err = au_di_init(dentry);
20758+ ret = ERR_PTR(err);
20759+ if (unlikely(err))
7f207e10 20760+ goto out_si;
1308ab2a 20761+
9dbd164d 20762+ inode = NULL;
027c5e7a 20763+ npositive = 0; /* suppress a warning */
4a4d8108
AM
20764+ parent = dentry->d_parent; /* dir inode is locked */
20765+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
20766+ err = au_alive_dir(parent);
20767+ if (!err)
20768+ err = au_digen_test(parent, au_sigen(sb));
20769+ if (!err) {
5afbbe0d
AM
20770+ /* regardless LOOKUP_CREATE, always ALLOW_NEG */
20771+ npositive = au_lkup_dentry(dentry, au_dbtop(parent),
20772+ AuLkup_ALLOW_NEG);
027c5e7a
AM
20773+ err = npositive;
20774+ }
4a4d8108 20775+ di_read_unlock(parent, AuLock_IR);
4a4d8108
AM
20776+ ret = ERR_PTR(err);
20777+ if (unlikely(err < 0))
20778+ goto out_unlock;
1308ab2a 20779+
4a4d8108 20780+ if (npositive) {
b752ccd1 20781+ inode = au_new_inode(dentry, /*must_new*/0);
c1595e42
JR
20782+ if (IS_ERR(inode)) {
20783+ ret = (void *)inode;
20784+ inode = NULL;
20785+ goto out_unlock;
20786+ }
9dbd164d 20787+ }
4a4d8108 20788+
c1595e42
JR
20789+ if (inode)
20790+ atomic_inc(&inode->i_count);
4a4d8108 20791+ ret = d_splice_alias(inode, dentry);
43982f53 20792+#if 0 /* reserved for future use */
537831f9
AM
20793+ if (unlikely(d_need_lookup(dentry))) {
20794+ spin_lock(&dentry->d_lock);
20795+ dentry->d_flags &= ~DCACHE_NEED_LOOKUP;
20796+ spin_unlock(&dentry->d_lock);
20797+ } else
20798+#endif
c1595e42 20799+ if (inode) {
2000de60 20800+ if (!IS_ERR(ret)) {
c1595e42 20801+ iput(inode);
2000de60
JR
20802+ if (ret && ret != dentry)
20803+ ii_write_unlock(inode);
20804+ } else {
c1595e42
JR
20805+ ii_write_unlock(inode);
20806+ iput(inode);
20807+ inode = NULL;
20808+ }
7f207e10 20809+ }
1facf9fc 20810+
4f0767ce 20811+out_unlock:
4a4d8108 20812+ di_write_unlock(dentry);
7f207e10 20813+out_si:
4a4d8108 20814+ si_read_unlock(sb);
7f207e10 20815+out:
4a4d8108
AM
20816+ return ret;
20817+}
1facf9fc 20818+
4a4d8108 20819+/* ---------------------------------------------------------------------- */
1facf9fc 20820+
acd2b654
AM
20821+/*
20822+ * very dirty and complicated aufs ->atomic_open().
20823+ * aufs_atomic_open()
20824+ * + au_aopen_or_create()
20825+ * + add_simple()
20826+ * + vfsub_atomic_open()
20827+ * + branch fs ->atomic_open()
20828+ * may call the actual 'open' for h_file
20829+ * + inc br_nfiles only if opened
20830+ * + au_aopen_no_open() or au_aopen_do_open()
20831+ *
20832+ * au_aopen_do_open()
20833+ * + finish_open()
20834+ * + au_do_aopen()
20835+ * + au_do_open() the body of all 'open'
20836+ * + au_do_open_nondir()
20837+ * set the passed h_file
20838+ *
20839+ * au_aopen_no_open()
20840+ * + finish_no_open()
20841+ */
20842+
b912730e 20843+struct aopen_node {
8b6a4947 20844+ struct hlist_bl_node hblist;
b912730e
AM
20845+ struct file *file, *h_file;
20846+};
20847+
20848+static int au_do_aopen(struct inode *inode, struct file *file)
20849+{
8b6a4947
AM
20850+ struct hlist_bl_head *aopen;
20851+ struct hlist_bl_node *pos;
b912730e
AM
20852+ struct aopen_node *node;
20853+ struct au_do_open_args args = {
8b6a4947
AM
20854+ .aopen = 1,
20855+ .open = au_do_open_nondir
b912730e
AM
20856+ };
20857+
20858+ aopen = &au_sbi(inode->i_sb)->si_aopen;
8b6a4947
AM
20859+ hlist_bl_lock(aopen);
20860+ hlist_bl_for_each_entry(node, pos, aopen, hblist)
b912730e
AM
20861+ if (node->file == file) {
20862+ args.h_file = node->h_file;
20863+ break;
20864+ }
8b6a4947 20865+ hlist_bl_unlock(aopen);
b912730e
AM
20866+ /* AuDebugOn(!args.h_file); */
20867+
20868+ return au_do_open(file, &args);
20869+}
20870+
acd2b654
AM
20871+static int au_aopen_do_open(struct file *file, struct dentry *dentry,
20872+ struct aopen_node *aopen_node)
20873+{
20874+ int err;
20875+ struct hlist_bl_head *aopen;
20876+
20877+ AuLabel(here);
20878+ aopen = &au_sbi(dentry->d_sb)->si_aopen;
20879+ au_hbl_add(&aopen_node->hblist, aopen);
20880+ err = finish_open(file, dentry, au_do_aopen);
20881+ au_hbl_del(&aopen_node->hblist, aopen);
20882+ /* AuDbgFile(file); */
20883+ AuDbg("%pd%s%s\n", dentry,
20884+ (file->f_mode & FMODE_CREATED) ? " created" : "",
20885+ (file->f_mode & FMODE_OPENED) ? " opened" : "");
20886+
20887+ AuTraceErr(err);
20888+ return err;
20889+}
20890+
20891+static int au_aopen_no_open(struct file *file, struct dentry *dentry)
20892+{
20893+ int err;
20894+
20895+ AuLabel(here);
20896+ dget(dentry);
20897+ err = finish_no_open(file, dentry);
20898+
20899+ AuTraceErr(err);
20900+ return err;
20901+}
20902+
b912730e
AM
20903+static int aufs_atomic_open(struct inode *dir, struct dentry *dentry,
20904+ struct file *file, unsigned int open_flag,
acd2b654 20905+ umode_t create_mode)
b912730e 20906+{
acd2b654 20907+ int err, did_open;
5afbbe0d 20908+ unsigned int lkup_flags;
acd2b654
AM
20909+ aufs_bindex_t bindex;
20910+ struct super_block *sb;
f0c0a007 20911+ struct dentry *parent, *d;
b912730e
AM
20912+ struct vfsub_aopen_args args = {
20913+ .open_flag = open_flag,
acd2b654 20914+ .create_mode = create_mode
b912730e
AM
20915+ };
20916+ struct aopen_node aopen_node = {
20917+ .file = file
20918+ };
20919+
20920+ IMustLock(dir);
5afbbe0d 20921+ AuDbg("open_flag 0%o\n", open_flag);
b912730e
AM
20922+ AuDbgDentry(dentry);
20923+
20924+ err = 0;
20925+ if (!au_di(dentry)) {
5afbbe0d
AM
20926+ lkup_flags = LOOKUP_OPEN;
20927+ if (open_flag & O_CREAT)
20928+ lkup_flags |= LOOKUP_CREATE;
20929+ d = aufs_lookup(dir, dentry, lkup_flags);
b912730e
AM
20930+ if (IS_ERR(d)) {
20931+ err = PTR_ERR(d);
5afbbe0d 20932+ AuTraceErr(err);
b912730e
AM
20933+ goto out;
20934+ } else if (d) {
20935+ /*
20936+ * obsoleted dentry found.
20937+ * another error will be returned later.
20938+ */
20939+ d_drop(d);
b912730e 20940+ AuDbgDentry(d);
5afbbe0d 20941+ dput(d);
b912730e
AM
20942+ }
20943+ AuDbgDentry(dentry);
20944+ }
20945+
20946+ if (d_is_positive(dentry)
20947+ || d_unhashed(dentry)
20948+ || d_unlinked(dentry)
acd2b654
AM
20949+ || !(open_flag & O_CREAT)) {
20950+ err = au_aopen_no_open(file, dentry);
20951+ goto out; /* success */
20952+ }
b912730e
AM
20953+
20954+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
20955+ if (unlikely(err))
20956+ goto out;
20957+
acd2b654 20958+ sb = dentry->d_sb;
b912730e
AM
20959+ parent = dentry->d_parent; /* dir is locked */
20960+ di_write_lock_parent(parent);
5afbbe0d 20961+ err = au_lkup_dentry(dentry, /*btop*/0, AuLkup_ALLOW_NEG);
acd2b654
AM
20962+ if (unlikely(err < 0))
20963+ goto out_parent;
b912730e
AM
20964+
20965+ AuDbgDentry(dentry);
acd2b654
AM
20966+ if (d_is_positive(dentry)) {
20967+ err = au_aopen_no_open(file, dentry);
20968+ goto out_parent; /* success */
20969+ }
b912730e 20970+
acd2b654 20971+ args.file = alloc_empty_file(file->f_flags, current_cred());
b912730e
AM
20972+ err = PTR_ERR(args.file);
20973+ if (IS_ERR(args.file))
acd2b654 20974+ goto out_parent;
b912730e 20975+
acd2b654 20976+ bindex = au_dbtop(dentry);
b912730e
AM
20977+ err = au_aopen_or_create(dir, dentry, &args);
20978+ AuTraceErr(err);
20979+ AuDbgFile(args.file);
acd2b654
AM
20980+ file->f_mode = args.file->f_mode & ~FMODE_OPENED;
20981+ did_open = !!(args.file->f_mode & FMODE_OPENED);
20982+ if (!did_open) {
20983+ fput(args.file);
20984+ args.file = NULL;
b912730e 20985+ }
8b6a4947
AM
20986+ di_write_unlock(parent);
20987+ di_write_unlock(dentry);
acd2b654
AM
20988+ if (unlikely(err < 0)) {
20989+ if (args.file)
20990+ fput(args.file);
20991+ goto out_sb;
b912730e 20992+ }
b912730e 20993+
acd2b654
AM
20994+ if (!did_open)
20995+ err = au_aopen_no_open(file, dentry);
8b6a4947 20996+ else {
acd2b654
AM
20997+ aopen_node.h_file = args.file;
20998+ err = au_aopen_do_open(file, dentry, &aopen_node);
8b6a4947 20999+ }
acd2b654
AM
21000+ if (unlikely(err < 0)) {
21001+ if (args.file)
21002+ fput(args.file);
21003+ if (did_open)
21004+ au_lcnt_dec(&args.br->br_nfiles);
b912730e 21005+ }
acd2b654
AM
21006+ goto out_sb; /* success */
21007+
21008+out_parent:
21009+ di_write_unlock(parent);
21010+ di_write_unlock(dentry);
21011+out_sb:
21012+ si_read_unlock(sb);
b912730e 21013+out:
b912730e 21014+ AuTraceErr(err);
acd2b654 21015+ AuDbgFile(file);
b912730e
AM
21016+ return err;
21017+}
21018+
21019+
21020+/* ---------------------------------------------------------------------- */
21021+
4a4d8108
AM
21022+static int au_wr_dir_cpup(struct dentry *dentry, struct dentry *parent,
21023+ const unsigned char add_entry, aufs_bindex_t bcpup,
5afbbe0d 21024+ aufs_bindex_t btop)
4a4d8108
AM
21025+{
21026+ int err;
21027+ struct dentry *h_parent;
21028+ struct inode *h_dir;
1facf9fc 21029+
027c5e7a 21030+ if (add_entry)
5527c038 21031+ IMustLock(d_inode(parent));
027c5e7a 21032+ else
4a4d8108
AM
21033+ di_write_lock_parent(parent);
21034+
21035+ err = 0;
21036+ if (!au_h_dptr(parent, bcpup)) {
5afbbe0d 21037+ if (btop > bcpup)
c2b27bf2 21038+ err = au_cpup_dirs(dentry, bcpup);
5afbbe0d 21039+ else if (btop < bcpup)
4a4d8108
AM
21040+ err = au_cpdown_dirs(dentry, bcpup);
21041+ else
c2b27bf2 21042+ BUG();
4a4d8108 21043+ }
38d290e6 21044+ if (!err && add_entry && !au_ftest_wrdir(add_entry, TMPFILE)) {
4a4d8108 21045+ h_parent = au_h_dptr(parent, bcpup);
5527c038 21046+ h_dir = d_inode(h_parent);
be118d29 21047+ inode_lock_shared_nested(h_dir, AuLsc_I_PARENT);
7e9cd9fe 21048+ err = au_lkup_neg(dentry, bcpup, /*wh*/0);
4a4d8108 21049+ /* todo: no unlock here */
3c1bdaff 21050+ inode_unlock_shared(h_dir);
027c5e7a
AM
21051+
21052+ AuDbg("bcpup %d\n", bcpup);
21053+ if (!err) {
5527c038 21054+ if (d_really_is_negative(dentry))
5afbbe0d 21055+ au_set_h_dptr(dentry, btop, NULL);
4a4d8108
AM
21056+ au_update_dbrange(dentry, /*do_put_zero*/0);
21057+ }
1308ab2a 21058+ }
1facf9fc 21059+
4a4d8108
AM
21060+ if (!add_entry)
21061+ di_write_unlock(parent);
21062+ if (!err)
21063+ err = bcpup; /* success */
1308ab2a 21064+
027c5e7a 21065+ AuTraceErr(err);
4a4d8108
AM
21066+ return err;
21067+}
1facf9fc 21068+
4a4d8108
AM
21069+/*
21070+ * decide the branch and the parent dir where we will create a new entry.
21071+ * returns new bindex or an error.
21072+ * copyup the parent dir if needed.
21073+ */
21074+int au_wr_dir(struct dentry *dentry, struct dentry *src_dentry,
21075+ struct au_wr_dir_args *args)
21076+{
21077+ int err;
392086de 21078+ unsigned int flags;
5afbbe0d 21079+ aufs_bindex_t bcpup, btop, src_btop;
86dc4139
AM
21080+ const unsigned char add_entry
21081+ = au_ftest_wrdir(args->flags, ADD_ENTRY)
38d290e6 21082+ | au_ftest_wrdir(args->flags, TMPFILE);
4a4d8108
AM
21083+ struct super_block *sb;
21084+ struct dentry *parent;
21085+ struct au_sbinfo *sbinfo;
1facf9fc 21086+
4a4d8108
AM
21087+ sb = dentry->d_sb;
21088+ sbinfo = au_sbi(sb);
21089+ parent = dget_parent(dentry);
5afbbe0d
AM
21090+ btop = au_dbtop(dentry);
21091+ bcpup = btop;
4a4d8108
AM
21092+ if (args->force_btgt < 0) {
21093+ if (src_dentry) {
5afbbe0d
AM
21094+ src_btop = au_dbtop(src_dentry);
21095+ if (src_btop < btop)
21096+ bcpup = src_btop;
4a4d8108 21097+ } else if (add_entry) {
392086de
AM
21098+ flags = 0;
21099+ if (au_ftest_wrdir(args->flags, ISDIR))
21100+ au_fset_wbr(flags, DIR);
21101+ err = AuWbrCreate(sbinfo, dentry, flags);
4a4d8108
AM
21102+ bcpup = err;
21103+ }
1facf9fc 21104+
5527c038 21105+ if (bcpup < 0 || au_test_ro(sb, bcpup, d_inode(dentry))) {
4a4d8108
AM
21106+ if (add_entry)
21107+ err = AuWbrCopyup(sbinfo, dentry);
21108+ else {
21109+ if (!IS_ROOT(dentry)) {
21110+ di_read_lock_parent(parent, !AuLock_IR);
21111+ err = AuWbrCopyup(sbinfo, dentry);
21112+ di_read_unlock(parent, !AuLock_IR);
21113+ } else
21114+ err = AuWbrCopyup(sbinfo, dentry);
21115+ }
21116+ bcpup = err;
21117+ if (unlikely(err < 0))
21118+ goto out;
21119+ }
21120+ } else {
21121+ bcpup = args->force_btgt;
5527c038 21122+ AuDebugOn(au_test_ro(sb, bcpup, d_inode(dentry)));
1308ab2a 21123+ }
027c5e7a 21124+
5afbbe0d 21125+ AuDbg("btop %d, bcpup %d\n", btop, bcpup);
4a4d8108 21126+ err = bcpup;
5afbbe0d 21127+ if (bcpup == btop)
4a4d8108 21128+ goto out; /* success */
4a4d8108
AM
21129+
21130+ /* copyup the new parent into the branch we process */
5afbbe0d 21131+ err = au_wr_dir_cpup(dentry, parent, add_entry, bcpup, btop);
027c5e7a 21132+ if (err >= 0) {
5527c038 21133+ if (d_really_is_negative(dentry)) {
5afbbe0d
AM
21134+ au_set_h_dptr(dentry, btop, NULL);
21135+ au_set_dbtop(dentry, bcpup);
21136+ au_set_dbbot(dentry, bcpup);
027c5e7a 21137+ }
38d290e6
JR
21138+ AuDebugOn(add_entry
21139+ && !au_ftest_wrdir(args->flags, TMPFILE)
21140+ && !au_h_dptr(dentry, bcpup));
027c5e7a 21141+ }
86dc4139
AM
21142+
21143+out:
21144+ dput(parent);
21145+ return err;
21146+}
21147+
21148+/* ---------------------------------------------------------------------- */
21149+
21150+void au_pin_hdir_unlock(struct au_pin *p)
21151+{
21152+ if (p->hdir)
5afbbe0d 21153+ au_hn_inode_unlock(p->hdir);
86dc4139
AM
21154+}
21155+
c1595e42 21156+int au_pin_hdir_lock(struct au_pin *p)
86dc4139
AM
21157+{
21158+ int err;
21159+
21160+ err = 0;
21161+ if (!p->hdir)
21162+ goto out;
21163+
21164+ /* even if an error happens later, keep this lock */
5afbbe0d 21165+ au_hn_inode_lock_nested(p->hdir, p->lsc_hi);
86dc4139
AM
21166+
21167+ err = -EBUSY;
5527c038 21168+ if (unlikely(p->hdir->hi_inode != d_inode(p->h_parent)))
86dc4139
AM
21169+ goto out;
21170+
21171+ err = 0;
21172+ if (p->h_dentry)
21173+ err = au_h_verify(p->h_dentry, p->udba, p->hdir->hi_inode,
21174+ p->h_parent, p->br);
21175+
21176+out:
21177+ return err;
21178+}
21179+
21180+int au_pin_hdir_relock(struct au_pin *p)
21181+{
21182+ int err, i;
21183+ struct inode *h_i;
21184+ struct dentry *h_d[] = {
21185+ p->h_dentry,
21186+ p->h_parent
21187+ };
21188+
21189+ err = au_pin_hdir_lock(p);
21190+ if (unlikely(err))
21191+ goto out;
21192+
21193+ for (i = 0; !err && i < sizeof(h_d)/sizeof(*h_d); i++) {
21194+ if (!h_d[i])
21195+ continue;
5527c038
JR
21196+ if (d_is_positive(h_d[i])) {
21197+ h_i = d_inode(h_d[i]);
86dc4139 21198+ err = !h_i->i_nlink;
5527c038 21199+ }
86dc4139
AM
21200+ }
21201+
21202+out:
21203+ return err;
21204+}
21205+
5afbbe0d 21206+static void au_pin_hdir_set_owner(struct au_pin *p, struct task_struct *task)
86dc4139 21207+{
eca34b5c 21208+ atomic_long_set(&p->hdir->hi_inode->i_rwsem.owner, (long)task);
86dc4139
AM
21209+}
21210+
21211+void au_pin_hdir_acquire_nest(struct au_pin *p)
21212+{
21213+ if (p->hdir) {
5afbbe0d 21214+ rwsem_acquire_nest(&p->hdir->hi_inode->i_rwsem.dep_map,
86dc4139
AM
21215+ p->lsc_hi, 0, NULL, _RET_IP_);
21216+ au_pin_hdir_set_owner(p, current);
21217+ }
dece6358 21218+}
1facf9fc 21219+
86dc4139
AM
21220+void au_pin_hdir_release(struct au_pin *p)
21221+{
21222+ if (p->hdir) {
21223+ au_pin_hdir_set_owner(p, p->task);
5afbbe0d 21224+ rwsem_release(&p->hdir->hi_inode->i_rwsem.dep_map, 1, _RET_IP_);
86dc4139
AM
21225+ }
21226+}
1308ab2a 21227+
4a4d8108 21228+struct dentry *au_pinned_h_parent(struct au_pin *pin)
1308ab2a 21229+{
4a4d8108
AM
21230+ if (pin && pin->parent)
21231+ return au_h_dptr(pin->parent, pin->bindex);
21232+ return NULL;
dece6358 21233+}
1facf9fc 21234+
4a4d8108 21235+void au_unpin(struct au_pin *p)
dece6358 21236+{
86dc4139
AM
21237+ if (p->hdir)
21238+ au_pin_hdir_unlock(p);
e49829fe 21239+ if (p->h_mnt && au_ftest_pin(p->flags, MNT_WRITE))
b4510431 21240+ vfsub_mnt_drop_write(p->h_mnt);
4a4d8108
AM
21241+ if (!p->hdir)
21242+ return;
1facf9fc 21243+
4a4d8108
AM
21244+ if (!au_ftest_pin(p->flags, DI_LOCKED))
21245+ di_read_unlock(p->parent, AuLock_IR);
21246+ iput(p->hdir->hi_inode);
21247+ dput(p->parent);
21248+ p->parent = NULL;
21249+ p->hdir = NULL;
21250+ p->h_mnt = NULL;
86dc4139 21251+ /* do not clear p->task */
4a4d8108 21252+}
1308ab2a 21253+
4a4d8108
AM
21254+int au_do_pin(struct au_pin *p)
21255+{
21256+ int err;
21257+ struct super_block *sb;
4a4d8108
AM
21258+ struct inode *h_dir;
21259+
21260+ err = 0;
21261+ sb = p->dentry->d_sb;
86dc4139 21262+ p->br = au_sbr(sb, p->bindex);
4a4d8108
AM
21263+ if (IS_ROOT(p->dentry)) {
21264+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
86dc4139 21265+ p->h_mnt = au_br_mnt(p->br);
b4510431 21266+ err = vfsub_mnt_want_write(p->h_mnt);
4a4d8108
AM
21267+ if (unlikely(err)) {
21268+ au_fclr_pin(p->flags, MNT_WRITE);
21269+ goto out_err;
21270+ }
21271+ }
dece6358 21272+ goto out;
1facf9fc 21273+ }
21274+
86dc4139 21275+ p->h_dentry = NULL;
5afbbe0d 21276+ if (p->bindex <= au_dbbot(p->dentry))
86dc4139 21277+ p->h_dentry = au_h_dptr(p->dentry, p->bindex);
dece6358 21278+
4a4d8108
AM
21279+ p->parent = dget_parent(p->dentry);
21280+ if (!au_ftest_pin(p->flags, DI_LOCKED))
21281+ di_read_lock(p->parent, AuLock_IR, p->lsc_di);
dece6358 21282+
4a4d8108 21283+ h_dir = NULL;
86dc4139 21284+ p->h_parent = au_h_dptr(p->parent, p->bindex);
5527c038 21285+ p->hdir = au_hi(d_inode(p->parent), p->bindex);
4a4d8108
AM
21286+ if (p->hdir)
21287+ h_dir = p->hdir->hi_inode;
dece6358 21288+
b752ccd1
AM
21289+ /*
21290+ * udba case, or
21291+ * if DI_LOCKED is not set, then p->parent may be different
21292+ * and h_parent can be NULL.
21293+ */
86dc4139 21294+ if (unlikely(!p->hdir || !h_dir || !p->h_parent)) {
e49829fe 21295+ err = -EBUSY;
4a4d8108
AM
21296+ if (!au_ftest_pin(p->flags, DI_LOCKED))
21297+ di_read_unlock(p->parent, AuLock_IR);
21298+ dput(p->parent);
21299+ p->parent = NULL;
21300+ goto out_err;
21301+ }
1308ab2a 21302+
4a4d8108 21303+ if (au_ftest_pin(p->flags, MNT_WRITE)) {
86dc4139 21304+ p->h_mnt = au_br_mnt(p->br);
b4510431 21305+ err = vfsub_mnt_want_write(p->h_mnt);
dece6358 21306+ if (unlikely(err)) {
4a4d8108 21307+ au_fclr_pin(p->flags, MNT_WRITE);
86dc4139
AM
21308+ if (!au_ftest_pin(p->flags, DI_LOCKED))
21309+ di_read_unlock(p->parent, AuLock_IR);
21310+ dput(p->parent);
21311+ p->parent = NULL;
21312+ goto out_err;
dece6358
AM
21313+ }
21314+ }
4a4d8108 21315+
86dc4139
AM
21316+ au_igrab(h_dir);
21317+ err = au_pin_hdir_lock(p);
21318+ if (!err)
21319+ goto out; /* success */
21320+
076b876e
AM
21321+ au_unpin(p);
21322+
4f0767ce 21323+out_err:
4a4d8108
AM
21324+ pr_err("err %d\n", err);
21325+ err = au_busy_or_stale();
4f0767ce 21326+out:
1facf9fc 21327+ return err;
21328+}
21329+
4a4d8108
AM
21330+void au_pin_init(struct au_pin *p, struct dentry *dentry,
21331+ aufs_bindex_t bindex, int lsc_di, int lsc_hi,
21332+ unsigned int udba, unsigned char flags)
21333+{
21334+ p->dentry = dentry;
21335+ p->udba = udba;
21336+ p->lsc_di = lsc_di;
21337+ p->lsc_hi = lsc_hi;
21338+ p->flags = flags;
21339+ p->bindex = bindex;
21340+
21341+ p->parent = NULL;
21342+ p->hdir = NULL;
21343+ p->h_mnt = NULL;
86dc4139
AM
21344+
21345+ p->h_dentry = NULL;
21346+ p->h_parent = NULL;
21347+ p->br = NULL;
21348+ p->task = current;
4a4d8108
AM
21349+}
21350+
21351+int au_pin(struct au_pin *pin, struct dentry *dentry, aufs_bindex_t bindex,
21352+ unsigned int udba, unsigned char flags)
21353+{
21354+ au_pin_init(pin, dentry, bindex, AuLsc_DI_PARENT, AuLsc_I_PARENT2,
21355+ udba, flags);
21356+ return au_do_pin(pin);
21357+}
21358+
dece6358
AM
21359+/* ---------------------------------------------------------------------- */
21360+
1308ab2a 21361+/*
4a4d8108
AM
21362+ * ->setattr() and ->getattr() are called in various cases.
21363+ * chmod, stat: dentry is revalidated.
21364+ * fchmod, fstat: file and dentry are not revalidated, additionally they may be
21365+ * unhashed.
21366+ * for ->setattr(), ia->ia_file is passed from ftruncate only.
1308ab2a 21367+ */
027c5e7a 21368+/* todo: consolidate with do_refresh() and simple_reval_dpath() */
c1595e42 21369+int au_reval_for_attr(struct dentry *dentry, unsigned int sigen)
1facf9fc 21370+{
4a4d8108 21371+ int err;
4a4d8108 21372+ struct dentry *parent;
1facf9fc 21373+
1308ab2a 21374+ err = 0;
027c5e7a 21375+ if (au_digen_test(dentry, sigen)) {
4a4d8108
AM
21376+ parent = dget_parent(dentry);
21377+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a 21378+ err = au_refresh_dentry(dentry, parent);
4a4d8108
AM
21379+ di_read_unlock(parent, AuLock_IR);
21380+ dput(parent);
dece6358 21381+ }
1facf9fc 21382+
4a4d8108 21383+ AuTraceErr(err);
1308ab2a 21384+ return err;
21385+}
dece6358 21386+
c1595e42
JR
21387+int au_pin_and_icpup(struct dentry *dentry, struct iattr *ia,
21388+ struct au_icpup_args *a)
1308ab2a 21389+{
21390+ int err;
4a4d8108 21391+ loff_t sz;
5afbbe0d 21392+ aufs_bindex_t btop, ibtop;
4a4d8108
AM
21393+ struct dentry *hi_wh, *parent;
21394+ struct inode *inode;
4a4d8108
AM
21395+ struct au_wr_dir_args wr_dir_args = {
21396+ .force_btgt = -1,
21397+ .flags = 0
21398+ };
21399+
2000de60 21400+ if (d_is_dir(dentry))
4a4d8108
AM
21401+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
21402+ /* plink or hi_wh() case */
5afbbe0d 21403+ btop = au_dbtop(dentry);
5527c038 21404+ inode = d_inode(dentry);
5afbbe0d
AM
21405+ ibtop = au_ibtop(inode);
21406+ if (btop != ibtop && !au_test_ro(inode->i_sb, ibtop, inode))
21407+ wr_dir_args.force_btgt = ibtop;
4a4d8108
AM
21408+ err = au_wr_dir(dentry, /*src_dentry*/NULL, &wr_dir_args);
21409+ if (unlikely(err < 0))
21410+ goto out;
21411+ a->btgt = err;
5afbbe0d 21412+ if (err != btop)
4a4d8108
AM
21413+ au_fset_icpup(a->flags, DID_CPUP);
21414+
21415+ err = 0;
21416+ a->pin_flags = AuPin_MNT_WRITE;
21417+ parent = NULL;
21418+ if (!IS_ROOT(dentry)) {
21419+ au_fset_pin(a->pin_flags, DI_LOCKED);
21420+ parent = dget_parent(dentry);
21421+ di_write_lock_parent(parent);
21422+ }
21423+
21424+ err = au_pin(&a->pin, dentry, a->btgt, a->udba, a->pin_flags);
21425+ if (unlikely(err))
21426+ goto out_parent;
21427+
4a4d8108 21428+ sz = -1;
5afbbe0d 21429+ a->h_path.dentry = au_h_dptr(dentry, btop);
5527c038 21430+ a->h_inode = d_inode(a->h_path.dentry);
c1595e42 21431+ if (ia && (ia->ia_valid & ATTR_SIZE)) {
be118d29 21432+ inode_lock_shared_nested(a->h_inode, AuLsc_I_CHILD);
c1595e42
JR
21433+ if (ia->ia_size < i_size_read(a->h_inode))
21434+ sz = ia->ia_size;
3c1bdaff 21435+ inode_unlock_shared(a->h_inode);
c1595e42 21436+ }
4a4d8108 21437+
4a4d8108 21438+ hi_wh = NULL;
027c5e7a 21439+ if (au_ftest_icpup(a->flags, DID_CPUP) && d_unlinked(dentry)) {
4a4d8108
AM
21440+ hi_wh = au_hi_wh(inode, a->btgt);
21441+ if (!hi_wh) {
c2b27bf2
AM
21442+ struct au_cp_generic cpg = {
21443+ .dentry = dentry,
21444+ .bdst = a->btgt,
21445+ .bsrc = -1,
21446+ .len = sz,
21447+ .pin = &a->pin
21448+ };
21449+ err = au_sio_cpup_wh(&cpg, /*file*/NULL);
4a4d8108
AM
21450+ if (unlikely(err))
21451+ goto out_unlock;
21452+ hi_wh = au_hi_wh(inode, a->btgt);
21453+ /* todo: revalidate hi_wh? */
21454+ }
21455+ }
21456+
21457+ if (parent) {
21458+ au_pin_set_parent_lflag(&a->pin, /*lflag*/0);
21459+ di_downgrade_lock(parent, AuLock_IR);
21460+ dput(parent);
21461+ parent = NULL;
21462+ }
21463+ if (!au_ftest_icpup(a->flags, DID_CPUP))
21464+ goto out; /* success */
21465+
21466+ if (!d_unhashed(dentry)) {
c2b27bf2
AM
21467+ struct au_cp_generic cpg = {
21468+ .dentry = dentry,
21469+ .bdst = a->btgt,
5afbbe0d 21470+ .bsrc = btop,
c2b27bf2
AM
21471+ .len = sz,
21472+ .pin = &a->pin,
21473+ .flags = AuCpup_DTIME | AuCpup_HOPEN
21474+ };
21475+ err = au_sio_cpup_simple(&cpg);
4a4d8108
AM
21476+ if (!err)
21477+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
21478+ } else if (!hi_wh)
21479+ a->h_path.dentry = au_h_dptr(dentry, a->btgt);
21480+ else
21481+ a->h_path.dentry = hi_wh; /* do not dget here */
1308ab2a 21482+
4f0767ce 21483+out_unlock:
5527c038 21484+ a->h_inode = d_inode(a->h_path.dentry);
86dc4139 21485+ if (!err)
dece6358 21486+ goto out; /* success */
4a4d8108 21487+ au_unpin(&a->pin);
4f0767ce 21488+out_parent:
4a4d8108
AM
21489+ if (parent) {
21490+ di_write_unlock(parent);
21491+ dput(parent);
21492+ }
4f0767ce 21493+out:
86dc4139 21494+ if (!err)
febd17d6 21495+ inode_lock_nested(a->h_inode, AuLsc_I_CHILD);
1facf9fc 21496+ return err;
21497+}
21498+
4a4d8108 21499+static int aufs_setattr(struct dentry *dentry, struct iattr *ia)
1facf9fc 21500+{
4a4d8108 21501+ int err;
523b37e3 21502+ struct inode *inode, *delegated;
4a4d8108
AM
21503+ struct super_block *sb;
21504+ struct file *file;
21505+ struct au_icpup_args *a;
1facf9fc 21506+
5527c038 21507+ inode = d_inode(dentry);
4a4d8108 21508+ IMustLock(inode);
dece6358 21509+
f2c43d5f
AM
21510+ err = setattr_prepare(dentry, ia);
21511+ if (unlikely(err))
21512+ goto out;
21513+
4a4d8108
AM
21514+ err = -ENOMEM;
21515+ a = kzalloc(sizeof(*a), GFP_NOFS);
21516+ if (unlikely(!a))
21517+ goto out;
1facf9fc 21518+
4a4d8108
AM
21519+ if (ia->ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
21520+ ia->ia_valid &= ~ATTR_MODE;
dece6358 21521+
4a4d8108
AM
21522+ file = NULL;
21523+ sb = dentry->d_sb;
e49829fe
JR
21524+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21525+ if (unlikely(err))
21526+ goto out_kfree;
21527+
4a4d8108
AM
21528+ if (ia->ia_valid & ATTR_FILE) {
21529+ /* currently ftruncate(2) only */
7e9cd9fe 21530+ AuDebugOn(!d_is_reg(dentry));
4a4d8108 21531+ file = ia->ia_file;
521ced18
JR
21532+ err = au_reval_and_lock_fdi(file, au_reopen_nondir, /*wlock*/1,
21533+ /*fi_lsc*/0);
4a4d8108
AM
21534+ if (unlikely(err))
21535+ goto out_si;
21536+ ia->ia_file = au_hf_top(file);
21537+ a->udba = AuOpt_UDBA_NONE;
21538+ } else {
21539+ /* fchmod() doesn't pass ia_file */
21540+ a->udba = au_opt_udba(sb);
027c5e7a
AM
21541+ di_write_lock_child(dentry);
21542+ /* no d_unlinked(), to set UDBA_NONE for root */
4a4d8108
AM
21543+ if (d_unhashed(dentry))
21544+ a->udba = AuOpt_UDBA_NONE;
4a4d8108
AM
21545+ if (a->udba != AuOpt_UDBA_NONE) {
21546+ AuDebugOn(IS_ROOT(dentry));
21547+ err = au_reval_for_attr(dentry, au_sigen(sb));
21548+ if (unlikely(err))
21549+ goto out_dentry;
21550+ }
dece6358 21551+ }
dece6358 21552+
4a4d8108
AM
21553+ err = au_pin_and_icpup(dentry, ia, a);
21554+ if (unlikely(err < 0))
21555+ goto out_dentry;
21556+ if (au_ftest_icpup(a->flags, DID_CPUP)) {
21557+ ia->ia_file = NULL;
21558+ ia->ia_valid &= ~ATTR_FILE;
1308ab2a 21559+ }
dece6358 21560+
4a4d8108
AM
21561+ a->h_path.mnt = au_sbr_mnt(sb, a->btgt);
21562+ if ((ia->ia_valid & (ATTR_MODE | ATTR_CTIME))
21563+ == (ATTR_MODE | ATTR_CTIME)) {
7eafdf33 21564+ err = security_path_chmod(&a->h_path, ia->ia_mode);
4a4d8108
AM
21565+ if (unlikely(err))
21566+ goto out_unlock;
21567+ } else if ((ia->ia_valid & (ATTR_UID | ATTR_GID))
21568+ && (ia->ia_valid & ATTR_CTIME)) {
86dc4139 21569+ err = security_path_chown(&a->h_path, ia->ia_uid, ia->ia_gid);
4a4d8108
AM
21570+ if (unlikely(err))
21571+ goto out_unlock;
21572+ }
dece6358 21573+
4a4d8108
AM
21574+ if (ia->ia_valid & ATTR_SIZE) {
21575+ struct file *f;
1308ab2a 21576+
953406b4 21577+ if (ia->ia_size < i_size_read(inode))
4a4d8108 21578+ /* unmap only */
953406b4 21579+ truncate_setsize(inode, ia->ia_size);
1308ab2a 21580+
4a4d8108
AM
21581+ f = NULL;
21582+ if (ia->ia_valid & ATTR_FILE)
21583+ f = ia->ia_file;
febd17d6 21584+ inode_unlock(a->h_inode);
4a4d8108 21585+ err = vfsub_trunc(&a->h_path, ia->ia_size, ia->ia_valid, f);
febd17d6 21586+ inode_lock_nested(a->h_inode, AuLsc_I_CHILD);
523b37e3
AM
21587+ } else {
21588+ delegated = NULL;
21589+ while (1) {
21590+ err = vfsub_notify_change(&a->h_path, ia, &delegated);
21591+ if (delegated) {
21592+ err = break_deleg_wait(&delegated);
21593+ if (!err)
21594+ continue;
21595+ }
21596+ break;
21597+ }
21598+ }
8cdd5066
JR
21599+ /*
21600+ * regardless aufs 'acl' option setting.
21601+ * why don't all acl-aware fs call this func from their ->setattr()?
21602+ */
21603+ if (!err && (ia->ia_valid & ATTR_MODE))
21604+ err = vfsub_acl_chmod(a->h_inode, ia->ia_mode);
4a4d8108
AM
21605+ if (!err)
21606+ au_cpup_attr_changeable(inode);
1308ab2a 21607+
4f0767ce 21608+out_unlock:
febd17d6 21609+ inode_unlock(a->h_inode);
4a4d8108 21610+ au_unpin(&a->pin);
027c5e7a 21611+ if (unlikely(err))
5afbbe0d 21612+ au_update_dbtop(dentry);
4f0767ce 21613+out_dentry:
4a4d8108
AM
21614+ di_write_unlock(dentry);
21615+ if (file) {
21616+ fi_write_unlock(file);
21617+ ia->ia_file = file;
21618+ ia->ia_valid |= ATTR_FILE;
21619+ }
4f0767ce 21620+out_si:
4a4d8108 21621+ si_read_unlock(sb);
e49829fe 21622+out_kfree:
9f237c51 21623+ au_kfree_rcu(a);
4f0767ce 21624+out:
4a4d8108
AM
21625+ AuTraceErr(err);
21626+ return err;
1facf9fc 21627+}
21628+
c1595e42
JR
21629+#if IS_ENABLED(CONFIG_AUFS_XATTR) || IS_ENABLED(CONFIG_FS_POSIX_ACL)
21630+static int au_h_path_to_set_attr(struct dentry *dentry,
21631+ struct au_icpup_args *a, struct path *h_path)
21632+{
21633+ int err;
21634+ struct super_block *sb;
21635+
21636+ sb = dentry->d_sb;
21637+ a->udba = au_opt_udba(sb);
21638+ /* no d_unlinked(), to set UDBA_NONE for root */
21639+ if (d_unhashed(dentry))
21640+ a->udba = AuOpt_UDBA_NONE;
21641+ if (a->udba != AuOpt_UDBA_NONE) {
21642+ AuDebugOn(IS_ROOT(dentry));
21643+ err = au_reval_for_attr(dentry, au_sigen(sb));
21644+ if (unlikely(err))
21645+ goto out;
21646+ }
21647+ err = au_pin_and_icpup(dentry, /*ia*/NULL, a);
21648+ if (unlikely(err < 0))
21649+ goto out;
21650+
21651+ h_path->dentry = a->h_path.dentry;
21652+ h_path->mnt = au_sbr_mnt(sb, a->btgt);
21653+
21654+out:
21655+ return err;
21656+}
21657+
f2c43d5f
AM
21658+ssize_t au_sxattr(struct dentry *dentry, struct inode *inode,
21659+ struct au_sxattr *arg)
c1595e42
JR
21660+{
21661+ int err;
21662+ struct path h_path;
21663+ struct super_block *sb;
21664+ struct au_icpup_args *a;
5afbbe0d 21665+ struct inode *h_inode;
c1595e42 21666+
c1595e42
JR
21667+ IMustLock(inode);
21668+
21669+ err = -ENOMEM;
21670+ a = kzalloc(sizeof(*a), GFP_NOFS);
21671+ if (unlikely(!a))
21672+ goto out;
21673+
21674+ sb = dentry->d_sb;
21675+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21676+ if (unlikely(err))
21677+ goto out_kfree;
21678+
21679+ h_path.dentry = NULL; /* silence gcc */
21680+ di_write_lock_child(dentry);
21681+ err = au_h_path_to_set_attr(dentry, a, &h_path);
21682+ if (unlikely(err))
21683+ goto out_di;
21684+
febd17d6 21685+ inode_unlock(a->h_inode);
c1595e42
JR
21686+ switch (arg->type) {
21687+ case AU_XATTR_SET:
5afbbe0d 21688+ AuDebugOn(d_is_negative(h_path.dentry));
c1595e42
JR
21689+ err = vfsub_setxattr(h_path.dentry,
21690+ arg->u.set.name, arg->u.set.value,
21691+ arg->u.set.size, arg->u.set.flags);
21692+ break;
c1595e42
JR
21693+ case AU_ACL_SET:
21694+ err = -EOPNOTSUPP;
5527c038 21695+ h_inode = d_inode(h_path.dentry);
c1595e42 21696+ if (h_inode->i_op->set_acl)
f2c43d5f 21697+ /* this will call posix_acl_update_mode */
c1595e42
JR
21698+ err = h_inode->i_op->set_acl(h_inode,
21699+ arg->u.acl_set.acl,
21700+ arg->u.acl_set.type);
21701+ break;
21702+ }
21703+ if (!err)
21704+ au_cpup_attr_timesizes(inode);
21705+
21706+ au_unpin(&a->pin);
21707+ if (unlikely(err))
5afbbe0d 21708+ au_update_dbtop(dentry);
c1595e42
JR
21709+
21710+out_di:
21711+ di_write_unlock(dentry);
21712+ si_read_unlock(sb);
21713+out_kfree:
9f237c51 21714+ au_kfree_rcu(a);
c1595e42
JR
21715+out:
21716+ AuTraceErr(err);
21717+ return err;
21718+}
21719+#endif
21720+
4a4d8108
AM
21721+static void au_refresh_iattr(struct inode *inode, struct kstat *st,
21722+ unsigned int nlink)
1facf9fc 21723+{
9dbd164d
AM
21724+ unsigned int n;
21725+
4a4d8108 21726+ inode->i_mode = st->mode;
86dc4139
AM
21727+ /* don't i_[ug]id_write() here */
21728+ inode->i_uid = st->uid;
21729+ inode->i_gid = st->gid;
4a4d8108
AM
21730+ inode->i_atime = st->atime;
21731+ inode->i_mtime = st->mtime;
21732+ inode->i_ctime = st->ctime;
1facf9fc 21733+
4a4d8108
AM
21734+ au_cpup_attr_nlink(inode, /*force*/0);
21735+ if (S_ISDIR(inode->i_mode)) {
9dbd164d
AM
21736+ n = inode->i_nlink;
21737+ n -= nlink;
21738+ n += st->nlink;
f6b6e03d 21739+ smp_mb(); /* for i_nlink */
7eafdf33 21740+ /* 0 can happen */
92d182d2 21741+ set_nlink(inode, n);
4a4d8108 21742+ }
1facf9fc 21743+
4a4d8108
AM
21744+ spin_lock(&inode->i_lock);
21745+ inode->i_blocks = st->blocks;
21746+ i_size_write(inode, st->size);
21747+ spin_unlock(&inode->i_lock);
1facf9fc 21748+}
21749+
c1595e42 21750+/*
f2c43d5f 21751+ * common routine for aufs_getattr() and au_getxattr().
c1595e42
JR
21752+ * returns zero or negative (an error).
21753+ * @dentry will be read-locked in success.
21754+ */
a2654f78
AM
21755+int au_h_path_getattr(struct dentry *dentry, int force, struct path *h_path,
21756+ int locked)
1facf9fc 21757+{
4a4d8108 21758+ int err;
076b876e 21759+ unsigned int mnt_flags, sigen;
c1595e42 21760+ unsigned char udba_none;
4a4d8108 21761+ aufs_bindex_t bindex;
4a4d8108
AM
21762+ struct super_block *sb, *h_sb;
21763+ struct inode *inode;
1facf9fc 21764+
c1595e42
JR
21765+ h_path->mnt = NULL;
21766+ h_path->dentry = NULL;
21767+
21768+ err = 0;
4a4d8108 21769+ sb = dentry->d_sb;
4a4d8108
AM
21770+ mnt_flags = au_mntflags(sb);
21771+ udba_none = !!au_opt_test(mnt_flags, UDBA_NONE);
1facf9fc 21772+
a2654f78
AM
21773+ if (unlikely(locked))
21774+ goto body; /* skip locking dinfo */
21775+
4a4d8108 21776+ /* support fstat(2) */
027c5e7a 21777+ if (!d_unlinked(dentry) && !udba_none) {
076b876e 21778+ sigen = au_sigen(sb);
027c5e7a
AM
21779+ err = au_digen_test(dentry, sigen);
21780+ if (!err) {
4a4d8108 21781+ di_read_lock_child(dentry, AuLock_IR);
027c5e7a 21782+ err = au_dbrange_test(dentry);
c1595e42
JR
21783+ if (unlikely(err)) {
21784+ di_read_unlock(dentry, AuLock_IR);
21785+ goto out;
21786+ }
027c5e7a 21787+ } else {
4a4d8108
AM
21788+ AuDebugOn(IS_ROOT(dentry));
21789+ di_write_lock_child(dentry);
027c5e7a
AM
21790+ err = au_dbrange_test(dentry);
21791+ if (!err)
21792+ err = au_reval_for_attr(dentry, sigen);
c1595e42
JR
21793+ if (!err)
21794+ di_downgrade_lock(dentry, AuLock_IR);
21795+ else {
21796+ di_write_unlock(dentry);
21797+ goto out;
21798+ }
4a4d8108
AM
21799+ }
21800+ } else
21801+ di_read_lock_child(dentry, AuLock_IR);
1facf9fc 21802+
a2654f78 21803+body:
5527c038 21804+ inode = d_inode(dentry);
5afbbe0d 21805+ bindex = au_ibtop(inode);
c1595e42
JR
21806+ h_path->mnt = au_sbr_mnt(sb, bindex);
21807+ h_sb = h_path->mnt->mnt_sb;
21808+ if (!force
21809+ && !au_test_fs_bad_iattr(h_sb)
21810+ && udba_none)
21811+ goto out; /* success */
1facf9fc 21812+
5afbbe0d 21813+ if (au_dbtop(dentry) == bindex)
c1595e42 21814+ h_path->dentry = au_h_dptr(dentry, bindex);
4a4d8108 21815+ else if (au_opt_test(mnt_flags, PLINK) && au_plink_test(inode)) {
c1595e42
JR
21816+ h_path->dentry = au_plink_lkup(inode, bindex);
21817+ if (IS_ERR(h_path->dentry))
21818+ /* pretending success */
21819+ h_path->dentry = NULL;
21820+ else
21821+ dput(h_path->dentry);
4a4d8108 21822+ }
c1595e42
JR
21823+
21824+out:
21825+ return err;
21826+}
21827+
521ced18
JR
21828+static int aufs_getattr(const struct path *path, struct kstat *st,
21829+ u32 request, unsigned int query)
c1595e42
JR
21830+{
21831+ int err;
21832+ unsigned char positive;
21833+ struct path h_path;
521ced18 21834+ struct dentry *dentry;
c1595e42
JR
21835+ struct inode *inode;
21836+ struct super_block *sb;
21837+
521ced18 21838+ dentry = path->dentry;
5527c038 21839+ inode = d_inode(dentry);
c1595e42
JR
21840+ sb = dentry->d_sb;
21841+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
21842+ if (unlikely(err))
21843+ goto out;
a2654f78 21844+ err = au_h_path_getattr(dentry, /*force*/0, &h_path, /*locked*/0);
c1595e42
JR
21845+ if (unlikely(err))
21846+ goto out_si;
c06a8ce3 21847+ if (unlikely(!h_path.dentry))
c1595e42 21848+ /* illegally overlapped or something */
4a4d8108
AM
21849+ goto out_fill; /* pretending success */
21850+
5527c038 21851+ positive = d_is_positive(h_path.dentry);
4a4d8108 21852+ if (positive)
521ced18
JR
21853+ /* no vfsub version */
21854+ err = vfs_getattr(&h_path, st, request, query);
4a4d8108
AM
21855+ if (!err) {
21856+ if (positive)
c06a8ce3 21857+ au_refresh_iattr(inode, st,
5527c038 21858+ d_inode(h_path.dentry)->i_nlink);
4a4d8108 21859+ goto out_fill; /* success */
1facf9fc 21860+ }
7f207e10 21861+ AuTraceErr(err);
c1595e42 21862+ goto out_di;
4a4d8108 21863+
4f0767ce 21864+out_fill:
4a4d8108 21865+ generic_fillattr(inode, st);
c1595e42 21866+out_di:
4a4d8108 21867+ di_read_unlock(dentry, AuLock_IR);
c1595e42 21868+out_si:
4a4d8108 21869+ si_read_unlock(sb);
7f207e10
AM
21870+out:
21871+ AuTraceErr(err);
4a4d8108 21872+ return err;
1facf9fc 21873+}
21874+
21875+/* ---------------------------------------------------------------------- */
21876+
febd17d6
JR
21877+static const char *aufs_get_link(struct dentry *dentry, struct inode *inode,
21878+ struct delayed_call *done)
4a4d8108 21879+{
c2c0f25c 21880+ const char *ret;
c2c0f25c 21881+ struct dentry *h_dentry;
febd17d6 21882+ struct inode *h_inode;
4a4d8108 21883+ int err;
c2c0f25c 21884+ aufs_bindex_t bindex;
1facf9fc 21885+
79b8bda9 21886+ ret = NULL; /* suppress a warning */
febd17d6
JR
21887+ err = -ECHILD;
21888+ if (!dentry)
21889+ goto out;
21890+
027c5e7a
AM
21891+ err = aufs_read_lock(dentry, AuLock_IR | AuLock_GEN);
21892+ if (unlikely(err))
c2c0f25c 21893+ goto out;
027c5e7a
AM
21894+
21895+ err = au_d_hashed_positive(dentry);
c2c0f25c
AM
21896+ if (unlikely(err))
21897+ goto out_unlock;
21898+
21899+ err = -EINVAL;
21900+ inode = d_inode(dentry);
5afbbe0d 21901+ bindex = au_ibtop(inode);
c2c0f25c 21902+ h_inode = au_h_iptr(inode, bindex);
febd17d6 21903+ if (unlikely(!h_inode->i_op->get_link))
c2c0f25c
AM
21904+ goto out_unlock;
21905+
21906+ err = -EBUSY;
21907+ h_dentry = NULL;
5afbbe0d 21908+ if (au_dbtop(dentry) <= bindex) {
c2c0f25c
AM
21909+ h_dentry = au_h_dptr(dentry, bindex);
21910+ if (h_dentry)
21911+ dget(h_dentry);
027c5e7a 21912+ }
c2c0f25c
AM
21913+ if (!h_dentry) {
21914+ h_dentry = d_find_any_alias(h_inode);
21915+ if (IS_ERR(h_dentry)) {
21916+ err = PTR_ERR(h_dentry);
febd17d6 21917+ goto out_unlock;
c2c0f25c
AM
21918+ }
21919+ }
21920+ if (unlikely(!h_dentry))
febd17d6 21921+ goto out_unlock;
1facf9fc 21922+
c2c0f25c 21923+ err = 0;
062440b3 21924+ AuDbg("%ps\n", h_inode->i_op->get_link);
c2c0f25c 21925+ AuDbgDentry(h_dentry);
f2c43d5f 21926+ ret = vfs_get_link(h_dentry, done);
c2c0f25c 21927+ dput(h_dentry);
febd17d6
JR
21928+ if (IS_ERR(ret))
21929+ err = PTR_ERR(ret);
c2c0f25c 21930+
c2c0f25c
AM
21931+out_unlock:
21932+ aufs_read_unlock(dentry, AuLock_IR);
4f0767ce 21933+out:
c2c0f25c
AM
21934+ if (unlikely(err))
21935+ ret = ERR_PTR(err);
21936+ AuTraceErrPtr(ret);
21937+ return ret;
4a4d8108 21938+}
1facf9fc 21939+
4a4d8108 21940+/* ---------------------------------------------------------------------- */
1facf9fc 21941+
e2f27e51
AM
21942+static int au_is_special(struct inode *inode)
21943+{
21944+ return (inode->i_mode & (S_IFBLK | S_IFCHR | S_IFIFO | S_IFSOCK));
21945+}
21946+
acd2b654
AM
21947+static int aufs_update_time(struct inode *inode, struct timespec64 *ts,
21948+ int flags)
4a4d8108 21949+{
0c3ec466 21950+ int err;
e2f27e51 21951+ aufs_bindex_t bindex;
0c3ec466
AM
21952+ struct super_block *sb;
21953+ struct inode *h_inode;
e2f27e51 21954+ struct vfsmount *h_mnt;
0c3ec466
AM
21955+
21956+ sb = inode->i_sb;
e2f27e51
AM
21957+ WARN_ONCE((flags & S_ATIME) && !IS_NOATIME(inode),
21958+ "unexpected s_flags 0x%lx", sb->s_flags);
21959+
0c3ec466
AM
21960+ /* mmap_sem might be acquired already, cf. aufs_mmap() */
21961+ lockdep_off();
21962+ si_read_lock(sb, AuLock_FLUSH);
21963+ ii_write_lock_child(inode);
e2f27e51
AM
21964+
21965+ err = 0;
21966+ bindex = au_ibtop(inode);
21967+ h_inode = au_h_iptr(inode, bindex);
21968+ if (!au_test_ro(sb, bindex, inode)) {
21969+ h_mnt = au_sbr_mnt(sb, bindex);
21970+ err = vfsub_mnt_want_write(h_mnt);
21971+ if (!err) {
21972+ err = vfsub_update_time(h_inode, ts, flags);
21973+ vfsub_mnt_drop_write(h_mnt);
21974+ }
21975+ } else if (au_is_special(h_inode)) {
21976+ /*
21977+ * Never copy-up here.
21978+ * These special files may already be opened and used for
21979+ * communicating. If we copied it up, then the communication
21980+ * would be corrupted.
21981+ */
21982+ AuWarn1("timestamps for i%lu are ignored "
21983+ "since it is on readonly branch (hi%lu).\n",
21984+ inode->i_ino, h_inode->i_ino);
21985+ } else if (flags & ~S_ATIME) {
21986+ err = -EIO;
21987+ AuIOErr1("unexpected flags 0x%x\n", flags);
21988+ AuDebugOn(1);
21989+ }
21990+
38d290e6
JR
21991+ if (!err)
21992+ au_cpup_attr_timesizes(inode);
0c3ec466
AM
21993+ ii_write_unlock(inode);
21994+ si_read_unlock(sb);
21995+ lockdep_on();
38d290e6
JR
21996+
21997+ if (!err && (flags & S_VERSION))
21998+ inode_inc_iversion(inode);
21999+
0c3ec466 22000+ return err;
4a4d8108 22001+}
1facf9fc 22002+
4a4d8108 22003+/* ---------------------------------------------------------------------- */
1308ab2a 22004+
b95c5147
AM
22005+/* no getattr version will be set by module.c:aufs_init() */
22006+struct inode_operations aufs_iop_nogetattr[AuIop_Last],
22007+ aufs_iop[] = {
22008+ [AuIop_SYMLINK] = {
22009+ .permission = aufs_permission,
c1595e42 22010+#ifdef CONFIG_FS_POSIX_ACL
b95c5147
AM
22011+ .get_acl = aufs_get_acl,
22012+ .set_acl = aufs_set_acl, /* unsupport for symlink? */
c1595e42
JR
22013+#endif
22014+
b95c5147
AM
22015+ .setattr = aufs_setattr,
22016+ .getattr = aufs_getattr,
0c3ec466 22017+
c1595e42 22018+#ifdef CONFIG_AUFS_XATTR
b95c5147 22019+ .listxattr = aufs_listxattr,
c1595e42
JR
22020+#endif
22021+
febd17d6 22022+ .get_link = aufs_get_link,
0c3ec466 22023+
b95c5147
AM
22024+ /* .update_time = aufs_update_time */
22025+ },
22026+ [AuIop_DIR] = {
22027+ .create = aufs_create,
22028+ .lookup = aufs_lookup,
22029+ .link = aufs_link,
22030+ .unlink = aufs_unlink,
22031+ .symlink = aufs_symlink,
22032+ .mkdir = aufs_mkdir,
22033+ .rmdir = aufs_rmdir,
22034+ .mknod = aufs_mknod,
22035+ .rename = aufs_rename,
22036+
22037+ .permission = aufs_permission,
c1595e42 22038+#ifdef CONFIG_FS_POSIX_ACL
b95c5147
AM
22039+ .get_acl = aufs_get_acl,
22040+ .set_acl = aufs_set_acl,
c1595e42
JR
22041+#endif
22042+
b95c5147
AM
22043+ .setattr = aufs_setattr,
22044+ .getattr = aufs_getattr,
0c3ec466 22045+
c1595e42 22046+#ifdef CONFIG_AUFS_XATTR
b95c5147 22047+ .listxattr = aufs_listxattr,
c1595e42
JR
22048+#endif
22049+
b95c5147
AM
22050+ .update_time = aufs_update_time,
22051+ .atomic_open = aufs_atomic_open,
22052+ .tmpfile = aufs_tmpfile
22053+ },
22054+ [AuIop_OTHER] = {
22055+ .permission = aufs_permission,
c1595e42 22056+#ifdef CONFIG_FS_POSIX_ACL
b95c5147
AM
22057+ .get_acl = aufs_get_acl,
22058+ .set_acl = aufs_set_acl,
c1595e42
JR
22059+#endif
22060+
b95c5147
AM
22061+ .setattr = aufs_setattr,
22062+ .getattr = aufs_getattr,
0c3ec466 22063+
c1595e42 22064+#ifdef CONFIG_AUFS_XATTR
b95c5147 22065+ .listxattr = aufs_listxattr,
c1595e42
JR
22066+#endif
22067+
b95c5147
AM
22068+ .update_time = aufs_update_time
22069+ }
4a4d8108 22070+};
7f207e10 22071diff -urN /usr/share/empty/fs/aufs/i_op_del.c linux/fs/aufs/i_op_del.c
eca34b5c 22072--- /usr/share/empty/fs/aufs/i_op_del.c 1970-01-01 01:00:00.000000000 +0100
016522bc 22073+++ linux/fs/aufs/i_op_del.c 2020-01-27 10:57:18.172204883 +0100
eca801bf 22074@@ -0,0 +1,513 @@
cd7a4cd9 22075+// SPDX-License-Identifier: GPL-2.0
1facf9fc 22076+/*
016522bc 22077+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 22078+ *
22079+ * This program, aufs is free software; you can redistribute it and/or modify
22080+ * it under the terms of the GNU General Public License as published by
22081+ * the Free Software Foundation; either version 2 of the License, or
22082+ * (at your option) any later version.
dece6358
AM
22083+ *
22084+ * This program is distributed in the hope that it will be useful,
22085+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22086+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22087+ * GNU General Public License for more details.
22088+ *
22089+ * You should have received a copy of the GNU General Public License
523b37e3 22090+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 22091+ */
22092+
22093+/*
4a4d8108 22094+ * inode operations (del entry)
1308ab2a 22095+ */
dece6358 22096+
eca801bf 22097+#include <linux/iversion.h>
1308ab2a 22098+#include "aufs.h"
dece6358 22099+
4a4d8108
AM
22100+/*
22101+ * decide if a new whiteout for @dentry is necessary or not.
22102+ * when it is necessary, prepare the parent dir for the upper branch whose
22103+ * branch index is @bcpup for creation. the actual creation of the whiteout will
22104+ * be done by caller.
22105+ * return value:
22106+ * 0: wh is unnecessary
22107+ * plus: wh is necessary
22108+ * minus: error
22109+ */
22110+int au_wr_dir_need_wh(struct dentry *dentry, int isdir, aufs_bindex_t *bcpup)
1308ab2a 22111+{
4a4d8108 22112+ int need_wh, err;
5afbbe0d 22113+ aufs_bindex_t btop;
4a4d8108 22114+ struct super_block *sb;
dece6358 22115+
4a4d8108 22116+ sb = dentry->d_sb;
5afbbe0d 22117+ btop = au_dbtop(dentry);
4a4d8108 22118+ if (*bcpup < 0) {
5afbbe0d
AM
22119+ *bcpup = btop;
22120+ if (au_test_ro(sb, btop, d_inode(dentry))) {
4a4d8108
AM
22121+ err = AuWbrCopyup(au_sbi(sb), dentry);
22122+ *bcpup = err;
22123+ if (unlikely(err < 0))
22124+ goto out;
22125+ }
22126+ } else
5afbbe0d 22127+ AuDebugOn(btop < *bcpup
5527c038 22128+ || au_test_ro(sb, *bcpup, d_inode(dentry)));
5afbbe0d 22129+ AuDbg("bcpup %d, btop %d\n", *bcpup, btop);
1308ab2a 22130+
5afbbe0d 22131+ if (*bcpup != btop) {
4a4d8108
AM
22132+ err = au_cpup_dirs(dentry, *bcpup);
22133+ if (unlikely(err))
22134+ goto out;
22135+ need_wh = 1;
22136+ } else {
027c5e7a 22137+ struct au_dinfo *dinfo, *tmp;
4a4d8108 22138+
027c5e7a
AM
22139+ need_wh = -ENOMEM;
22140+ dinfo = au_di(dentry);
22141+ tmp = au_di_alloc(sb, AuLsc_DI_TMP);
22142+ if (tmp) {
22143+ au_di_cp(tmp, dinfo);
22144+ au_di_swap(tmp, dinfo);
22145+ /* returns the number of positive dentries */
5afbbe0d
AM
22146+ need_wh = au_lkup_dentry(dentry, btop + 1,
22147+ /* AuLkup_IGNORE_PERM */ 0);
027c5e7a
AM
22148+ au_di_swap(tmp, dinfo);
22149+ au_rw_write_unlock(&tmp->di_rwsem);
22150+ au_di_free(tmp);
4a4d8108
AM
22151+ }
22152+ }
22153+ AuDbg("need_wh %d\n", need_wh);
22154+ err = need_wh;
22155+
4f0767ce 22156+out:
4a4d8108 22157+ return err;
1facf9fc 22158+}
22159+
4a4d8108
AM
22160+/*
22161+ * simple tests for the del-entry operations.
22162+ * following the checks in vfs, plus the parent-child relationship.
22163+ */
22164+int au_may_del(struct dentry *dentry, aufs_bindex_t bindex,
22165+ struct dentry *h_parent, int isdir)
1facf9fc 22166+{
4a4d8108
AM
22167+ int err;
22168+ umode_t h_mode;
22169+ struct dentry *h_dentry, *h_latest;
1308ab2a 22170+ struct inode *h_inode;
1facf9fc 22171+
4a4d8108 22172+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 22173+ if (d_really_is_positive(dentry)) {
4a4d8108 22174+ err = -ENOENT;
5527c038
JR
22175+ if (unlikely(d_is_negative(h_dentry)))
22176+ goto out;
22177+ h_inode = d_inode(h_dentry);
22178+ if (unlikely(!h_inode->i_nlink))
4a4d8108 22179+ goto out;
1facf9fc 22180+
4a4d8108
AM
22181+ h_mode = h_inode->i_mode;
22182+ if (!isdir) {
22183+ err = -EISDIR;
22184+ if (unlikely(S_ISDIR(h_mode)))
22185+ goto out;
22186+ } else if (unlikely(!S_ISDIR(h_mode))) {
22187+ err = -ENOTDIR;
22188+ goto out;
22189+ }
22190+ } else {
22191+ /* rename(2) case */
22192+ err = -EIO;
5527c038 22193+ if (unlikely(d_is_positive(h_dentry)))
4a4d8108
AM
22194+ goto out;
22195+ }
1facf9fc 22196+
4a4d8108
AM
22197+ err = -ENOENT;
22198+ /* expected parent dir is locked */
22199+ if (unlikely(h_parent != h_dentry->d_parent))
22200+ goto out;
22201+ err = 0;
22202+
22203+ /*
22204+ * rmdir a dir may break the consistency on some filesystem.
22205+ * let's try heavy test.
22206+ */
22207+ err = -EACCES;
076b876e 22208+ if (unlikely(!au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1)
5527c038 22209+ && au_test_h_perm(d_inode(h_parent),
076b876e 22210+ MAY_EXEC | MAY_WRITE)))
4a4d8108
AM
22211+ goto out;
22212+
076b876e 22213+ h_latest = au_sio_lkup_one(&dentry->d_name, h_parent);
4a4d8108
AM
22214+ err = -EIO;
22215+ if (IS_ERR(h_latest))
22216+ goto out;
22217+ if (h_latest == h_dentry)
22218+ err = 0;
22219+ dput(h_latest);
22220+
4f0767ce 22221+out:
4a4d8108 22222+ return err;
1308ab2a 22223+}
1facf9fc 22224+
4a4d8108
AM
22225+/*
22226+ * decide the branch where we operate for @dentry. the branch index will be set
acd2b654 22227+ * @rbcpup. after deciding it, 'pin' it and store the timestamps of the parent
4a4d8108
AM
22228+ * dir for reverting.
22229+ * when a new whiteout is necessary, create it.
22230+ */
22231+static struct dentry*
22232+lock_hdir_create_wh(struct dentry *dentry, int isdir, aufs_bindex_t *rbcpup,
22233+ struct au_dtime *dt, struct au_pin *pin)
1308ab2a 22234+{
4a4d8108
AM
22235+ struct dentry *wh_dentry;
22236+ struct super_block *sb;
22237+ struct path h_path;
22238+ int err, need_wh;
22239+ unsigned int udba;
22240+ aufs_bindex_t bcpup;
dece6358 22241+
4a4d8108
AM
22242+ need_wh = au_wr_dir_need_wh(dentry, isdir, rbcpup);
22243+ wh_dentry = ERR_PTR(need_wh);
22244+ if (unlikely(need_wh < 0))
22245+ goto out;
22246+
22247+ sb = dentry->d_sb;
22248+ udba = au_opt_udba(sb);
22249+ bcpup = *rbcpup;
22250+ err = au_pin(pin, dentry, bcpup, udba,
22251+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
22252+ wh_dentry = ERR_PTR(err);
22253+ if (unlikely(err))
22254+ goto out;
22255+
22256+ h_path.dentry = au_pinned_h_parent(pin);
22257+ if (udba != AuOpt_UDBA_NONE
5afbbe0d 22258+ && au_dbtop(dentry) == bcpup) {
4a4d8108
AM
22259+ err = au_may_del(dentry, bcpup, h_path.dentry, isdir);
22260+ wh_dentry = ERR_PTR(err);
22261+ if (unlikely(err))
22262+ goto out_unpin;
22263+ }
22264+
22265+ h_path.mnt = au_sbr_mnt(sb, bcpup);
22266+ au_dtime_store(dt, au_pinned_parent(pin), &h_path);
22267+ wh_dentry = NULL;
22268+ if (!need_wh)
22269+ goto out; /* success, no need to create whiteout */
22270+
22271+ wh_dentry = au_wh_create(dentry, bcpup, h_path.dentry);
22272+ if (IS_ERR(wh_dentry))
22273+ goto out_unpin;
22274+
22275+ /* returns with the parent is locked and wh_dentry is dget-ed */
22276+ goto out; /* success */
22277+
4f0767ce 22278+out_unpin:
4a4d8108 22279+ au_unpin(pin);
4f0767ce 22280+out:
4a4d8108 22281+ return wh_dentry;
1facf9fc 22282+}
22283+
4a4d8108
AM
22284+/*
22285+ * when removing a dir, rename it to a unique temporary whiteout-ed name first
22286+ * in order to be revertible and save time for removing many child whiteouts
22287+ * under the dir.
22288+ * returns 1 when there are too many child whiteout and caller should remove
22289+ * them asynchronously. returns 0 when the number of children is enough small to
22290+ * remove now or the branch fs is a remote fs.
22291+ * otherwise return an error.
22292+ */
22293+static int renwh_and_rmdir(struct dentry *dentry, aufs_bindex_t bindex,
22294+ struct au_nhash *whlist, struct inode *dir)
1facf9fc 22295+{
4a4d8108
AM
22296+ int rmdir_later, err, dirwh;
22297+ struct dentry *h_dentry;
22298+ struct super_block *sb;
5527c038 22299+ struct inode *inode;
4a4d8108
AM
22300+
22301+ sb = dentry->d_sb;
22302+ SiMustAnyLock(sb);
22303+ h_dentry = au_h_dptr(dentry, bindex);
22304+ err = au_whtmp_ren(h_dentry, au_sbr(sb, bindex));
22305+ if (unlikely(err))
22306+ goto out;
22307+
22308+ /* stop monitoring */
5527c038
JR
22309+ inode = d_inode(dentry);
22310+ au_hn_free(au_hi(inode, bindex));
4a4d8108
AM
22311+
22312+ if (!au_test_fs_remote(h_dentry->d_sb)) {
22313+ dirwh = au_sbi(sb)->si_dirwh;
22314+ rmdir_later = (dirwh <= 1);
22315+ if (!rmdir_later)
22316+ rmdir_later = au_nhash_test_longer_wh(whlist, bindex,
22317+ dirwh);
22318+ if (rmdir_later)
22319+ return rmdir_later;
22320+ }
1facf9fc 22321+
4a4d8108
AM
22322+ err = au_whtmp_rmdir(dir, bindex, h_dentry, whlist);
22323+ if (unlikely(err)) {
523b37e3
AM
22324+ AuIOErr("rmdir %pd, b%d failed, %d. ignored\n",
22325+ h_dentry, bindex, err);
4a4d8108
AM
22326+ err = 0;
22327+ }
dece6358 22328+
4f0767ce 22329+out:
4a4d8108
AM
22330+ AuTraceErr(err);
22331+ return err;
22332+}
1308ab2a 22333+
4a4d8108
AM
22334+/*
22335+ * final procedure for deleting a entry.
22336+ * maintain dentry and iattr.
22337+ */
22338+static void epilog(struct inode *dir, struct dentry *dentry,
22339+ aufs_bindex_t bindex)
22340+{
22341+ struct inode *inode;
1308ab2a 22342+
5527c038 22343+ inode = d_inode(dentry);
4a4d8108
AM
22344+ d_drop(dentry);
22345+ inode->i_ctime = dir->i_ctime;
1308ab2a 22346+
b912730e 22347+ au_dir_ts(dir, bindex);
be118d29 22348+ inode_inc_iversion(dir);
1facf9fc 22349+}
22350+
4a4d8108
AM
22351+/*
22352+ * when an error happened, remove the created whiteout and revert everything.
22353+ */
7f207e10
AM
22354+static int do_revert(int err, struct inode *dir, aufs_bindex_t bindex,
22355+ aufs_bindex_t bwh, struct dentry *wh_dentry,
22356+ struct dentry *dentry, struct au_dtime *dt)
1facf9fc 22357+{
4a4d8108
AM
22358+ int rerr;
22359+ struct path h_path = {
22360+ .dentry = wh_dentry,
7f207e10 22361+ .mnt = au_sbr_mnt(dir->i_sb, bindex)
4a4d8108 22362+ };
dece6358 22363+
7f207e10 22364+ rerr = au_wh_unlink_dentry(au_h_iptr(dir, bindex), &h_path, dentry);
4a4d8108
AM
22365+ if (!rerr) {
22366+ au_set_dbwh(dentry, bwh);
22367+ au_dtime_revert(dt);
22368+ return 0;
22369+ }
dece6358 22370+
523b37e3 22371+ AuIOErr("%pd reverting whiteout failed(%d, %d)\n", dentry, err, rerr);
4a4d8108 22372+ return -EIO;
1facf9fc 22373+}
22374+
4a4d8108 22375+/* ---------------------------------------------------------------------- */
1facf9fc 22376+
4a4d8108 22377+int aufs_unlink(struct inode *dir, struct dentry *dentry)
1308ab2a 22378+{
4a4d8108 22379+ int err;
5afbbe0d 22380+ aufs_bindex_t bwh, bindex, btop;
523b37e3 22381+ struct inode *inode, *h_dir, *delegated;
4a4d8108 22382+ struct dentry *parent, *wh_dentry;
acd2b654 22383+ /* to reduce stack size */
c2b27bf2
AM
22384+ struct {
22385+ struct au_dtime dt;
22386+ struct au_pin pin;
22387+ struct path h_path;
22388+ } *a;
1facf9fc 22389+
4a4d8108 22390+ IMustLock(dir);
027c5e7a 22391+
c2b27bf2
AM
22392+ err = -ENOMEM;
22393+ a = kmalloc(sizeof(*a), GFP_NOFS);
22394+ if (unlikely(!a))
22395+ goto out;
22396+
027c5e7a
AM
22397+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_GEN);
22398+ if (unlikely(err))
c2b27bf2 22399+ goto out_free;
027c5e7a
AM
22400+ err = au_d_hashed_positive(dentry);
22401+ if (unlikely(err))
22402+ goto out_unlock;
5527c038 22403+ inode = d_inode(dentry);
4a4d8108 22404+ IMustLock(inode);
027c5e7a 22405+ err = -EISDIR;
2000de60 22406+ if (unlikely(d_is_dir(dentry)))
027c5e7a 22407+ goto out_unlock; /* possible? */
1facf9fc 22408+
5afbbe0d 22409+ btop = au_dbtop(dentry);
4a4d8108
AM
22410+ bwh = au_dbwh(dentry);
22411+ bindex = -1;
027c5e7a
AM
22412+ parent = dentry->d_parent; /* dir inode is locked */
22413+ di_write_lock_parent(parent);
c2b27bf2
AM
22414+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/0, &bindex, &a->dt,
22415+ &a->pin);
4a4d8108
AM
22416+ err = PTR_ERR(wh_dentry);
22417+ if (IS_ERR(wh_dentry))
027c5e7a 22418+ goto out_parent;
1facf9fc 22419+
5afbbe0d
AM
22420+ a->h_path.mnt = au_sbr_mnt(dentry->d_sb, btop);
22421+ a->h_path.dentry = au_h_dptr(dentry, btop);
c2b27bf2 22422+ dget(a->h_path.dentry);
5afbbe0d 22423+ if (bindex == btop) {
c2b27bf2 22424+ h_dir = au_pinned_h_dir(&a->pin);
523b37e3
AM
22425+ delegated = NULL;
22426+ err = vfsub_unlink(h_dir, &a->h_path, &delegated, /*force*/0);
22427+ if (unlikely(err == -EWOULDBLOCK)) {
22428+ pr_warn("cannot retry for NFSv4 delegation"
22429+ " for an internal unlink\n");
22430+ iput(delegated);
22431+ }
4a4d8108
AM
22432+ } else {
22433+ /* dir inode is locked */
5527c038 22434+ h_dir = d_inode(wh_dentry->d_parent);
4a4d8108
AM
22435+ IMustLock(h_dir);
22436+ err = 0;
22437+ }
dece6358 22438+
4a4d8108 22439+ if (!err) {
7f207e10 22440+ vfsub_drop_nlink(inode);
4a4d8108
AM
22441+ epilog(dir, dentry, bindex);
22442+
22443+ /* update target timestamps */
5afbbe0d 22444+ if (bindex == btop) {
c2b27bf2
AM
22445+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL);
22446+ /*ignore*/
5527c038 22447+ inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
4a4d8108
AM
22448+ } else
22449+ /* todo: this timestamp may be reverted later */
22450+ inode->i_ctime = h_dir->i_ctime;
027c5e7a 22451+ goto out_unpin; /* success */
1facf9fc 22452+ }
22453+
4a4d8108
AM
22454+ /* revert */
22455+ if (wh_dentry) {
22456+ int rerr;
22457+
c2b27bf2
AM
22458+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry,
22459+ &a->dt);
4a4d8108
AM
22460+ if (rerr)
22461+ err = rerr;
dece6358 22462+ }
1facf9fc 22463+
027c5e7a 22464+out_unpin:
c2b27bf2 22465+ au_unpin(&a->pin);
4a4d8108 22466+ dput(wh_dentry);
c2b27bf2 22467+ dput(a->h_path.dentry);
027c5e7a 22468+out_parent:
4a4d8108 22469+ di_write_unlock(parent);
027c5e7a 22470+out_unlock:
4a4d8108 22471+ aufs_read_unlock(dentry, AuLock_DW);
c2b27bf2 22472+out_free:
9f237c51 22473+ au_kfree_rcu(a);
027c5e7a 22474+out:
4a4d8108 22475+ return err;
dece6358
AM
22476+}
22477+
4a4d8108 22478+int aufs_rmdir(struct inode *dir, struct dentry *dentry)
1308ab2a 22479+{
4a4d8108 22480+ int err, rmdir_later;
5afbbe0d 22481+ aufs_bindex_t bwh, bindex, btop;
4a4d8108
AM
22482+ struct inode *inode;
22483+ struct dentry *parent, *wh_dentry, *h_dentry;
22484+ struct au_whtmp_rmdir *args;
acd2b654 22485+ /* to reduce stack size */
c2b27bf2
AM
22486+ struct {
22487+ struct au_dtime dt;
22488+ struct au_pin pin;
22489+ } *a;
1facf9fc 22490+
4a4d8108 22491+ IMustLock(dir);
027c5e7a 22492+
c2b27bf2
AM
22493+ err = -ENOMEM;
22494+ a = kmalloc(sizeof(*a), GFP_NOFS);
22495+ if (unlikely(!a))
22496+ goto out;
22497+
027c5e7a
AM
22498+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_GEN);
22499+ if (unlikely(err))
c2b27bf2 22500+ goto out_free;
53392da6
AM
22501+ err = au_alive_dir(dentry);
22502+ if (unlikely(err))
027c5e7a 22503+ goto out_unlock;
5527c038 22504+ inode = d_inode(dentry);
4a4d8108 22505+ IMustLock(inode);
027c5e7a 22506+ err = -ENOTDIR;
2000de60 22507+ if (unlikely(!d_is_dir(dentry)))
027c5e7a 22508+ goto out_unlock; /* possible? */
dece6358 22509+
4a4d8108
AM
22510+ err = -ENOMEM;
22511+ args = au_whtmp_rmdir_alloc(dir->i_sb, GFP_NOFS);
22512+ if (unlikely(!args))
22513+ goto out_unlock;
dece6358 22514+
4a4d8108
AM
22515+ parent = dentry->d_parent; /* dir inode is locked */
22516+ di_write_lock_parent(parent);
22517+ err = au_test_empty(dentry, &args->whlist);
22518+ if (unlikely(err))
027c5e7a 22519+ goto out_parent;
1facf9fc 22520+
5afbbe0d 22521+ btop = au_dbtop(dentry);
4a4d8108
AM
22522+ bwh = au_dbwh(dentry);
22523+ bindex = -1;
c2b27bf2
AM
22524+ wh_dentry = lock_hdir_create_wh(dentry, /*isdir*/1, &bindex, &a->dt,
22525+ &a->pin);
4a4d8108
AM
22526+ err = PTR_ERR(wh_dentry);
22527+ if (IS_ERR(wh_dentry))
027c5e7a 22528+ goto out_parent;
1facf9fc 22529+
5afbbe0d 22530+ h_dentry = au_h_dptr(dentry, btop);
4a4d8108
AM
22531+ dget(h_dentry);
22532+ rmdir_later = 0;
5afbbe0d
AM
22533+ if (bindex == btop) {
22534+ err = renwh_and_rmdir(dentry, btop, &args->whlist, dir);
4a4d8108
AM
22535+ if (err > 0) {
22536+ rmdir_later = err;
22537+ err = 0;
22538+ }
22539+ } else {
22540+ /* stop monitoring */
5afbbe0d 22541+ au_hn_free(au_hi(inode, btop));
4a4d8108
AM
22542+
22543+ /* dir inode is locked */
5527c038 22544+ IMustLock(d_inode(wh_dentry->d_parent));
1facf9fc 22545+ err = 0;
22546+ }
22547+
4a4d8108 22548+ if (!err) {
027c5e7a 22549+ vfsub_dead_dir(inode);
4a4d8108
AM
22550+ au_set_dbdiropq(dentry, -1);
22551+ epilog(dir, dentry, bindex);
1308ab2a 22552+
4a4d8108 22553+ if (rmdir_later) {
5afbbe0d 22554+ au_whtmp_kick_rmdir(dir, btop, h_dentry, args);
4a4d8108
AM
22555+ args = NULL;
22556+ }
1308ab2a 22557+
4a4d8108 22558+ goto out_unpin; /* success */
1facf9fc 22559+ }
22560+
4a4d8108
AM
22561+ /* revert */
22562+ AuLabel(revert);
22563+ if (wh_dentry) {
22564+ int rerr;
1308ab2a 22565+
c2b27bf2
AM
22566+ rerr = do_revert(err, dir, bindex, bwh, wh_dentry, dentry,
22567+ &a->dt);
4a4d8108
AM
22568+ if (rerr)
22569+ err = rerr;
1facf9fc 22570+ }
22571+
4f0767ce 22572+out_unpin:
c2b27bf2 22573+ au_unpin(&a->pin);
4a4d8108
AM
22574+ dput(wh_dentry);
22575+ dput(h_dentry);
027c5e7a 22576+out_parent:
4a4d8108
AM
22577+ di_write_unlock(parent);
22578+ if (args)
22579+ au_whtmp_rmdir_free(args);
4f0767ce 22580+out_unlock:
4a4d8108 22581+ aufs_read_unlock(dentry, AuLock_DW);
c2b27bf2 22582+out_free:
9f237c51 22583+ au_kfree_rcu(a);
4f0767ce 22584+out:
4a4d8108
AM
22585+ AuTraceErr(err);
22586+ return err;
dece6358 22587+}
7f207e10 22588diff -urN /usr/share/empty/fs/aufs/i_op_ren.c linux/fs/aufs/i_op_ren.c
eca34b5c 22589--- /usr/share/empty/fs/aufs/i_op_ren.c 1970-01-01 01:00:00.000000000 +0100
016522bc 22590+++ linux/fs/aufs/i_op_ren.c 2020-01-27 10:57:18.172204883 +0100
eca801bf 22591@@ -0,0 +1,1250 @@
cd7a4cd9 22592+// SPDX-License-Identifier: GPL-2.0
1facf9fc 22593+/*
016522bc 22594+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 22595+ *
22596+ * This program, aufs is free software; you can redistribute it and/or modify
22597+ * it under the terms of the GNU General Public License as published by
22598+ * the Free Software Foundation; either version 2 of the License, or
22599+ * (at your option) any later version.
dece6358
AM
22600+ *
22601+ * This program is distributed in the hope that it will be useful,
22602+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22603+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22604+ * GNU General Public License for more details.
22605+ *
22606+ * You should have received a copy of the GNU General Public License
523b37e3 22607+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 22608+ */
22609+
22610+/*
4a4d8108
AM
22611+ * inode operation (rename entry)
22612+ * todo: this is crazy monster
1facf9fc 22613+ */
22614+
eca801bf 22615+#include <linux/iversion.h>
1facf9fc 22616+#include "aufs.h"
22617+
4a4d8108
AM
22618+enum { AuSRC, AuDST, AuSrcDst };
22619+enum { AuPARENT, AuCHILD, AuParentChild };
1facf9fc 22620+
f2c43d5f
AM
22621+#define AuRen_ISDIR_SRC 1
22622+#define AuRen_ISDIR_DST (1 << 1)
22623+#define AuRen_ISSAMEDIR (1 << 2)
22624+#define AuRen_WHSRC (1 << 3)
22625+#define AuRen_WHDST (1 << 4)
22626+#define AuRen_MNT_WRITE (1 << 5)
22627+#define AuRen_DT_DSTDIR (1 << 6)
22628+#define AuRen_DIROPQ_SRC (1 << 7)
22629+#define AuRen_DIROPQ_DST (1 << 8)
8b6a4947
AM
22630+#define AuRen_DIRREN (1 << 9)
22631+#define AuRen_DROPPED_SRC (1 << 10)
22632+#define AuRen_DROPPED_DST (1 << 11)
4a4d8108 22633+#define au_ftest_ren(flags, name) ((flags) & AuRen_##name)
7f207e10
AM
22634+#define au_fset_ren(flags, name) \
22635+ do { (flags) |= AuRen_##name; } while (0)
22636+#define au_fclr_ren(flags, name) \
22637+ do { (flags) &= ~AuRen_##name; } while (0)
1facf9fc 22638+
8b6a4947
AM
22639+#ifndef CONFIG_AUFS_DIRREN
22640+#undef AuRen_DIRREN
22641+#define AuRen_DIRREN 0
22642+#endif
22643+
4a4d8108
AM
22644+struct au_ren_args {
22645+ struct {
22646+ struct dentry *dentry, *h_dentry, *parent, *h_parent,
22647+ *wh_dentry;
22648+ struct inode *dir, *inode;
f2c43d5f 22649+ struct au_hinode *hdir, *hinode;
4a4d8108 22650+ struct au_dtime dt[AuParentChild];
f2c43d5f 22651+ aufs_bindex_t btop, bdiropq;
4a4d8108 22652+ } sd[AuSrcDst];
1facf9fc 22653+
4a4d8108
AM
22654+#define src_dentry sd[AuSRC].dentry
22655+#define src_dir sd[AuSRC].dir
22656+#define src_inode sd[AuSRC].inode
22657+#define src_h_dentry sd[AuSRC].h_dentry
22658+#define src_parent sd[AuSRC].parent
22659+#define src_h_parent sd[AuSRC].h_parent
22660+#define src_wh_dentry sd[AuSRC].wh_dentry
22661+#define src_hdir sd[AuSRC].hdir
f2c43d5f 22662+#define src_hinode sd[AuSRC].hinode
4a4d8108
AM
22663+#define src_h_dir sd[AuSRC].hdir->hi_inode
22664+#define src_dt sd[AuSRC].dt
5afbbe0d 22665+#define src_btop sd[AuSRC].btop
f2c43d5f 22666+#define src_bdiropq sd[AuSRC].bdiropq
1facf9fc 22667+
4a4d8108
AM
22668+#define dst_dentry sd[AuDST].dentry
22669+#define dst_dir sd[AuDST].dir
22670+#define dst_inode sd[AuDST].inode
22671+#define dst_h_dentry sd[AuDST].h_dentry
22672+#define dst_parent sd[AuDST].parent
22673+#define dst_h_parent sd[AuDST].h_parent
22674+#define dst_wh_dentry sd[AuDST].wh_dentry
22675+#define dst_hdir sd[AuDST].hdir
f2c43d5f 22676+#define dst_hinode sd[AuDST].hinode
4a4d8108
AM
22677+#define dst_h_dir sd[AuDST].hdir->hi_inode
22678+#define dst_dt sd[AuDST].dt
5afbbe0d 22679+#define dst_btop sd[AuDST].btop
f2c43d5f 22680+#define dst_bdiropq sd[AuDST].bdiropq
4a4d8108
AM
22681+
22682+ struct dentry *h_trap;
22683+ struct au_branch *br;
4a4d8108
AM
22684+ struct path h_path;
22685+ struct au_nhash whlist;
f2c43d5f 22686+ aufs_bindex_t btgt, src_bwh;
1facf9fc 22687+
f2c43d5f
AM
22688+ struct {
22689+ unsigned short auren_flags;
22690+ unsigned char flags; /* syscall parameter */
22691+ unsigned char exchange;
22692+ } __packed;
1facf9fc 22693+
4a4d8108
AM
22694+ struct au_whtmp_rmdir *thargs;
22695+ struct dentry *h_dst;
8b6a4947 22696+ struct au_hinode *h_root;
4a4d8108 22697+};
1308ab2a 22698+
4a4d8108 22699+/* ---------------------------------------------------------------------- */
1308ab2a 22700+
4a4d8108
AM
22701+/*
22702+ * functions for reverting.
22703+ * when an error happened in a single rename systemcall, we should revert
79b8bda9 22704+ * everything as if nothing happened.
4a4d8108
AM
22705+ * we don't need to revert the copied-up/down the parent dir since they are
22706+ * harmless.
22707+ */
1facf9fc 22708+
4a4d8108
AM
22709+#define RevertFailure(fmt, ...) do { \
22710+ AuIOErr("revert failure: " fmt " (%d, %d)\n", \
22711+ ##__VA_ARGS__, err, rerr); \
22712+ err = -EIO; \
22713+} while (0)
1facf9fc 22714+
f2c43d5f 22715+static void au_ren_do_rev_diropq(int err, struct au_ren_args *a, int idx)
1facf9fc 22716+{
4a4d8108 22717+ int rerr;
f2c43d5f
AM
22718+ struct dentry *d;
22719+#define src_or_dst(member) a->sd[idx].member
1facf9fc 22720+
f2c43d5f
AM
22721+ d = src_or_dst(dentry); /* {src,dst}_dentry */
22722+ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD);
22723+ rerr = au_diropq_remove(d, a->btgt);
22724+ au_hn_inode_unlock(src_or_dst(hinode));
22725+ au_set_dbdiropq(d, src_or_dst(bdiropq));
4a4d8108 22726+ if (rerr)
f2c43d5f
AM
22727+ RevertFailure("remove diropq %pd", d);
22728+
22729+#undef src_or_dst_
22730+}
22731+
22732+static void au_ren_rev_diropq(int err, struct au_ren_args *a)
22733+{
22734+ if (au_ftest_ren(a->auren_flags, DIROPQ_SRC))
22735+ au_ren_do_rev_diropq(err, a, AuSRC);
22736+ if (au_ftest_ren(a->auren_flags, DIROPQ_DST))
22737+ au_ren_do_rev_diropq(err, a, AuDST);
4a4d8108 22738+}
1facf9fc 22739+
4a4d8108
AM
22740+static void au_ren_rev_rename(int err, struct au_ren_args *a)
22741+{
22742+ int rerr;
523b37e3 22743+ struct inode *delegated;
1facf9fc 22744+
b4510431
AM
22745+ a->h_path.dentry = vfsub_lkup_one(&a->src_dentry->d_name,
22746+ a->src_h_parent);
4a4d8108
AM
22747+ rerr = PTR_ERR(a->h_path.dentry);
22748+ if (IS_ERR(a->h_path.dentry)) {
523b37e3 22749+ RevertFailure("lkup one %pd", a->src_dentry);
4a4d8108 22750+ return;
1facf9fc 22751+ }
22752+
523b37e3 22753+ delegated = NULL;
4a4d8108
AM
22754+ rerr = vfsub_rename(a->dst_h_dir,
22755+ au_h_dptr(a->src_dentry, a->btgt),
f2c43d5f 22756+ a->src_h_dir, &a->h_path, &delegated, a->flags);
523b37e3
AM
22757+ if (unlikely(rerr == -EWOULDBLOCK)) {
22758+ pr_warn("cannot retry for NFSv4 delegation"
22759+ " for an internal rename\n");
22760+ iput(delegated);
22761+ }
4a4d8108
AM
22762+ d_drop(a->h_path.dentry);
22763+ dput(a->h_path.dentry);
22764+ /* au_set_h_dptr(a->src_dentry, a->btgt, NULL); */
22765+ if (rerr)
523b37e3 22766+ RevertFailure("rename %pd", a->src_dentry);
1facf9fc 22767+}
22768+
4a4d8108 22769+static void au_ren_rev_whtmp(int err, struct au_ren_args *a)
1facf9fc 22770+{
4a4d8108 22771+ int rerr;
523b37e3 22772+ struct inode *delegated;
dece6358 22773+
b4510431
AM
22774+ a->h_path.dentry = vfsub_lkup_one(&a->dst_dentry->d_name,
22775+ a->dst_h_parent);
4a4d8108
AM
22776+ rerr = PTR_ERR(a->h_path.dentry);
22777+ if (IS_ERR(a->h_path.dentry)) {
523b37e3 22778+ RevertFailure("lkup one %pd", a->dst_dentry);
4a4d8108
AM
22779+ return;
22780+ }
5527c038 22781+ if (d_is_positive(a->h_path.dentry)) {
4a4d8108
AM
22782+ d_drop(a->h_path.dentry);
22783+ dput(a->h_path.dentry);
22784+ return;
dece6358
AM
22785+ }
22786+
523b37e3
AM
22787+ delegated = NULL;
22788+ rerr = vfsub_rename(a->dst_h_dir, a->h_dst, a->dst_h_dir, &a->h_path,
f2c43d5f 22789+ &delegated, a->flags);
523b37e3
AM
22790+ if (unlikely(rerr == -EWOULDBLOCK)) {
22791+ pr_warn("cannot retry for NFSv4 delegation"
22792+ " for an internal rename\n");
22793+ iput(delegated);
22794+ }
4a4d8108
AM
22795+ d_drop(a->h_path.dentry);
22796+ dput(a->h_path.dentry);
22797+ if (!rerr)
22798+ au_set_h_dptr(a->dst_dentry, a->btgt, dget(a->h_dst));
22799+ else
523b37e3 22800+ RevertFailure("rename %pd", a->h_dst);
4a4d8108 22801+}
1308ab2a 22802+
4a4d8108
AM
22803+static void au_ren_rev_whsrc(int err, struct au_ren_args *a)
22804+{
22805+ int rerr;
1308ab2a 22806+
4a4d8108
AM
22807+ a->h_path.dentry = a->src_wh_dentry;
22808+ rerr = au_wh_unlink_dentry(a->src_h_dir, &a->h_path, a->src_dentry);
027c5e7a 22809+ au_set_dbwh(a->src_dentry, a->src_bwh);
4a4d8108 22810+ if (rerr)
523b37e3 22811+ RevertFailure("unlink %pd", a->src_wh_dentry);
4a4d8108 22812+}
4a4d8108 22813+#undef RevertFailure
1facf9fc 22814+
1308ab2a 22815+/* ---------------------------------------------------------------------- */
22816+
4a4d8108
AM
22817+/*
22818+ * when we have to copyup the renaming entry, do it with the rename-target name
22819+ * in order to minimize the cost (the later actual rename is unnecessary).
22820+ * otherwise rename it on the target branch.
22821+ */
22822+static int au_ren_or_cpup(struct au_ren_args *a)
1facf9fc 22823+{
dece6358 22824+ int err;
4a4d8108 22825+ struct dentry *d;
523b37e3 22826+ struct inode *delegated;
1facf9fc 22827+
4a4d8108 22828+ d = a->src_dentry;
5afbbe0d 22829+ if (au_dbtop(d) == a->btgt) {
4a4d8108 22830+ a->h_path.dentry = a->dst_h_dentry;
5afbbe0d 22831+ AuDebugOn(au_dbtop(d) != a->btgt);
523b37e3 22832+ delegated = NULL;
4a4d8108 22833+ err = vfsub_rename(a->src_h_dir, au_h_dptr(d, a->btgt),
f2c43d5f
AM
22834+ a->dst_h_dir, &a->h_path, &delegated,
22835+ a->flags);
523b37e3
AM
22836+ if (unlikely(err == -EWOULDBLOCK)) {
22837+ pr_warn("cannot retry for NFSv4 delegation"
22838+ " for an internal rename\n");
22839+ iput(delegated);
22840+ }
c2b27bf2 22841+ } else
86dc4139 22842+ BUG();
1308ab2a 22843+
027c5e7a
AM
22844+ if (!err && a->h_dst)
22845+ /* it will be set to dinfo later */
22846+ dget(a->h_dst);
1facf9fc 22847+
dece6358
AM
22848+ return err;
22849+}
1facf9fc 22850+
4a4d8108
AM
22851+/* cf. aufs_rmdir() */
22852+static int au_ren_del_whtmp(struct au_ren_args *a)
dece6358 22853+{
4a4d8108
AM
22854+ int err;
22855+ struct inode *dir;
1facf9fc 22856+
4a4d8108
AM
22857+ dir = a->dst_dir;
22858+ SiMustAnyLock(dir->i_sb);
22859+ if (!au_nhash_test_longer_wh(&a->whlist, a->btgt,
22860+ au_sbi(dir->i_sb)->si_dirwh)
22861+ || au_test_fs_remote(a->h_dst->d_sb)) {
22862+ err = au_whtmp_rmdir(dir, a->btgt, a->h_dst, &a->whlist);
22863+ if (unlikely(err))
523b37e3
AM
22864+ pr_warn("failed removing whtmp dir %pd (%d), "
22865+ "ignored.\n", a->h_dst, err);
4a4d8108
AM
22866+ } else {
22867+ au_nhash_wh_free(&a->thargs->whlist);
22868+ a->thargs->whlist = a->whlist;
22869+ a->whlist.nh_num = 0;
22870+ au_whtmp_kick_rmdir(dir, a->btgt, a->h_dst, a->thargs);
22871+ dput(a->h_dst);
22872+ a->thargs = NULL;
22873+ }
22874+
22875+ return 0;
1308ab2a 22876+}
1facf9fc 22877+
4a4d8108 22878+/* make it 'opaque' dir. */
f2c43d5f 22879+static int au_ren_do_diropq(struct au_ren_args *a, int idx)
4a4d8108
AM
22880+{
22881+ int err;
f2c43d5f
AM
22882+ struct dentry *d, *diropq;
22883+#define src_or_dst(member) a->sd[idx].member
1facf9fc 22884+
4a4d8108 22885+ err = 0;
f2c43d5f
AM
22886+ d = src_or_dst(dentry); /* {src,dst}_dentry */
22887+ src_or_dst(bdiropq) = au_dbdiropq(d);
22888+ src_or_dst(hinode) = au_hi(src_or_dst(inode), a->btgt);
22889+ au_hn_inode_lock_nested(src_or_dst(hinode), AuLsc_I_CHILD);
22890+ diropq = au_diropq_create(d, a->btgt);
22891+ au_hn_inode_unlock(src_or_dst(hinode));
4a4d8108
AM
22892+ if (IS_ERR(diropq))
22893+ err = PTR_ERR(diropq);
076b876e
AM
22894+ else
22895+ dput(diropq);
1facf9fc 22896+
f2c43d5f 22897+#undef src_or_dst_
4a4d8108
AM
22898+ return err;
22899+}
1facf9fc 22900+
f2c43d5f 22901+static int au_ren_diropq(struct au_ren_args *a)
4a4d8108
AM
22902+{
22903+ int err;
f2c43d5f
AM
22904+ unsigned char always;
22905+ struct dentry *d;
1facf9fc 22906+
f2c43d5f
AM
22907+ err = 0;
22908+ d = a->dst_dentry; /* already renamed on the branch */
22909+ always = !!au_opt_test(au_mntflags(d->d_sb), ALWAYS_DIROPQ);
22910+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)
8b6a4947 22911+ && !au_ftest_ren(a->auren_flags, DIRREN)
f2c43d5f
AM
22912+ && a->btgt != au_dbdiropq(a->src_dentry)
22913+ && (a->dst_wh_dentry
22914+ || a->btgt <= au_dbdiropq(d)
22915+ /* hide the lower to keep xino */
22916+ /* the lowers may not be a dir, but we hide them anyway */
22917+ || a->btgt < au_dbbot(d)
22918+ || always)) {
22919+ AuDbg("here\n");
22920+ err = au_ren_do_diropq(a, AuSRC);
22921+ if (unlikely(err))
4a4d8108 22922+ goto out;
f2c43d5f 22923+ au_fset_ren(a->auren_flags, DIROPQ_SRC);
4a4d8108 22924+ }
f2c43d5f
AM
22925+ if (!a->exchange)
22926+ goto out; /* success */
1facf9fc 22927+
f2c43d5f
AM
22928+ d = a->src_dentry; /* already renamed on the branch */
22929+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)
22930+ && a->btgt != au_dbdiropq(a->dst_dentry)
22931+ && (a->btgt < au_dbdiropq(d)
22932+ || a->btgt < au_dbbot(d)
22933+ || always)) {
22934+ AuDbgDentry(a->src_dentry);
22935+ AuDbgDentry(a->dst_dentry);
22936+ err = au_ren_do_diropq(a, AuDST);
4a4d8108 22937+ if (unlikely(err))
f2c43d5f
AM
22938+ goto out_rev_src;
22939+ au_fset_ren(a->auren_flags, DIROPQ_DST);
22940+ }
22941+ goto out; /* success */
dece6358 22942+
f2c43d5f
AM
22943+out_rev_src:
22944+ AuDbg("err %d, reverting src\n", err);
22945+ au_ren_rev_diropq(err, a);
22946+out:
22947+ return err;
22948+}
22949+
22950+static int do_rename(struct au_ren_args *a)
22951+{
22952+ int err;
22953+ struct dentry *d, *h_d;
22954+
22955+ if (!a->exchange) {
22956+ /* prepare workqueue args for asynchronous rmdir */
22957+ h_d = a->dst_h_dentry;
22958+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)
8b6a4947 22959+ /* && !au_ftest_ren(a->auren_flags, DIRREN) */
f2c43d5f
AM
22960+ && d_is_positive(h_d)) {
22961+ err = -ENOMEM;
22962+ a->thargs = au_whtmp_rmdir_alloc(a->src_dentry->d_sb,
22963+ GFP_NOFS);
22964+ if (unlikely(!a->thargs))
22965+ goto out;
22966+ a->h_dst = dget(h_d);
22967+ }
22968+
22969+ /* create whiteout for src_dentry */
22970+ if (au_ftest_ren(a->auren_flags, WHSRC)) {
22971+ a->src_bwh = au_dbwh(a->src_dentry);
22972+ AuDebugOn(a->src_bwh >= 0);
22973+ a->src_wh_dentry = au_wh_create(a->src_dentry, a->btgt,
22974+ a->src_h_parent);
22975+ err = PTR_ERR(a->src_wh_dentry);
22976+ if (IS_ERR(a->src_wh_dentry))
22977+ goto out_thargs;
22978+ }
22979+
22980+ /* lookup whiteout for dentry */
22981+ if (au_ftest_ren(a->auren_flags, WHDST)) {
22982+ h_d = au_wh_lkup(a->dst_h_parent,
22983+ &a->dst_dentry->d_name, a->br);
22984+ err = PTR_ERR(h_d);
22985+ if (IS_ERR(h_d))
22986+ goto out_whsrc;
22987+ if (d_is_negative(h_d))
22988+ dput(h_d);
22989+ else
22990+ a->dst_wh_dentry = h_d;
22991+ }
22992+
22993+ /* rename dentry to tmpwh */
22994+ if (a->thargs) {
22995+ err = au_whtmp_ren(a->dst_h_dentry, a->br);
22996+ if (unlikely(err))
22997+ goto out_whdst;
22998+
22999+ d = a->dst_dentry;
23000+ au_set_h_dptr(d, a->btgt, NULL);
23001+ err = au_lkup_neg(d, a->btgt, /*wh*/0);
23002+ if (unlikely(err))
23003+ goto out_whtmp;
23004+ a->dst_h_dentry = au_h_dptr(d, a->btgt);
23005+ }
4a4d8108 23006+ }
1facf9fc 23007+
5afbbe0d 23008+ BUG_ON(d_is_positive(a->dst_h_dentry) && a->src_btop != a->btgt);
43982f53 23009+#if 0 /* debugging */
8b6a4947
AM
23010+ BUG_ON(!au_ftest_ren(a->auren_flags, DIRREN)
23011+ && d_is_positive(a->dst_h_dentry)
23012+ && a->src_btop != a->btgt);
23013+#endif
1facf9fc 23014+
4a4d8108 23015+ /* rename by vfs_rename or cpup */
4a4d8108
AM
23016+ err = au_ren_or_cpup(a);
23017+ if (unlikely(err))
23018+ /* leave the copied-up one */
23019+ goto out_whtmp;
1308ab2a 23020+
4a4d8108 23021+ /* make dir opaque */
f2c43d5f
AM
23022+ err = au_ren_diropq(a);
23023+ if (unlikely(err))
23024+ goto out_rename;
1308ab2a 23025+
4a4d8108 23026+ /* update target timestamps */
f2c43d5f
AM
23027+ if (a->exchange) {
23028+ AuDebugOn(au_dbtop(a->dst_dentry) != a->btgt);
23029+ a->h_path.dentry = au_h_dptr(a->dst_dentry, a->btgt);
23030+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
23031+ a->dst_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
23032+ }
5afbbe0d 23033+ AuDebugOn(au_dbtop(a->src_dentry) != a->btgt);
4a4d8108
AM
23034+ a->h_path.dentry = au_h_dptr(a->src_dentry, a->btgt);
23035+ vfsub_update_h_iattr(&a->h_path, /*did*/NULL); /*ignore*/
5527c038 23036+ a->src_inode->i_ctime = d_inode(a->h_path.dentry)->i_ctime;
1facf9fc 23037+
f2c43d5f
AM
23038+ if (!a->exchange) {
23039+ /* remove whiteout for dentry */
23040+ if (a->dst_wh_dentry) {
23041+ a->h_path.dentry = a->dst_wh_dentry;
23042+ err = au_wh_unlink_dentry(a->dst_h_dir, &a->h_path,
23043+ a->dst_dentry);
23044+ if (unlikely(err))
23045+ goto out_diropq;
23046+ }
1facf9fc 23047+
f2c43d5f
AM
23048+ /* remove whtmp */
23049+ if (a->thargs)
23050+ au_ren_del_whtmp(a); /* ignore this error */
1308ab2a 23051+
f2c43d5f
AM
23052+ au_fhsm_wrote(a->src_dentry->d_sb, a->btgt, /*force*/0);
23053+ }
4a4d8108
AM
23054+ err = 0;
23055+ goto out_success;
23056+
4f0767ce 23057+out_diropq:
f2c43d5f 23058+ au_ren_rev_diropq(err, a);
4f0767ce 23059+out_rename:
7e9cd9fe 23060+ au_ren_rev_rename(err, a);
027c5e7a 23061+ dput(a->h_dst);
4f0767ce 23062+out_whtmp:
4a4d8108
AM
23063+ if (a->thargs)
23064+ au_ren_rev_whtmp(err, a);
4f0767ce 23065+out_whdst:
4a4d8108
AM
23066+ dput(a->dst_wh_dentry);
23067+ a->dst_wh_dentry = NULL;
4f0767ce 23068+out_whsrc:
4a4d8108
AM
23069+ if (a->src_wh_dentry)
23070+ au_ren_rev_whsrc(err, a);
4f0767ce 23071+out_success:
4a4d8108
AM
23072+ dput(a->src_wh_dentry);
23073+ dput(a->dst_wh_dentry);
4f0767ce 23074+out_thargs:
4a4d8108
AM
23075+ if (a->thargs) {
23076+ dput(a->h_dst);
23077+ au_whtmp_rmdir_free(a->thargs);
23078+ a->thargs = NULL;
23079+ }
4f0767ce 23080+out:
4a4d8108 23081+ return err;
dece6358 23082+}
1facf9fc 23083+
1308ab2a 23084+/* ---------------------------------------------------------------------- */
1facf9fc 23085+
4a4d8108
AM
23086+/*
23087+ * test if @dentry dir can be rename destination or not.
23088+ * success means, it is a logically empty dir.
23089+ */
23090+static int may_rename_dstdir(struct dentry *dentry, struct au_nhash *whlist)
1308ab2a 23091+{
4a4d8108 23092+ return au_test_empty(dentry, whlist);
1308ab2a 23093+}
1facf9fc 23094+
4a4d8108 23095+/*
8b6a4947
AM
23096+ * test if @a->src_dentry dir can be rename source or not.
23097+ * if it can, return 0.
4a4d8108
AM
23098+ * success means,
23099+ * - it is a logically empty dir.
23100+ * - or, it exists on writable branch and has no children including whiteouts
8b6a4947 23101+ * on the lower branch unless DIRREN is on.
4a4d8108 23102+ */
8b6a4947 23103+static int may_rename_srcdir(struct au_ren_args *a)
4a4d8108
AM
23104+{
23105+ int err;
23106+ unsigned int rdhash;
8b6a4947
AM
23107+ aufs_bindex_t btop, btgt;
23108+ struct dentry *dentry;
23109+ struct super_block *sb;
23110+ struct au_sbinfo *sbinfo;
1facf9fc 23111+
8b6a4947
AM
23112+ dentry = a->src_dentry;
23113+ sb = dentry->d_sb;
23114+ sbinfo = au_sbi(sb);
23115+ if (au_opt_test(sbinfo->si_mntflags, DIRREN))
23116+ au_fset_ren(a->auren_flags, DIRREN);
23117+
23118+ btgt = a->btgt;
5afbbe0d
AM
23119+ btop = au_dbtop(dentry);
23120+ if (btop != btgt) {
4a4d8108 23121+ struct au_nhash whlist;
dece6358 23122+
8b6a4947
AM
23123+ SiMustAnyLock(sb);
23124+ rdhash = sbinfo->si_rdhash;
4a4d8108
AM
23125+ if (!rdhash)
23126+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL,
23127+ dentry));
23128+ err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
23129+ if (unlikely(err))
23130+ goto out;
23131+ err = au_test_empty(dentry, &whlist);
23132+ au_nhash_wh_free(&whlist);
23133+ goto out;
23134+ }
dece6358 23135+
5afbbe0d 23136+ if (btop == au_dbtaildir(dentry))
4a4d8108 23137+ return 0; /* success */
dece6358 23138+
4a4d8108 23139+ err = au_test_empty_lower(dentry);
1facf9fc 23140+
4f0767ce 23141+out:
4a4d8108 23142+ if (err == -ENOTEMPTY) {
8b6a4947
AM
23143+ if (au_ftest_ren(a->auren_flags, DIRREN)) {
23144+ err = 0;
23145+ } else {
23146+ AuWarn1("renaming dir who has child(ren) on multiple "
23147+ "branches, is not supported\n");
23148+ err = -EXDEV;
23149+ }
4a4d8108
AM
23150+ }
23151+ return err;
23152+}
1308ab2a 23153+
4a4d8108
AM
23154+/* side effect: sets whlist and h_dentry */
23155+static int au_ren_may_dir(struct au_ren_args *a)
1308ab2a 23156+{
4a4d8108
AM
23157+ int err;
23158+ unsigned int rdhash;
23159+ struct dentry *d;
1facf9fc 23160+
4a4d8108
AM
23161+ d = a->dst_dentry;
23162+ SiMustAnyLock(d->d_sb);
1facf9fc 23163+
4a4d8108 23164+ err = 0;
f2c43d5f 23165+ if (au_ftest_ren(a->auren_flags, ISDIR_DST) && a->dst_inode) {
4a4d8108
AM
23166+ rdhash = au_sbi(d->d_sb)->si_rdhash;
23167+ if (!rdhash)
23168+ rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, d));
23169+ err = au_nhash_alloc(&a->whlist, rdhash, GFP_NOFS);
23170+ if (unlikely(err))
23171+ goto out;
1308ab2a 23172+
f2c43d5f
AM
23173+ if (!a->exchange) {
23174+ au_set_dbtop(d, a->dst_btop);
23175+ err = may_rename_dstdir(d, &a->whlist);
23176+ au_set_dbtop(d, a->btgt);
23177+ } else
8b6a4947 23178+ err = may_rename_srcdir(a);
4a4d8108 23179+ }
5afbbe0d 23180+ a->dst_h_dentry = au_h_dptr(d, au_dbtop(d));
4a4d8108
AM
23181+ if (unlikely(err))
23182+ goto out;
23183+
23184+ d = a->src_dentry;
5afbbe0d 23185+ a->src_h_dentry = au_h_dptr(d, au_dbtop(d));
f2c43d5f 23186+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) {
8b6a4947 23187+ err = may_rename_srcdir(a);
4a4d8108
AM
23188+ if (unlikely(err)) {
23189+ au_nhash_wh_free(&a->whlist);
23190+ a->whlist.nh_num = 0;
23191+ }
23192+ }
4f0767ce 23193+out:
4a4d8108 23194+ return err;
1facf9fc 23195+}
23196+
4a4d8108 23197+/* ---------------------------------------------------------------------- */
1facf9fc 23198+
4a4d8108
AM
23199+/*
23200+ * simple tests for rename.
23201+ * following the checks in vfs, plus the parent-child relationship.
23202+ */
23203+static int au_may_ren(struct au_ren_args *a)
23204+{
23205+ int err, isdir;
23206+ struct inode *h_inode;
1facf9fc 23207+
5afbbe0d 23208+ if (a->src_btop == a->btgt) {
4a4d8108 23209+ err = au_may_del(a->src_dentry, a->btgt, a->src_h_parent,
f2c43d5f 23210+ au_ftest_ren(a->auren_flags, ISDIR_SRC));
4a4d8108
AM
23211+ if (unlikely(err))
23212+ goto out;
23213+ err = -EINVAL;
23214+ if (unlikely(a->src_h_dentry == a->h_trap))
23215+ goto out;
23216+ }
1facf9fc 23217+
4a4d8108 23218+ err = 0;
5afbbe0d 23219+ if (a->dst_btop != a->btgt)
4a4d8108 23220+ goto out;
1facf9fc 23221+
027c5e7a
AM
23222+ err = -ENOTEMPTY;
23223+ if (unlikely(a->dst_h_dentry == a->h_trap))
23224+ goto out;
23225+
4a4d8108 23226+ err = -EIO;
f2c43d5f 23227+ isdir = !!au_ftest_ren(a->auren_flags, ISDIR_DST);
5527c038
JR
23228+ if (d_really_is_negative(a->dst_dentry)) {
23229+ if (d_is_negative(a->dst_h_dentry))
23230+ err = au_may_add(a->dst_dentry, a->btgt,
23231+ a->dst_h_parent, isdir);
4a4d8108 23232+ } else {
5527c038 23233+ if (unlikely(d_is_negative(a->dst_h_dentry)))
4a4d8108 23234+ goto out;
5527c038
JR
23235+ h_inode = d_inode(a->dst_h_dentry);
23236+ if (h_inode->i_nlink)
23237+ err = au_may_del(a->dst_dentry, a->btgt,
23238+ a->dst_h_parent, isdir);
4a4d8108 23239+ }
1facf9fc 23240+
4f0767ce 23241+out:
4a4d8108
AM
23242+ if (unlikely(err == -ENOENT || err == -EEXIST))
23243+ err = -EIO;
23244+ AuTraceErr(err);
23245+ return err;
23246+}
1facf9fc 23247+
1308ab2a 23248+/* ---------------------------------------------------------------------- */
1facf9fc 23249+
4a4d8108
AM
23250+/*
23251+ * locking order
23252+ * (VFS)
23253+ * - src_dir and dir by lock_rename()
acd2b654 23254+ * - inode if exists
4a4d8108
AM
23255+ * (aufs)
23256+ * - lock all
23257+ * + src_dentry and dentry by aufs_read_and_write_lock2() which calls,
23258+ * + si_read_lock
23259+ * + di_write_lock2_child()
23260+ * + di_write_lock_child()
23261+ * + ii_write_lock_child()
23262+ * + di_write_lock_child2()
23263+ * + ii_write_lock_child2()
23264+ * + src_parent and parent
23265+ * + di_write_lock_parent()
23266+ * + ii_write_lock_parent()
23267+ * + di_write_lock_parent2()
23268+ * + ii_write_lock_parent2()
23269+ * + lower src_dir and dir by vfsub_lock_rename()
23270+ * + verify the every relationships between child and parent. if any
23271+ * of them failed, unlock all and return -EBUSY.
23272+ */
23273+static void au_ren_unlock(struct au_ren_args *a)
1308ab2a 23274+{
4a4d8108
AM
23275+ vfsub_unlock_rename(a->src_h_parent, a->src_hdir,
23276+ a->dst_h_parent, a->dst_hdir);
8b6a4947
AM
23277+ if (au_ftest_ren(a->auren_flags, DIRREN)
23278+ && a->h_root)
23279+ au_hn_inode_unlock(a->h_root);
f2c43d5f 23280+ if (au_ftest_ren(a->auren_flags, MNT_WRITE))
86dc4139 23281+ vfsub_mnt_drop_write(au_br_mnt(a->br));
1308ab2a 23282+}
23283+
4a4d8108 23284+static int au_ren_lock(struct au_ren_args *a)
1308ab2a 23285+{
4a4d8108
AM
23286+ int err;
23287+ unsigned int udba;
1308ab2a 23288+
4a4d8108
AM
23289+ err = 0;
23290+ a->src_h_parent = au_h_dptr(a->src_parent, a->btgt);
23291+ a->src_hdir = au_hi(a->src_dir, a->btgt);
23292+ a->dst_h_parent = au_h_dptr(a->dst_parent, a->btgt);
23293+ a->dst_hdir = au_hi(a->dst_dir, a->btgt);
86dc4139
AM
23294+
23295+ err = vfsub_mnt_want_write(au_br_mnt(a->br));
23296+ if (unlikely(err))
23297+ goto out;
f2c43d5f 23298+ au_fset_ren(a->auren_flags, MNT_WRITE);
8b6a4947
AM
23299+ if (au_ftest_ren(a->auren_flags, DIRREN)) {
23300+ struct dentry *root;
23301+ struct inode *dir;
23302+
23303+ /*
23304+ * sbinfo is already locked, so this ii_read_lock is
23305+ * unnecessary. but our debugging feature checks it.
23306+ */
23307+ root = a->src_inode->i_sb->s_root;
23308+ if (root != a->src_parent && root != a->dst_parent) {
23309+ dir = d_inode(root);
23310+ ii_read_lock_parent3(dir);
23311+ a->h_root = au_hi(dir, a->btgt);
23312+ ii_read_unlock(dir);
23313+ au_hn_inode_lock_nested(a->h_root, AuLsc_I_PARENT3);
23314+ }
23315+ }
4a4d8108
AM
23316+ a->h_trap = vfsub_lock_rename(a->src_h_parent, a->src_hdir,
23317+ a->dst_h_parent, a->dst_hdir);
23318+ udba = au_opt_udba(a->src_dentry->d_sb);
5527c038
JR
23319+ if (unlikely(a->src_hdir->hi_inode != d_inode(a->src_h_parent)
23320+ || a->dst_hdir->hi_inode != d_inode(a->dst_h_parent)))
4a4d8108 23321+ err = au_busy_or_stale();
5afbbe0d 23322+ if (!err && au_dbtop(a->src_dentry) == a->btgt)
4a4d8108 23323+ err = au_h_verify(a->src_h_dentry, udba,
5527c038 23324+ d_inode(a->src_h_parent), a->src_h_parent,
4a4d8108 23325+ a->br);
5afbbe0d 23326+ if (!err && au_dbtop(a->dst_dentry) == a->btgt)
4a4d8108 23327+ err = au_h_verify(a->dst_h_dentry, udba,
5527c038 23328+ d_inode(a->dst_h_parent), a->dst_h_parent,
4a4d8108 23329+ a->br);
86dc4139 23330+ if (!err)
4a4d8108 23331+ goto out; /* success */
4a4d8108
AM
23332+
23333+ err = au_busy_or_stale();
4a4d8108 23334+ au_ren_unlock(a);
86dc4139 23335+
4f0767ce 23336+out:
4a4d8108 23337+ return err;
1facf9fc 23338+}
23339+
23340+/* ---------------------------------------------------------------------- */
23341+
4a4d8108 23342+static void au_ren_refresh_dir(struct au_ren_args *a)
1facf9fc 23343+{
4a4d8108 23344+ struct inode *dir;
dece6358 23345+
4a4d8108 23346+ dir = a->dst_dir;
be118d29 23347+ inode_inc_iversion(dir);
f2c43d5f 23348+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)) {
4a4d8108
AM
23349+ /* is this updating defined in POSIX? */
23350+ au_cpup_attr_timesizes(a->src_inode);
23351+ au_cpup_attr_nlink(dir, /*force*/1);
4a4d8108 23352+ }
b912730e 23353+ au_dir_ts(dir, a->btgt);
dece6358 23354+
f2c43d5f
AM
23355+ if (a->exchange) {
23356+ dir = a->src_dir;
be118d29 23357+ inode_inc_iversion(dir);
f2c43d5f
AM
23358+ if (au_ftest_ren(a->auren_flags, ISDIR_DST)) {
23359+ /* is this updating defined in POSIX? */
23360+ au_cpup_attr_timesizes(a->dst_inode);
23361+ au_cpup_attr_nlink(dir, /*force*/1);
23362+ }
23363+ au_dir_ts(dir, a->btgt);
23364+ }
23365+
23366+ if (au_ftest_ren(a->auren_flags, ISSAMEDIR))
4a4d8108 23367+ return;
dece6358 23368+
4a4d8108 23369+ dir = a->src_dir;
be118d29 23370+ inode_inc_iversion(dir);
f2c43d5f 23371+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC))
4a4d8108 23372+ au_cpup_attr_nlink(dir, /*force*/1);
b912730e 23373+ au_dir_ts(dir, a->btgt);
1facf9fc 23374+}
23375+
4a4d8108 23376+static void au_ren_refresh(struct au_ren_args *a)
1facf9fc 23377+{
5afbbe0d 23378+ aufs_bindex_t bbot, bindex;
4a4d8108
AM
23379+ struct dentry *d, *h_d;
23380+ struct inode *i, *h_i;
23381+ struct super_block *sb;
dece6358 23382+
027c5e7a
AM
23383+ d = a->dst_dentry;
23384+ d_drop(d);
23385+ if (a->h_dst)
23386+ /* already dget-ed by au_ren_or_cpup() */
23387+ au_set_h_dptr(d, a->btgt, a->h_dst);
23388+
23389+ i = a->dst_inode;
23390+ if (i) {
f2c43d5f
AM
23391+ if (!a->exchange) {
23392+ if (!au_ftest_ren(a->auren_flags, ISDIR_DST))
23393+ vfsub_drop_nlink(i);
23394+ else {
23395+ vfsub_dead_dir(i);
23396+ au_cpup_attr_timesizes(i);
23397+ }
23398+ au_update_dbrange(d, /*do_put_zero*/1);
23399+ } else
23400+ au_cpup_attr_nlink(i, /*force*/1);
027c5e7a 23401+ } else {
5afbbe0d
AM
23402+ bbot = a->btgt;
23403+ for (bindex = au_dbtop(d); bindex < bbot; bindex++)
027c5e7a 23404+ au_set_h_dptr(d, bindex, NULL);
5afbbe0d
AM
23405+ bbot = au_dbbot(d);
23406+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++)
027c5e7a
AM
23407+ au_set_h_dptr(d, bindex, NULL);
23408+ au_update_dbrange(d, /*do_put_zero*/0);
23409+ }
23410+
8b6a4947
AM
23411+ if (a->exchange
23412+ || au_ftest_ren(a->auren_flags, DIRREN)) {
23413+ d_drop(a->src_dentry);
23414+ if (au_ftest_ren(a->auren_flags, DIRREN))
23415+ au_set_dbwh(a->src_dentry, -1);
23416+ return;
23417+ }
23418+
4a4d8108 23419+ d = a->src_dentry;
8b6a4947
AM
23420+ au_set_dbwh(d, -1);
23421+ bbot = au_dbbot(d);
23422+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) {
23423+ h_d = au_h_dptr(d, bindex);
23424+ if (h_d)
23425+ au_set_h_dptr(d, bindex, NULL);
23426+ }
23427+ au_set_dbbot(d, a->btgt);
4a4d8108 23428+
8b6a4947
AM
23429+ sb = d->d_sb;
23430+ i = a->src_inode;
23431+ if (au_opt_test(au_mntflags(sb), PLINK) && au_plink_test(i))
23432+ return; /* success */
4a4d8108 23433+
8b6a4947
AM
23434+ bbot = au_ibbot(i);
23435+ for (bindex = a->btgt + 1; bindex <= bbot; bindex++) {
23436+ h_i = au_h_iptr(i, bindex);
23437+ if (h_i) {
23438+ au_xino_write(sb, bindex, h_i->i_ino, /*ino*/0);
23439+ /* ignore this error */
23440+ au_set_h_iptr(i, bindex, NULL, 0);
4a4d8108
AM
23441+ }
23442+ }
8b6a4947 23443+ au_set_ibbot(i, a->btgt);
1308ab2a 23444+}
dece6358 23445+
4a4d8108
AM
23446+/* ---------------------------------------------------------------------- */
23447+
23448+/* mainly for link(2) and rename(2) */
23449+int au_wbr(struct dentry *dentry, aufs_bindex_t btgt)
1308ab2a 23450+{
4a4d8108
AM
23451+ aufs_bindex_t bdiropq, bwh;
23452+ struct dentry *parent;
23453+ struct au_branch *br;
23454+
23455+ parent = dentry->d_parent;
5527c038 23456+ IMustLock(d_inode(parent)); /* dir is locked */
4a4d8108
AM
23457+
23458+ bdiropq = au_dbdiropq(parent);
23459+ bwh = au_dbwh(dentry);
23460+ br = au_sbr(dentry->d_sb, btgt);
23461+ if (au_br_rdonly(br)
23462+ || (0 <= bdiropq && bdiropq < btgt)
23463+ || (0 <= bwh && bwh < btgt))
23464+ btgt = -1;
23465+
23466+ AuDbg("btgt %d\n", btgt);
23467+ return btgt;
1facf9fc 23468+}
23469+
5afbbe0d 23470+/* sets src_btop, dst_btop and btgt */
4a4d8108 23471+static int au_ren_wbr(struct au_ren_args *a)
1facf9fc 23472+{
4a4d8108
AM
23473+ int err;
23474+ struct au_wr_dir_args wr_dir_args = {
23475+ /* .force_btgt = -1, */
23476+ .flags = AuWrDir_ADD_ENTRY
23477+ };
dece6358 23478+
5afbbe0d
AM
23479+ a->src_btop = au_dbtop(a->src_dentry);
23480+ a->dst_btop = au_dbtop(a->dst_dentry);
f2c43d5f
AM
23481+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC)
23482+ || au_ftest_ren(a->auren_flags, ISDIR_DST))
4a4d8108 23483+ au_fset_wrdir(wr_dir_args.flags, ISDIR);
5afbbe0d
AM
23484+ wr_dir_args.force_btgt = a->src_btop;
23485+ if (a->dst_inode && a->dst_btop < a->src_btop)
23486+ wr_dir_args.force_btgt = a->dst_btop;
4a4d8108
AM
23487+ wr_dir_args.force_btgt = au_wbr(a->dst_dentry, wr_dir_args.force_btgt);
23488+ err = au_wr_dir(a->dst_dentry, a->src_dentry, &wr_dir_args);
23489+ a->btgt = err;
f2c43d5f
AM
23490+ if (a->exchange)
23491+ au_update_dbtop(a->dst_dentry);
dece6358 23492+
4a4d8108 23493+ return err;
1facf9fc 23494+}
23495+
4a4d8108 23496+static void au_ren_dt(struct au_ren_args *a)
1facf9fc 23497+{
4a4d8108
AM
23498+ a->h_path.dentry = a->src_h_parent;
23499+ au_dtime_store(a->src_dt + AuPARENT, a->src_parent, &a->h_path);
f2c43d5f 23500+ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR)) {
4a4d8108
AM
23501+ a->h_path.dentry = a->dst_h_parent;
23502+ au_dtime_store(a->dst_dt + AuPARENT, a->dst_parent, &a->h_path);
23503+ }
1facf9fc 23504+
f2c43d5f
AM
23505+ au_fclr_ren(a->auren_flags, DT_DSTDIR);
23506+ if (!au_ftest_ren(a->auren_flags, ISDIR_SRC)
23507+ && !a->exchange)
4a4d8108 23508+ return;
dece6358 23509+
4a4d8108
AM
23510+ a->h_path.dentry = a->src_h_dentry;
23511+ au_dtime_store(a->src_dt + AuCHILD, a->src_dentry, &a->h_path);
5527c038 23512+ if (d_is_positive(a->dst_h_dentry)) {
f2c43d5f 23513+ au_fset_ren(a->auren_flags, DT_DSTDIR);
4a4d8108
AM
23514+ a->h_path.dentry = a->dst_h_dentry;
23515+ au_dtime_store(a->dst_dt + AuCHILD, a->dst_dentry, &a->h_path);
23516+ }
1308ab2a 23517+}
dece6358 23518+
4a4d8108 23519+static void au_ren_rev_dt(int err, struct au_ren_args *a)
1308ab2a 23520+{
4a4d8108 23521+ struct dentry *h_d;
febd17d6 23522+ struct inode *h_inode;
4a4d8108
AM
23523+
23524+ au_dtime_revert(a->src_dt + AuPARENT);
f2c43d5f 23525+ if (!au_ftest_ren(a->auren_flags, ISSAMEDIR))
4a4d8108
AM
23526+ au_dtime_revert(a->dst_dt + AuPARENT);
23527+
f2c43d5f 23528+ if (au_ftest_ren(a->auren_flags, ISDIR_SRC) && err != -EIO) {
4a4d8108 23529+ h_d = a->src_dt[AuCHILD].dt_h_path.dentry;
febd17d6
JR
23530+ h_inode = d_inode(h_d);
23531+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 23532+ au_dtime_revert(a->src_dt + AuCHILD);
febd17d6 23533+ inode_unlock(h_inode);
4a4d8108 23534+
f2c43d5f 23535+ if (au_ftest_ren(a->auren_flags, DT_DSTDIR)) {
4a4d8108 23536+ h_d = a->dst_dt[AuCHILD].dt_h_path.dentry;
febd17d6
JR
23537+ h_inode = d_inode(h_d);
23538+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
4a4d8108 23539+ au_dtime_revert(a->dst_dt + AuCHILD);
febd17d6 23540+ inode_unlock(h_inode);
1facf9fc 23541+ }
23542+ }
23543+}
23544+
4a4d8108
AM
23545+/* ---------------------------------------------------------------------- */
23546+
23547+int aufs_rename(struct inode *_src_dir, struct dentry *_src_dentry,
f2c43d5f
AM
23548+ struct inode *_dst_dir, struct dentry *_dst_dentry,
23549+ unsigned int _flags)
1facf9fc 23550+{
f2c43d5f 23551+ int err, lock_flags;
8b6a4947 23552+ void *rev;
4a4d8108
AM
23553+ /* reduce stack space */
23554+ struct au_ren_args *a;
f2c43d5f 23555+ struct au_pin pin;
4a4d8108 23556+
f2c43d5f 23557+ AuDbg("%pd, %pd, 0x%x\n", _src_dentry, _dst_dentry, _flags);
4a4d8108
AM
23558+ IMustLock(_src_dir);
23559+ IMustLock(_dst_dir);
23560+
f2c43d5f
AM
23561+ err = -EINVAL;
23562+ if (unlikely(_flags & RENAME_WHITEOUT))
23563+ goto out;
23564+
4a4d8108
AM
23565+ err = -ENOMEM;
23566+ BUILD_BUG_ON(sizeof(*a) > PAGE_SIZE);
23567+ a = kzalloc(sizeof(*a), GFP_NOFS);
23568+ if (unlikely(!a))
23569+ goto out;
23570+
f2c43d5f 23571+ a->flags = _flags;
acd2b654
AM
23572+ BUILD_BUG_ON(sizeof(a->exchange) == sizeof(u8)
23573+ && RENAME_EXCHANGE > U8_MAX);
f2c43d5f 23574+ a->exchange = _flags & RENAME_EXCHANGE;
4a4d8108
AM
23575+ a->src_dir = _src_dir;
23576+ a->src_dentry = _src_dentry;
5527c038
JR
23577+ a->src_inode = NULL;
23578+ if (d_really_is_positive(a->src_dentry))
23579+ a->src_inode = d_inode(a->src_dentry);
4a4d8108
AM
23580+ a->src_parent = a->src_dentry->d_parent; /* dir inode is locked */
23581+ a->dst_dir = _dst_dir;
23582+ a->dst_dentry = _dst_dentry;
5527c038
JR
23583+ a->dst_inode = NULL;
23584+ if (d_really_is_positive(a->dst_dentry))
23585+ a->dst_inode = d_inode(a->dst_dentry);
4a4d8108
AM
23586+ a->dst_parent = a->dst_dentry->d_parent; /* dir inode is locked */
23587+ if (a->dst_inode) {
f2c43d5f
AM
23588+ /*
23589+ * if EXCHANGE && src is non-dir && dst is dir,
23590+ * dst is not locked.
23591+ */
23592+ /* IMustLock(a->dst_inode); */
4a4d8108 23593+ au_igrab(a->dst_inode);
1facf9fc 23594+ }
1facf9fc 23595+
4a4d8108 23596+ err = -ENOTDIR;
f2c43d5f 23597+ lock_flags = AuLock_FLUSH | AuLock_NOPLM | AuLock_GEN;
2000de60 23598+ if (d_is_dir(a->src_dentry)) {
f2c43d5f
AM
23599+ au_fset_ren(a->auren_flags, ISDIR_SRC);
23600+ if (unlikely(!a->exchange
23601+ && d_really_is_positive(a->dst_dentry)
2000de60 23602+ && !d_is_dir(a->dst_dentry)))
4a4d8108 23603+ goto out_free;
f2c43d5f
AM
23604+ lock_flags |= AuLock_DIRS;
23605+ }
23606+ if (a->dst_inode && d_is_dir(a->dst_dentry)) {
23607+ au_fset_ren(a->auren_flags, ISDIR_DST);
23608+ if (unlikely(!a->exchange
23609+ && d_really_is_positive(a->src_dentry)
23610+ && !d_is_dir(a->src_dentry)))
23611+ goto out_free;
23612+ lock_flags |= AuLock_DIRS;
b95c5147 23613+ }
8b6a4947
AM
23614+ err = aufs_read_and_write_lock2(a->dst_dentry, a->src_dentry,
23615+ lock_flags);
e49829fe
JR
23616+ if (unlikely(err))
23617+ goto out_free;
1facf9fc 23618+
027c5e7a
AM
23619+ err = au_d_hashed_positive(a->src_dentry);
23620+ if (unlikely(err))
23621+ goto out_unlock;
23622+ err = -ENOENT;
23623+ if (a->dst_inode) {
23624+ /*
f2c43d5f 23625+ * If it is a dir, VFS unhash it before this
027c5e7a
AM
23626+ * function. It means we cannot rely upon d_unhashed().
23627+ */
23628+ if (unlikely(!a->dst_inode->i_nlink))
23629+ goto out_unlock;
f2c43d5f 23630+ if (!au_ftest_ren(a->auren_flags, ISDIR_DST)) {
027c5e7a 23631+ err = au_d_hashed_positive(a->dst_dentry);
f2c43d5f 23632+ if (unlikely(err && !a->exchange))
027c5e7a
AM
23633+ goto out_unlock;
23634+ } else if (unlikely(IS_DEADDIR(a->dst_inode)))
23635+ goto out_unlock;
23636+ } else if (unlikely(d_unhashed(a->dst_dentry)))
23637+ goto out_unlock;
23638+
7eafdf33
AM
23639+ /*
23640+ * is it possible?
79b8bda9 23641+ * yes, it happened (in linux-3.3-rcN) but I don't know why.
7eafdf33
AM
23642+ * there may exist a problem somewhere else.
23643+ */
23644+ err = -EINVAL;
5527c038 23645+ if (unlikely(d_inode(a->dst_parent) == d_inode(a->src_dentry)))
7eafdf33
AM
23646+ goto out_unlock;
23647+
f2c43d5f 23648+ au_fset_ren(a->auren_flags, ISSAMEDIR); /* temporary */
4a4d8108 23649+ di_write_lock_parent(a->dst_parent);
1facf9fc 23650+
4a4d8108
AM
23651+ /* which branch we process */
23652+ err = au_ren_wbr(a);
23653+ if (unlikely(err < 0))
027c5e7a 23654+ goto out_parent;
4a4d8108 23655+ a->br = au_sbr(a->dst_dentry->d_sb, a->btgt);
86dc4139 23656+ a->h_path.mnt = au_br_mnt(a->br);
1facf9fc 23657+
4a4d8108
AM
23658+ /* are they available to be renamed */
23659+ err = au_ren_may_dir(a);
23660+ if (unlikely(err))
23661+ goto out_children;
1facf9fc 23662+
4a4d8108 23663+ /* prepare the writable parent dir on the same branch */
5afbbe0d 23664+ if (a->dst_btop == a->btgt) {
f2c43d5f 23665+ au_fset_ren(a->auren_flags, WHDST);
4a4d8108
AM
23666+ } else {
23667+ err = au_cpup_dirs(a->dst_dentry, a->btgt);
23668+ if (unlikely(err))
23669+ goto out_children;
23670+ }
1facf9fc 23671+
f2c43d5f
AM
23672+ err = 0;
23673+ if (!a->exchange) {
23674+ if (a->src_dir != a->dst_dir) {
23675+ /*
23676+ * this temporary unlock is safe,
23677+ * because both dir->i_mutex are locked.
23678+ */
23679+ di_write_unlock(a->dst_parent);
23680+ di_write_lock_parent(a->src_parent);
23681+ err = au_wr_dir_need_wh(a->src_dentry,
23682+ au_ftest_ren(a->auren_flags,
23683+ ISDIR_SRC),
23684+ &a->btgt);
23685+ di_write_unlock(a->src_parent);
23686+ di_write_lock2_parent(a->src_parent, a->dst_parent,
23687+ /*isdir*/1);
23688+ au_fclr_ren(a->auren_flags, ISSAMEDIR);
23689+ } else
23690+ err = au_wr_dir_need_wh(a->src_dentry,
23691+ au_ftest_ren(a->auren_flags,
23692+ ISDIR_SRC),
23693+ &a->btgt);
23694+ }
4a4d8108
AM
23695+ if (unlikely(err < 0))
23696+ goto out_children;
23697+ if (err)
f2c43d5f 23698+ au_fset_ren(a->auren_flags, WHSRC);
1facf9fc 23699+
86dc4139 23700+ /* cpup src */
5afbbe0d 23701+ if (a->src_btop != a->btgt) {
86dc4139
AM
23702+ err = au_pin(&pin, a->src_dentry, a->btgt,
23703+ au_opt_udba(a->src_dentry->d_sb),
23704+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
367653fa 23705+ if (!err) {
c2b27bf2
AM
23706+ struct au_cp_generic cpg = {
23707+ .dentry = a->src_dentry,
23708+ .bdst = a->btgt,
5afbbe0d 23709+ .bsrc = a->src_btop,
c2b27bf2
AM
23710+ .len = -1,
23711+ .pin = &pin,
23712+ .flags = AuCpup_DTIME | AuCpup_HOPEN
23713+ };
5afbbe0d 23714+ AuDebugOn(au_dbtop(a->src_dentry) != a->src_btop);
c2b27bf2 23715+ err = au_sio_cpup_simple(&cpg);
367653fa 23716+ au_unpin(&pin);
86dc4139 23717+ }
86dc4139
AM
23718+ if (unlikely(err))
23719+ goto out_children;
5afbbe0d 23720+ a->src_btop = a->btgt;
86dc4139 23721+ a->src_h_dentry = au_h_dptr(a->src_dentry, a->btgt);
f2c43d5f
AM
23722+ if (!a->exchange)
23723+ au_fset_ren(a->auren_flags, WHSRC);
23724+ }
23725+
23726+ /* cpup dst */
23727+ if (a->exchange && a->dst_inode
23728+ && a->dst_btop != a->btgt) {
23729+ err = au_pin(&pin, a->dst_dentry, a->btgt,
23730+ au_opt_udba(a->dst_dentry->d_sb),
23731+ AuPin_DI_LOCKED | AuPin_MNT_WRITE);
23732+ if (!err) {
23733+ struct au_cp_generic cpg = {
23734+ .dentry = a->dst_dentry,
23735+ .bdst = a->btgt,
23736+ .bsrc = a->dst_btop,
23737+ .len = -1,
23738+ .pin = &pin,
23739+ .flags = AuCpup_DTIME | AuCpup_HOPEN
23740+ };
23741+ err = au_sio_cpup_simple(&cpg);
23742+ au_unpin(&pin);
23743+ }
23744+ if (unlikely(err))
23745+ goto out_children;
23746+ a->dst_btop = a->btgt;
23747+ a->dst_h_dentry = au_h_dptr(a->dst_dentry, a->btgt);
86dc4139
AM
23748+ }
23749+
4a4d8108
AM
23750+ /* lock them all */
23751+ err = au_ren_lock(a);
23752+ if (unlikely(err))
86dc4139 23753+ /* leave the copied-up one */
4a4d8108 23754+ goto out_children;
1facf9fc 23755+
f2c43d5f
AM
23756+ if (!a->exchange) {
23757+ if (!au_opt_test(au_mntflags(a->dst_dir->i_sb), UDBA_NONE))
23758+ err = au_may_ren(a);
23759+ else if (unlikely(a->dst_dentry->d_name.len > AUFS_MAX_NAMELEN))
23760+ err = -ENAMETOOLONG;
23761+ if (unlikely(err))
23762+ goto out_hdir;
23763+ }
1facf9fc 23764+
4a4d8108
AM
23765+ /* store timestamps to be revertible */
23766+ au_ren_dt(a);
1facf9fc 23767+
8b6a4947
AM
23768+ /* store dirren info */
23769+ if (au_ftest_ren(a->auren_flags, DIRREN)) {
23770+ err = au_dr_rename(a->src_dentry, a->btgt,
23771+ &a->dst_dentry->d_name, &rev);
23772+ AuTraceErr(err);
23773+ if (unlikely(err))
23774+ goto out_dt;
23775+ }
23776+
4a4d8108
AM
23777+ /* here we go */
23778+ err = do_rename(a);
23779+ if (unlikely(err))
8b6a4947
AM
23780+ goto out_dirren;
23781+
23782+ if (au_ftest_ren(a->auren_flags, DIRREN))
23783+ au_dr_rename_fin(a->src_dentry, a->btgt, rev);
4a4d8108
AM
23784+
23785+ /* update dir attributes */
23786+ au_ren_refresh_dir(a);
23787+
23788+ /* dput/iput all lower dentries */
23789+ au_ren_refresh(a);
23790+
23791+ goto out_hdir; /* success */
23792+
8b6a4947
AM
23793+out_dirren:
23794+ if (au_ftest_ren(a->auren_flags, DIRREN))
23795+ au_dr_rename_rev(a->src_dentry, a->btgt, rev);
4f0767ce 23796+out_dt:
4a4d8108 23797+ au_ren_rev_dt(err, a);
4f0767ce 23798+out_hdir:
4a4d8108 23799+ au_ren_unlock(a);
4f0767ce 23800+out_children:
4a4d8108 23801+ au_nhash_wh_free(&a->whlist);
5afbbe0d
AM
23802+ if (err && a->dst_inode && a->dst_btop != a->btgt) {
23803+ AuDbg("btop %d, btgt %d\n", a->dst_btop, a->btgt);
027c5e7a 23804+ au_set_h_dptr(a->dst_dentry, a->btgt, NULL);
5afbbe0d 23805+ au_set_dbtop(a->dst_dentry, a->dst_btop);
4a4d8108 23806+ }
027c5e7a 23807+out_parent:
f2c43d5f 23808+ if (!err) {
8b6a4947
AM
23809+ if (d_unhashed(a->src_dentry))
23810+ au_fset_ren(a->auren_flags, DROPPED_SRC);
23811+ if (d_unhashed(a->dst_dentry))
23812+ au_fset_ren(a->auren_flags, DROPPED_DST);
f2c43d5f
AM
23813+ if (!a->exchange)
23814+ d_move(a->src_dentry, a->dst_dentry);
8b6a4947 23815+ else {
f2c43d5f 23816+ d_exchange(a->src_dentry, a->dst_dentry);
8b6a4947
AM
23817+ if (au_ftest_ren(a->auren_flags, DROPPED_DST))
23818+ d_drop(a->dst_dentry);
23819+ }
23820+ if (au_ftest_ren(a->auren_flags, DROPPED_SRC))
23821+ d_drop(a->src_dentry);
f2c43d5f 23822+ } else {
5afbbe0d 23823+ au_update_dbtop(a->dst_dentry);
027c5e7a
AM
23824+ if (!a->dst_inode)
23825+ d_drop(a->dst_dentry);
23826+ }
f2c43d5f 23827+ if (au_ftest_ren(a->auren_flags, ISSAMEDIR))
4a4d8108
AM
23828+ di_write_unlock(a->dst_parent);
23829+ else
23830+ di_write_unlock2(a->src_parent, a->dst_parent);
027c5e7a 23831+out_unlock:
4a4d8108 23832+ aufs_read_and_write_unlock2(a->dst_dentry, a->src_dentry);
4f0767ce 23833+out_free:
4a4d8108
AM
23834+ iput(a->dst_inode);
23835+ if (a->thargs)
23836+ au_whtmp_rmdir_free(a->thargs);
9f237c51 23837+ au_kfree_rcu(a);
4f0767ce 23838+out:
4a4d8108
AM
23839+ AuTraceErr(err);
23840+ return err;
1308ab2a 23841+}
7f207e10 23842diff -urN /usr/share/empty/fs/aufs/Kconfig linux/fs/aufs/Kconfig
eca34b5c
AM
23843--- /usr/share/empty/fs/aufs/Kconfig 1970-01-01 01:00:00.000000000 +0100
23844+++ linux/fs/aufs/Kconfig 2019-07-11 15:42:14.458904362 +0200
2121bcd9
AM
23845@@ -0,0 +1,199 @@
23846+# SPDX-License-Identifier: GPL-2.0
4a4d8108
AM
23847+config AUFS_FS
23848+ tristate "Aufs (Advanced multi layered unification filesystem) support"
4a4d8108
AM
23849+ help
23850+ Aufs is a stackable unification filesystem such as Unionfs,
23851+ which unifies several directories and provides a merged single
23852+ directory.
23853+ In the early days, aufs was entirely re-designed and
23854+ re-implemented Unionfs Version 1.x series. Introducing many
23855+ original ideas, approaches and improvements, it becomes totally
23856+ different from Unionfs while keeping the basic features.
1facf9fc 23857+
4a4d8108
AM
23858+if AUFS_FS
23859+choice
23860+ prompt "Maximum number of branches"
23861+ default AUFS_BRANCH_MAX_127
23862+ help
23863+ Specifies the maximum number of branches (or member directories)
23864+ in a single aufs. The larger value consumes more system
23865+ resources and has a minor impact to performance.
23866+config AUFS_BRANCH_MAX_127
23867+ bool "127"
23868+ help
23869+ Specifies the maximum number of branches (or member directories)
23870+ in a single aufs. The larger value consumes more system
23871+ resources and has a minor impact to performance.
23872+config AUFS_BRANCH_MAX_511
23873+ bool "511"
23874+ help
23875+ Specifies the maximum number of branches (or member directories)
23876+ in a single aufs. The larger value consumes more system
23877+ resources and has a minor impact to performance.
23878+config AUFS_BRANCH_MAX_1023
23879+ bool "1023"
23880+ help
23881+ Specifies the maximum number of branches (or member directories)
23882+ in a single aufs. The larger value consumes more system
23883+ resources and has a minor impact to performance.
23884+config AUFS_BRANCH_MAX_32767
23885+ bool "32767"
23886+ help
23887+ Specifies the maximum number of branches (or member directories)
23888+ in a single aufs. The larger value consumes more system
23889+ resources and has a minor impact to performance.
23890+endchoice
1facf9fc 23891+
e49829fe
JR
23892+config AUFS_SBILIST
23893+ bool
23894+ depends on AUFS_MAGIC_SYSRQ || PROC_FS
23895+ default y
23896+ help
23897+ Automatic configuration for internal use.
23898+ When aufs supports Magic SysRq or /proc, enabled automatically.
23899+
4a4d8108
AM
23900+config AUFS_HNOTIFY
23901+ bool "Detect direct branch access (bypassing aufs)"
23902+ help
23903+ If you want to modify files on branches directly, eg. bypassing aufs,
23904+ and want aufs to detect the changes of them fully, then enable this
23905+ option and use 'udba=notify' mount option.
7f207e10 23906+ Currently there is only one available configuration, "fsnotify".
4a4d8108
AM
23907+ It will have a negative impact to the performance.
23908+ See detail in aufs.5.
dece6358 23909+
4a4d8108
AM
23910+choice
23911+ prompt "method" if AUFS_HNOTIFY
23912+ default AUFS_HFSNOTIFY
23913+config AUFS_HFSNOTIFY
23914+ bool "fsnotify"
23915+ select FSNOTIFY
4a4d8108 23916+endchoice
1facf9fc 23917+
4a4d8108
AM
23918+config AUFS_EXPORT
23919+ bool "NFS-exportable aufs"
2cbb1c4b 23920+ depends on EXPORTFS
4a4d8108
AM
23921+ help
23922+ If you want to export your mounted aufs via NFS, then enable this
23923+ option. There are several requirements for this configuration.
23924+ See detail in aufs.5.
1facf9fc 23925+
4a4d8108
AM
23926+config AUFS_INO_T_64
23927+ bool
23928+ depends on AUFS_EXPORT
23929+ depends on 64BIT && !(ALPHA || S390)
23930+ default y
23931+ help
23932+ Automatic configuration for internal use.
23933+ /* typedef unsigned long/int __kernel_ino_t */
23934+ /* alpha and s390x are int */
1facf9fc 23935+
c1595e42
JR
23936+config AUFS_XATTR
23937+ bool "support for XATTR/EA (including Security Labels)"
23938+ help
23939+ If your branch fs supports XATTR/EA and you want to make them
23940+ available in aufs too, then enable this opsion and specify the
23941+ branch attributes for EA.
23942+ See detail in aufs.5.
23943+
076b876e
AM
23944+config AUFS_FHSM
23945+ bool "File-based Hierarchical Storage Management"
23946+ help
23947+ Hierarchical Storage Management (or HSM) is a well-known feature
23948+ in the storage world. Aufs provides this feature as file-based.
23949+ with multiple branches.
23950+ These multiple branches are prioritized, ie. the topmost one
23951+ should be the fastest drive and be used heavily.
23952+
4a4d8108
AM
23953+config AUFS_RDU
23954+ bool "Readdir in userspace"
23955+ help
23956+ Aufs has two methods to provide a merged view for a directory,
23957+ by a user-space library and by kernel-space natively. The latter
23958+ is always enabled but sometimes large and slow.
23959+ If you enable this option, install the library in aufs2-util
23960+ package, and set some environment variables for your readdir(3),
23961+ then the work will be handled in user-space which generally
23962+ shows better performance in most cases.
23963+ See detail in aufs.5.
1facf9fc 23964+
8b6a4947
AM
23965+config AUFS_DIRREN
23966+ bool "Workaround for rename(2)-ing a directory"
23967+ help
23968+ By default, aufs returns EXDEV error in renameing a dir who has
23969+ his child on the lower branch, since it is a bad idea to issue
23970+ rename(2) internally for every lower branch. But user may not
23971+ accept this behaviour. So here is a workaround to allow such
23972+ rename(2) and store some extra infromation on the writable
23973+ branch. Obviously this costs high (and I don't like it).
23974+ To use this feature, you need to enable this configuration AND
23975+ to specify the mount option `dirren.'
23976+ See details in aufs.5 and the design documents.
23977+
4a4d8108
AM
23978+config AUFS_SHWH
23979+ bool "Show whiteouts"
23980+ help
23981+ If you want to make the whiteouts in aufs visible, then enable
23982+ this option and specify 'shwh' mount option. Although it may
23983+ sounds like philosophy or something, but in technically it
23984+ simply shows the name of whiteout with keeping its behaviour.
1facf9fc 23985+
4a4d8108
AM
23986+config AUFS_BR_RAMFS
23987+ bool "Ramfs (initramfs/rootfs) as an aufs branch"
23988+ help
23989+ If you want to use ramfs as an aufs branch fs, then enable this
23990+ option. Generally tmpfs is recommended.
23991+ Aufs prohibited them to be a branch fs by default, because
23992+ initramfs becomes unusable after switch_root or something
23993+ generally. If you sets initramfs as an aufs branch and boot your
23994+ system by switch_root, you will meet a problem easily since the
23995+ files in initramfs may be inaccessible.
23996+ Unless you are going to use ramfs as an aufs branch fs without
23997+ switch_root or something, leave it N.
1facf9fc 23998+
4a4d8108
AM
23999+config AUFS_BR_FUSE
24000+ bool "Fuse fs as an aufs branch"
24001+ depends on FUSE_FS
24002+ select AUFS_POLL
24003+ help
24004+ If you want to use fuse-based userspace filesystem as an aufs
24005+ branch fs, then enable this option.
24006+ It implements the internal poll(2) operation which is
24007+ implemented by fuse only (curretnly).
1facf9fc 24008+
4a4d8108
AM
24009+config AUFS_POLL
24010+ bool
24011+ help
24012+ Automatic configuration for internal use.
1facf9fc 24013+
4a4d8108
AM
24014+config AUFS_BR_HFSPLUS
24015+ bool "Hfsplus as an aufs branch"
24016+ depends on HFSPLUS_FS
24017+ default y
24018+ help
24019+ If you want to use hfsplus fs as an aufs branch fs, then enable
24020+ this option. This option introduces a small overhead at
24021+ copying-up a file on hfsplus.
1facf9fc 24022+
4a4d8108
AM
24023+config AUFS_BDEV_LOOP
24024+ bool
24025+ depends on BLK_DEV_LOOP
24026+ default y
24027+ help
24028+ Automatic configuration for internal use.
24029+ Convert =[ym] into =y.
1308ab2a 24030+
4a4d8108
AM
24031+config AUFS_DEBUG
24032+ bool "Debug aufs"
24033+ help
24034+ Enable this to compile aufs internal debug code.
24035+ It will have a negative impact to the performance.
24036+
24037+config AUFS_MAGIC_SYSRQ
24038+ bool
24039+ depends on AUFS_DEBUG && MAGIC_SYSRQ
24040+ default y
24041+ help
24042+ Automatic configuration for internal use.
24043+ When aufs supports Magic SysRq, enabled automatically.
24044+endif
acd2b654 24045diff -urN /usr/share/empty/fs/aufs/lcnt.h linux/fs/aufs/lcnt.h
eca34b5c 24046--- /usr/share/empty/fs/aufs/lcnt.h 1970-01-01 01:00:00.000000000 +0100
016522bc 24047+++ linux/fs/aufs/lcnt.h 2020-01-27 10:57:18.175538316 +0100
acd2b654
AM
24048@@ -0,0 +1,186 @@
24049+/* SPDX-License-Identifier: GPL-2.0 */
24050+/*
016522bc 24051+ * Copyright (C) 2018-2020 Junjiro R. Okajima
acd2b654
AM
24052+ *
24053+ * This program, aufs is free software; you can redistribute it and/or modify
24054+ * it under the terms of the GNU General Public License as published by
24055+ * the Free Software Foundation; either version 2 of the License, or
24056+ * (at your option) any later version.
24057+ *
24058+ * This program is distributed in the hope that it will be useful,
24059+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24060+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24061+ * GNU General Public License for more details.
24062+ *
24063+ * You should have received a copy of the GNU General Public License
24064+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
24065+ */
24066+
24067+/*
24068+ * simple long counter wrapper
24069+ */
24070+
24071+#ifndef __AUFS_LCNT_H__
24072+#define __AUFS_LCNT_H__
24073+
24074+#ifdef __KERNEL__
24075+
24076+#include "debug.h"
24077+
24078+#define AuLCntATOMIC 1
24079+#define AuLCntPCPUCNT 2
24080+/*
24081+ * why does percpu_refcount require extra synchronize_rcu()s in
24082+ * au_br_do_free()
24083+ */
24084+#define AuLCntPCPUREF 3
24085+
24086+/* #define AuLCntChosen AuLCntATOMIC */
24087+#define AuLCntChosen AuLCntPCPUCNT
24088+/* #define AuLCntChosen AuLCntPCPUREF */
24089+
24090+#if AuLCntChosen == AuLCntATOMIC
24091+#include <linux/atomic.h>
24092+
24093+typedef atomic_long_t au_lcnt_t;
24094+
24095+static inline int au_lcnt_init(au_lcnt_t *cnt, void *release __maybe_unused)
24096+{
24097+ atomic_long_set(cnt, 0);
24098+ return 0;
24099+}
24100+
24101+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused)
24102+{
24103+ /* empty */
24104+}
24105+
24106+static inline void au_lcnt_fin(au_lcnt_t *cnt __maybe_unused,
24107+ int do_sync __maybe_unused)
24108+{
24109+ /* empty */
24110+}
24111+
24112+static inline void au_lcnt_inc(au_lcnt_t *cnt)
24113+{
24114+ atomic_long_inc(cnt);
24115+}
24116+
24117+static inline void au_lcnt_dec(au_lcnt_t *cnt)
24118+{
24119+ atomic_long_dec(cnt);
24120+}
24121+
24122+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev __maybe_unused)
24123+{
24124+ return atomic_long_read(cnt);
24125+}
24126+#endif
24127+
24128+#if AuLCntChosen == AuLCntPCPUCNT
24129+#include <linux/percpu_counter.h>
24130+
24131+typedef struct percpu_counter au_lcnt_t;
24132+
24133+static inline int au_lcnt_init(au_lcnt_t *cnt, void *release __maybe_unused)
24134+{
24135+ return percpu_counter_init(cnt, 0, GFP_NOFS);
24136+}
24137+
24138+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused)
24139+{
24140+ /* empty */
24141+}
24142+
24143+static inline void au_lcnt_fin(au_lcnt_t *cnt, int do_sync __maybe_unused)
24144+{
24145+ percpu_counter_destroy(cnt);
24146+}
24147+
24148+static inline void au_lcnt_inc(au_lcnt_t *cnt)
24149+{
24150+ percpu_counter_inc(cnt);
24151+}
24152+
24153+static inline void au_lcnt_dec(au_lcnt_t *cnt)
24154+{
24155+ percpu_counter_dec(cnt);
24156+}
24157+
24158+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev __maybe_unused)
24159+{
24160+ s64 n;
24161+
24162+ n = percpu_counter_sum(cnt);
24163+ BUG_ON(n < 0);
24164+ if (LONG_MAX != LLONG_MAX
24165+ && n > LONG_MAX)
24166+ AuWarn1("%s\n", "wrap-around");
24167+
24168+ return n;
24169+}
24170+#endif
24171+
24172+#if AuLCntChosen == AuLCntPCPUREF
24173+#include <linux/percpu-refcount.h>
24174+
24175+typedef struct percpu_ref au_lcnt_t;
24176+
24177+static inline int au_lcnt_init(au_lcnt_t *cnt, percpu_ref_func_t *release)
24178+{
24179+ if (!release)
24180+ release = percpu_ref_exit;
24181+ return percpu_ref_init(cnt, release, /*percpu mode*/0, GFP_NOFS);
24182+}
24183+
24184+static inline void au_lcnt_wait_for_fin(au_lcnt_t *cnt __maybe_unused)
24185+{
24186+ synchronize_rcu();
24187+}
24188+
24189+static inline void au_lcnt_fin(au_lcnt_t *cnt, int do_sync)
24190+{
24191+ percpu_ref_kill(cnt);
24192+ if (do_sync)
24193+ au_lcnt_wait_for_fin(cnt);
24194+}
24195+
24196+static inline void au_lcnt_inc(au_lcnt_t *cnt)
24197+{
24198+ percpu_ref_get(cnt);
24199+}
24200+
24201+static inline void au_lcnt_dec(au_lcnt_t *cnt)
24202+{
24203+ percpu_ref_put(cnt);
24204+}
24205+
24206+/*
24207+ * avoid calling this func as possible.
24208+ */
24209+static inline long au_lcnt_read(au_lcnt_t *cnt, int do_rev)
24210+{
24211+ long l;
24212+
24213+ percpu_ref_switch_to_atomic_sync(cnt);
24214+ l = atomic_long_read(&cnt->count);
24215+ if (do_rev)
24216+ percpu_ref_switch_to_percpu(cnt);
24217+
24218+ /* percpu_ref is initialized by 1 instead of 0 */
24219+ return l - 1;
24220+}
24221+#endif
24222+
24223+#ifdef CONFIG_AUFS_DEBUG
24224+#define AuLCntZero(val) do { \
24225+ long l = val; \
24226+ if (l) \
24227+ AuDbg("%s = %ld\n", #val, l); \
24228+} while (0)
24229+#else
24230+#define AuLCntZero(val) do {} while (0)
24231+#endif
24232+
24233+#endif /* __KERNEL__ */
24234+#endif /* __AUFS_LCNT_H__ */
7f207e10 24235diff -urN /usr/share/empty/fs/aufs/loop.c linux/fs/aufs/loop.c
eca34b5c 24236--- /usr/share/empty/fs/aufs/loop.c 1970-01-01 01:00:00.000000000 +0100
016522bc 24237+++ linux/fs/aufs/loop.c 2020-01-27 10:57:18.175538316 +0100
062440b3 24238@@ -0,0 +1,148 @@
cd7a4cd9 24239+// SPDX-License-Identifier: GPL-2.0
1facf9fc 24240+/*
016522bc 24241+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 24242+ *
24243+ * This program, aufs is free software; you can redistribute it and/or modify
24244+ * it under the terms of the GNU General Public License as published by
24245+ * the Free Software Foundation; either version 2 of the License, or
24246+ * (at your option) any later version.
dece6358
AM
24247+ *
24248+ * This program is distributed in the hope that it will be useful,
24249+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24250+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24251+ * GNU General Public License for more details.
24252+ *
24253+ * You should have received a copy of the GNU General Public License
523b37e3 24254+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24255+ */
24256+
24257+/*
24258+ * support for loopback block device as a branch
24259+ */
24260+
1facf9fc 24261+#include "aufs.h"
24262+
392086de
AM
24263+/* added into drivers/block/loop.c */
24264+static struct file *(*backing_file_func)(struct super_block *sb);
24265+
1facf9fc 24266+/*
24267+ * test if two lower dentries have overlapping branches.
24268+ */
b752ccd1 24269+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding)
1facf9fc 24270+{
b752ccd1 24271+ struct super_block *h_sb;
392086de
AM
24272+ struct file *backing_file;
24273+
24274+ if (unlikely(!backing_file_func)) {
24275+ /* don't load "loop" module here */
24276+ backing_file_func = symbol_get(loop_backing_file);
24277+ if (unlikely(!backing_file_func))
24278+ /* "loop" module is not loaded */
24279+ return 0;
24280+ }
1facf9fc 24281+
b752ccd1 24282+ h_sb = h_adding->d_sb;
392086de
AM
24283+ backing_file = backing_file_func(h_sb);
24284+ if (!backing_file)
1facf9fc 24285+ return 0;
24286+
2000de60 24287+ h_adding = backing_file->f_path.dentry;
b752ccd1
AM
24288+ /*
24289+ * h_adding can be local NFS.
24290+ * in this case aufs cannot detect the loop.
24291+ */
24292+ if (unlikely(h_adding->d_sb == sb))
1facf9fc 24293+ return 1;
b752ccd1 24294+ return !!au_test_subdir(h_adding, sb->s_root);
1facf9fc 24295+}
24296+
24297+/* true if a kernel thread named 'loop[0-9].*' accesses a file */
24298+int au_test_loopback_kthread(void)
24299+{
b752ccd1
AM
24300+ int ret;
24301+ struct task_struct *tsk = current;
a2a7ad62 24302+ char c, comm[sizeof(tsk->comm)];
b752ccd1
AM
24303+
24304+ ret = 0;
24305+ if (tsk->flags & PF_KTHREAD) {
a2a7ad62
AM
24306+ get_task_comm(comm, tsk);
24307+ c = comm[4];
b752ccd1 24308+ ret = ('0' <= c && c <= '9'
a2a7ad62 24309+ && !strncmp(comm, "loop", 4));
b752ccd1 24310+ }
1facf9fc 24311+
b752ccd1 24312+ return ret;
1facf9fc 24313+}
87a755f4
AM
24314+
24315+/* ---------------------------------------------------------------------- */
24316+
24317+#define au_warn_loopback_step 16
24318+static int au_warn_loopback_nelem = au_warn_loopback_step;
24319+static unsigned long *au_warn_loopback_array;
24320+
24321+void au_warn_loopback(struct super_block *h_sb)
24322+{
24323+ int i, new_nelem;
24324+ unsigned long *a, magic;
24325+ static DEFINE_SPINLOCK(spin);
24326+
24327+ magic = h_sb->s_magic;
24328+ spin_lock(&spin);
24329+ a = au_warn_loopback_array;
24330+ for (i = 0; i < au_warn_loopback_nelem && *a; i++)
24331+ if (a[i] == magic) {
24332+ spin_unlock(&spin);
24333+ return;
24334+ }
24335+
24336+ /* h_sb is new to us, print it */
24337+ if (i < au_warn_loopback_nelem) {
24338+ a[i] = magic;
24339+ goto pr;
24340+ }
24341+
24342+ /* expand the array */
24343+ new_nelem = au_warn_loopback_nelem + au_warn_loopback_step;
24344+ a = au_kzrealloc(au_warn_loopback_array,
24345+ au_warn_loopback_nelem * sizeof(unsigned long),
e2f27e51
AM
24346+ new_nelem * sizeof(unsigned long), GFP_ATOMIC,
24347+ /*may_shrink*/0);
87a755f4
AM
24348+ if (a) {
24349+ au_warn_loopback_nelem = new_nelem;
24350+ au_warn_loopback_array = a;
24351+ a[i] = magic;
24352+ goto pr;
24353+ }
24354+
24355+ spin_unlock(&spin);
24356+ AuWarn1("realloc failed, ignored\n");
24357+ return;
24358+
24359+pr:
24360+ spin_unlock(&spin);
0c3ec466
AM
24361+ pr_warn("you may want to try another patch for loopback file "
24362+ "on %s(0x%lx) branch\n", au_sbtype(h_sb), magic);
87a755f4
AM
24363+}
24364+
24365+int au_loopback_init(void)
24366+{
24367+ int err;
24368+ struct super_block *sb __maybe_unused;
24369+
fbc438ed 24370+ BUILD_BUG_ON(sizeof(sb->s_magic) != sizeof(*au_warn_loopback_array));
87a755f4
AM
24371+
24372+ err = 0;
24373+ au_warn_loopback_array = kcalloc(au_warn_loopback_step,
24374+ sizeof(unsigned long), GFP_NOFS);
24375+ if (unlikely(!au_warn_loopback_array))
24376+ err = -ENOMEM;
24377+
24378+ return err;
24379+}
24380+
24381+void au_loopback_fin(void)
24382+{
79b8bda9
AM
24383+ if (backing_file_func)
24384+ symbol_put(loop_backing_file);
9f237c51 24385+ au_kfree_try_rcu(au_warn_loopback_array);
87a755f4 24386+}
7f207e10 24387diff -urN /usr/share/empty/fs/aufs/loop.h linux/fs/aufs/loop.h
eca34b5c 24388--- /usr/share/empty/fs/aufs/loop.h 1970-01-01 01:00:00.000000000 +0100
016522bc 24389+++ linux/fs/aufs/loop.h 2020-01-27 10:57:18.175538316 +0100
eca801bf 24390@@ -0,0 +1,55 @@
062440b3 24391+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 24392+/*
016522bc 24393+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 24394+ *
24395+ * This program, aufs is free software; you can redistribute it and/or modify
24396+ * it under the terms of the GNU General Public License as published by
24397+ * the Free Software Foundation; either version 2 of the License, or
24398+ * (at your option) any later version.
dece6358
AM
24399+ *
24400+ * This program is distributed in the hope that it will be useful,
24401+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24402+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24403+ * GNU General Public License for more details.
24404+ *
24405+ * You should have received a copy of the GNU General Public License
523b37e3 24406+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24407+ */
24408+
24409+/*
24410+ * support for loopback mount as a branch
24411+ */
24412+
24413+#ifndef __AUFS_LOOP_H__
24414+#define __AUFS_LOOP_H__
24415+
24416+#ifdef __KERNEL__
24417+
dece6358
AM
24418+struct dentry;
24419+struct super_block;
1facf9fc 24420+
24421+#ifdef CONFIG_AUFS_BDEV_LOOP
392086de
AM
24422+/* drivers/block/loop.c */
24423+struct file *loop_backing_file(struct super_block *sb);
24424+
1facf9fc 24425+/* loop.c */
b752ccd1 24426+int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding);
1facf9fc 24427+int au_test_loopback_kthread(void);
87a755f4
AM
24428+void au_warn_loopback(struct super_block *h_sb);
24429+
24430+int au_loopback_init(void);
24431+void au_loopback_fin(void);
1facf9fc 24432+#else
83b672a5 24433+AuStub(struct file *, loop_backing_file, return NULL, struct super_block *sb)
eca801bf 24434+
4a4d8108 24435+AuStubInt0(au_test_loopback_overlap, struct super_block *sb,
b752ccd1 24436+ struct dentry *h_adding)
4a4d8108 24437+AuStubInt0(au_test_loopback_kthread, void)
87a755f4
AM
24438+AuStubVoid(au_warn_loopback, struct super_block *h_sb)
24439+
24440+AuStubInt0(au_loopback_init, void)
24441+AuStubVoid(au_loopback_fin, void)
1facf9fc 24442+#endif /* BLK_DEV_LOOP */
24443+
24444+#endif /* __KERNEL__ */
24445+#endif /* __AUFS_LOOP_H__ */
7f207e10 24446diff -urN /usr/share/empty/fs/aufs/magic.mk linux/fs/aufs/magic.mk
eca34b5c
AM
24447--- /usr/share/empty/fs/aufs/magic.mk 1970-01-01 01:00:00.000000000 +0100
24448+++ linux/fs/aufs/magic.mk 2019-07-11 15:42:14.468904634 +0200
2121bcd9
AM
24449@@ -0,0 +1,31 @@
24450+# SPDX-License-Identifier: GPL-2.0
1facf9fc 24451+
24452+# defined in ${srctree}/fs/fuse/inode.c
24453+# tristate
24454+ifdef CONFIG_FUSE_FS
24455+ccflags-y += -DFUSE_SUPER_MAGIC=0x65735546
24456+endif
24457+
1facf9fc 24458+# defined in ${srctree}/fs/xfs/xfs_sb.h
24459+# tristate
24460+ifdef CONFIG_XFS_FS
24461+ccflags-y += -DXFS_SB_MAGIC=0x58465342
24462+endif
24463+
24464+# defined in ${srctree}/fs/configfs/mount.c
24465+# tristate
24466+ifdef CONFIG_CONFIGFS_FS
24467+ccflags-y += -DCONFIGFS_MAGIC=0x62656570
24468+endif
24469+
1facf9fc 24470+# defined in ${srctree}/fs/ubifs/ubifs.h
24471+# tristate
24472+ifdef CONFIG_UBIFS_FS
24473+ccflags-y += -DUBIFS_SUPER_MAGIC=0x24051905
24474+endif
4a4d8108
AM
24475+
24476+# defined in ${srctree}/fs/hfsplus/hfsplus_raw.h
24477+# tristate
24478+ifdef CONFIG_HFSPLUS_FS
24479+ccflags-y += -DHFSPLUS_SUPER_MAGIC=0x482b
24480+endif
7f207e10 24481diff -urN /usr/share/empty/fs/aufs/Makefile linux/fs/aufs/Makefile
eca34b5c
AM
24482--- /usr/share/empty/fs/aufs/Makefile 1970-01-01 01:00:00.000000000 +0100
24483+++ linux/fs/aufs/Makefile 2019-07-11 15:42:14.462237786 +0200
2121bcd9
AM
24484@@ -0,0 +1,46 @@
24485+# SPDX-License-Identifier: GPL-2.0
4a4d8108
AM
24486+
24487+include ${src}/magic.mk
24488+ifeq (${CONFIG_AUFS_FS},m)
24489+include ${src}/conf.mk
24490+endif
24491+-include ${src}/priv_def.mk
24492+
24493+# cf. include/linux/kernel.h
24494+# enable pr_debug
24495+ccflags-y += -DDEBUG
f6c5ef8b
AM
24496+# sparse requires the full pathname
24497+ifdef M
523b37e3 24498+ccflags-y += -include ${M}/../../include/uapi/linux/aufs_type.h
f6c5ef8b 24499+else
523b37e3 24500+ccflags-y += -include ${srctree}/include/uapi/linux/aufs_type.h
f6c5ef8b 24501+endif
4a4d8108
AM
24502+
24503+obj-$(CONFIG_AUFS_FS) += aufs.o
24504+aufs-y := module.o sbinfo.o super.o branch.o xino.o sysaufs.o opts.o \
24505+ wkq.o vfsub.o dcsub.o \
e49829fe 24506+ cpup.o whout.o wbr_policy.o \
4a4d8108
AM
24507+ dinfo.o dentry.o \
24508+ dynop.o \
24509+ finfo.o file.o f_op.o \
24510+ dir.o vdir.o \
24511+ iinfo.o inode.o i_op.o i_op_add.o i_op_del.o i_op_ren.o \
c2b27bf2 24512+ mvdown.o ioctl.o
4a4d8108
AM
24513+
24514+# all are boolean
e49829fe 24515+aufs-$(CONFIG_PROC_FS) += procfs.o plink.o
4a4d8108
AM
24516+aufs-$(CONFIG_SYSFS) += sysfs.o
24517+aufs-$(CONFIG_DEBUG_FS) += dbgaufs.o
24518+aufs-$(CONFIG_AUFS_BDEV_LOOP) += loop.o
24519+aufs-$(CONFIG_AUFS_HNOTIFY) += hnotify.o
24520+aufs-$(CONFIG_AUFS_HFSNOTIFY) += hfsnotify.o
4a4d8108 24521+aufs-$(CONFIG_AUFS_EXPORT) += export.o
c1595e42
JR
24522+aufs-$(CONFIG_AUFS_XATTR) += xattr.o
24523+aufs-$(CONFIG_FS_POSIX_ACL) += posix_acl.o
8b6a4947 24524+aufs-$(CONFIG_AUFS_DIRREN) += dirren.o
076b876e 24525+aufs-$(CONFIG_AUFS_FHSM) += fhsm.o
4a4d8108
AM
24526+aufs-$(CONFIG_AUFS_POLL) += poll.o
24527+aufs-$(CONFIG_AUFS_RDU) += rdu.o
4a4d8108
AM
24528+aufs-$(CONFIG_AUFS_BR_HFSPLUS) += hfsplus.o
24529+aufs-$(CONFIG_AUFS_DEBUG) += debug.o
24530+aufs-$(CONFIG_AUFS_MAGIC_SYSRQ) += sysrq.o
7f207e10 24531diff -urN /usr/share/empty/fs/aufs/module.c linux/fs/aufs/module.c
eca34b5c 24532--- /usr/share/empty/fs/aufs/module.c 1970-01-01 01:00:00.000000000 +0100
016522bc 24533+++ linux/fs/aufs/module.c 2020-01-27 10:57:18.175538316 +0100
062440b3 24534@@ -0,0 +1,273 @@
cd7a4cd9 24535+// SPDX-License-Identifier: GPL-2.0
1facf9fc 24536+/*
016522bc 24537+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 24538+ *
24539+ * This program, aufs is free software; you can redistribute it and/or modify
24540+ * it under the terms of the GNU General Public License as published by
24541+ * the Free Software Foundation; either version 2 of the License, or
24542+ * (at your option) any later version.
dece6358
AM
24543+ *
24544+ * This program is distributed in the hope that it will be useful,
24545+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24546+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24547+ * GNU General Public License for more details.
24548+ *
24549+ * You should have received a copy of the GNU General Public License
523b37e3 24550+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24551+ */
24552+
24553+/*
24554+ * module global variables and operations
24555+ */
24556+
24557+#include <linux/module.h>
24558+#include <linux/seq_file.h>
24559+#include "aufs.h"
24560+
e2f27e51
AM
24561+/* shrinkable realloc */
24562+void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink)
1facf9fc 24563+{
e2f27e51
AM
24564+ size_t sz;
24565+ int diff;
1facf9fc 24566+
e2f27e51
AM
24567+ sz = 0;
24568+ diff = -1;
24569+ if (p) {
24570+#if 0 /* unused */
24571+ if (!new_sz) {
9f237c51 24572+ au_kfree_rcu(p);
e2f27e51
AM
24573+ p = NULL;
24574+ goto out;
24575+ }
24576+#else
24577+ AuDebugOn(!new_sz);
24578+#endif
24579+ sz = ksize(p);
24580+ diff = au_kmidx_sub(sz, new_sz);
24581+ }
24582+ if (sz && !diff)
24583+ goto out;
24584+
24585+ if (sz < new_sz)
24586+ /* expand or SLOB */
24587+ p = krealloc(p, new_sz, gfp);
24588+ else if (new_sz < sz && may_shrink) {
24589+ /* shrink */
24590+ void *q;
24591+
24592+ q = kmalloc(new_sz, gfp);
24593+ if (q) {
24594+ if (p) {
24595+ memcpy(q, p, new_sz);
9f237c51 24596+ au_kfree_try_rcu(p);
e2f27e51
AM
24597+ }
24598+ p = q;
24599+ } else
24600+ p = NULL;
24601+ }
24602+
24603+out:
24604+ return p;
24605+}
24606+
24607+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp,
24608+ int may_shrink)
24609+{
24610+ p = au_krealloc(p, new_sz, gfp, may_shrink);
24611+ if (p && new_sz > nused)
1facf9fc 24612+ memset(p + nused, 0, new_sz - nused);
24613+ return p;
24614+}
24615+
24616+/* ---------------------------------------------------------------------- */
1facf9fc 24617+/*
24618+ * aufs caches
24619+ */
1c60b727 24620+struct kmem_cache *au_cache[AuCache_Last];
5afbbe0d
AM
24621+
24622+static void au_cache_fin(void)
24623+{
24624+ int i;
24625+
24626+ /*
24627+ * Make sure all delayed rcu free inodes are flushed before we
24628+ * destroy cache.
24629+ */
24630+ rcu_barrier();
24631+
24632+ /* excluding AuCache_HNOTIFY */
24633+ BUILD_BUG_ON(AuCache_HNOTIFY + 1 != AuCache_Last);
24634+ for (i = 0; i < AuCache_HNOTIFY; i++) {
1c60b727
AM
24635+ kmem_cache_destroy(au_cache[i]);
24636+ au_cache[i] = NULL;
5afbbe0d
AM
24637+ }
24638+}
24639+
1facf9fc 24640+static int __init au_cache_init(void)
24641+{
1c60b727
AM
24642+ au_cache[AuCache_DINFO] = AuCacheCtor(au_dinfo, au_di_init_once);
24643+ if (au_cache[AuCache_DINFO])
027c5e7a 24644+ /* SLAB_DESTROY_BY_RCU */
1c60b727 24645+ au_cache[AuCache_ICNTNR] = AuCacheCtor(au_icntnr,
f0c0a007 24646+ au_icntnr_init_once);
1c60b727
AM
24647+ if (au_cache[AuCache_ICNTNR])
24648+ au_cache[AuCache_FINFO] = AuCacheCtor(au_finfo,
f0c0a007 24649+ au_fi_init_once);
1c60b727
AM
24650+ if (au_cache[AuCache_FINFO])
24651+ au_cache[AuCache_VDIR] = AuCache(au_vdir);
24652+ if (au_cache[AuCache_VDIR])
24653+ au_cache[AuCache_DEHSTR] = AuCache(au_vdir_dehstr);
24654+ if (au_cache[AuCache_DEHSTR])
1facf9fc 24655+ return 0;
24656+
5afbbe0d 24657+ au_cache_fin();
1facf9fc 24658+ return -ENOMEM;
24659+}
24660+
1facf9fc 24661+/* ---------------------------------------------------------------------- */
24662+
24663+int au_dir_roflags;
24664+
e49829fe 24665+#ifdef CONFIG_AUFS_SBILIST
1e00d052
AM
24666+/*
24667+ * iterate_supers_type() doesn't protect us from
24668+ * remounting (branch management)
24669+ */
8b6a4947 24670+struct hlist_bl_head au_sbilist;
e49829fe
JR
24671+#endif
24672+
1facf9fc 24673+/*
24674+ * functions for module interface.
24675+ */
24676+MODULE_LICENSE("GPL");
24677+/* MODULE_LICENSE("GPL v2"); */
dece6358 24678+MODULE_AUTHOR("Junjiro R. Okajima <aufs-users@lists.sourceforge.net>");
1facf9fc 24679+MODULE_DESCRIPTION(AUFS_NAME
24680+ " -- Advanced multi layered unification filesystem");
24681+MODULE_VERSION(AUFS_VERSION);
c06a8ce3 24682+MODULE_ALIAS_FS(AUFS_NAME);
1facf9fc 24683+
1facf9fc 24684+/* this module parameter has no meaning when SYSFS is disabled */
24685+int sysaufs_brs = 1;
24686+MODULE_PARM_DESC(brs, "use <sysfs>/fs/aufs/si_*/brN");
cd7a4cd9 24687+module_param_named(brs, sysaufs_brs, int, 0444);
1facf9fc 24688+
076b876e 24689+/* this module parameter has no meaning when USER_NS is disabled */
8cdd5066 24690+bool au_userns;
076b876e 24691+MODULE_PARM_DESC(allow_userns, "allow unprivileged to mount under userns");
cd7a4cd9 24692+module_param_named(allow_userns, au_userns, bool, 0444);
076b876e 24693+
1facf9fc 24694+/* ---------------------------------------------------------------------- */
24695+
24696+static char au_esc_chars[0x20 + 3]; /* 0x01-0x20, backslash, del, and NULL */
24697+
24698+int au_seq_path(struct seq_file *seq, struct path *path)
24699+{
79b8bda9
AM
24700+ int err;
24701+
24702+ err = seq_path(seq, path, au_esc_chars);
1c60b727 24703+ if (err >= 0)
79b8bda9 24704+ err = 0;
1c60b727 24705+ else
79b8bda9
AM
24706+ err = -ENOMEM;
24707+
24708+ return err;
1facf9fc 24709+}
24710+
24711+/* ---------------------------------------------------------------------- */
24712+
24713+static int __init aufs_init(void)
24714+{
24715+ int err, i;
24716+ char *p;
24717+
24718+ p = au_esc_chars;
24719+ for (i = 1; i <= ' '; i++)
24720+ *p++ = i;
24721+ *p++ = '\\';
24722+ *p++ = '\x7f';
24723+ *p = 0;
24724+
24725+ au_dir_roflags = au_file_roflags(O_DIRECTORY | O_LARGEFILE);
24726+
b95c5147
AM
24727+ memcpy(aufs_iop_nogetattr, aufs_iop, sizeof(aufs_iop));
24728+ for (i = 0; i < AuIop_Last; i++)
24729+ aufs_iop_nogetattr[i].getattr = NULL;
24730+
1c60b727 24731+ memset(au_cache, 0, sizeof(au_cache)); /* including hnotify */
f0c0a007 24732+
e49829fe 24733+ au_sbilist_init();
1facf9fc 24734+ sysaufs_brs_init();
24735+ au_debug_init();
4a4d8108 24736+ au_dy_init();
1facf9fc 24737+ err = sysaufs_init();
24738+ if (unlikely(err))
24739+ goto out;
062440b3 24740+ err = dbgaufs_init();
4f0767ce 24741+ if (unlikely(err))
953406b4 24742+ goto out_sysaufs;
062440b3
AM
24743+ err = au_procfs_init();
24744+ if (unlikely(err))
24745+ goto out_dbgaufs;
e49829fe
JR
24746+ err = au_wkq_init();
24747+ if (unlikely(err))
24748+ goto out_procfs;
87a755f4 24749+ err = au_loopback_init();
1facf9fc 24750+ if (unlikely(err))
24751+ goto out_wkq;
87a755f4
AM
24752+ err = au_hnotify_init();
24753+ if (unlikely(err))
24754+ goto out_loopback;
1facf9fc 24755+ err = au_sysrq_init();
24756+ if (unlikely(err))
24757+ goto out_hin;
24758+ err = au_cache_init();
24759+ if (unlikely(err))
24760+ goto out_sysrq;
076b876e
AM
24761+
24762+ aufs_fs_type.fs_flags |= au_userns ? FS_USERNS_MOUNT : 0;
1facf9fc 24763+ err = register_filesystem(&aufs_fs_type);
24764+ if (unlikely(err))
24765+ goto out_cache;
076b876e 24766+
4a4d8108
AM
24767+ /* since we define pr_fmt, call printk directly */
24768+ printk(KERN_INFO AUFS_NAME " " AUFS_VERSION "\n");
1facf9fc 24769+ goto out; /* success */
24770+
4f0767ce 24771+out_cache:
1facf9fc 24772+ au_cache_fin();
4f0767ce 24773+out_sysrq:
1facf9fc 24774+ au_sysrq_fin();
4f0767ce 24775+out_hin:
4a4d8108 24776+ au_hnotify_fin();
87a755f4
AM
24777+out_loopback:
24778+ au_loopback_fin();
4f0767ce 24779+out_wkq:
1facf9fc 24780+ au_wkq_fin();
e49829fe
JR
24781+out_procfs:
24782+ au_procfs_fin();
062440b3
AM
24783+out_dbgaufs:
24784+ dbgaufs_fin();
4f0767ce 24785+out_sysaufs:
1facf9fc 24786+ sysaufs_fin();
4a4d8108 24787+ au_dy_fin();
4f0767ce 24788+out:
1facf9fc 24789+ return err;
24790+}
24791+
24792+static void __exit aufs_exit(void)
24793+{
24794+ unregister_filesystem(&aufs_fs_type);
24795+ au_cache_fin();
24796+ au_sysrq_fin();
4a4d8108 24797+ au_hnotify_fin();
87a755f4 24798+ au_loopback_fin();
1facf9fc 24799+ au_wkq_fin();
e49829fe 24800+ au_procfs_fin();
062440b3 24801+ dbgaufs_fin();
1facf9fc 24802+ sysaufs_fin();
4a4d8108 24803+ au_dy_fin();
1facf9fc 24804+}
24805+
24806+module_init(aufs_init);
24807+module_exit(aufs_exit);
7f207e10 24808diff -urN /usr/share/empty/fs/aufs/module.h linux/fs/aufs/module.h
eca34b5c 24809--- /usr/share/empty/fs/aufs/module.h 1970-01-01 01:00:00.000000000 +0100
016522bc 24810+++ linux/fs/aufs/module.h 2020-01-27 10:57:18.175538316 +0100
9f237c51 24811@@ -0,0 +1,166 @@
062440b3 24812+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 24813+/*
016522bc 24814+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 24815+ *
24816+ * This program, aufs is free software; you can redistribute it and/or modify
24817+ * it under the terms of the GNU General Public License as published by
24818+ * the Free Software Foundation; either version 2 of the License, or
24819+ * (at your option) any later version.
dece6358
AM
24820+ *
24821+ * This program is distributed in the hope that it will be useful,
24822+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24823+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24824+ * GNU General Public License for more details.
24825+ *
24826+ * You should have received a copy of the GNU General Public License
523b37e3 24827+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 24828+ */
24829+
24830+/*
24831+ * module initialization and module-global
24832+ */
24833+
24834+#ifndef __AUFS_MODULE_H__
24835+#define __AUFS_MODULE_H__
24836+
24837+#ifdef __KERNEL__
24838+
24839+#include <linux/slab.h>
9f237c51
AM
24840+#include "debug.h"
24841+#include "dentry.h"
24842+#include "dir.h"
24843+#include "file.h"
24844+#include "inode.h"
1facf9fc 24845+
dece6358
AM
24846+struct path;
24847+struct seq_file;
24848+
1facf9fc 24849+/* module parameters */
1facf9fc 24850+extern int sysaufs_brs;
8cdd5066 24851+extern bool au_userns;
1facf9fc 24852+
24853+/* ---------------------------------------------------------------------- */
24854+
24855+extern int au_dir_roflags;
24856+
e2f27e51
AM
24857+void *au_krealloc(void *p, unsigned int new_sz, gfp_t gfp, int may_shrink);
24858+void *au_kzrealloc(void *p, unsigned int nused, unsigned int new_sz, gfp_t gfp,
24859+ int may_shrink);
24860+
9f237c51
AM
24861+/*
24862+ * Comparing the size of the object with sizeof(struct rcu_head)
24863+ * case 1: object is always larger
24864+ * --> au_kfree_rcu() or au_kfree_do_rcu()
24865+ * case 2: object is always smaller
24866+ * --> au_kfree_small()
24867+ * case 3: object can be any size
24868+ * --> au_kfree_try_rcu()
24869+ */
24870+
24871+static inline void au_kfree_do_rcu(const void *p)
24872+{
24873+ struct {
24874+ struct rcu_head rcu;
24875+ } *a = (void *)p;
24876+
24877+ kfree_rcu(a, rcu);
24878+}
24879+
24880+#define au_kfree_rcu(_p) do { \
24881+ typeof(_p) p = (_p); \
24882+ BUILD_BUG_ON(sizeof(*p) < sizeof(struct rcu_head)); \
24883+ if (p) \
24884+ au_kfree_do_rcu(p); \
24885+ } while (0)
24886+
24887+#define au_kfree_do_sz_test(sz) (sz >= sizeof(struct rcu_head))
24888+#define au_kfree_sz_test(p) (p && au_kfree_do_sz_test(ksize(p)))
24889+
24890+static inline void au_kfree_try_rcu(const void *p)
24891+{
24892+ if (!p)
24893+ return;
24894+ if (au_kfree_sz_test(p))
24895+ au_kfree_do_rcu(p);
24896+ else
24897+ kfree(p);
24898+}
24899+
24900+static inline void au_kfree_small(const void *p)
24901+{
24902+ if (!p)
24903+ return;
24904+ AuDebugOn(au_kfree_sz_test(p));
24905+ kfree(p);
24906+}
24907+
e2f27e51
AM
24908+static inline int au_kmidx_sub(size_t sz, size_t new_sz)
24909+{
24910+#ifndef CONFIG_SLOB
24911+ return kmalloc_index(sz) - kmalloc_index(new_sz);
24912+#else
24913+ return -1; /* SLOB is untested */
24914+#endif
24915+}
24916+
1facf9fc 24917+int au_seq_path(struct seq_file *seq, struct path *path);
24918+
e49829fe
JR
24919+#ifdef CONFIG_PROC_FS
24920+/* procfs.c */
24921+int __init au_procfs_init(void);
24922+void au_procfs_fin(void);
24923+#else
24924+AuStubInt0(au_procfs_init, void);
24925+AuStubVoid(au_procfs_fin, void);
24926+#endif
24927+
4f0767ce
JR
24928+/* ---------------------------------------------------------------------- */
24929+
1c60b727 24930+/* kmem cache */
1facf9fc 24931+enum {
24932+ AuCache_DINFO,
24933+ AuCache_ICNTNR,
24934+ AuCache_FINFO,
24935+ AuCache_VDIR,
24936+ AuCache_DEHSTR,
7eafdf33 24937+ AuCache_HNOTIFY, /* must be last */
1facf9fc 24938+ AuCache_Last
24939+};
24940+
1c60b727 24941+extern struct kmem_cache *au_cache[AuCache_Last];
f0c0a007 24942+
4a4d8108
AM
24943+#define AuCacheFlags (SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD)
24944+#define AuCache(type) KMEM_CACHE(type, AuCacheFlags)
24945+#define AuCacheCtor(type, ctor) \
24946+ kmem_cache_create(#type, sizeof(struct type), \
24947+ __alignof__(struct type), AuCacheFlags, ctor)
1facf9fc 24948+
9f237c51
AM
24949+#define AuCacheFuncs(name, index) \
24950+ static inline struct au_##name *au_cache_alloc_##name(void) \
24951+ { return kmem_cache_alloc(au_cache[AuCache_##index], GFP_NOFS); } \
24952+ static inline void au_cache_free_##name##_norcu(struct au_##name *p) \
24953+ { kmem_cache_free(au_cache[AuCache_##index], p); } \
24954+ \
24955+ static inline void au_cache_free_##name##_rcu_cb(struct rcu_head *rcu) \
24956+ { void *p = rcu; \
24957+ p -= offsetof(struct au_##name, rcu); \
24958+ kmem_cache_free(au_cache[AuCache_##index], p); } \
24959+ static inline void au_cache_free_##name##_rcu(struct au_##name *p) \
24960+ { BUILD_BUG_ON(sizeof(struct au_##name) < sizeof(struct rcu_head)); \
24961+ call_rcu(&p->rcu, au_cache_free_##name##_rcu_cb); } \
24962+ \
24963+ static inline void au_cache_free_##name(struct au_##name *p) \
24964+ { /* au_cache_free_##name##_norcu(p); */ \
24965+ au_cache_free_##name##_rcu(p); }
1facf9fc 24966+
24967+AuCacheFuncs(dinfo, DINFO);
24968+AuCacheFuncs(icntnr, ICNTNR);
24969+AuCacheFuncs(finfo, FINFO);
24970+AuCacheFuncs(vdir, VDIR);
4a4d8108
AM
24971+AuCacheFuncs(vdir_dehstr, DEHSTR);
24972+#ifdef CONFIG_AUFS_HNOTIFY
24973+AuCacheFuncs(hnotify, HNOTIFY);
24974+#endif
1facf9fc 24975+
4a4d8108
AM
24976+#endif /* __KERNEL__ */
24977+#endif /* __AUFS_MODULE_H__ */
c2b27bf2 24978diff -urN /usr/share/empty/fs/aufs/mvdown.c linux/fs/aufs/mvdown.c
eca34b5c 24979--- /usr/share/empty/fs/aufs/mvdown.c 1970-01-01 01:00:00.000000000 +0100
016522bc 24980+++ linux/fs/aufs/mvdown.c 2020-01-27 10:57:18.175538316 +0100
ba1aed25 24981@@ -0,0 +1,706 @@
cd7a4cd9 24982+// SPDX-License-Identifier: GPL-2.0
c2b27bf2 24983+/*
016522bc 24984+ * Copyright (C) 2011-2020 Junjiro R. Okajima
c2b27bf2
AM
24985+ *
24986+ * This program, aufs is free software; you can redistribute it and/or modify
24987+ * it under the terms of the GNU General Public License as published by
24988+ * the Free Software Foundation; either version 2 of the License, or
24989+ * (at your option) any later version.
24990+ *
24991+ * This program is distributed in the hope that it will be useful,
24992+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
24993+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24994+ * GNU General Public License for more details.
24995+ *
24996+ * You should have received a copy of the GNU General Public License
523b37e3
AM
24997+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
24998+ */
24999+
25000+/*
25001+ * move-down, opposite of copy-up
c2b27bf2
AM
25002+ */
25003+
25004+#include "aufs.h"
25005+
c2b27bf2
AM
25006+struct au_mvd_args {
25007+ struct {
c2b27bf2
AM
25008+ struct super_block *h_sb;
25009+ struct dentry *h_parent;
25010+ struct au_hinode *hdir;
392086de 25011+ struct inode *h_dir, *h_inode;
c1595e42 25012+ struct au_pin pin;
c2b27bf2
AM
25013+ } info[AUFS_MVDOWN_NARRAY];
25014+
25015+ struct aufs_mvdown mvdown;
25016+ struct dentry *dentry, *parent;
25017+ struct inode *inode, *dir;
25018+ struct super_block *sb;
25019+ aufs_bindex_t bopq, bwh, bfound;
25020+ unsigned char rename_lock;
c2b27bf2
AM
25021+};
25022+
392086de 25023+#define mvd_errno mvdown.au_errno
076b876e
AM
25024+#define mvd_bsrc mvdown.stbr[AUFS_MVDOWN_UPPER].bindex
25025+#define mvd_src_brid mvdown.stbr[AUFS_MVDOWN_UPPER].brid
25026+#define mvd_bdst mvdown.stbr[AUFS_MVDOWN_LOWER].bindex
25027+#define mvd_dst_brid mvdown.stbr[AUFS_MVDOWN_LOWER].brid
c2b27bf2 25028+
392086de
AM
25029+#define mvd_h_src_sb info[AUFS_MVDOWN_UPPER].h_sb
25030+#define mvd_h_src_parent info[AUFS_MVDOWN_UPPER].h_parent
25031+#define mvd_hdir_src info[AUFS_MVDOWN_UPPER].hdir
25032+#define mvd_h_src_dir info[AUFS_MVDOWN_UPPER].h_dir
25033+#define mvd_h_src_inode info[AUFS_MVDOWN_UPPER].h_inode
c1595e42 25034+#define mvd_pin_src info[AUFS_MVDOWN_UPPER].pin
392086de
AM
25035+
25036+#define mvd_h_dst_sb info[AUFS_MVDOWN_LOWER].h_sb
25037+#define mvd_h_dst_parent info[AUFS_MVDOWN_LOWER].h_parent
25038+#define mvd_hdir_dst info[AUFS_MVDOWN_LOWER].hdir
25039+#define mvd_h_dst_dir info[AUFS_MVDOWN_LOWER].h_dir
25040+#define mvd_h_dst_inode info[AUFS_MVDOWN_LOWER].h_inode
c1595e42 25041+#define mvd_pin_dst info[AUFS_MVDOWN_LOWER].pin
c2b27bf2
AM
25042+
25043+#define AU_MVD_PR(flag, ...) do { \
25044+ if (flag) \
25045+ pr_err(__VA_ARGS__); \
25046+ } while (0)
25047+
076b876e
AM
25048+static int find_lower_writable(struct au_mvd_args *a)
25049+{
25050+ struct super_block *sb;
5afbbe0d 25051+ aufs_bindex_t bindex, bbot;
076b876e
AM
25052+ struct au_branch *br;
25053+
25054+ sb = a->sb;
25055+ bindex = a->mvd_bsrc;
5afbbe0d 25056+ bbot = au_sbbot(sb);
076b876e 25057+ if (a->mvdown.flags & AUFS_MVDOWN_FHSM_LOWER)
5afbbe0d 25058+ for (bindex++; bindex <= bbot; bindex++) {
076b876e
AM
25059+ br = au_sbr(sb, bindex);
25060+ if (au_br_fhsm(br->br_perm)
8b6a4947 25061+ && !sb_rdonly(au_br_sb(br)))
076b876e
AM
25062+ return bindex;
25063+ }
25064+ else if (!(a->mvdown.flags & AUFS_MVDOWN_ROLOWER))
5afbbe0d 25065+ for (bindex++; bindex <= bbot; bindex++) {
076b876e
AM
25066+ br = au_sbr(sb, bindex);
25067+ if (!au_br_rdonly(br))
25068+ return bindex;
25069+ }
25070+ else
5afbbe0d 25071+ for (bindex++; bindex <= bbot; bindex++) {
076b876e 25072+ br = au_sbr(sb, bindex);
8b6a4947 25073+ if (!sb_rdonly(au_br_sb(br))) {
076b876e
AM
25074+ if (au_br_rdonly(br))
25075+ a->mvdown.flags
25076+ |= AUFS_MVDOWN_ROLOWER_R;
25077+ return bindex;
25078+ }
25079+ }
25080+
25081+ return -1;
25082+}
25083+
c2b27bf2 25084+/* make the parent dir on bdst */
392086de 25085+static int au_do_mkdir(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25086+{
25087+ int err;
25088+
25089+ err = 0;
25090+ a->mvd_hdir_src = au_hi(a->dir, a->mvd_bsrc);
25091+ a->mvd_hdir_dst = au_hi(a->dir, a->mvd_bdst);
25092+ a->mvd_h_src_parent = au_h_dptr(a->parent, a->mvd_bsrc);
25093+ a->mvd_h_dst_parent = NULL;
5afbbe0d 25094+ if (au_dbbot(a->parent) >= a->mvd_bdst)
c2b27bf2
AM
25095+ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst);
25096+ if (!a->mvd_h_dst_parent) {
25097+ err = au_cpdown_dirs(a->dentry, a->mvd_bdst);
25098+ if (unlikely(err)) {
392086de 25099+ AU_MVD_PR(dmsg, "cpdown_dirs failed\n");
c2b27bf2
AM
25100+ goto out;
25101+ }
25102+ a->mvd_h_dst_parent = au_h_dptr(a->parent, a->mvd_bdst);
25103+ }
25104+
25105+out:
25106+ AuTraceErr(err);
25107+ return err;
25108+}
25109+
25110+/* lock them all */
392086de 25111+static int au_do_lock(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25112+{
25113+ int err;
25114+ struct dentry *h_trap;
25115+
25116+ a->mvd_h_src_sb = au_sbr_sb(a->sb, a->mvd_bsrc);
25117+ a->mvd_h_dst_sb = au_sbr_sb(a->sb, a->mvd_bdst);
c1595e42
JR
25118+ err = au_pin(&a->mvd_pin_dst, a->dentry, a->mvd_bdst,
25119+ au_opt_udba(a->sb),
25120+ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
25121+ AuTraceErr(err);
25122+ if (unlikely(err)) {
25123+ AU_MVD_PR(dmsg, "pin_dst failed\n");
25124+ goto out;
25125+ }
25126+
c2b27bf2
AM
25127+ if (a->mvd_h_src_sb != a->mvd_h_dst_sb) {
25128+ a->rename_lock = 0;
c1595e42
JR
25129+ au_pin_init(&a->mvd_pin_src, a->dentry, a->mvd_bsrc,
25130+ AuLsc_DI_PARENT, AuLsc_I_PARENT3,
25131+ au_opt_udba(a->sb),
25132+ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
25133+ err = au_do_pin(&a->mvd_pin_src);
25134+ AuTraceErr(err);
5527c038 25135+ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent);
c1595e42
JR
25136+ if (unlikely(err)) {
25137+ AU_MVD_PR(dmsg, "pin_src failed\n");
25138+ goto out_dst;
25139+ }
25140+ goto out; /* success */
c2b27bf2
AM
25141+ }
25142+
c2b27bf2 25143+ a->rename_lock = 1;
c1595e42
JR
25144+ au_pin_hdir_unlock(&a->mvd_pin_dst);
25145+ err = au_pin(&a->mvd_pin_src, a->dentry, a->mvd_bsrc,
25146+ au_opt_udba(a->sb),
25147+ AuPin_MNT_WRITE | AuPin_DI_LOCKED);
25148+ AuTraceErr(err);
5527c038 25149+ a->mvd_h_src_dir = d_inode(a->mvd_h_src_parent);
c1595e42
JR
25150+ if (unlikely(err)) {
25151+ AU_MVD_PR(dmsg, "pin_src failed\n");
25152+ au_pin_hdir_lock(&a->mvd_pin_dst);
25153+ goto out_dst;
25154+ }
25155+ au_pin_hdir_unlock(&a->mvd_pin_src);
c2b27bf2
AM
25156+ h_trap = vfsub_lock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
25157+ a->mvd_h_dst_parent, a->mvd_hdir_dst);
25158+ if (h_trap) {
25159+ err = (h_trap != a->mvd_h_src_parent);
25160+ if (err)
25161+ err = (h_trap != a->mvd_h_dst_parent);
25162+ }
25163+ BUG_ON(err); /* it should never happen */
c1595e42
JR
25164+ if (unlikely(a->mvd_h_src_dir != au_pinned_h_dir(&a->mvd_pin_src))) {
25165+ err = -EBUSY;
25166+ AuTraceErr(err);
25167+ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
25168+ a->mvd_h_dst_parent, a->mvd_hdir_dst);
25169+ au_pin_hdir_lock(&a->mvd_pin_src);
25170+ au_unpin(&a->mvd_pin_src);
25171+ au_pin_hdir_lock(&a->mvd_pin_dst);
25172+ goto out_dst;
25173+ }
25174+ goto out; /* success */
c2b27bf2 25175+
c1595e42
JR
25176+out_dst:
25177+ au_unpin(&a->mvd_pin_dst);
c2b27bf2
AM
25178+out:
25179+ AuTraceErr(err);
25180+ return err;
25181+}
25182+
392086de 25183+static void au_do_unlock(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2 25184+{
c1595e42
JR
25185+ if (!a->rename_lock)
25186+ au_unpin(&a->mvd_pin_src);
25187+ else {
c2b27bf2
AM
25188+ vfsub_unlock_rename(a->mvd_h_src_parent, a->mvd_hdir_src,
25189+ a->mvd_h_dst_parent, a->mvd_hdir_dst);
c1595e42
JR
25190+ au_pin_hdir_lock(&a->mvd_pin_src);
25191+ au_unpin(&a->mvd_pin_src);
25192+ au_pin_hdir_lock(&a->mvd_pin_dst);
25193+ }
25194+ au_unpin(&a->mvd_pin_dst);
c2b27bf2
AM
25195+}
25196+
25197+/* copy-down the file */
392086de 25198+static int au_do_cpdown(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25199+{
25200+ int err;
25201+ struct au_cp_generic cpg = {
25202+ .dentry = a->dentry,
25203+ .bdst = a->mvd_bdst,
25204+ .bsrc = a->mvd_bsrc,
25205+ .len = -1,
c1595e42 25206+ .pin = &a->mvd_pin_dst,
c2b27bf2
AM
25207+ .flags = AuCpup_DTIME | AuCpup_HOPEN
25208+ };
25209+
25210+ AuDbg("b%d, b%d\n", cpg.bsrc, cpg.bdst);
392086de
AM
25211+ if (a->mvdown.flags & AUFS_MVDOWN_OWLOWER)
25212+ au_fset_cpup(cpg.flags, OVERWRITE);
25213+ if (a->mvdown.flags & AUFS_MVDOWN_ROLOWER)
25214+ au_fset_cpup(cpg.flags, RWDST);
c2b27bf2
AM
25215+ err = au_sio_cpdown_simple(&cpg);
25216+ if (unlikely(err))
392086de 25217+ AU_MVD_PR(dmsg, "cpdown failed\n");
c2b27bf2
AM
25218+
25219+ AuTraceErr(err);
25220+ return err;
25221+}
25222+
25223+/*
25224+ * unlink the whiteout on bdst if exist which may be created by UDBA while we
25225+ * were sleeping
25226+ */
392086de 25227+static int au_do_unlink_wh(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25228+{
25229+ int err;
25230+ struct path h_path;
25231+ struct au_branch *br;
523b37e3 25232+ struct inode *delegated;
c2b27bf2
AM
25233+
25234+ br = au_sbr(a->sb, a->mvd_bdst);
25235+ h_path.dentry = au_wh_lkup(a->mvd_h_dst_parent, &a->dentry->d_name, br);
25236+ err = PTR_ERR(h_path.dentry);
25237+ if (IS_ERR(h_path.dentry)) {
392086de 25238+ AU_MVD_PR(dmsg, "wh_lkup failed\n");
c2b27bf2
AM
25239+ goto out;
25240+ }
25241+
25242+ err = 0;
5527c038 25243+ if (d_is_positive(h_path.dentry)) {
c2b27bf2 25244+ h_path.mnt = au_br_mnt(br);
523b37e3 25245+ delegated = NULL;
5527c038 25246+ err = vfsub_unlink(d_inode(a->mvd_h_dst_parent), &h_path,
523b37e3
AM
25247+ &delegated, /*force*/0);
25248+ if (unlikely(err == -EWOULDBLOCK)) {
25249+ pr_warn("cannot retry for NFSv4 delegation"
25250+ " for an internal unlink\n");
25251+ iput(delegated);
25252+ }
c2b27bf2 25253+ if (unlikely(err))
392086de 25254+ AU_MVD_PR(dmsg, "wh_unlink failed\n");
c2b27bf2
AM
25255+ }
25256+ dput(h_path.dentry);
25257+
25258+out:
25259+ AuTraceErr(err);
25260+ return err;
25261+}
25262+
25263+/*
25264+ * unlink the topmost h_dentry
c2b27bf2 25265+ */
392086de 25266+static int au_do_unlink(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25267+{
25268+ int err;
25269+ struct path h_path;
523b37e3 25270+ struct inode *delegated;
c2b27bf2
AM
25271+
25272+ h_path.mnt = au_sbr_mnt(a->sb, a->mvd_bsrc);
25273+ h_path.dentry = au_h_dptr(a->dentry, a->mvd_bsrc);
523b37e3
AM
25274+ delegated = NULL;
25275+ err = vfsub_unlink(a->mvd_h_src_dir, &h_path, &delegated, /*force*/0);
25276+ if (unlikely(err == -EWOULDBLOCK)) {
25277+ pr_warn("cannot retry for NFSv4 delegation"
25278+ " for an internal unlink\n");
25279+ iput(delegated);
25280+ }
c2b27bf2 25281+ if (unlikely(err))
392086de 25282+ AU_MVD_PR(dmsg, "unlink failed\n");
c2b27bf2
AM
25283+
25284+ AuTraceErr(err);
25285+ return err;
25286+}
25287+
076b876e
AM
25288+/* Since mvdown succeeded, we ignore an error of this function */
25289+static void au_do_stfs(const unsigned char dmsg, struct au_mvd_args *a)
25290+{
25291+ int err;
25292+ struct au_branch *br;
25293+
25294+ a->mvdown.flags |= AUFS_MVDOWN_STFS_FAILED;
25295+ br = au_sbr(a->sb, a->mvd_bsrc);
25296+ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_UPPER].stfs);
25297+ if (!err) {
25298+ br = au_sbr(a->sb, a->mvd_bdst);
25299+ a->mvdown.stbr[AUFS_MVDOWN_LOWER].brid = br->br_id;
25300+ err = au_br_stfs(br, &a->mvdown.stbr[AUFS_MVDOWN_LOWER].stfs);
25301+ }
25302+ if (!err)
25303+ a->mvdown.flags &= ~AUFS_MVDOWN_STFS_FAILED;
25304+ else
25305+ AU_MVD_PR(dmsg, "statfs failed (%d), ignored\n", err);
25306+}
25307+
c2b27bf2
AM
25308+/*
25309+ * copy-down the file and unlink the bsrc file.
25310+ * - unlink the bdst whout if exist
25311+ * - copy-down the file (with whtmp name and rename)
25312+ * - unlink the bsrc file
25313+ */
392086de 25314+static int au_do_mvdown(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25315+{
25316+ int err;
25317+
392086de 25318+ err = au_do_mkdir(dmsg, a);
c2b27bf2 25319+ if (!err)
392086de 25320+ err = au_do_lock(dmsg, a);
c2b27bf2
AM
25321+ if (unlikely(err))
25322+ goto out;
25323+
25324+ /*
25325+ * do not revert the activities we made on bdst since they should be
25326+ * harmless in aufs.
25327+ */
25328+
392086de 25329+ err = au_do_cpdown(dmsg, a);
c2b27bf2 25330+ if (!err)
392086de
AM
25331+ err = au_do_unlink_wh(dmsg, a);
25332+ if (!err && !(a->mvdown.flags & AUFS_MVDOWN_KUPPER))
25333+ err = au_do_unlink(dmsg, a);
c2b27bf2
AM
25334+ if (unlikely(err))
25335+ goto out_unlock;
25336+
c1595e42
JR
25337+ AuDbg("%pd2, 0x%x, %d --> %d\n",
25338+ a->dentry, a->mvdown.flags, a->mvd_bsrc, a->mvd_bdst);
076b876e
AM
25339+ if (find_lower_writable(a) < 0)
25340+ a->mvdown.flags |= AUFS_MVDOWN_BOTTOM;
25341+
25342+ if (a->mvdown.flags & AUFS_MVDOWN_STFS)
25343+ au_do_stfs(dmsg, a);
25344+
c2b27bf2 25345+ /* maintain internal array */
392086de
AM
25346+ if (!(a->mvdown.flags & AUFS_MVDOWN_KUPPER)) {
25347+ au_set_h_dptr(a->dentry, a->mvd_bsrc, NULL);
5afbbe0d 25348+ au_set_dbtop(a->dentry, a->mvd_bdst);
392086de 25349+ au_set_h_iptr(a->inode, a->mvd_bsrc, NULL, /*flags*/0);
5afbbe0d 25350+ au_set_ibtop(a->inode, a->mvd_bdst);
79b8bda9
AM
25351+ } else {
25352+ /* hide the lower */
25353+ au_set_h_dptr(a->dentry, a->mvd_bdst, NULL);
5afbbe0d 25354+ au_set_dbbot(a->dentry, a->mvd_bsrc);
79b8bda9 25355+ au_set_h_iptr(a->inode, a->mvd_bdst, NULL, /*flags*/0);
5afbbe0d 25356+ au_set_ibbot(a->inode, a->mvd_bsrc);
392086de 25357+ }
5afbbe0d
AM
25358+ if (au_dbbot(a->dentry) < a->mvd_bdst)
25359+ au_set_dbbot(a->dentry, a->mvd_bdst);
25360+ if (au_ibbot(a->inode) < a->mvd_bdst)
25361+ au_set_ibbot(a->inode, a->mvd_bdst);
c2b27bf2
AM
25362+
25363+out_unlock:
392086de 25364+ au_do_unlock(dmsg, a);
c2b27bf2
AM
25365+out:
25366+ AuTraceErr(err);
25367+ return err;
25368+}
25369+
25370+/* ---------------------------------------------------------------------- */
25371+
c2b27bf2 25372+/* make sure the file is idle */
392086de 25373+static int au_mvd_args_busy(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25374+{
25375+ int err, plinked;
c2b27bf2
AM
25376+
25377+ err = 0;
c2b27bf2 25378+ plinked = !!au_opt_test(au_mntflags(a->sb), PLINK);
5afbbe0d 25379+ if (au_dbtop(a->dentry) == a->mvd_bsrc
c1595e42 25380+ && au_dcount(a->dentry) == 1
c2b27bf2 25381+ && atomic_read(&a->inode->i_count) == 1
392086de 25382+ /* && a->mvd_h_src_inode->i_nlink == 1 */
c2b27bf2
AM
25383+ && (!plinked || !au_plink_test(a->inode))
25384+ && a->inode->i_nlink == 1)
25385+ goto out;
25386+
25387+ err = -EBUSY;
392086de 25388+ AU_MVD_PR(dmsg,
c1595e42 25389+ "b%d, d{b%d, c%d?}, i{c%d?, l%u}, hi{l%u}, p{%d, %d}\n",
5afbbe0d 25390+ a->mvd_bsrc, au_dbtop(a->dentry), au_dcount(a->dentry),
c2b27bf2 25391+ atomic_read(&a->inode->i_count), a->inode->i_nlink,
392086de 25392+ a->mvd_h_src_inode->i_nlink,
c2b27bf2
AM
25393+ plinked, plinked ? au_plink_test(a->inode) : 0);
25394+
25395+out:
25396+ AuTraceErr(err);
25397+ return err;
25398+}
25399+
25400+/* make sure the parent dir is fine */
392086de 25401+static int au_mvd_args_parent(const unsigned char dmsg,
c2b27bf2
AM
25402+ struct au_mvd_args *a)
25403+{
25404+ int err;
25405+ aufs_bindex_t bindex;
25406+
25407+ err = 0;
25408+ if (unlikely(au_alive_dir(a->parent))) {
25409+ err = -ENOENT;
392086de 25410+ AU_MVD_PR(dmsg, "parent dir is dead\n");
c2b27bf2
AM
25411+ goto out;
25412+ }
25413+
25414+ a->bopq = au_dbdiropq(a->parent);
25415+ bindex = au_wbr_nonopq(a->dentry, a->mvd_bdst);
25416+ AuDbg("b%d\n", bindex);
25417+ if (unlikely((bindex >= 0 && bindex < a->mvd_bdst)
25418+ || (a->bopq != -1 && a->bopq < a->mvd_bdst))) {
25419+ err = -EINVAL;
392086de
AM
25420+ a->mvd_errno = EAU_MVDOWN_OPAQUE;
25421+ AU_MVD_PR(dmsg, "ancestor is opaque b%d, b%d\n",
c2b27bf2
AM
25422+ a->bopq, a->mvd_bdst);
25423+ }
25424+
25425+out:
25426+ AuTraceErr(err);
25427+ return err;
25428+}
25429+
392086de 25430+static int au_mvd_args_intermediate(const unsigned char dmsg,
c2b27bf2
AM
25431+ struct au_mvd_args *a)
25432+{
25433+ int err;
25434+ struct au_dinfo *dinfo, *tmp;
25435+
25436+ /* lookup the next lower positive entry */
25437+ err = -ENOMEM;
25438+ tmp = au_di_alloc(a->sb, AuLsc_DI_TMP);
25439+ if (unlikely(!tmp))
25440+ goto out;
25441+
25442+ a->bfound = -1;
25443+ a->bwh = -1;
25444+ dinfo = au_di(a->dentry);
25445+ au_di_cp(tmp, dinfo);
25446+ au_di_swap(tmp, dinfo);
25447+
25448+ /* returns the number of positive dentries */
5afbbe0d
AM
25449+ err = au_lkup_dentry(a->dentry, a->mvd_bsrc + 1,
25450+ /* AuLkup_IGNORE_PERM */ 0);
c2b27bf2
AM
25451+ if (!err)
25452+ a->bwh = au_dbwh(a->dentry);
25453+ else if (err > 0)
5afbbe0d 25454+ a->bfound = au_dbtop(a->dentry);
c2b27bf2
AM
25455+
25456+ au_di_swap(tmp, dinfo);
25457+ au_rw_write_unlock(&tmp->di_rwsem);
25458+ au_di_free(tmp);
25459+ if (unlikely(err < 0))
392086de 25460+ AU_MVD_PR(dmsg, "failed look-up lower\n");
c2b27bf2
AM
25461+
25462+ /*
25463+ * here, we have these cases.
25464+ * bfound == -1
25465+ * no positive dentry under bsrc. there are more sub-cases.
25466+ * bwh < 0
25467+ * there no whiteout, we can safely move-down.
25468+ * bwh <= bsrc
25469+ * impossible
25470+ * bsrc < bwh && bwh < bdst
25471+ * there is a whiteout on RO branch. cannot proceed.
25472+ * bwh == bdst
25473+ * there is a whiteout on the RW target branch. it should
25474+ * be removed.
25475+ * bdst < bwh
25476+ * there is a whiteout somewhere unrelated branch.
25477+ * -1 < bfound && bfound <= bsrc
25478+ * impossible.
25479+ * bfound < bdst
25480+ * found, but it is on RO branch between bsrc and bdst. cannot
25481+ * proceed.
25482+ * bfound == bdst
25483+ * found, replace it if AUFS_MVDOWN_FORCE is set. otherwise return
25484+ * error.
25485+ * bdst < bfound
25486+ * found, after we create the file on bdst, it will be hidden.
25487+ */
25488+
25489+ AuDebugOn(a->bfound == -1
25490+ && a->bwh != -1
25491+ && a->bwh <= a->mvd_bsrc);
25492+ AuDebugOn(-1 < a->bfound
25493+ && a->bfound <= a->mvd_bsrc);
25494+
25495+ err = -EINVAL;
25496+ if (a->bfound == -1
25497+ && a->mvd_bsrc < a->bwh
25498+ && a->bwh != -1
25499+ && a->bwh < a->mvd_bdst) {
392086de
AM
25500+ a->mvd_errno = EAU_MVDOWN_WHITEOUT;
25501+ AU_MVD_PR(dmsg, "bsrc %d, bdst %d, bfound %d, bwh %d\n",
c2b27bf2
AM
25502+ a->mvd_bsrc, a->mvd_bdst, a->bfound, a->bwh);
25503+ goto out;
25504+ } else if (a->bfound != -1 && a->bfound < a->mvd_bdst) {
392086de
AM
25505+ a->mvd_errno = EAU_MVDOWN_UPPER;
25506+ AU_MVD_PR(dmsg, "bdst %d, bfound %d\n",
c2b27bf2
AM
25507+ a->mvd_bdst, a->bfound);
25508+ goto out;
25509+ }
25510+
25511+ err = 0; /* success */
25512+
25513+out:
25514+ AuTraceErr(err);
25515+ return err;
25516+}
25517+
392086de 25518+static int au_mvd_args_exist(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25519+{
25520+ int err;
25521+
392086de
AM
25522+ err = 0;
25523+ if (!(a->mvdown.flags & AUFS_MVDOWN_OWLOWER)
25524+ && a->bfound == a->mvd_bdst)
25525+ err = -EEXIST;
c2b27bf2
AM
25526+ AuTraceErr(err);
25527+ return err;
25528+}
25529+
392086de 25530+static int au_mvd_args(const unsigned char dmsg, struct au_mvd_args *a)
c2b27bf2
AM
25531+{
25532+ int err;
25533+ struct au_branch *br;
25534+
25535+ err = -EISDIR;
25536+ if (unlikely(S_ISDIR(a->inode->i_mode)))
25537+ goto out;
25538+
25539+ err = -EINVAL;
392086de 25540+ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_UPPER))
5afbbe0d 25541+ a->mvd_bsrc = au_ibtop(a->inode);
392086de
AM
25542+ else {
25543+ a->mvd_bsrc = au_br_index(a->sb, a->mvd_src_brid);
25544+ if (unlikely(a->mvd_bsrc < 0
5afbbe0d
AM
25545+ || (a->mvd_bsrc < au_dbtop(a->dentry)
25546+ || au_dbbot(a->dentry) < a->mvd_bsrc
392086de 25547+ || !au_h_dptr(a->dentry, a->mvd_bsrc))
5afbbe0d
AM
25548+ || (a->mvd_bsrc < au_ibtop(a->inode)
25549+ || au_ibbot(a->inode) < a->mvd_bsrc
392086de
AM
25550+ || !au_h_iptr(a->inode, a->mvd_bsrc)))) {
25551+ a->mvd_errno = EAU_MVDOWN_NOUPPER;
25552+ AU_MVD_PR(dmsg, "no upper\n");
25553+ goto out;
25554+ }
25555+ }
5afbbe0d 25556+ if (unlikely(a->mvd_bsrc == au_sbbot(a->sb))) {
392086de
AM
25557+ a->mvd_errno = EAU_MVDOWN_BOTTOM;
25558+ AU_MVD_PR(dmsg, "on the bottom\n");
c2b27bf2
AM
25559+ goto out;
25560+ }
392086de 25561+ a->mvd_h_src_inode = au_h_iptr(a->inode, a->mvd_bsrc);
c2b27bf2
AM
25562+ br = au_sbr(a->sb, a->mvd_bsrc);
25563+ err = au_br_rdonly(br);
392086de
AM
25564+ if (!(a->mvdown.flags & AUFS_MVDOWN_ROUPPER)) {
25565+ if (unlikely(err))
25566+ goto out;
25567+ } else if (!(vfsub_native_ro(a->mvd_h_src_inode)
25568+ || IS_APPEND(a->mvd_h_src_inode))) {
25569+ if (err)
25570+ a->mvdown.flags |= AUFS_MVDOWN_ROUPPER_R;
25571+ /* go on */
25572+ } else
c2b27bf2
AM
25573+ goto out;
25574+
25575+ err = -EINVAL;
392086de
AM
25576+ if (!(a->mvdown.flags & AUFS_MVDOWN_BRID_LOWER)) {
25577+ a->mvd_bdst = find_lower_writable(a);
25578+ if (unlikely(a->mvd_bdst < 0)) {
25579+ a->mvd_errno = EAU_MVDOWN_BOTTOM;
25580+ AU_MVD_PR(dmsg, "no writable lower branch\n");
25581+ goto out;
25582+ }
25583+ } else {
25584+ a->mvd_bdst = au_br_index(a->sb, a->mvd_dst_brid);
25585+ if (unlikely(a->mvd_bdst < 0
5afbbe0d 25586+ || au_sbbot(a->sb) < a->mvd_bdst)) {
392086de
AM
25587+ a->mvd_errno = EAU_MVDOWN_NOLOWERBR;
25588+ AU_MVD_PR(dmsg, "no lower brid\n");
25589+ goto out;
25590+ }
c2b27bf2
AM
25591+ }
25592+
392086de 25593+ err = au_mvd_args_busy(dmsg, a);
c2b27bf2 25594+ if (!err)
392086de 25595+ err = au_mvd_args_parent(dmsg, a);
c2b27bf2 25596+ if (!err)
392086de 25597+ err = au_mvd_args_intermediate(dmsg, a);
c2b27bf2 25598+ if (!err)
392086de 25599+ err = au_mvd_args_exist(dmsg, a);
c2b27bf2
AM
25600+ if (!err)
25601+ AuDbg("b%d, b%d\n", a->mvd_bsrc, a->mvd_bdst);
25602+
25603+out:
25604+ AuTraceErr(err);
25605+ return err;
25606+}
25607+
25608+int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *uarg)
25609+{
392086de
AM
25610+ int err, e;
25611+ unsigned char dmsg;
25612+ struct au_mvd_args *args;
79b8bda9 25613+ struct inode *inode;
c2b27bf2 25614+
79b8bda9 25615+ inode = d_inode(dentry);
c2b27bf2
AM
25616+ err = -EPERM;
25617+ if (unlikely(!capable(CAP_SYS_ADMIN)))
25618+ goto out;
25619+
392086de
AM
25620+ err = -ENOMEM;
25621+ args = kmalloc(sizeof(*args), GFP_NOFS);
25622+ if (unlikely(!args))
25623+ goto out;
25624+
25625+ err = copy_from_user(&args->mvdown, uarg, sizeof(args->mvdown));
25626+ if (!err)
ba1aed25
AM
25627+ /* VERIFY_WRITE */
25628+ err = !access_ok(uarg, sizeof(*uarg));
c2b27bf2
AM
25629+ if (unlikely(err)) {
25630+ err = -EFAULT;
392086de
AM
25631+ AuTraceErr(err);
25632+ goto out_free;
c2b27bf2 25633+ }
392086de
AM
25634+ AuDbg("flags 0x%x\n", args->mvdown.flags);
25635+ args->mvdown.flags &= ~(AUFS_MVDOWN_ROLOWER_R | AUFS_MVDOWN_ROUPPER_R);
25636+ args->mvdown.au_errno = 0;
25637+ args->dentry = dentry;
79b8bda9 25638+ args->inode = inode;
392086de 25639+ args->sb = dentry->d_sb;
c2b27bf2 25640+
392086de
AM
25641+ err = -ENOENT;
25642+ dmsg = !!(args->mvdown.flags & AUFS_MVDOWN_DMSG);
25643+ args->parent = dget_parent(dentry);
5527c038 25644+ args->dir = d_inode(args->parent);
febd17d6 25645+ inode_lock_nested(args->dir, I_MUTEX_PARENT);
392086de
AM
25646+ dput(args->parent);
25647+ if (unlikely(args->parent != dentry->d_parent)) {
25648+ AU_MVD_PR(dmsg, "parent dir is moved\n");
c2b27bf2
AM
25649+ goto out_dir;
25650+ }
25651+
febd17d6 25652+ inode_lock_nested(inode, I_MUTEX_CHILD);
b95c5147 25653+ err = aufs_read_lock(dentry, AuLock_DW | AuLock_FLUSH | AuLock_NOPLMW);
c2b27bf2
AM
25654+ if (unlikely(err))
25655+ goto out_inode;
25656+
392086de
AM
25657+ di_write_lock_parent(args->parent);
25658+ err = au_mvd_args(dmsg, args);
c2b27bf2
AM
25659+ if (unlikely(err))
25660+ goto out_parent;
25661+
392086de 25662+ err = au_do_mvdown(dmsg, args);
c2b27bf2
AM
25663+ if (unlikely(err))
25664+ goto out_parent;
c2b27bf2 25665+
392086de 25666+ au_cpup_attr_timesizes(args->dir);
79b8bda9
AM
25667+ au_cpup_attr_timesizes(inode);
25668+ if (!(args->mvdown.flags & AUFS_MVDOWN_KUPPER))
25669+ au_cpup_igen(inode, au_h_iptr(inode, args->mvd_bdst));
c2b27bf2
AM
25670+ /* au_digen_dec(dentry); */
25671+
25672+out_parent:
392086de 25673+ di_write_unlock(args->parent);
c2b27bf2
AM
25674+ aufs_read_unlock(dentry, AuLock_DW);
25675+out_inode:
febd17d6 25676+ inode_unlock(inode);
c2b27bf2 25677+out_dir:
febd17d6 25678+ inode_unlock(args->dir);
392086de
AM
25679+out_free:
25680+ e = copy_to_user(uarg, &args->mvdown, sizeof(args->mvdown));
25681+ if (unlikely(e))
25682+ err = -EFAULT;
9f237c51 25683+ au_kfree_rcu(args);
c2b27bf2
AM
25684+out:
25685+ AuTraceErr(err);
25686+ return err;
25687+}
25688diff -urN /usr/share/empty/fs/aufs/opts.c linux/fs/aufs/opts.c
eca34b5c 25689--- /usr/share/empty/fs/aufs/opts.c 1970-01-01 01:00:00.000000000 +0100
016522bc 25690+++ linux/fs/aufs/opts.c 2020-01-27 10:57:18.175538316 +0100
eca34b5c 25691@@ -0,0 +1,1880 @@
cd7a4cd9 25692+// SPDX-License-Identifier: GPL-2.0
1facf9fc 25693+/*
016522bc 25694+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 25695+ *
25696+ * This program, aufs is free software; you can redistribute it and/or modify
25697+ * it under the terms of the GNU General Public License as published by
25698+ * the Free Software Foundation; either version 2 of the License, or
25699+ * (at your option) any later version.
dece6358
AM
25700+ *
25701+ * This program is distributed in the hope that it will be useful,
25702+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
25703+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25704+ * GNU General Public License for more details.
25705+ *
25706+ * You should have received a copy of the GNU General Public License
523b37e3 25707+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 25708+ */
25709+
25710+/*
25711+ * mount options/flags
25712+ */
25713+
dece6358 25714+#include <linux/namei.h>
1facf9fc 25715+#include <linux/types.h> /* a distribution requires */
25716+#include <linux/parser.h>
25717+#include "aufs.h"
25718+
25719+/* ---------------------------------------------------------------------- */
25720+
25721+enum {
25722+ Opt_br,
7e9cd9fe
AM
25723+ Opt_add, Opt_del, Opt_mod, Opt_append, Opt_prepend,
25724+ Opt_idel, Opt_imod,
25725+ Opt_dirwh, Opt_rdcache, Opt_rdblk, Opt_rdhash,
dece6358 25726+ Opt_rdblk_def, Opt_rdhash_def,
7e9cd9fe 25727+ Opt_xino, Opt_noxino,
1facf9fc 25728+ Opt_trunc_xino, Opt_trunc_xino_v, Opt_notrunc_xino,
25729+ Opt_trunc_xino_path, Opt_itrunc_xino,
25730+ Opt_trunc_xib, Opt_notrunc_xib,
dece6358 25731+ Opt_shwh, Opt_noshwh,
1facf9fc 25732+ Opt_plink, Opt_noplink, Opt_list_plink,
25733+ Opt_udba,
4a4d8108 25734+ Opt_dio, Opt_nodio,
1facf9fc 25735+ Opt_diropq_a, Opt_diropq_w,
25736+ Opt_warn_perm, Opt_nowarn_perm,
25737+ Opt_wbr_copyup, Opt_wbr_create,
076b876e 25738+ Opt_fhsm_sec,
1facf9fc 25739+ Opt_verbose, Opt_noverbose,
25740+ Opt_sum, Opt_nosum, Opt_wsum,
076b876e 25741+ Opt_dirperm1, Opt_nodirperm1,
8b6a4947 25742+ Opt_dirren, Opt_nodirren,
c1595e42 25743+ Opt_acl, Opt_noacl,
1facf9fc 25744+ Opt_tail, Opt_ignore, Opt_ignore_silent, Opt_err
25745+};
25746+
25747+static match_table_t options = {
25748+ {Opt_br, "br=%s"},
25749+ {Opt_br, "br:%s"},
25750+
25751+ {Opt_add, "add=%d:%s"},
25752+ {Opt_add, "add:%d:%s"},
25753+ {Opt_add, "ins=%d:%s"},
25754+ {Opt_add, "ins:%d:%s"},
25755+ {Opt_append, "append=%s"},
25756+ {Opt_append, "append:%s"},
25757+ {Opt_prepend, "prepend=%s"},
25758+ {Opt_prepend, "prepend:%s"},
25759+
25760+ {Opt_del, "del=%s"},
25761+ {Opt_del, "del:%s"},
25762+ /* {Opt_idel, "idel:%d"}, */
25763+ {Opt_mod, "mod=%s"},
25764+ {Opt_mod, "mod:%s"},
25765+ /* {Opt_imod, "imod:%d:%s"}, */
25766+
25767+ {Opt_dirwh, "dirwh=%d"},
25768+
25769+ {Opt_xino, "xino=%s"},
25770+ {Opt_noxino, "noxino"},
25771+ {Opt_trunc_xino, "trunc_xino"},
25772+ {Opt_trunc_xino_v, "trunc_xino_v=%d:%d"},
25773+ {Opt_notrunc_xino, "notrunc_xino"},
25774+ {Opt_trunc_xino_path, "trunc_xino=%s"},
25775+ {Opt_itrunc_xino, "itrunc_xino=%d"},
25776+ /* {Opt_zxino, "zxino=%s"}, */
25777+ {Opt_trunc_xib, "trunc_xib"},
25778+ {Opt_notrunc_xib, "notrunc_xib"},
25779+
e49829fe 25780+#ifdef CONFIG_PROC_FS
1facf9fc 25781+ {Opt_plink, "plink"},
e49829fe
JR
25782+#else
25783+ {Opt_ignore_silent, "plink"},
25784+#endif
25785+
1facf9fc 25786+ {Opt_noplink, "noplink"},
e49829fe 25787+
1facf9fc 25788+#ifdef CONFIG_AUFS_DEBUG
25789+ {Opt_list_plink, "list_plink"},
25790+#endif
25791+
25792+ {Opt_udba, "udba=%s"},
25793+
4a4d8108
AM
25794+ {Opt_dio, "dio"},
25795+ {Opt_nodio, "nodio"},
25796+
8b6a4947
AM
25797+#ifdef CONFIG_AUFS_DIRREN
25798+ {Opt_dirren, "dirren"},
25799+ {Opt_nodirren, "nodirren"},
25800+#else
25801+ {Opt_ignore, "dirren"},
25802+ {Opt_ignore_silent, "nodirren"},
25803+#endif
25804+
076b876e
AM
25805+#ifdef CONFIG_AUFS_FHSM
25806+ {Opt_fhsm_sec, "fhsm_sec=%d"},
25807+#else
8b6a4947 25808+ {Opt_ignore, "fhsm_sec=%d"},
076b876e
AM
25809+#endif
25810+
1facf9fc 25811+ {Opt_diropq_a, "diropq=always"},
25812+ {Opt_diropq_a, "diropq=a"},
25813+ {Opt_diropq_w, "diropq=whiteouted"},
25814+ {Opt_diropq_w, "diropq=w"},
25815+
25816+ {Opt_warn_perm, "warn_perm"},
25817+ {Opt_nowarn_perm, "nowarn_perm"},
25818+
25819+ /* keep them temporary */
1facf9fc 25820+ {Opt_ignore_silent, "nodlgt"},
8b6a4947 25821+ {Opt_ignore, "clean_plink"},
1facf9fc 25822+
dece6358
AM
25823+#ifdef CONFIG_AUFS_SHWH
25824+ {Opt_shwh, "shwh"},
25825+#endif
25826+ {Opt_noshwh, "noshwh"},
25827+
076b876e
AM
25828+ {Opt_dirperm1, "dirperm1"},
25829+ {Opt_nodirperm1, "nodirperm1"},
25830+
1facf9fc 25831+ {Opt_verbose, "verbose"},
25832+ {Opt_verbose, "v"},
25833+ {Opt_noverbose, "noverbose"},
25834+ {Opt_noverbose, "quiet"},
25835+ {Opt_noverbose, "q"},
25836+ {Opt_noverbose, "silent"},
25837+
25838+ {Opt_sum, "sum"},
25839+ {Opt_nosum, "nosum"},
25840+ {Opt_wsum, "wsum"},
25841+
25842+ {Opt_rdcache, "rdcache=%d"},
25843+ {Opt_rdblk, "rdblk=%d"},
dece6358 25844+ {Opt_rdblk_def, "rdblk=def"},
1facf9fc 25845+ {Opt_rdhash, "rdhash=%d"},
dece6358 25846+ {Opt_rdhash_def, "rdhash=def"},
1facf9fc 25847+
25848+ {Opt_wbr_create, "create=%s"},
25849+ {Opt_wbr_create, "create_policy=%s"},
25850+ {Opt_wbr_copyup, "cpup=%s"},
25851+ {Opt_wbr_copyup, "copyup=%s"},
25852+ {Opt_wbr_copyup, "copyup_policy=%s"},
25853+
c1595e42
JR
25854+ /* generic VFS flag */
25855+#ifdef CONFIG_FS_POSIX_ACL
25856+ {Opt_acl, "acl"},
25857+ {Opt_noacl, "noacl"},
25858+#else
8b6a4947 25859+ {Opt_ignore, "acl"},
c1595e42
JR
25860+ {Opt_ignore_silent, "noacl"},
25861+#endif
25862+
1facf9fc 25863+ /* internal use for the scripts */
25864+ {Opt_ignore_silent, "si=%s"},
25865+
25866+ {Opt_br, "dirs=%s"},
25867+ {Opt_ignore, "debug=%d"},
25868+ {Opt_ignore, "delete=whiteout"},
25869+ {Opt_ignore, "delete=all"},
25870+ {Opt_ignore, "imap=%s"},
25871+
1308ab2a 25872+ /* temporary workaround, due to old mount(8)? */
25873+ {Opt_ignore_silent, "relatime"},
25874+
1facf9fc 25875+ {Opt_err, NULL}
25876+};
25877+
25878+/* ---------------------------------------------------------------------- */
25879+
076b876e 25880+static const char *au_parser_pattern(int val, match_table_t tbl)
1facf9fc 25881+{
076b876e
AM
25882+ struct match_token *p;
25883+
25884+ p = tbl;
25885+ while (p->pattern) {
25886+ if (p->token == val)
25887+ return p->pattern;
25888+ p++;
1facf9fc 25889+ }
25890+ BUG();
25891+ return "??";
25892+}
25893+
076b876e
AM
25894+static const char *au_optstr(int *val, match_table_t tbl)
25895+{
25896+ struct match_token *p;
25897+ int v;
25898+
25899+ v = *val;
2000de60
JR
25900+ if (!v)
25901+ goto out;
076b876e 25902+ p = tbl;
2000de60
JR
25903+ while (p->pattern) {
25904+ if (p->token
25905+ && (v & p->token) == p->token) {
076b876e
AM
25906+ *val &= ~p->token;
25907+ return p->pattern;
25908+ }
25909+ p++;
25910+ }
2000de60
JR
25911+
25912+out:
076b876e
AM
25913+ return NULL;
25914+}
25915+
1facf9fc 25916+/* ---------------------------------------------------------------------- */
25917+
1e00d052 25918+static match_table_t brperm = {
1facf9fc 25919+ {AuBrPerm_RO, AUFS_BRPERM_RO},
25920+ {AuBrPerm_RR, AUFS_BRPERM_RR},
25921+ {AuBrPerm_RW, AUFS_BRPERM_RW},
1e00d052
AM
25922+ {0, NULL}
25923+};
1facf9fc 25924+
86dc4139 25925+static match_table_t brattr = {
076b876e
AM
25926+ /* general */
25927+ {AuBrAttr_COO_REG, AUFS_BRATTR_COO_REG},
25928+ {AuBrAttr_COO_ALL, AUFS_BRATTR_COO_ALL},
c1595e42 25929+ /* 'unpin' attrib is meaningless since linux-3.18-rc1 */
86dc4139 25930+ {AuBrAttr_UNPIN, AUFS_BRATTR_UNPIN},
2000de60 25931+#ifdef CONFIG_AUFS_FHSM
076b876e 25932+ {AuBrAttr_FHSM, AUFS_BRATTR_FHSM},
2000de60
JR
25933+#endif
25934+#ifdef CONFIG_AUFS_XATTR
c1595e42
JR
25935+ {AuBrAttr_ICEX, AUFS_BRATTR_ICEX},
25936+ {AuBrAttr_ICEX_SEC, AUFS_BRATTR_ICEX_SEC},
25937+ {AuBrAttr_ICEX_SYS, AUFS_BRATTR_ICEX_SYS},
25938+ {AuBrAttr_ICEX_TR, AUFS_BRATTR_ICEX_TR},
25939+ {AuBrAttr_ICEX_USR, AUFS_BRATTR_ICEX_USR},
25940+ {AuBrAttr_ICEX_OTH, AUFS_BRATTR_ICEX_OTH},
2000de60 25941+#endif
076b876e
AM
25942+
25943+ /* ro/rr branch */
1e00d052 25944+ {AuBrRAttr_WH, AUFS_BRRATTR_WH},
076b876e
AM
25945+
25946+ /* rw branch */
25947+ {AuBrWAttr_MOO, AUFS_BRWATTR_MOO},
1e00d052 25948+ {AuBrWAttr_NoLinkWH, AUFS_BRWATTR_NLWH},
076b876e 25949+
1e00d052 25950+ {0, NULL}
1facf9fc 25951+};
25952+
1e00d052
AM
25953+static int br_attr_val(char *str, match_table_t table, substring_t args[])
25954+{
25955+ int attr, v;
25956+ char *p;
25957+
25958+ attr = 0;
25959+ do {
25960+ p = strchr(str, '+');
25961+ if (p)
25962+ *p = 0;
25963+ v = match_token(str, table, args);
076b876e
AM
25964+ if (v) {
25965+ if (v & AuBrAttr_CMOO_Mask)
25966+ attr &= ~AuBrAttr_CMOO_Mask;
1e00d052 25967+ attr |= v;
076b876e 25968+ } else {
1e00d052
AM
25969+ if (p)
25970+ *p = '+';
0c3ec466 25971+ pr_warn("ignored branch attribute %s\n", str);
1e00d052
AM
25972+ break;
25973+ }
25974+ if (p)
25975+ str = p + 1;
25976+ } while (p);
25977+
25978+ return attr;
25979+}
25980+
076b876e
AM
25981+static int au_do_optstr_br_attr(au_br_perm_str_t *str, int perm)
25982+{
25983+ int sz;
25984+ const char *p;
25985+ char *q;
25986+
076b876e
AM
25987+ q = str->a;
25988+ *q = 0;
25989+ p = au_optstr(&perm, brattr);
25990+ if (p) {
25991+ sz = strlen(p);
25992+ memcpy(q, p, sz + 1);
25993+ q += sz;
25994+ } else
25995+ goto out;
25996+
25997+ do {
25998+ p = au_optstr(&perm, brattr);
25999+ if (p) {
26000+ *q++ = '+';
26001+ sz = strlen(p);
26002+ memcpy(q, p, sz + 1);
26003+ q += sz;
26004+ }
26005+ } while (p);
26006+
26007+out:
c1595e42 26008+ return q - str->a;
076b876e
AM
26009+}
26010+
4a4d8108 26011+static int noinline_for_stack br_perm_val(char *perm)
1facf9fc 26012+{
076b876e
AM
26013+ int val, bad, sz;
26014+ char *p;
1facf9fc 26015+ substring_t args[MAX_OPT_ARGS];
076b876e 26016+ au_br_perm_str_t attr;
1facf9fc 26017+
1e00d052
AM
26018+ p = strchr(perm, '+');
26019+ if (p)
26020+ *p = 0;
26021+ val = match_token(perm, brperm, args);
26022+ if (!val) {
26023+ if (p)
26024+ *p = '+';
0c3ec466 26025+ pr_warn("ignored branch permission %s\n", perm);
1e00d052
AM
26026+ val = AuBrPerm_RO;
26027+ goto out;
26028+ }
26029+ if (!p)
26030+ goto out;
26031+
076b876e
AM
26032+ val |= br_attr_val(p + 1, brattr, args);
26033+
26034+ bad = 0;
86dc4139 26035+ switch (val & AuBrPerm_Mask) {
1e00d052
AM
26036+ case AuBrPerm_RO:
26037+ case AuBrPerm_RR:
076b876e
AM
26038+ bad = val & AuBrWAttr_Mask;
26039+ val &= ~AuBrWAttr_Mask;
1e00d052
AM
26040+ break;
26041+ case AuBrPerm_RW:
076b876e
AM
26042+ bad = val & AuBrRAttr_Mask;
26043+ val &= ~AuBrRAttr_Mask;
1e00d052
AM
26044+ break;
26045+ }
c1595e42
JR
26046+
26047+ /*
26048+ * 'unpin' attrib becomes meaningless since linux-3.18-rc1, but aufs
26049+ * does not treat it as an error, just warning.
26050+ * this is a tiny guard for the user operation.
26051+ */
26052+ if (val & AuBrAttr_UNPIN) {
26053+ bad |= AuBrAttr_UNPIN;
26054+ val &= ~AuBrAttr_UNPIN;
26055+ }
26056+
076b876e
AM
26057+ if (unlikely(bad)) {
26058+ sz = au_do_optstr_br_attr(&attr, bad);
26059+ AuDebugOn(!sz);
26060+ pr_warn("ignored branch attribute %s\n", attr.a);
26061+ }
1e00d052
AM
26062+
26063+out:
1facf9fc 26064+ return val;
26065+}
26066+
076b876e 26067+void au_optstr_br_perm(au_br_perm_str_t *str, int perm)
1facf9fc 26068+{
076b876e
AM
26069+ au_br_perm_str_t attr;
26070+ const char *p;
26071+ char *q;
1e00d052
AM
26072+ int sz;
26073+
076b876e
AM
26074+ q = str->a;
26075+ p = au_optstr(&perm, brperm);
26076+ AuDebugOn(!p || !*p);
26077+ sz = strlen(p);
26078+ memcpy(q, p, sz + 1);
26079+ q += sz;
1e00d052 26080+
076b876e
AM
26081+ sz = au_do_optstr_br_attr(&attr, perm);
26082+ if (sz) {
26083+ *q++ = '+';
26084+ memcpy(q, attr.a, sz + 1);
1e00d052
AM
26085+ }
26086+
076b876e 26087+ AuDebugOn(strlen(str->a) >= sizeof(str->a));
1facf9fc 26088+}
26089+
26090+/* ---------------------------------------------------------------------- */
26091+
26092+static match_table_t udbalevel = {
26093+ {AuOpt_UDBA_REVAL, "reval"},
26094+ {AuOpt_UDBA_NONE, "none"},
4a4d8108
AM
26095+#ifdef CONFIG_AUFS_HNOTIFY
26096+ {AuOpt_UDBA_HNOTIFY, "notify"}, /* abstraction */
26097+#ifdef CONFIG_AUFS_HFSNOTIFY
26098+ {AuOpt_UDBA_HNOTIFY, "fsnotify"},
4a4d8108 26099+#endif
1facf9fc 26100+#endif
26101+ {-1, NULL}
26102+};
26103+
4a4d8108 26104+static int noinline_for_stack udba_val(char *str)
1facf9fc 26105+{
26106+ substring_t args[MAX_OPT_ARGS];
26107+
7f207e10 26108+ return match_token(str, udbalevel, args);
1facf9fc 26109+}
26110+
26111+const char *au_optstr_udba(int udba)
26112+{
076b876e 26113+ return au_parser_pattern(udba, udbalevel);
1facf9fc 26114+}
26115+
26116+/* ---------------------------------------------------------------------- */
26117+
26118+static match_table_t au_wbr_create_policy = {
26119+ {AuWbrCreate_TDP, "tdp"},
26120+ {AuWbrCreate_TDP, "top-down-parent"},
26121+ {AuWbrCreate_RR, "rr"},
26122+ {AuWbrCreate_RR, "round-robin"},
26123+ {AuWbrCreate_MFS, "mfs"},
26124+ {AuWbrCreate_MFS, "most-free-space"},
26125+ {AuWbrCreate_MFSV, "mfs:%d"},
26126+ {AuWbrCreate_MFSV, "most-free-space:%d"},
26127+
f2c43d5f
AM
26128+ /* top-down regardless the parent, and then mfs */
26129+ {AuWbrCreate_TDMFS, "tdmfs:%d"},
26130+ {AuWbrCreate_TDMFSV, "tdmfs:%d:%d"},
26131+
1facf9fc 26132+ {AuWbrCreate_MFSRR, "mfsrr:%d"},
26133+ {AuWbrCreate_MFSRRV, "mfsrr:%d:%d"},
26134+ {AuWbrCreate_PMFS, "pmfs"},
26135+ {AuWbrCreate_PMFSV, "pmfs:%d"},
392086de
AM
26136+ {AuWbrCreate_PMFSRR, "pmfsrr:%d"},
26137+ {AuWbrCreate_PMFSRRV, "pmfsrr:%d:%d"},
1facf9fc 26138+
26139+ {-1, NULL}
26140+};
26141+
1facf9fc 26142+static int au_wbr_mfs_wmark(substring_t *arg, char *str,
26143+ struct au_opt_wbr_create *create)
26144+{
26145+ int err;
26146+ unsigned long long ull;
26147+
26148+ err = 0;
a2654f78 26149+ if (!match_u64(arg, &ull))
1facf9fc 26150+ create->mfsrr_watermark = ull;
26151+ else {
4a4d8108 26152+ pr_err("bad integer in %s\n", str);
1facf9fc 26153+ err = -EINVAL;
26154+ }
26155+
26156+ return err;
26157+}
26158+
26159+static int au_wbr_mfs_sec(substring_t *arg, char *str,
26160+ struct au_opt_wbr_create *create)
26161+{
26162+ int n, err;
26163+
26164+ err = 0;
027c5e7a 26165+ if (!match_int(arg, &n) && 0 <= n && n <= AUFS_MFS_MAX_SEC)
1facf9fc 26166+ create->mfs_second = n;
26167+ else {
4a4d8108 26168+ pr_err("bad integer in %s\n", str);
1facf9fc 26169+ err = -EINVAL;
26170+ }
26171+
26172+ return err;
26173+}
26174+
4a4d8108
AM
26175+static int noinline_for_stack
26176+au_wbr_create_val(char *str, struct au_opt_wbr_create *create)
1facf9fc 26177+{
26178+ int err, e;
26179+ substring_t args[MAX_OPT_ARGS];
26180+
26181+ err = match_token(str, au_wbr_create_policy, args);
26182+ create->wbr_create = err;
26183+ switch (err) {
26184+ case AuWbrCreate_MFSRRV:
f2c43d5f 26185+ case AuWbrCreate_TDMFSV:
392086de 26186+ case AuWbrCreate_PMFSRRV:
1facf9fc 26187+ e = au_wbr_mfs_wmark(&args[0], str, create);
26188+ if (!e)
26189+ e = au_wbr_mfs_sec(&args[1], str, create);
26190+ if (unlikely(e))
26191+ err = e;
26192+ break;
26193+ case AuWbrCreate_MFSRR:
f2c43d5f 26194+ case AuWbrCreate_TDMFS:
392086de 26195+ case AuWbrCreate_PMFSRR:
1facf9fc 26196+ e = au_wbr_mfs_wmark(&args[0], str, create);
26197+ if (unlikely(e)) {
26198+ err = e;
26199+ break;
26200+ }
26201+ /*FALLTHROUGH*/
26202+ case AuWbrCreate_MFS:
26203+ case AuWbrCreate_PMFS:
027c5e7a 26204+ create->mfs_second = AUFS_MFS_DEF_SEC;
1facf9fc 26205+ break;
26206+ case AuWbrCreate_MFSV:
26207+ case AuWbrCreate_PMFSV:
26208+ e = au_wbr_mfs_sec(&args[0], str, create);
26209+ if (unlikely(e))
26210+ err = e;
26211+ break;
26212+ }
26213+
26214+ return err;
26215+}
26216+
26217+const char *au_optstr_wbr_create(int wbr_create)
26218+{
076b876e 26219+ return au_parser_pattern(wbr_create, au_wbr_create_policy);
1facf9fc 26220+}
26221+
26222+static match_table_t au_wbr_copyup_policy = {
26223+ {AuWbrCopyup_TDP, "tdp"},
26224+ {AuWbrCopyup_TDP, "top-down-parent"},
26225+ {AuWbrCopyup_BUP, "bup"},
26226+ {AuWbrCopyup_BUP, "bottom-up-parent"},
26227+ {AuWbrCopyup_BU, "bu"},
26228+ {AuWbrCopyup_BU, "bottom-up"},
26229+ {-1, NULL}
26230+};
26231+
4a4d8108 26232+static int noinline_for_stack au_wbr_copyup_val(char *str)
1facf9fc 26233+{
26234+ substring_t args[MAX_OPT_ARGS];
26235+
26236+ return match_token(str, au_wbr_copyup_policy, args);
26237+}
26238+
26239+const char *au_optstr_wbr_copyup(int wbr_copyup)
26240+{
076b876e 26241+ return au_parser_pattern(wbr_copyup, au_wbr_copyup_policy);
1facf9fc 26242+}
26243+
26244+/* ---------------------------------------------------------------------- */
26245+
26246+static const int lkup_dirflags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
26247+
26248+static void dump_opts(struct au_opts *opts)
26249+{
26250+#ifdef CONFIG_AUFS_DEBUG
26251+ /* reduce stack space */
26252+ union {
26253+ struct au_opt_add *add;
26254+ struct au_opt_del *del;
26255+ struct au_opt_mod *mod;
26256+ struct au_opt_xino *xino;
26257+ struct au_opt_xino_itrunc *xino_itrunc;
26258+ struct au_opt_wbr_create *create;
26259+ } u;
26260+ struct au_opt *opt;
26261+
26262+ opt = opts->opt;
26263+ while (opt->type != Opt_tail) {
26264+ switch (opt->type) {
26265+ case Opt_add:
26266+ u.add = &opt->add;
26267+ AuDbg("add {b%d, %s, 0x%x, %p}\n",
26268+ u.add->bindex, u.add->pathname, u.add->perm,
26269+ u.add->path.dentry);
26270+ break;
26271+ case Opt_del:
26272+ case Opt_idel:
26273+ u.del = &opt->del;
26274+ AuDbg("del {%s, %p}\n",
26275+ u.del->pathname, u.del->h_path.dentry);
26276+ break;
26277+ case Opt_mod:
26278+ case Opt_imod:
26279+ u.mod = &opt->mod;
26280+ AuDbg("mod {%s, 0x%x, %p}\n",
26281+ u.mod->path, u.mod->perm, u.mod->h_root);
26282+ break;
26283+ case Opt_append:
26284+ u.add = &opt->add;
26285+ AuDbg("append {b%d, %s, 0x%x, %p}\n",
26286+ u.add->bindex, u.add->pathname, u.add->perm,
26287+ u.add->path.dentry);
26288+ break;
26289+ case Opt_prepend:
26290+ u.add = &opt->add;
26291+ AuDbg("prepend {b%d, %s, 0x%x, %p}\n",
26292+ u.add->bindex, u.add->pathname, u.add->perm,
26293+ u.add->path.dentry);
26294+ break;
26295+ case Opt_dirwh:
26296+ AuDbg("dirwh %d\n", opt->dirwh);
26297+ break;
26298+ case Opt_rdcache:
26299+ AuDbg("rdcache %d\n", opt->rdcache);
26300+ break;
26301+ case Opt_rdblk:
26302+ AuDbg("rdblk %u\n", opt->rdblk);
26303+ break;
dece6358
AM
26304+ case Opt_rdblk_def:
26305+ AuDbg("rdblk_def\n");
26306+ break;
1facf9fc 26307+ case Opt_rdhash:
26308+ AuDbg("rdhash %u\n", opt->rdhash);
26309+ break;
dece6358
AM
26310+ case Opt_rdhash_def:
26311+ AuDbg("rdhash_def\n");
26312+ break;
1facf9fc 26313+ case Opt_xino:
26314+ u.xino = &opt->xino;
523b37e3 26315+ AuDbg("xino {%s %pD}\n", u.xino->path, u.xino->file);
1facf9fc 26316+ break;
26317+ case Opt_trunc_xino:
26318+ AuLabel(trunc_xino);
26319+ break;
26320+ case Opt_notrunc_xino:
26321+ AuLabel(notrunc_xino);
26322+ break;
26323+ case Opt_trunc_xino_path:
26324+ case Opt_itrunc_xino:
26325+ u.xino_itrunc = &opt->xino_itrunc;
26326+ AuDbg("trunc_xino %d\n", u.xino_itrunc->bindex);
26327+ break;
1facf9fc 26328+ case Opt_noxino:
26329+ AuLabel(noxino);
26330+ break;
26331+ case Opt_trunc_xib:
26332+ AuLabel(trunc_xib);
26333+ break;
26334+ case Opt_notrunc_xib:
26335+ AuLabel(notrunc_xib);
26336+ break;
dece6358
AM
26337+ case Opt_shwh:
26338+ AuLabel(shwh);
26339+ break;
26340+ case Opt_noshwh:
26341+ AuLabel(noshwh);
26342+ break;
076b876e
AM
26343+ case Opt_dirperm1:
26344+ AuLabel(dirperm1);
26345+ break;
26346+ case Opt_nodirperm1:
26347+ AuLabel(nodirperm1);
26348+ break;
1facf9fc 26349+ case Opt_plink:
26350+ AuLabel(plink);
26351+ break;
26352+ case Opt_noplink:
26353+ AuLabel(noplink);
26354+ break;
26355+ case Opt_list_plink:
26356+ AuLabel(list_plink);
26357+ break;
26358+ case Opt_udba:
26359+ AuDbg("udba %d, %s\n",
26360+ opt->udba, au_optstr_udba(opt->udba));
26361+ break;
4a4d8108
AM
26362+ case Opt_dio:
26363+ AuLabel(dio);
26364+ break;
26365+ case Opt_nodio:
26366+ AuLabel(nodio);
26367+ break;
1facf9fc 26368+ case Opt_diropq_a:
26369+ AuLabel(diropq_a);
26370+ break;
26371+ case Opt_diropq_w:
26372+ AuLabel(diropq_w);
26373+ break;
26374+ case Opt_warn_perm:
26375+ AuLabel(warn_perm);
26376+ break;
26377+ case Opt_nowarn_perm:
26378+ AuLabel(nowarn_perm);
26379+ break;
1facf9fc 26380+ case Opt_verbose:
26381+ AuLabel(verbose);
26382+ break;
26383+ case Opt_noverbose:
26384+ AuLabel(noverbose);
26385+ break;
26386+ case Opt_sum:
26387+ AuLabel(sum);
26388+ break;
26389+ case Opt_nosum:
26390+ AuLabel(nosum);
26391+ break;
26392+ case Opt_wsum:
26393+ AuLabel(wsum);
26394+ break;
26395+ case Opt_wbr_create:
26396+ u.create = &opt->wbr_create;
26397+ AuDbg("create %d, %s\n", u.create->wbr_create,
26398+ au_optstr_wbr_create(u.create->wbr_create));
26399+ switch (u.create->wbr_create) {
26400+ case AuWbrCreate_MFSV:
26401+ case AuWbrCreate_PMFSV:
26402+ AuDbg("%d sec\n", u.create->mfs_second);
26403+ break;
26404+ case AuWbrCreate_MFSRR:
f2c43d5f 26405+ case AuWbrCreate_TDMFS:
1facf9fc 26406+ AuDbg("%llu watermark\n",
26407+ u.create->mfsrr_watermark);
26408+ break;
26409+ case AuWbrCreate_MFSRRV:
f2c43d5f 26410+ case AuWbrCreate_TDMFSV:
392086de 26411+ case AuWbrCreate_PMFSRRV:
1facf9fc 26412+ AuDbg("%llu watermark, %d sec\n",
26413+ u.create->mfsrr_watermark,
26414+ u.create->mfs_second);
26415+ break;
26416+ }
26417+ break;
26418+ case Opt_wbr_copyup:
26419+ AuDbg("copyup %d, %s\n", opt->wbr_copyup,
26420+ au_optstr_wbr_copyup(opt->wbr_copyup));
26421+ break;
076b876e
AM
26422+ case Opt_fhsm_sec:
26423+ AuDbg("fhsm_sec %u\n", opt->fhsm_second);
26424+ break;
8b6a4947
AM
26425+ case Opt_dirren:
26426+ AuLabel(dirren);
26427+ break;
26428+ case Opt_nodirren:
26429+ AuLabel(nodirren);
26430+ break;
c1595e42
JR
26431+ case Opt_acl:
26432+ AuLabel(acl);
26433+ break;
26434+ case Opt_noacl:
26435+ AuLabel(noacl);
26436+ break;
1facf9fc 26437+ default:
26438+ BUG();
26439+ }
26440+ opt++;
26441+ }
26442+#endif
26443+}
26444+
26445+void au_opts_free(struct au_opts *opts)
26446+{
26447+ struct au_opt *opt;
26448+
26449+ opt = opts->opt;
26450+ while (opt->type != Opt_tail) {
26451+ switch (opt->type) {
26452+ case Opt_add:
26453+ case Opt_append:
26454+ case Opt_prepend:
26455+ path_put(&opt->add.path);
26456+ break;
26457+ case Opt_del:
26458+ case Opt_idel:
26459+ path_put(&opt->del.h_path);
26460+ break;
26461+ case Opt_mod:
26462+ case Opt_imod:
26463+ dput(opt->mod.h_root);
26464+ break;
26465+ case Opt_xino:
26466+ fput(opt->xino.file);
26467+ break;
26468+ }
26469+ opt++;
26470+ }
26471+}
26472+
26473+static int opt_add(struct au_opt *opt, char *opt_str, unsigned long sb_flags,
26474+ aufs_bindex_t bindex)
26475+{
26476+ int err;
26477+ struct au_opt_add *add = &opt->add;
26478+ char *p;
26479+
26480+ add->bindex = bindex;
1e00d052 26481+ add->perm = AuBrPerm_RO;
1facf9fc 26482+ add->pathname = opt_str;
26483+ p = strchr(opt_str, '=');
26484+ if (p) {
26485+ *p++ = 0;
26486+ if (*p)
26487+ add->perm = br_perm_val(p);
26488+ }
26489+
26490+ err = vfsub_kern_path(add->pathname, lkup_dirflags, &add->path);
26491+ if (!err) {
26492+ if (!p) {
26493+ add->perm = AuBrPerm_RO;
26494+ if (au_test_fs_rr(add->path.dentry->d_sb))
26495+ add->perm = AuBrPerm_RR;
2121bcd9 26496+ else if (!bindex && !(sb_flags & SB_RDONLY))
1facf9fc 26497+ add->perm = AuBrPerm_RW;
26498+ }
26499+ opt->type = Opt_add;
26500+ goto out;
26501+ }
4a4d8108 26502+ pr_err("lookup failed %s (%d)\n", add->pathname, err);
1facf9fc 26503+ err = -EINVAL;
26504+
4f0767ce 26505+out:
1facf9fc 26506+ return err;
26507+}
26508+
26509+static int au_opts_parse_del(struct au_opt_del *del, substring_t args[])
26510+{
26511+ int err;
26512+
26513+ del->pathname = args[0].from;
26514+ AuDbg("del path %s\n", del->pathname);
26515+
26516+ err = vfsub_kern_path(del->pathname, lkup_dirflags, &del->h_path);
26517+ if (unlikely(err))
4a4d8108 26518+ pr_err("lookup failed %s (%d)\n", del->pathname, err);
1facf9fc 26519+
26520+ return err;
26521+}
26522+
26523+#if 0 /* reserved for future use */
26524+static int au_opts_parse_idel(struct super_block *sb, aufs_bindex_t bindex,
26525+ struct au_opt_del *del, substring_t args[])
26526+{
26527+ int err;
26528+ struct dentry *root;
26529+
26530+ err = -EINVAL;
26531+ root = sb->s_root;
26532+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d 26533+ if (bindex < 0 || au_sbbot(sb) < bindex) {
4a4d8108 26534+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 26535+ goto out;
26536+ }
26537+
26538+ err = 0;
26539+ del->h_path.dentry = dget(au_h_dptr(root, bindex));
26540+ del->h_path.mnt = mntget(au_sbr_mnt(sb, bindex));
26541+
4f0767ce 26542+out:
1facf9fc 26543+ aufs_read_unlock(root, !AuLock_IR);
26544+ return err;
26545+}
26546+#endif
26547+
4a4d8108
AM
26548+static int noinline_for_stack
26549+au_opts_parse_mod(struct au_opt_mod *mod, substring_t args[])
1facf9fc 26550+{
26551+ int err;
26552+ struct path path;
26553+ char *p;
26554+
26555+ err = -EINVAL;
26556+ mod->path = args[0].from;
26557+ p = strchr(mod->path, '=');
26558+ if (unlikely(!p)) {
acd2b654 26559+ pr_err("no permission %s\n", args[0].from);
1facf9fc 26560+ goto out;
26561+ }
26562+
26563+ *p++ = 0;
26564+ err = vfsub_kern_path(mod->path, lkup_dirflags, &path);
26565+ if (unlikely(err)) {
4a4d8108 26566+ pr_err("lookup failed %s (%d)\n", mod->path, err);
1facf9fc 26567+ goto out;
26568+ }
26569+
26570+ mod->perm = br_perm_val(p);
26571+ AuDbg("mod path %s, perm 0x%x, %s\n", mod->path, mod->perm, p);
26572+ mod->h_root = dget(path.dentry);
26573+ path_put(&path);
26574+
4f0767ce 26575+out:
1facf9fc 26576+ return err;
26577+}
26578+
26579+#if 0 /* reserved for future use */
26580+static int au_opts_parse_imod(struct super_block *sb, aufs_bindex_t bindex,
26581+ struct au_opt_mod *mod, substring_t args[])
26582+{
26583+ int err;
26584+ struct dentry *root;
26585+
26586+ err = -EINVAL;
26587+ root = sb->s_root;
26588+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d 26589+ if (bindex < 0 || au_sbbot(sb) < bindex) {
4a4d8108 26590+ pr_err("out of bounds, %d\n", bindex);
1facf9fc 26591+ goto out;
26592+ }
26593+
26594+ err = 0;
26595+ mod->perm = br_perm_val(args[1].from);
26596+ AuDbg("mod path %s, perm 0x%x, %s\n",
26597+ mod->path, mod->perm, args[1].from);
26598+ mod->h_root = dget(au_h_dptr(root, bindex));
26599+
4f0767ce 26600+out:
1facf9fc 26601+ aufs_read_unlock(root, !AuLock_IR);
26602+ return err;
26603+}
26604+#endif
26605+
26606+static int au_opts_parse_xino(struct super_block *sb, struct au_opt_xino *xino,
26607+ substring_t args[])
26608+{
26609+ int err;
26610+ struct file *file;
26611+
83b672a5 26612+ file = au_xino_create(sb, args[0].from, /*silent*/0, /*wbrtop*/0);
1facf9fc 26613+ err = PTR_ERR(file);
26614+ if (IS_ERR(file))
26615+ goto out;
26616+
26617+ err = -EINVAL;
2000de60 26618+ if (unlikely(file->f_path.dentry->d_sb == sb)) {
1facf9fc 26619+ fput(file);
4a4d8108 26620+ pr_err("%s must be outside\n", args[0].from);
1facf9fc 26621+ goto out;
26622+ }
26623+
26624+ err = 0;
26625+ xino->file = file;
26626+ xino->path = args[0].from;
26627+
4f0767ce 26628+out:
1facf9fc 26629+ return err;
26630+}
26631+
4a4d8108
AM
26632+static int noinline_for_stack
26633+au_opts_parse_xino_itrunc_path(struct super_block *sb,
26634+ struct au_opt_xino_itrunc *xino_itrunc,
26635+ substring_t args[])
1facf9fc 26636+{
26637+ int err;
5afbbe0d 26638+ aufs_bindex_t bbot, bindex;
1facf9fc 26639+ struct path path;
26640+ struct dentry *root;
26641+
26642+ err = vfsub_kern_path(args[0].from, lkup_dirflags, &path);
26643+ if (unlikely(err)) {
4a4d8108 26644+ pr_err("lookup failed %s (%d)\n", args[0].from, err);
1facf9fc 26645+ goto out;
26646+ }
26647+
26648+ xino_itrunc->bindex = -1;
26649+ root = sb->s_root;
26650+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d
AM
26651+ bbot = au_sbbot(sb);
26652+ for (bindex = 0; bindex <= bbot; bindex++) {
1facf9fc 26653+ if (au_h_dptr(root, bindex) == path.dentry) {
26654+ xino_itrunc->bindex = bindex;
26655+ break;
26656+ }
26657+ }
26658+ aufs_read_unlock(root, !AuLock_IR);
26659+ path_put(&path);
26660+
26661+ if (unlikely(xino_itrunc->bindex < 0)) {
4a4d8108 26662+ pr_err("no such branch %s\n", args[0].from);
1facf9fc 26663+ err = -EINVAL;
26664+ }
26665+
4f0767ce 26666+out:
1facf9fc 26667+ return err;
26668+}
26669+
26670+/* called without aufs lock */
26671+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts)
26672+{
26673+ int err, n, token;
26674+ aufs_bindex_t bindex;
26675+ unsigned char skipped;
26676+ struct dentry *root;
26677+ struct au_opt *opt, *opt_tail;
26678+ char *opt_str;
26679+ /* reduce the stack space */
26680+ union {
26681+ struct au_opt_xino_itrunc *xino_itrunc;
26682+ struct au_opt_wbr_create *create;
26683+ } u;
26684+ struct {
26685+ substring_t args[MAX_OPT_ARGS];
26686+ } *a;
26687+
26688+ err = -ENOMEM;
26689+ a = kmalloc(sizeof(*a), GFP_NOFS);
26690+ if (unlikely(!a))
26691+ goto out;
26692+
26693+ root = sb->s_root;
26694+ err = 0;
26695+ bindex = 0;
26696+ opt = opts->opt;
26697+ opt_tail = opt + opts->max_opt - 1;
26698+ opt->type = Opt_tail;
26699+ while (!err && (opt_str = strsep(&str, ",")) && *opt_str) {
26700+ err = -EINVAL;
26701+ skipped = 0;
26702+ token = match_token(opt_str, options, a->args);
26703+ switch (token) {
26704+ case Opt_br:
26705+ err = 0;
26706+ while (!err && (opt_str = strsep(&a->args[0].from, ":"))
26707+ && *opt_str) {
26708+ err = opt_add(opt, opt_str, opts->sb_flags,
26709+ bindex++);
26710+ if (unlikely(!err && ++opt > opt_tail)) {
26711+ err = -E2BIG;
26712+ break;
26713+ }
26714+ opt->type = Opt_tail;
26715+ skipped = 1;
26716+ }
26717+ break;
26718+ case Opt_add:
26719+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 26720+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26721+ break;
26722+ }
26723+ bindex = n;
26724+ err = opt_add(opt, a->args[1].from, opts->sb_flags,
26725+ bindex);
26726+ if (!err)
26727+ opt->type = token;
26728+ break;
26729+ case Opt_append:
26730+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
26731+ /*dummy bindex*/1);
26732+ if (!err)
26733+ opt->type = token;
26734+ break;
26735+ case Opt_prepend:
26736+ err = opt_add(opt, a->args[0].from, opts->sb_flags,
26737+ /*bindex*/0);
26738+ if (!err)
26739+ opt->type = token;
26740+ break;
26741+ case Opt_del:
26742+ err = au_opts_parse_del(&opt->del, a->args);
26743+ if (!err)
26744+ opt->type = token;
26745+ break;
26746+#if 0 /* reserved for future use */
26747+ case Opt_idel:
26748+ del->pathname = "(indexed)";
26749+ if (unlikely(match_int(&args[0], &n))) {
4a4d8108 26750+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26751+ break;
26752+ }
26753+ err = au_opts_parse_idel(sb, n, &opt->del, a->args);
26754+ if (!err)
26755+ opt->type = token;
26756+ break;
26757+#endif
26758+ case Opt_mod:
26759+ err = au_opts_parse_mod(&opt->mod, a->args);
26760+ if (!err)
26761+ opt->type = token;
26762+ break;
26763+#ifdef IMOD /* reserved for future use */
26764+ case Opt_imod:
26765+ u.mod->path = "(indexed)";
26766+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 26767+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26768+ break;
26769+ }
26770+ err = au_opts_parse_imod(sb, n, &opt->mod, a->args);
26771+ if (!err)
26772+ opt->type = token;
26773+ break;
26774+#endif
26775+ case Opt_xino:
26776+ err = au_opts_parse_xino(sb, &opt->xino, a->args);
26777+ if (!err)
26778+ opt->type = token;
26779+ break;
26780+
26781+ case Opt_trunc_xino_path:
26782+ err = au_opts_parse_xino_itrunc_path
26783+ (sb, &opt->xino_itrunc, a->args);
26784+ if (!err)
26785+ opt->type = token;
26786+ break;
26787+
26788+ case Opt_itrunc_xino:
26789+ u.xino_itrunc = &opt->xino_itrunc;
26790+ if (unlikely(match_int(&a->args[0], &n))) {
4a4d8108 26791+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26792+ break;
26793+ }
26794+ u.xino_itrunc->bindex = n;
26795+ aufs_read_lock(root, AuLock_FLUSH);
5afbbe0d 26796+ if (n < 0 || au_sbbot(sb) < n) {
4a4d8108 26797+ pr_err("out of bounds, %d\n", n);
1facf9fc 26798+ aufs_read_unlock(root, !AuLock_IR);
26799+ break;
26800+ }
26801+ aufs_read_unlock(root, !AuLock_IR);
26802+ err = 0;
26803+ opt->type = token;
26804+ break;
26805+
26806+ case Opt_dirwh:
26807+ if (unlikely(match_int(&a->args[0], &opt->dirwh)))
26808+ break;
26809+ err = 0;
26810+ opt->type = token;
26811+ break;
26812+
26813+ case Opt_rdcache:
027c5e7a
AM
26814+ if (unlikely(match_int(&a->args[0], &n))) {
26815+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26816+ break;
027c5e7a
AM
26817+ }
26818+ if (unlikely(n > AUFS_RDCACHE_MAX)) {
26819+ pr_err("rdcache must be smaller than %d\n",
26820+ AUFS_RDCACHE_MAX);
26821+ break;
26822+ }
26823+ opt->rdcache = n;
1facf9fc 26824+ err = 0;
26825+ opt->type = token;
26826+ break;
26827+ case Opt_rdblk:
26828+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 26829+ || n < 0
1facf9fc 26830+ || n > KMALLOC_MAX_SIZE)) {
4a4d8108 26831+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26832+ break;
26833+ }
1308ab2a 26834+ if (unlikely(n && n < NAME_MAX)) {
4a4d8108
AM
26835+ pr_err("rdblk must be larger than %d\n",
26836+ NAME_MAX);
1facf9fc 26837+ break;
26838+ }
26839+ opt->rdblk = n;
26840+ err = 0;
26841+ opt->type = token;
26842+ break;
26843+ case Opt_rdhash:
26844+ if (unlikely(match_int(&a->args[0], &n)
1308ab2a 26845+ || n < 0
1facf9fc 26846+ || n * sizeof(struct hlist_head)
26847+ > KMALLOC_MAX_SIZE)) {
4a4d8108 26848+ pr_err("bad integer in %s\n", opt_str);
1facf9fc 26849+ break;
26850+ }
26851+ opt->rdhash = n;
26852+ err = 0;
26853+ opt->type = token;
26854+ break;
26855+
26856+ case Opt_trunc_xino:
26857+ case Opt_notrunc_xino:
26858+ case Opt_noxino:
26859+ case Opt_trunc_xib:
26860+ case Opt_notrunc_xib:
dece6358
AM
26861+ case Opt_shwh:
26862+ case Opt_noshwh:
076b876e
AM
26863+ case Opt_dirperm1:
26864+ case Opt_nodirperm1:
1facf9fc 26865+ case Opt_plink:
26866+ case Opt_noplink:
26867+ case Opt_list_plink:
4a4d8108
AM
26868+ case Opt_dio:
26869+ case Opt_nodio:
1facf9fc 26870+ case Opt_diropq_a:
26871+ case Opt_diropq_w:
26872+ case Opt_warn_perm:
26873+ case Opt_nowarn_perm:
1facf9fc 26874+ case Opt_verbose:
26875+ case Opt_noverbose:
26876+ case Opt_sum:
26877+ case Opt_nosum:
26878+ case Opt_wsum:
dece6358
AM
26879+ case Opt_rdblk_def:
26880+ case Opt_rdhash_def:
8b6a4947
AM
26881+ case Opt_dirren:
26882+ case Opt_nodirren:
c1595e42
JR
26883+ case Opt_acl:
26884+ case Opt_noacl:
1facf9fc 26885+ err = 0;
26886+ opt->type = token;
26887+ break;
26888+
26889+ case Opt_udba:
26890+ opt->udba = udba_val(a->args[0].from);
26891+ if (opt->udba >= 0) {
26892+ err = 0;
26893+ opt->type = token;
26894+ } else
4a4d8108 26895+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 26896+ break;
26897+
26898+ case Opt_wbr_create:
26899+ u.create = &opt->wbr_create;
26900+ u.create->wbr_create
26901+ = au_wbr_create_val(a->args[0].from, u.create);
26902+ if (u.create->wbr_create >= 0) {
26903+ err = 0;
26904+ opt->type = token;
26905+ } else
4a4d8108 26906+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 26907+ break;
26908+ case Opt_wbr_copyup:
26909+ opt->wbr_copyup = au_wbr_copyup_val(a->args[0].from);
26910+ if (opt->wbr_copyup >= 0) {
26911+ err = 0;
26912+ opt->type = token;
26913+ } else
4a4d8108 26914+ pr_err("wrong value, %s\n", opt_str);
1facf9fc 26915+ break;
26916+
076b876e
AM
26917+ case Opt_fhsm_sec:
26918+ if (unlikely(match_int(&a->args[0], &n)
26919+ || n < 0)) {
26920+ pr_err("bad integer in %s\n", opt_str);
26921+ break;
26922+ }
26923+ if (sysaufs_brs) {
26924+ opt->fhsm_second = n;
26925+ opt->type = token;
26926+ } else
26927+ pr_warn("ignored %s\n", opt_str);
26928+ err = 0;
26929+ break;
26930+
1facf9fc 26931+ case Opt_ignore:
0c3ec466 26932+ pr_warn("ignored %s\n", opt_str);
1facf9fc 26933+ /*FALLTHROUGH*/
26934+ case Opt_ignore_silent:
26935+ skipped = 1;
26936+ err = 0;
26937+ break;
26938+ case Opt_err:
4a4d8108 26939+ pr_err("unknown option %s\n", opt_str);
1facf9fc 26940+ break;
26941+ }
26942+
26943+ if (!err && !skipped) {
26944+ if (unlikely(++opt > opt_tail)) {
26945+ err = -E2BIG;
26946+ opt--;
26947+ opt->type = Opt_tail;
26948+ break;
26949+ }
26950+ opt->type = Opt_tail;
26951+ }
26952+ }
26953+
9f237c51 26954+ au_kfree_rcu(a);
1facf9fc 26955+ dump_opts(opts);
26956+ if (unlikely(err))
26957+ au_opts_free(opts);
26958+
4f0767ce 26959+out:
1facf9fc 26960+ return err;
26961+}
26962+
26963+static int au_opt_wbr_create(struct super_block *sb,
26964+ struct au_opt_wbr_create *create)
26965+{
26966+ int err;
26967+ struct au_sbinfo *sbinfo;
26968+
dece6358
AM
26969+ SiMustWriteLock(sb);
26970+
1facf9fc 26971+ err = 1; /* handled */
26972+ sbinfo = au_sbi(sb);
26973+ if (sbinfo->si_wbr_create_ops->fin) {
26974+ err = sbinfo->si_wbr_create_ops->fin(sb);
26975+ if (!err)
26976+ err = 1;
26977+ }
26978+
26979+ sbinfo->si_wbr_create = create->wbr_create;
26980+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + create->wbr_create;
26981+ switch (create->wbr_create) {
26982+ case AuWbrCreate_MFSRRV:
26983+ case AuWbrCreate_MFSRR:
f2c43d5f
AM
26984+ case AuWbrCreate_TDMFS:
26985+ case AuWbrCreate_TDMFSV:
392086de
AM
26986+ case AuWbrCreate_PMFSRR:
26987+ case AuWbrCreate_PMFSRRV:
1facf9fc 26988+ sbinfo->si_wbr_mfs.mfsrr_watermark = create->mfsrr_watermark;
26989+ /*FALLTHROUGH*/
26990+ case AuWbrCreate_MFS:
26991+ case AuWbrCreate_MFSV:
26992+ case AuWbrCreate_PMFS:
26993+ case AuWbrCreate_PMFSV:
e49829fe
JR
26994+ sbinfo->si_wbr_mfs.mfs_expire
26995+ = msecs_to_jiffies(create->mfs_second * MSEC_PER_SEC);
1facf9fc 26996+ break;
26997+ }
26998+
26999+ if (sbinfo->si_wbr_create_ops->init)
27000+ sbinfo->si_wbr_create_ops->init(sb); /* ignore */
27001+
27002+ return err;
27003+}
27004+
27005+/*
27006+ * returns,
27007+ * plus: processed without an error
27008+ * zero: unprocessed
27009+ */
27010+static int au_opt_simple(struct super_block *sb, struct au_opt *opt,
27011+ struct au_opts *opts)
27012+{
27013+ int err;
27014+ struct au_sbinfo *sbinfo;
27015+
dece6358
AM
27016+ SiMustWriteLock(sb);
27017+
1facf9fc 27018+ err = 1; /* handled */
27019+ sbinfo = au_sbi(sb);
27020+ switch (opt->type) {
27021+ case Opt_udba:
27022+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
27023+ sbinfo->si_mntflags |= opt->udba;
27024+ opts->given_udba |= opt->udba;
27025+ break;
27026+
27027+ case Opt_plink:
27028+ au_opt_set(sbinfo->si_mntflags, PLINK);
27029+ break;
27030+ case Opt_noplink:
27031+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
e49829fe 27032+ au_plink_put(sb, /*verbose*/1);
1facf9fc 27033+ au_opt_clr(sbinfo->si_mntflags, PLINK);
27034+ break;
27035+ case Opt_list_plink:
27036+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
27037+ au_plink_list(sb);
27038+ break;
27039+
4a4d8108
AM
27040+ case Opt_dio:
27041+ au_opt_set(sbinfo->si_mntflags, DIO);
27042+ au_fset_opts(opts->flags, REFRESH_DYAOP);
27043+ break;
27044+ case Opt_nodio:
27045+ au_opt_clr(sbinfo->si_mntflags, DIO);
27046+ au_fset_opts(opts->flags, REFRESH_DYAOP);
27047+ break;
27048+
076b876e
AM
27049+ case Opt_fhsm_sec:
27050+ au_fhsm_set(sbinfo, opt->fhsm_second);
27051+ break;
27052+
1facf9fc 27053+ case Opt_diropq_a:
27054+ au_opt_set(sbinfo->si_mntflags, ALWAYS_DIROPQ);
27055+ break;
27056+ case Opt_diropq_w:
27057+ au_opt_clr(sbinfo->si_mntflags, ALWAYS_DIROPQ);
27058+ break;
27059+
27060+ case Opt_warn_perm:
27061+ au_opt_set(sbinfo->si_mntflags, WARN_PERM);
27062+ break;
27063+ case Opt_nowarn_perm:
27064+ au_opt_clr(sbinfo->si_mntflags, WARN_PERM);
27065+ break;
27066+
1facf9fc 27067+ case Opt_verbose:
27068+ au_opt_set(sbinfo->si_mntflags, VERBOSE);
27069+ break;
27070+ case Opt_noverbose:
27071+ au_opt_clr(sbinfo->si_mntflags, VERBOSE);
27072+ break;
27073+
27074+ case Opt_sum:
27075+ au_opt_set(sbinfo->si_mntflags, SUM);
27076+ break;
27077+ case Opt_wsum:
27078+ au_opt_clr(sbinfo->si_mntflags, SUM);
27079+ au_opt_set(sbinfo->si_mntflags, SUM_W);
eca34b5c 27080+ break;
1facf9fc 27081+ case Opt_nosum:
27082+ au_opt_clr(sbinfo->si_mntflags, SUM);
27083+ au_opt_clr(sbinfo->si_mntflags, SUM_W);
27084+ break;
27085+
27086+ case Opt_wbr_create:
27087+ err = au_opt_wbr_create(sb, &opt->wbr_create);
27088+ break;
27089+ case Opt_wbr_copyup:
27090+ sbinfo->si_wbr_copyup = opt->wbr_copyup;
27091+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + opt->wbr_copyup;
27092+ break;
27093+
27094+ case Opt_dirwh:
27095+ sbinfo->si_dirwh = opt->dirwh;
27096+ break;
27097+
27098+ case Opt_rdcache:
e49829fe
JR
27099+ sbinfo->si_rdcache
27100+ = msecs_to_jiffies(opt->rdcache * MSEC_PER_SEC);
1facf9fc 27101+ break;
27102+ case Opt_rdblk:
27103+ sbinfo->si_rdblk = opt->rdblk;
27104+ break;
dece6358
AM
27105+ case Opt_rdblk_def:
27106+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
27107+ break;
1facf9fc 27108+ case Opt_rdhash:
27109+ sbinfo->si_rdhash = opt->rdhash;
27110+ break;
dece6358
AM
27111+ case Opt_rdhash_def:
27112+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
27113+ break;
27114+
27115+ case Opt_shwh:
27116+ au_opt_set(sbinfo->si_mntflags, SHWH);
27117+ break;
27118+ case Opt_noshwh:
27119+ au_opt_clr(sbinfo->si_mntflags, SHWH);
27120+ break;
1facf9fc 27121+
076b876e
AM
27122+ case Opt_dirperm1:
27123+ au_opt_set(sbinfo->si_mntflags, DIRPERM1);
27124+ break;
27125+ case Opt_nodirperm1:
27126+ au_opt_clr(sbinfo->si_mntflags, DIRPERM1);
27127+ break;
27128+
1facf9fc 27129+ case Opt_trunc_xino:
27130+ au_opt_set(sbinfo->si_mntflags, TRUNC_XINO);
27131+ break;
27132+ case Opt_notrunc_xino:
27133+ au_opt_clr(sbinfo->si_mntflags, TRUNC_XINO);
27134+ break;
27135+
27136+ case Opt_trunc_xino_path:
27137+ case Opt_itrunc_xino:
acd2b654
AM
27138+ err = au_xino_trunc(sb, opt->xino_itrunc.bindex,
27139+ /*idx_begin*/0);
1facf9fc 27140+ if (!err)
27141+ err = 1;
27142+ break;
27143+
27144+ case Opt_trunc_xib:
27145+ au_fset_opts(opts->flags, TRUNC_XIB);
27146+ break;
27147+ case Opt_notrunc_xib:
27148+ au_fclr_opts(opts->flags, TRUNC_XIB);
27149+ break;
27150+
8b6a4947
AM
27151+ case Opt_dirren:
27152+ err = 1;
27153+ if (!au_opt_test(sbinfo->si_mntflags, DIRREN)) {
27154+ err = au_dr_opt_set(sb);
27155+ if (!err)
27156+ err = 1;
27157+ }
27158+ if (err == 1)
27159+ au_opt_set(sbinfo->si_mntflags, DIRREN);
27160+ break;
27161+ case Opt_nodirren:
27162+ err = 1;
27163+ if (au_opt_test(sbinfo->si_mntflags, DIRREN)) {
27164+ err = au_dr_opt_clr(sb, au_ftest_opts(opts->flags,
27165+ DR_FLUSHED));
27166+ if (!err)
27167+ err = 1;
27168+ }
27169+ if (err == 1)
27170+ au_opt_clr(sbinfo->si_mntflags, DIRREN);
27171+ break;
27172+
c1595e42 27173+ case Opt_acl:
2121bcd9 27174+ sb->s_flags |= SB_POSIXACL;
c1595e42
JR
27175+ break;
27176+ case Opt_noacl:
2121bcd9 27177+ sb->s_flags &= ~SB_POSIXACL;
c1595e42
JR
27178+ break;
27179+
1facf9fc 27180+ default:
27181+ err = 0;
27182+ break;
27183+ }
27184+
27185+ return err;
27186+}
27187+
27188+/*
27189+ * returns tri-state.
27190+ * plus: processed without an error
27191+ * zero: unprocessed
27192+ * minus: error
27193+ */
27194+static int au_opt_br(struct super_block *sb, struct au_opt *opt,
27195+ struct au_opts *opts)
27196+{
27197+ int err, do_refresh;
27198+
27199+ err = 0;
27200+ switch (opt->type) {
27201+ case Opt_append:
5afbbe0d 27202+ opt->add.bindex = au_sbbot(sb) + 1;
1facf9fc 27203+ if (opt->add.bindex < 0)
27204+ opt->add.bindex = 0;
27205+ goto add;
eca34b5c 27206+ /* Always goto add, not fallthrough */
1facf9fc 27207+ case Opt_prepend:
27208+ opt->add.bindex = 0;
eca34b5c 27209+ /* fallthrough */
f6b6e03d 27210+ add: /* indented label */
1facf9fc 27211+ case Opt_add:
27212+ err = au_br_add(sb, &opt->add,
27213+ au_ftest_opts(opts->flags, REMOUNT));
27214+ if (!err) {
27215+ err = 1;
027c5e7a 27216+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 27217+ }
27218+ break;
27219+
27220+ case Opt_del:
27221+ case Opt_idel:
27222+ err = au_br_del(sb, &opt->del,
27223+ au_ftest_opts(opts->flags, REMOUNT));
27224+ if (!err) {
27225+ err = 1;
27226+ au_fset_opts(opts->flags, TRUNC_XIB);
027c5e7a 27227+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 27228+ }
27229+ break;
27230+
27231+ case Opt_mod:
27232+ case Opt_imod:
27233+ err = au_br_mod(sb, &opt->mod,
27234+ au_ftest_opts(opts->flags, REMOUNT),
27235+ &do_refresh);
27236+ if (!err) {
27237+ err = 1;
027c5e7a
AM
27238+ if (do_refresh)
27239+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 27240+ }
27241+ break;
27242+ }
1facf9fc 27243+ return err;
27244+}
27245+
27246+static int au_opt_xino(struct super_block *sb, struct au_opt *opt,
27247+ struct au_opt_xino **opt_xino,
27248+ struct au_opts *opts)
27249+{
27250+ int err;
1facf9fc 27251+
27252+ err = 0;
27253+ switch (opt->type) {
27254+ case Opt_xino:
062440b3
AM
27255+ err = au_xino_set(sb, &opt->xino,
27256+ !!au_ftest_opts(opts->flags, REMOUNT));
27257+ if (unlikely(err))
27258+ break;
27259+
27260+ *opt_xino = &opt->xino;
1facf9fc 27261+ break;
27262+
27263+ case Opt_noxino:
27264+ au_xino_clr(sb);
1facf9fc 27265+ *opt_xino = (void *)-1;
27266+ break;
27267+ }
27268+
27269+ return err;
27270+}
27271+
27272+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
27273+ unsigned int pending)
27274+{
076b876e 27275+ int err, fhsm;
5afbbe0d 27276+ aufs_bindex_t bindex, bbot;
79b8bda9 27277+ unsigned char do_plink, skip, do_free, can_no_dreval;
1facf9fc 27278+ struct au_branch *br;
27279+ struct au_wbr *wbr;
79b8bda9 27280+ struct dentry *root, *dentry;
1facf9fc 27281+ struct inode *dir, *h_dir;
27282+ struct au_sbinfo *sbinfo;
27283+ struct au_hinode *hdir;
27284+
dece6358
AM
27285+ SiMustAnyLock(sb);
27286+
1facf9fc 27287+ sbinfo = au_sbi(sb);
27288+ AuDebugOn(!(sbinfo->si_mntflags & AuOptMask_UDBA));
27289+
2121bcd9 27290+ if (!(sb_flags & SB_RDONLY)) {
dece6358 27291+ if (unlikely(!au_br_writable(au_sbr_perm(sb, 0))))
0c3ec466 27292+ pr_warn("first branch should be rw\n");
dece6358 27293+ if (unlikely(au_opt_test(sbinfo->si_mntflags, SHWH)))
febd17d6 27294+ pr_warn_once("shwh should be used with ro\n");
dece6358 27295+ }
1facf9fc 27296+
4a4d8108 27297+ if (au_opt_test((sbinfo->si_mntflags | pending), UDBA_HNOTIFY)
1facf9fc 27298+ && !au_opt_test(sbinfo->si_mntflags, XINO))
febd17d6 27299+ pr_warn_once("udba=*notify requires xino\n");
1facf9fc 27300+
076b876e 27301+ if (au_opt_test(sbinfo->si_mntflags, DIRPERM1))
febd17d6
JR
27302+ pr_warn_once("dirperm1 breaks the protection"
27303+ " by the permission bits on the lower branch\n");
076b876e 27304+
1facf9fc 27305+ err = 0;
076b876e 27306+ fhsm = 0;
1facf9fc 27307+ root = sb->s_root;
5527c038 27308+ dir = d_inode(root);
1facf9fc 27309+ do_plink = !!au_opt_test(sbinfo->si_mntflags, PLINK);
79b8bda9
AM
27310+ can_no_dreval = !!au_opt_test((sbinfo->si_mntflags | pending),
27311+ UDBA_NONE);
5afbbe0d
AM
27312+ bbot = au_sbbot(sb);
27313+ for (bindex = 0; !err && bindex <= bbot; bindex++) {
1facf9fc 27314+ skip = 0;
27315+ h_dir = au_h_iptr(dir, bindex);
27316+ br = au_sbr(sb, bindex);
1facf9fc 27317+
c1595e42
JR
27318+ if ((br->br_perm & AuBrAttr_ICEX)
27319+ && !h_dir->i_op->listxattr)
27320+ br->br_perm &= ~AuBrAttr_ICEX;
43982f53 27321+#if 0 /* untested */
c1595e42 27322+ if ((br->br_perm & AuBrAttr_ICEX_SEC)
2121bcd9 27323+ && (au_br_sb(br)->s_flags & SB_NOSEC))
c1595e42
JR
27324+ br->br_perm &= ~AuBrAttr_ICEX_SEC;
27325+#endif
27326+
27327+ do_free = 0;
1facf9fc 27328+ wbr = br->br_wbr;
27329+ if (wbr)
27330+ wbr_wh_read_lock(wbr);
27331+
1e00d052 27332+ if (!au_br_writable(br->br_perm)) {
1facf9fc 27333+ do_free = !!wbr;
27334+ skip = (!wbr
27335+ || (!wbr->wbr_whbase
27336+ && !wbr->wbr_plink
27337+ && !wbr->wbr_orph));
1e00d052 27338+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 27339+ /* skip = (!br->br_whbase && !br->br_orph); */
27340+ skip = (!wbr || !wbr->wbr_whbase);
27341+ if (skip && wbr) {
27342+ if (do_plink)
27343+ skip = !!wbr->wbr_plink;
27344+ else
27345+ skip = !wbr->wbr_plink;
27346+ }
1e00d052 27347+ } else {
1facf9fc 27348+ /* skip = (br->br_whbase && br->br_ohph); */
27349+ skip = (wbr && wbr->wbr_whbase);
27350+ if (skip) {
27351+ if (do_plink)
27352+ skip = !!wbr->wbr_plink;
27353+ else
27354+ skip = !wbr->wbr_plink;
27355+ }
1facf9fc 27356+ }
27357+ if (wbr)
27358+ wbr_wh_read_unlock(wbr);
27359+
79b8bda9
AM
27360+ if (can_no_dreval) {
27361+ dentry = br->br_path.dentry;
27362+ spin_lock(&dentry->d_lock);
27363+ if (dentry->d_flags &
27364+ (DCACHE_OP_REVALIDATE | DCACHE_OP_WEAK_REVALIDATE))
27365+ can_no_dreval = 0;
27366+ spin_unlock(&dentry->d_lock);
27367+ }
27368+
076b876e
AM
27369+ if (au_br_fhsm(br->br_perm)) {
27370+ fhsm++;
27371+ AuDebugOn(!br->br_fhsm);
27372+ }
27373+
1facf9fc 27374+ if (skip)
27375+ continue;
27376+
27377+ hdir = au_hi(dir, bindex);
5afbbe0d 27378+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 27379+ if (wbr)
27380+ wbr_wh_write_lock(wbr);
86dc4139 27381+ err = au_wh_init(br, sb);
1facf9fc 27382+ if (wbr)
27383+ wbr_wh_write_unlock(wbr);
5afbbe0d 27384+ au_hn_inode_unlock(hdir);
1facf9fc 27385+
27386+ if (!err && do_free) {
9f237c51 27387+ au_kfree_rcu(wbr);
1facf9fc 27388+ br->br_wbr = NULL;
27389+ }
27390+ }
27391+
79b8bda9
AM
27392+ if (can_no_dreval)
27393+ au_fset_si(sbinfo, NO_DREVAL);
27394+ else
27395+ au_fclr_si(sbinfo, NO_DREVAL);
27396+
c1595e42 27397+ if (fhsm >= 2) {
076b876e 27398+ au_fset_si(sbinfo, FHSM);
5afbbe0d 27399+ for (bindex = bbot; bindex >= 0; bindex--) {
c1595e42
JR
27400+ br = au_sbr(sb, bindex);
27401+ if (au_br_fhsm(br->br_perm)) {
27402+ au_fhsm_set_bottom(sb, bindex);
27403+ break;
27404+ }
27405+ }
27406+ } else {
076b876e 27407+ au_fclr_si(sbinfo, FHSM);
c1595e42
JR
27408+ au_fhsm_set_bottom(sb, -1);
27409+ }
076b876e 27410+
1facf9fc 27411+ return err;
27412+}
27413+
27414+int au_opts_mount(struct super_block *sb, struct au_opts *opts)
27415+{
27416+ int err;
27417+ unsigned int tmp;
5afbbe0d 27418+ aufs_bindex_t bindex, bbot;
1facf9fc 27419+ struct au_opt *opt;
27420+ struct au_opt_xino *opt_xino, xino;
27421+ struct au_sbinfo *sbinfo;
027c5e7a 27422+ struct au_branch *br;
076b876e 27423+ struct inode *dir;
1facf9fc 27424+
dece6358
AM
27425+ SiMustWriteLock(sb);
27426+
1facf9fc 27427+ err = 0;
27428+ opt_xino = NULL;
27429+ opt = opts->opt;
27430+ while (err >= 0 && opt->type != Opt_tail)
27431+ err = au_opt_simple(sb, opt++, opts);
27432+ if (err > 0)
27433+ err = 0;
27434+ else if (unlikely(err < 0))
27435+ goto out;
27436+
27437+ /* disable xino and udba temporary */
27438+ sbinfo = au_sbi(sb);
27439+ tmp = sbinfo->si_mntflags;
27440+ au_opt_clr(sbinfo->si_mntflags, XINO);
27441+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_REVAL);
27442+
27443+ opt = opts->opt;
27444+ while (err >= 0 && opt->type != Opt_tail)
27445+ err = au_opt_br(sb, opt++, opts);
27446+ if (err > 0)
27447+ err = 0;
27448+ else if (unlikely(err < 0))
27449+ goto out;
27450+
5afbbe0d
AM
27451+ bbot = au_sbbot(sb);
27452+ if (unlikely(bbot < 0)) {
1facf9fc 27453+ err = -EINVAL;
4a4d8108 27454+ pr_err("no branches\n");
1facf9fc 27455+ goto out;
27456+ }
27457+
27458+ if (au_opt_test(tmp, XINO))
27459+ au_opt_set(sbinfo->si_mntflags, XINO);
27460+ opt = opts->opt;
27461+ while (!err && opt->type != Opt_tail)
27462+ err = au_opt_xino(sb, opt++, &opt_xino, opts);
27463+ if (unlikely(err))
27464+ goto out;
27465+
27466+ err = au_opts_verify(sb, sb->s_flags, tmp);
27467+ if (unlikely(err))
27468+ goto out;
27469+
27470+ /* restore xino */
27471+ if (au_opt_test(tmp, XINO) && !opt_xino) {
27472+ xino.file = au_xino_def(sb);
27473+ err = PTR_ERR(xino.file);
27474+ if (IS_ERR(xino.file))
27475+ goto out;
27476+
27477+ err = au_xino_set(sb, &xino, /*remount*/0);
27478+ fput(xino.file);
27479+ if (unlikely(err))
27480+ goto out;
27481+ }
27482+
27483+ /* restore udba */
027c5e7a 27484+ tmp &= AuOptMask_UDBA;
1facf9fc 27485+ sbinfo->si_mntflags &= ~AuOptMask_UDBA;
027c5e7a 27486+ sbinfo->si_mntflags |= tmp;
5afbbe0d
AM
27487+ bbot = au_sbbot(sb);
27488+ for (bindex = 0; bindex <= bbot; bindex++) {
027c5e7a
AM
27489+ br = au_sbr(sb, bindex);
27490+ err = au_hnotify_reset_br(tmp, br, br->br_perm);
27491+ if (unlikely(err))
27492+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
27493+ bindex, err);
27494+ /* go on even if err */
27495+ }
4a4d8108 27496+ if (au_opt_test(tmp, UDBA_HNOTIFY)) {
5527c038 27497+ dir = d_inode(sb->s_root);
4a4d8108 27498+ au_hn_reset(dir, au_hi_flags(dir, /*isdir*/1) & ~AuHi_XINO);
1facf9fc 27499+ }
27500+
4f0767ce 27501+out:
1facf9fc 27502+ return err;
27503+}
27504+
27505+int au_opts_remount(struct super_block *sb, struct au_opts *opts)
27506+{
27507+ int err, rerr;
79b8bda9 27508+ unsigned char no_dreval;
1facf9fc 27509+ struct inode *dir;
27510+ struct au_opt_xino *opt_xino;
27511+ struct au_opt *opt;
27512+ struct au_sbinfo *sbinfo;
27513+
dece6358
AM
27514+ SiMustWriteLock(sb);
27515+
8b6a4947
AM
27516+ err = au_dr_opt_flush(sb);
27517+ if (unlikely(err))
27518+ goto out;
27519+ au_fset_opts(opts->flags, DR_FLUSHED);
27520+
5527c038 27521+ dir = d_inode(sb->s_root);
1facf9fc 27522+ sbinfo = au_sbi(sb);
1facf9fc 27523+ opt_xino = NULL;
27524+ opt = opts->opt;
27525+ while (err >= 0 && opt->type != Opt_tail) {
27526+ err = au_opt_simple(sb, opt, opts);
27527+ if (!err)
27528+ err = au_opt_br(sb, opt, opts);
27529+ if (!err)
27530+ err = au_opt_xino(sb, opt, &opt_xino, opts);
27531+ opt++;
27532+ }
27533+ if (err > 0)
27534+ err = 0;
27535+ AuTraceErr(err);
27536+ /* go on even err */
27537+
79b8bda9 27538+ no_dreval = !!au_ftest_si(sbinfo, NO_DREVAL);
1facf9fc 27539+ rerr = au_opts_verify(sb, opts->sb_flags, /*pending*/0);
27540+ if (unlikely(rerr && !err))
27541+ err = rerr;
27542+
79b8bda9 27543+ if (no_dreval != !!au_ftest_si(sbinfo, NO_DREVAL))
b95c5147 27544+ au_fset_opts(opts->flags, REFRESH_IDOP);
79b8bda9 27545+
1facf9fc 27546+ if (au_ftest_opts(opts->flags, TRUNC_XIB)) {
27547+ rerr = au_xib_trunc(sb);
27548+ if (unlikely(rerr && !err))
27549+ err = rerr;
27550+ }
27551+
27552+ /* will be handled by the caller */
027c5e7a 27553+ if (!au_ftest_opts(opts->flags, REFRESH)
79b8bda9
AM
27554+ && (opts->given_udba
27555+ || au_opt_test(sbinfo->si_mntflags, XINO)
b95c5147 27556+ || au_ftest_opts(opts->flags, REFRESH_IDOP)
79b8bda9 27557+ ))
027c5e7a 27558+ au_fset_opts(opts->flags, REFRESH);
1facf9fc 27559+
27560+ AuDbg("status 0x%x\n", opts->flags);
8b6a4947
AM
27561+
27562+out:
1facf9fc 27563+ return err;
27564+}
27565+
27566+/* ---------------------------------------------------------------------- */
27567+
27568+unsigned int au_opt_udba(struct super_block *sb)
27569+{
27570+ return au_mntflags(sb) & AuOptMask_UDBA;
27571+}
7f207e10 27572diff -urN /usr/share/empty/fs/aufs/opts.h linux/fs/aufs/opts.h
eca34b5c 27573--- /usr/share/empty/fs/aufs/opts.h 1970-01-01 01:00:00.000000000 +0100
016522bc 27574+++ linux/fs/aufs/opts.h 2020-01-27 10:57:18.175538316 +0100
062440b3
AM
27575@@ -0,0 +1,225 @@
27576+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 27577+/*
016522bc 27578+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 27579+ *
27580+ * This program, aufs is free software; you can redistribute it and/or modify
27581+ * it under the terms of the GNU General Public License as published by
27582+ * the Free Software Foundation; either version 2 of the License, or
27583+ * (at your option) any later version.
dece6358
AM
27584+ *
27585+ * This program is distributed in the hope that it will be useful,
27586+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27587+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27588+ * GNU General Public License for more details.
27589+ *
27590+ * You should have received a copy of the GNU General Public License
523b37e3 27591+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 27592+ */
27593+
27594+/*
27595+ * mount options/flags
27596+ */
27597+
27598+#ifndef __AUFS_OPTS_H__
27599+#define __AUFS_OPTS_H__
27600+
27601+#ifdef __KERNEL__
27602+
dece6358 27603+#include <linux/path.h>
1facf9fc 27604+
dece6358 27605+struct file;
dece6358 27606+
1facf9fc 27607+/* ---------------------------------------------------------------------- */
27608+
27609+/* mount flags */
27610+#define AuOpt_XINO 1 /* external inode number bitmap
27611+ and translation table */
27612+#define AuOpt_TRUNC_XINO (1 << 1) /* truncate xino files */
27613+#define AuOpt_UDBA_NONE (1 << 2) /* users direct branch access */
27614+#define AuOpt_UDBA_REVAL (1 << 3)
4a4d8108 27615+#define AuOpt_UDBA_HNOTIFY (1 << 4)
dece6358
AM
27616+#define AuOpt_SHWH (1 << 5) /* show whiteout */
27617+#define AuOpt_PLINK (1 << 6) /* pseudo-link */
076b876e
AM
27618+#define AuOpt_DIRPERM1 (1 << 7) /* ignore the lower dir's perm
27619+ bits */
dece6358
AM
27620+#define AuOpt_ALWAYS_DIROPQ (1 << 9) /* policy to creating diropq */
27621+#define AuOpt_SUM (1 << 10) /* summation for statfs(2) */
27622+#define AuOpt_SUM_W (1 << 11) /* unimplemented */
27623+#define AuOpt_WARN_PERM (1 << 12) /* warn when add-branch */
eca801bf 27624+#define AuOpt_VERBOSE (1 << 13) /* print the cause of error */
4a4d8108 27625+#define AuOpt_DIO (1 << 14) /* direct io */
8b6a4947 27626+#define AuOpt_DIRREN (1 << 15) /* directory rename */
1facf9fc 27627+
4a4d8108
AM
27628+#ifndef CONFIG_AUFS_HNOTIFY
27629+#undef AuOpt_UDBA_HNOTIFY
27630+#define AuOpt_UDBA_HNOTIFY 0
1facf9fc 27631+#endif
8b6a4947
AM
27632+#ifndef CONFIG_AUFS_DIRREN
27633+#undef AuOpt_DIRREN
27634+#define AuOpt_DIRREN 0
27635+#endif
dece6358
AM
27636+#ifndef CONFIG_AUFS_SHWH
27637+#undef AuOpt_SHWH
27638+#define AuOpt_SHWH 0
27639+#endif
1facf9fc 27640+
27641+#define AuOpt_Def (AuOpt_XINO \
27642+ | AuOpt_UDBA_REVAL \
27643+ | AuOpt_PLINK \
27644+ /* | AuOpt_DIRPERM1 */ \
27645+ | AuOpt_WARN_PERM)
27646+#define AuOptMask_UDBA (AuOpt_UDBA_NONE \
27647+ | AuOpt_UDBA_REVAL \
4a4d8108 27648+ | AuOpt_UDBA_HNOTIFY)
1facf9fc 27649+
27650+#define au_opt_test(flags, name) (flags & AuOpt_##name)
27651+#define au_opt_set(flags, name) do { \
27652+ BUILD_BUG_ON(AuOpt_##name & AuOptMask_UDBA); \
27653+ ((flags) |= AuOpt_##name); \
27654+} while (0)
27655+#define au_opt_set_udba(flags, name) do { \
27656+ (flags) &= ~AuOptMask_UDBA; \
27657+ ((flags) |= AuOpt_##name); \
27658+} while (0)
7f207e10
AM
27659+#define au_opt_clr(flags, name) do { \
27660+ ((flags) &= ~AuOpt_##name); \
27661+} while (0)
1facf9fc 27662+
e49829fe
JR
27663+static inline unsigned int au_opts_plink(unsigned int mntflags)
27664+{
27665+#ifdef CONFIG_PROC_FS
27666+ return mntflags;
27667+#else
27668+ return mntflags & ~AuOpt_PLINK;
27669+#endif
27670+}
27671+
1facf9fc 27672+/* ---------------------------------------------------------------------- */
27673+
27674+/* policies to select one among multiple writable branches */
27675+enum {
27676+ AuWbrCreate_TDP, /* top down parent */
27677+ AuWbrCreate_RR, /* round robin */
27678+ AuWbrCreate_MFS, /* most free space */
27679+ AuWbrCreate_MFSV, /* mfs with seconds */
27680+ AuWbrCreate_MFSRR, /* mfs then rr */
27681+ AuWbrCreate_MFSRRV, /* mfs then rr with seconds */
f2c43d5f
AM
27682+ AuWbrCreate_TDMFS, /* top down regardless parent and mfs */
27683+ AuWbrCreate_TDMFSV, /* top down regardless parent and mfs */
1facf9fc 27684+ AuWbrCreate_PMFS, /* parent and mfs */
27685+ AuWbrCreate_PMFSV, /* parent and mfs with seconds */
392086de
AM
27686+ AuWbrCreate_PMFSRR, /* parent, mfs and round-robin */
27687+ AuWbrCreate_PMFSRRV, /* plus seconds */
1facf9fc 27688+
27689+ AuWbrCreate_Def = AuWbrCreate_TDP
27690+};
27691+
27692+enum {
27693+ AuWbrCopyup_TDP, /* top down parent */
27694+ AuWbrCopyup_BUP, /* bottom up parent */
27695+ AuWbrCopyup_BU, /* bottom up */
27696+
27697+ AuWbrCopyup_Def = AuWbrCopyup_TDP
27698+};
27699+
27700+/* ---------------------------------------------------------------------- */
27701+
27702+struct au_opt_add {
27703+ aufs_bindex_t bindex;
27704+ char *pathname;
27705+ int perm;
27706+ struct path path;
27707+};
27708+
27709+struct au_opt_del {
27710+ char *pathname;
27711+ struct path h_path;
27712+};
27713+
27714+struct au_opt_mod {
27715+ char *path;
27716+ int perm;
27717+ struct dentry *h_root;
27718+};
27719+
27720+struct au_opt_xino {
27721+ char *path;
27722+ struct file *file;
27723+};
27724+
27725+struct au_opt_xino_itrunc {
27726+ aufs_bindex_t bindex;
27727+};
27728+
27729+struct au_opt_wbr_create {
27730+ int wbr_create;
27731+ int mfs_second;
27732+ unsigned long long mfsrr_watermark;
27733+};
27734+
27735+struct au_opt {
27736+ int type;
27737+ union {
27738+ struct au_opt_xino xino;
27739+ struct au_opt_xino_itrunc xino_itrunc;
27740+ struct au_opt_add add;
27741+ struct au_opt_del del;
27742+ struct au_opt_mod mod;
27743+ int dirwh;
27744+ int rdcache;
27745+ unsigned int rdblk;
27746+ unsigned int rdhash;
27747+ int udba;
27748+ struct au_opt_wbr_create wbr_create;
27749+ int wbr_copyup;
076b876e 27750+ unsigned int fhsm_second;
1facf9fc 27751+ };
27752+};
27753+
27754+/* opts flags */
27755+#define AuOpts_REMOUNT 1
027c5e7a
AM
27756+#define AuOpts_REFRESH (1 << 1)
27757+#define AuOpts_TRUNC_XIB (1 << 2)
27758+#define AuOpts_REFRESH_DYAOP (1 << 3)
b95c5147 27759+#define AuOpts_REFRESH_IDOP (1 << 4)
8b6a4947 27760+#define AuOpts_DR_FLUSHED (1 << 5)
1facf9fc 27761+#define au_ftest_opts(flags, name) ((flags) & AuOpts_##name)
7f207e10
AM
27762+#define au_fset_opts(flags, name) \
27763+ do { (flags) |= AuOpts_##name; } while (0)
27764+#define au_fclr_opts(flags, name) \
27765+ do { (flags) &= ~AuOpts_##name; } while (0)
1facf9fc 27766+
8b6a4947
AM
27767+#ifndef CONFIG_AUFS_DIRREN
27768+#undef AuOpts_DR_FLUSHED
27769+#define AuOpts_DR_FLUSHED 0
27770+#endif
27771+
1facf9fc 27772+struct au_opts {
27773+ struct au_opt *opt;
27774+ int max_opt;
27775+
27776+ unsigned int given_udba;
27777+ unsigned int flags;
27778+ unsigned long sb_flags;
27779+};
27780+
27781+/* ---------------------------------------------------------------------- */
27782+
7e9cd9fe 27783+/* opts.c */
076b876e 27784+void au_optstr_br_perm(au_br_perm_str_t *str, int perm);
1facf9fc 27785+const char *au_optstr_udba(int udba);
27786+const char *au_optstr_wbr_copyup(int wbr_copyup);
27787+const char *au_optstr_wbr_create(int wbr_create);
27788+
27789+void au_opts_free(struct au_opts *opts);
3c1bdaff 27790+struct super_block;
1facf9fc 27791+int au_opts_parse(struct super_block *sb, char *str, struct au_opts *opts);
27792+int au_opts_verify(struct super_block *sb, unsigned long sb_flags,
27793+ unsigned int pending);
27794+int au_opts_mount(struct super_block *sb, struct au_opts *opts);
27795+int au_opts_remount(struct super_block *sb, struct au_opts *opts);
27796+
27797+unsigned int au_opt_udba(struct super_block *sb);
27798+
1facf9fc 27799+#endif /* __KERNEL__ */
27800+#endif /* __AUFS_OPTS_H__ */
7f207e10 27801diff -urN /usr/share/empty/fs/aufs/plink.c linux/fs/aufs/plink.c
eca34b5c 27802--- /usr/share/empty/fs/aufs/plink.c 1970-01-01 01:00:00.000000000 +0100
016522bc 27803+++ linux/fs/aufs/plink.c 2020-01-27 10:57:18.175538316 +0100
062440b3 27804@@ -0,0 +1,516 @@
cd7a4cd9 27805+// SPDX-License-Identifier: GPL-2.0
1facf9fc 27806+/*
016522bc 27807+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 27808+ *
27809+ * This program, aufs is free software; you can redistribute it and/or modify
27810+ * it under the terms of the GNU General Public License as published by
27811+ * the Free Software Foundation; either version 2 of the License, or
27812+ * (at your option) any later version.
dece6358
AM
27813+ *
27814+ * This program is distributed in the hope that it will be useful,
27815+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
27816+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27817+ * GNU General Public License for more details.
27818+ *
27819+ * You should have received a copy of the GNU General Public License
523b37e3 27820+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 27821+ */
27822+
27823+/*
27824+ * pseudo-link
27825+ */
27826+
27827+#include "aufs.h"
27828+
27829+/*
e49829fe 27830+ * the pseudo-link maintenance mode.
1facf9fc 27831+ * during a user process maintains the pseudo-links,
27832+ * prohibit adding a new plink and branch manipulation.
e49829fe
JR
27833+ *
27834+ * Flags
27835+ * NOPLM:
27836+ * For entry functions which will handle plink, and i_mutex is already held
27837+ * in VFS.
27838+ * They cannot wait and should return an error at once.
27839+ * Callers has to check the error.
27840+ * NOPLMW:
27841+ * For entry functions which will handle plink, but i_mutex is not held
27842+ * in VFS.
27843+ * They can wait the plink maintenance mode to finish.
27844+ *
27845+ * They behave like F_SETLK and F_SETLKW.
27846+ * If the caller never handle plink, then both flags are unnecessary.
1facf9fc 27847+ */
e49829fe
JR
27848+
27849+int au_plink_maint(struct super_block *sb, int flags)
1facf9fc 27850+{
e49829fe
JR
27851+ int err;
27852+ pid_t pid, ppid;
f0c0a007 27853+ struct task_struct *parent, *prev;
e49829fe 27854+ struct au_sbinfo *sbi;
dece6358
AM
27855+
27856+ SiMustAnyLock(sb);
27857+
e49829fe
JR
27858+ err = 0;
27859+ if (!au_opt_test(au_mntflags(sb), PLINK))
27860+ goto out;
27861+
27862+ sbi = au_sbi(sb);
27863+ pid = sbi->si_plink_maint_pid;
27864+ if (!pid || pid == current->pid)
27865+ goto out;
27866+
27867+ /* todo: it highly depends upon /sbin/mount.aufs */
f0c0a007
AM
27868+ prev = NULL;
27869+ parent = current;
27870+ ppid = 0;
e49829fe 27871+ rcu_read_lock();
f0c0a007
AM
27872+ while (1) {
27873+ parent = rcu_dereference(parent->real_parent);
27874+ if (parent == prev)
27875+ break;
27876+ ppid = task_pid_vnr(parent);
27877+ if (pid == ppid) {
27878+ rcu_read_unlock();
27879+ goto out;
27880+ }
27881+ prev = parent;
27882+ }
e49829fe 27883+ rcu_read_unlock();
e49829fe
JR
27884+
27885+ if (au_ftest_lock(flags, NOPLMW)) {
027c5e7a
AM
27886+ /* if there is no i_mutex lock in VFS, we don't need to wait */
27887+ /* AuDebugOn(!lockdep_depth(current)); */
e49829fe
JR
27888+ while (sbi->si_plink_maint_pid) {
27889+ si_read_unlock(sb);
27890+ /* gave up wake_up_bit() */
27891+ wait_event(sbi->si_plink_wq, !sbi->si_plink_maint_pid);
27892+
27893+ if (au_ftest_lock(flags, FLUSH))
27894+ au_nwt_flush(&sbi->si_nowait);
27895+ si_noflush_read_lock(sb);
27896+ }
27897+ } else if (au_ftest_lock(flags, NOPLM)) {
27898+ AuDbg("ppid %d, pid %d\n", ppid, pid);
27899+ err = -EAGAIN;
27900+ }
27901+
27902+out:
27903+ return err;
4a4d8108
AM
27904+}
27905+
e49829fe 27906+void au_plink_maint_leave(struct au_sbinfo *sbinfo)
4a4d8108 27907+{
4a4d8108 27908+ spin_lock(&sbinfo->si_plink_maint_lock);
027c5e7a 27909+ sbinfo->si_plink_maint_pid = 0;
4a4d8108 27910+ spin_unlock(&sbinfo->si_plink_maint_lock);
027c5e7a 27911+ wake_up_all(&sbinfo->si_plink_wq);
4a4d8108
AM
27912+}
27913+
e49829fe 27914+int au_plink_maint_enter(struct super_block *sb)
4a4d8108
AM
27915+{
27916+ int err;
4a4d8108
AM
27917+ struct au_sbinfo *sbinfo;
27918+
27919+ err = 0;
4a4d8108
AM
27920+ sbinfo = au_sbi(sb);
27921+ /* make sure i am the only one in this fs */
e49829fe
JR
27922+ si_write_lock(sb, AuLock_FLUSH);
27923+ if (au_opt_test(au_mntflags(sb), PLINK)) {
27924+ spin_lock(&sbinfo->si_plink_maint_lock);
27925+ if (!sbinfo->si_plink_maint_pid)
27926+ sbinfo->si_plink_maint_pid = current->pid;
27927+ else
27928+ err = -EBUSY;
27929+ spin_unlock(&sbinfo->si_plink_maint_lock);
27930+ }
4a4d8108
AM
27931+ si_write_unlock(sb);
27932+
27933+ return err;
1facf9fc 27934+}
27935+
27936+/* ---------------------------------------------------------------------- */
27937+
1facf9fc 27938+#ifdef CONFIG_AUFS_DEBUG
27939+void au_plink_list(struct super_block *sb)
27940+{
86dc4139 27941+ int i;
1facf9fc 27942+ struct au_sbinfo *sbinfo;
8b6a4947
AM
27943+ struct hlist_bl_head *hbl;
27944+ struct hlist_bl_node *pos;
5afbbe0d 27945+ struct au_icntnr *icntnr;
1facf9fc 27946+
dece6358
AM
27947+ SiMustAnyLock(sb);
27948+
1facf9fc 27949+ sbinfo = au_sbi(sb);
27950+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 27951+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 27952+
86dc4139 27953+ for (i = 0; i < AuPlink_NHASH; i++) {
8b6a4947
AM
27954+ hbl = sbinfo->si_plink + i;
27955+ hlist_bl_lock(hbl);
27956+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink)
5afbbe0d 27957+ AuDbg("%lu\n", icntnr->vfs_inode.i_ino);
8b6a4947 27958+ hlist_bl_unlock(hbl);
86dc4139 27959+ }
1facf9fc 27960+}
27961+#endif
27962+
27963+/* is the inode pseudo-linked? */
27964+int au_plink_test(struct inode *inode)
27965+{
86dc4139 27966+ int found, i;
1facf9fc 27967+ struct au_sbinfo *sbinfo;
8b6a4947
AM
27968+ struct hlist_bl_head *hbl;
27969+ struct hlist_bl_node *pos;
5afbbe0d 27970+ struct au_icntnr *icntnr;
1facf9fc 27971+
27972+ sbinfo = au_sbi(inode->i_sb);
dece6358 27973+ AuRwMustAnyLock(&sbinfo->si_rwsem);
1facf9fc 27974+ AuDebugOn(!au_opt_test(au_mntflags(inode->i_sb), PLINK));
e49829fe 27975+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
1facf9fc 27976+
27977+ found = 0;
86dc4139 27978+ i = au_plink_hash(inode->i_ino);
8b6a4947
AM
27979+ hbl = sbinfo->si_plink + i;
27980+ hlist_bl_lock(hbl);
27981+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink)
5afbbe0d 27982+ if (&icntnr->vfs_inode == inode) {
1facf9fc 27983+ found = 1;
27984+ break;
27985+ }
8b6a4947 27986+ hlist_bl_unlock(hbl);
1facf9fc 27987+ return found;
27988+}
27989+
27990+/* ---------------------------------------------------------------------- */
27991+
27992+/*
27993+ * generate a name for plink.
27994+ * the file will be stored under AUFS_WH_PLINKDIR.
27995+ */
27996+/* 20 is max digits length of ulong 64 */
27997+#define PLINK_NAME_LEN ((20 + 1) * 2)
27998+
27999+static int plink_name(char *name, int len, struct inode *inode,
28000+ aufs_bindex_t bindex)
28001+{
28002+ int rlen;
28003+ struct inode *h_inode;
28004+
28005+ h_inode = au_h_iptr(inode, bindex);
28006+ rlen = snprintf(name, len, "%lu.%lu", inode->i_ino, h_inode->i_ino);
28007+ return rlen;
28008+}
28009+
7f207e10
AM
28010+struct au_do_plink_lkup_args {
28011+ struct dentry **errp;
28012+ struct qstr *tgtname;
28013+ struct dentry *h_parent;
28014+ struct au_branch *br;
28015+};
28016+
28017+static struct dentry *au_do_plink_lkup(struct qstr *tgtname,
28018+ struct dentry *h_parent,
28019+ struct au_branch *br)
28020+{
28021+ struct dentry *h_dentry;
febd17d6 28022+ struct inode *h_inode;
7f207e10 28023+
febd17d6 28024+ h_inode = d_inode(h_parent);
be118d29 28025+ inode_lock_shared_nested(h_inode, AuLsc_I_CHILD2);
b4510431 28026+ h_dentry = vfsub_lkup_one(tgtname, h_parent);
3c1bdaff 28027+ inode_unlock_shared(h_inode);
7f207e10
AM
28028+ return h_dentry;
28029+}
28030+
28031+static void au_call_do_plink_lkup(void *args)
28032+{
28033+ struct au_do_plink_lkup_args *a = args;
28034+ *a->errp = au_do_plink_lkup(a->tgtname, a->h_parent, a->br);
28035+}
28036+
1facf9fc 28037+/* lookup the plink-ed @inode under the branch at @bindex */
28038+struct dentry *au_plink_lkup(struct inode *inode, aufs_bindex_t bindex)
28039+{
28040+ struct dentry *h_dentry, *h_parent;
28041+ struct au_branch *br;
7f207e10 28042+ int wkq_err;
1facf9fc 28043+ char a[PLINK_NAME_LEN];
0c3ec466 28044+ struct qstr tgtname = QSTR_INIT(a, 0);
1facf9fc 28045+
e49829fe
JR
28046+ AuDebugOn(au_plink_maint(inode->i_sb, AuLock_NOPLM));
28047+
1facf9fc 28048+ br = au_sbr(inode->i_sb, bindex);
28049+ h_parent = br->br_wbr->wbr_plink;
1facf9fc 28050+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
28051+
2dfbb274 28052+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) {
7f207e10
AM
28053+ struct au_do_plink_lkup_args args = {
28054+ .errp = &h_dentry,
28055+ .tgtname = &tgtname,
28056+ .h_parent = h_parent,
28057+ .br = br
28058+ };
28059+
28060+ wkq_err = au_wkq_wait(au_call_do_plink_lkup, &args);
28061+ if (unlikely(wkq_err))
28062+ h_dentry = ERR_PTR(wkq_err);
28063+ } else
28064+ h_dentry = au_do_plink_lkup(&tgtname, h_parent, br);
28065+
1facf9fc 28066+ return h_dentry;
28067+}
28068+
28069+/* create a pseudo-link */
28070+static int do_whplink(struct qstr *tgt, struct dentry *h_parent,
28071+ struct dentry *h_dentry, struct au_branch *br)
28072+{
28073+ int err;
28074+ struct path h_path = {
86dc4139 28075+ .mnt = au_br_mnt(br)
1facf9fc 28076+ };
523b37e3 28077+ struct inode *h_dir, *delegated;
1facf9fc 28078+
5527c038 28079+ h_dir = d_inode(h_parent);
febd17d6 28080+ inode_lock_nested(h_dir, AuLsc_I_CHILD2);
4f0767ce 28081+again:
b4510431 28082+ h_path.dentry = vfsub_lkup_one(tgt, h_parent);
1facf9fc 28083+ err = PTR_ERR(h_path.dentry);
28084+ if (IS_ERR(h_path.dentry))
28085+ goto out;
28086+
28087+ err = 0;
28088+ /* wh.plink dir is not monitored */
7f207e10 28089+ /* todo: is it really safe? */
5527c038
JR
28090+ if (d_is_positive(h_path.dentry)
28091+ && d_inode(h_path.dentry) != d_inode(h_dentry)) {
523b37e3
AM
28092+ delegated = NULL;
28093+ err = vfsub_unlink(h_dir, &h_path, &delegated, /*force*/0);
28094+ if (unlikely(err == -EWOULDBLOCK)) {
28095+ pr_warn("cannot retry for NFSv4 delegation"
28096+ " for an internal unlink\n");
28097+ iput(delegated);
28098+ }
1facf9fc 28099+ dput(h_path.dentry);
28100+ h_path.dentry = NULL;
28101+ if (!err)
28102+ goto again;
28103+ }
5527c038 28104+ if (!err && d_is_negative(h_path.dentry)) {
523b37e3
AM
28105+ delegated = NULL;
28106+ err = vfsub_link(h_dentry, h_dir, &h_path, &delegated);
28107+ if (unlikely(err == -EWOULDBLOCK)) {
28108+ pr_warn("cannot retry for NFSv4 delegation"
28109+ " for an internal link\n");
28110+ iput(delegated);
28111+ }
28112+ }
1facf9fc 28113+ dput(h_path.dentry);
28114+
4f0767ce 28115+out:
febd17d6 28116+ inode_unlock(h_dir);
1facf9fc 28117+ return err;
28118+}
28119+
28120+struct do_whplink_args {
28121+ int *errp;
28122+ struct qstr *tgt;
28123+ struct dentry *h_parent;
28124+ struct dentry *h_dentry;
28125+ struct au_branch *br;
28126+};
28127+
28128+static void call_do_whplink(void *args)
28129+{
28130+ struct do_whplink_args *a = args;
28131+ *a->errp = do_whplink(a->tgt, a->h_parent, a->h_dentry, a->br);
28132+}
28133+
28134+static int whplink(struct dentry *h_dentry, struct inode *inode,
28135+ aufs_bindex_t bindex, struct au_branch *br)
28136+{
28137+ int err, wkq_err;
28138+ struct au_wbr *wbr;
28139+ struct dentry *h_parent;
1facf9fc 28140+ char a[PLINK_NAME_LEN];
0c3ec466 28141+ struct qstr tgtname = QSTR_INIT(a, 0);
1facf9fc 28142+
28143+ wbr = au_sbr(inode->i_sb, bindex)->br_wbr;
28144+ h_parent = wbr->wbr_plink;
1facf9fc 28145+ tgtname.len = plink_name(a, sizeof(a), inode, bindex);
28146+
28147+ /* always superio. */
2dfbb274 28148+ if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) {
1facf9fc 28149+ struct do_whplink_args args = {
28150+ .errp = &err,
28151+ .tgt = &tgtname,
28152+ .h_parent = h_parent,
28153+ .h_dentry = h_dentry,
28154+ .br = br
28155+ };
28156+ wkq_err = au_wkq_wait(call_do_whplink, &args);
28157+ if (unlikely(wkq_err))
28158+ err = wkq_err;
28159+ } else
28160+ err = do_whplink(&tgtname, h_parent, h_dentry, br);
1facf9fc 28161+
28162+ return err;
28163+}
28164+
1facf9fc 28165+/*
28166+ * create a new pseudo-link for @h_dentry on @bindex.
28167+ * the linked inode is held in aufs @inode.
28168+ */
28169+void au_plink_append(struct inode *inode, aufs_bindex_t bindex,
28170+ struct dentry *h_dentry)
28171+{
28172+ struct super_block *sb;
28173+ struct au_sbinfo *sbinfo;
8b6a4947
AM
28174+ struct hlist_bl_head *hbl;
28175+ struct hlist_bl_node *pos;
5afbbe0d 28176+ struct au_icntnr *icntnr;
86dc4139 28177+ int found, err, cnt, i;
1facf9fc 28178+
28179+ sb = inode->i_sb;
28180+ sbinfo = au_sbi(sb);
28181+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 28182+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 28183+
86dc4139 28184+ found = au_plink_test(inode);
4a4d8108 28185+ if (found)
1facf9fc 28186+ return;
4a4d8108 28187+
86dc4139 28188+ i = au_plink_hash(inode->i_ino);
8b6a4947 28189+ hbl = sbinfo->si_plink + i;
5afbbe0d 28190+ au_igrab(inode);
1facf9fc 28191+
8b6a4947
AM
28192+ hlist_bl_lock(hbl);
28193+ hlist_bl_for_each_entry(icntnr, pos, hbl, plink) {
5afbbe0d 28194+ if (&icntnr->vfs_inode == inode) {
4a4d8108
AM
28195+ found = 1;
28196+ break;
28197+ }
1facf9fc 28198+ }
5afbbe0d
AM
28199+ if (!found) {
28200+ icntnr = container_of(inode, struct au_icntnr, vfs_inode);
8b6a4947 28201+ hlist_bl_add_head(&icntnr->plink, hbl);
5afbbe0d 28202+ }
8b6a4947 28203+ hlist_bl_unlock(hbl);
4a4d8108 28204+ if (!found) {
8b6a4947 28205+ cnt = au_hbl_count(hbl);
acd2b654 28206+#define msg "unexpectedly unbalanced or too many pseudo-links"
86dc4139
AM
28207+ if (cnt > AUFS_PLINK_WARN)
28208+ AuWarn1(msg ", %d\n", cnt);
28209+#undef msg
1facf9fc 28210+ err = whplink(h_dentry, inode, bindex, au_sbr(sb, bindex));
5afbbe0d
AM
28211+ if (unlikely(err)) {
28212+ pr_warn("err %d, damaged pseudo link.\n", err);
8b6a4947 28213+ au_hbl_del(&icntnr->plink, hbl);
5afbbe0d 28214+ iput(&icntnr->vfs_inode);
4a4d8108 28215+ }
5afbbe0d
AM
28216+ } else
28217+ iput(&icntnr->vfs_inode);
1facf9fc 28218+}
28219+
28220+/* free all plinks */
e49829fe 28221+void au_plink_put(struct super_block *sb, int verbose)
1facf9fc 28222+{
86dc4139 28223+ int i, warned;
1facf9fc 28224+ struct au_sbinfo *sbinfo;
8b6a4947
AM
28225+ struct hlist_bl_head *hbl;
28226+ struct hlist_bl_node *pos, *tmp;
5afbbe0d 28227+ struct au_icntnr *icntnr;
1facf9fc 28228+
dece6358
AM
28229+ SiMustWriteLock(sb);
28230+
1facf9fc 28231+ sbinfo = au_sbi(sb);
28232+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 28233+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 28234+
1facf9fc 28235+ /* no spin_lock since sbinfo is write-locked */
86dc4139
AM
28236+ warned = 0;
28237+ for (i = 0; i < AuPlink_NHASH; i++) {
8b6a4947
AM
28238+ hbl = sbinfo->si_plink + i;
28239+ if (!warned && verbose && !hlist_bl_empty(hbl)) {
86dc4139
AM
28240+ pr_warn("pseudo-link is not flushed");
28241+ warned = 1;
28242+ }
8b6a4947 28243+ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink)
5afbbe0d 28244+ iput(&icntnr->vfs_inode);
8b6a4947 28245+ INIT_HLIST_BL_HEAD(hbl);
86dc4139 28246+ }
1facf9fc 28247+}
28248+
e49829fe
JR
28249+void au_plink_clean(struct super_block *sb, int verbose)
28250+{
28251+ struct dentry *root;
28252+
28253+ root = sb->s_root;
28254+ aufs_write_lock(root);
28255+ if (au_opt_test(au_mntflags(sb), PLINK))
28256+ au_plink_put(sb, verbose);
28257+ aufs_write_unlock(root);
28258+}
28259+
86dc4139
AM
28260+static int au_plink_do_half_refresh(struct inode *inode, aufs_bindex_t br_id)
28261+{
28262+ int do_put;
5afbbe0d 28263+ aufs_bindex_t btop, bbot, bindex;
86dc4139
AM
28264+
28265+ do_put = 0;
5afbbe0d
AM
28266+ btop = au_ibtop(inode);
28267+ bbot = au_ibbot(inode);
28268+ if (btop >= 0) {
28269+ for (bindex = btop; bindex <= bbot; bindex++) {
86dc4139
AM
28270+ if (!au_h_iptr(inode, bindex)
28271+ || au_ii_br_id(inode, bindex) != br_id)
28272+ continue;
28273+ au_set_h_iptr(inode, bindex, NULL, 0);
28274+ do_put = 1;
28275+ break;
28276+ }
28277+ if (do_put)
5afbbe0d 28278+ for (bindex = btop; bindex <= bbot; bindex++)
86dc4139
AM
28279+ if (au_h_iptr(inode, bindex)) {
28280+ do_put = 0;
28281+ break;
28282+ }
28283+ } else
28284+ do_put = 1;
28285+
28286+ return do_put;
28287+}
28288+
1facf9fc 28289+/* free the plinks on a branch specified by @br_id */
28290+void au_plink_half_refresh(struct super_block *sb, aufs_bindex_t br_id)
28291+{
28292+ struct au_sbinfo *sbinfo;
8b6a4947
AM
28293+ struct hlist_bl_head *hbl;
28294+ struct hlist_bl_node *pos, *tmp;
5afbbe0d 28295+ struct au_icntnr *icntnr;
1facf9fc 28296+ struct inode *inode;
86dc4139 28297+ int i, do_put;
1facf9fc 28298+
dece6358
AM
28299+ SiMustWriteLock(sb);
28300+
1facf9fc 28301+ sbinfo = au_sbi(sb);
28302+ AuDebugOn(!au_opt_test(au_mntflags(sb), PLINK));
e49829fe 28303+ AuDebugOn(au_plink_maint(sb, AuLock_NOPLM));
1facf9fc 28304+
8b6a4947 28305+ /* no bit_lock since sbinfo is write-locked */
86dc4139 28306+ for (i = 0; i < AuPlink_NHASH; i++) {
8b6a4947
AM
28307+ hbl = sbinfo->si_plink + i;
28308+ hlist_bl_for_each_entry_safe(icntnr, pos, tmp, hbl, plink) {
5afbbe0d 28309+ inode = au_igrab(&icntnr->vfs_inode);
86dc4139
AM
28310+ ii_write_lock_child(inode);
28311+ do_put = au_plink_do_half_refresh(inode, br_id);
5afbbe0d 28312+ if (do_put) {
8b6a4947 28313+ hlist_bl_del(&icntnr->plink);
5afbbe0d
AM
28314+ iput(inode);
28315+ }
86dc4139
AM
28316+ ii_write_unlock(inode);
28317+ iput(inode);
dece6358 28318+ }
dece6358
AM
28319+ }
28320+}
7f207e10 28321diff -urN /usr/share/empty/fs/aufs/poll.c linux/fs/aufs/poll.c
eca34b5c 28322--- /usr/share/empty/fs/aufs/poll.c 1970-01-01 01:00:00.000000000 +0100
016522bc 28323+++ linux/fs/aufs/poll.c 2020-01-27 10:57:18.175538316 +0100
cd7a4cd9
AM
28324@@ -0,0 +1,51 @@
28325+// SPDX-License-Identifier: GPL-2.0
dece6358 28326+/*
016522bc 28327+ * Copyright (C) 2005-2020 Junjiro R. Okajima
dece6358
AM
28328+ *
28329+ * This program, aufs is free software; you can redistribute it and/or modify
28330+ * it under the terms of the GNU General Public License as published by
28331+ * the Free Software Foundation; either version 2 of the License, or
28332+ * (at your option) any later version.
28333+ *
28334+ * This program is distributed in the hope that it will be useful,
28335+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28336+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28337+ * GNU General Public License for more details.
28338+ *
28339+ * You should have received a copy of the GNU General Public License
523b37e3 28340+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
dece6358
AM
28341+ */
28342+
1308ab2a 28343+/*
28344+ * poll operation
28345+ * There is only one filesystem which implements ->poll operation, currently.
28346+ */
28347+
28348+#include "aufs.h"
28349+
cd7a4cd9 28350+__poll_t aufs_poll(struct file *file, struct poll_table_struct *pt)
1308ab2a 28351+{
be118d29 28352+ __poll_t mask;
1308ab2a 28353+ struct file *h_file;
1308ab2a 28354+ struct super_block *sb;
28355+
28356+ /* We should pretend an error happened. */
be118d29 28357+ mask = EPOLLERR /* | EPOLLIN | EPOLLOUT */;
b912730e 28358+ sb = file->f_path.dentry->d_sb;
e49829fe 28359+ si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLMW);
b912730e 28360+
521ced18 28361+ h_file = au_read_pre(file, /*keep_fi*/0, /*lsc*/0);
062440b3
AM
28362+ if (IS_ERR(h_file)) {
28363+ AuDbg("h_file %ld\n", PTR_ERR(h_file));
1308ab2a 28364+ goto out;
062440b3 28365+ }
1308ab2a 28366+
cd7a4cd9 28367+ mask = vfs_poll(h_file, pt);
b912730e 28368+ fput(h_file); /* instead of au_read_post() */
1308ab2a 28369+
4f0767ce 28370+out:
1308ab2a 28371+ si_read_unlock(sb);
062440b3 28372+ if (mask & EPOLLERR)
b00004a5 28373+ AuDbg("mask 0x%x\n", mask);
1308ab2a 28374+ return mask;
28375+}
c1595e42 28376diff -urN /usr/share/empty/fs/aufs/posix_acl.c linux/fs/aufs/posix_acl.c
eca34b5c 28377--- /usr/share/empty/fs/aufs/posix_acl.c 1970-01-01 01:00:00.000000000 +0100
016522bc 28378+++ linux/fs/aufs/posix_acl.c 2020-01-27 10:57:18.175538316 +0100
9f00928d 28379@@ -0,0 +1,105 @@
cd7a4cd9 28380+// SPDX-License-Identifier: GPL-2.0
c1595e42 28381+/*
016522bc 28382+ * Copyright (C) 2014-2020 Junjiro R. Okajima
c1595e42
JR
28383+ *
28384+ * This program, aufs is free software; you can redistribute it and/or modify
28385+ * it under the terms of the GNU General Public License as published by
28386+ * the Free Software Foundation; either version 2 of the License, or
28387+ * (at your option) any later version.
28388+ *
28389+ * This program is distributed in the hope that it will be useful,
28390+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28391+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28392+ * GNU General Public License for more details.
28393+ *
28394+ * You should have received a copy of the GNU General Public License
28395+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
28396+ */
28397+
28398+/*
28399+ * posix acl operations
28400+ */
28401+
28402+#include <linux/fs.h>
c1595e42
JR
28403+#include "aufs.h"
28404+
28405+struct posix_acl *aufs_get_acl(struct inode *inode, int type)
28406+{
28407+ struct posix_acl *acl;
28408+ int err;
28409+ aufs_bindex_t bindex;
28410+ struct inode *h_inode;
28411+ struct super_block *sb;
28412+
28413+ acl = NULL;
28414+ sb = inode->i_sb;
28415+ si_read_lock(sb, AuLock_FLUSH);
28416+ ii_read_lock_child(inode);
2121bcd9 28417+ if (!(sb->s_flags & SB_POSIXACL))
c1595e42
JR
28418+ goto out;
28419+
5afbbe0d 28420+ bindex = au_ibtop(inode);
c1595e42
JR
28421+ h_inode = au_h_iptr(inode, bindex);
28422+ if (unlikely(!h_inode
28423+ || ((h_inode->i_mode & S_IFMT)
28424+ != (inode->i_mode & S_IFMT)))) {
28425+ err = au_busy_or_stale();
28426+ acl = ERR_PTR(err);
28427+ goto out;
28428+ }
28429+
28430+ /* always topmost only */
28431+ acl = get_acl(h_inode, type);
9f00928d
AM
28432+ if (IS_ERR(acl))
28433+ forget_cached_acl(inode, type);
28434+ else
a2654f78 28435+ set_cached_acl(inode, type, acl);
c1595e42
JR
28436+
28437+out:
28438+ ii_read_unlock(inode);
28439+ si_read_unlock(sb);
28440+
28441+ AuTraceErrPtr(acl);
28442+ return acl;
28443+}
28444+
28445+int aufs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
28446+{
28447+ int err;
28448+ ssize_t ssz;
28449+ struct dentry *dentry;
f2c43d5f 28450+ struct au_sxattr arg = {
c1595e42
JR
28451+ .type = AU_ACL_SET,
28452+ .u.acl_set = {
28453+ .acl = acl,
28454+ .type = type
28455+ },
28456+ };
28457+
5afbbe0d
AM
28458+ IMustLock(inode);
28459+
c1595e42
JR
28460+ if (inode->i_ino == AUFS_ROOT_INO)
28461+ dentry = dget(inode->i_sb->s_root);
28462+ else {
28463+ dentry = d_find_alias(inode);
28464+ if (!dentry)
28465+ dentry = d_find_any_alias(inode);
28466+ if (!dentry) {
28467+ pr_warn("cannot handle this inode, "
28468+ "please report to aufs-users ML\n");
28469+ err = -ENOENT;
28470+ goto out;
28471+ }
28472+ }
28473+
f2c43d5f 28474+ ssz = au_sxattr(dentry, inode, &arg);
9f00928d
AM
28475+ /* forget even it if succeeds since the branch might set differently */
28476+ forget_cached_acl(inode, type);
c1595e42
JR
28477+ dput(dentry);
28478+ err = ssz;
9f00928d 28479+ if (ssz >= 0)
c1595e42
JR
28480+ err = 0;
28481+
28482+out:
c1595e42
JR
28483+ return err;
28484+}
7f207e10 28485diff -urN /usr/share/empty/fs/aufs/procfs.c linux/fs/aufs/procfs.c
eca34b5c 28486--- /usr/share/empty/fs/aufs/procfs.c 1970-01-01 01:00:00.000000000 +0100
016522bc 28487+++ linux/fs/aufs/procfs.c 2020-04-03 08:16:47.547461775 +0200
062440b3 28488@@ -0,0 +1,171 @@
cd7a4cd9 28489+// SPDX-License-Identifier: GPL-2.0
e49829fe 28490+/*
016522bc 28491+ * Copyright (C) 2010-2020 Junjiro R. Okajima
e49829fe
JR
28492+ *
28493+ * This program, aufs is free software; you can redistribute it and/or modify
28494+ * it under the terms of the GNU General Public License as published by
28495+ * the Free Software Foundation; either version 2 of the License, or
28496+ * (at your option) any later version.
28497+ *
28498+ * This program is distributed in the hope that it will be useful,
28499+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28500+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28501+ * GNU General Public License for more details.
28502+ *
28503+ * You should have received a copy of the GNU General Public License
523b37e3 28504+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
e49829fe
JR
28505+ */
28506+
28507+/*
28508+ * procfs interfaces
28509+ */
28510+
28511+#include <linux/proc_fs.h>
28512+#include "aufs.h"
28513+
28514+static int au_procfs_plm_release(struct inode *inode, struct file *file)
28515+{
28516+ struct au_sbinfo *sbinfo;
28517+
28518+ sbinfo = file->private_data;
28519+ if (sbinfo) {
28520+ au_plink_maint_leave(sbinfo);
28521+ kobject_put(&sbinfo->si_kobj);
28522+ }
28523+
28524+ return 0;
28525+}
28526+
28527+static void au_procfs_plm_write_clean(struct file *file)
28528+{
28529+ struct au_sbinfo *sbinfo;
28530+
28531+ sbinfo = file->private_data;
28532+ if (sbinfo)
28533+ au_plink_clean(sbinfo->si_sb, /*verbose*/0);
28534+}
28535+
28536+static int au_procfs_plm_write_si(struct file *file, unsigned long id)
28537+{
28538+ int err;
28539+ struct super_block *sb;
28540+ struct au_sbinfo *sbinfo;
8b6a4947 28541+ struct hlist_bl_node *pos;
e49829fe
JR
28542+
28543+ err = -EBUSY;
28544+ if (unlikely(file->private_data))
28545+ goto out;
28546+
28547+ sb = NULL;
53392da6 28548+ /* don't use au_sbilist_lock() here */
8b6a4947
AM
28549+ hlist_bl_lock(&au_sbilist);
28550+ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list)
e49829fe 28551+ if (id == sysaufs_si_id(sbinfo)) {
83b672a5
AM
28552+ if (kobject_get_unless_zero(&sbinfo->si_kobj))
28553+ sb = sbinfo->si_sb;
e49829fe
JR
28554+ break;
28555+ }
8b6a4947 28556+ hlist_bl_unlock(&au_sbilist);
e49829fe
JR
28557+
28558+ err = -EINVAL;
28559+ if (unlikely(!sb))
28560+ goto out;
28561+
28562+ err = au_plink_maint_enter(sb);
28563+ if (!err)
28564+ /* keep kobject_get() */
28565+ file->private_data = sbinfo;
28566+ else
28567+ kobject_put(&sbinfo->si_kobj);
28568+out:
28569+ return err;
28570+}
28571+
28572+/*
28573+ * Accept a valid "si=xxxx" only.
28574+ * Once it is accepted successfully, accept "clean" too.
28575+ */
28576+static ssize_t au_procfs_plm_write(struct file *file, const char __user *ubuf,
28577+ size_t count, loff_t *ppos)
28578+{
28579+ ssize_t err;
28580+ unsigned long id;
28581+ /* last newline is allowed */
28582+ char buf[3 + sizeof(unsigned long) * 2 + 1];
28583+
28584+ err = -EACCES;
28585+ if (unlikely(!capable(CAP_SYS_ADMIN)))
28586+ goto out;
28587+
28588+ err = -EINVAL;
28589+ if (unlikely(count > sizeof(buf)))
28590+ goto out;
28591+
28592+ err = copy_from_user(buf, ubuf, count);
28593+ if (unlikely(err)) {
28594+ err = -EFAULT;
28595+ goto out;
28596+ }
28597+ buf[count] = 0;
28598+
28599+ err = -EINVAL;
28600+ if (!strcmp("clean", buf)) {
28601+ au_procfs_plm_write_clean(file);
28602+ goto out_success;
28603+ } else if (unlikely(strncmp("si=", buf, 3)))
28604+ goto out;
28605+
9dbd164d 28606+ err = kstrtoul(buf + 3, 16, &id);
e49829fe
JR
28607+ if (unlikely(err))
28608+ goto out;
28609+
28610+ err = au_procfs_plm_write_si(file, id);
28611+ if (unlikely(err))
28612+ goto out;
28613+
28614+out_success:
28615+ err = count; /* success */
28616+out:
28617+ return err;
28618+}
28619+
28620+static const struct file_operations au_procfs_plm_fop = {
28621+ .write = au_procfs_plm_write,
28622+ .release = au_procfs_plm_release,
28623+ .owner = THIS_MODULE
28624+};
28625+
28626+/* ---------------------------------------------------------------------- */
28627+
28628+static struct proc_dir_entry *au_procfs_dir;
28629+
28630+void au_procfs_fin(void)
28631+{
28632+ remove_proc_entry(AUFS_PLINK_MAINT_NAME, au_procfs_dir);
28633+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
28634+}
28635+
28636+int __init au_procfs_init(void)
28637+{
28638+ int err;
28639+ struct proc_dir_entry *entry;
28640+
28641+ err = -ENOMEM;
28642+ au_procfs_dir = proc_mkdir(AUFS_PLINK_MAINT_DIR, NULL);
28643+ if (unlikely(!au_procfs_dir))
28644+ goto out;
28645+
cd7a4cd9 28646+ entry = proc_create(AUFS_PLINK_MAINT_NAME, S_IFREG | 0200,
e49829fe
JR
28647+ au_procfs_dir, &au_procfs_plm_fop);
28648+ if (unlikely(!entry))
28649+ goto out_dir;
28650+
28651+ err = 0;
28652+ goto out; /* success */
28653+
28654+
28655+out_dir:
28656+ remove_proc_entry(AUFS_PLINK_MAINT_DIR, NULL);
28657+out:
28658+ return err;
28659+}
7f207e10 28660diff -urN /usr/share/empty/fs/aufs/rdu.c linux/fs/aufs/rdu.c
eca34b5c 28661--- /usr/share/empty/fs/aufs/rdu.c 1970-01-01 01:00:00.000000000 +0100
016522bc 28662+++ linux/fs/aufs/rdu.c 2020-01-27 10:57:18.178871751 +0100
ba1aed25 28663@@ -0,0 +1,384 @@
cd7a4cd9 28664+// SPDX-License-Identifier: GPL-2.0
1308ab2a 28665+/*
016522bc 28666+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1308ab2a 28667+ *
28668+ * This program, aufs is free software; you can redistribute it and/or modify
28669+ * it under the terms of the GNU General Public License as published by
28670+ * the Free Software Foundation; either version 2 of the License, or
28671+ * (at your option) any later version.
28672+ *
28673+ * This program is distributed in the hope that it will be useful,
28674+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
28675+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28676+ * GNU General Public License for more details.
28677+ *
28678+ * You should have received a copy of the GNU General Public License
523b37e3 28679+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1308ab2a 28680+ */
28681+
28682+/*
28683+ * readdir in userspace.
28684+ */
28685+
b752ccd1 28686+#include <linux/compat.h>
4a4d8108 28687+#include <linux/fs_stack.h>
1308ab2a 28688+#include <linux/security.h>
1308ab2a 28689+#include "aufs.h"
28690+
28691+/* bits for struct aufs_rdu.flags */
28692+#define AuRdu_CALLED 1
28693+#define AuRdu_CONT (1 << 1)
28694+#define AuRdu_FULL (1 << 2)
28695+#define au_ftest_rdu(flags, name) ((flags) & AuRdu_##name)
7f207e10
AM
28696+#define au_fset_rdu(flags, name) \
28697+ do { (flags) |= AuRdu_##name; } while (0)
28698+#define au_fclr_rdu(flags, name) \
28699+ do { (flags) &= ~AuRdu_##name; } while (0)
1308ab2a 28700+
28701+struct au_rdu_arg {
392086de 28702+ struct dir_context ctx;
1308ab2a 28703+ struct aufs_rdu *rdu;
28704+ union au_rdu_ent_ul ent;
28705+ unsigned long end;
28706+
28707+ struct super_block *sb;
28708+ int err;
28709+};
28710+
392086de 28711+static int au_rdu_fill(struct dir_context *ctx, const char *name, int nlen,
1308ab2a 28712+ loff_t offset, u64 h_ino, unsigned int d_type)
28713+{
28714+ int err, len;
392086de 28715+ struct au_rdu_arg *arg = container_of(ctx, struct au_rdu_arg, ctx);
1308ab2a 28716+ struct aufs_rdu *rdu = arg->rdu;
28717+ struct au_rdu_ent ent;
28718+
28719+ err = 0;
28720+ arg->err = 0;
28721+ au_fset_rdu(rdu->cookie.flags, CALLED);
28722+ len = au_rdu_len(nlen);
28723+ if (arg->ent.ul + len < arg->end) {
28724+ ent.ino = h_ino;
28725+ ent.bindex = rdu->cookie.bindex;
28726+ ent.type = d_type;
28727+ ent.nlen = nlen;
4a4d8108
AM
28728+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
28729+ ent.type = DT_UNKNOWN;
1308ab2a 28730+
9dbd164d 28731+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 28732+ err = -EFAULT;
28733+ if (copy_to_user(arg->ent.e, &ent, sizeof(ent)))
28734+ goto out;
28735+ if (copy_to_user(arg->ent.e->name, name, nlen))
28736+ goto out;
28737+ /* the terminating NULL */
28738+ if (__put_user(0, arg->ent.e->name + nlen))
28739+ goto out;
28740+ err = 0;
28741+ /* AuDbg("%p, %.*s\n", arg->ent.p, nlen, name); */
28742+ arg->ent.ul += len;
28743+ rdu->rent++;
28744+ } else {
28745+ err = -EFAULT;
28746+ au_fset_rdu(rdu->cookie.flags, FULL);
28747+ rdu->full = 1;
28748+ rdu->tail = arg->ent;
28749+ }
28750+
4f0767ce 28751+out:
1308ab2a 28752+ /* AuTraceErr(err); */
28753+ return err;
28754+}
28755+
28756+static int au_rdu_do(struct file *h_file, struct au_rdu_arg *arg)
28757+{
28758+ int err;
28759+ loff_t offset;
28760+ struct au_rdu_cookie *cookie = &arg->rdu->cookie;
28761+
92d182d2 28762+ /* we don't have to care (FMODE_32BITHASH | FMODE_64BITHASH) for ext4 */
1308ab2a 28763+ offset = vfsub_llseek(h_file, cookie->h_pos, SEEK_SET);
28764+ err = offset;
28765+ if (unlikely(offset != cookie->h_pos))
28766+ goto out;
28767+
28768+ err = 0;
28769+ do {
28770+ arg->err = 0;
28771+ au_fclr_rdu(cookie->flags, CALLED);
28772+ /* smp_mb(); */
392086de 28773+ err = vfsub_iterate_dir(h_file, &arg->ctx);
1308ab2a 28774+ if (err >= 0)
28775+ err = arg->err;
28776+ } while (!err
28777+ && au_ftest_rdu(cookie->flags, CALLED)
28778+ && !au_ftest_rdu(cookie->flags, FULL));
28779+ cookie->h_pos = h_file->f_pos;
28780+
4f0767ce 28781+out:
1308ab2a 28782+ AuTraceErr(err);
28783+ return err;
28784+}
28785+
28786+static int au_rdu(struct file *file, struct aufs_rdu *rdu)
28787+{
28788+ int err;
5afbbe0d 28789+ aufs_bindex_t bbot;
392086de
AM
28790+ struct au_rdu_arg arg = {
28791+ .ctx = {
2000de60 28792+ .actor = au_rdu_fill
392086de
AM
28793+ }
28794+ };
1308ab2a 28795+ struct dentry *dentry;
28796+ struct inode *inode;
28797+ struct file *h_file;
28798+ struct au_rdu_cookie *cookie = &rdu->cookie;
28799+
ba1aed25
AM
28800+ /* VERIFY_WRITE */
28801+ err = !access_ok(rdu->ent.e, rdu->sz);
1308ab2a 28802+ if (unlikely(err)) {
28803+ err = -EFAULT;
28804+ AuTraceErr(err);
28805+ goto out;
28806+ }
28807+ rdu->rent = 0;
28808+ rdu->tail = rdu->ent;
28809+ rdu->full = 0;
28810+ arg.rdu = rdu;
28811+ arg.ent = rdu->ent;
28812+ arg.end = arg.ent.ul;
28813+ arg.end += rdu->sz;
28814+
28815+ err = -ENOTDIR;
5afbbe0d 28816+ if (unlikely(!file->f_op->iterate && !file->f_op->iterate_shared))
1308ab2a 28817+ goto out;
28818+
28819+ err = security_file_permission(file, MAY_READ);
28820+ AuTraceErr(err);
28821+ if (unlikely(err))
28822+ goto out;
28823+
2000de60 28824+ dentry = file->f_path.dentry;
5527c038 28825+ inode = d_inode(dentry);
5afbbe0d 28826+ inode_lock_shared(inode);
1308ab2a 28827+
28828+ arg.sb = inode->i_sb;
e49829fe
JR
28829+ err = si_read_lock(arg.sb, AuLock_FLUSH | AuLock_NOPLM);
28830+ if (unlikely(err))
28831+ goto out_mtx;
027c5e7a
AM
28832+ err = au_alive_dir(dentry);
28833+ if (unlikely(err))
28834+ goto out_si;
e49829fe 28835+ /* todo: reval? */
1308ab2a 28836+ fi_read_lock(file);
28837+
28838+ err = -EAGAIN;
28839+ if (unlikely(au_ftest_rdu(cookie->flags, CONT)
28840+ && cookie->generation != au_figen(file)))
28841+ goto out_unlock;
28842+
28843+ err = 0;
28844+ if (!rdu->blk) {
28845+ rdu->blk = au_sbi(arg.sb)->si_rdblk;
28846+ if (!rdu->blk)
28847+ rdu->blk = au_dir_size(file, /*dentry*/NULL);
28848+ }
5afbbe0d
AM
28849+ bbot = au_fbtop(file);
28850+ if (cookie->bindex < bbot)
28851+ cookie->bindex = bbot;
28852+ bbot = au_fbbot_dir(file);
28853+ /* AuDbg("b%d, b%d\n", cookie->bindex, bbot); */
28854+ for (; !err && cookie->bindex <= bbot;
1308ab2a 28855+ cookie->bindex++, cookie->h_pos = 0) {
4a4d8108 28856+ h_file = au_hf_dir(file, cookie->bindex);
1308ab2a 28857+ if (!h_file)
28858+ continue;
28859+
28860+ au_fclr_rdu(cookie->flags, FULL);
28861+ err = au_rdu_do(h_file, &arg);
28862+ AuTraceErr(err);
28863+ if (unlikely(au_ftest_rdu(cookie->flags, FULL) || err))
28864+ break;
28865+ }
28866+ AuDbg("rent %llu\n", rdu->rent);
28867+
28868+ if (!err && !au_ftest_rdu(cookie->flags, CONT)) {
28869+ rdu->shwh = !!au_opt_test(au_sbi(arg.sb)->si_mntflags, SHWH);
28870+ au_fset_rdu(cookie->flags, CONT);
28871+ cookie->generation = au_figen(file);
28872+ }
28873+
28874+ ii_read_lock_child(inode);
5afbbe0d 28875+ fsstack_copy_attr_atime(inode, au_h_iptr(inode, au_ibtop(inode)));
1308ab2a 28876+ ii_read_unlock(inode);
28877+
4f0767ce 28878+out_unlock:
1308ab2a 28879+ fi_read_unlock(file);
027c5e7a 28880+out_si:
1308ab2a 28881+ si_read_unlock(arg.sb);
4f0767ce 28882+out_mtx:
5afbbe0d 28883+ inode_unlock_shared(inode);
4f0767ce 28884+out:
1308ab2a 28885+ AuTraceErr(err);
28886+ return err;
28887+}
28888+
28889+static int au_rdu_ino(struct file *file, struct aufs_rdu *rdu)
28890+{
28891+ int err;
28892+ ino_t ino;
28893+ unsigned long long nent;
28894+ union au_rdu_ent_ul *u;
28895+ struct au_rdu_ent ent;
28896+ struct super_block *sb;
28897+
28898+ err = 0;
28899+ nent = rdu->nent;
28900+ u = &rdu->ent;
2000de60 28901+ sb = file->f_path.dentry->d_sb;
1308ab2a 28902+ si_read_lock(sb, AuLock_FLUSH);
28903+ while (nent-- > 0) {
9dbd164d 28904+ /* unnecessary to support mmap_sem since this is a dir */
1308ab2a 28905+ err = copy_from_user(&ent, u->e, sizeof(ent));
4a4d8108 28906+ if (!err)
ba1aed25
AM
28907+ /* VERIFY_WRITE */
28908+ err = !access_ok(&u->e->ino, sizeof(ino));
1308ab2a 28909+ if (unlikely(err)) {
28910+ err = -EFAULT;
28911+ AuTraceErr(err);
28912+ break;
28913+ }
28914+
28915+ /* AuDbg("b%d, i%llu\n", ent.bindex, ent.ino); */
28916+ if (!ent.wh)
28917+ err = au_ino(sb, ent.bindex, ent.ino, ent.type, &ino);
28918+ else
28919+ err = au_wh_ino(sb, ent.bindex, ent.ino, ent.type,
28920+ &ino);
28921+ if (unlikely(err)) {
28922+ AuTraceErr(err);
28923+ break;
28924+ }
28925+
28926+ err = __put_user(ino, &u->e->ino);
28927+ if (unlikely(err)) {
28928+ err = -EFAULT;
28929+ AuTraceErr(err);
28930+ break;
28931+ }
28932+ u->ul += au_rdu_len(ent.nlen);
28933+ }
28934+ si_read_unlock(sb);
28935+
28936+ return err;
28937+}
28938+
28939+/* ---------------------------------------------------------------------- */
28940+
28941+static int au_rdu_verify(struct aufs_rdu *rdu)
28942+{
b752ccd1 28943+ AuDbg("rdu{%llu, %p, %u | %u | %llu, %u, %u | "
1308ab2a 28944+ "%llu, b%d, 0x%x, g%u}\n",
b752ccd1 28945+ rdu->sz, rdu->ent.e, rdu->verify[AufsCtlRduV_SZ],
1308ab2a 28946+ rdu->blk,
28947+ rdu->rent, rdu->shwh, rdu->full,
28948+ rdu->cookie.h_pos, rdu->cookie.bindex, rdu->cookie.flags,
28949+ rdu->cookie.generation);
dece6358 28950+
b752ccd1 28951+ if (rdu->verify[AufsCtlRduV_SZ] == sizeof(*rdu))
1308ab2a 28952+ return 0;
dece6358 28953+
b752ccd1
AM
28954+ AuDbg("%u:%u\n",
28955+ rdu->verify[AufsCtlRduV_SZ], (unsigned int)sizeof(*rdu));
1308ab2a 28956+ return -EINVAL;
28957+}
28958+
28959+long au_rdu_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
dece6358 28960+{
1308ab2a 28961+ long err, e;
28962+ struct aufs_rdu rdu;
28963+ void __user *p = (void __user *)arg;
dece6358 28964+
1308ab2a 28965+ err = copy_from_user(&rdu, p, sizeof(rdu));
28966+ if (unlikely(err)) {
28967+ err = -EFAULT;
28968+ AuTraceErr(err);
28969+ goto out;
28970+ }
28971+ err = au_rdu_verify(&rdu);
dece6358
AM
28972+ if (unlikely(err))
28973+ goto out;
28974+
1308ab2a 28975+ switch (cmd) {
28976+ case AUFS_CTL_RDU:
28977+ err = au_rdu(file, &rdu);
28978+ if (unlikely(err))
28979+ break;
dece6358 28980+
1308ab2a 28981+ e = copy_to_user(p, &rdu, sizeof(rdu));
28982+ if (unlikely(e)) {
28983+ err = -EFAULT;
28984+ AuTraceErr(err);
28985+ }
28986+ break;
28987+ case AUFS_CTL_RDU_INO:
28988+ err = au_rdu_ino(file, &rdu);
28989+ break;
28990+
28991+ default:
4a4d8108 28992+ /* err = -ENOTTY; */
1308ab2a 28993+ err = -EINVAL;
28994+ }
dece6358 28995+
4f0767ce 28996+out:
1308ab2a 28997+ AuTraceErr(err);
28998+ return err;
1facf9fc 28999+}
b752ccd1
AM
29000+
29001+#ifdef CONFIG_COMPAT
29002+long au_rdu_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
29003+{
29004+ long err, e;
29005+ struct aufs_rdu rdu;
29006+ void __user *p = compat_ptr(arg);
29007+
29008+ /* todo: get_user()? */
29009+ err = copy_from_user(&rdu, p, sizeof(rdu));
29010+ if (unlikely(err)) {
29011+ err = -EFAULT;
29012+ AuTraceErr(err);
29013+ goto out;
29014+ }
29015+ rdu.ent.e = compat_ptr(rdu.ent.ul);
29016+ err = au_rdu_verify(&rdu);
29017+ if (unlikely(err))
29018+ goto out;
29019+
29020+ switch (cmd) {
29021+ case AUFS_CTL_RDU:
29022+ err = au_rdu(file, &rdu);
29023+ if (unlikely(err))
29024+ break;
29025+
29026+ rdu.ent.ul = ptr_to_compat(rdu.ent.e);
29027+ rdu.tail.ul = ptr_to_compat(rdu.tail.e);
29028+ e = copy_to_user(p, &rdu, sizeof(rdu));
29029+ if (unlikely(e)) {
29030+ err = -EFAULT;
29031+ AuTraceErr(err);
29032+ }
29033+ break;
29034+ case AUFS_CTL_RDU_INO:
29035+ err = au_rdu_ino(file, &rdu);
29036+ break;
29037+
29038+ default:
29039+ /* err = -ENOTTY; */
29040+ err = -EINVAL;
29041+ }
29042+
4f0767ce 29043+out:
b752ccd1
AM
29044+ AuTraceErr(err);
29045+ return err;
29046+}
29047+#endif
7f207e10 29048diff -urN /usr/share/empty/fs/aufs/rwsem.h linux/fs/aufs/rwsem.h
eca34b5c 29049--- /usr/share/empty/fs/aufs/rwsem.h 1970-01-01 01:00:00.000000000 +0100
016522bc 29050+++ linux/fs/aufs/rwsem.h 2020-01-27 10:57:18.178871751 +0100
062440b3
AM
29051@@ -0,0 +1,73 @@
29052+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 29053+/*
016522bc 29054+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 29055+ *
29056+ * This program, aufs is free software; you can redistribute it and/or modify
29057+ * it under the terms of the GNU General Public License as published by
29058+ * the Free Software Foundation; either version 2 of the License, or
29059+ * (at your option) any later version.
dece6358
AM
29060+ *
29061+ * This program is distributed in the hope that it will be useful,
29062+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29063+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29064+ * GNU General Public License for more details.
29065+ *
29066+ * You should have received a copy of the GNU General Public License
523b37e3 29067+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 29068+ */
29069+
29070+/*
29071+ * simple read-write semaphore wrappers
29072+ */
29073+
29074+#ifndef __AUFS_RWSEM_H__
29075+#define __AUFS_RWSEM_H__
29076+
29077+#ifdef __KERNEL__
29078+
4a4d8108 29079+#include "debug.h"
dece6358 29080+
acd2b654 29081+/* in the future, the name 'au_rwsem' will be totally gone */
8b6a4947 29082+#define au_rwsem rw_semaphore
dece6358
AM
29083+
29084+/* to debug easier, do not make them inlined functions */
8b6a4947 29085+#define AuRwMustNoWaiters(rw) AuDebugOn(rwsem_is_contended(rw))
dece6358 29086+/* rwsem_is_locked() is unusable */
8b6a4947
AM
29087+#define AuRwMustReadLock(rw) AuDebugOn(!lockdep_recursing(current) \
29088+ && debug_locks \
29089+ && !lockdep_is_held_type(rw, 1))
29090+#define AuRwMustWriteLock(rw) AuDebugOn(!lockdep_recursing(current) \
29091+ && debug_locks \
29092+ && !lockdep_is_held_type(rw, 0))
29093+#define AuRwMustAnyLock(rw) AuDebugOn(!lockdep_recursing(current) \
29094+ && debug_locks \
29095+ && !lockdep_is_held(rw))
29096+#define AuRwDestroy(rw) AuDebugOn(!lockdep_recursing(current) \
29097+ && debug_locks \
29098+ && lockdep_is_held(rw))
29099+
29100+#define au_rw_init(rw) init_rwsem(rw)
dece6358 29101+
5afbbe0d
AM
29102+#define au_rw_init_wlock(rw) do { \
29103+ au_rw_init(rw); \
8b6a4947 29104+ down_write(rw); \
5afbbe0d 29105+ } while (0)
dece6358 29106+
8b6a4947
AM
29107+#define au_rw_init_wlock_nested(rw, lsc) do { \
29108+ au_rw_init(rw); \
29109+ down_write_nested(rw, lsc); \
5afbbe0d 29110+ } while (0)
dece6358 29111+
8b6a4947
AM
29112+#define au_rw_read_lock(rw) down_read(rw)
29113+#define au_rw_read_lock_nested(rw, lsc) down_read_nested(rw, lsc)
29114+#define au_rw_read_unlock(rw) up_read(rw)
29115+#define au_rw_dgrade_lock(rw) downgrade_write(rw)
29116+#define au_rw_write_lock(rw) down_write(rw)
29117+#define au_rw_write_lock_nested(rw, lsc) down_write_nested(rw, lsc)
29118+#define au_rw_write_unlock(rw) up_write(rw)
29119+/* why is not _nested version defined? */
29120+#define au_rw_read_trylock(rw) down_read_trylock(rw)
29121+#define au_rw_write_trylock(rw) down_write_trylock(rw)
1facf9fc 29122+
29123+#endif /* __KERNEL__ */
29124+#endif /* __AUFS_RWSEM_H__ */
7f207e10 29125diff -urN /usr/share/empty/fs/aufs/sbinfo.c linux/fs/aufs/sbinfo.c
eca34b5c 29126--- /usr/share/empty/fs/aufs/sbinfo.c 1970-01-01 01:00:00.000000000 +0100
016522bc 29127+++ linux/fs/aufs/sbinfo.c 2020-01-27 10:57:18.178871751 +0100
eca801bf 29128@@ -0,0 +1,314 @@
cd7a4cd9 29129+// SPDX-License-Identifier: GPL-2.0
1facf9fc 29130+/*
016522bc 29131+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 29132+ *
29133+ * This program, aufs is free software; you can redistribute it and/or modify
29134+ * it under the terms of the GNU General Public License as published by
29135+ * the Free Software Foundation; either version 2 of the License, or
29136+ * (at your option) any later version.
dece6358
AM
29137+ *
29138+ * This program is distributed in the hope that it will be useful,
29139+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29140+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29141+ * GNU General Public License for more details.
29142+ *
29143+ * You should have received a copy of the GNU General Public License
523b37e3 29144+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 29145+ */
29146+
29147+/*
29148+ * superblock private data
29149+ */
29150+
eca801bf 29151+#include <linux/iversion.h>
1facf9fc 29152+#include "aufs.h"
29153+
29154+/*
29155+ * they are necessary regardless sysfs is disabled.
29156+ */
29157+void au_si_free(struct kobject *kobj)
29158+{
86dc4139 29159+ int i;
1facf9fc 29160+ struct au_sbinfo *sbinfo;
b752ccd1 29161+ char *locked __maybe_unused; /* debug only */
1facf9fc 29162+
29163+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
86dc4139 29164+ for (i = 0; i < AuPlink_NHASH; i++)
8b6a4947 29165+ AuDebugOn(!hlist_bl_empty(sbinfo->si_plink + i));
f0c0a007 29166+ AuDebugOn(atomic_read(&sbinfo->si_nowait.nw_len));
5afbbe0d 29167+
acd2b654
AM
29168+ AuLCntZero(au_lcnt_read(&sbinfo->si_ninodes, /*do_rev*/0));
29169+ au_lcnt_fin(&sbinfo->si_ninodes, /*do_sync*/0);
29170+ AuLCntZero(au_lcnt_read(&sbinfo->si_nfiles, /*do_rev*/0));
29171+ au_lcnt_fin(&sbinfo->si_nfiles, /*do_sync*/0);
1facf9fc 29172+
062440b3 29173+ dbgaufs_si_fin(sbinfo);
e49829fe 29174+ au_rw_write_lock(&sbinfo->si_rwsem);
1facf9fc 29175+ au_br_free(sbinfo);
e49829fe 29176+ au_rw_write_unlock(&sbinfo->si_rwsem);
b752ccd1 29177+
9f237c51 29178+ au_kfree_try_rcu(sbinfo->si_branch);
1facf9fc 29179+ mutex_destroy(&sbinfo->si_xib_mtx);
dece6358 29180+ AuRwDestroy(&sbinfo->si_rwsem);
1facf9fc 29181+
acd2b654
AM
29182+ au_lcnt_wait_for_fin(&sbinfo->si_ninodes);
29183+ /* si_nfiles is waited too */
9f237c51 29184+ au_kfree_rcu(sbinfo);
1facf9fc 29185+}
29186+
29187+int au_si_alloc(struct super_block *sb)
29188+{
86dc4139 29189+ int err, i;
1facf9fc 29190+ struct au_sbinfo *sbinfo;
29191+
29192+ err = -ENOMEM;
4a4d8108 29193+ sbinfo = kzalloc(sizeof(*sbinfo), GFP_NOFS);
1facf9fc 29194+ if (unlikely(!sbinfo))
29195+ goto out;
29196+
29197+ /* will be reallocated separately */
29198+ sbinfo->si_branch = kzalloc(sizeof(*sbinfo->si_branch), GFP_NOFS);
29199+ if (unlikely(!sbinfo->si_branch))
febd17d6 29200+ goto out_sbinfo;
1facf9fc 29201+
1facf9fc 29202+ err = sysaufs_si_init(sbinfo);
062440b3
AM
29203+ if (!err) {
29204+ dbgaufs_si_null(sbinfo);
29205+ err = dbgaufs_si_init(sbinfo);
29206+ if (unlikely(err))
29207+ kobject_put(&sbinfo->si_kobj);
29208+ }
1facf9fc 29209+ if (unlikely(err))
29210+ goto out_br;
29211+
29212+ au_nwt_init(&sbinfo->si_nowait);
dece6358 29213+ au_rw_init_wlock(&sbinfo->si_rwsem);
b752ccd1 29214+
acd2b654
AM
29215+ au_lcnt_init(&sbinfo->si_ninodes, /*release*/NULL);
29216+ au_lcnt_init(&sbinfo->si_nfiles, /*release*/NULL);
7f207e10 29217+
5afbbe0d 29218+ sbinfo->si_bbot = -1;
392086de 29219+ sbinfo->si_last_br_id = AUFS_BRANCH_MAX / 2;
1facf9fc 29220+
29221+ sbinfo->si_wbr_copyup = AuWbrCopyup_Def;
29222+ sbinfo->si_wbr_create = AuWbrCreate_Def;
4a4d8108
AM
29223+ sbinfo->si_wbr_copyup_ops = au_wbr_copyup_ops + sbinfo->si_wbr_copyup;
29224+ sbinfo->si_wbr_create_ops = au_wbr_create_ops + sbinfo->si_wbr_create;
1facf9fc 29225+
076b876e
AM
29226+ au_fhsm_init(sbinfo);
29227+
e49829fe 29228+ sbinfo->si_mntflags = au_opts_plink(AuOpt_Def);
1facf9fc 29229+
392086de
AM
29230+ sbinfo->si_xino_jiffy = jiffies;
29231+ sbinfo->si_xino_expire
29232+ = msecs_to_jiffies(AUFS_XINO_DEF_SEC * MSEC_PER_SEC);
1facf9fc 29233+ mutex_init(&sbinfo->si_xib_mtx);
1facf9fc 29234+ /* leave si_xib_last_pindex and si_xib_next_bit */
29235+
8b6a4947 29236+ INIT_HLIST_BL_HEAD(&sbinfo->si_aopen);
b912730e 29237+
e49829fe 29238+ sbinfo->si_rdcache = msecs_to_jiffies(AUFS_RDCACHE_DEF * MSEC_PER_SEC);
1facf9fc 29239+ sbinfo->si_rdblk = AUFS_RDBLK_DEF;
29240+ sbinfo->si_rdhash = AUFS_RDHASH_DEF;
29241+ sbinfo->si_dirwh = AUFS_DIRWH_DEF;
29242+
86dc4139 29243+ for (i = 0; i < AuPlink_NHASH; i++)
8b6a4947 29244+ INIT_HLIST_BL_HEAD(sbinfo->si_plink + i);
1facf9fc 29245+ init_waitqueue_head(&sbinfo->si_plink_wq);
4a4d8108 29246+ spin_lock_init(&sbinfo->si_plink_maint_lock);
1facf9fc 29247+
8b6a4947 29248+ INIT_HLIST_BL_HEAD(&sbinfo->si_files);
523b37e3 29249+
b95c5147
AM
29250+ /* with getattr by default */
29251+ sbinfo->si_iop_array = aufs_iop;
29252+
1facf9fc 29253+ /* leave other members for sysaufs and si_mnt. */
29254+ sbinfo->si_sb = sb;
29255+ sb->s_fs_info = sbinfo;
b752ccd1 29256+ si_pid_set(sb);
1facf9fc 29257+ return 0; /* success */
29258+
4f0767ce 29259+out_br:
9f237c51 29260+ au_kfree_try_rcu(sbinfo->si_branch);
4f0767ce 29261+out_sbinfo:
9f237c51 29262+ au_kfree_rcu(sbinfo);
4f0767ce 29263+out:
1facf9fc 29264+ return err;
29265+}
29266+
e2f27e51 29267+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink)
1facf9fc 29268+{
29269+ int err, sz;
29270+ struct au_branch **brp;
29271+
dece6358
AM
29272+ AuRwMustWriteLock(&sbinfo->si_rwsem);
29273+
1facf9fc 29274+ err = -ENOMEM;
5afbbe0d 29275+ sz = sizeof(*brp) * (sbinfo->si_bbot + 1);
1facf9fc 29276+ if (unlikely(!sz))
29277+ sz = sizeof(*brp);
e2f27e51
AM
29278+ brp = au_kzrealloc(sbinfo->si_branch, sz, sizeof(*brp) * nbr, GFP_NOFS,
29279+ may_shrink);
1facf9fc 29280+ if (brp) {
29281+ sbinfo->si_branch = brp;
29282+ err = 0;
29283+ }
29284+
29285+ return err;
29286+}
29287+
29288+/* ---------------------------------------------------------------------- */
29289+
29290+unsigned int au_sigen_inc(struct super_block *sb)
29291+{
29292+ unsigned int gen;
5527c038 29293+ struct inode *inode;
1facf9fc 29294+
dece6358
AM
29295+ SiMustWriteLock(sb);
29296+
1facf9fc 29297+ gen = ++au_sbi(sb)->si_generation;
29298+ au_update_digen(sb->s_root);
5527c038
JR
29299+ inode = d_inode(sb->s_root);
29300+ au_update_iigen(inode, /*half*/0);
be118d29 29301+ inode_inc_iversion(inode);
1facf9fc 29302+ return gen;
29303+}
29304+
29305+aufs_bindex_t au_new_br_id(struct super_block *sb)
29306+{
29307+ aufs_bindex_t br_id;
29308+ int i;
29309+ struct au_sbinfo *sbinfo;
29310+
dece6358
AM
29311+ SiMustWriteLock(sb);
29312+
1facf9fc 29313+ sbinfo = au_sbi(sb);
29314+ for (i = 0; i <= AUFS_BRANCH_MAX; i++) {
29315+ br_id = ++sbinfo->si_last_br_id;
7f207e10 29316+ AuDebugOn(br_id < 0);
1facf9fc 29317+ if (br_id && au_br_index(sb, br_id) < 0)
29318+ return br_id;
29319+ }
29320+
29321+ return -1;
29322+}
29323+
29324+/* ---------------------------------------------------------------------- */
29325+
e49829fe
JR
29326+/* it is ok that new 'nwt' tasks are appended while we are sleeping */
29327+int si_read_lock(struct super_block *sb, int flags)
29328+{
29329+ int err;
29330+
29331+ err = 0;
29332+ if (au_ftest_lock(flags, FLUSH))
29333+ au_nwt_flush(&au_sbi(sb)->si_nowait);
29334+
29335+ si_noflush_read_lock(sb);
29336+ err = au_plink_maint(sb, flags);
29337+ if (unlikely(err))
29338+ si_read_unlock(sb);
29339+
29340+ return err;
29341+}
29342+
29343+int si_write_lock(struct super_block *sb, int flags)
29344+{
29345+ int err;
29346+
29347+ if (au_ftest_lock(flags, FLUSH))
29348+ au_nwt_flush(&au_sbi(sb)->si_nowait);
29349+
29350+ si_noflush_write_lock(sb);
29351+ err = au_plink_maint(sb, flags);
29352+ if (unlikely(err))
29353+ si_write_unlock(sb);
29354+
29355+ return err;
29356+}
29357+
1facf9fc 29358+/* dentry and super_block lock. call at entry point */
e49829fe 29359+int aufs_read_lock(struct dentry *dentry, int flags)
1facf9fc 29360+{
e49829fe 29361+ int err;
027c5e7a 29362+ struct super_block *sb;
e49829fe 29363+
027c5e7a
AM
29364+ sb = dentry->d_sb;
29365+ err = si_read_lock(sb, flags);
29366+ if (unlikely(err))
29367+ goto out;
29368+
29369+ if (au_ftest_lock(flags, DW))
29370+ di_write_lock_child(dentry);
29371+ else
29372+ di_read_lock_child(dentry, flags);
29373+
29374+ if (au_ftest_lock(flags, GEN)) {
29375+ err = au_digen_test(dentry, au_sigen(sb));
79b8bda9
AM
29376+ if (!au_opt_test(au_mntflags(sb), UDBA_NONE))
29377+ AuDebugOn(!err && au_dbrange_test(dentry));
29378+ else if (!err)
29379+ err = au_dbrange_test(dentry);
027c5e7a
AM
29380+ if (unlikely(err))
29381+ aufs_read_unlock(dentry, flags);
e49829fe
JR
29382+ }
29383+
027c5e7a 29384+out:
e49829fe 29385+ return err;
1facf9fc 29386+}
29387+
29388+void aufs_read_unlock(struct dentry *dentry, int flags)
29389+{
29390+ if (au_ftest_lock(flags, DW))
29391+ di_write_unlock(dentry);
29392+ else
29393+ di_read_unlock(dentry, flags);
29394+ si_read_unlock(dentry->d_sb);
29395+}
29396+
29397+void aufs_write_lock(struct dentry *dentry)
29398+{
e49829fe 29399+ si_write_lock(dentry->d_sb, AuLock_FLUSH | AuLock_NOPLMW);
1facf9fc 29400+ di_write_lock_child(dentry);
29401+}
29402+
29403+void aufs_write_unlock(struct dentry *dentry)
29404+{
29405+ di_write_unlock(dentry);
29406+ si_write_unlock(dentry->d_sb);
29407+}
29408+
e49829fe 29409+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags)
1facf9fc 29410+{
e49829fe 29411+ int err;
027c5e7a
AM
29412+ unsigned int sigen;
29413+ struct super_block *sb;
e49829fe 29414+
027c5e7a
AM
29415+ sb = d1->d_sb;
29416+ err = si_read_lock(sb, flags);
29417+ if (unlikely(err))
29418+ goto out;
29419+
b95c5147 29420+ di_write_lock2_child(d1, d2, au_ftest_lock(flags, DIRS));
027c5e7a
AM
29421+
29422+ if (au_ftest_lock(flags, GEN)) {
29423+ sigen = au_sigen(sb);
29424+ err = au_digen_test(d1, sigen);
29425+ AuDebugOn(!err && au_dbrange_test(d1));
29426+ if (!err) {
29427+ err = au_digen_test(d2, sigen);
29428+ AuDebugOn(!err && au_dbrange_test(d2));
29429+ }
29430+ if (unlikely(err))
29431+ aufs_read_and_write_unlock2(d1, d2);
29432+ }
29433+
29434+out:
e49829fe 29435+ return err;
1facf9fc 29436+}
29437+
29438+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2)
29439+{
29440+ di_write_unlock2(d1, d2);
29441+ si_read_unlock(d1->d_sb);
29442+}
7f207e10 29443diff -urN /usr/share/empty/fs/aufs/super.c linux/fs/aufs/super.c
eca34b5c 29444--- /usr/share/empty/fs/aufs/super.c 1970-01-01 01:00:00.000000000 +0100
016522bc 29445+++ linux/fs/aufs/super.c 2020-01-27 10:57:18.178871751 +0100
fbc438ed 29446@@ -0,0 +1,1047 @@
cd7a4cd9 29447+// SPDX-License-Identifier: GPL-2.0
1facf9fc 29448+/*
016522bc 29449+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 29450+ *
29451+ * This program, aufs is free software; you can redistribute it and/or modify
29452+ * it under the terms of the GNU General Public License as published by
29453+ * the Free Software Foundation; either version 2 of the License, or
29454+ * (at your option) any later version.
dece6358
AM
29455+ *
29456+ * This program is distributed in the hope that it will be useful,
29457+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
29458+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29459+ * GNU General Public License for more details.
29460+ *
29461+ * You should have received a copy of the GNU General Public License
523b37e3 29462+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 29463+ */
29464+
29465+/*
29466+ * mount and super_block operations
29467+ */
29468+
eca801bf 29469+#include <linux/iversion.h>
f6c5ef8b 29470+#include <linux/mm.h>
1facf9fc 29471+#include <linux/seq_file.h>
29472+#include <linux/statfs.h>
7f207e10 29473+#include <linux/vmalloc.h>
1facf9fc 29474+#include "aufs.h"
29475+
29476+/*
29477+ * super_operations
29478+ */
29479+static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused)
29480+{
29481+ struct au_icntnr *c;
29482+
29483+ c = au_cache_alloc_icntnr();
29484+ if (c) {
027c5e7a 29485+ au_icntnr_init(c);
be118d29 29486+ inode_set_iversion(&c->vfs_inode, 1); /* sigen(sb); */
1facf9fc 29487+ c->iinfo.ii_hinode = NULL;
29488+ return &c->vfs_inode;
29489+ }
29490+ return NULL;
29491+}
29492+
29493+static void aufs_destroy_inode(struct inode *inode)
29494+{
5afbbe0d
AM
29495+ if (!au_is_bad_inode(inode))
29496+ au_iinfo_fin(inode);
fbc438ed
JR
29497+}
29498+
29499+static void aufs_free_inode(struct inode *inode)
29500+{
29501+ au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode));
1facf9fc 29502+}
29503+
29504+struct inode *au_iget_locked(struct super_block *sb, ino_t ino)
29505+{
29506+ struct inode *inode;
29507+ int err;
29508+
29509+ inode = iget_locked(sb, ino);
29510+ if (unlikely(!inode)) {
29511+ inode = ERR_PTR(-ENOMEM);
29512+ goto out;
29513+ }
29514+ if (!(inode->i_state & I_NEW))
29515+ goto out;
29516+
29517+ err = au_xigen_new(inode);
29518+ if (!err)
29519+ err = au_iinfo_init(inode);
29520+ if (!err)
be118d29 29521+ inode_inc_iversion(inode);
1facf9fc 29522+ else {
29523+ iget_failed(inode);
29524+ inode = ERR_PTR(err);
29525+ }
29526+
4f0767ce 29527+out:
1facf9fc 29528+ /* never return NULL */
29529+ AuDebugOn(!inode);
29530+ AuTraceErrPtr(inode);
29531+ return inode;
29532+}
29533+
29534+/* lock free root dinfo */
29535+static int au_show_brs(struct seq_file *seq, struct super_block *sb)
29536+{
29537+ int err;
5afbbe0d 29538+ aufs_bindex_t bindex, bbot;
1facf9fc 29539+ struct path path;
4a4d8108 29540+ struct au_hdentry *hdp;
1facf9fc 29541+ struct au_branch *br;
076b876e 29542+ au_br_perm_str_t perm;
1facf9fc 29543+
29544+ err = 0;
5afbbe0d
AM
29545+ bbot = au_sbbot(sb);
29546+ bindex = 0;
29547+ hdp = au_hdentry(au_di(sb->s_root), bindex);
29548+ for (; !err && bindex <= bbot; bindex++, hdp++) {
1facf9fc 29549+ br = au_sbr(sb, bindex);
86dc4139 29550+ path.mnt = au_br_mnt(br);
5afbbe0d 29551+ path.dentry = hdp->hd_dentry;
1facf9fc 29552+ err = au_seq_path(seq, &path);
79b8bda9 29553+ if (!err) {
076b876e 29554+ au_optstr_br_perm(&perm, br->br_perm);
79b8bda9 29555+ seq_printf(seq, "=%s", perm.a);
5afbbe0d 29556+ if (bindex != bbot)
79b8bda9 29557+ seq_putc(seq, ':');
1e00d052 29558+ }
1facf9fc 29559+ }
79b8bda9
AM
29560+ if (unlikely(err || seq_has_overflowed(seq)))
29561+ err = -E2BIG;
1facf9fc 29562+
29563+ return err;
29564+}
29565+
f2c43d5f
AM
29566+static void au_gen_fmt(char *fmt, int len __maybe_unused, const char *pat,
29567+ const char *append)
29568+{
29569+ char *p;
29570+
29571+ p = fmt;
29572+ while (*pat != ':')
29573+ *p++ = *pat++;
29574+ *p++ = *pat++;
29575+ strcpy(p, append);
29576+ AuDebugOn(strlen(fmt) >= len);
29577+}
29578+
1facf9fc 29579+static void au_show_wbr_create(struct seq_file *m, int v,
29580+ struct au_sbinfo *sbinfo)
29581+{
29582+ const char *pat;
f2c43d5f
AM
29583+ char fmt[32];
29584+ struct au_wbr_mfs *mfs;
1facf9fc 29585+
dece6358
AM
29586+ AuRwMustAnyLock(&sbinfo->si_rwsem);
29587+
c2b27bf2 29588+ seq_puts(m, ",create=");
1facf9fc 29589+ pat = au_optstr_wbr_create(v);
f2c43d5f 29590+ mfs = &sbinfo->si_wbr_mfs;
1facf9fc 29591+ switch (v) {
29592+ case AuWbrCreate_TDP:
29593+ case AuWbrCreate_RR:
29594+ case AuWbrCreate_MFS:
29595+ case AuWbrCreate_PMFS:
c2b27bf2 29596+ seq_puts(m, pat);
1facf9fc 29597+ break;
f2c43d5f
AM
29598+ case AuWbrCreate_MFSRR:
29599+ case AuWbrCreate_TDMFS:
29600+ case AuWbrCreate_PMFSRR:
29601+ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu");
29602+ seq_printf(m, fmt, mfs->mfsrr_watermark);
1facf9fc 29603+ break;
f2c43d5f 29604+ case AuWbrCreate_MFSV:
1facf9fc 29605+ case AuWbrCreate_PMFSV:
f2c43d5f
AM
29606+ au_gen_fmt(fmt, sizeof(fmt), pat, "%lu");
29607+ seq_printf(m, fmt,
29608+ jiffies_to_msecs(mfs->mfs_expire)
e49829fe 29609+ / MSEC_PER_SEC);
1facf9fc 29610+ break;
1facf9fc 29611+ case AuWbrCreate_MFSRRV:
f2c43d5f 29612+ case AuWbrCreate_TDMFSV:
392086de 29613+ case AuWbrCreate_PMFSRRV:
f2c43d5f
AM
29614+ au_gen_fmt(fmt, sizeof(fmt), pat, "%llu:%lu");
29615+ seq_printf(m, fmt, mfs->mfsrr_watermark,
29616+ jiffies_to_msecs(mfs->mfs_expire) / MSEC_PER_SEC);
392086de 29617+ break;
f2c43d5f
AM
29618+ default:
29619+ BUG();
1facf9fc 29620+ }
29621+}
29622+
7eafdf33 29623+static int au_show_xino(struct seq_file *seq, struct super_block *sb)
1facf9fc 29624+{
29625+#ifdef CONFIG_SYSFS
29626+ return 0;
29627+#else
29628+ int err;
29629+ const int len = sizeof(AUFS_XINO_FNAME) - 1;
29630+ aufs_bindex_t bindex, brid;
1facf9fc 29631+ struct qstr *name;
29632+ struct file *f;
29633+ struct dentry *d, *h_root;
acd2b654 29634+ struct au_branch *br;
1facf9fc 29635+
dece6358
AM
29636+ AuRwMustAnyLock(&sbinfo->si_rwsem);
29637+
1facf9fc 29638+ err = 0;
1facf9fc 29639+ f = au_sbi(sb)->si_xib;
29640+ if (!f)
29641+ goto out;
29642+
29643+ /* stop printing the default xino path on the first writable branch */
29644+ h_root = NULL;
acd2b654
AM
29645+ bindex = au_xi_root(sb, f->f_path.dentry);
29646+ if (bindex >= 0) {
29647+ br = au_sbr_sb(sb, bindex);
29648+ h_root = au_br_dentry(br);
1facf9fc 29649+ }
acd2b654 29650+
2000de60 29651+ d = f->f_path.dentry;
1facf9fc 29652+ name = &d->d_name;
29653+ /* safe ->d_parent because the file is unlinked */
29654+ if (d->d_parent == h_root
29655+ && name->len == len
29656+ && !memcmp(name->name, AUFS_XINO_FNAME, len))
29657+ goto out;
29658+
29659+ seq_puts(seq, ",xino=");
29660+ err = au_xino_path(seq, f);
29661+
4f0767ce 29662+out:
1facf9fc 29663+ return err;
29664+#endif
29665+}
29666+
29667+/* seq_file will re-call me in case of too long string */
7eafdf33 29668+static int aufs_show_options(struct seq_file *m, struct dentry *dentry)
1facf9fc 29669+{
027c5e7a 29670+ int err;
1facf9fc 29671+ unsigned int mnt_flags, v;
29672+ struct super_block *sb;
29673+ struct au_sbinfo *sbinfo;
29674+
29675+#define AuBool(name, str) do { \
29676+ v = au_opt_test(mnt_flags, name); \
29677+ if (v != au_opt_test(AuOpt_Def, name)) \
29678+ seq_printf(m, ",%s" #str, v ? "" : "no"); \
29679+} while (0)
29680+
29681+#define AuStr(name, str) do { \
29682+ v = mnt_flags & AuOptMask_##name; \
29683+ if (v != (AuOpt_Def & AuOptMask_##name)) \
29684+ seq_printf(m, "," #str "=%s", au_optstr_##str(v)); \
29685+} while (0)
29686+
29687+#define AuUInt(name, str, val) do { \
29688+ if (val != AUFS_##name##_DEF) \
29689+ seq_printf(m, "," #str "=%u", val); \
29690+} while (0)
29691+
7eafdf33 29692+ sb = dentry->d_sb;
2121bcd9 29693+ if (sb->s_flags & SB_POSIXACL)
c1595e42 29694+ seq_puts(m, ",acl");
43982f53 29695+#if 0 /* reserved for future use */
be118d29
JR
29696+ if (sb->s_flags & SB_I_VERSION)
29697+ seq_puts(m, ",i_version");
29698+#endif
c1595e42
JR
29699+
29700+ /* lock free root dinfo */
1facf9fc 29701+ si_noflush_read_lock(sb);
29702+ sbinfo = au_sbi(sb);
29703+ seq_printf(m, ",si=%lx", sysaufs_si_id(sbinfo));
29704+
29705+ mnt_flags = au_mntflags(sb);
29706+ if (au_opt_test(mnt_flags, XINO)) {
7eafdf33 29707+ err = au_show_xino(m, sb);
1facf9fc 29708+ if (unlikely(err))
29709+ goto out;
29710+ } else
29711+ seq_puts(m, ",noxino");
29712+
29713+ AuBool(TRUNC_XINO, trunc_xino);
29714+ AuStr(UDBA, udba);
dece6358 29715+ AuBool(SHWH, shwh);
1facf9fc 29716+ AuBool(PLINK, plink);
4a4d8108 29717+ AuBool(DIO, dio);
076b876e 29718+ AuBool(DIRPERM1, dirperm1);
1facf9fc 29719+
29720+ v = sbinfo->si_wbr_create;
29721+ if (v != AuWbrCreate_Def)
29722+ au_show_wbr_create(m, v, sbinfo);
29723+
29724+ v = sbinfo->si_wbr_copyup;
29725+ if (v != AuWbrCopyup_Def)
29726+ seq_printf(m, ",cpup=%s", au_optstr_wbr_copyup(v));
29727+
29728+ v = au_opt_test(mnt_flags, ALWAYS_DIROPQ);
29729+ if (v != au_opt_test(AuOpt_Def, ALWAYS_DIROPQ))
29730+ seq_printf(m, ",diropq=%c", v ? 'a' : 'w');
29731+
29732+ AuUInt(DIRWH, dirwh, sbinfo->si_dirwh);
29733+
027c5e7a
AM
29734+ v = jiffies_to_msecs(sbinfo->si_rdcache) / MSEC_PER_SEC;
29735+ AuUInt(RDCACHE, rdcache, v);
1facf9fc 29736+
29737+ AuUInt(RDBLK, rdblk, sbinfo->si_rdblk);
29738+ AuUInt(RDHASH, rdhash, sbinfo->si_rdhash);
29739+
076b876e
AM
29740+ au_fhsm_show(m, sbinfo);
29741+
8b6a4947 29742+ AuBool(DIRREN, dirren);
1facf9fc 29743+ AuBool(SUM, sum);
29744+ /* AuBool(SUM_W, wsum); */
29745+ AuBool(WARN_PERM, warn_perm);
29746+ AuBool(VERBOSE, verbose);
29747+
4f0767ce 29748+out:
1facf9fc 29749+ /* be sure to print "br:" last */
29750+ if (!sysaufs_brs) {
29751+ seq_puts(m, ",br:");
29752+ au_show_brs(m, sb);
29753+ }
29754+ si_read_unlock(sb);
29755+ return 0;
29756+
1facf9fc 29757+#undef AuBool
29758+#undef AuStr
4a4d8108 29759+#undef AuUInt
1facf9fc 29760+}
29761+
29762+/* ---------------------------------------------------------------------- */
29763+
29764+/* sum mode which returns the summation for statfs(2) */
29765+
29766+static u64 au_add_till_max(u64 a, u64 b)
29767+{
29768+ u64 old;
29769+
29770+ old = a;
29771+ a += b;
92d182d2
AM
29772+ if (old <= a)
29773+ return a;
29774+ return ULLONG_MAX;
29775+}
29776+
29777+static u64 au_mul_till_max(u64 a, long mul)
29778+{
29779+ u64 old;
29780+
29781+ old = a;
29782+ a *= mul;
29783+ if (old <= a)
1facf9fc 29784+ return a;
29785+ return ULLONG_MAX;
29786+}
29787+
29788+static int au_statfs_sum(struct super_block *sb, struct kstatfs *buf)
29789+{
29790+ int err;
92d182d2 29791+ long bsize, factor;
1facf9fc 29792+ u64 blocks, bfree, bavail, files, ffree;
5afbbe0d 29793+ aufs_bindex_t bbot, bindex, i;
1facf9fc 29794+ unsigned char shared;
7f207e10 29795+ struct path h_path;
1facf9fc 29796+ struct super_block *h_sb;
29797+
92d182d2
AM
29798+ err = 0;
29799+ bsize = LONG_MAX;
29800+ files = 0;
29801+ ffree = 0;
1facf9fc 29802+ blocks = 0;
29803+ bfree = 0;
29804+ bavail = 0;
5afbbe0d
AM
29805+ bbot = au_sbbot(sb);
29806+ for (bindex = 0; bindex <= bbot; bindex++) {
7f207e10
AM
29807+ h_path.mnt = au_sbr_mnt(sb, bindex);
29808+ h_sb = h_path.mnt->mnt_sb;
1facf9fc 29809+ shared = 0;
92d182d2 29810+ for (i = 0; !shared && i < bindex; i++)
1facf9fc 29811+ shared = (au_sbr_sb(sb, i) == h_sb);
29812+ if (shared)
29813+ continue;
29814+
29815+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
29816+ h_path.dentry = h_path.mnt->mnt_root;
29817+ err = vfs_statfs(&h_path, buf);
1facf9fc 29818+ if (unlikely(err))
29819+ goto out;
29820+
92d182d2
AM
29821+ if (bsize > buf->f_bsize) {
29822+ /*
29823+ * we will reduce bsize, so we have to expand blocks
29824+ * etc. to match them again
29825+ */
29826+ factor = (bsize / buf->f_bsize);
29827+ blocks = au_mul_till_max(blocks, factor);
29828+ bfree = au_mul_till_max(bfree, factor);
29829+ bavail = au_mul_till_max(bavail, factor);
29830+ bsize = buf->f_bsize;
29831+ }
29832+
29833+ factor = (buf->f_bsize / bsize);
29834+ blocks = au_add_till_max(blocks,
29835+ au_mul_till_max(buf->f_blocks, factor));
29836+ bfree = au_add_till_max(bfree,
29837+ au_mul_till_max(buf->f_bfree, factor));
29838+ bavail = au_add_till_max(bavail,
29839+ au_mul_till_max(buf->f_bavail, factor));
1facf9fc 29840+ files = au_add_till_max(files, buf->f_files);
29841+ ffree = au_add_till_max(ffree, buf->f_ffree);
29842+ }
29843+
92d182d2 29844+ buf->f_bsize = bsize;
1facf9fc 29845+ buf->f_blocks = blocks;
29846+ buf->f_bfree = bfree;
29847+ buf->f_bavail = bavail;
29848+ buf->f_files = files;
29849+ buf->f_ffree = ffree;
92d182d2 29850+ buf->f_frsize = 0;
1facf9fc 29851+
4f0767ce 29852+out:
1facf9fc 29853+ return err;
29854+}
29855+
29856+static int aufs_statfs(struct dentry *dentry, struct kstatfs *buf)
29857+{
29858+ int err;
7f207e10 29859+ struct path h_path;
1facf9fc 29860+ struct super_block *sb;
29861+
29862+ /* lock free root dinfo */
29863+ sb = dentry->d_sb;
29864+ si_noflush_read_lock(sb);
7f207e10 29865+ if (!au_opt_test(au_mntflags(sb), SUM)) {
1facf9fc 29866+ /* sb->s_root for NFS is unreliable */
7f207e10
AM
29867+ h_path.mnt = au_sbr_mnt(sb, 0);
29868+ h_path.dentry = h_path.mnt->mnt_root;
29869+ err = vfs_statfs(&h_path, buf);
29870+ } else
1facf9fc 29871+ err = au_statfs_sum(sb, buf);
29872+ si_read_unlock(sb);
29873+
29874+ if (!err) {
29875+ buf->f_type = AUFS_SUPER_MAGIC;
4a4d8108 29876+ buf->f_namelen = AUFS_MAX_NAMELEN;
1facf9fc 29877+ memset(&buf->f_fsid, 0, sizeof(buf->f_fsid));
29878+ }
29879+ /* buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; */
29880+
29881+ return err;
29882+}
29883+
29884+/* ---------------------------------------------------------------------- */
29885+
537831f9
AM
29886+static int aufs_sync_fs(struct super_block *sb, int wait)
29887+{
29888+ int err, e;
5afbbe0d 29889+ aufs_bindex_t bbot, bindex;
537831f9
AM
29890+ struct au_branch *br;
29891+ struct super_block *h_sb;
29892+
29893+ err = 0;
29894+ si_noflush_read_lock(sb);
5afbbe0d
AM
29895+ bbot = au_sbbot(sb);
29896+ for (bindex = 0; bindex <= bbot; bindex++) {
537831f9
AM
29897+ br = au_sbr(sb, bindex);
29898+ if (!au_br_writable(br->br_perm))
29899+ continue;
29900+
29901+ h_sb = au_sbr_sb(sb, bindex);
a2654f78
AM
29902+ e = vfsub_sync_filesystem(h_sb, wait);
29903+ if (unlikely(e && !err))
29904+ err = e;
29905+ /* go on even if an error happens */
537831f9
AM
29906+ }
29907+ si_read_unlock(sb);
29908+
29909+ return err;
29910+}
29911+
29912+/* ---------------------------------------------------------------------- */
29913+
1facf9fc 29914+/* final actions when unmounting a file system */
29915+static void aufs_put_super(struct super_block *sb)
29916+{
29917+ struct au_sbinfo *sbinfo;
29918+
29919+ sbinfo = au_sbi(sb);
062440b3
AM
29920+ if (sbinfo)
29921+ kobject_put(&sbinfo->si_kobj);
1facf9fc 29922+}
29923+
29924+/* ---------------------------------------------------------------------- */
29925+
79b8bda9
AM
29926+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb,
29927+ struct super_block *sb, void *arg)
7f207e10
AM
29928+{
29929+ void *array;
076b876e 29930+ unsigned long long n, sz;
7f207e10
AM
29931+
29932+ array = NULL;
29933+ n = 0;
29934+ if (!*hint)
29935+ goto out;
29936+
29937+ if (*hint > ULLONG_MAX / sizeof(array)) {
29938+ array = ERR_PTR(-EMFILE);
29939+ pr_err("hint %llu\n", *hint);
29940+ goto out;
29941+ }
29942+
076b876e
AM
29943+ sz = sizeof(array) * *hint;
29944+ array = kzalloc(sz, GFP_NOFS);
7f207e10 29945+ if (unlikely(!array))
076b876e 29946+ array = vzalloc(sz);
7f207e10
AM
29947+ if (unlikely(!array)) {
29948+ array = ERR_PTR(-ENOMEM);
29949+ goto out;
29950+ }
29951+
79b8bda9 29952+ n = cb(sb, array, *hint, arg);
7f207e10
AM
29953+ AuDebugOn(n > *hint);
29954+
29955+out:
29956+ *hint = n;
29957+ return array;
29958+}
29959+
79b8bda9 29960+static unsigned long long au_iarray_cb(struct super_block *sb, void *a,
7f207e10
AM
29961+ unsigned long long max __maybe_unused,
29962+ void *arg)
29963+{
29964+ unsigned long long n;
29965+ struct inode **p, *inode;
29966+ struct list_head *head;
29967+
29968+ n = 0;
29969+ p = a;
29970+ head = arg;
79b8bda9 29971+ spin_lock(&sb->s_inode_list_lock);
7f207e10 29972+ list_for_each_entry(inode, head, i_sb_list) {
5afbbe0d
AM
29973+ if (!au_is_bad_inode(inode)
29974+ && au_ii(inode)->ii_btop >= 0) {
2cbb1c4b
JR
29975+ spin_lock(&inode->i_lock);
29976+ if (atomic_read(&inode->i_count)) {
29977+ au_igrab(inode);
29978+ *p++ = inode;
29979+ n++;
29980+ AuDebugOn(n > max);
29981+ }
29982+ spin_unlock(&inode->i_lock);
7f207e10
AM
29983+ }
29984+ }
79b8bda9 29985+ spin_unlock(&sb->s_inode_list_lock);
7f207e10
AM
29986+
29987+ return n;
29988+}
29989+
29990+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max)
29991+{
acd2b654
AM
29992+ struct au_sbinfo *sbi;
29993+
29994+ sbi = au_sbi(sb);
29995+ *max = au_lcnt_read(&sbi->si_ninodes, /*do_rev*/1);
79b8bda9 29996+ return au_array_alloc(max, au_iarray_cb, sb, &sb->s_inodes);
7f207e10
AM
29997+}
29998+
29999+void au_iarray_free(struct inode **a, unsigned long long max)
30000+{
30001+ unsigned long long ull;
30002+
30003+ for (ull = 0; ull < max; ull++)
30004+ iput(a[ull]);
be52b249 30005+ kvfree(a);
7f207e10
AM
30006+}
30007+
30008+/* ---------------------------------------------------------------------- */
30009+
1facf9fc 30010+/*
30011+ * refresh dentry and inode at remount time.
30012+ */
027c5e7a
AM
30013+/* todo: consolidate with simple_reval_dpath() and au_reval_for_attr() */
30014+static int au_do_refresh(struct dentry *dentry, unsigned int dir_flags,
30015+ struct dentry *parent)
1facf9fc 30016+{
30017+ int err;
1facf9fc 30018+
30019+ di_write_lock_child(dentry);
1facf9fc 30020+ di_read_lock_parent(parent, AuLock_IR);
027c5e7a
AM
30021+ err = au_refresh_dentry(dentry, parent);
30022+ if (!err && dir_flags)
5527c038 30023+ au_hn_reset(d_inode(dentry), dir_flags);
1facf9fc 30024+ di_read_unlock(parent, AuLock_IR);
1facf9fc 30025+ di_write_unlock(dentry);
30026+
30027+ return err;
30028+}
30029+
027c5e7a
AM
30030+static int au_do_refresh_d(struct dentry *dentry, unsigned int sigen,
30031+ struct au_sbinfo *sbinfo,
b95c5147 30032+ const unsigned int dir_flags, unsigned int do_idop)
1facf9fc 30033+{
027c5e7a
AM
30034+ int err;
30035+ struct dentry *parent;
027c5e7a
AM
30036+
30037+ err = 0;
30038+ parent = dget_parent(dentry);
30039+ if (!au_digen_test(parent, sigen) && au_digen_test(dentry, sigen)) {
5527c038
JR
30040+ if (d_really_is_positive(dentry)) {
30041+ if (!d_is_dir(dentry))
027c5e7a
AM
30042+ err = au_do_refresh(dentry, /*dir_flags*/0,
30043+ parent);
30044+ else {
30045+ err = au_do_refresh(dentry, dir_flags, parent);
30046+ if (unlikely(err))
30047+ au_fset_si(sbinfo, FAILED_REFRESH_DIR);
30048+ }
30049+ } else
30050+ err = au_do_refresh(dentry, /*dir_flags*/0, parent);
30051+ AuDbgDentry(dentry);
30052+ }
30053+ dput(parent);
30054+
79b8bda9 30055+ if (!err) {
b95c5147 30056+ if (do_idop)
79b8bda9
AM
30057+ au_refresh_dop(dentry, /*force_reval*/0);
30058+ } else
30059+ au_refresh_dop(dentry, /*force_reval*/1);
30060+
027c5e7a
AM
30061+ AuTraceErr(err);
30062+ return err;
1facf9fc 30063+}
30064+
b95c5147 30065+static int au_refresh_d(struct super_block *sb, unsigned int do_idop)
1facf9fc 30066+{
30067+ int err, i, j, ndentry, e;
027c5e7a 30068+ unsigned int sigen;
1facf9fc 30069+ struct au_dcsub_pages dpages;
30070+ struct au_dpage *dpage;
027c5e7a
AM
30071+ struct dentry **dentries, *d;
30072+ struct au_sbinfo *sbinfo;
30073+ struct dentry *root = sb->s_root;
5527c038 30074+ const unsigned int dir_flags = au_hi_flags(d_inode(root), /*isdir*/1);
1facf9fc 30075+
b95c5147 30076+ if (do_idop)
79b8bda9
AM
30077+ au_refresh_dop(root, /*force_reval*/0);
30078+
027c5e7a
AM
30079+ err = au_dpages_init(&dpages, GFP_NOFS);
30080+ if (unlikely(err))
1facf9fc 30081+ goto out;
027c5e7a
AM
30082+ err = au_dcsub_pages(&dpages, root, NULL, NULL);
30083+ if (unlikely(err))
1facf9fc 30084+ goto out_dpages;
1facf9fc 30085+
027c5e7a
AM
30086+ sigen = au_sigen(sb);
30087+ sbinfo = au_sbi(sb);
30088+ for (i = 0; i < dpages.ndpage; i++) {
1facf9fc 30089+ dpage = dpages.dpages + i;
30090+ dentries = dpage->dentries;
30091+ ndentry = dpage->ndentry;
027c5e7a 30092+ for (j = 0; j < ndentry; j++) {
1facf9fc 30093+ d = dentries[j];
79b8bda9 30094+ e = au_do_refresh_d(d, sigen, sbinfo, dir_flags,
b95c5147 30095+ do_idop);
027c5e7a
AM
30096+ if (unlikely(e && !err))
30097+ err = e;
30098+ /* go on even err */
1facf9fc 30099+ }
30100+ }
30101+
4f0767ce 30102+out_dpages:
1facf9fc 30103+ au_dpages_free(&dpages);
4f0767ce 30104+out:
1facf9fc 30105+ return err;
30106+}
30107+
b95c5147 30108+static int au_refresh_i(struct super_block *sb, unsigned int do_idop)
1facf9fc 30109+{
027c5e7a
AM
30110+ int err, e;
30111+ unsigned int sigen;
30112+ unsigned long long max, ull;
30113+ struct inode *inode, **array;
1facf9fc 30114+
027c5e7a
AM
30115+ array = au_iarray_alloc(sb, &max);
30116+ err = PTR_ERR(array);
30117+ if (IS_ERR(array))
30118+ goto out;
1facf9fc 30119+
30120+ err = 0;
027c5e7a
AM
30121+ sigen = au_sigen(sb);
30122+ for (ull = 0; ull < max; ull++) {
30123+ inode = array[ull];
076b876e
AM
30124+ if (unlikely(!inode))
30125+ break;
b95c5147
AM
30126+
30127+ e = 0;
30128+ ii_write_lock_child(inode);
537831f9 30129+ if (au_iigen(inode, NULL) != sigen) {
027c5e7a 30130+ e = au_refresh_hinode_self(inode);
1facf9fc 30131+ if (unlikely(e)) {
b95c5147 30132+ au_refresh_iop(inode, /*force_getattr*/1);
027c5e7a 30133+ pr_err("error %d, i%lu\n", e, inode->i_ino);
1facf9fc 30134+ if (!err)
30135+ err = e;
30136+ /* go on even if err */
30137+ }
30138+ }
b95c5147
AM
30139+ if (!e && do_idop)
30140+ au_refresh_iop(inode, /*force_getattr*/0);
30141+ ii_write_unlock(inode);
1facf9fc 30142+ }
30143+
027c5e7a 30144+ au_iarray_free(array, max);
1facf9fc 30145+
4f0767ce 30146+out:
1facf9fc 30147+ return err;
30148+}
30149+
b95c5147 30150+static void au_remount_refresh(struct super_block *sb, unsigned int do_idop)
1facf9fc 30151+{
027c5e7a
AM
30152+ int err, e;
30153+ unsigned int udba;
5afbbe0d 30154+ aufs_bindex_t bindex, bbot;
1facf9fc 30155+ struct dentry *root;
30156+ struct inode *inode;
027c5e7a 30157+ struct au_branch *br;
79b8bda9 30158+ struct au_sbinfo *sbi;
1facf9fc 30159+
30160+ au_sigen_inc(sb);
79b8bda9
AM
30161+ sbi = au_sbi(sb);
30162+ au_fclr_si(sbi, FAILED_REFRESH_DIR);
1facf9fc 30163+
30164+ root = sb->s_root;
30165+ DiMustNoWaiters(root);
5527c038 30166+ inode = d_inode(root);
1facf9fc 30167+ IiMustNoWaiters(inode);
1facf9fc 30168+
027c5e7a 30169+ udba = au_opt_udba(sb);
5afbbe0d
AM
30170+ bbot = au_sbbot(sb);
30171+ for (bindex = 0; bindex <= bbot; bindex++) {
027c5e7a
AM
30172+ br = au_sbr(sb, bindex);
30173+ err = au_hnotify_reset_br(udba, br, br->br_perm);
1facf9fc 30174+ if (unlikely(err))
027c5e7a
AM
30175+ AuIOErr("hnotify failed on br %d, %d, ignored\n",
30176+ bindex, err);
30177+ /* go on even if err */
1facf9fc 30178+ }
027c5e7a 30179+ au_hn_reset(inode, au_hi_flags(inode, /*isdir*/1));
1facf9fc 30180+
b95c5147 30181+ if (do_idop) {
79b8bda9
AM
30182+ if (au_ftest_si(sbi, NO_DREVAL)) {
30183+ AuDebugOn(sb->s_d_op == &aufs_dop_noreval);
30184+ sb->s_d_op = &aufs_dop_noreval;
b95c5147
AM
30185+ AuDebugOn(sbi->si_iop_array == aufs_iop_nogetattr);
30186+ sbi->si_iop_array = aufs_iop_nogetattr;
79b8bda9
AM
30187+ } else {
30188+ AuDebugOn(sb->s_d_op == &aufs_dop);
30189+ sb->s_d_op = &aufs_dop;
b95c5147
AM
30190+ AuDebugOn(sbi->si_iop_array == aufs_iop);
30191+ sbi->si_iop_array = aufs_iop;
79b8bda9 30192+ }
062440b3 30193+ pr_info("reset to %ps and %ps\n",
b95c5147 30194+ sb->s_d_op, sbi->si_iop_array);
79b8bda9
AM
30195+ }
30196+
027c5e7a 30197+ di_write_unlock(root);
b95c5147
AM
30198+ err = au_refresh_d(sb, do_idop);
30199+ e = au_refresh_i(sb, do_idop);
027c5e7a
AM
30200+ if (unlikely(e && !err))
30201+ err = e;
1facf9fc 30202+ /* aufs_write_lock() calls ..._child() */
30203+ di_write_lock_child(root);
027c5e7a
AM
30204+
30205+ au_cpup_attr_all(inode, /*force*/1);
30206+
30207+ if (unlikely(err))
30208+ AuIOErr("refresh failed, ignored, %d\n", err);
1facf9fc 30209+}
30210+
30211+/* stop extra interpretation of errno in mount(8), and strange error messages */
30212+static int cvt_err(int err)
30213+{
30214+ AuTraceErr(err);
30215+
30216+ switch (err) {
30217+ case -ENOENT:
30218+ case -ENOTDIR:
30219+ case -EEXIST:
30220+ case -EIO:
30221+ err = -EINVAL;
30222+ }
30223+ return err;
30224+}
30225+
30226+static int aufs_remount_fs(struct super_block *sb, int *flags, char *data)
30227+{
4a4d8108
AM
30228+ int err, do_dx;
30229+ unsigned int mntflags;
be52b249
AM
30230+ struct au_opts opts = {
30231+ .opt = NULL
30232+ };
1facf9fc 30233+ struct dentry *root;
30234+ struct inode *inode;
30235+ struct au_sbinfo *sbinfo;
30236+
30237+ err = 0;
30238+ root = sb->s_root;
30239+ if (!data || !*data) {
e49829fe
JR
30240+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
30241+ if (!err) {
30242+ di_write_lock_child(root);
30243+ err = au_opts_verify(sb, *flags, /*pending*/0);
30244+ aufs_write_unlock(root);
30245+ }
1facf9fc 30246+ goto out;
30247+ }
30248+
30249+ err = -ENOMEM;
1facf9fc 30250+ opts.opt = (void *)__get_free_page(GFP_NOFS);
30251+ if (unlikely(!opts.opt))
30252+ goto out;
30253+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
30254+ opts.flags = AuOpts_REMOUNT;
30255+ opts.sb_flags = *flags;
30256+
30257+ /* parse it before aufs lock */
30258+ err = au_opts_parse(sb, data, &opts);
30259+ if (unlikely(err))
30260+ goto out_opts;
30261+
30262+ sbinfo = au_sbi(sb);
5527c038 30263+ inode = d_inode(root);
febd17d6 30264+ inode_lock(inode);
e49829fe
JR
30265+ err = si_write_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
30266+ if (unlikely(err))
30267+ goto out_mtx;
30268+ di_write_lock_child(root);
1facf9fc 30269+
30270+ /* au_opts_remount() may return an error */
30271+ err = au_opts_remount(sb, &opts);
30272+ au_opts_free(&opts);
30273+
027c5e7a 30274+ if (au_ftest_opts(opts.flags, REFRESH))
b95c5147 30275+ au_remount_refresh(sb, au_ftest_opts(opts.flags, REFRESH_IDOP));
1facf9fc 30276+
4a4d8108
AM
30277+ if (au_ftest_opts(opts.flags, REFRESH_DYAOP)) {
30278+ mntflags = au_mntflags(sb);
30279+ do_dx = !!au_opt_test(mntflags, DIO);
30280+ au_dy_arefresh(do_dx);
30281+ }
30282+
076b876e 30283+ au_fhsm_wrote_all(sb, /*force*/1); /* ?? */
1facf9fc 30284+ aufs_write_unlock(root);
953406b4 30285+
e49829fe 30286+out_mtx:
febd17d6 30287+ inode_unlock(inode);
4f0767ce 30288+out_opts:
1c60b727 30289+ free_page((unsigned long)opts.opt);
4f0767ce 30290+out:
1facf9fc 30291+ err = cvt_err(err);
30292+ AuTraceErr(err);
30293+ return err;
30294+}
30295+
4a4d8108 30296+static const struct super_operations aufs_sop = {
1facf9fc 30297+ .alloc_inode = aufs_alloc_inode,
30298+ .destroy_inode = aufs_destroy_inode,
fbc438ed 30299+ .free_inode = aufs_free_inode,
b752ccd1 30300+ /* always deleting, no clearing */
1facf9fc 30301+ .drop_inode = generic_delete_inode,
30302+ .show_options = aufs_show_options,
30303+ .statfs = aufs_statfs,
30304+ .put_super = aufs_put_super,
537831f9 30305+ .sync_fs = aufs_sync_fs,
1facf9fc 30306+ .remount_fs = aufs_remount_fs
30307+};
30308+
30309+/* ---------------------------------------------------------------------- */
30310+
30311+static int alloc_root(struct super_block *sb)
30312+{
30313+ int err;
30314+ struct inode *inode;
30315+ struct dentry *root;
30316+
30317+ err = -ENOMEM;
30318+ inode = au_iget_locked(sb, AUFS_ROOT_INO);
30319+ err = PTR_ERR(inode);
30320+ if (IS_ERR(inode))
30321+ goto out;
30322+
b95c5147 30323+ inode->i_op = aufs_iop + AuIop_DIR; /* with getattr by default */
1facf9fc 30324+ inode->i_fop = &aufs_dir_fop;
30325+ inode->i_mode = S_IFDIR;
9dbd164d 30326+ set_nlink(inode, 2);
1facf9fc 30327+ unlock_new_inode(inode);
30328+
92d182d2 30329+ root = d_make_root(inode);
1facf9fc 30330+ if (unlikely(!root))
92d182d2 30331+ goto out;
1facf9fc 30332+ err = PTR_ERR(root);
30333+ if (IS_ERR(root))
92d182d2 30334+ goto out;
1facf9fc 30335+
4a4d8108 30336+ err = au_di_init(root);
1facf9fc 30337+ if (!err) {
30338+ sb->s_root = root;
30339+ return 0; /* success */
30340+ }
30341+ dput(root);
1facf9fc 30342+
4f0767ce 30343+out:
1facf9fc 30344+ return err;
1facf9fc 30345+}
30346+
30347+static int aufs_fill_super(struct super_block *sb, void *raw_data,
30348+ int silent __maybe_unused)
30349+{
30350+ int err;
be52b249
AM
30351+ struct au_opts opts = {
30352+ .opt = NULL
30353+ };
79b8bda9 30354+ struct au_sbinfo *sbinfo;
1facf9fc 30355+ struct dentry *root;
30356+ struct inode *inode;
30357+ char *arg = raw_data;
30358+
30359+ if (unlikely(!arg || !*arg)) {
30360+ err = -EINVAL;
4a4d8108 30361+ pr_err("no arg\n");
1facf9fc 30362+ goto out;
30363+ }
30364+
30365+ err = -ENOMEM;
1facf9fc 30366+ opts.opt = (void *)__get_free_page(GFP_NOFS);
30367+ if (unlikely(!opts.opt))
30368+ goto out;
30369+ opts.max_opt = PAGE_SIZE / sizeof(*opts.opt);
30370+ opts.sb_flags = sb->s_flags;
30371+
30372+ err = au_si_alloc(sb);
30373+ if (unlikely(err))
30374+ goto out_opts;
79b8bda9 30375+ sbinfo = au_sbi(sb);
1facf9fc 30376+
30377+ /* all timestamps always follow the ones on the branch */
2121bcd9 30378+ sb->s_flags |= SB_NOATIME | SB_NODIRATIME;
be118d29 30379+ sb->s_flags |= SB_I_VERSION; /* do we really need this? */
1facf9fc 30380+ sb->s_op = &aufs_sop;
027c5e7a 30381+ sb->s_d_op = &aufs_dop;
1facf9fc 30382+ sb->s_magic = AUFS_SUPER_MAGIC;
30383+ sb->s_maxbytes = 0;
c1595e42 30384+ sb->s_stack_depth = 1;
1facf9fc 30385+ au_export_init(sb);
f2c43d5f 30386+ au_xattr_init(sb);
1facf9fc 30387+
30388+ err = alloc_root(sb);
30389+ if (unlikely(err)) {
30390+ si_write_unlock(sb);
30391+ goto out_info;
30392+ }
30393+ root = sb->s_root;
5527c038 30394+ inode = d_inode(root);
1facf9fc 30395+
30396+ /*
30397+ * actually we can parse options regardless aufs lock here.
30398+ * but at remount time, parsing must be done before aufs lock.
30399+ * so we follow the same rule.
30400+ */
30401+ ii_write_lock_parent(inode);
30402+ aufs_write_unlock(root);
30403+ err = au_opts_parse(sb, arg, &opts);
30404+ if (unlikely(err))
30405+ goto out_root;
30406+
30407+ /* lock vfs_inode first, then aufs. */
febd17d6 30408+ inode_lock(inode);
1facf9fc 30409+ aufs_write_lock(root);
30410+ err = au_opts_mount(sb, &opts);
30411+ au_opts_free(&opts);
79b8bda9
AM
30412+ if (!err && au_ftest_si(sbinfo, NO_DREVAL)) {
30413+ sb->s_d_op = &aufs_dop_noreval;
062440b3 30414+ pr_info("%ps\n", sb->s_d_op);
79b8bda9 30415+ au_refresh_dop(root, /*force_reval*/0);
b95c5147
AM
30416+ sbinfo->si_iop_array = aufs_iop_nogetattr;
30417+ au_refresh_iop(inode, /*force_getattr*/0);
79b8bda9 30418+ }
1facf9fc 30419+ aufs_write_unlock(root);
febd17d6 30420+ inode_unlock(inode);
4a4d8108
AM
30421+ if (!err)
30422+ goto out_opts; /* success */
1facf9fc 30423+
4f0767ce 30424+out_root:
1facf9fc 30425+ dput(root);
30426+ sb->s_root = NULL;
4f0767ce 30427+out_info:
79b8bda9 30428+ kobject_put(&sbinfo->si_kobj);
1facf9fc 30429+ sb->s_fs_info = NULL;
4f0767ce 30430+out_opts:
1c60b727 30431+ free_page((unsigned long)opts.opt);
4f0767ce 30432+out:
1facf9fc 30433+ AuTraceErr(err);
30434+ err = cvt_err(err);
30435+ AuTraceErr(err);
30436+ return err;
30437+}
30438+
30439+/* ---------------------------------------------------------------------- */
30440+
027c5e7a
AM
30441+static struct dentry *aufs_mount(struct file_system_type *fs_type, int flags,
30442+ const char *dev_name __maybe_unused,
30443+ void *raw_data)
1facf9fc 30444+{
027c5e7a 30445+ struct dentry *root;
1facf9fc 30446+
30447+ /* all timestamps always follow the ones on the branch */
30448+ /* mnt->mnt_flags |= MNT_NOATIME | MNT_NODIRATIME; */
027c5e7a
AM
30449+ root = mount_nodev(fs_type, flags, raw_data, aufs_fill_super);
30450+ if (IS_ERR(root))
30451+ goto out;
30452+
062440b3 30453+ au_sbilist_add(root->d_sb);
027c5e7a
AM
30454+
30455+out:
30456+ return root;
1facf9fc 30457+}
30458+
e49829fe
JR
30459+static void aufs_kill_sb(struct super_block *sb)
30460+{
30461+ struct au_sbinfo *sbinfo;
30462+
30463+ sbinfo = au_sbi(sb);
30464+ if (sbinfo) {
30465+ au_sbilist_del(sb);
30466+ aufs_write_lock(sb->s_root);
076b876e 30467+ au_fhsm_fin(sb);
e49829fe
JR
30468+ if (sbinfo->si_wbr_create_ops->fin)
30469+ sbinfo->si_wbr_create_ops->fin(sb);
30470+ if (au_opt_test(sbinfo->si_mntflags, UDBA_HNOTIFY)) {
30471+ au_opt_set_udba(sbinfo->si_mntflags, UDBA_NONE);
b95c5147 30472+ au_remount_refresh(sb, /*do_idop*/0);
e49829fe
JR
30473+ }
30474+ if (au_opt_test(sbinfo->si_mntflags, PLINK))
30475+ au_plink_put(sb, /*verbose*/1);
30476+ au_xino_clr(sb);
8b6a4947 30477+ au_dr_opt_flush(sb);
1e00d052 30478+ sbinfo->si_sb = NULL;
e49829fe 30479+ aufs_write_unlock(sb->s_root);
e49829fe
JR
30480+ au_nwt_flush(&sbinfo->si_nowait);
30481+ }
98d9a5b1 30482+ kill_anon_super(sb);
e49829fe
JR
30483+}
30484+
1facf9fc 30485+struct file_system_type aufs_fs_type = {
30486+ .name = AUFS_FSTYPE,
c06a8ce3
AM
30487+ /* a race between rename and others */
30488+ .fs_flags = FS_RENAME_DOES_D_MOVE,
027c5e7a 30489+ .mount = aufs_mount,
e49829fe 30490+ .kill_sb = aufs_kill_sb,
1facf9fc 30491+ /* no need to __module_get() and module_put(). */
30492+ .owner = THIS_MODULE,
30493+};
7f207e10 30494diff -urN /usr/share/empty/fs/aufs/super.h linux/fs/aufs/super.h
eca34b5c 30495--- /usr/share/empty/fs/aufs/super.h 1970-01-01 01:00:00.000000000 +0100
016522bc 30496+++ linux/fs/aufs/super.h 2020-01-27 10:57:18.178871751 +0100
acd2b654 30497@@ -0,0 +1,589 @@
062440b3 30498+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 30499+/*
016522bc 30500+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 30501+ *
30502+ * This program, aufs is free software; you can redistribute it and/or modify
30503+ * it under the terms of the GNU General Public License as published by
30504+ * the Free Software Foundation; either version 2 of the License, or
30505+ * (at your option) any later version.
dece6358
AM
30506+ *
30507+ * This program is distributed in the hope that it will be useful,
30508+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
30509+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30510+ * GNU General Public License for more details.
30511+ *
30512+ * You should have received a copy of the GNU General Public License
523b37e3 30513+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 30514+ */
30515+
30516+/*
30517+ * super_block operations
30518+ */
30519+
30520+#ifndef __AUFS_SUPER_H__
30521+#define __AUFS_SUPER_H__
30522+
30523+#ifdef __KERNEL__
30524+
30525+#include <linux/fs.h>
5527c038 30526+#include <linux/kobject.h>
8b6a4947 30527+#include "hbl.h"
acd2b654 30528+#include "lcnt.h"
1facf9fc 30529+#include "rwsem.h"
1facf9fc 30530+#include "wkq.h"
30531+
1facf9fc 30532+/* policies to select one among multiple writable branches */
30533+struct au_wbr_copyup_operations {
30534+ int (*copyup)(struct dentry *dentry);
30535+};
30536+
392086de
AM
30537+#define AuWbr_DIR 1 /* target is a dir */
30538+#define AuWbr_PARENT (1 << 1) /* always require a parent */
30539+
30540+#define au_ftest_wbr(flags, name) ((flags) & AuWbr_##name)
30541+#define au_fset_wbr(flags, name) { (flags) |= AuWbr_##name; }
30542+#define au_fclr_wbr(flags, name) { (flags) &= ~AuWbr_##name; }
30543+
1facf9fc 30544+struct au_wbr_create_operations {
392086de 30545+ int (*create)(struct dentry *dentry, unsigned int flags);
1facf9fc 30546+ int (*init)(struct super_block *sb);
30547+ int (*fin)(struct super_block *sb);
30548+};
30549+
30550+struct au_wbr_mfs {
30551+ struct mutex mfs_lock; /* protect this structure */
30552+ unsigned long mfs_jiffy;
30553+ unsigned long mfs_expire;
30554+ aufs_bindex_t mfs_bindex;
30555+
30556+ unsigned long long mfsrr_bytes;
30557+ unsigned long long mfsrr_watermark;
30558+};
30559+
86dc4139
AM
30560+#define AuPlink_NHASH 100
30561+static inline int au_plink_hash(ino_t ino)
30562+{
30563+ return ino % AuPlink_NHASH;
30564+}
30565+
076b876e
AM
30566+/* File-based Hierarchical Storage Management */
30567+struct au_fhsm {
30568+#ifdef CONFIG_AUFS_FHSM
30569+ /* allow only one process who can receive the notification */
30570+ spinlock_t fhsm_spin;
30571+ pid_t fhsm_pid;
30572+ wait_queue_head_t fhsm_wqh;
30573+ atomic_t fhsm_readable;
30574+
c1595e42 30575+ /* these are protected by si_rwsem */
076b876e 30576+ unsigned long fhsm_expire;
c1595e42 30577+ aufs_bindex_t fhsm_bottom;
076b876e
AM
30578+#endif
30579+};
30580+
1facf9fc 30581+struct au_branch;
30582+struct au_sbinfo {
30583+ /* nowait tasks in the system-wide workqueue */
30584+ struct au_nowait_tasks si_nowait;
30585+
b752ccd1 30586+ /*
acd2b654 30587+ * tried sb->s_umount, but failed due to the dependency between i_mutex.
b752ccd1
AM
30588+ * rwsem for au_sbinfo is necessary.
30589+ */
dece6358 30590+ struct au_rwsem si_rwsem;
1facf9fc 30591+
7f207e10 30592+ /*
523b37e3
AM
30593+ * dirty approach to protect sb->sb_inodes and ->s_files (gone) from
30594+ * remount.
7f207e10 30595+ */
acd2b654 30596+ au_lcnt_t si_ninodes, si_nfiles;
7f207e10 30597+
1facf9fc 30598+ /* branch management */
30599+ unsigned int si_generation;
30600+
2000de60 30601+ /* see AuSi_ flags */
1facf9fc 30602+ unsigned char au_si_status;
30603+
5afbbe0d 30604+ aufs_bindex_t si_bbot;
7f207e10
AM
30605+
30606+ /* dirty trick to keep br_id plus */
30607+ unsigned int si_last_br_id :
30608+ sizeof(aufs_bindex_t) * BITS_PER_BYTE - 1;
1facf9fc 30609+ struct au_branch **si_branch;
30610+
30611+ /* policy to select a writable branch */
30612+ unsigned char si_wbr_copyup;
30613+ unsigned char si_wbr_create;
30614+ struct au_wbr_copyup_operations *si_wbr_copyup_ops;
30615+ struct au_wbr_create_operations *si_wbr_create_ops;
30616+
30617+ /* round robin */
30618+ atomic_t si_wbr_rr_next;
30619+
30620+ /* most free space */
30621+ struct au_wbr_mfs si_wbr_mfs;
30622+
076b876e
AM
30623+ /* File-based Hierarchical Storage Management */
30624+ struct au_fhsm si_fhsm;
30625+
1facf9fc 30626+ /* mount flags */
30627+ /* include/asm-ia64/siginfo.h defines a macro named si_flags */
30628+ unsigned int si_mntflags;
30629+
30630+ /* external inode number (bitmap and translation table) */
5527c038
JR
30631+ vfs_readf_t si_xread;
30632+ vfs_writef_t si_xwrite;
acd2b654
AM
30633+ loff_t si_ximaxent; /* max entries in a xino */
30634+
1facf9fc 30635+ struct file *si_xib;
30636+ struct mutex si_xib_mtx; /* protect xib members */
30637+ unsigned long *si_xib_buf;
30638+ unsigned long si_xib_last_pindex;
30639+ int si_xib_next_bit;
acd2b654 30640+
392086de
AM
30641+ unsigned long si_xino_jiffy;
30642+ unsigned long si_xino_expire;
1facf9fc 30643+ /* reserved for future use */
30644+ /* unsigned long long si_xib_limit; */ /* Max xib file size */
30645+
30646+#ifdef CONFIG_AUFS_EXPORT
30647+ /* i_generation */
acd2b654 30648+ /* todo: make xigen file an array to support many inode numbers */
1facf9fc 30649+ struct file *si_xigen;
30650+ atomic_t si_xigen_next;
30651+#endif
30652+
acd2b654 30653+ /* dirty trick to support atomic_open */
8b6a4947 30654+ struct hlist_bl_head si_aopen;
b912730e 30655+
1facf9fc 30656+ /* vdir parameters */
e49829fe 30657+ unsigned long si_rdcache; /* max cache time in jiffies */
1facf9fc 30658+ unsigned int si_rdblk; /* deblk size */
30659+ unsigned int si_rdhash; /* hash size */
30660+
30661+ /*
30662+ * If the number of whiteouts are larger than si_dirwh, leave all of
30663+ * them after au_whtmp_ren to reduce the cost of rmdir(2).
30664+ * future fsck.aufs or kernel thread will remove them later.
30665+ * Otherwise, remove all whiteouts and the dir in rmdir(2).
30666+ */
30667+ unsigned int si_dirwh;
30668+
1facf9fc 30669+ /* pseudo_link list */
8b6a4947 30670+ struct hlist_bl_head si_plink[AuPlink_NHASH];
1facf9fc 30671+ wait_queue_head_t si_plink_wq;
4a4d8108 30672+ spinlock_t si_plink_maint_lock;
e49829fe 30673+ pid_t si_plink_maint_pid;
1facf9fc 30674+
523b37e3 30675+ /* file list */
8b6a4947 30676+ struct hlist_bl_head si_files;
523b37e3 30677+
b95c5147 30678+ /* with/without getattr, brother of sb->s_d_op */
43982f53 30679+ const struct inode_operations *si_iop_array;
b95c5147 30680+
1facf9fc 30681+ /*
30682+ * sysfs and lifetime management.
30683+ * this is not a small structure and it may be a waste of memory in case
acd2b654 30684+ * of sysfs is disabled, particularly when many aufs-es are mounted.
1facf9fc 30685+ * but using sysfs is majority.
30686+ */
30687+ struct kobject si_kobj;
30688+#ifdef CONFIG_DEBUG_FS
86dc4139
AM
30689+ struct dentry *si_dbgaufs;
30690+ struct dentry *si_dbgaufs_plink;
30691+ struct dentry *si_dbgaufs_xib;
1facf9fc 30692+#ifdef CONFIG_AUFS_EXPORT
30693+ struct dentry *si_dbgaufs_xigen;
30694+#endif
30695+#endif
30696+
e49829fe 30697+#ifdef CONFIG_AUFS_SBILIST
8b6a4947 30698+ struct hlist_bl_node si_list;
e49829fe
JR
30699+#endif
30700+
1facf9fc 30701+ /* dirty, necessary for unmounting, sysfs and sysrq */
30702+ struct super_block *si_sb;
30703+};
30704+
dece6358
AM
30705+/* sbinfo status flags */
30706+/*
30707+ * set true when refresh_dirs() failed at remount time.
30708+ * then try refreshing dirs at access time again.
062440b3 30709+ * if it is false, refreshing dirs at access time is unnecessary
dece6358 30710+ */
027c5e7a 30711+#define AuSi_FAILED_REFRESH_DIR 1
076b876e 30712+#define AuSi_FHSM (1 << 1) /* fhsm is active now */
79b8bda9 30713+#define AuSi_NO_DREVAL (1 << 2) /* disable all d_revalidate */
076b876e
AM
30714+
30715+#ifndef CONFIG_AUFS_FHSM
30716+#undef AuSi_FHSM
30717+#define AuSi_FHSM 0
30718+#endif
30719+
dece6358
AM
30720+static inline unsigned char au_do_ftest_si(struct au_sbinfo *sbi,
30721+ unsigned int flag)
30722+{
30723+ AuRwMustAnyLock(&sbi->si_rwsem);
30724+ return sbi->au_si_status & flag;
30725+}
30726+#define au_ftest_si(sbinfo, name) au_do_ftest_si(sbinfo, AuSi_##name)
30727+#define au_fset_si(sbinfo, name) do { \
30728+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
30729+ (sbinfo)->au_si_status |= AuSi_##name; \
30730+} while (0)
30731+#define au_fclr_si(sbinfo, name) do { \
30732+ AuRwMustWriteLock(&(sbinfo)->si_rwsem); \
30733+ (sbinfo)->au_si_status &= ~AuSi_##name; \
30734+} while (0)
30735+
1facf9fc 30736+/* ---------------------------------------------------------------------- */
30737+
30738+/* policy to select one among writable branches */
4a4d8108
AM
30739+#define AuWbrCopyup(sbinfo, ...) \
30740+ ((sbinfo)->si_wbr_copyup_ops->copyup(__VA_ARGS__))
30741+#define AuWbrCreate(sbinfo, ...) \
30742+ ((sbinfo)->si_wbr_create_ops->create(__VA_ARGS__))
1facf9fc 30743+
30744+/* flags for si_read_lock()/aufs_read_lock()/di_read_lock() */
30745+#define AuLock_DW 1 /* write-lock dentry */
30746+#define AuLock_IR (1 << 1) /* read-lock inode */
30747+#define AuLock_IW (1 << 2) /* write-lock inode */
30748+#define AuLock_FLUSH (1 << 3) /* wait for 'nowait' tasks */
b95c5147 30749+#define AuLock_DIRS (1 << 4) /* target is a pair of dirs */
f2c43d5f 30750+ /* except RENAME_EXCHANGE */
e49829fe
JR
30751+#define AuLock_NOPLM (1 << 5) /* return err in plm mode */
30752+#define AuLock_NOPLMW (1 << 6) /* wait for plm mode ends */
027c5e7a 30753+#define AuLock_GEN (1 << 7) /* test digen/iigen */
1facf9fc 30754+#define au_ftest_lock(flags, name) ((flags) & AuLock_##name)
7f207e10
AM
30755+#define au_fset_lock(flags, name) \
30756+ do { (flags) |= AuLock_##name; } while (0)
30757+#define au_fclr_lock(flags, name) \
30758+ do { (flags) &= ~AuLock_##name; } while (0)
1facf9fc 30759+
30760+/* ---------------------------------------------------------------------- */
30761+
30762+/* super.c */
30763+extern struct file_system_type aufs_fs_type;
30764+struct inode *au_iget_locked(struct super_block *sb, ino_t ino);
79b8bda9
AM
30765+typedef unsigned long long (*au_arraycb_t)(struct super_block *sb, void *array,
30766+ unsigned long long max, void *arg);
79b8bda9
AM
30767+void *au_array_alloc(unsigned long long *hint, au_arraycb_t cb,
30768+ struct super_block *sb, void *arg);
7f207e10
AM
30769+struct inode **au_iarray_alloc(struct super_block *sb, unsigned long long *max);
30770+void au_iarray_free(struct inode **a, unsigned long long max);
1facf9fc 30771+
30772+/* sbinfo.c */
30773+void au_si_free(struct kobject *kobj);
30774+int au_si_alloc(struct super_block *sb);
e2f27e51 30775+int au_sbr_realloc(struct au_sbinfo *sbinfo, int nbr, int may_shrink);
1facf9fc 30776+
30777+unsigned int au_sigen_inc(struct super_block *sb);
30778+aufs_bindex_t au_new_br_id(struct super_block *sb);
30779+
e49829fe
JR
30780+int si_read_lock(struct super_block *sb, int flags);
30781+int si_write_lock(struct super_block *sb, int flags);
30782+int aufs_read_lock(struct dentry *dentry, int flags);
1facf9fc 30783+void aufs_read_unlock(struct dentry *dentry, int flags);
30784+void aufs_write_lock(struct dentry *dentry);
30785+void aufs_write_unlock(struct dentry *dentry);
e49829fe 30786+int aufs_read_and_write_lock2(struct dentry *d1, struct dentry *d2, int flags);
1facf9fc 30787+void aufs_read_and_write_unlock2(struct dentry *d1, struct dentry *d2);
30788+
30789+/* wbr_policy.c */
30790+extern struct au_wbr_copyup_operations au_wbr_copyup_ops[];
30791+extern struct au_wbr_create_operations au_wbr_create_ops[];
30792+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst);
c2b27bf2 30793+int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex);
5afbbe0d 30794+int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop);
c2b27bf2
AM
30795+
30796+/* mvdown.c */
30797+int au_mvdown(struct dentry *dentry, struct aufs_mvdown __user *arg);
1facf9fc 30798+
076b876e
AM
30799+#ifdef CONFIG_AUFS_FHSM
30800+/* fhsm.c */
30801+
30802+static inline pid_t au_fhsm_pid(struct au_fhsm *fhsm)
30803+{
30804+ pid_t pid;
30805+
30806+ spin_lock(&fhsm->fhsm_spin);
30807+ pid = fhsm->fhsm_pid;
30808+ spin_unlock(&fhsm->fhsm_spin);
30809+
30810+ return pid;
30811+}
30812+
30813+void au_fhsm_wrote(struct super_block *sb, aufs_bindex_t bindex, int force);
30814+void au_fhsm_wrote_all(struct super_block *sb, int force);
30815+int au_fhsm_fd(struct super_block *sb, int oflags);
30816+int au_fhsm_br_alloc(struct au_branch *br);
c1595e42 30817+void au_fhsm_set_bottom(struct super_block *sb, aufs_bindex_t bindex);
076b876e
AM
30818+void au_fhsm_fin(struct super_block *sb);
30819+void au_fhsm_init(struct au_sbinfo *sbinfo);
30820+void au_fhsm_set(struct au_sbinfo *sbinfo, unsigned int sec);
30821+void au_fhsm_show(struct seq_file *seq, struct au_sbinfo *sbinfo);
30822+#else
30823+AuStubVoid(au_fhsm_wrote, struct super_block *sb, aufs_bindex_t bindex,
30824+ int force)
30825+AuStubVoid(au_fhsm_wrote_all, struct super_block *sb, int force)
30826+AuStub(int, au_fhsm_fd, return -EOPNOTSUPP, struct super_block *sb, int oflags)
c1595e42
JR
30827+AuStub(pid_t, au_fhsm_pid, return 0, struct au_fhsm *fhsm)
30828+AuStubInt0(au_fhsm_br_alloc, struct au_branch *br)
30829+AuStubVoid(au_fhsm_set_bottom, struct super_block *sb, aufs_bindex_t bindex)
076b876e
AM
30830+AuStubVoid(au_fhsm_fin, struct super_block *sb)
30831+AuStubVoid(au_fhsm_init, struct au_sbinfo *sbinfo)
30832+AuStubVoid(au_fhsm_set, struct au_sbinfo *sbinfo, unsigned int sec)
30833+AuStubVoid(au_fhsm_show, struct seq_file *seq, struct au_sbinfo *sbinfo)
30834+#endif
30835+
1facf9fc 30836+/* ---------------------------------------------------------------------- */
30837+
30838+static inline struct au_sbinfo *au_sbi(struct super_block *sb)
30839+{
30840+ return sb->s_fs_info;
30841+}
30842+
30843+/* ---------------------------------------------------------------------- */
30844+
30845+#ifdef CONFIG_AUFS_EXPORT
a2a7ad62 30846+int au_test_nfsd(void);
1facf9fc 30847+void au_export_init(struct super_block *sb);
b752ccd1 30848+void au_xigen_inc(struct inode *inode);
1facf9fc 30849+int au_xigen_new(struct inode *inode);
062440b3 30850+int au_xigen_set(struct super_block *sb, struct path *path);
1facf9fc 30851+void au_xigen_clr(struct super_block *sb);
30852+
30853+static inline int au_busy_or_stale(void)
30854+{
b752ccd1 30855+ if (!au_test_nfsd())
1facf9fc 30856+ return -EBUSY;
30857+ return -ESTALE;
30858+}
30859+#else
b752ccd1 30860+AuStubInt0(au_test_nfsd, void)
a2a7ad62 30861+AuStubVoid(au_export_init, struct super_block *sb)
b752ccd1 30862+AuStubVoid(au_xigen_inc, struct inode *inode)
4a4d8108 30863+AuStubInt0(au_xigen_new, struct inode *inode)
062440b3 30864+AuStubInt0(au_xigen_set, struct super_block *sb, struct path *path)
4a4d8108 30865+AuStubVoid(au_xigen_clr, struct super_block *sb)
c1595e42 30866+AuStub(int, au_busy_or_stale, return -EBUSY, void)
1facf9fc 30867+#endif /* CONFIG_AUFS_EXPORT */
30868+
30869+/* ---------------------------------------------------------------------- */
30870+
e49829fe
JR
30871+#ifdef CONFIG_AUFS_SBILIST
30872+/* module.c */
8b6a4947 30873+extern struct hlist_bl_head au_sbilist;
e49829fe
JR
30874+
30875+static inline void au_sbilist_init(void)
30876+{
8b6a4947 30877+ INIT_HLIST_BL_HEAD(&au_sbilist);
e49829fe
JR
30878+}
30879+
30880+static inline void au_sbilist_add(struct super_block *sb)
30881+{
8b6a4947 30882+ au_hbl_add(&au_sbi(sb)->si_list, &au_sbilist);
e49829fe
JR
30883+}
30884+
30885+static inline void au_sbilist_del(struct super_block *sb)
30886+{
8b6a4947 30887+ au_hbl_del(&au_sbi(sb)->si_list, &au_sbilist);
e49829fe 30888+}
53392da6
AM
30889+
30890+#ifdef CONFIG_AUFS_MAGIC_SYSRQ
30891+static inline void au_sbilist_lock(void)
30892+{
8b6a4947 30893+ hlist_bl_lock(&au_sbilist);
53392da6
AM
30894+}
30895+
30896+static inline void au_sbilist_unlock(void)
30897+{
8b6a4947 30898+ hlist_bl_unlock(&au_sbilist);
53392da6
AM
30899+}
30900+#define AuGFP_SBILIST GFP_ATOMIC
30901+#else
30902+AuStubVoid(au_sbilist_lock, void)
30903+AuStubVoid(au_sbilist_unlock, void)
30904+#define AuGFP_SBILIST GFP_NOFS
30905+#endif /* CONFIG_AUFS_MAGIC_SYSRQ */
e49829fe
JR
30906+#else
30907+AuStubVoid(au_sbilist_init, void)
c1595e42
JR
30908+AuStubVoid(au_sbilist_add, struct super_block *sb)
30909+AuStubVoid(au_sbilist_del, struct super_block *sb)
53392da6
AM
30910+AuStubVoid(au_sbilist_lock, void)
30911+AuStubVoid(au_sbilist_unlock, void)
30912+#define AuGFP_SBILIST GFP_NOFS
e49829fe
JR
30913+#endif
30914+
30915+/* ---------------------------------------------------------------------- */
30916+
1facf9fc 30917+static inline void dbgaufs_si_null(struct au_sbinfo *sbinfo)
30918+{
dece6358 30919+ /*
c1595e42 30920+ * This function is a dynamic '__init' function actually,
dece6358
AM
30921+ * so the tiny check for si_rwsem is unnecessary.
30922+ */
30923+ /* AuRwMustWriteLock(&sbinfo->si_rwsem); */
1facf9fc 30924+#ifdef CONFIG_DEBUG_FS
30925+ sbinfo->si_dbgaufs = NULL;
86dc4139 30926+ sbinfo->si_dbgaufs_plink = NULL;
1facf9fc 30927+ sbinfo->si_dbgaufs_xib = NULL;
30928+#ifdef CONFIG_AUFS_EXPORT
30929+ sbinfo->si_dbgaufs_xigen = NULL;
30930+#endif
30931+#endif
30932+}
30933+
30934+/* ---------------------------------------------------------------------- */
30935+
a2654f78
AM
30936+/* current->atomic_flags */
30937+/* this value should never corrupt the ones defined in linux/sched.h */
fbc438ed 30938+#define PFA_AUFS 0x10
a2654f78
AM
30939+
30940+TASK_PFA_TEST(AUFS, test_aufs) /* task_test_aufs */
30941+TASK_PFA_SET(AUFS, aufs) /* task_set_aufs */
30942+TASK_PFA_CLEAR(AUFS, aufs) /* task_clear_aufs */
b752ccd1
AM
30943+
30944+static inline int si_pid_test(struct super_block *sb)
30945+{
a2654f78 30946+ return !!task_test_aufs(current);
b752ccd1
AM
30947+}
30948+
30949+static inline void si_pid_clr(struct super_block *sb)
30950+{
a2654f78
AM
30951+ AuDebugOn(!task_test_aufs(current));
30952+ task_clear_aufs(current);
b752ccd1
AM
30953+}
30954+
a2654f78
AM
30955+static inline void si_pid_set(struct super_block *sb)
30956+{
30957+ AuDebugOn(task_test_aufs(current));
30958+ task_set_aufs(current);
30959+}
febd17d6 30960+
b752ccd1
AM
30961+/* ---------------------------------------------------------------------- */
30962+
1facf9fc 30963+/* lock superblock. mainly for entry point functions */
8b6a4947
AM
30964+#define __si_read_lock(sb) au_rw_read_lock(&au_sbi(sb)->si_rwsem)
30965+#define __si_write_lock(sb) au_rw_write_lock(&au_sbi(sb)->si_rwsem)
30966+#define __si_read_trylock(sb) au_rw_read_trylock(&au_sbi(sb)->si_rwsem)
30967+#define __si_write_trylock(sb) au_rw_write_trylock(&au_sbi(sb)->si_rwsem)
30968+/*
30969+#define __si_read_trylock_nested(sb) \
30970+ au_rw_read_trylock_nested(&au_sbi(sb)->si_rwsem)
30971+#define __si_write_trylock_nested(sb) \
30972+ au_rw_write_trylock_nested(&au_sbi(sb)->si_rwsem)
30973+*/
30974+
30975+#define __si_read_unlock(sb) au_rw_read_unlock(&au_sbi(sb)->si_rwsem)
30976+#define __si_write_unlock(sb) au_rw_write_unlock(&au_sbi(sb)->si_rwsem)
30977+#define __si_downgrade_lock(sb) au_rw_dgrade_lock(&au_sbi(sb)->si_rwsem)
1facf9fc 30978+
dece6358
AM
30979+#define SiMustNoWaiters(sb) AuRwMustNoWaiters(&au_sbi(sb)->si_rwsem)
30980+#define SiMustAnyLock(sb) AuRwMustAnyLock(&au_sbi(sb)->si_rwsem)
30981+#define SiMustWriteLock(sb) AuRwMustWriteLock(&au_sbi(sb)->si_rwsem)
30982+
b752ccd1
AM
30983+static inline void si_noflush_read_lock(struct super_block *sb)
30984+{
30985+ __si_read_lock(sb);
30986+ si_pid_set(sb);
30987+}
30988+
30989+static inline int si_noflush_read_trylock(struct super_block *sb)
30990+{
076b876e
AM
30991+ int locked;
30992+
30993+ locked = __si_read_trylock(sb);
b752ccd1
AM
30994+ if (locked)
30995+ si_pid_set(sb);
30996+ return locked;
30997+}
30998+
30999+static inline void si_noflush_write_lock(struct super_block *sb)
31000+{
31001+ __si_write_lock(sb);
31002+ si_pid_set(sb);
31003+}
31004+
31005+static inline int si_noflush_write_trylock(struct super_block *sb)
31006+{
076b876e
AM
31007+ int locked;
31008+
31009+ locked = __si_write_trylock(sb);
b752ccd1
AM
31010+ if (locked)
31011+ si_pid_set(sb);
31012+ return locked;
31013+}
31014+
7e9cd9fe 31015+#if 0 /* reserved */
1facf9fc 31016+static inline int si_read_trylock(struct super_block *sb, int flags)
31017+{
31018+ if (au_ftest_lock(flags, FLUSH))
31019+ au_nwt_flush(&au_sbi(sb)->si_nowait);
31020+ return si_noflush_read_trylock(sb);
31021+}
e49829fe 31022+#endif
1facf9fc 31023+
b752ccd1
AM
31024+static inline void si_read_unlock(struct super_block *sb)
31025+{
31026+ si_pid_clr(sb);
31027+ __si_read_unlock(sb);
31028+}
31029+
7e9cd9fe 31030+#if 0 /* reserved */
1facf9fc 31031+static inline int si_write_trylock(struct super_block *sb, int flags)
31032+{
31033+ if (au_ftest_lock(flags, FLUSH))
31034+ au_nwt_flush(&au_sbi(sb)->si_nowait);
31035+ return si_noflush_write_trylock(sb);
31036+}
b752ccd1
AM
31037+#endif
31038+
31039+static inline void si_write_unlock(struct super_block *sb)
31040+{
31041+ si_pid_clr(sb);
31042+ __si_write_unlock(sb);
31043+}
31044+
7e9cd9fe 31045+#if 0 /* reserved */
b752ccd1
AM
31046+static inline void si_downgrade_lock(struct super_block *sb)
31047+{
31048+ __si_downgrade_lock(sb);
31049+}
31050+#endif
1facf9fc 31051+
31052+/* ---------------------------------------------------------------------- */
31053+
5afbbe0d 31054+static inline aufs_bindex_t au_sbbot(struct super_block *sb)
1facf9fc 31055+{
dece6358 31056+ SiMustAnyLock(sb);
5afbbe0d 31057+ return au_sbi(sb)->si_bbot;
1facf9fc 31058+}
31059+
31060+static inline unsigned int au_mntflags(struct super_block *sb)
31061+{
dece6358 31062+ SiMustAnyLock(sb);
1facf9fc 31063+ return au_sbi(sb)->si_mntflags;
31064+}
31065+
31066+static inline unsigned int au_sigen(struct super_block *sb)
31067+{
dece6358 31068+ SiMustAnyLock(sb);
1facf9fc 31069+ return au_sbi(sb)->si_generation;
31070+}
31071+
31072+static inline struct au_branch *au_sbr(struct super_block *sb,
31073+ aufs_bindex_t bindex)
31074+{
dece6358 31075+ SiMustAnyLock(sb);
1facf9fc 31076+ return au_sbi(sb)->si_branch[0 + bindex];
31077+}
31078+
acd2b654 31079+static inline loff_t au_xi_maxent(struct super_block *sb)
1facf9fc 31080+{
dece6358 31081+ SiMustAnyLock(sb);
acd2b654 31082+ return au_sbi(sb)->si_ximaxent;
1facf9fc 31083+}
31084+
31085+#endif /* __KERNEL__ */
31086+#endif /* __AUFS_SUPER_H__ */
7f207e10 31087diff -urN /usr/share/empty/fs/aufs/sysaufs.c linux/fs/aufs/sysaufs.c
eca34b5c 31088--- /usr/share/empty/fs/aufs/sysaufs.c 1970-01-01 01:00:00.000000000 +0100
016522bc 31089+++ linux/fs/aufs/sysaufs.c 2020-01-27 10:57:18.178871751 +0100
062440b3 31090@@ -0,0 +1,93 @@
cd7a4cd9 31091+// SPDX-License-Identifier: GPL-2.0
1facf9fc 31092+/*
016522bc 31093+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 31094+ *
31095+ * This program, aufs is free software; you can redistribute it and/or modify
31096+ * it under the terms of the GNU General Public License as published by
31097+ * the Free Software Foundation; either version 2 of the License, or
31098+ * (at your option) any later version.
dece6358
AM
31099+ *
31100+ * This program is distributed in the hope that it will be useful,
31101+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31102+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31103+ * GNU General Public License for more details.
31104+ *
31105+ * You should have received a copy of the GNU General Public License
523b37e3 31106+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31107+ */
31108+
31109+/*
31110+ * sysfs interface and lifetime management
31111+ * they are necessary regardless sysfs is disabled.
31112+ */
31113+
1facf9fc 31114+#include <linux/random.h>
1facf9fc 31115+#include "aufs.h"
31116+
31117+unsigned long sysaufs_si_mask;
e49829fe 31118+struct kset *sysaufs_kset;
1facf9fc 31119+
31120+#define AuSiAttr(_name) { \
31121+ .attr = { .name = __stringify(_name), .mode = 0444 }, \
31122+ .show = sysaufs_si_##_name, \
31123+}
31124+
31125+static struct sysaufs_si_attr sysaufs_si_attr_xi_path = AuSiAttr(xi_path);
31126+struct attribute *sysaufs_si_attrs[] = {
31127+ &sysaufs_si_attr_xi_path.attr,
31128+ NULL,
31129+};
31130+
4a4d8108 31131+static const struct sysfs_ops au_sbi_ops = {
1facf9fc 31132+ .show = sysaufs_si_show
31133+};
31134+
31135+static struct kobj_type au_sbi_ktype = {
31136+ .release = au_si_free,
31137+ .sysfs_ops = &au_sbi_ops,
31138+ .default_attrs = sysaufs_si_attrs
31139+};
31140+
31141+/* ---------------------------------------------------------------------- */
31142+
31143+int sysaufs_si_init(struct au_sbinfo *sbinfo)
31144+{
31145+ int err;
31146+
e49829fe 31147+ sbinfo->si_kobj.kset = sysaufs_kset;
1facf9fc 31148+ /* cf. sysaufs_name() */
31149+ err = kobject_init_and_add
e49829fe 31150+ (&sbinfo->si_kobj, &au_sbi_ktype, /*&sysaufs_kset->kobj*/NULL,
1facf9fc 31151+ SysaufsSiNamePrefix "%lx", sysaufs_si_id(sbinfo));
31152+
1facf9fc 31153+ return err;
31154+}
31155+
31156+void sysaufs_fin(void)
31157+{
e49829fe
JR
31158+ sysfs_remove_group(&sysaufs_kset->kobj, sysaufs_attr_group);
31159+ kset_unregister(sysaufs_kset);
1facf9fc 31160+}
31161+
31162+int __init sysaufs_init(void)
31163+{
31164+ int err;
31165+
31166+ do {
31167+ get_random_bytes(&sysaufs_si_mask, sizeof(sysaufs_si_mask));
31168+ } while (!sysaufs_si_mask);
31169+
4a4d8108 31170+ err = -EINVAL;
e49829fe
JR
31171+ sysaufs_kset = kset_create_and_add(AUFS_NAME, NULL, fs_kobj);
31172+ if (unlikely(!sysaufs_kset))
4a4d8108 31173+ goto out;
e49829fe
JR
31174+ err = PTR_ERR(sysaufs_kset);
31175+ if (IS_ERR(sysaufs_kset))
1facf9fc 31176+ goto out;
e49829fe 31177+ err = sysfs_create_group(&sysaufs_kset->kobj, sysaufs_attr_group);
062440b3 31178+ if (unlikely(err))
e49829fe 31179+ kset_unregister(sysaufs_kset);
1facf9fc 31180+
4f0767ce 31181+out:
1facf9fc 31182+ return err;
31183+}
7f207e10 31184diff -urN /usr/share/empty/fs/aufs/sysaufs.h linux/fs/aufs/sysaufs.h
eca34b5c 31185--- /usr/share/empty/fs/aufs/sysaufs.h 1970-01-01 01:00:00.000000000 +0100
016522bc 31186+++ linux/fs/aufs/sysaufs.h 2020-01-27 10:57:18.178871751 +0100
062440b3
AM
31187@@ -0,0 +1,102 @@
31188+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 31189+/*
016522bc 31190+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 31191+ *
31192+ * This program, aufs is free software; you can redistribute it and/or modify
31193+ * it under the terms of the GNU General Public License as published by
31194+ * the Free Software Foundation; either version 2 of the License, or
31195+ * (at your option) any later version.
dece6358
AM
31196+ *
31197+ * This program is distributed in the hope that it will be useful,
31198+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31199+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31200+ * GNU General Public License for more details.
31201+ *
31202+ * You should have received a copy of the GNU General Public License
523b37e3 31203+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31204+ */
31205+
31206+/*
31207+ * sysfs interface and mount lifetime management
31208+ */
31209+
31210+#ifndef __SYSAUFS_H__
31211+#define __SYSAUFS_H__
31212+
31213+#ifdef __KERNEL__
31214+
1facf9fc 31215+#include <linux/sysfs.h>
1facf9fc 31216+#include "module.h"
31217+
dece6358
AM
31218+struct super_block;
31219+struct au_sbinfo;
31220+
1facf9fc 31221+struct sysaufs_si_attr {
31222+ struct attribute attr;
31223+ int (*show)(struct seq_file *seq, struct super_block *sb);
31224+};
31225+
31226+/* ---------------------------------------------------------------------- */
31227+
31228+/* sysaufs.c */
31229+extern unsigned long sysaufs_si_mask;
e49829fe 31230+extern struct kset *sysaufs_kset;
1facf9fc 31231+extern struct attribute *sysaufs_si_attrs[];
31232+int sysaufs_si_init(struct au_sbinfo *sbinfo);
31233+int __init sysaufs_init(void);
31234+void sysaufs_fin(void);
31235+
31236+/* ---------------------------------------------------------------------- */
31237+
31238+/* some people doesn't like to show a pointer in kernel */
31239+static inline unsigned long sysaufs_si_id(struct au_sbinfo *sbinfo)
31240+{
31241+ return sysaufs_si_mask ^ (unsigned long)sbinfo;
31242+}
31243+
31244+#define SysaufsSiNamePrefix "si_"
31245+#define SysaufsSiNameLen (sizeof(SysaufsSiNamePrefix) + 16)
31246+static inline void sysaufs_name(struct au_sbinfo *sbinfo, char *name)
31247+{
31248+ snprintf(name, SysaufsSiNameLen, SysaufsSiNamePrefix "%lx",
31249+ sysaufs_si_id(sbinfo));
31250+}
31251+
31252+struct au_branch;
31253+#ifdef CONFIG_SYSFS
31254+/* sysfs.c */
31255+extern struct attribute_group *sysaufs_attr_group;
31256+
31257+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb);
31258+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
31259+ char *buf);
076b876e
AM
31260+long au_brinfo_ioctl(struct file *file, unsigned long arg);
31261+#ifdef CONFIG_COMPAT
31262+long au_brinfo_compat_ioctl(struct file *file, unsigned long arg);
31263+#endif
1facf9fc 31264+
31265+void sysaufs_br_init(struct au_branch *br);
31266+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex);
31267+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex);
31268+
31269+#define sysaufs_brs_init() do {} while (0)
31270+
31271+#else
31272+#define sysaufs_attr_group NULL
31273+
4a4d8108 31274+AuStubInt0(sysaufs_si_xi_path, struct seq_file *seq, struct super_block *sb)
c1595e42
JR
31275+AuStub(ssize_t, sysaufs_si_show, return 0, struct kobject *kobj,
31276+ struct attribute *attr, char *buf)
4a4d8108
AM
31277+AuStubVoid(sysaufs_br_init, struct au_branch *br)
31278+AuStubVoid(sysaufs_brs_add, struct super_block *sb, aufs_bindex_t bindex)
31279+AuStubVoid(sysaufs_brs_del, struct super_block *sb, aufs_bindex_t bindex)
1facf9fc 31280+
31281+static inline void sysaufs_brs_init(void)
31282+{
31283+ sysaufs_brs = 0;
31284+}
31285+
31286+#endif /* CONFIG_SYSFS */
31287+
31288+#endif /* __KERNEL__ */
31289+#endif /* __SYSAUFS_H__ */
7f207e10 31290diff -urN /usr/share/empty/fs/aufs/sysfs.c linux/fs/aufs/sysfs.c
eca34b5c 31291--- /usr/share/empty/fs/aufs/sysfs.c 1970-01-01 01:00:00.000000000 +0100
016522bc 31292+++ linux/fs/aufs/sysfs.c 2020-01-27 10:57:18.178871751 +0100
ba1aed25 31293@@ -0,0 +1,374 @@
cd7a4cd9 31294+// SPDX-License-Identifier: GPL-2.0
1facf9fc 31295+/*
016522bc 31296+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 31297+ *
31298+ * This program, aufs is free software; you can redistribute it and/or modify
31299+ * it under the terms of the GNU General Public License as published by
31300+ * the Free Software Foundation; either version 2 of the License, or
31301+ * (at your option) any later version.
dece6358
AM
31302+ *
31303+ * This program is distributed in the hope that it will be useful,
31304+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31305+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31306+ * GNU General Public License for more details.
31307+ *
31308+ * You should have received a copy of the GNU General Public License
523b37e3 31309+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31310+ */
31311+
31312+/*
31313+ * sysfs interface
31314+ */
31315+
076b876e 31316+#include <linux/compat.h>
1facf9fc 31317+#include <linux/seq_file.h>
1facf9fc 31318+#include "aufs.h"
31319+
4a4d8108
AM
31320+#ifdef CONFIG_AUFS_FS_MODULE
31321+/* this entry violates the "one line per file" policy of sysfs */
31322+static ssize_t config_show(struct kobject *kobj, struct kobj_attribute *attr,
31323+ char *buf)
31324+{
31325+ ssize_t err;
31326+ static char *conf =
31327+/* this file is generated at compiling */
31328+#include "conf.str"
31329+ ;
31330+
31331+ err = snprintf(buf, PAGE_SIZE, conf);
31332+ if (unlikely(err >= PAGE_SIZE))
31333+ err = -EFBIG;
31334+ return err;
31335+}
31336+
31337+static struct kobj_attribute au_config_attr = __ATTR_RO(config);
31338+#endif
31339+
1facf9fc 31340+static struct attribute *au_attr[] = {
4a4d8108
AM
31341+#ifdef CONFIG_AUFS_FS_MODULE
31342+ &au_config_attr.attr,
31343+#endif
1facf9fc 31344+ NULL, /* need to NULL terminate the list of attributes */
31345+};
31346+
31347+static struct attribute_group sysaufs_attr_group_body = {
31348+ .attrs = au_attr
31349+};
31350+
31351+struct attribute_group *sysaufs_attr_group = &sysaufs_attr_group_body;
31352+
31353+/* ---------------------------------------------------------------------- */
31354+
31355+int sysaufs_si_xi_path(struct seq_file *seq, struct super_block *sb)
31356+{
31357+ int err;
31358+
dece6358
AM
31359+ SiMustAnyLock(sb);
31360+
1facf9fc 31361+ err = 0;
31362+ if (au_opt_test(au_mntflags(sb), XINO)) {
31363+ err = au_xino_path(seq, au_sbi(sb)->si_xib);
31364+ seq_putc(seq, '\n');
31365+ }
31366+ return err;
31367+}
31368+
31369+/*
31370+ * the lifetime of branch is independent from the entry under sysfs.
31371+ * sysfs handles the lifetime of the entry, and never call ->show() after it is
31372+ * unlinked.
31373+ */
31374+static int sysaufs_si_br(struct seq_file *seq, struct super_block *sb,
392086de 31375+ aufs_bindex_t bindex, int idx)
1facf9fc 31376+{
1e00d052 31377+ int err;
1facf9fc 31378+ struct path path;
31379+ struct dentry *root;
31380+ struct au_branch *br;
076b876e 31381+ au_br_perm_str_t perm;
1facf9fc 31382+
31383+ AuDbg("b%d\n", bindex);
31384+
1e00d052 31385+ err = 0;
1facf9fc 31386+ root = sb->s_root;
31387+ di_read_lock_parent(root, !AuLock_IR);
31388+ br = au_sbr(sb, bindex);
392086de
AM
31389+
31390+ switch (idx) {
31391+ case AuBrSysfs_BR:
31392+ path.mnt = au_br_mnt(br);
31393+ path.dentry = au_h_dptr(root, bindex);
79b8bda9
AM
31394+ err = au_seq_path(seq, &path);
31395+ if (!err) {
31396+ au_optstr_br_perm(&perm, br->br_perm);
31397+ seq_printf(seq, "=%s\n", perm.a);
31398+ }
392086de
AM
31399+ break;
31400+ case AuBrSysfs_BRID:
79b8bda9 31401+ seq_printf(seq, "%d\n", br->br_id);
392086de
AM
31402+ break;
31403+ }
076b876e 31404+ di_read_unlock(root, !AuLock_IR);
79b8bda9 31405+ if (unlikely(err || seq_has_overflowed(seq)))
076b876e 31406+ err = -E2BIG;
392086de 31407+
1e00d052 31408+ return err;
1facf9fc 31409+}
31410+
31411+/* ---------------------------------------------------------------------- */
31412+
31413+static struct seq_file *au_seq(char *p, ssize_t len)
31414+{
31415+ struct seq_file *seq;
31416+
31417+ seq = kzalloc(sizeof(*seq), GFP_NOFS);
31418+ if (seq) {
31419+ /* mutex_init(&seq.lock); */
31420+ seq->buf = p;
31421+ seq->size = len;
31422+ return seq; /* success */
31423+ }
31424+
31425+ seq = ERR_PTR(-ENOMEM);
31426+ return seq;
31427+}
31428+
392086de
AM
31429+#define SysaufsBr_PREFIX "br"
31430+#define SysaufsBrid_PREFIX "brid"
1facf9fc 31431+
31432+/* todo: file size may exceed PAGE_SIZE */
31433+ssize_t sysaufs_si_show(struct kobject *kobj, struct attribute *attr,
1308ab2a 31434+ char *buf)
1facf9fc 31435+{
31436+ ssize_t err;
392086de 31437+ int idx;
1facf9fc 31438+ long l;
5afbbe0d 31439+ aufs_bindex_t bbot;
1facf9fc 31440+ struct au_sbinfo *sbinfo;
31441+ struct super_block *sb;
31442+ struct seq_file *seq;
31443+ char *name;
31444+ struct attribute **cattr;
31445+
31446+ sbinfo = container_of(kobj, struct au_sbinfo, si_kobj);
31447+ sb = sbinfo->si_sb;
1308ab2a 31448+
31449+ /*
31450+ * prevent a race condition between sysfs and aufs.
31451+ * for instance, sysfs_file_read() calls sysfs_get_active_two() which
31452+ * prohibits maintaining the sysfs entries.
31453+ * hew we acquire read lock after sysfs_get_active_two().
31454+ * on the other hand, the remount process may maintain the sysfs/aufs
31455+ * entries after acquiring write lock.
31456+ * it can cause a deadlock.
31457+ * simply we gave up processing read here.
31458+ */
31459+ err = -EBUSY;
31460+ if (unlikely(!si_noflush_read_trylock(sb)))
31461+ goto out;
1facf9fc 31462+
31463+ seq = au_seq(buf, PAGE_SIZE);
31464+ err = PTR_ERR(seq);
31465+ if (IS_ERR(seq))
1308ab2a 31466+ goto out_unlock;
1facf9fc 31467+
31468+ name = (void *)attr->name;
31469+ cattr = sysaufs_si_attrs;
31470+ while (*cattr) {
31471+ if (!strcmp(name, (*cattr)->name)) {
31472+ err = container_of(*cattr, struct sysaufs_si_attr, attr)
31473+ ->show(seq, sb);
31474+ goto out_seq;
31475+ }
31476+ cattr++;
31477+ }
31478+
392086de
AM
31479+ if (!strncmp(name, SysaufsBrid_PREFIX,
31480+ sizeof(SysaufsBrid_PREFIX) - 1)) {
31481+ idx = AuBrSysfs_BRID;
31482+ name += sizeof(SysaufsBrid_PREFIX) - 1;
31483+ } else if (!strncmp(name, SysaufsBr_PREFIX,
31484+ sizeof(SysaufsBr_PREFIX) - 1)) {
31485+ idx = AuBrSysfs_BR;
1facf9fc 31486+ name += sizeof(SysaufsBr_PREFIX) - 1;
392086de
AM
31487+ } else
31488+ BUG();
31489+
31490+ err = kstrtol(name, 10, &l);
31491+ if (!err) {
5afbbe0d
AM
31492+ bbot = au_sbbot(sb);
31493+ if (l <= bbot)
392086de
AM
31494+ err = sysaufs_si_br(seq, sb, (aufs_bindex_t)l, idx);
31495+ else
31496+ err = -ENOENT;
1facf9fc 31497+ }
1facf9fc 31498+
4f0767ce 31499+out_seq:
1facf9fc 31500+ if (!err) {
31501+ err = seq->count;
31502+ /* sysfs limit */
31503+ if (unlikely(err == PAGE_SIZE))
31504+ err = -EFBIG;
31505+ }
9f237c51 31506+ au_kfree_rcu(seq);
4f0767ce 31507+out_unlock:
1facf9fc 31508+ si_read_unlock(sb);
4f0767ce 31509+out:
1facf9fc 31510+ return err;
31511+}
31512+
31513+/* ---------------------------------------------------------------------- */
31514+
076b876e
AM
31515+static int au_brinfo(struct super_block *sb, union aufs_brinfo __user *arg)
31516+{
31517+ int err;
31518+ int16_t brid;
5afbbe0d 31519+ aufs_bindex_t bindex, bbot;
076b876e
AM
31520+ size_t sz;
31521+ char *buf;
31522+ struct seq_file *seq;
31523+ struct au_branch *br;
31524+
31525+ si_read_lock(sb, AuLock_FLUSH);
5afbbe0d
AM
31526+ bbot = au_sbbot(sb);
31527+ err = bbot + 1;
076b876e
AM
31528+ if (!arg)
31529+ goto out;
31530+
31531+ err = -ENOMEM;
31532+ buf = (void *)__get_free_page(GFP_NOFS);
31533+ if (unlikely(!buf))
31534+ goto out;
31535+
31536+ seq = au_seq(buf, PAGE_SIZE);
31537+ err = PTR_ERR(seq);
31538+ if (IS_ERR(seq))
31539+ goto out_buf;
31540+
31541+ sz = sizeof(*arg) - offsetof(union aufs_brinfo, path);
5afbbe0d 31542+ for (bindex = 0; bindex <= bbot; bindex++, arg++) {
ba1aed25
AM
31543+ /* VERIFY_WRITE */
31544+ err = !access_ok(arg, sizeof(*arg));
076b876e
AM
31545+ if (unlikely(err))
31546+ break;
31547+
31548+ br = au_sbr(sb, bindex);
31549+ brid = br->br_id;
31550+ BUILD_BUG_ON(sizeof(brid) != sizeof(arg->id));
31551+ err = __put_user(brid, &arg->id);
31552+ if (unlikely(err))
31553+ break;
31554+
31555+ BUILD_BUG_ON(sizeof(br->br_perm) != sizeof(arg->perm));
31556+ err = __put_user(br->br_perm, &arg->perm);
31557+ if (unlikely(err))
31558+ break;
31559+
79b8bda9
AM
31560+ err = au_seq_path(seq, &br->br_path);
31561+ if (unlikely(err))
31562+ break;
31563+ seq_putc(seq, '\0');
31564+ if (!seq_has_overflowed(seq)) {
076b876e
AM
31565+ err = copy_to_user(arg->path, seq->buf, seq->count);
31566+ seq->count = 0;
31567+ if (unlikely(err))
31568+ break;
31569+ } else {
31570+ err = -E2BIG;
31571+ goto out_seq;
31572+ }
31573+ }
31574+ if (unlikely(err))
31575+ err = -EFAULT;
31576+
31577+out_seq:
9f237c51 31578+ au_kfree_rcu(seq);
076b876e 31579+out_buf:
1c60b727 31580+ free_page((unsigned long)buf);
076b876e
AM
31581+out:
31582+ si_read_unlock(sb);
31583+ return err;
31584+}
31585+
31586+long au_brinfo_ioctl(struct file *file, unsigned long arg)
31587+{
2000de60 31588+ return au_brinfo(file->f_path.dentry->d_sb, (void __user *)arg);
076b876e
AM
31589+}
31590+
31591+#ifdef CONFIG_COMPAT
31592+long au_brinfo_compat_ioctl(struct file *file, unsigned long arg)
31593+{
2000de60 31594+ return au_brinfo(file->f_path.dentry->d_sb, compat_ptr(arg));
076b876e
AM
31595+}
31596+#endif
31597+
31598+/* ---------------------------------------------------------------------- */
31599+
1facf9fc 31600+void sysaufs_br_init(struct au_branch *br)
31601+{
392086de
AM
31602+ int i;
31603+ struct au_brsysfs *br_sysfs;
31604+ struct attribute *attr;
4a4d8108 31605+
392086de
AM
31606+ br_sysfs = br->br_sysfs;
31607+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
31608+ attr = &br_sysfs->attr;
31609+ sysfs_attr_init(attr);
31610+ attr->name = br_sysfs->name;
cd7a4cd9 31611+ attr->mode = 0444;
392086de
AM
31612+ br_sysfs++;
31613+ }
1facf9fc 31614+}
31615+
31616+void sysaufs_brs_del(struct super_block *sb, aufs_bindex_t bindex)
31617+{
31618+ struct au_branch *br;
31619+ struct kobject *kobj;
392086de
AM
31620+ struct au_brsysfs *br_sysfs;
31621+ int i;
5afbbe0d 31622+ aufs_bindex_t bbot;
1facf9fc 31623+
1facf9fc 31624+ if (!sysaufs_brs)
31625+ return;
31626+
31627+ kobj = &au_sbi(sb)->si_kobj;
5afbbe0d
AM
31628+ bbot = au_sbbot(sb);
31629+ for (; bindex <= bbot; bindex++) {
1facf9fc 31630+ br = au_sbr(sb, bindex);
392086de
AM
31631+ br_sysfs = br->br_sysfs;
31632+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
31633+ sysfs_remove_file(kobj, &br_sysfs->attr);
31634+ br_sysfs++;
31635+ }
1facf9fc 31636+ }
31637+}
31638+
31639+void sysaufs_brs_add(struct super_block *sb, aufs_bindex_t bindex)
31640+{
392086de 31641+ int err, i;
5afbbe0d 31642+ aufs_bindex_t bbot;
1facf9fc 31643+ struct kobject *kobj;
31644+ struct au_branch *br;
392086de 31645+ struct au_brsysfs *br_sysfs;
1facf9fc 31646+
1facf9fc 31647+ if (!sysaufs_brs)
31648+ return;
31649+
31650+ kobj = &au_sbi(sb)->si_kobj;
5afbbe0d
AM
31651+ bbot = au_sbbot(sb);
31652+ for (; bindex <= bbot; bindex++) {
1facf9fc 31653+ br = au_sbr(sb, bindex);
392086de
AM
31654+ br_sysfs = br->br_sysfs;
31655+ snprintf(br_sysfs[AuBrSysfs_BR].name, sizeof(br_sysfs->name),
31656+ SysaufsBr_PREFIX "%d", bindex);
31657+ snprintf(br_sysfs[AuBrSysfs_BRID].name, sizeof(br_sysfs->name),
31658+ SysaufsBrid_PREFIX "%d", bindex);
31659+ for (i = 0; i < ARRAY_SIZE(br->br_sysfs); i++) {
31660+ err = sysfs_create_file(kobj, &br_sysfs->attr);
31661+ if (unlikely(err))
31662+ pr_warn("failed %s under sysfs(%d)\n",
31663+ br_sysfs->name, err);
31664+ br_sysfs++;
31665+ }
1facf9fc 31666+ }
31667+}
7f207e10 31668diff -urN /usr/share/empty/fs/aufs/sysrq.c linux/fs/aufs/sysrq.c
eca34b5c 31669--- /usr/share/empty/fs/aufs/sysrq.c 1970-01-01 01:00:00.000000000 +0100
016522bc 31670+++ linux/fs/aufs/sysrq.c 2020-01-27 10:57:18.178871751 +0100
43982f53 31671@@ -0,0 +1,149 @@
cd7a4cd9 31672+// SPDX-License-Identifier: GPL-2.0
1facf9fc 31673+/*
016522bc 31674+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 31675+ *
31676+ * This program, aufs is free software; you can redistribute it and/or modify
31677+ * it under the terms of the GNU General Public License as published by
31678+ * the Free Software Foundation; either version 2 of the License, or
31679+ * (at your option) any later version.
dece6358
AM
31680+ *
31681+ * This program is distributed in the hope that it will be useful,
31682+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31683+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31684+ * GNU General Public License for more details.
31685+ *
31686+ * You should have received a copy of the GNU General Public License
523b37e3 31687+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31688+ */
31689+
31690+/*
acd2b654 31691+ * magic sysrq handler
1facf9fc 31692+ */
31693+
1facf9fc 31694+/* #include <linux/sysrq.h> */
027c5e7a 31695+#include <linux/writeback.h>
1facf9fc 31696+#include "aufs.h"
31697+
31698+/* ---------------------------------------------------------------------- */
31699+
31700+static void sysrq_sb(struct super_block *sb)
31701+{
31702+ char *plevel;
31703+ struct au_sbinfo *sbinfo;
31704+ struct file *file;
8b6a4947
AM
31705+ struct hlist_bl_head *files;
31706+ struct hlist_bl_node *pos;
523b37e3 31707+ struct au_finfo *finfo;
43982f53 31708+ struct inode *i;
1facf9fc 31709+
31710+ plevel = au_plevel;
31711+ au_plevel = KERN_WARNING;
1facf9fc 31712+
4a4d8108 31713+ /* since we define pr_fmt, call printk directly */
c06a8ce3
AM
31714+#define pr(str) printk(KERN_WARNING AUFS_NAME ": " str)
31715+
31716+ sbinfo = au_sbi(sb);
4a4d8108 31717+ printk(KERN_WARNING "si=%lx\n", sysaufs_si_id(sbinfo));
c06a8ce3 31718+ pr("superblock\n");
1facf9fc 31719+ au_dpri_sb(sb);
027c5e7a 31720+
43982f53 31721+#if 0 /* reserved */
027c5e7a
AM
31722+ do {
31723+ int err, i, j, ndentry;
31724+ struct au_dcsub_pages dpages;
31725+ struct au_dpage *dpage;
31726+
31727+ err = au_dpages_init(&dpages, GFP_ATOMIC);
31728+ if (unlikely(err))
31729+ break;
31730+ err = au_dcsub_pages(&dpages, sb->s_root, NULL, NULL);
31731+ if (!err)
31732+ for (i = 0; i < dpages.ndpage; i++) {
31733+ dpage = dpages.dpages + i;
31734+ ndentry = dpage->ndentry;
31735+ for (j = 0; j < ndentry; j++)
31736+ au_dpri_dentry(dpage->dentries[j]);
31737+ }
31738+ au_dpages_free(&dpages);
31739+ } while (0);
31740+#endif
31741+
43982f53
AM
31742+ pr("isolated inode\n");
31743+ spin_lock(&sb->s_inode_list_lock);
31744+ list_for_each_entry(i, &sb->s_inodes, i_sb_list) {
31745+ spin_lock(&i->i_lock);
31746+ if (hlist_empty(&i->i_dentry))
31747+ au_dpri_inode(i);
31748+ spin_unlock(&i->i_lock);
027c5e7a 31749+ }
43982f53
AM
31750+ spin_unlock(&sb->s_inode_list_lock);
31751+
c06a8ce3 31752+ pr("files\n");
523b37e3 31753+ files = &au_sbi(sb)->si_files;
8b6a4947
AM
31754+ hlist_bl_lock(files);
31755+ hlist_bl_for_each_entry(finfo, pos, files, fi_hlist) {
4a4d8108 31756+ umode_t mode;
076b876e 31757+
523b37e3 31758+ file = finfo->fi_file;
c06a8ce3 31759+ mode = file_inode(file)->i_mode;
38d290e6 31760+ if (!special_file(mode))
1facf9fc 31761+ au_dpri_file(file);
523b37e3 31762+ }
8b6a4947 31763+ hlist_bl_unlock(files);
c06a8ce3 31764+ pr("done\n");
1facf9fc 31765+
c06a8ce3 31766+#undef pr
1facf9fc 31767+ au_plevel = plevel;
1facf9fc 31768+}
31769+
31770+/* ---------------------------------------------------------------------- */
31771+
31772+/* module parameter */
31773+static char *aufs_sysrq_key = "a";
cd7a4cd9 31774+module_param_named(sysrq, aufs_sysrq_key, charp, 0444);
1facf9fc 31775+MODULE_PARM_DESC(sysrq, "MagicSysRq key for " AUFS_NAME);
31776+
0c5527e5 31777+static void au_sysrq(int key __maybe_unused)
1facf9fc 31778+{
1facf9fc 31779+ struct au_sbinfo *sbinfo;
8b6a4947 31780+ struct hlist_bl_node *pos;
1facf9fc 31781+
027c5e7a 31782+ lockdep_off();
53392da6 31783+ au_sbilist_lock();
8b6a4947 31784+ hlist_bl_for_each_entry(sbinfo, pos, &au_sbilist, si_list)
1facf9fc 31785+ sysrq_sb(sbinfo->si_sb);
53392da6 31786+ au_sbilist_unlock();
027c5e7a 31787+ lockdep_on();
1facf9fc 31788+}
31789+
31790+static struct sysrq_key_op au_sysrq_op = {
31791+ .handler = au_sysrq,
31792+ .help_msg = "Aufs",
31793+ .action_msg = "Aufs",
31794+ .enable_mask = SYSRQ_ENABLE_DUMP
31795+};
31796+
31797+/* ---------------------------------------------------------------------- */
31798+
31799+int __init au_sysrq_init(void)
31800+{
31801+ int err;
31802+ char key;
31803+
31804+ err = -1;
31805+ key = *aufs_sysrq_key;
31806+ if ('a' <= key && key <= 'z')
31807+ err = register_sysrq_key(key, &au_sysrq_op);
31808+ if (unlikely(err))
4a4d8108 31809+ pr_err("err %d, sysrq=%c\n", err, key);
1facf9fc 31810+ return err;
31811+}
31812+
31813+void au_sysrq_fin(void)
31814+{
31815+ int err;
076b876e 31816+
1facf9fc 31817+ err = unregister_sysrq_key(*aufs_sysrq_key, &au_sysrq_op);
31818+ if (unlikely(err))
4a4d8108 31819+ pr_err("err %d (ignored)\n", err);
1facf9fc 31820+}
7f207e10 31821diff -urN /usr/share/empty/fs/aufs/vdir.c linux/fs/aufs/vdir.c
eca34b5c 31822--- /usr/share/empty/fs/aufs/vdir.c 1970-01-01 01:00:00.000000000 +0100
016522bc 31823+++ linux/fs/aufs/vdir.c 2020-01-27 10:57:18.178871751 +0100
eca801bf 31824@@ -0,0 +1,896 @@
cd7a4cd9 31825+// SPDX-License-Identifier: GPL-2.0
1facf9fc 31826+/*
016522bc 31827+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 31828+ *
31829+ * This program, aufs is free software; you can redistribute it and/or modify
31830+ * it under the terms of the GNU General Public License as published by
31831+ * the Free Software Foundation; either version 2 of the License, or
31832+ * (at your option) any later version.
dece6358
AM
31833+ *
31834+ * This program is distributed in the hope that it will be useful,
31835+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
31836+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31837+ * GNU General Public License for more details.
31838+ *
31839+ * You should have received a copy of the GNU General Public License
523b37e3 31840+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 31841+ */
31842+
31843+/*
31844+ * virtual or vertical directory
31845+ */
31846+
eca801bf 31847+#include <linux/iversion.h>
1facf9fc 31848+#include "aufs.h"
31849+
dece6358 31850+static unsigned int calc_size(int nlen)
1facf9fc 31851+{
dece6358 31852+ return ALIGN(sizeof(struct au_vdir_de) + nlen, sizeof(ino_t));
1facf9fc 31853+}
31854+
31855+static int set_deblk_end(union au_vdir_deblk_p *p,
31856+ union au_vdir_deblk_p *deblk_end)
31857+{
31858+ if (calc_size(0) <= deblk_end->deblk - p->deblk) {
31859+ p->de->de_str.len = 0;
31860+ /* smp_mb(); */
31861+ return 0;
31862+ }
31863+ return -1; /* error */
31864+}
31865+
31866+/* returns true or false */
31867+static int is_deblk_end(union au_vdir_deblk_p *p,
31868+ union au_vdir_deblk_p *deblk_end)
31869+{
31870+ if (calc_size(0) <= deblk_end->deblk - p->deblk)
31871+ return !p->de->de_str.len;
31872+ return 1;
31873+}
31874+
31875+static unsigned char *last_deblk(struct au_vdir *vdir)
31876+{
31877+ return vdir->vd_deblk[vdir->vd_nblk - 1];
31878+}
31879+
31880+/* ---------------------------------------------------------------------- */
31881+
79b8bda9 31882+/* estimate the appropriate size for name hash table */
1308ab2a 31883+unsigned int au_rdhash_est(loff_t sz)
31884+{
31885+ unsigned int n;
31886+
31887+ n = UINT_MAX;
31888+ sz >>= 10;
31889+ if (sz < n)
31890+ n = sz;
31891+ if (sz < AUFS_RDHASH_DEF)
31892+ n = AUFS_RDHASH_DEF;
4a4d8108 31893+ /* pr_info("n %u\n", n); */
1308ab2a 31894+ return n;
31895+}
31896+
1facf9fc 31897+/*
31898+ * the allocated memory has to be freed by
dece6358 31899+ * au_nhash_wh_free() or au_nhash_de_free().
1facf9fc 31900+ */
dece6358 31901+int au_nhash_alloc(struct au_nhash *nhash, unsigned int num_hash, gfp_t gfp)
1facf9fc 31902+{
1facf9fc 31903+ struct hlist_head *head;
dece6358 31904+ unsigned int u;
076b876e 31905+ size_t sz;
1facf9fc 31906+
076b876e
AM
31907+ sz = sizeof(*nhash->nh_head) * num_hash;
31908+ head = kmalloc(sz, gfp);
dece6358
AM
31909+ if (head) {
31910+ nhash->nh_num = num_hash;
31911+ nhash->nh_head = head;
31912+ for (u = 0; u < num_hash; u++)
1facf9fc 31913+ INIT_HLIST_HEAD(head++);
dece6358 31914+ return 0; /* success */
1facf9fc 31915+ }
1facf9fc 31916+
dece6358 31917+ return -ENOMEM;
1facf9fc 31918+}
31919+
dece6358
AM
31920+static void nhash_count(struct hlist_head *head)
31921+{
43982f53 31922+#if 0 /* debugging */
dece6358
AM
31923+ unsigned long n;
31924+ struct hlist_node *pos;
31925+
31926+ n = 0;
31927+ hlist_for_each(pos, head)
31928+ n++;
4a4d8108 31929+ pr_info("%lu\n", n);
dece6358
AM
31930+#endif
31931+}
31932+
31933+static void au_nhash_wh_do_free(struct hlist_head *head)
1facf9fc 31934+{
c06a8ce3
AM
31935+ struct au_vdir_wh *pos;
31936+ struct hlist_node *node;
1facf9fc 31937+
c06a8ce3 31938+ hlist_for_each_entry_safe(pos, node, head, wh_hash)
9f237c51 31939+ au_kfree_rcu(pos);
1facf9fc 31940+}
31941+
dece6358 31942+static void au_nhash_de_do_free(struct hlist_head *head)
1facf9fc 31943+{
c06a8ce3
AM
31944+ struct au_vdir_dehstr *pos;
31945+ struct hlist_node *node;
1facf9fc 31946+
c06a8ce3 31947+ hlist_for_each_entry_safe(pos, node, head, hash)
1c60b727 31948+ au_cache_free_vdir_dehstr(pos);
1facf9fc 31949+}
31950+
dece6358
AM
31951+static void au_nhash_do_free(struct au_nhash *nhash,
31952+ void (*free)(struct hlist_head *head))
1facf9fc 31953+{
1308ab2a 31954+ unsigned int n;
1facf9fc 31955+ struct hlist_head *head;
1facf9fc 31956+
dece6358 31957+ n = nhash->nh_num;
1308ab2a 31958+ if (!n)
31959+ return;
31960+
dece6358 31961+ head = nhash->nh_head;
1308ab2a 31962+ while (n-- > 0) {
dece6358
AM
31963+ nhash_count(head);
31964+ free(head++);
1facf9fc 31965+ }
9f237c51 31966+ au_kfree_try_rcu(nhash->nh_head);
1facf9fc 31967+}
31968+
dece6358 31969+void au_nhash_wh_free(struct au_nhash *whlist)
1facf9fc 31970+{
dece6358
AM
31971+ au_nhash_do_free(whlist, au_nhash_wh_do_free);
31972+}
1facf9fc 31973+
dece6358
AM
31974+static void au_nhash_de_free(struct au_nhash *delist)
31975+{
31976+ au_nhash_do_free(delist, au_nhash_de_do_free);
1facf9fc 31977+}
31978+
31979+/* ---------------------------------------------------------------------- */
31980+
31981+int au_nhash_test_longer_wh(struct au_nhash *whlist, aufs_bindex_t btgt,
31982+ int limit)
31983+{
31984+ int num;
31985+ unsigned int u, n;
31986+ struct hlist_head *head;
c06a8ce3 31987+ struct au_vdir_wh *pos;
1facf9fc 31988+
31989+ num = 0;
31990+ n = whlist->nh_num;
31991+ head = whlist->nh_head;
1308ab2a 31992+ for (u = 0; u < n; u++, head++)
c06a8ce3
AM
31993+ hlist_for_each_entry(pos, head, wh_hash)
31994+ if (pos->wh_bindex == btgt && ++num > limit)
1facf9fc 31995+ return 1;
1facf9fc 31996+ return 0;
31997+}
31998+
31999+static struct hlist_head *au_name_hash(struct au_nhash *nhash,
dece6358 32000+ unsigned char *name,
1facf9fc 32001+ unsigned int len)
32002+{
dece6358
AM
32003+ unsigned int v;
32004+ /* const unsigned int magic_bit = 12; */
32005+
1308ab2a 32006+ AuDebugOn(!nhash->nh_num || !nhash->nh_head);
32007+
dece6358 32008+ v = 0;
f0c0a007
AM
32009+ if (len > 8)
32010+ len = 8;
dece6358
AM
32011+ while (len--)
32012+ v += *name++;
32013+ /* v = hash_long(v, magic_bit); */
32014+ v %= nhash->nh_num;
32015+ return nhash->nh_head + v;
32016+}
32017+
32018+static int au_nhash_test_name(struct au_vdir_destr *str, const char *name,
32019+ int nlen)
32020+{
32021+ return str->len == nlen && !memcmp(str->name, name, nlen);
1facf9fc 32022+}
32023+
32024+/* returns found or not */
dece6358 32025+int au_nhash_test_known_wh(struct au_nhash *whlist, char *name, int nlen)
1facf9fc 32026+{
32027+ struct hlist_head *head;
c06a8ce3 32028+ struct au_vdir_wh *pos;
1facf9fc 32029+ struct au_vdir_destr *str;
32030+
dece6358 32031+ head = au_name_hash(whlist, name, nlen);
c06a8ce3
AM
32032+ hlist_for_each_entry(pos, head, wh_hash) {
32033+ str = &pos->wh_str;
1facf9fc 32034+ AuDbg("%.*s\n", str->len, str->name);
dece6358
AM
32035+ if (au_nhash_test_name(str, name, nlen))
32036+ return 1;
32037+ }
32038+ return 0;
32039+}
32040+
32041+/* returns found(true) or not */
32042+static int test_known(struct au_nhash *delist, char *name, int nlen)
32043+{
32044+ struct hlist_head *head;
c06a8ce3 32045+ struct au_vdir_dehstr *pos;
dece6358
AM
32046+ struct au_vdir_destr *str;
32047+
32048+ head = au_name_hash(delist, name, nlen);
c06a8ce3
AM
32049+ hlist_for_each_entry(pos, head, hash) {
32050+ str = pos->str;
dece6358
AM
32051+ AuDbg("%.*s\n", str->len, str->name);
32052+ if (au_nhash_test_name(str, name, nlen))
1facf9fc 32053+ return 1;
32054+ }
32055+ return 0;
32056+}
32057+
dece6358
AM
32058+static void au_shwh_init_wh(struct au_vdir_wh *wh, ino_t ino,
32059+ unsigned char d_type)
32060+{
32061+#ifdef CONFIG_AUFS_SHWH
32062+ wh->wh_ino = ino;
32063+ wh->wh_type = d_type;
32064+#endif
32065+}
32066+
32067+/* ---------------------------------------------------------------------- */
32068+
32069+int au_nhash_append_wh(struct au_nhash *whlist, char *name, int nlen, ino_t ino,
32070+ unsigned int d_type, aufs_bindex_t bindex,
32071+ unsigned char shwh)
1facf9fc 32072+{
32073+ int err;
32074+ struct au_vdir_destr *str;
32075+ struct au_vdir_wh *wh;
32076+
dece6358 32077+ AuDbg("%.*s\n", nlen, name);
1308ab2a 32078+ AuDebugOn(!whlist->nh_num || !whlist->nh_head);
32079+
1facf9fc 32080+ err = -ENOMEM;
dece6358 32081+ wh = kmalloc(sizeof(*wh) + nlen, GFP_NOFS);
1facf9fc 32082+ if (unlikely(!wh))
32083+ goto out;
32084+
32085+ err = 0;
32086+ wh->wh_bindex = bindex;
dece6358
AM
32087+ if (shwh)
32088+ au_shwh_init_wh(wh, ino, d_type);
1facf9fc 32089+ str = &wh->wh_str;
dece6358
AM
32090+ str->len = nlen;
32091+ memcpy(str->name, name, nlen);
32092+ hlist_add_head(&wh->wh_hash, au_name_hash(whlist, name, nlen));
1facf9fc 32093+ /* smp_mb(); */
32094+
4f0767ce 32095+out:
1facf9fc 32096+ return err;
32097+}
32098+
1facf9fc 32099+static int append_deblk(struct au_vdir *vdir)
32100+{
32101+ int err;
dece6358 32102+ unsigned long ul;
1facf9fc 32103+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
32104+ union au_vdir_deblk_p p, deblk_end;
32105+ unsigned char **o;
32106+
32107+ err = -ENOMEM;
e2f27e51
AM
32108+ o = au_krealloc(vdir->vd_deblk, sizeof(*o) * (vdir->vd_nblk + 1),
32109+ GFP_NOFS, /*may_shrink*/0);
1facf9fc 32110+ if (unlikely(!o))
32111+ goto out;
32112+
32113+ vdir->vd_deblk = o;
32114+ p.deblk = kmalloc(deblk_sz, GFP_NOFS);
32115+ if (p.deblk) {
32116+ ul = vdir->vd_nblk++;
32117+ vdir->vd_deblk[ul] = p.deblk;
32118+ vdir->vd_last.ul = ul;
32119+ vdir->vd_last.p.deblk = p.deblk;
32120+ deblk_end.deblk = p.deblk + deblk_sz;
32121+ err = set_deblk_end(&p, &deblk_end);
32122+ }
32123+
4f0767ce 32124+out:
1facf9fc 32125+ return err;
32126+}
32127+
dece6358
AM
32128+static int append_de(struct au_vdir *vdir, char *name, int nlen, ino_t ino,
32129+ unsigned int d_type, struct au_nhash *delist)
32130+{
32131+ int err;
32132+ unsigned int sz;
32133+ const unsigned int deblk_sz = vdir->vd_deblk_sz;
32134+ union au_vdir_deblk_p p, *room, deblk_end;
32135+ struct au_vdir_dehstr *dehstr;
32136+
32137+ p.deblk = last_deblk(vdir);
32138+ deblk_end.deblk = p.deblk + deblk_sz;
32139+ room = &vdir->vd_last.p;
32140+ AuDebugOn(room->deblk < p.deblk || deblk_end.deblk <= room->deblk
32141+ || !is_deblk_end(room, &deblk_end));
32142+
32143+ sz = calc_size(nlen);
32144+ if (unlikely(sz > deblk_end.deblk - room->deblk)) {
32145+ err = append_deblk(vdir);
32146+ if (unlikely(err))
32147+ goto out;
32148+
32149+ p.deblk = last_deblk(vdir);
32150+ deblk_end.deblk = p.deblk + deblk_sz;
32151+ /* smp_mb(); */
32152+ AuDebugOn(room->deblk != p.deblk);
32153+ }
32154+
32155+ err = -ENOMEM;
4a4d8108 32156+ dehstr = au_cache_alloc_vdir_dehstr();
dece6358
AM
32157+ if (unlikely(!dehstr))
32158+ goto out;
32159+
32160+ dehstr->str = &room->de->de_str;
32161+ hlist_add_head(&dehstr->hash, au_name_hash(delist, name, nlen));
32162+ room->de->de_ino = ino;
32163+ room->de->de_type = d_type;
32164+ room->de->de_str.len = nlen;
32165+ memcpy(room->de->de_str.name, name, nlen);
32166+
32167+ err = 0;
32168+ room->deblk += sz;
32169+ if (unlikely(set_deblk_end(room, &deblk_end)))
32170+ err = append_deblk(vdir);
32171+ /* smp_mb(); */
32172+
4f0767ce 32173+out:
dece6358
AM
32174+ return err;
32175+}
32176+
32177+/* ---------------------------------------------------------------------- */
32178+
1c60b727 32179+void au_vdir_free(struct au_vdir *vdir)
dece6358
AM
32180+{
32181+ unsigned char **deblk;
32182+
32183+ deblk = vdir->vd_deblk;
1c60b727 32184+ while (vdir->vd_nblk--)
9f237c51
AM
32185+ au_kfree_try_rcu(*deblk++);
32186+ au_kfree_try_rcu(vdir->vd_deblk);
1c60b727 32187+ au_cache_free_vdir(vdir);
dece6358
AM
32188+}
32189+
1308ab2a 32190+static struct au_vdir *alloc_vdir(struct file *file)
1facf9fc 32191+{
32192+ struct au_vdir *vdir;
1308ab2a 32193+ struct super_block *sb;
1facf9fc 32194+ int err;
32195+
2000de60 32196+ sb = file->f_path.dentry->d_sb;
dece6358
AM
32197+ SiMustAnyLock(sb);
32198+
1facf9fc 32199+ err = -ENOMEM;
32200+ vdir = au_cache_alloc_vdir();
32201+ if (unlikely(!vdir))
32202+ goto out;
32203+
32204+ vdir->vd_deblk = kzalloc(sizeof(*vdir->vd_deblk), GFP_NOFS);
32205+ if (unlikely(!vdir->vd_deblk))
32206+ goto out_free;
32207+
32208+ vdir->vd_deblk_sz = au_sbi(sb)->si_rdblk;
1308ab2a 32209+ if (!vdir->vd_deblk_sz) {
79b8bda9 32210+ /* estimate the appropriate size for deblk */
1308ab2a 32211+ vdir->vd_deblk_sz = au_dir_size(file, /*dentry*/NULL);
4a4d8108 32212+ /* pr_info("vd_deblk_sz %u\n", vdir->vd_deblk_sz); */
1308ab2a 32213+ }
1facf9fc 32214+ vdir->vd_nblk = 0;
32215+ vdir->vd_version = 0;
32216+ vdir->vd_jiffy = 0;
32217+ err = append_deblk(vdir);
32218+ if (!err)
32219+ return vdir; /* success */
32220+
9f237c51 32221+ au_kfree_try_rcu(vdir->vd_deblk);
1facf9fc 32222+
4f0767ce 32223+out_free:
1c60b727 32224+ au_cache_free_vdir(vdir);
4f0767ce 32225+out:
1facf9fc 32226+ vdir = ERR_PTR(err);
32227+ return vdir;
32228+}
32229+
32230+static int reinit_vdir(struct au_vdir *vdir)
32231+{
32232+ int err;
32233+ union au_vdir_deblk_p p, deblk_end;
32234+
32235+ while (vdir->vd_nblk > 1) {
9f237c51 32236+ au_kfree_try_rcu(vdir->vd_deblk[vdir->vd_nblk - 1]);
1facf9fc 32237+ /* vdir->vd_deblk[vdir->vd_nblk - 1] = NULL; */
32238+ vdir->vd_nblk--;
32239+ }
32240+ p.deblk = vdir->vd_deblk[0];
32241+ deblk_end.deblk = p.deblk + vdir->vd_deblk_sz;
32242+ err = set_deblk_end(&p, &deblk_end);
32243+ /* keep vd_dblk_sz */
32244+ vdir->vd_last.ul = 0;
32245+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
32246+ vdir->vd_version = 0;
32247+ vdir->vd_jiffy = 0;
32248+ /* smp_mb(); */
32249+ return err;
32250+}
32251+
32252+/* ---------------------------------------------------------------------- */
32253+
1facf9fc 32254+#define AuFillVdir_CALLED 1
32255+#define AuFillVdir_WHABLE (1 << 1)
dece6358 32256+#define AuFillVdir_SHWH (1 << 2)
1facf9fc 32257+#define au_ftest_fillvdir(flags, name) ((flags) & AuFillVdir_##name)
7f207e10
AM
32258+#define au_fset_fillvdir(flags, name) \
32259+ do { (flags) |= AuFillVdir_##name; } while (0)
32260+#define au_fclr_fillvdir(flags, name) \
32261+ do { (flags) &= ~AuFillVdir_##name; } while (0)
1facf9fc 32262+
dece6358
AM
32263+#ifndef CONFIG_AUFS_SHWH
32264+#undef AuFillVdir_SHWH
32265+#define AuFillVdir_SHWH 0
32266+#endif
32267+
1facf9fc 32268+struct fillvdir_arg {
392086de 32269+ struct dir_context ctx;
1facf9fc 32270+ struct file *file;
32271+ struct au_vdir *vdir;
dece6358
AM
32272+ struct au_nhash delist;
32273+ struct au_nhash whlist;
1facf9fc 32274+ aufs_bindex_t bindex;
32275+ unsigned int flags;
32276+ int err;
32277+};
32278+
392086de 32279+static int fillvdir(struct dir_context *ctx, const char *__name, int nlen,
1facf9fc 32280+ loff_t offset __maybe_unused, u64 h_ino,
32281+ unsigned int d_type)
32282+{
392086de 32283+ struct fillvdir_arg *arg = container_of(ctx, struct fillvdir_arg, ctx);
1facf9fc 32284+ char *name = (void *)__name;
32285+ struct super_block *sb;
1facf9fc 32286+ ino_t ino;
dece6358 32287+ const unsigned char shwh = !!au_ftest_fillvdir(arg->flags, SHWH);
1facf9fc 32288+
1facf9fc 32289+ arg->err = 0;
2000de60 32290+ sb = arg->file->f_path.dentry->d_sb;
1facf9fc 32291+ au_fset_fillvdir(arg->flags, CALLED);
32292+ /* smp_mb(); */
dece6358 32293+ if (nlen <= AUFS_WH_PFX_LEN
1facf9fc 32294+ || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
dece6358
AM
32295+ if (test_known(&arg->delist, name, nlen)
32296+ || au_nhash_test_known_wh(&arg->whlist, name, nlen))
32297+ goto out; /* already exists or whiteouted */
1facf9fc 32298+
dece6358 32299+ arg->err = au_ino(sb, arg->bindex, h_ino, d_type, &ino);
4a4d8108
AM
32300+ if (!arg->err) {
32301+ if (unlikely(nlen > AUFS_MAX_NAMELEN))
32302+ d_type = DT_UNKNOWN;
dece6358
AM
32303+ arg->err = append_de(arg->vdir, name, nlen, ino,
32304+ d_type, &arg->delist);
4a4d8108 32305+ }
1facf9fc 32306+ } else if (au_ftest_fillvdir(arg->flags, WHABLE)) {
32307+ name += AUFS_WH_PFX_LEN;
dece6358
AM
32308+ nlen -= AUFS_WH_PFX_LEN;
32309+ if (au_nhash_test_known_wh(&arg->whlist, name, nlen))
32310+ goto out; /* already whiteouted */
1facf9fc 32311+
acd2b654 32312+ ino = 0; /* just to suppress a warning */
dece6358
AM
32313+ if (shwh)
32314+ arg->err = au_wh_ino(sb, arg->bindex, h_ino, d_type,
32315+ &ino);
4a4d8108
AM
32316+ if (!arg->err) {
32317+ if (nlen <= AUFS_MAX_NAMELEN + AUFS_WH_PFX_LEN)
32318+ d_type = DT_UNKNOWN;
1facf9fc 32319+ arg->err = au_nhash_append_wh
dece6358
AM
32320+ (&arg->whlist, name, nlen, ino, d_type,
32321+ arg->bindex, shwh);
4a4d8108 32322+ }
1facf9fc 32323+ }
32324+
4f0767ce 32325+out:
1facf9fc 32326+ if (!arg->err)
32327+ arg->vdir->vd_jiffy = jiffies;
32328+ /* smp_mb(); */
32329+ AuTraceErr(arg->err);
32330+ return arg->err;
32331+}
32332+
dece6358
AM
32333+static int au_handle_shwh(struct super_block *sb, struct au_vdir *vdir,
32334+ struct au_nhash *whlist, struct au_nhash *delist)
32335+{
32336+#ifdef CONFIG_AUFS_SHWH
32337+ int err;
32338+ unsigned int nh, u;
32339+ struct hlist_head *head;
c06a8ce3
AM
32340+ struct au_vdir_wh *pos;
32341+ struct hlist_node *n;
dece6358
AM
32342+ char *p, *o;
32343+ struct au_vdir_destr *destr;
32344+
32345+ AuDebugOn(!au_opt_test(au_mntflags(sb), SHWH));
32346+
32347+ err = -ENOMEM;
537831f9 32348+ o = p = (void *)__get_free_page(GFP_NOFS);
dece6358
AM
32349+ if (unlikely(!p))
32350+ goto out;
32351+
32352+ err = 0;
32353+ nh = whlist->nh_num;
32354+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
32355+ p += AUFS_WH_PFX_LEN;
32356+ for (u = 0; u < nh; u++) {
32357+ head = whlist->nh_head + u;
c06a8ce3
AM
32358+ hlist_for_each_entry_safe(pos, n, head, wh_hash) {
32359+ destr = &pos->wh_str;
dece6358
AM
32360+ memcpy(p, destr->name, destr->len);
32361+ err = append_de(vdir, o, destr->len + AUFS_WH_PFX_LEN,
c06a8ce3 32362+ pos->wh_ino, pos->wh_type, delist);
dece6358
AM
32363+ if (unlikely(err))
32364+ break;
32365+ }
32366+ }
32367+
1c60b727 32368+ free_page((unsigned long)o);
dece6358 32369+
4f0767ce 32370+out:
dece6358
AM
32371+ AuTraceErr(err);
32372+ return err;
32373+#else
32374+ return 0;
32375+#endif
32376+}
32377+
1facf9fc 32378+static int au_do_read_vdir(struct fillvdir_arg *arg)
32379+{
32380+ int err;
dece6358 32381+ unsigned int rdhash;
1facf9fc 32382+ loff_t offset;
5afbbe0d 32383+ aufs_bindex_t bbot, bindex, btop;
dece6358 32384+ unsigned char shwh;
1facf9fc 32385+ struct file *hf, *file;
32386+ struct super_block *sb;
32387+
1facf9fc 32388+ file = arg->file;
2000de60 32389+ sb = file->f_path.dentry->d_sb;
dece6358
AM
32390+ SiMustAnyLock(sb);
32391+
32392+ rdhash = au_sbi(sb)->si_rdhash;
1308ab2a 32393+ if (!rdhash)
32394+ rdhash = au_rdhash_est(au_dir_size(file, /*dentry*/NULL));
dece6358
AM
32395+ err = au_nhash_alloc(&arg->delist, rdhash, GFP_NOFS);
32396+ if (unlikely(err))
1facf9fc 32397+ goto out;
dece6358
AM
32398+ err = au_nhash_alloc(&arg->whlist, rdhash, GFP_NOFS);
32399+ if (unlikely(err))
1facf9fc 32400+ goto out_delist;
32401+
32402+ err = 0;
32403+ arg->flags = 0;
dece6358
AM
32404+ shwh = 0;
32405+ if (au_opt_test(au_mntflags(sb), SHWH)) {
32406+ shwh = 1;
32407+ au_fset_fillvdir(arg->flags, SHWH);
32408+ }
5afbbe0d
AM
32409+ btop = au_fbtop(file);
32410+ bbot = au_fbbot_dir(file);
32411+ for (bindex = btop; !err && bindex <= bbot; bindex++) {
4a4d8108 32412+ hf = au_hf_dir(file, bindex);
1facf9fc 32413+ if (!hf)
32414+ continue;
32415+
32416+ offset = vfsub_llseek(hf, 0, SEEK_SET);
32417+ err = offset;
32418+ if (unlikely(offset))
32419+ break;
32420+
32421+ arg->bindex = bindex;
32422+ au_fclr_fillvdir(arg->flags, WHABLE);
dece6358 32423+ if (shwh
5afbbe0d 32424+ || (bindex != bbot
dece6358 32425+ && au_br_whable(au_sbr_perm(sb, bindex))))
1facf9fc 32426+ au_fset_fillvdir(arg->flags, WHABLE);
32427+ do {
32428+ arg->err = 0;
32429+ au_fclr_fillvdir(arg->flags, CALLED);
32430+ /* smp_mb(); */
392086de 32431+ err = vfsub_iterate_dir(hf, &arg->ctx);
1facf9fc 32432+ if (err >= 0)
32433+ err = arg->err;
32434+ } while (!err && au_ftest_fillvdir(arg->flags, CALLED));
392086de
AM
32435+
32436+ /*
32437+ * dir_relax() may be good for concurrency, but aufs should not
32438+ * use it since it will cause a lockdep problem.
32439+ */
1facf9fc 32440+ }
dece6358
AM
32441+
32442+ if (!err && shwh)
32443+ err = au_handle_shwh(sb, arg->vdir, &arg->whlist, &arg->delist);
32444+
32445+ au_nhash_wh_free(&arg->whlist);
1facf9fc 32446+
4f0767ce 32447+out_delist:
dece6358 32448+ au_nhash_de_free(&arg->delist);
4f0767ce 32449+out:
1facf9fc 32450+ return err;
32451+}
32452+
32453+static int read_vdir(struct file *file, int may_read)
32454+{
32455+ int err;
32456+ unsigned long expire;
32457+ unsigned char do_read;
392086de
AM
32458+ struct fillvdir_arg arg = {
32459+ .ctx = {
2000de60 32460+ .actor = fillvdir
392086de
AM
32461+ }
32462+ };
1facf9fc 32463+ struct inode *inode;
32464+ struct au_vdir *vdir, *allocated;
32465+
32466+ err = 0;
c06a8ce3 32467+ inode = file_inode(file);
1facf9fc 32468+ IMustLock(inode);
5afbbe0d 32469+ IiMustWriteLock(inode);
dece6358
AM
32470+ SiMustAnyLock(inode->i_sb);
32471+
1facf9fc 32472+ allocated = NULL;
32473+ do_read = 0;
32474+ expire = au_sbi(inode->i_sb)->si_rdcache;
32475+ vdir = au_ivdir(inode);
32476+ if (!vdir) {
32477+ do_read = 1;
1308ab2a 32478+ vdir = alloc_vdir(file);
1facf9fc 32479+ err = PTR_ERR(vdir);
32480+ if (IS_ERR(vdir))
32481+ goto out;
32482+ err = 0;
32483+ allocated = vdir;
32484+ } else if (may_read
be118d29 32485+ && (!inode_eq_iversion(inode, vdir->vd_version)
1facf9fc 32486+ || time_after(jiffies, vdir->vd_jiffy + expire))) {
32487+ do_read = 1;
32488+ err = reinit_vdir(vdir);
32489+ if (unlikely(err))
32490+ goto out;
32491+ }
32492+
32493+ if (!do_read)
32494+ return 0; /* success */
32495+
32496+ arg.file = file;
32497+ arg.vdir = vdir;
32498+ err = au_do_read_vdir(&arg);
32499+ if (!err) {
392086de 32500+ /* file->f_pos = 0; */ /* todo: ctx->pos? */
be118d29 32501+ vdir->vd_version = inode_query_iversion(inode);
1facf9fc 32502+ vdir->vd_last.ul = 0;
32503+ vdir->vd_last.p.deblk = vdir->vd_deblk[0];
32504+ if (allocated)
32505+ au_set_ivdir(inode, allocated);
32506+ } else if (allocated)
1c60b727 32507+ au_vdir_free(allocated);
1facf9fc 32508+
4f0767ce 32509+out:
1facf9fc 32510+ return err;
32511+}
32512+
32513+static int copy_vdir(struct au_vdir *tgt, struct au_vdir *src)
32514+{
32515+ int err, rerr;
32516+ unsigned long ul, n;
32517+ const unsigned int deblk_sz = src->vd_deblk_sz;
32518+
32519+ AuDebugOn(tgt->vd_nblk != 1);
32520+
32521+ err = -ENOMEM;
32522+ if (tgt->vd_nblk < src->vd_nblk) {
32523+ unsigned char **p;
32524+
e2f27e51
AM
32525+ p = au_krealloc(tgt->vd_deblk, sizeof(*p) * src->vd_nblk,
32526+ GFP_NOFS, /*may_shrink*/0);
1facf9fc 32527+ if (unlikely(!p))
32528+ goto out;
32529+ tgt->vd_deblk = p;
32530+ }
32531+
1308ab2a 32532+ if (tgt->vd_deblk_sz != deblk_sz) {
32533+ unsigned char *p;
32534+
32535+ tgt->vd_deblk_sz = deblk_sz;
e2f27e51
AM
32536+ p = au_krealloc(tgt->vd_deblk[0], deblk_sz, GFP_NOFS,
32537+ /*may_shrink*/1);
1308ab2a 32538+ if (unlikely(!p))
32539+ goto out;
32540+ tgt->vd_deblk[0] = p;
32541+ }
1facf9fc 32542+ memcpy(tgt->vd_deblk[0], src->vd_deblk[0], deblk_sz);
1facf9fc 32543+ tgt->vd_version = src->vd_version;
32544+ tgt->vd_jiffy = src->vd_jiffy;
32545+
32546+ n = src->vd_nblk;
32547+ for (ul = 1; ul < n; ul++) {
dece6358
AM
32548+ tgt->vd_deblk[ul] = kmemdup(src->vd_deblk[ul], deblk_sz,
32549+ GFP_NOFS);
32550+ if (unlikely(!tgt->vd_deblk[ul]))
1facf9fc 32551+ goto out;
1308ab2a 32552+ tgt->vd_nblk++;
1facf9fc 32553+ }
1308ab2a 32554+ tgt->vd_nblk = n;
32555+ tgt->vd_last.ul = tgt->vd_last.ul;
32556+ tgt->vd_last.p.deblk = tgt->vd_deblk[tgt->vd_last.ul];
32557+ tgt->vd_last.p.deblk += src->vd_last.p.deblk
32558+ - src->vd_deblk[src->vd_last.ul];
1facf9fc 32559+ /* smp_mb(); */
32560+ return 0; /* success */
32561+
4f0767ce 32562+out:
1facf9fc 32563+ rerr = reinit_vdir(tgt);
32564+ BUG_ON(rerr);
32565+ return err;
32566+}
32567+
32568+int au_vdir_init(struct file *file)
32569+{
32570+ int err;
32571+ struct inode *inode;
32572+ struct au_vdir *vdir_cache, *allocated;
32573+
392086de 32574+ /* test file->f_pos here instead of ctx->pos */
1facf9fc 32575+ err = read_vdir(file, !file->f_pos);
32576+ if (unlikely(err))
32577+ goto out;
32578+
32579+ allocated = NULL;
32580+ vdir_cache = au_fvdir_cache(file);
32581+ if (!vdir_cache) {
1308ab2a 32582+ vdir_cache = alloc_vdir(file);
1facf9fc 32583+ err = PTR_ERR(vdir_cache);
32584+ if (IS_ERR(vdir_cache))
32585+ goto out;
32586+ allocated = vdir_cache;
32587+ } else if (!file->f_pos && vdir_cache->vd_version != file->f_version) {
392086de 32588+ /* test file->f_pos here instead of ctx->pos */
1facf9fc 32589+ err = reinit_vdir(vdir_cache);
32590+ if (unlikely(err))
32591+ goto out;
32592+ } else
32593+ return 0; /* success */
32594+
c06a8ce3 32595+ inode = file_inode(file);
1facf9fc 32596+ err = copy_vdir(vdir_cache, au_ivdir(inode));
32597+ if (!err) {
be118d29 32598+ file->f_version = inode_query_iversion(inode);
1facf9fc 32599+ if (allocated)
32600+ au_set_fvdir_cache(file, allocated);
32601+ } else if (allocated)
1c60b727 32602+ au_vdir_free(allocated);
1facf9fc 32603+
4f0767ce 32604+out:
1facf9fc 32605+ return err;
32606+}
32607+
32608+static loff_t calc_offset(struct au_vdir *vdir)
32609+{
32610+ loff_t offset;
32611+ union au_vdir_deblk_p p;
32612+
32613+ p.deblk = vdir->vd_deblk[vdir->vd_last.ul];
32614+ offset = vdir->vd_last.p.deblk - p.deblk;
32615+ offset += vdir->vd_deblk_sz * vdir->vd_last.ul;
32616+ return offset;
32617+}
32618+
32619+/* returns true or false */
392086de 32620+static int seek_vdir(struct file *file, struct dir_context *ctx)
1facf9fc 32621+{
32622+ int valid;
32623+ unsigned int deblk_sz;
32624+ unsigned long ul, n;
32625+ loff_t offset;
32626+ union au_vdir_deblk_p p, deblk_end;
32627+ struct au_vdir *vdir_cache;
32628+
32629+ valid = 1;
32630+ vdir_cache = au_fvdir_cache(file);
32631+ offset = calc_offset(vdir_cache);
32632+ AuDbg("offset %lld\n", offset);
392086de 32633+ if (ctx->pos == offset)
1facf9fc 32634+ goto out;
32635+
32636+ vdir_cache->vd_last.ul = 0;
32637+ vdir_cache->vd_last.p.deblk = vdir_cache->vd_deblk[0];
392086de 32638+ if (!ctx->pos)
1facf9fc 32639+ goto out;
32640+
32641+ valid = 0;
32642+ deblk_sz = vdir_cache->vd_deblk_sz;
392086de 32643+ ul = div64_u64(ctx->pos, deblk_sz);
1facf9fc 32644+ AuDbg("ul %lu\n", ul);
32645+ if (ul >= vdir_cache->vd_nblk)
32646+ goto out;
32647+
32648+ n = vdir_cache->vd_nblk;
32649+ for (; ul < n; ul++) {
32650+ p.deblk = vdir_cache->vd_deblk[ul];
32651+ deblk_end.deblk = p.deblk + deblk_sz;
32652+ offset = ul;
32653+ offset *= deblk_sz;
392086de 32654+ while (!is_deblk_end(&p, &deblk_end) && offset < ctx->pos) {
1facf9fc 32655+ unsigned int l;
32656+
32657+ l = calc_size(p.de->de_str.len);
32658+ offset += l;
32659+ p.deblk += l;
32660+ }
32661+ if (!is_deblk_end(&p, &deblk_end)) {
32662+ valid = 1;
32663+ vdir_cache->vd_last.ul = ul;
32664+ vdir_cache->vd_last.p = p;
32665+ break;
32666+ }
32667+ }
32668+
4f0767ce 32669+out:
1facf9fc 32670+ /* smp_mb(); */
b00004a5
AM
32671+ if (!valid)
32672+ AuDbg("valid %d\n", !valid);
1facf9fc 32673+ return valid;
32674+}
32675+
392086de 32676+int au_vdir_fill_de(struct file *file, struct dir_context *ctx)
1facf9fc 32677+{
1facf9fc 32678+ unsigned int l, deblk_sz;
32679+ union au_vdir_deblk_p deblk_end;
32680+ struct au_vdir *vdir_cache;
32681+ struct au_vdir_de *de;
32682+
392086de 32683+ if (!seek_vdir(file, ctx))
1facf9fc 32684+ return 0;
32685+
acd2b654 32686+ vdir_cache = au_fvdir_cache(file);
1facf9fc 32687+ deblk_sz = vdir_cache->vd_deblk_sz;
32688+ while (1) {
32689+ deblk_end.deblk = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
32690+ deblk_end.deblk += deblk_sz;
32691+ while (!is_deblk_end(&vdir_cache->vd_last.p, &deblk_end)) {
32692+ de = vdir_cache->vd_last.p.de;
32693+ AuDbg("%.*s, off%lld, i%lu, dt%d\n",
392086de 32694+ de->de_str.len, de->de_str.name, ctx->pos,
1facf9fc 32695+ (unsigned long)de->de_ino, de->de_type);
392086de
AM
32696+ if (unlikely(!dir_emit(ctx, de->de_str.name,
32697+ de->de_str.len, de->de_ino,
32698+ de->de_type))) {
1facf9fc 32699+ /* todo: ignore the error caused by udba? */
32700+ /* return err; */
32701+ return 0;
32702+ }
32703+
32704+ l = calc_size(de->de_str.len);
32705+ vdir_cache->vd_last.p.deblk += l;
392086de 32706+ ctx->pos += l;
1facf9fc 32707+ }
32708+ if (vdir_cache->vd_last.ul < vdir_cache->vd_nblk - 1) {
32709+ vdir_cache->vd_last.ul++;
32710+ vdir_cache->vd_last.p.deblk
32711+ = vdir_cache->vd_deblk[vdir_cache->vd_last.ul];
392086de 32712+ ctx->pos = deblk_sz * vdir_cache->vd_last.ul;
1facf9fc 32713+ continue;
32714+ }
32715+ break;
32716+ }
32717+
32718+ /* smp_mb(); */
32719+ return 0;
32720+}
7f207e10 32721diff -urN /usr/share/empty/fs/aufs/vfsub.c linux/fs/aufs/vfsub.c
eca34b5c 32722--- /usr/share/empty/fs/aufs/vfsub.c 1970-01-01 01:00:00.000000000 +0100
016522bc 32723+++ linux/fs/aufs/vfsub.c 2020-01-27 10:57:18.178871751 +0100
acd2b654 32724@@ -0,0 +1,902 @@
cd7a4cd9 32725+// SPDX-License-Identifier: GPL-2.0
1facf9fc 32726+/*
016522bc 32727+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 32728+ *
32729+ * This program, aufs is free software; you can redistribute it and/or modify
32730+ * it under the terms of the GNU General Public License as published by
32731+ * the Free Software Foundation; either version 2 of the License, or
32732+ * (at your option) any later version.
dece6358
AM
32733+ *
32734+ * This program is distributed in the hope that it will be useful,
32735+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
32736+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32737+ * GNU General Public License for more details.
32738+ *
32739+ * You should have received a copy of the GNU General Public License
523b37e3 32740+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 32741+ */
32742+
32743+/*
32744+ * sub-routines for VFS
32745+ */
32746+
8b6a4947 32747+#include <linux/mnt_namespace.h>
dece6358 32748+#include <linux/namei.h>
8cdd5066 32749+#include <linux/nsproxy.h>
dece6358
AM
32750+#include <linux/security.h>
32751+#include <linux/splice.h>
1facf9fc 32752+#include "aufs.h"
32753+
8cdd5066
JR
32754+#ifdef CONFIG_AUFS_BR_FUSE
32755+int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb)
32756+{
8cdd5066
JR
32757+ if (!au_test_fuse(h_sb) || !au_userns)
32758+ return 0;
32759+
8b6a4947 32760+ return is_current_mnt_ns(mnt) ? 0 : -EACCES;
8cdd5066
JR
32761+}
32762+#endif
32763+
a2654f78
AM
32764+int vfsub_sync_filesystem(struct super_block *h_sb, int wait)
32765+{
32766+ int err;
32767+
32768+ lockdep_off();
32769+ down_read(&h_sb->s_umount);
32770+ err = __sync_filesystem(h_sb, wait);
32771+ up_read(&h_sb->s_umount);
32772+ lockdep_on();
32773+
32774+ return err;
32775+}
32776+
8cdd5066
JR
32777+/* ---------------------------------------------------------------------- */
32778+
1facf9fc 32779+int vfsub_update_h_iattr(struct path *h_path, int *did)
32780+{
32781+ int err;
32782+ struct kstat st;
32783+ struct super_block *h_sb;
32784+
32785+ /* for remote fs, leave work for its getattr or d_revalidate */
32786+ /* for bad i_attr fs, handle them in aufs_getattr() */
32787+ /* still some fs may acquire i_mutex. we need to skip them */
32788+ err = 0;
32789+ if (!did)
32790+ did = &err;
32791+ h_sb = h_path->dentry->d_sb;
32792+ *did = (!au_test_fs_remote(h_sb) && au_test_fs_refresh_iattr(h_sb));
32793+ if (*did)
521ced18 32794+ err = vfsub_getattr(h_path, &st);
1facf9fc 32795+
32796+ return err;
32797+}
32798+
32799+/* ---------------------------------------------------------------------- */
32800+
4a4d8108 32801+struct file *vfsub_dentry_open(struct path *path, int flags)
1308ab2a 32802+{
32803+ struct file *file;
32804+
b4510431 32805+ file = dentry_open(path, flags /* | __FMODE_NONOTIFY */,
7f207e10 32806+ current_cred());
2cbb1c4b
JR
32807+ if (!IS_ERR_OR_NULL(file)
32808+ && (file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
5527c038 32809+ i_readcount_inc(d_inode(path->dentry));
4a4d8108 32810+
1308ab2a 32811+ return file;
32812+}
32813+
1facf9fc 32814+struct file *vfsub_filp_open(const char *path, int oflags, int mode)
32815+{
32816+ struct file *file;
32817+
2cbb1c4b 32818+ lockdep_off();
7f207e10 32819+ file = filp_open(path,
2cbb1c4b 32820+ oflags /* | __FMODE_NONOTIFY */,
7f207e10 32821+ mode);
2cbb1c4b 32822+ lockdep_on();
1facf9fc 32823+ if (IS_ERR(file))
32824+ goto out;
32825+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
32826+
4f0767ce 32827+out:
1facf9fc 32828+ return file;
32829+}
32830+
b912730e
AM
32831+/*
32832+ * Ideally this function should call VFS:do_last() in order to keep all its
32833+ * checkings. But it is very hard for aufs to regenerate several VFS internal
32834+ * structure such as nameidata. This is a second (or third) best approach.
32835+ * cf. linux/fs/namei.c:do_last(), lookup_open() and atomic_open().
32836+ */
32837+int vfsub_atomic_open(struct inode *dir, struct dentry *dentry,
acd2b654 32838+ struct vfsub_aopen_args *args)
b912730e
AM
32839+{
32840+ int err;
acd2b654 32841+ struct au_branch *br = args->br;
b912730e
AM
32842+ struct file *file = args->file;
32843+ /* copied from linux/fs/namei.c:atomic_open() */
32844+ struct dentry *const DENTRY_NOT_SET = (void *)-1UL;
32845+
32846+ IMustLock(dir);
32847+ AuDebugOn(!dir->i_op->atomic_open);
32848+
32849+ err = au_br_test_oflag(args->open_flag, br);
32850+ if (unlikely(err))
32851+ goto out;
32852+
acd2b654
AM
32853+ au_lcnt_inc(&br->br_nfiles);
32854+ file->f_path.dentry = DENTRY_NOT_SET;
32855+ file->f_path.mnt = au_br_mnt(br);
32856+ AuDbg("%ps\n", dir->i_op->atomic_open);
b912730e 32857+ err = dir->i_op->atomic_open(dir, dentry, file, args->open_flag,
acd2b654
AM
32858+ args->create_mode);
32859+ if (unlikely(err < 0)) {
32860+ au_lcnt_dec(&br->br_nfiles);
b912730e 32861+ goto out;
acd2b654 32862+ }
b912730e 32863+
acd2b654
AM
32864+ /* temporary workaround for nfsv4 branch */
32865+ if (au_test_nfs(dir->i_sb))
32866+ nfs_mark_for_revalidate(dir);
b912730e 32867+
acd2b654
AM
32868+ if (file->f_mode & FMODE_CREATED)
32869+ fsnotify_create(dir, dentry);
32870+ if (!(file->f_mode & FMODE_OPENED)) {
32871+ au_lcnt_dec(&br->br_nfiles);
32872+ goto out;
b912730e
AM
32873+ }
32874+
acd2b654
AM
32875+ /* todo: call VFS:may_open() here */
32876+ /* todo: ima_file_check() too? */
32877+ if (!err && (args->open_flag & __FMODE_EXEC))
32878+ err = deny_write_access(file);
32879+ if (!err)
32880+ fsnotify_open(file);
32881+ else
32882+ au_lcnt_dec(&br->br_nfiles);
32883+ /* note that the file is created and still opened */
b912730e
AM
32884+
32885+out:
32886+ return err;
32887+}
32888+
1facf9fc 32889+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path)
32890+{
32891+ int err;
32892+
1facf9fc 32893+ err = kern_path(name, flags, path);
5527c038 32894+ if (!err && d_is_positive(path->dentry))
1facf9fc 32895+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
32896+ return err;
32897+}
32898+
febd17d6
JR
32899+struct dentry *vfsub_lookup_one_len_unlocked(const char *name,
32900+ struct dentry *parent, int len)
32901+{
32902+ struct path path = {
32903+ .mnt = NULL
32904+ };
32905+
32906+ path.dentry = lookup_one_len_unlocked(name, parent, len);
32907+ if (IS_ERR(path.dentry))
32908+ goto out;
32909+ if (d_is_positive(path.dentry))
32910+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
32911+
32912+out:
32913+ AuTraceErrPtr(path.dentry);
32914+ return path.dentry;
32915+}
32916+
1facf9fc 32917+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
32918+ int len)
32919+{
32920+ struct path path = {
32921+ .mnt = NULL
32922+ };
32923+
1308ab2a 32924+ /* VFS checks it too, but by WARN_ON_ONCE() */
5527c038 32925+ IMustLock(d_inode(parent));
1facf9fc 32926+
32927+ path.dentry = lookup_one_len(name, parent, len);
32928+ if (IS_ERR(path.dentry))
32929+ goto out;
5527c038 32930+ if (d_is_positive(path.dentry))
1facf9fc 32931+ vfsub_update_h_iattr(&path, /*did*/NULL); /*ignore*/
32932+
4f0767ce 32933+out:
4a4d8108 32934+ AuTraceErrPtr(path.dentry);
1facf9fc 32935+ return path.dentry;
32936+}
32937+
b4510431 32938+void vfsub_call_lkup_one(void *args)
2cbb1c4b 32939+{
b4510431
AM
32940+ struct vfsub_lkup_one_args *a = args;
32941+ *a->errp = vfsub_lkup_one(a->name, a->parent);
2cbb1c4b
JR
32942+}
32943+
1facf9fc 32944+/* ---------------------------------------------------------------------- */
32945+
32946+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
32947+ struct dentry *d2, struct au_hinode *hdir2)
32948+{
32949+ struct dentry *d;
32950+
2cbb1c4b 32951+ lockdep_off();
1facf9fc 32952+ d = lock_rename(d1, d2);
2cbb1c4b 32953+ lockdep_on();
4a4d8108 32954+ au_hn_suspend(hdir1);
1facf9fc 32955+ if (hdir1 != hdir2)
4a4d8108 32956+ au_hn_suspend(hdir2);
1facf9fc 32957+
32958+ return d;
32959+}
32960+
32961+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
32962+ struct dentry *d2, struct au_hinode *hdir2)
32963+{
4a4d8108 32964+ au_hn_resume(hdir1);
1facf9fc 32965+ if (hdir1 != hdir2)
4a4d8108 32966+ au_hn_resume(hdir2);
2cbb1c4b 32967+ lockdep_off();
1facf9fc 32968+ unlock_rename(d1, d2);
2cbb1c4b 32969+ lockdep_on();
1facf9fc 32970+}
32971+
32972+/* ---------------------------------------------------------------------- */
32973+
b4510431 32974+int vfsub_create(struct inode *dir, struct path *path, int mode, bool want_excl)
1facf9fc 32975+{
32976+ int err;
32977+ struct dentry *d;
32978+
32979+ IMustLock(dir);
32980+
32981+ d = path->dentry;
32982+ path->dentry = d->d_parent;
b752ccd1 32983+ err = security_path_mknod(path, d, mode, 0);
1facf9fc 32984+ path->dentry = d;
32985+ if (unlikely(err))
32986+ goto out;
32987+
c1595e42 32988+ lockdep_off();
b4510431 32989+ err = vfs_create(dir, path->dentry, mode, want_excl);
c1595e42 32990+ lockdep_on();
1facf9fc 32991+ if (!err) {
32992+ struct path tmp = *path;
32993+ int did;
32994+
32995+ vfsub_update_h_iattr(&tmp, &did);
32996+ if (did) {
32997+ tmp.dentry = path->dentry->d_parent;
32998+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
32999+ }
33000+ /*ignore*/
33001+ }
33002+
4f0767ce 33003+out:
1facf9fc 33004+ return err;
33005+}
33006+
33007+int vfsub_symlink(struct inode *dir, struct path *path, const char *symname)
33008+{
33009+ int err;
33010+ struct dentry *d;
33011+
33012+ IMustLock(dir);
33013+
33014+ d = path->dentry;
33015+ path->dentry = d->d_parent;
b752ccd1 33016+ err = security_path_symlink(path, d, symname);
1facf9fc 33017+ path->dentry = d;
33018+ if (unlikely(err))
33019+ goto out;
33020+
c1595e42 33021+ lockdep_off();
1facf9fc 33022+ err = vfs_symlink(dir, path->dentry, symname);
c1595e42 33023+ lockdep_on();
1facf9fc 33024+ if (!err) {
33025+ struct path tmp = *path;
33026+ int did;
33027+
33028+ vfsub_update_h_iattr(&tmp, &did);
33029+ if (did) {
33030+ tmp.dentry = path->dentry->d_parent;
33031+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33032+ }
33033+ /*ignore*/
33034+ }
33035+
4f0767ce 33036+out:
1facf9fc 33037+ return err;
33038+}
33039+
33040+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev)
33041+{
33042+ int err;
33043+ struct dentry *d;
33044+
33045+ IMustLock(dir);
33046+
33047+ d = path->dentry;
33048+ path->dentry = d->d_parent;
027c5e7a 33049+ err = security_path_mknod(path, d, mode, new_encode_dev(dev));
1facf9fc 33050+ path->dentry = d;
33051+ if (unlikely(err))
33052+ goto out;
33053+
c1595e42 33054+ lockdep_off();
1facf9fc 33055+ err = vfs_mknod(dir, path->dentry, mode, dev);
c1595e42 33056+ lockdep_on();
1facf9fc 33057+ if (!err) {
33058+ struct path tmp = *path;
33059+ int did;
33060+
33061+ vfsub_update_h_iattr(&tmp, &did);
33062+ if (did) {
33063+ tmp.dentry = path->dentry->d_parent;
33064+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33065+ }
33066+ /*ignore*/
33067+ }
33068+
4f0767ce 33069+out:
1facf9fc 33070+ return err;
33071+}
33072+
33073+static int au_test_nlink(struct inode *inode)
33074+{
33075+ const unsigned int link_max = UINT_MAX >> 1; /* rough margin */
33076+
33077+ if (!au_test_fs_no_limit_nlink(inode->i_sb)
33078+ || inode->i_nlink < link_max)
33079+ return 0;
33080+ return -EMLINK;
33081+}
33082+
523b37e3
AM
33083+int vfsub_link(struct dentry *src_dentry, struct inode *dir, struct path *path,
33084+ struct inode **delegated_inode)
1facf9fc 33085+{
33086+ int err;
33087+ struct dentry *d;
33088+
33089+ IMustLock(dir);
33090+
5527c038 33091+ err = au_test_nlink(d_inode(src_dentry));
1facf9fc 33092+ if (unlikely(err))
33093+ return err;
33094+
b4510431 33095+ /* we don't call may_linkat() */
1facf9fc 33096+ d = path->dentry;
33097+ path->dentry = d->d_parent;
b752ccd1 33098+ err = security_path_link(src_dentry, path, d);
1facf9fc 33099+ path->dentry = d;
33100+ if (unlikely(err))
33101+ goto out;
33102+
2cbb1c4b 33103+ lockdep_off();
523b37e3 33104+ err = vfs_link(src_dentry, dir, path->dentry, delegated_inode);
2cbb1c4b 33105+ lockdep_on();
1facf9fc 33106+ if (!err) {
33107+ struct path tmp = *path;
33108+ int did;
33109+
33110+ /* fuse has different memory inode for the same inumber */
33111+ vfsub_update_h_iattr(&tmp, &did);
33112+ if (did) {
33113+ tmp.dentry = path->dentry->d_parent;
33114+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33115+ tmp.dentry = src_dentry;
33116+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33117+ }
33118+ /*ignore*/
33119+ }
33120+
4f0767ce 33121+out:
1facf9fc 33122+ return err;
33123+}
33124+
33125+int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
523b37e3 33126+ struct inode *dir, struct path *path,
f2c43d5f 33127+ struct inode **delegated_inode, unsigned int flags)
1facf9fc 33128+{
33129+ int err;
33130+ struct path tmp = {
33131+ .mnt = path->mnt
33132+ };
33133+ struct dentry *d;
33134+
33135+ IMustLock(dir);
33136+ IMustLock(src_dir);
33137+
33138+ d = path->dentry;
33139+ path->dentry = d->d_parent;
33140+ tmp.dentry = src_dentry->d_parent;
38d290e6 33141+ err = security_path_rename(&tmp, src_dentry, path, d, /*flags*/0);
1facf9fc 33142+ path->dentry = d;
33143+ if (unlikely(err))
33144+ goto out;
33145+
2cbb1c4b 33146+ lockdep_off();
523b37e3 33147+ err = vfs_rename(src_dir, src_dentry, dir, path->dentry,
f2c43d5f 33148+ delegated_inode, flags);
2cbb1c4b 33149+ lockdep_on();
1facf9fc 33150+ if (!err) {
33151+ int did;
33152+
33153+ tmp.dentry = d->d_parent;
33154+ vfsub_update_h_iattr(&tmp, &did);
33155+ if (did) {
33156+ tmp.dentry = src_dentry;
33157+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33158+ tmp.dentry = src_dentry->d_parent;
33159+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33160+ }
33161+ /*ignore*/
33162+ }
33163+
4f0767ce 33164+out:
1facf9fc 33165+ return err;
33166+}
33167+
33168+int vfsub_mkdir(struct inode *dir, struct path *path, int mode)
33169+{
33170+ int err;
33171+ struct dentry *d;
33172+
33173+ IMustLock(dir);
33174+
33175+ d = path->dentry;
33176+ path->dentry = d->d_parent;
b752ccd1 33177+ err = security_path_mkdir(path, d, mode);
1facf9fc 33178+ path->dentry = d;
33179+ if (unlikely(err))
33180+ goto out;
33181+
c1595e42 33182+ lockdep_off();
1facf9fc 33183+ err = vfs_mkdir(dir, path->dentry, mode);
c1595e42 33184+ lockdep_on();
1facf9fc 33185+ if (!err) {
33186+ struct path tmp = *path;
33187+ int did;
33188+
33189+ vfsub_update_h_iattr(&tmp, &did);
33190+ if (did) {
33191+ tmp.dentry = path->dentry->d_parent;
33192+ vfsub_update_h_iattr(&tmp, /*did*/NULL);
33193+ }
33194+ /*ignore*/
33195+ }
33196+
4f0767ce 33197+out:
1facf9fc 33198+ return err;
33199+}
33200+
33201+int vfsub_rmdir(struct inode *dir, struct path *path)
33202+{
33203+ int err;
33204+ struct dentry *d;
33205+
33206+ IMustLock(dir);
33207+
33208+ d = path->dentry;
33209+ path->dentry = d->d_parent;
b752ccd1 33210+ err = security_path_rmdir(path, d);
1facf9fc 33211+ path->dentry = d;
33212+ if (unlikely(err))
33213+ goto out;
33214+
2cbb1c4b 33215+ lockdep_off();
1facf9fc 33216+ err = vfs_rmdir(dir, path->dentry);
2cbb1c4b 33217+ lockdep_on();
1facf9fc 33218+ if (!err) {
33219+ struct path tmp = {
33220+ .dentry = path->dentry->d_parent,
33221+ .mnt = path->mnt
33222+ };
33223+
33224+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
33225+ }
33226+
4f0767ce 33227+out:
1facf9fc 33228+ return err;
33229+}
33230+
33231+/* ---------------------------------------------------------------------- */
33232+
9dbd164d 33233+/* todo: support mmap_sem? */
1facf9fc 33234+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
33235+ loff_t *ppos)
33236+{
33237+ ssize_t err;
33238+
2cbb1c4b 33239+ lockdep_off();
1facf9fc 33240+ err = vfs_read(file, ubuf, count, ppos);
2cbb1c4b 33241+ lockdep_on();
1facf9fc 33242+ if (err >= 0)
33243+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
33244+ return err;
33245+}
33246+
33247+/* todo: kernel_read()? */
33248+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
33249+ loff_t *ppos)
33250+{
33251+ ssize_t err;
33252+ mm_segment_t oldfs;
b752ccd1
AM
33253+ union {
33254+ void *k;
33255+ char __user *u;
33256+ } buf;
1facf9fc 33257+
b752ccd1 33258+ buf.k = kbuf;
1facf9fc 33259+ oldfs = get_fs();
33260+ set_fs(KERNEL_DS);
b752ccd1 33261+ err = vfsub_read_u(file, buf.u, count, ppos);
1facf9fc 33262+ set_fs(oldfs);
33263+ return err;
33264+}
33265+
33266+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
33267+ loff_t *ppos)
33268+{
33269+ ssize_t err;
33270+
2cbb1c4b 33271+ lockdep_off();
1facf9fc 33272+ err = vfs_write(file, ubuf, count, ppos);
2cbb1c4b 33273+ lockdep_on();
1facf9fc 33274+ if (err >= 0)
33275+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
33276+ return err;
33277+}
33278+
33279+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos)
33280+{
33281+ ssize_t err;
33282+ mm_segment_t oldfs;
b752ccd1
AM
33283+ union {
33284+ void *k;
33285+ const char __user *u;
33286+ } buf;
1facf9fc 33287+
b752ccd1 33288+ buf.k = kbuf;
1facf9fc 33289+ oldfs = get_fs();
33290+ set_fs(KERNEL_DS);
b752ccd1 33291+ err = vfsub_write_u(file, buf.u, count, ppos);
1facf9fc 33292+ set_fs(oldfs);
33293+ return err;
33294+}
33295+
4a4d8108
AM
33296+int vfsub_flush(struct file *file, fl_owner_t id)
33297+{
33298+ int err;
33299+
33300+ err = 0;
523b37e3 33301+ if (file->f_op->flush) {
2000de60 33302+ if (!au_test_nfs(file->f_path.dentry->d_sb))
2cbb1c4b
JR
33303+ err = file->f_op->flush(file, id);
33304+ else {
33305+ lockdep_off();
33306+ err = file->f_op->flush(file, id);
33307+ lockdep_on();
33308+ }
4a4d8108
AM
33309+ if (!err)
33310+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL);
33311+ /*ignore*/
33312+ }
33313+ return err;
33314+}
33315+
392086de 33316+int vfsub_iterate_dir(struct file *file, struct dir_context *ctx)
1facf9fc 33317+{
33318+ int err;
33319+
062440b3 33320+ AuDbg("%pD, ctx{%ps, %llu}\n", file, ctx->actor, ctx->pos);
392086de 33321+
2cbb1c4b 33322+ lockdep_off();
392086de 33323+ err = iterate_dir(file, ctx);
2cbb1c4b 33324+ lockdep_on();
1facf9fc 33325+ if (err >= 0)
33326+ vfsub_update_h_iattr(&file->f_path, /*did*/NULL); /*ignore*/
1c60b727 33327+
1facf9fc 33328+ return err;
33329+}
33330+
33331+long vfsub_splice_to(struct file *in, loff_t *ppos,
33332+ struct pipe_inode_info *pipe, size_t len,
33333+ unsigned int flags)
33334+{
33335+ long err;
33336+
2cbb1c4b 33337+ lockdep_off();
0fc653ad 33338+ err = do_splice_to(in, ppos, pipe, len, flags);
2cbb1c4b 33339+ lockdep_on();
4a4d8108 33340+ file_accessed(in);
1facf9fc 33341+ if (err >= 0)
33342+ vfsub_update_h_iattr(&in->f_path, /*did*/NULL); /*ignore*/
33343+ return err;
33344+}
33345+
33346+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
33347+ loff_t *ppos, size_t len, unsigned int flags)
33348+{
33349+ long err;
33350+
2cbb1c4b 33351+ lockdep_off();
0fc653ad 33352+ err = do_splice_from(pipe, out, ppos, len, flags);
2cbb1c4b 33353+ lockdep_on();
1facf9fc 33354+ if (err >= 0)
33355+ vfsub_update_h_iattr(&out->f_path, /*did*/NULL); /*ignore*/
33356+ return err;
33357+}
33358+
53392da6
AM
33359+int vfsub_fsync(struct file *file, struct path *path, int datasync)
33360+{
33361+ int err;
33362+
33363+ /* file can be NULL */
33364+ lockdep_off();
33365+ err = vfs_fsync(file, datasync);
33366+ lockdep_on();
33367+ if (!err) {
33368+ if (!path) {
33369+ AuDebugOn(!file);
33370+ path = &file->f_path;
33371+ }
33372+ vfsub_update_h_iattr(path, /*did*/NULL); /*ignore*/
33373+ }
33374+ return err;
33375+}
33376+
1facf9fc 33377+/* cf. open.c:do_sys_truncate() and do_sys_ftruncate() */
33378+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
33379+ struct file *h_file)
33380+{
33381+ int err;
33382+ struct inode *h_inode;
c06a8ce3 33383+ struct super_block *h_sb;
1facf9fc 33384+
1facf9fc 33385+ if (!h_file) {
c06a8ce3
AM
33386+ err = vfsub_truncate(h_path, length);
33387+ goto out;
1facf9fc 33388+ }
33389+
5527c038 33390+ h_inode = d_inode(h_path->dentry);
c06a8ce3
AM
33391+ h_sb = h_inode->i_sb;
33392+ lockdep_off();
33393+ sb_start_write(h_sb);
33394+ lockdep_on();
1facf9fc 33395+ err = locks_verify_truncate(h_inode, h_file, length);
33396+ if (!err)
953406b4 33397+ err = security_path_truncate(h_path);
2cbb1c4b
JR
33398+ if (!err) {
33399+ lockdep_off();
1facf9fc 33400+ err = do_truncate(h_path->dentry, length, attr, h_file);
2cbb1c4b
JR
33401+ lockdep_on();
33402+ }
c06a8ce3
AM
33403+ lockdep_off();
33404+ sb_end_write(h_sb);
33405+ lockdep_on();
1facf9fc 33406+
4f0767ce 33407+out:
1facf9fc 33408+ return err;
33409+}
33410+
33411+/* ---------------------------------------------------------------------- */
33412+
33413+struct au_vfsub_mkdir_args {
33414+ int *errp;
33415+ struct inode *dir;
33416+ struct path *path;
33417+ int mode;
33418+};
33419+
33420+static void au_call_vfsub_mkdir(void *args)
33421+{
33422+ struct au_vfsub_mkdir_args *a = args;
33423+ *a->errp = vfsub_mkdir(a->dir, a->path, a->mode);
33424+}
33425+
33426+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode)
33427+{
33428+ int err, do_sio, wkq_err;
33429+
33430+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
c1595e42
JR
33431+ if (!do_sio) {
33432+ lockdep_off();
1facf9fc 33433+ err = vfsub_mkdir(dir, path, mode);
c1595e42
JR
33434+ lockdep_on();
33435+ } else {
1facf9fc 33436+ struct au_vfsub_mkdir_args args = {
33437+ .errp = &err,
33438+ .dir = dir,
33439+ .path = path,
33440+ .mode = mode
33441+ };
33442+ wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args);
33443+ if (unlikely(wkq_err))
33444+ err = wkq_err;
33445+ }
33446+
33447+ return err;
33448+}
33449+
33450+struct au_vfsub_rmdir_args {
33451+ int *errp;
33452+ struct inode *dir;
33453+ struct path *path;
33454+};
33455+
33456+static void au_call_vfsub_rmdir(void *args)
33457+{
33458+ struct au_vfsub_rmdir_args *a = args;
33459+ *a->errp = vfsub_rmdir(a->dir, a->path);
33460+}
33461+
33462+int vfsub_sio_rmdir(struct inode *dir, struct path *path)
33463+{
33464+ int err, do_sio, wkq_err;
33465+
33466+ do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE);
c1595e42
JR
33467+ if (!do_sio) {
33468+ lockdep_off();
1facf9fc 33469+ err = vfsub_rmdir(dir, path);
c1595e42
JR
33470+ lockdep_on();
33471+ } else {
1facf9fc 33472+ struct au_vfsub_rmdir_args args = {
33473+ .errp = &err,
33474+ .dir = dir,
33475+ .path = path
33476+ };
33477+ wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args);
33478+ if (unlikely(wkq_err))
33479+ err = wkq_err;
33480+ }
33481+
33482+ return err;
33483+}
33484+
33485+/* ---------------------------------------------------------------------- */
33486+
33487+struct notify_change_args {
33488+ int *errp;
33489+ struct path *path;
33490+ struct iattr *ia;
523b37e3 33491+ struct inode **delegated_inode;
1facf9fc 33492+};
33493+
33494+static void call_notify_change(void *args)
33495+{
33496+ struct notify_change_args *a = args;
33497+ struct inode *h_inode;
33498+
5527c038 33499+ h_inode = d_inode(a->path->dentry);
1facf9fc 33500+ IMustLock(h_inode);
33501+
33502+ *a->errp = -EPERM;
33503+ if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
c1595e42 33504+ lockdep_off();
523b37e3
AM
33505+ *a->errp = notify_change(a->path->dentry, a->ia,
33506+ a->delegated_inode);
c1595e42 33507+ lockdep_on();
1facf9fc 33508+ if (!*a->errp)
33509+ vfsub_update_h_iattr(a->path, /*did*/NULL); /*ignore*/
33510+ }
33511+ AuTraceErr(*a->errp);
33512+}
33513+
523b37e3
AM
33514+int vfsub_notify_change(struct path *path, struct iattr *ia,
33515+ struct inode **delegated_inode)
1facf9fc 33516+{
33517+ int err;
33518+ struct notify_change_args args = {
523b37e3
AM
33519+ .errp = &err,
33520+ .path = path,
33521+ .ia = ia,
33522+ .delegated_inode = delegated_inode
1facf9fc 33523+ };
33524+
33525+ call_notify_change(&args);
33526+
33527+ return err;
33528+}
33529+
523b37e3
AM
33530+int vfsub_sio_notify_change(struct path *path, struct iattr *ia,
33531+ struct inode **delegated_inode)
1facf9fc 33532+{
33533+ int err, wkq_err;
33534+ struct notify_change_args args = {
523b37e3
AM
33535+ .errp = &err,
33536+ .path = path,
33537+ .ia = ia,
33538+ .delegated_inode = delegated_inode
1facf9fc 33539+ };
33540+
33541+ wkq_err = au_wkq_wait(call_notify_change, &args);
33542+ if (unlikely(wkq_err))
33543+ err = wkq_err;
33544+
33545+ return err;
33546+}
33547+
33548+/* ---------------------------------------------------------------------- */
33549+
33550+struct unlink_args {
33551+ int *errp;
33552+ struct inode *dir;
33553+ struct path *path;
523b37e3 33554+ struct inode **delegated_inode;
1facf9fc 33555+};
33556+
33557+static void call_unlink(void *args)
33558+{
33559+ struct unlink_args *a = args;
33560+ struct dentry *d = a->path->dentry;
33561+ struct inode *h_inode;
33562+ const int stop_sillyrename = (au_test_nfs(d->d_sb)
c1595e42 33563+ && au_dcount(d) == 1);
1facf9fc 33564+
33565+ IMustLock(a->dir);
33566+
33567+ a->path->dentry = d->d_parent;
33568+ *a->errp = security_path_unlink(a->path, d);
33569+ a->path->dentry = d;
33570+ if (unlikely(*a->errp))
33571+ return;
33572+
33573+ if (!stop_sillyrename)
33574+ dget(d);
5527c038
JR
33575+ h_inode = NULL;
33576+ if (d_is_positive(d)) {
33577+ h_inode = d_inode(d);
027c5e7a 33578+ ihold(h_inode);
5527c038 33579+ }
1facf9fc 33580+
2cbb1c4b 33581+ lockdep_off();
523b37e3 33582+ *a->errp = vfs_unlink(a->dir, d, a->delegated_inode);
2cbb1c4b 33583+ lockdep_on();
1facf9fc 33584+ if (!*a->errp) {
33585+ struct path tmp = {
33586+ .dentry = d->d_parent,
33587+ .mnt = a->path->mnt
33588+ };
33589+ vfsub_update_h_iattr(&tmp, /*did*/NULL); /*ignore*/
33590+ }
33591+
33592+ if (!stop_sillyrename)
33593+ dput(d);
33594+ if (h_inode)
33595+ iput(h_inode);
33596+
33597+ AuTraceErr(*a->errp);
33598+}
33599+
33600+/*
33601+ * @dir: must be locked.
33602+ * @dentry: target dentry.
33603+ */
523b37e3
AM
33604+int vfsub_unlink(struct inode *dir, struct path *path,
33605+ struct inode **delegated_inode, int force)
1facf9fc 33606+{
33607+ int err;
33608+ struct unlink_args args = {
523b37e3
AM
33609+ .errp = &err,
33610+ .dir = dir,
33611+ .path = path,
33612+ .delegated_inode = delegated_inode
1facf9fc 33613+ };
33614+
33615+ if (!force)
33616+ call_unlink(&args);
33617+ else {
33618+ int wkq_err;
33619+
33620+ wkq_err = au_wkq_wait(call_unlink, &args);
33621+ if (unlikely(wkq_err))
33622+ err = wkq_err;
33623+ }
33624+
33625+ return err;
33626+}
7f207e10 33627diff -urN /usr/share/empty/fs/aufs/vfsub.h linux/fs/aufs/vfsub.h
eca34b5c 33628--- /usr/share/empty/fs/aufs/vfsub.h 1970-01-01 01:00:00.000000000 +0100
016522bc 33629+++ linux/fs/aufs/vfsub.h 2020-01-27 10:57:18.178871751 +0100
eca801bf 33630@@ -0,0 +1,354 @@
062440b3 33631+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 33632+/*
016522bc 33633+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 33634+ *
33635+ * This program, aufs is free software; you can redistribute it and/or modify
33636+ * it under the terms of the GNU General Public License as published by
33637+ * the Free Software Foundation; either version 2 of the License, or
33638+ * (at your option) any later version.
dece6358
AM
33639+ *
33640+ * This program is distributed in the hope that it will be useful,
33641+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
33642+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33643+ * GNU General Public License for more details.
33644+ *
33645+ * You should have received a copy of the GNU General Public License
523b37e3 33646+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 33647+ */
33648+
33649+/*
33650+ * sub-routines for VFS
33651+ */
33652+
33653+#ifndef __AUFS_VFSUB_H__
33654+#define __AUFS_VFSUB_H__
33655+
33656+#ifdef __KERNEL__
33657+
33658+#include <linux/fs.h>
b4510431 33659+#include <linux/mount.h>
8cdd5066 33660+#include <linux/posix_acl.h>
c1595e42 33661+#include <linux/xattr.h>
7f207e10 33662+#include "debug.h"
1facf9fc 33663+
7f207e10 33664+/* copied from linux/fs/internal.h */
2cbb1c4b 33665+/* todo: BAD approach!! */
c06a8ce3 33666+extern void __mnt_drop_write(struct vfsmount *);
acd2b654 33667+extern struct file *alloc_empty_file(int, const struct cred *);
7f207e10
AM
33668+
33669+/* ---------------------------------------------------------------------- */
1facf9fc 33670+
33671+/* lock subclass for lower inode */
33672+/* default MAX_LOCKDEP_SUBCLASSES(8) is not enough */
33673+/* reduce? gave up. */
33674+enum {
c1595e42 33675+ AuLsc_I_Begin = I_MUTEX_PARENT2, /* 5 */
1facf9fc 33676+ AuLsc_I_PARENT, /* lower inode, parent first */
33677+ AuLsc_I_PARENT2, /* copyup dirs */
dece6358 33678+ AuLsc_I_PARENT3, /* copyup wh */
1facf9fc 33679+ AuLsc_I_CHILD,
33680+ AuLsc_I_CHILD2,
33681+ AuLsc_I_End
33682+};
33683+
33684+/* to debug easier, do not make them inlined functions */
33685+#define MtxMustLock(mtx) AuDebugOn(!mutex_is_locked(mtx))
febd17d6 33686+#define IMustLock(i) AuDebugOn(!inode_is_locked(i))
1facf9fc 33687+
33688+/* ---------------------------------------------------------------------- */
33689+
7f207e10
AM
33690+static inline void vfsub_drop_nlink(struct inode *inode)
33691+{
33692+ AuDebugOn(!inode->i_nlink);
33693+ drop_nlink(inode);
33694+}
33695+
027c5e7a
AM
33696+static inline void vfsub_dead_dir(struct inode *inode)
33697+{
33698+ AuDebugOn(!S_ISDIR(inode->i_mode));
33699+ inode->i_flags |= S_DEAD;
33700+ clear_nlink(inode);
33701+}
33702+
392086de
AM
33703+static inline int vfsub_native_ro(struct inode *inode)
33704+{
8b6a4947 33705+ return sb_rdonly(inode->i_sb)
392086de
AM
33706+ || IS_RDONLY(inode)
33707+ /* || IS_APPEND(inode) */
33708+ || IS_IMMUTABLE(inode);
33709+}
33710+
8cdd5066
JR
33711+#ifdef CONFIG_AUFS_BR_FUSE
33712+int vfsub_test_mntns(struct vfsmount *mnt, struct super_block *h_sb);
33713+#else
33714+AuStubInt0(vfsub_test_mntns, struct vfsmount *mnt, struct super_block *h_sb);
33715+#endif
33716+
a2654f78
AM
33717+int vfsub_sync_filesystem(struct super_block *h_sb, int wait);
33718+
7f207e10
AM
33719+/* ---------------------------------------------------------------------- */
33720+
33721+int vfsub_update_h_iattr(struct path *h_path, int *did);
33722+struct file *vfsub_dentry_open(struct path *path, int flags);
33723+struct file *vfsub_filp_open(const char *path, int oflags, int mode);
acd2b654 33724+struct au_branch;
b912730e 33725+struct vfsub_aopen_args {
acd2b654
AM
33726+ struct file *file;
33727+ unsigned int open_flag;
33728+ umode_t create_mode;
33729+ struct au_branch *br;
b912730e 33730+};
b912730e 33731+int vfsub_atomic_open(struct inode *dir, struct dentry *dentry,
acd2b654 33732+ struct vfsub_aopen_args *args);
1facf9fc 33733+int vfsub_kern_path(const char *name, unsigned int flags, struct path *path);
b4510431 33734+
febd17d6
JR
33735+struct dentry *vfsub_lookup_one_len_unlocked(const char *name,
33736+ struct dentry *parent, int len);
1facf9fc 33737+struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
33738+ int len);
b4510431
AM
33739+
33740+struct vfsub_lkup_one_args {
33741+ struct dentry **errp;
33742+ struct qstr *name;
33743+ struct dentry *parent;
33744+};
33745+
33746+static inline struct dentry *vfsub_lkup_one(struct qstr *name,
33747+ struct dentry *parent)
33748+{
33749+ return vfsub_lookup_one_len(name->name, parent, name->len);
33750+}
33751+
33752+void vfsub_call_lkup_one(void *args);
33753+
33754+/* ---------------------------------------------------------------------- */
33755+
33756+static inline int vfsub_mnt_want_write(struct vfsmount *mnt)
33757+{
33758+ int err;
076b876e 33759+
b4510431
AM
33760+ lockdep_off();
33761+ err = mnt_want_write(mnt);
33762+ lockdep_on();
33763+ return err;
33764+}
33765+
33766+static inline void vfsub_mnt_drop_write(struct vfsmount *mnt)
33767+{
33768+ lockdep_off();
33769+ mnt_drop_write(mnt);
33770+ lockdep_on();
33771+}
1facf9fc 33772+
7e9cd9fe 33773+#if 0 /* reserved */
c06a8ce3
AM
33774+static inline void vfsub_mnt_drop_write_file(struct file *file)
33775+{
33776+ lockdep_off();
33777+ mnt_drop_write_file(file);
33778+ lockdep_on();
33779+}
7e9cd9fe 33780+#endif
c06a8ce3 33781+
1facf9fc 33782+/* ---------------------------------------------------------------------- */
33783+
33784+struct au_hinode;
33785+struct dentry *vfsub_lock_rename(struct dentry *d1, struct au_hinode *hdir1,
33786+ struct dentry *d2, struct au_hinode *hdir2);
33787+void vfsub_unlock_rename(struct dentry *d1, struct au_hinode *hdir1,
33788+ struct dentry *d2, struct au_hinode *hdir2);
33789+
537831f9
AM
33790+int vfsub_create(struct inode *dir, struct path *path, int mode,
33791+ bool want_excl);
1facf9fc 33792+int vfsub_symlink(struct inode *dir, struct path *path,
33793+ const char *symname);
33794+int vfsub_mknod(struct inode *dir, struct path *path, int mode, dev_t dev);
33795+int vfsub_link(struct dentry *src_dentry, struct inode *dir,
523b37e3 33796+ struct path *path, struct inode **delegated_inode);
1facf9fc 33797+int vfsub_rename(struct inode *src_hdir, struct dentry *src_dentry,
523b37e3 33798+ struct inode *hdir, struct path *path,
f2c43d5f 33799+ struct inode **delegated_inode, unsigned int flags);
1facf9fc 33800+int vfsub_mkdir(struct inode *dir, struct path *path, int mode);
33801+int vfsub_rmdir(struct inode *dir, struct path *path);
33802+
33803+/* ---------------------------------------------------------------------- */
33804+
33805+ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
33806+ loff_t *ppos);
33807+ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count,
33808+ loff_t *ppos);
33809+ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
33810+ loff_t *ppos);
33811+ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count,
33812+ loff_t *ppos);
4a4d8108 33813+int vfsub_flush(struct file *file, fl_owner_t id);
392086de
AM
33814+int vfsub_iterate_dir(struct file *file, struct dir_context *ctx);
33815+
c06a8ce3
AM
33816+static inline loff_t vfsub_f_size_read(struct file *file)
33817+{
33818+ return i_size_read(file_inode(file));
33819+}
33820+
4a4d8108
AM
33821+static inline unsigned int vfsub_file_flags(struct file *file)
33822+{
33823+ unsigned int flags;
33824+
33825+ spin_lock(&file->f_lock);
33826+ flags = file->f_flags;
33827+ spin_unlock(&file->f_lock);
33828+
33829+ return flags;
33830+}
1308ab2a 33831+
f0c0a007
AM
33832+static inline int vfsub_file_execed(struct file *file)
33833+{
33834+ /* todo: direct access f_flags */
33835+ return !!(vfsub_file_flags(file) & __FMODE_EXEC);
33836+}
33837+
7e9cd9fe 33838+#if 0 /* reserved */
1facf9fc 33839+static inline void vfsub_file_accessed(struct file *h_file)
33840+{
33841+ file_accessed(h_file);
33842+ vfsub_update_h_iattr(&h_file->f_path, /*did*/NULL); /*ignore*/
33843+}
7e9cd9fe 33844+#endif
1facf9fc 33845+
79b8bda9 33846+#if 0 /* reserved */
1facf9fc 33847+static inline void vfsub_touch_atime(struct vfsmount *h_mnt,
33848+ struct dentry *h_dentry)
33849+{
33850+ struct path h_path = {
33851+ .dentry = h_dentry,
33852+ .mnt = h_mnt
33853+ };
92d182d2 33854+ touch_atime(&h_path);
1facf9fc 33855+ vfsub_update_h_iattr(&h_path, /*did*/NULL); /*ignore*/
33856+}
79b8bda9 33857+#endif
1facf9fc 33858+
cd7a4cd9
AM
33859+static inline int vfsub_update_time(struct inode *h_inode,
33860+ struct timespec64 *ts, int flags)
0c3ec466 33861+{
5afbbe0d 33862+ return update_time(h_inode, ts, flags);
0c3ec466
AM
33863+ /* no vfsub_update_h_iattr() since we don't have struct path */
33864+}
33865+
8cdd5066
JR
33866+#ifdef CONFIG_FS_POSIX_ACL
33867+static inline int vfsub_acl_chmod(struct inode *h_inode, umode_t h_mode)
33868+{
33869+ int err;
33870+
33871+ err = posix_acl_chmod(h_inode, h_mode);
33872+ if (err == -EOPNOTSUPP)
33873+ err = 0;
33874+ return err;
33875+}
33876+#else
33877+AuStubInt0(vfsub_acl_chmod, struct inode *h_inode, umode_t h_mode);
33878+#endif
33879+
4a4d8108
AM
33880+long vfsub_splice_to(struct file *in, loff_t *ppos,
33881+ struct pipe_inode_info *pipe, size_t len,
33882+ unsigned int flags);
33883+long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
33884+ loff_t *ppos, size_t len, unsigned int flags);
c06a8ce3
AM
33885+
33886+static inline long vfsub_truncate(struct path *path, loff_t length)
33887+{
33888+ long err;
076b876e 33889+
c06a8ce3
AM
33890+ lockdep_off();
33891+ err = vfs_truncate(path, length);
33892+ lockdep_on();
33893+ return err;
33894+}
33895+
4a4d8108
AM
33896+int vfsub_trunc(struct path *h_path, loff_t length, unsigned int attr,
33897+ struct file *h_file);
53392da6 33898+int vfsub_fsync(struct file *file, struct path *path, int datasync);
4a4d8108 33899+
521ced18
JR
33900+/*
33901+ * re-use branch fs's ioctl(FICLONE) while aufs itself doesn't support such
33902+ * ioctl.
33903+ */
9f237c51
AM
33904+static inline loff_t vfsub_clone_file_range(struct file *src, struct file *dst,
33905+ loff_t len)
521ced18 33906+{
9f237c51 33907+ loff_t err;
521ced18
JR
33908+
33909+ lockdep_off();
9f237c51 33910+ err = vfs_clone_file_range(src, 0, dst, 0, len, /*remap_flags*/0);
521ced18
JR
33911+ lockdep_on();
33912+
33913+ return err;
33914+}
33915+
33916+/* copy_file_range(2) is a systemcall */
33917+static inline ssize_t vfsub_copy_file_range(struct file *src, loff_t src_pos,
33918+ struct file *dst, loff_t dst_pos,
33919+ size_t len, unsigned int flags)
33920+{
33921+ ssize_t ssz;
33922+
33923+ lockdep_off();
33924+ ssz = vfs_copy_file_range(src, src_pos, dst, dst_pos, len, flags);
33925+ lockdep_on();
33926+
33927+ return ssz;
33928+}
33929+
1facf9fc 33930+/* ---------------------------------------------------------------------- */
33931+
33932+static inline loff_t vfsub_llseek(struct file *file, loff_t offset, int origin)
33933+{
33934+ loff_t err;
33935+
2cbb1c4b 33936+ lockdep_off();
1facf9fc 33937+ err = vfs_llseek(file, offset, origin);
2cbb1c4b 33938+ lockdep_on();
1facf9fc 33939+ return err;
33940+}
33941+
33942+/* ---------------------------------------------------------------------- */
33943+
4a4d8108
AM
33944+int vfsub_sio_mkdir(struct inode *dir, struct path *path, int mode);
33945+int vfsub_sio_rmdir(struct inode *dir, struct path *path);
523b37e3
AM
33946+int vfsub_sio_notify_change(struct path *path, struct iattr *ia,
33947+ struct inode **delegated_inode);
33948+int vfsub_notify_change(struct path *path, struct iattr *ia,
33949+ struct inode **delegated_inode);
33950+int vfsub_unlink(struct inode *dir, struct path *path,
33951+ struct inode **delegated_inode, int force);
4a4d8108 33952+
521ced18
JR
33953+static inline int vfsub_getattr(const struct path *path, struct kstat *st)
33954+{
33955+ return vfs_getattr(path, st, STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT);
33956+}
33957+
c1595e42
JR
33958+/* ---------------------------------------------------------------------- */
33959+
33960+static inline int vfsub_setxattr(struct dentry *dentry, const char *name,
33961+ const void *value, size_t size, int flags)
33962+{
33963+ int err;
33964+
33965+ lockdep_off();
33966+ err = vfs_setxattr(dentry, name, value, size, flags);
33967+ lockdep_on();
33968+
33969+ return err;
33970+}
33971+
33972+static inline int vfsub_removexattr(struct dentry *dentry, const char *name)
33973+{
33974+ int err;
33975+
33976+ lockdep_off();
33977+ err = vfs_removexattr(dentry, name);
33978+ lockdep_on();
33979+
33980+ return err;
33981+}
33982+
1facf9fc 33983+#endif /* __KERNEL__ */
33984+#endif /* __AUFS_VFSUB_H__ */
7f207e10 33985diff -urN /usr/share/empty/fs/aufs/wbr_policy.c linux/fs/aufs/wbr_policy.c
eca34b5c 33986--- /usr/share/empty/fs/aufs/wbr_policy.c 1970-01-01 01:00:00.000000000 +0100
016522bc 33987+++ linux/fs/aufs/wbr_policy.c 2020-01-27 10:57:18.178871751 +0100
cd7a4cd9
AM
33988@@ -0,0 +1,830 @@
33989+// SPDX-License-Identifier: GPL-2.0
1facf9fc 33990+/*
016522bc 33991+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 33992+ *
33993+ * This program, aufs is free software; you can redistribute it and/or modify
33994+ * it under the terms of the GNU General Public License as published by
33995+ * the Free Software Foundation; either version 2 of the License, or
33996+ * (at your option) any later version.
dece6358
AM
33997+ *
33998+ * This program is distributed in the hope that it will be useful,
33999+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
34000+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34001+ * GNU General Public License for more details.
34002+ *
34003+ * You should have received a copy of the GNU General Public License
523b37e3 34004+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 34005+ */
34006+
34007+/*
34008+ * policies for selecting one among multiple writable branches
34009+ */
34010+
34011+#include <linux/statfs.h>
34012+#include "aufs.h"
34013+
34014+/* subset of cpup_attr() */
34015+static noinline_for_stack
34016+int au_cpdown_attr(struct path *h_path, struct dentry *h_src)
34017+{
34018+ int err, sbits;
34019+ struct iattr ia;
34020+ struct inode *h_isrc;
34021+
5527c038 34022+ h_isrc = d_inode(h_src);
1facf9fc 34023+ ia.ia_valid = ATTR_FORCE | ATTR_MODE | ATTR_UID | ATTR_GID;
34024+ ia.ia_mode = h_isrc->i_mode;
34025+ ia.ia_uid = h_isrc->i_uid;
34026+ ia.ia_gid = h_isrc->i_gid;
34027+ sbits = !!(ia.ia_mode & (S_ISUID | S_ISGID));
5527c038 34028+ au_cpup_attr_flags(d_inode(h_path->dentry), h_isrc->i_flags);
523b37e3
AM
34029+ /* no delegation since it is just created */
34030+ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL);
1facf9fc 34031+
34032+ /* is this nfs only? */
34033+ if (!err && sbits && au_test_nfs(h_path->dentry->d_sb)) {
34034+ ia.ia_valid = ATTR_FORCE | ATTR_MODE;
34035+ ia.ia_mode = h_isrc->i_mode;
523b37e3 34036+ err = vfsub_sio_notify_change(h_path, &ia, /*delegated*/NULL);
1facf9fc 34037+ }
34038+
34039+ return err;
34040+}
34041+
34042+#define AuCpdown_PARENT_OPQ 1
34043+#define AuCpdown_WHED (1 << 1)
34044+#define AuCpdown_MADE_DIR (1 << 2)
34045+#define AuCpdown_DIROPQ (1 << 3)
34046+#define au_ftest_cpdown(flags, name) ((flags) & AuCpdown_##name)
7f207e10
AM
34047+#define au_fset_cpdown(flags, name) \
34048+ do { (flags) |= AuCpdown_##name; } while (0)
34049+#define au_fclr_cpdown(flags, name) \
34050+ do { (flags) &= ~AuCpdown_##name; } while (0)
1facf9fc 34051+
1facf9fc 34052+static int au_cpdown_dir_opq(struct dentry *dentry, aufs_bindex_t bdst,
c2b27bf2 34053+ unsigned int *flags)
1facf9fc 34054+{
34055+ int err;
34056+ struct dentry *opq_dentry;
34057+
34058+ opq_dentry = au_diropq_create(dentry, bdst);
34059+ err = PTR_ERR(opq_dentry);
34060+ if (IS_ERR(opq_dentry))
34061+ goto out;
34062+ dput(opq_dentry);
c2b27bf2 34063+ au_fset_cpdown(*flags, DIROPQ);
1facf9fc 34064+
4f0767ce 34065+out:
1facf9fc 34066+ return err;
34067+}
34068+
34069+static int au_cpdown_dir_wh(struct dentry *dentry, struct dentry *h_parent,
34070+ struct inode *dir, aufs_bindex_t bdst)
34071+{
34072+ int err;
34073+ struct path h_path;
34074+ struct au_branch *br;
34075+
34076+ br = au_sbr(dentry->d_sb, bdst);
34077+ h_path.dentry = au_wh_lkup(h_parent, &dentry->d_name, br);
34078+ err = PTR_ERR(h_path.dentry);
34079+ if (IS_ERR(h_path.dentry))
34080+ goto out;
34081+
34082+ err = 0;
5527c038 34083+ if (d_is_positive(h_path.dentry)) {
86dc4139 34084+ h_path.mnt = au_br_mnt(br);
1facf9fc 34085+ err = au_wh_unlink_dentry(au_h_iptr(dir, bdst), &h_path,
34086+ dentry);
34087+ }
34088+ dput(h_path.dentry);
34089+
4f0767ce 34090+out:
1facf9fc 34091+ return err;
34092+}
34093+
34094+static int au_cpdown_dir(struct dentry *dentry, aufs_bindex_t bdst,
86dc4139 34095+ struct au_pin *pin,
1facf9fc 34096+ struct dentry *h_parent, void *arg)
34097+{
34098+ int err, rerr;
5afbbe0d 34099+ aufs_bindex_t bopq, btop;
1facf9fc 34100+ struct path h_path;
34101+ struct dentry *parent;
34102+ struct inode *h_dir, *h_inode, *inode, *dir;
c2b27bf2 34103+ unsigned int *flags = arg;
1facf9fc 34104+
5afbbe0d 34105+ btop = au_dbtop(dentry);
1facf9fc 34106+ /* dentry is di-locked */
34107+ parent = dget_parent(dentry);
5527c038
JR
34108+ dir = d_inode(parent);
34109+ h_dir = d_inode(h_parent);
1facf9fc 34110+ AuDebugOn(h_dir != au_h_iptr(dir, bdst));
34111+ IMustLock(h_dir);
34112+
86dc4139 34113+ err = au_lkup_neg(dentry, bdst, /*wh*/0);
1facf9fc 34114+ if (unlikely(err < 0))
34115+ goto out;
34116+ h_path.dentry = au_h_dptr(dentry, bdst);
34117+ h_path.mnt = au_sbr_mnt(dentry->d_sb, bdst);
cd7a4cd9 34118+ err = vfsub_sio_mkdir(au_h_iptr(dir, bdst), &h_path, 0755);
1facf9fc 34119+ if (unlikely(err))
34120+ goto out_put;
c2b27bf2 34121+ au_fset_cpdown(*flags, MADE_DIR);
1facf9fc 34122+
1facf9fc 34123+ bopq = au_dbdiropq(dentry);
c2b27bf2
AM
34124+ au_fclr_cpdown(*flags, WHED);
34125+ au_fclr_cpdown(*flags, DIROPQ);
1facf9fc 34126+ if (au_dbwh(dentry) == bdst)
c2b27bf2
AM
34127+ au_fset_cpdown(*flags, WHED);
34128+ if (!au_ftest_cpdown(*flags, PARENT_OPQ) && bopq <= bdst)
34129+ au_fset_cpdown(*flags, PARENT_OPQ);
5527c038 34130+ h_inode = d_inode(h_path.dentry);
febd17d6 34131+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
c2b27bf2
AM
34132+ if (au_ftest_cpdown(*flags, WHED)) {
34133+ err = au_cpdown_dir_opq(dentry, bdst, flags);
1facf9fc 34134+ if (unlikely(err)) {
febd17d6 34135+ inode_unlock(h_inode);
1facf9fc 34136+ goto out_dir;
34137+ }
34138+ }
34139+
5afbbe0d 34140+ err = au_cpdown_attr(&h_path, au_h_dptr(dentry, btop));
febd17d6 34141+ inode_unlock(h_inode);
1facf9fc 34142+ if (unlikely(err))
34143+ goto out_opq;
34144+
c2b27bf2 34145+ if (au_ftest_cpdown(*flags, WHED)) {
1facf9fc 34146+ err = au_cpdown_dir_wh(dentry, h_parent, dir, bdst);
34147+ if (unlikely(err))
34148+ goto out_opq;
34149+ }
34150+
5527c038 34151+ inode = d_inode(dentry);
5afbbe0d
AM
34152+ if (au_ibbot(inode) < bdst)
34153+ au_set_ibbot(inode, bdst);
1facf9fc 34154+ au_set_h_iptr(inode, bdst, au_igrab(h_inode),
34155+ au_hi_flags(inode, /*isdir*/1));
076b876e 34156+ au_fhsm_wrote(dentry->d_sb, bdst, /*force*/0);
1facf9fc 34157+ goto out; /* success */
34158+
34159+ /* revert */
4f0767ce 34160+out_opq:
c2b27bf2 34161+ if (au_ftest_cpdown(*flags, DIROPQ)) {
febd17d6 34162+ inode_lock_nested(h_inode, AuLsc_I_CHILD);
1facf9fc 34163+ rerr = au_diropq_remove(dentry, bdst);
febd17d6 34164+ inode_unlock(h_inode);
1facf9fc 34165+ if (unlikely(rerr)) {
523b37e3
AM
34166+ AuIOErr("failed removing diropq for %pd b%d (%d)\n",
34167+ dentry, bdst, rerr);
1facf9fc 34168+ err = -EIO;
34169+ goto out;
34170+ }
34171+ }
4f0767ce 34172+out_dir:
c2b27bf2 34173+ if (au_ftest_cpdown(*flags, MADE_DIR)) {
1facf9fc 34174+ rerr = vfsub_sio_rmdir(au_h_iptr(dir, bdst), &h_path);
34175+ if (unlikely(rerr)) {
523b37e3
AM
34176+ AuIOErr("failed removing %pd b%d (%d)\n",
34177+ dentry, bdst, rerr);
1facf9fc 34178+ err = -EIO;
34179+ }
34180+ }
4f0767ce 34181+out_put:
1facf9fc 34182+ au_set_h_dptr(dentry, bdst, NULL);
5afbbe0d
AM
34183+ if (au_dbbot(dentry) == bdst)
34184+ au_update_dbbot(dentry);
4f0767ce 34185+out:
1facf9fc 34186+ dput(parent);
34187+ return err;
34188+}
34189+
34190+int au_cpdown_dirs(struct dentry *dentry, aufs_bindex_t bdst)
34191+{
34192+ int err;
c2b27bf2 34193+ unsigned int flags;
1facf9fc 34194+
c2b27bf2
AM
34195+ flags = 0;
34196+ err = au_cp_dirs(dentry, bdst, au_cpdown_dir, &flags);
1facf9fc 34197+
34198+ return err;
34199+}
34200+
34201+/* ---------------------------------------------------------------------- */
34202+
34203+/* policies for create */
34204+
c2b27bf2 34205+int au_wbr_nonopq(struct dentry *dentry, aufs_bindex_t bindex)
4a4d8108
AM
34206+{
34207+ int err, i, j, ndentry;
34208+ aufs_bindex_t bopq;
34209+ struct au_dcsub_pages dpages;
34210+ struct au_dpage *dpage;
34211+ struct dentry **dentries, *parent, *d;
34212+
34213+ err = au_dpages_init(&dpages, GFP_NOFS);
34214+ if (unlikely(err))
34215+ goto out;
34216+ parent = dget_parent(dentry);
027c5e7a 34217+ err = au_dcsub_pages_rev_aufs(&dpages, parent, /*do_include*/0);
4a4d8108
AM
34218+ if (unlikely(err))
34219+ goto out_free;
34220+
34221+ err = bindex;
34222+ for (i = 0; i < dpages.ndpage; i++) {
34223+ dpage = dpages.dpages + i;
34224+ dentries = dpage->dentries;
34225+ ndentry = dpage->ndentry;
34226+ for (j = 0; j < ndentry; j++) {
34227+ d = dentries[j];
34228+ di_read_lock_parent2(d, !AuLock_IR);
34229+ bopq = au_dbdiropq(d);
34230+ di_read_unlock(d, !AuLock_IR);
34231+ if (bopq >= 0 && bopq < err)
34232+ err = bopq;
34233+ }
34234+ }
34235+
34236+out_free:
34237+ dput(parent);
34238+ au_dpages_free(&dpages);
34239+out:
34240+ return err;
34241+}
34242+
1facf9fc 34243+static int au_wbr_bu(struct super_block *sb, aufs_bindex_t bindex)
34244+{
34245+ for (; bindex >= 0; bindex--)
34246+ if (!au_br_rdonly(au_sbr(sb, bindex)))
34247+ return bindex;
34248+ return -EROFS;
34249+}
34250+
34251+/* top down parent */
392086de
AM
34252+static int au_wbr_create_tdp(struct dentry *dentry,
34253+ unsigned int flags __maybe_unused)
1facf9fc 34254+{
34255+ int err;
5afbbe0d 34256+ aufs_bindex_t btop, bindex;
1facf9fc 34257+ struct super_block *sb;
34258+ struct dentry *parent, *h_parent;
34259+
34260+ sb = dentry->d_sb;
5afbbe0d
AM
34261+ btop = au_dbtop(dentry);
34262+ err = btop;
34263+ if (!au_br_rdonly(au_sbr(sb, btop)))
1facf9fc 34264+ goto out;
34265+
34266+ err = -EROFS;
34267+ parent = dget_parent(dentry);
5afbbe0d 34268+ for (bindex = au_dbtop(parent); bindex < btop; bindex++) {
1facf9fc 34269+ h_parent = au_h_dptr(parent, bindex);
5527c038 34270+ if (!h_parent || d_is_negative(h_parent))
1facf9fc 34271+ continue;
34272+
34273+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
34274+ err = bindex;
34275+ break;
34276+ }
34277+ }
34278+ dput(parent);
34279+
34280+ /* bottom up here */
4a4d8108 34281+ if (unlikely(err < 0)) {
5afbbe0d 34282+ err = au_wbr_bu(sb, btop - 1);
4a4d8108
AM
34283+ if (err >= 0)
34284+ err = au_wbr_nonopq(dentry, err);
34285+ }
1facf9fc 34286+
4f0767ce 34287+out:
1facf9fc 34288+ AuDbg("b%d\n", err);
34289+ return err;
34290+}
34291+
34292+/* ---------------------------------------------------------------------- */
34293+
34294+/* an exception for the policy other than tdp */
34295+static int au_wbr_create_exp(struct dentry *dentry)
34296+{
34297+ int err;
34298+ aufs_bindex_t bwh, bdiropq;
34299+ struct dentry *parent;
34300+
34301+ err = -1;
34302+ bwh = au_dbwh(dentry);
34303+ parent = dget_parent(dentry);
34304+ bdiropq = au_dbdiropq(parent);
34305+ if (bwh >= 0) {
34306+ if (bdiropq >= 0)
34307+ err = min(bdiropq, bwh);
34308+ else
34309+ err = bwh;
34310+ AuDbg("%d\n", err);
34311+ } else if (bdiropq >= 0) {
34312+ err = bdiropq;
34313+ AuDbg("%d\n", err);
34314+ }
34315+ dput(parent);
34316+
4a4d8108
AM
34317+ if (err >= 0)
34318+ err = au_wbr_nonopq(dentry, err);
34319+
1facf9fc 34320+ if (err >= 0 && au_br_rdonly(au_sbr(dentry->d_sb, err)))
34321+ err = -1;
34322+
34323+ AuDbg("%d\n", err);
34324+ return err;
34325+}
34326+
34327+/* ---------------------------------------------------------------------- */
34328+
34329+/* round robin */
34330+static int au_wbr_create_init_rr(struct super_block *sb)
34331+{
34332+ int err;
34333+
5afbbe0d 34334+ err = au_wbr_bu(sb, au_sbbot(sb));
1facf9fc 34335+ atomic_set(&au_sbi(sb)->si_wbr_rr_next, -err); /* less important */
dece6358 34336+ /* smp_mb(); */
1facf9fc 34337+
34338+ AuDbg("b%d\n", err);
34339+ return err;
34340+}
34341+
392086de 34342+static int au_wbr_create_rr(struct dentry *dentry, unsigned int flags)
1facf9fc 34343+{
34344+ int err, nbr;
34345+ unsigned int u;
5afbbe0d 34346+ aufs_bindex_t bindex, bbot;
1facf9fc 34347+ struct super_block *sb;
34348+ atomic_t *next;
34349+
34350+ err = au_wbr_create_exp(dentry);
34351+ if (err >= 0)
34352+ goto out;
34353+
34354+ sb = dentry->d_sb;
34355+ next = &au_sbi(sb)->si_wbr_rr_next;
5afbbe0d
AM
34356+ bbot = au_sbbot(sb);
34357+ nbr = bbot + 1;
34358+ for (bindex = 0; bindex <= bbot; bindex++) {
392086de 34359+ if (!au_ftest_wbr(flags, DIR)) {
1facf9fc 34360+ err = atomic_dec_return(next) + 1;
34361+ /* modulo for 0 is meaningless */
34362+ if (unlikely(!err))
34363+ err = atomic_dec_return(next) + 1;
34364+ } else
34365+ err = atomic_read(next);
34366+ AuDbg("%d\n", err);
34367+ u = err;
34368+ err = u % nbr;
34369+ AuDbg("%d\n", err);
34370+ if (!au_br_rdonly(au_sbr(sb, err)))
34371+ break;
34372+ err = -EROFS;
34373+ }
34374+
4a4d8108
AM
34375+ if (err >= 0)
34376+ err = au_wbr_nonopq(dentry, err);
34377+
4f0767ce 34378+out:
1facf9fc 34379+ AuDbg("%d\n", err);
34380+ return err;
34381+}
34382+
34383+/* ---------------------------------------------------------------------- */
34384+
34385+/* most free space */
392086de 34386+static void au_mfs(struct dentry *dentry, struct dentry *parent)
1facf9fc 34387+{
34388+ struct super_block *sb;
34389+ struct au_branch *br;
34390+ struct au_wbr_mfs *mfs;
392086de 34391+ struct dentry *h_parent;
5afbbe0d 34392+ aufs_bindex_t bindex, bbot;
1facf9fc 34393+ int err;
34394+ unsigned long long b, bavail;
7f207e10 34395+ struct path h_path;
1facf9fc 34396+ /* reduce the stack usage */
34397+ struct kstatfs *st;
34398+
34399+ st = kmalloc(sizeof(*st), GFP_NOFS);
34400+ if (unlikely(!st)) {
34401+ AuWarn1("failed updating mfs(%d), ignored\n", -ENOMEM);
34402+ return;
34403+ }
34404+
34405+ bavail = 0;
34406+ sb = dentry->d_sb;
34407+ mfs = &au_sbi(sb)->si_wbr_mfs;
dece6358 34408+ MtxMustLock(&mfs->mfs_lock);
1facf9fc 34409+ mfs->mfs_bindex = -EROFS;
34410+ mfs->mfsrr_bytes = 0;
392086de
AM
34411+ if (!parent) {
34412+ bindex = 0;
5afbbe0d 34413+ bbot = au_sbbot(sb);
392086de 34414+ } else {
5afbbe0d
AM
34415+ bindex = au_dbtop(parent);
34416+ bbot = au_dbtaildir(parent);
392086de
AM
34417+ }
34418+
5afbbe0d 34419+ for (; bindex <= bbot; bindex++) {
392086de
AM
34420+ if (parent) {
34421+ h_parent = au_h_dptr(parent, bindex);
5527c038 34422+ if (!h_parent || d_is_negative(h_parent))
392086de
AM
34423+ continue;
34424+ }
1facf9fc 34425+ br = au_sbr(sb, bindex);
34426+ if (au_br_rdonly(br))
34427+ continue;
34428+
34429+ /* sb->s_root for NFS is unreliable */
86dc4139 34430+ h_path.mnt = au_br_mnt(br);
7f207e10
AM
34431+ h_path.dentry = h_path.mnt->mnt_root;
34432+ err = vfs_statfs(&h_path, st);
1facf9fc 34433+ if (unlikely(err)) {
34434+ AuWarn1("failed statfs, b%d, %d\n", bindex, err);
34435+ continue;
34436+ }
34437+
34438+ /* when the available size is equal, select the lower one */
34439+ BUILD_BUG_ON(sizeof(b) < sizeof(st->f_bavail)
34440+ || sizeof(b) < sizeof(st->f_bsize));
34441+ b = st->f_bavail * st->f_bsize;
34442+ br->br_wbr->wbr_bytes = b;
34443+ if (b >= bavail) {
34444+ bavail = b;
34445+ mfs->mfs_bindex = bindex;
34446+ mfs->mfs_jiffy = jiffies;
34447+ }
34448+ }
34449+
34450+ mfs->mfsrr_bytes = bavail;
34451+ AuDbg("b%d\n", mfs->mfs_bindex);
9f237c51 34452+ au_kfree_rcu(st);
1facf9fc 34453+}
34454+
392086de 34455+static int au_wbr_create_mfs(struct dentry *dentry, unsigned int flags)
1facf9fc 34456+{
34457+ int err;
392086de 34458+ struct dentry *parent;
1facf9fc 34459+ struct super_block *sb;
34460+ struct au_wbr_mfs *mfs;
34461+
34462+ err = au_wbr_create_exp(dentry);
34463+ if (err >= 0)
34464+ goto out;
34465+
34466+ sb = dentry->d_sb;
392086de
AM
34467+ parent = NULL;
34468+ if (au_ftest_wbr(flags, PARENT))
34469+ parent = dget_parent(dentry);
1facf9fc 34470+ mfs = &au_sbi(sb)->si_wbr_mfs;
34471+ mutex_lock(&mfs->mfs_lock);
34472+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
34473+ || mfs->mfs_bindex < 0
34474+ || au_br_rdonly(au_sbr(sb, mfs->mfs_bindex)))
392086de 34475+ au_mfs(dentry, parent);
1facf9fc 34476+ mutex_unlock(&mfs->mfs_lock);
34477+ err = mfs->mfs_bindex;
392086de 34478+ dput(parent);
1facf9fc 34479+
4a4d8108
AM
34480+ if (err >= 0)
34481+ err = au_wbr_nonopq(dentry, err);
34482+
4f0767ce 34483+out:
1facf9fc 34484+ AuDbg("b%d\n", err);
34485+ return err;
34486+}
34487+
34488+static int au_wbr_create_init_mfs(struct super_block *sb)
34489+{
34490+ struct au_wbr_mfs *mfs;
34491+
34492+ mfs = &au_sbi(sb)->si_wbr_mfs;
34493+ mutex_init(&mfs->mfs_lock);
34494+ mfs->mfs_jiffy = 0;
34495+ mfs->mfs_bindex = -EROFS;
34496+
34497+ return 0;
34498+}
34499+
34500+static int au_wbr_create_fin_mfs(struct super_block *sb __maybe_unused)
34501+{
34502+ mutex_destroy(&au_sbi(sb)->si_wbr_mfs.mfs_lock);
34503+ return 0;
34504+}
34505+
34506+/* ---------------------------------------------------------------------- */
34507+
f2c43d5f
AM
34508+/* top down regardless parent, and then mfs */
34509+static int au_wbr_create_tdmfs(struct dentry *dentry,
34510+ unsigned int flags __maybe_unused)
34511+{
34512+ int err;
34513+ aufs_bindex_t bwh, btail, bindex, bfound, bmfs;
34514+ unsigned long long watermark;
34515+ struct super_block *sb;
34516+ struct au_wbr_mfs *mfs;
34517+ struct au_branch *br;
34518+ struct dentry *parent;
34519+
34520+ sb = dentry->d_sb;
34521+ mfs = &au_sbi(sb)->si_wbr_mfs;
34522+ mutex_lock(&mfs->mfs_lock);
34523+ if (time_after(jiffies, mfs->mfs_jiffy + mfs->mfs_expire)
34524+ || mfs->mfs_bindex < 0)
34525+ au_mfs(dentry, /*parent*/NULL);
34526+ watermark = mfs->mfsrr_watermark;
34527+ bmfs = mfs->mfs_bindex;
34528+ mutex_unlock(&mfs->mfs_lock);
34529+
34530+ /* another style of au_wbr_create_exp() */
34531+ bwh = au_dbwh(dentry);
34532+ parent = dget_parent(dentry);
34533+ btail = au_dbtaildir(parent);
34534+ if (bwh >= 0 && bwh < btail)
34535+ btail = bwh;
34536+
34537+ err = au_wbr_nonopq(dentry, btail);
34538+ if (unlikely(err < 0))
34539+ goto out;
34540+ btail = err;
34541+ bfound = -1;
34542+ for (bindex = 0; bindex <= btail; bindex++) {
34543+ br = au_sbr(sb, bindex);
34544+ if (au_br_rdonly(br))
34545+ continue;
34546+ if (br->br_wbr->wbr_bytes > watermark) {
34547+ bfound = bindex;
34548+ break;
34549+ }
34550+ }
34551+ err = bfound;
34552+ if (err < 0)
34553+ err = bmfs;
34554+
34555+out:
34556+ dput(parent);
34557+ AuDbg("b%d\n", err);
34558+ return err;
34559+}
34560+
34561+/* ---------------------------------------------------------------------- */
34562+
1facf9fc 34563+/* most free space and then round robin */
392086de 34564+static int au_wbr_create_mfsrr(struct dentry *dentry, unsigned int flags)
1facf9fc 34565+{
34566+ int err;
34567+ struct au_wbr_mfs *mfs;
34568+
392086de 34569+ err = au_wbr_create_mfs(dentry, flags);
1facf9fc 34570+ if (err >= 0) {
34571+ mfs = &au_sbi(dentry->d_sb)->si_wbr_mfs;
dece6358 34572+ mutex_lock(&mfs->mfs_lock);
1facf9fc 34573+ if (mfs->mfsrr_bytes < mfs->mfsrr_watermark)
392086de 34574+ err = au_wbr_create_rr(dentry, flags);
dece6358 34575+ mutex_unlock(&mfs->mfs_lock);
1facf9fc 34576+ }
34577+
34578+ AuDbg("b%d\n", err);
34579+ return err;
34580+}
34581+
34582+static int au_wbr_create_init_mfsrr(struct super_block *sb)
34583+{
34584+ int err;
34585+
34586+ au_wbr_create_init_mfs(sb); /* ignore */
34587+ err = au_wbr_create_init_rr(sb);
34588+
34589+ return err;
34590+}
34591+
34592+/* ---------------------------------------------------------------------- */
34593+
34594+/* top down parent and most free space */
392086de 34595+static int au_wbr_create_pmfs(struct dentry *dentry, unsigned int flags)
1facf9fc 34596+{
34597+ int err, e2;
34598+ unsigned long long b;
5afbbe0d 34599+ aufs_bindex_t bindex, btop, bbot;
1facf9fc 34600+ struct super_block *sb;
34601+ struct dentry *parent, *h_parent;
34602+ struct au_branch *br;
34603+
392086de 34604+ err = au_wbr_create_tdp(dentry, flags);
1facf9fc 34605+ if (unlikely(err < 0))
34606+ goto out;
34607+ parent = dget_parent(dentry);
5afbbe0d
AM
34608+ btop = au_dbtop(parent);
34609+ bbot = au_dbtaildir(parent);
34610+ if (btop == bbot)
1facf9fc 34611+ goto out_parent; /* success */
34612+
392086de 34613+ e2 = au_wbr_create_mfs(dentry, flags);
1facf9fc 34614+ if (e2 < 0)
34615+ goto out_parent; /* success */
34616+
34617+ /* when the available size is equal, select upper one */
34618+ sb = dentry->d_sb;
34619+ br = au_sbr(sb, err);
34620+ b = br->br_wbr->wbr_bytes;
34621+ AuDbg("b%d, %llu\n", err, b);
34622+
5afbbe0d 34623+ for (bindex = btop; bindex <= bbot; bindex++) {
1facf9fc 34624+ h_parent = au_h_dptr(parent, bindex);
5527c038 34625+ if (!h_parent || d_is_negative(h_parent))
1facf9fc 34626+ continue;
34627+
34628+ br = au_sbr(sb, bindex);
34629+ if (!au_br_rdonly(br) && br->br_wbr->wbr_bytes > b) {
34630+ b = br->br_wbr->wbr_bytes;
34631+ err = bindex;
34632+ AuDbg("b%d, %llu\n", err, b);
34633+ }
34634+ }
34635+
4a4d8108
AM
34636+ if (err >= 0)
34637+ err = au_wbr_nonopq(dentry, err);
34638+
4f0767ce 34639+out_parent:
1facf9fc 34640+ dput(parent);
4f0767ce 34641+out:
1facf9fc 34642+ AuDbg("b%d\n", err);
34643+ return err;
34644+}
34645+
34646+/* ---------------------------------------------------------------------- */
34647+
392086de
AM
34648+/*
34649+ * - top down parent
34650+ * - most free space with parent
34651+ * - most free space round-robin regardless parent
34652+ */
34653+static int au_wbr_create_pmfsrr(struct dentry *dentry, unsigned int flags)
34654+{
34655+ int err;
34656+ unsigned long long watermark;
34657+ struct super_block *sb;
34658+ struct au_branch *br;
34659+ struct au_wbr_mfs *mfs;
34660+
34661+ err = au_wbr_create_pmfs(dentry, flags | AuWbr_PARENT);
34662+ if (unlikely(err < 0))
34663+ goto out;
34664+
34665+ sb = dentry->d_sb;
34666+ br = au_sbr(sb, err);
34667+ mfs = &au_sbi(sb)->si_wbr_mfs;
34668+ mutex_lock(&mfs->mfs_lock);
34669+ watermark = mfs->mfsrr_watermark;
34670+ mutex_unlock(&mfs->mfs_lock);
34671+ if (br->br_wbr->wbr_bytes < watermark)
34672+ /* regardless the parent dir */
34673+ err = au_wbr_create_mfsrr(dentry, flags);
34674+
34675+out:
34676+ AuDbg("b%d\n", err);
34677+ return err;
34678+}
34679+
34680+/* ---------------------------------------------------------------------- */
34681+
1facf9fc 34682+/* policies for copyup */
34683+
34684+/* top down parent */
34685+static int au_wbr_copyup_tdp(struct dentry *dentry)
34686+{
392086de 34687+ return au_wbr_create_tdp(dentry, /*flags, anything is ok*/0);
1facf9fc 34688+}
34689+
34690+/* bottom up parent */
34691+static int au_wbr_copyup_bup(struct dentry *dentry)
34692+{
34693+ int err;
5afbbe0d 34694+ aufs_bindex_t bindex, btop;
1facf9fc 34695+ struct dentry *parent, *h_parent;
34696+ struct super_block *sb;
34697+
34698+ err = -EROFS;
34699+ sb = dentry->d_sb;
34700+ parent = dget_parent(dentry);
5afbbe0d
AM
34701+ btop = au_dbtop(parent);
34702+ for (bindex = au_dbtop(dentry); bindex >= btop; bindex--) {
1facf9fc 34703+ h_parent = au_h_dptr(parent, bindex);
5527c038 34704+ if (!h_parent || d_is_negative(h_parent))
1facf9fc 34705+ continue;
34706+
34707+ if (!au_br_rdonly(au_sbr(sb, bindex))) {
34708+ err = bindex;
34709+ break;
34710+ }
34711+ }
34712+ dput(parent);
34713+
34714+ /* bottom up here */
34715+ if (unlikely(err < 0))
5afbbe0d 34716+ err = au_wbr_bu(sb, btop - 1);
1facf9fc 34717+
34718+ AuDbg("b%d\n", err);
34719+ return err;
34720+}
34721+
34722+/* bottom up */
5afbbe0d 34723+int au_wbr_do_copyup_bu(struct dentry *dentry, aufs_bindex_t btop)
1facf9fc 34724+{
34725+ int err;
34726+
5afbbe0d 34727+ err = au_wbr_bu(dentry->d_sb, btop);
4a4d8108 34728+ AuDbg("b%d\n", err);
5afbbe0d 34729+ if (err > btop)
4a4d8108 34730+ err = au_wbr_nonopq(dentry, err);
1facf9fc 34731+
34732+ AuDbg("b%d\n", err);
34733+ return err;
34734+}
34735+
076b876e
AM
34736+static int au_wbr_copyup_bu(struct dentry *dentry)
34737+{
34738+ int err;
5afbbe0d 34739+ aufs_bindex_t btop;
076b876e 34740+
5afbbe0d
AM
34741+ btop = au_dbtop(dentry);
34742+ err = au_wbr_do_copyup_bu(dentry, btop);
076b876e
AM
34743+ return err;
34744+}
34745+
1facf9fc 34746+/* ---------------------------------------------------------------------- */
34747+
34748+struct au_wbr_copyup_operations au_wbr_copyup_ops[] = {
34749+ [AuWbrCopyup_TDP] = {
34750+ .copyup = au_wbr_copyup_tdp
34751+ },
34752+ [AuWbrCopyup_BUP] = {
34753+ .copyup = au_wbr_copyup_bup
34754+ },
34755+ [AuWbrCopyup_BU] = {
34756+ .copyup = au_wbr_copyup_bu
34757+ }
34758+};
34759+
34760+struct au_wbr_create_operations au_wbr_create_ops[] = {
34761+ [AuWbrCreate_TDP] = {
34762+ .create = au_wbr_create_tdp
34763+ },
34764+ [AuWbrCreate_RR] = {
34765+ .create = au_wbr_create_rr,
34766+ .init = au_wbr_create_init_rr
34767+ },
34768+ [AuWbrCreate_MFS] = {
34769+ .create = au_wbr_create_mfs,
34770+ .init = au_wbr_create_init_mfs,
34771+ .fin = au_wbr_create_fin_mfs
34772+ },
34773+ [AuWbrCreate_MFSV] = {
34774+ .create = au_wbr_create_mfs,
34775+ .init = au_wbr_create_init_mfs,
34776+ .fin = au_wbr_create_fin_mfs
34777+ },
34778+ [AuWbrCreate_MFSRR] = {
34779+ .create = au_wbr_create_mfsrr,
34780+ .init = au_wbr_create_init_mfsrr,
34781+ .fin = au_wbr_create_fin_mfs
34782+ },
34783+ [AuWbrCreate_MFSRRV] = {
34784+ .create = au_wbr_create_mfsrr,
34785+ .init = au_wbr_create_init_mfsrr,
34786+ .fin = au_wbr_create_fin_mfs
34787+ },
f2c43d5f
AM
34788+ [AuWbrCreate_TDMFS] = {
34789+ .create = au_wbr_create_tdmfs,
34790+ .init = au_wbr_create_init_mfs,
34791+ .fin = au_wbr_create_fin_mfs
34792+ },
34793+ [AuWbrCreate_TDMFSV] = {
34794+ .create = au_wbr_create_tdmfs,
34795+ .init = au_wbr_create_init_mfs,
34796+ .fin = au_wbr_create_fin_mfs
34797+ },
1facf9fc 34798+ [AuWbrCreate_PMFS] = {
34799+ .create = au_wbr_create_pmfs,
34800+ .init = au_wbr_create_init_mfs,
34801+ .fin = au_wbr_create_fin_mfs
34802+ },
34803+ [AuWbrCreate_PMFSV] = {
34804+ .create = au_wbr_create_pmfs,
34805+ .init = au_wbr_create_init_mfs,
34806+ .fin = au_wbr_create_fin_mfs
392086de
AM
34807+ },
34808+ [AuWbrCreate_PMFSRR] = {
34809+ .create = au_wbr_create_pmfsrr,
34810+ .init = au_wbr_create_init_mfsrr,
34811+ .fin = au_wbr_create_fin_mfs
34812+ },
34813+ [AuWbrCreate_PMFSRRV] = {
34814+ .create = au_wbr_create_pmfsrr,
34815+ .init = au_wbr_create_init_mfsrr,
34816+ .fin = au_wbr_create_fin_mfs
1facf9fc 34817+ }
34818+};
7f207e10 34819diff -urN /usr/share/empty/fs/aufs/whout.c linux/fs/aufs/whout.c
eca34b5c 34820--- /usr/share/empty/fs/aufs/whout.c 1970-01-01 01:00:00.000000000 +0100
016522bc 34821+++ linux/fs/aufs/whout.c 2020-01-27 10:57:18.178871751 +0100
062440b3 34822@@ -0,0 +1,1062 @@
cd7a4cd9 34823+// SPDX-License-Identifier: GPL-2.0
1facf9fc 34824+/*
016522bc 34825+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 34826+ *
34827+ * This program, aufs is free software; you can redistribute it and/or modify
34828+ * it under the terms of the GNU General Public License as published by
34829+ * the Free Software Foundation; either version 2 of the License, or
34830+ * (at your option) any later version.
dece6358
AM
34831+ *
34832+ * This program is distributed in the hope that it will be useful,
34833+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
34834+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34835+ * GNU General Public License for more details.
34836+ *
34837+ * You should have received a copy of the GNU General Public License
523b37e3 34838+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 34839+ */
34840+
34841+/*
34842+ * whiteout for logical deletion and opaque directory
34843+ */
34844+
1facf9fc 34845+#include "aufs.h"
34846+
cd7a4cd9 34847+#define WH_MASK 0444
1facf9fc 34848+
34849+/*
34850+ * If a directory contains this file, then it is opaque. We start with the
34851+ * .wh. flag so that it is blocked by lookup.
34852+ */
0c3ec466
AM
34853+static struct qstr diropq_name = QSTR_INIT(AUFS_WH_DIROPQ,
34854+ sizeof(AUFS_WH_DIROPQ) - 1);
1facf9fc 34855+
34856+/*
34857+ * generate whiteout name, which is NOT terminated by NULL.
34858+ * @name: original d_name.name
34859+ * @len: original d_name.len
34860+ * @wh: whiteout qstr
34861+ * returns zero when succeeds, otherwise error.
34862+ * succeeded value as wh->name should be freed by kfree().
34863+ */
34864+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name)
34865+{
34866+ char *p;
34867+
34868+ if (unlikely(name->len > PATH_MAX - AUFS_WH_PFX_LEN))
34869+ return -ENAMETOOLONG;
34870+
34871+ wh->len = name->len + AUFS_WH_PFX_LEN;
34872+ p = kmalloc(wh->len, GFP_NOFS);
34873+ wh->name = p;
34874+ if (p) {
34875+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
34876+ memcpy(p + AUFS_WH_PFX_LEN, name->name, name->len);
34877+ /* smp_mb(); */
34878+ return 0;
34879+ }
34880+ return -ENOMEM;
34881+}
34882+
34883+/* ---------------------------------------------------------------------- */
34884+
34885+/*
34886+ * test if the @wh_name exists under @h_parent.
34887+ * @try_sio specifies the necessary of super-io.
34888+ */
076b876e 34889+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio)
1facf9fc 34890+{
34891+ int err;
34892+ struct dentry *wh_dentry;
1facf9fc 34893+
1facf9fc 34894+ if (!try_sio)
b4510431 34895+ wh_dentry = vfsub_lkup_one(wh_name, h_parent);
1facf9fc 34896+ else
076b876e 34897+ wh_dentry = au_sio_lkup_one(wh_name, h_parent);
1facf9fc 34898+ err = PTR_ERR(wh_dentry);
2000de60
JR
34899+ if (IS_ERR(wh_dentry)) {
34900+ if (err == -ENAMETOOLONG)
34901+ err = 0;
1facf9fc 34902+ goto out;
2000de60 34903+ }
1facf9fc 34904+
34905+ err = 0;
5527c038 34906+ if (d_is_negative(wh_dentry))
1facf9fc 34907+ goto out_wh; /* success */
34908+
34909+ err = 1;
7e9cd9fe 34910+ if (d_is_reg(wh_dentry))
1facf9fc 34911+ goto out_wh; /* success */
34912+
34913+ err = -EIO;
523b37e3 34914+ AuIOErr("%pd Invalid whiteout entry type 0%o.\n",
5527c038 34915+ wh_dentry, d_inode(wh_dentry)->i_mode);
1facf9fc 34916+
4f0767ce 34917+out_wh:
1facf9fc 34918+ dput(wh_dentry);
4f0767ce 34919+out:
1facf9fc 34920+ return err;
34921+}
34922+
34923+/*
34924+ * test if the @h_dentry sets opaque or not.
34925+ */
076b876e 34926+int au_diropq_test(struct dentry *h_dentry)
1facf9fc 34927+{
34928+ int err;
34929+ struct inode *h_dir;
34930+
5527c038 34931+ h_dir = d_inode(h_dentry);
076b876e 34932+ err = au_wh_test(h_dentry, &diropq_name,
1facf9fc 34933+ au_test_h_perm_sio(h_dir, MAY_EXEC));
34934+ return err;
34935+}
34936+
34937+/*
34938+ * returns a negative dentry whose name is unique and temporary.
34939+ */
34940+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
34941+ struct qstr *prefix)
34942+{
1facf9fc 34943+ struct dentry *dentry;
34944+ int i;
027c5e7a 34945+ char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1],
4a4d8108 34946+ *name, *p;
027c5e7a 34947+ /* strict atomic_t is unnecessary here */
1facf9fc 34948+ static unsigned short cnt;
34949+ struct qstr qs;
34950+
4a4d8108
AM
34951+ BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN);
34952+
1facf9fc 34953+ name = defname;
027c5e7a
AM
34954+ qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1;
34955+ if (unlikely(prefix->len > DNAME_INLINE_LEN)) {
1facf9fc 34956+ dentry = ERR_PTR(-ENAMETOOLONG);
4a4d8108 34957+ if (unlikely(qs.len > NAME_MAX))
1facf9fc 34958+ goto out;
34959+ dentry = ERR_PTR(-ENOMEM);
34960+ name = kmalloc(qs.len + 1, GFP_NOFS);
34961+ if (unlikely(!name))
34962+ goto out;
34963+ }
34964+
34965+ /* doubly whiteout-ed */
34966+ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2);
34967+ p = name + AUFS_WH_PFX_LEN * 2;
34968+ memcpy(p, prefix->name, prefix->len);
34969+ p += prefix->len;
34970+ *p++ = '.';
4a4d8108 34971+ AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN);
1facf9fc 34972+
34973+ qs.name = name;
34974+ for (i = 0; i < 3; i++) {
b752ccd1 34975+ sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++);
076b876e 34976+ dentry = au_sio_lkup_one(&qs, h_parent);
5527c038 34977+ if (IS_ERR(dentry) || d_is_negative(dentry))
1facf9fc 34978+ goto out_name;
34979+ dput(dentry);
34980+ }
0c3ec466 34981+ /* pr_warn("could not get random name\n"); */
1facf9fc 34982+ dentry = ERR_PTR(-EEXIST);
34983+ AuDbg("%.*s\n", AuLNPair(&qs));
34984+ BUG();
34985+
4f0767ce 34986+out_name:
1facf9fc 34987+ if (name != defname)
9f237c51 34988+ au_kfree_try_rcu(name);
4f0767ce 34989+out:
4a4d8108 34990+ AuTraceErrPtr(dentry);
1facf9fc 34991+ return dentry;
1facf9fc 34992+}
34993+
34994+/*
34995+ * rename the @h_dentry on @br to the whiteouted temporary name.
34996+ */
34997+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br)
34998+{
34999+ int err;
35000+ struct path h_path = {
86dc4139 35001+ .mnt = au_br_mnt(br)
1facf9fc 35002+ };
523b37e3 35003+ struct inode *h_dir, *delegated;
1facf9fc 35004+ struct dentry *h_parent;
35005+
35006+ h_parent = h_dentry->d_parent; /* dir inode is locked */
5527c038 35007+ h_dir = d_inode(h_parent);
1facf9fc 35008+ IMustLock(h_dir);
35009+
35010+ h_path.dentry = au_whtmp_lkup(h_parent, br, &h_dentry->d_name);
35011+ err = PTR_ERR(h_path.dentry);
35012+ if (IS_ERR(h_path.dentry))
35013+ goto out;
35014+
35015+ /* under the same dir, no need to lock_rename() */
523b37e3 35016+ delegated = NULL;
f2c43d5f
AM
35017+ err = vfsub_rename(h_dir, h_dentry, h_dir, &h_path, &delegated,
35018+ /*flags*/0);
1facf9fc 35019+ AuTraceErr(err);
523b37e3
AM
35020+ if (unlikely(err == -EWOULDBLOCK)) {
35021+ pr_warn("cannot retry for NFSv4 delegation"
35022+ " for an internal rename\n");
35023+ iput(delegated);
35024+ }
1facf9fc 35025+ dput(h_path.dentry);
35026+
4f0767ce 35027+out:
4a4d8108 35028+ AuTraceErr(err);
1facf9fc 35029+ return err;
35030+}
35031+
35032+/* ---------------------------------------------------------------------- */
35033+/*
35034+ * functions for removing a whiteout
35035+ */
35036+
35037+static int do_unlink_wh(struct inode *h_dir, struct path *h_path)
35038+{
523b37e3
AM
35039+ int err, force;
35040+ struct inode *delegated;
1facf9fc 35041+
35042+ /*
35043+ * forces superio when the dir has a sticky bit.
35044+ * this may be a violation of unix fs semantics.
35045+ */
35046+ force = (h_dir->i_mode & S_ISVTX)
5527c038 35047+ && !uid_eq(current_fsuid(), d_inode(h_path->dentry)->i_uid);
523b37e3
AM
35048+ delegated = NULL;
35049+ err = vfsub_unlink(h_dir, h_path, &delegated, force);
35050+ if (unlikely(err == -EWOULDBLOCK)) {
35051+ pr_warn("cannot retry for NFSv4 delegation"
35052+ " for an internal unlink\n");
35053+ iput(delegated);
35054+ }
35055+ return err;
1facf9fc 35056+}
35057+
35058+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
35059+ struct dentry *dentry)
35060+{
35061+ int err;
35062+
35063+ err = do_unlink_wh(h_dir, h_path);
35064+ if (!err && dentry)
35065+ au_set_dbwh(dentry, -1);
35066+
35067+ return err;
35068+}
35069+
35070+static int unlink_wh_name(struct dentry *h_parent, struct qstr *wh,
35071+ struct au_branch *br)
35072+{
35073+ int err;
35074+ struct path h_path = {
86dc4139 35075+ .mnt = au_br_mnt(br)
1facf9fc 35076+ };
35077+
35078+ err = 0;
b4510431 35079+ h_path.dentry = vfsub_lkup_one(wh, h_parent);
1facf9fc 35080+ if (IS_ERR(h_path.dentry))
35081+ err = PTR_ERR(h_path.dentry);
35082+ else {
5527c038
JR
35083+ if (d_is_reg(h_path.dentry))
35084+ err = do_unlink_wh(d_inode(h_parent), &h_path);
1facf9fc 35085+ dput(h_path.dentry);
35086+ }
35087+
35088+ return err;
35089+}
35090+
35091+/* ---------------------------------------------------------------------- */
35092+/*
35093+ * initialize/clean whiteout for a branch
35094+ */
35095+
35096+static void au_wh_clean(struct inode *h_dir, struct path *whpath,
35097+ const int isdir)
35098+{
35099+ int err;
523b37e3 35100+ struct inode *delegated;
1facf9fc 35101+
5527c038 35102+ if (d_is_negative(whpath->dentry))
1facf9fc 35103+ return;
35104+
86dc4139
AM
35105+ if (isdir)
35106+ err = vfsub_rmdir(h_dir, whpath);
523b37e3
AM
35107+ else {
35108+ delegated = NULL;
35109+ err = vfsub_unlink(h_dir, whpath, &delegated, /*force*/0);
35110+ if (unlikely(err == -EWOULDBLOCK)) {
35111+ pr_warn("cannot retry for NFSv4 delegation"
35112+ " for an internal unlink\n");
35113+ iput(delegated);
35114+ }
35115+ }
1facf9fc 35116+ if (unlikely(err))
523b37e3
AM
35117+ pr_warn("failed removing %pd (%d), ignored.\n",
35118+ whpath->dentry, err);
1facf9fc 35119+}
35120+
35121+static int test_linkable(struct dentry *h_root)
35122+{
5527c038 35123+ struct inode *h_dir = d_inode(h_root);
1facf9fc 35124+
35125+ if (h_dir->i_op->link)
35126+ return 0;
35127+
523b37e3
AM
35128+ pr_err("%pd (%s) doesn't support link(2), use noplink and rw+nolwh\n",
35129+ h_root, au_sbtype(h_root->d_sb));
43982f53 35130+ return -ENOSYS; /* the branch doesn't have its ->link() */
1facf9fc 35131+}
35132+
35133+/* todo: should this mkdir be done in /sbin/mount.aufs helper? */
35134+static int au_whdir(struct inode *h_dir, struct path *path)
35135+{
35136+ int err;
35137+
35138+ err = -EEXIST;
5527c038 35139+ if (d_is_negative(path->dentry)) {
cd7a4cd9 35140+ int mode = 0700;
1facf9fc 35141+
35142+ if (au_test_nfs(path->dentry->d_sb))
cd7a4cd9 35143+ mode |= 0111;
86dc4139 35144+ err = vfsub_mkdir(h_dir, path, mode);
2000de60 35145+ } else if (d_is_dir(path->dentry))
1facf9fc 35146+ err = 0;
35147+ else
523b37e3 35148+ pr_err("unknown %pd exists\n", path->dentry);
1facf9fc 35149+
35150+ return err;
35151+}
35152+
35153+struct au_wh_base {
35154+ const struct qstr *name;
35155+ struct dentry *dentry;
35156+};
35157+
35158+static void au_wh_init_ro(struct inode *h_dir, struct au_wh_base base[],
35159+ struct path *h_path)
35160+{
35161+ h_path->dentry = base[AuBrWh_BASE].dentry;
35162+ au_wh_clean(h_dir, h_path, /*isdir*/0);
35163+ h_path->dentry = base[AuBrWh_PLINK].dentry;
35164+ au_wh_clean(h_dir, h_path, /*isdir*/1);
35165+ h_path->dentry = base[AuBrWh_ORPH].dentry;
35166+ au_wh_clean(h_dir, h_path, /*isdir*/1);
35167+}
35168+
35169+/*
35170+ * returns tri-state,
c1595e42 35171+ * minus: error, caller should print the message
acd2b654 35172+ * zero: success
c1595e42 35173+ * plus: error, caller should NOT print the message
1facf9fc 35174+ */
35175+static int au_wh_init_rw_nolink(struct dentry *h_root, struct au_wbr *wbr,
35176+ int do_plink, struct au_wh_base base[],
35177+ struct path *h_path)
35178+{
35179+ int err;
35180+ struct inode *h_dir;
35181+
5527c038 35182+ h_dir = d_inode(h_root);
1facf9fc 35183+ h_path->dentry = base[AuBrWh_BASE].dentry;
35184+ au_wh_clean(h_dir, h_path, /*isdir*/0);
35185+ h_path->dentry = base[AuBrWh_PLINK].dentry;
35186+ if (do_plink) {
35187+ err = test_linkable(h_root);
35188+ if (unlikely(err)) {
35189+ err = 1;
35190+ goto out;
35191+ }
35192+
35193+ err = au_whdir(h_dir, h_path);
35194+ if (unlikely(err))
35195+ goto out;
35196+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
35197+ } else
35198+ au_wh_clean(h_dir, h_path, /*isdir*/1);
35199+ h_path->dentry = base[AuBrWh_ORPH].dentry;
35200+ err = au_whdir(h_dir, h_path);
35201+ if (unlikely(err))
35202+ goto out;
35203+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
35204+
4f0767ce 35205+out:
1facf9fc 35206+ return err;
35207+}
35208+
35209+/*
35210+ * for the moment, aufs supports the branch filesystem which does not support
35211+ * link(2). testing on FAT which does not support i_op->setattr() fully either,
35212+ * copyup failed. finally, such filesystem will not be used as the writable
35213+ * branch.
35214+ *
35215+ * returns tri-state, see above.
35216+ */
35217+static int au_wh_init_rw(struct dentry *h_root, struct au_wbr *wbr,
35218+ int do_plink, struct au_wh_base base[],
35219+ struct path *h_path)
35220+{
35221+ int err;
35222+ struct inode *h_dir;
35223+
1308ab2a 35224+ WbrWhMustWriteLock(wbr);
35225+
1facf9fc 35226+ err = test_linkable(h_root);
35227+ if (unlikely(err)) {
35228+ err = 1;
35229+ goto out;
35230+ }
35231+
35232+ /*
35233+ * todo: should this create be done in /sbin/mount.aufs helper?
35234+ */
35235+ err = -EEXIST;
5527c038
JR
35236+ h_dir = d_inode(h_root);
35237+ if (d_is_negative(base[AuBrWh_BASE].dentry)) {
86dc4139
AM
35238+ h_path->dentry = base[AuBrWh_BASE].dentry;
35239+ err = vfsub_create(h_dir, h_path, WH_MASK, /*want_excl*/true);
7e9cd9fe 35240+ } else if (d_is_reg(base[AuBrWh_BASE].dentry))
1facf9fc 35241+ err = 0;
35242+ else
523b37e3 35243+ pr_err("unknown %pd2 exists\n", base[AuBrWh_BASE].dentry);
1facf9fc 35244+ if (unlikely(err))
35245+ goto out;
35246+
35247+ h_path->dentry = base[AuBrWh_PLINK].dentry;
35248+ if (do_plink) {
35249+ err = au_whdir(h_dir, h_path);
35250+ if (unlikely(err))
35251+ goto out;
35252+ wbr->wbr_plink = dget(base[AuBrWh_PLINK].dentry);
35253+ } else
35254+ au_wh_clean(h_dir, h_path, /*isdir*/1);
35255+ wbr->wbr_whbase = dget(base[AuBrWh_BASE].dentry);
35256+
35257+ h_path->dentry = base[AuBrWh_ORPH].dentry;
35258+ err = au_whdir(h_dir, h_path);
35259+ if (unlikely(err))
35260+ goto out;
35261+ wbr->wbr_orph = dget(base[AuBrWh_ORPH].dentry);
35262+
4f0767ce 35263+out:
1facf9fc 35264+ return err;
35265+}
35266+
35267+/*
35268+ * initialize the whiteout base file/dir for @br.
35269+ */
86dc4139 35270+int au_wh_init(struct au_branch *br, struct super_block *sb)
1facf9fc 35271+{
35272+ int err, i;
35273+ const unsigned char do_plink
35274+ = !!au_opt_test(au_mntflags(sb), PLINK);
1facf9fc 35275+ struct inode *h_dir;
86dc4139
AM
35276+ struct path path = br->br_path;
35277+ struct dentry *h_root = path.dentry;
1facf9fc 35278+ struct au_wbr *wbr = br->br_wbr;
35279+ static const struct qstr base_name[] = {
0c3ec466
AM
35280+ [AuBrWh_BASE] = QSTR_INIT(AUFS_BASE_NAME,
35281+ sizeof(AUFS_BASE_NAME) - 1),
35282+ [AuBrWh_PLINK] = QSTR_INIT(AUFS_PLINKDIR_NAME,
35283+ sizeof(AUFS_PLINKDIR_NAME) - 1),
35284+ [AuBrWh_ORPH] = QSTR_INIT(AUFS_ORPHDIR_NAME,
35285+ sizeof(AUFS_ORPHDIR_NAME) - 1)
1facf9fc 35286+ };
35287+ struct au_wh_base base[] = {
35288+ [AuBrWh_BASE] = {
35289+ .name = base_name + AuBrWh_BASE,
35290+ .dentry = NULL
35291+ },
35292+ [AuBrWh_PLINK] = {
35293+ .name = base_name + AuBrWh_PLINK,
35294+ .dentry = NULL
35295+ },
35296+ [AuBrWh_ORPH] = {
35297+ .name = base_name + AuBrWh_ORPH,
35298+ .dentry = NULL
35299+ }
35300+ };
35301+
1308ab2a 35302+ if (wbr)
35303+ WbrWhMustWriteLock(wbr);
1facf9fc 35304+
1facf9fc 35305+ for (i = 0; i < AuBrWh_Last; i++) {
35306+ /* doubly whiteouted */
35307+ struct dentry *d;
35308+
35309+ d = au_wh_lkup(h_root, (void *)base[i].name, br);
35310+ err = PTR_ERR(d);
35311+ if (IS_ERR(d))
35312+ goto out;
35313+
35314+ base[i].dentry = d;
35315+ AuDebugOn(wbr
35316+ && wbr->wbr_wh[i]
35317+ && wbr->wbr_wh[i] != base[i].dentry);
35318+ }
35319+
35320+ if (wbr)
35321+ for (i = 0; i < AuBrWh_Last; i++) {
35322+ dput(wbr->wbr_wh[i]);
35323+ wbr->wbr_wh[i] = NULL;
35324+ }
35325+
35326+ err = 0;
1e00d052 35327+ if (!au_br_writable(br->br_perm)) {
5527c038 35328+ h_dir = d_inode(h_root);
1facf9fc 35329+ au_wh_init_ro(h_dir, base, &path);
1e00d052 35330+ } else if (!au_br_wh_linkable(br->br_perm)) {
1facf9fc 35331+ err = au_wh_init_rw_nolink(h_root, wbr, do_plink, base, &path);
35332+ if (err > 0)
35333+ goto out;
35334+ else if (err)
35335+ goto out_err;
1e00d052 35336+ } else {
1facf9fc 35337+ err = au_wh_init_rw(h_root, wbr, do_plink, base, &path);
35338+ if (err > 0)
35339+ goto out;
35340+ else if (err)
35341+ goto out_err;
1facf9fc 35342+ }
35343+ goto out; /* success */
35344+
4f0767ce 35345+out_err:
523b37e3
AM
35346+ pr_err("an error(%d) on the writable branch %pd(%s)\n",
35347+ err, h_root, au_sbtype(h_root->d_sb));
4f0767ce 35348+out:
1facf9fc 35349+ for (i = 0; i < AuBrWh_Last; i++)
35350+ dput(base[i].dentry);
35351+ return err;
35352+}
35353+
35354+/* ---------------------------------------------------------------------- */
35355+/*
35356+ * whiteouts are all hard-linked usually.
35357+ * when its link count reaches a ceiling, we create a new whiteout base
35358+ * asynchronously.
35359+ */
35360+
35361+struct reinit_br_wh {
35362+ struct super_block *sb;
35363+ struct au_branch *br;
35364+};
35365+
35366+static void reinit_br_wh(void *arg)
35367+{
35368+ int err;
35369+ aufs_bindex_t bindex;
35370+ struct path h_path;
35371+ struct reinit_br_wh *a = arg;
35372+ struct au_wbr *wbr;
523b37e3 35373+ struct inode *dir, *delegated;
1facf9fc 35374+ struct dentry *h_root;
35375+ struct au_hinode *hdir;
35376+
35377+ err = 0;
35378+ wbr = a->br->br_wbr;
35379+ /* big aufs lock */
35380+ si_noflush_write_lock(a->sb);
35381+ if (!au_br_writable(a->br->br_perm))
35382+ goto out;
35383+ bindex = au_br_index(a->sb, a->br->br_id);
35384+ if (unlikely(bindex < 0))
35385+ goto out;
35386+
1308ab2a 35387+ di_read_lock_parent(a->sb->s_root, AuLock_IR);
5527c038 35388+ dir = d_inode(a->sb->s_root);
1facf9fc 35389+ hdir = au_hi(dir, bindex);
35390+ h_root = au_h_dptr(a->sb->s_root, bindex);
86dc4139 35391+ AuDebugOn(h_root != au_br_dentry(a->br));
1facf9fc 35392+
5afbbe0d 35393+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
1facf9fc 35394+ wbr_wh_write_lock(wbr);
35395+ err = au_h_verify(wbr->wbr_whbase, au_opt_udba(a->sb), hdir->hi_inode,
35396+ h_root, a->br);
35397+ if (!err) {
86dc4139
AM
35398+ h_path.dentry = wbr->wbr_whbase;
35399+ h_path.mnt = au_br_mnt(a->br);
523b37e3
AM
35400+ delegated = NULL;
35401+ err = vfsub_unlink(hdir->hi_inode, &h_path, &delegated,
35402+ /*force*/0);
35403+ if (unlikely(err == -EWOULDBLOCK)) {
35404+ pr_warn("cannot retry for NFSv4 delegation"
35405+ " for an internal unlink\n");
35406+ iput(delegated);
35407+ }
1facf9fc 35408+ } else {
523b37e3 35409+ pr_warn("%pd is moved, ignored\n", wbr->wbr_whbase);
1facf9fc 35410+ err = 0;
35411+ }
35412+ dput(wbr->wbr_whbase);
35413+ wbr->wbr_whbase = NULL;
35414+ if (!err)
86dc4139 35415+ err = au_wh_init(a->br, a->sb);
1facf9fc 35416+ wbr_wh_write_unlock(wbr);
5afbbe0d 35417+ au_hn_inode_unlock(hdir);
1308ab2a 35418+ di_read_unlock(a->sb->s_root, AuLock_IR);
076b876e
AM
35419+ if (!err)
35420+ au_fhsm_wrote(a->sb, bindex, /*force*/0);
1facf9fc 35421+
4f0767ce 35422+out:
1facf9fc 35423+ if (wbr)
35424+ atomic_dec(&wbr->wbr_wh_running);
acd2b654 35425+ au_lcnt_dec(&a->br->br_count);
1facf9fc 35426+ si_write_unlock(a->sb);
027c5e7a 35427+ au_nwt_done(&au_sbi(a->sb)->si_nowait);
9f237c51 35428+ au_kfree_rcu(a);
1facf9fc 35429+ if (unlikely(err))
35430+ AuIOErr("err %d\n", err);
35431+}
35432+
35433+static void kick_reinit_br_wh(struct super_block *sb, struct au_branch *br)
35434+{
35435+ int do_dec, wkq_err;
35436+ struct reinit_br_wh *arg;
35437+
35438+ do_dec = 1;
35439+ if (atomic_inc_return(&br->br_wbr->wbr_wh_running) != 1)
35440+ goto out;
35441+
35442+ /* ignore ENOMEM */
35443+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
35444+ if (arg) {
35445+ /*
35446+ * dec(wh_running), kfree(arg) and dec(br_count)
35447+ * in reinit function
35448+ */
35449+ arg->sb = sb;
35450+ arg->br = br;
acd2b654 35451+ au_lcnt_inc(&br->br_count);
53392da6 35452+ wkq_err = au_wkq_nowait(reinit_br_wh, arg, sb, /*flags*/0);
1facf9fc 35453+ if (unlikely(wkq_err)) {
35454+ atomic_dec(&br->br_wbr->wbr_wh_running);
acd2b654 35455+ au_lcnt_dec(&br->br_count);
9f237c51 35456+ au_kfree_rcu(arg);
1facf9fc 35457+ }
35458+ do_dec = 0;
35459+ }
35460+
4f0767ce 35461+out:
1facf9fc 35462+ if (do_dec)
35463+ atomic_dec(&br->br_wbr->wbr_wh_running);
35464+}
35465+
35466+/* ---------------------------------------------------------------------- */
35467+
35468+/*
35469+ * create the whiteout @wh.
35470+ */
35471+static int link_or_create_wh(struct super_block *sb, aufs_bindex_t bindex,
35472+ struct dentry *wh)
35473+{
35474+ int err;
35475+ struct path h_path = {
35476+ .dentry = wh
35477+ };
35478+ struct au_branch *br;
35479+ struct au_wbr *wbr;
35480+ struct dentry *h_parent;
523b37e3 35481+ struct inode *h_dir, *delegated;
1facf9fc 35482+
35483+ h_parent = wh->d_parent; /* dir inode is locked */
5527c038 35484+ h_dir = d_inode(h_parent);
1facf9fc 35485+ IMustLock(h_dir);
35486+
35487+ br = au_sbr(sb, bindex);
86dc4139 35488+ h_path.mnt = au_br_mnt(br);
1facf9fc 35489+ wbr = br->br_wbr;
35490+ wbr_wh_read_lock(wbr);
35491+ if (wbr->wbr_whbase) {
523b37e3
AM
35492+ delegated = NULL;
35493+ err = vfsub_link(wbr->wbr_whbase, h_dir, &h_path, &delegated);
35494+ if (unlikely(err == -EWOULDBLOCK)) {
35495+ pr_warn("cannot retry for NFSv4 delegation"
35496+ " for an internal link\n");
35497+ iput(delegated);
35498+ }
1facf9fc 35499+ if (!err || err != -EMLINK)
35500+ goto out;
35501+
35502+ /* link count full. re-initialize br_whbase. */
35503+ kick_reinit_br_wh(sb, br);
35504+ }
35505+
35506+ /* return this error in this context */
b4510431 35507+ err = vfsub_create(h_dir, &h_path, WH_MASK, /*want_excl*/true);
076b876e
AM
35508+ if (!err)
35509+ au_fhsm_wrote(sb, bindex, /*force*/0);
1facf9fc 35510+
4f0767ce 35511+out:
1facf9fc 35512+ wbr_wh_read_unlock(wbr);
35513+ return err;
35514+}
35515+
35516+/* ---------------------------------------------------------------------- */
35517+
35518+/*
35519+ * create or remove the diropq.
35520+ */
35521+static struct dentry *do_diropq(struct dentry *dentry, aufs_bindex_t bindex,
35522+ unsigned int flags)
35523+{
35524+ struct dentry *opq_dentry, *h_dentry;
35525+ struct super_block *sb;
35526+ struct au_branch *br;
35527+ int err;
35528+
35529+ sb = dentry->d_sb;
35530+ br = au_sbr(sb, bindex);
35531+ h_dentry = au_h_dptr(dentry, bindex);
b4510431 35532+ opq_dentry = vfsub_lkup_one(&diropq_name, h_dentry);
1facf9fc 35533+ if (IS_ERR(opq_dentry))
35534+ goto out;
35535+
35536+ if (au_ftest_diropq(flags, CREATE)) {
35537+ err = link_or_create_wh(sb, bindex, opq_dentry);
35538+ if (!err) {
35539+ au_set_dbdiropq(dentry, bindex);
35540+ goto out; /* success */
35541+ }
35542+ } else {
35543+ struct path tmp = {
35544+ .dentry = opq_dentry,
86dc4139 35545+ .mnt = au_br_mnt(br)
1facf9fc 35546+ };
5527c038 35547+ err = do_unlink_wh(au_h_iptr(d_inode(dentry), bindex), &tmp);
1facf9fc 35548+ if (!err)
35549+ au_set_dbdiropq(dentry, -1);
35550+ }
35551+ dput(opq_dentry);
35552+ opq_dentry = ERR_PTR(err);
35553+
4f0767ce 35554+out:
1facf9fc 35555+ return opq_dentry;
35556+}
35557+
35558+struct do_diropq_args {
35559+ struct dentry **errp;
35560+ struct dentry *dentry;
35561+ aufs_bindex_t bindex;
35562+ unsigned int flags;
35563+};
35564+
35565+static void call_do_diropq(void *args)
35566+{
35567+ struct do_diropq_args *a = args;
35568+ *a->errp = do_diropq(a->dentry, a->bindex, a->flags);
35569+}
35570+
35571+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
35572+ unsigned int flags)
35573+{
35574+ struct dentry *diropq, *h_dentry;
35575+
35576+ h_dentry = au_h_dptr(dentry, bindex);
5527c038 35577+ if (!au_test_h_perm_sio(d_inode(h_dentry), MAY_EXEC | MAY_WRITE))
1facf9fc 35578+ diropq = do_diropq(dentry, bindex, flags);
35579+ else {
35580+ int wkq_err;
35581+ struct do_diropq_args args = {
35582+ .errp = &diropq,
35583+ .dentry = dentry,
35584+ .bindex = bindex,
35585+ .flags = flags
35586+ };
35587+
35588+ wkq_err = au_wkq_wait(call_do_diropq, &args);
35589+ if (unlikely(wkq_err))
35590+ diropq = ERR_PTR(wkq_err);
35591+ }
35592+
35593+ return diropq;
35594+}
35595+
35596+/* ---------------------------------------------------------------------- */
35597+
35598+/*
35599+ * lookup whiteout dentry.
35600+ * @h_parent: lower parent dentry which must exist and be locked
35601+ * @base_name: name of dentry which will be whiteouted
35602+ * returns dentry for whiteout.
35603+ */
35604+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
35605+ struct au_branch *br)
35606+{
35607+ int err;
35608+ struct qstr wh_name;
35609+ struct dentry *wh_dentry;
35610+
35611+ err = au_wh_name_alloc(&wh_name, base_name);
35612+ wh_dentry = ERR_PTR(err);
35613+ if (!err) {
b4510431 35614+ wh_dentry = vfsub_lkup_one(&wh_name, h_parent);
9f237c51 35615+ au_kfree_try_rcu(wh_name.name);
1facf9fc 35616+ }
35617+ return wh_dentry;
35618+}
35619+
35620+/*
35621+ * link/create a whiteout for @dentry on @bindex.
35622+ */
35623+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
35624+ struct dentry *h_parent)
35625+{
35626+ struct dentry *wh_dentry;
35627+ struct super_block *sb;
35628+ int err;
35629+
35630+ sb = dentry->d_sb;
35631+ wh_dentry = au_wh_lkup(h_parent, &dentry->d_name, au_sbr(sb, bindex));
5527c038 35632+ if (!IS_ERR(wh_dentry) && d_is_negative(wh_dentry)) {
1facf9fc 35633+ err = link_or_create_wh(sb, bindex, wh_dentry);
076b876e 35634+ if (!err) {
1facf9fc 35635+ au_set_dbwh(dentry, bindex);
076b876e
AM
35636+ au_fhsm_wrote(sb, bindex, /*force*/0);
35637+ } else {
1facf9fc 35638+ dput(wh_dentry);
35639+ wh_dentry = ERR_PTR(err);
35640+ }
35641+ }
35642+
35643+ return wh_dentry;
35644+}
35645+
35646+/* ---------------------------------------------------------------------- */
35647+
35648+/* Delete all whiteouts in this directory on branch bindex. */
35649+static int del_wh_children(struct dentry *h_dentry, struct au_nhash *whlist,
35650+ aufs_bindex_t bindex, struct au_branch *br)
35651+{
35652+ int err;
35653+ unsigned long ul, n;
35654+ struct qstr wh_name;
35655+ char *p;
35656+ struct hlist_head *head;
c06a8ce3 35657+ struct au_vdir_wh *pos;
1facf9fc 35658+ struct au_vdir_destr *str;
35659+
35660+ err = -ENOMEM;
537831f9 35661+ p = (void *)__get_free_page(GFP_NOFS);
1facf9fc 35662+ wh_name.name = p;
35663+ if (unlikely(!wh_name.name))
35664+ goto out;
35665+
35666+ err = 0;
35667+ memcpy(p, AUFS_WH_PFX, AUFS_WH_PFX_LEN);
35668+ p += AUFS_WH_PFX_LEN;
35669+ n = whlist->nh_num;
35670+ head = whlist->nh_head;
35671+ for (ul = 0; !err && ul < n; ul++, head++) {
c06a8ce3
AM
35672+ hlist_for_each_entry(pos, head, wh_hash) {
35673+ if (pos->wh_bindex != bindex)
1facf9fc 35674+ continue;
35675+
c06a8ce3 35676+ str = &pos->wh_str;
1facf9fc 35677+ if (str->len + AUFS_WH_PFX_LEN <= PATH_MAX) {
35678+ memcpy(p, str->name, str->len);
35679+ wh_name.len = AUFS_WH_PFX_LEN + str->len;
35680+ err = unlink_wh_name(h_dentry, &wh_name, br);
35681+ if (!err)
35682+ continue;
35683+ break;
35684+ }
35685+ AuIOErr("whiteout name too long %.*s\n",
35686+ str->len, str->name);
35687+ err = -EIO;
35688+ break;
35689+ }
35690+ }
1c60b727 35691+ free_page((unsigned long)wh_name.name);
1facf9fc 35692+
4f0767ce 35693+out:
1facf9fc 35694+ return err;
35695+}
35696+
35697+struct del_wh_children_args {
35698+ int *errp;
35699+ struct dentry *h_dentry;
1308ab2a 35700+ struct au_nhash *whlist;
1facf9fc 35701+ aufs_bindex_t bindex;
35702+ struct au_branch *br;
35703+};
35704+
35705+static void call_del_wh_children(void *args)
35706+{
35707+ struct del_wh_children_args *a = args;
1308ab2a 35708+ *a->errp = del_wh_children(a->h_dentry, a->whlist, a->bindex, a->br);
1facf9fc 35709+}
35710+
35711+/* ---------------------------------------------------------------------- */
35712+
35713+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp)
35714+{
35715+ struct au_whtmp_rmdir *whtmp;
dece6358 35716+ int err;
1308ab2a 35717+ unsigned int rdhash;
dece6358
AM
35718+
35719+ SiMustAnyLock(sb);
1facf9fc 35720+
be52b249 35721+ whtmp = kzalloc(sizeof(*whtmp), gfp);
dece6358
AM
35722+ if (unlikely(!whtmp)) {
35723+ whtmp = ERR_PTR(-ENOMEM);
1facf9fc 35724+ goto out;
dece6358 35725+ }
1facf9fc 35726+
1308ab2a 35727+ /* no estimation for dir size */
35728+ rdhash = au_sbi(sb)->si_rdhash;
35729+ if (!rdhash)
35730+ rdhash = AUFS_RDHASH_DEF;
35731+ err = au_nhash_alloc(&whtmp->whlist, rdhash, gfp);
35732+ if (unlikely(err)) {
9f237c51 35733+ au_kfree_rcu(whtmp);
1308ab2a 35734+ whtmp = ERR_PTR(err);
35735+ }
dece6358 35736+
4f0767ce 35737+out:
dece6358 35738+ return whtmp;
1facf9fc 35739+}
35740+
35741+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp)
35742+{
027c5e7a 35743+ if (whtmp->br)
acd2b654 35744+ au_lcnt_dec(&whtmp->br->br_count);
1facf9fc 35745+ dput(whtmp->wh_dentry);
35746+ iput(whtmp->dir);
dece6358 35747+ au_nhash_wh_free(&whtmp->whlist);
9f237c51 35748+ au_kfree_rcu(whtmp);
1facf9fc 35749+}
35750+
35751+/*
35752+ * rmdir the whiteouted temporary named dir @h_dentry.
35753+ * @whlist: whiteouted children.
35754+ */
35755+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
35756+ struct dentry *wh_dentry, struct au_nhash *whlist)
35757+{
35758+ int err;
2000de60 35759+ unsigned int h_nlink;
1facf9fc 35760+ struct path h_tmp;
35761+ struct inode *wh_inode, *h_dir;
35762+ struct au_branch *br;
35763+
5527c038 35764+ h_dir = d_inode(wh_dentry->d_parent); /* dir inode is locked */
1facf9fc 35765+ IMustLock(h_dir);
35766+
35767+ br = au_sbr(dir->i_sb, bindex);
5527c038 35768+ wh_inode = d_inode(wh_dentry);
febd17d6 35769+ inode_lock_nested(wh_inode, AuLsc_I_CHILD);
1facf9fc 35770+
35771+ /*
35772+ * someone else might change some whiteouts while we were sleeping.
35773+ * it means this whlist may have an obsoleted entry.
35774+ */
35775+ if (!au_test_h_perm_sio(wh_inode, MAY_EXEC | MAY_WRITE))
35776+ err = del_wh_children(wh_dentry, whlist, bindex, br);
35777+ else {
35778+ int wkq_err;
35779+ struct del_wh_children_args args = {
35780+ .errp = &err,
35781+ .h_dentry = wh_dentry,
1308ab2a 35782+ .whlist = whlist,
1facf9fc 35783+ .bindex = bindex,
35784+ .br = br
35785+ };
35786+
35787+ wkq_err = au_wkq_wait(call_del_wh_children, &args);
35788+ if (unlikely(wkq_err))
35789+ err = wkq_err;
35790+ }
febd17d6 35791+ inode_unlock(wh_inode);
1facf9fc 35792+
35793+ if (!err) {
35794+ h_tmp.dentry = wh_dentry;
86dc4139 35795+ h_tmp.mnt = au_br_mnt(br);
2000de60 35796+ h_nlink = h_dir->i_nlink;
1facf9fc 35797+ err = vfsub_rmdir(h_dir, &h_tmp);
2000de60
JR
35798+ /* some fs doesn't change the parent nlink in some cases */
35799+ h_nlink -= h_dir->i_nlink;
1facf9fc 35800+ }
35801+
35802+ if (!err) {
5afbbe0d 35803+ if (au_ibtop(dir) == bindex) {
7f207e10 35804+ /* todo: dir->i_mutex is necessary */
1facf9fc 35805+ au_cpup_attr_timesizes(dir);
2000de60
JR
35806+ if (h_nlink)
35807+ vfsub_drop_nlink(dir);
1facf9fc 35808+ }
35809+ return 0; /* success */
35810+ }
35811+
523b37e3 35812+ pr_warn("failed removing %pd(%d), ignored\n", wh_dentry, err);
1facf9fc 35813+ return err;
35814+}
35815+
35816+static void call_rmdir_whtmp(void *args)
35817+{
35818+ int err;
e49829fe 35819+ aufs_bindex_t bindex;
1facf9fc 35820+ struct au_whtmp_rmdir *a = args;
35821+ struct super_block *sb;
35822+ struct dentry *h_parent;
35823+ struct inode *h_dir;
1facf9fc 35824+ struct au_hinode *hdir;
35825+
35826+ /* rmdir by nfsd may cause deadlock with this i_mutex */
febd17d6 35827+ /* inode_lock(a->dir); */
e49829fe 35828+ err = -EROFS;
1facf9fc 35829+ sb = a->dir->i_sb;
e49829fe
JR
35830+ si_read_lock(sb, !AuLock_FLUSH);
35831+ if (!au_br_writable(a->br->br_perm))
35832+ goto out;
35833+ bindex = au_br_index(sb, a->br->br_id);
35834+ if (unlikely(bindex < 0))
1facf9fc 35835+ goto out;
35836+
35837+ err = -EIO;
1facf9fc 35838+ ii_write_lock_parent(a->dir);
35839+ h_parent = dget_parent(a->wh_dentry);
5527c038 35840+ h_dir = d_inode(h_parent);
e49829fe 35841+ hdir = au_hi(a->dir, bindex);
86dc4139
AM
35842+ err = vfsub_mnt_want_write(au_br_mnt(a->br));
35843+ if (unlikely(err))
35844+ goto out_mnt;
5afbbe0d 35845+ au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
e49829fe
JR
35846+ err = au_h_verify(a->wh_dentry, au_opt_udba(sb), h_dir, h_parent,
35847+ a->br);
86dc4139
AM
35848+ if (!err)
35849+ err = au_whtmp_rmdir(a->dir, bindex, a->wh_dentry, &a->whlist);
5afbbe0d 35850+ au_hn_inode_unlock(hdir);
86dc4139
AM
35851+ vfsub_mnt_drop_write(au_br_mnt(a->br));
35852+
35853+out_mnt:
1facf9fc 35854+ dput(h_parent);
35855+ ii_write_unlock(a->dir);
4f0767ce 35856+out:
febd17d6 35857+ /* inode_unlock(a->dir); */
1facf9fc 35858+ au_whtmp_rmdir_free(a);
027c5e7a
AM
35859+ si_read_unlock(sb);
35860+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 35861+ if (unlikely(err))
35862+ AuIOErr("err %d\n", err);
35863+}
35864+
35865+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
35866+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args)
35867+{
35868+ int wkq_err;
e49829fe 35869+ struct super_block *sb;
1facf9fc 35870+
35871+ IMustLock(dir);
35872+
35873+ /* all post-process will be done in do_rmdir_whtmp(). */
e49829fe 35874+ sb = dir->i_sb;
1facf9fc 35875+ args->dir = au_igrab(dir);
e49829fe 35876+ args->br = au_sbr(sb, bindex);
acd2b654 35877+ au_lcnt_inc(&args->br->br_count);
1facf9fc 35878+ args->wh_dentry = dget(wh_dentry);
53392da6 35879+ wkq_err = au_wkq_nowait(call_rmdir_whtmp, args, sb, /*flags*/0);
1facf9fc 35880+ if (unlikely(wkq_err)) {
523b37e3 35881+ pr_warn("rmdir error %pd (%d), ignored\n", wh_dentry, wkq_err);
1facf9fc 35882+ au_whtmp_rmdir_free(args);
35883+ }
35884+}
7f207e10 35885diff -urN /usr/share/empty/fs/aufs/whout.h linux/fs/aufs/whout.h
eca34b5c 35886--- /usr/share/empty/fs/aufs/whout.h 1970-01-01 01:00:00.000000000 +0100
016522bc 35887+++ linux/fs/aufs/whout.h 2020-01-27 10:57:18.178871751 +0100
062440b3
AM
35888@@ -0,0 +1,86 @@
35889+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 35890+/*
016522bc 35891+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 35892+ *
35893+ * This program, aufs is free software; you can redistribute it and/or modify
35894+ * it under the terms of the GNU General Public License as published by
35895+ * the Free Software Foundation; either version 2 of the License, or
35896+ * (at your option) any later version.
dece6358
AM
35897+ *
35898+ * This program is distributed in the hope that it will be useful,
35899+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
35900+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35901+ * GNU General Public License for more details.
35902+ *
35903+ * You should have received a copy of the GNU General Public License
523b37e3 35904+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 35905+ */
35906+
35907+/*
35908+ * whiteout for logical deletion and opaque directory
35909+ */
35910+
35911+#ifndef __AUFS_WHOUT_H__
35912+#define __AUFS_WHOUT_H__
35913+
35914+#ifdef __KERNEL__
35915+
1facf9fc 35916+#include "dir.h"
35917+
35918+/* whout.c */
35919+int au_wh_name_alloc(struct qstr *wh, const struct qstr *name);
076b876e
AM
35920+int au_wh_test(struct dentry *h_parent, struct qstr *wh_name, int try_sio);
35921+int au_diropq_test(struct dentry *h_dentry);
3c1bdaff 35922+struct au_branch;
1facf9fc 35923+struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br,
35924+ struct qstr *prefix);
35925+int au_whtmp_ren(struct dentry *h_dentry, struct au_branch *br);
35926+int au_wh_unlink_dentry(struct inode *h_dir, struct path *h_path,
35927+ struct dentry *dentry);
86dc4139 35928+int au_wh_init(struct au_branch *br, struct super_block *sb);
1facf9fc 35929+
35930+/* diropq flags */
35931+#define AuDiropq_CREATE 1
35932+#define au_ftest_diropq(flags, name) ((flags) & AuDiropq_##name)
7f207e10
AM
35933+#define au_fset_diropq(flags, name) \
35934+ do { (flags) |= AuDiropq_##name; } while (0)
35935+#define au_fclr_diropq(flags, name) \
35936+ do { (flags) &= ~AuDiropq_##name; } while (0)
1facf9fc 35937+
35938+struct dentry *au_diropq_sio(struct dentry *dentry, aufs_bindex_t bindex,
35939+ unsigned int flags);
35940+struct dentry *au_wh_lkup(struct dentry *h_parent, struct qstr *base_name,
35941+ struct au_branch *br);
35942+struct dentry *au_wh_create(struct dentry *dentry, aufs_bindex_t bindex,
35943+ struct dentry *h_parent);
35944+
35945+/* real rmdir for the whiteout-ed dir */
35946+struct au_whtmp_rmdir {
35947+ struct inode *dir;
e49829fe 35948+ struct au_branch *br;
1facf9fc 35949+ struct dentry *wh_dentry;
dece6358 35950+ struct au_nhash whlist;
1facf9fc 35951+};
35952+
35953+struct au_whtmp_rmdir *au_whtmp_rmdir_alloc(struct super_block *sb, gfp_t gfp);
35954+void au_whtmp_rmdir_free(struct au_whtmp_rmdir *whtmp);
35955+int au_whtmp_rmdir(struct inode *dir, aufs_bindex_t bindex,
35956+ struct dentry *wh_dentry, struct au_nhash *whlist);
35957+void au_whtmp_kick_rmdir(struct inode *dir, aufs_bindex_t bindex,
35958+ struct dentry *wh_dentry, struct au_whtmp_rmdir *args);
35959+
35960+/* ---------------------------------------------------------------------- */
35961+
35962+static inline struct dentry *au_diropq_create(struct dentry *dentry,
35963+ aufs_bindex_t bindex)
35964+{
35965+ return au_diropq_sio(dentry, bindex, AuDiropq_CREATE);
35966+}
35967+
35968+static inline int au_diropq_remove(struct dentry *dentry, aufs_bindex_t bindex)
35969+{
35970+ return PTR_ERR(au_diropq_sio(dentry, bindex, !AuDiropq_CREATE));
35971+}
35972+
35973+#endif /* __KERNEL__ */
35974+#endif /* __AUFS_WHOUT_H__ */
7f207e10 35975diff -urN /usr/share/empty/fs/aufs/wkq.c linux/fs/aufs/wkq.c
eca34b5c 35976--- /usr/share/empty/fs/aufs/wkq.c 1970-01-01 01:00:00.000000000 +0100
016522bc 35977+++ linux/fs/aufs/wkq.c 2020-04-03 08:16:47.547461775 +0200
43982f53 35978@@ -0,0 +1,372 @@
cd7a4cd9 35979+// SPDX-License-Identifier: GPL-2.0
1facf9fc 35980+/*
016522bc 35981+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 35982+ *
35983+ * This program, aufs is free software; you can redistribute it and/or modify
35984+ * it under the terms of the GNU General Public License as published by
35985+ * the Free Software Foundation; either version 2 of the License, or
35986+ * (at your option) any later version.
dece6358
AM
35987+ *
35988+ * This program is distributed in the hope that it will be useful,
35989+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
35990+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35991+ * GNU General Public License for more details.
35992+ *
35993+ * You should have received a copy of the GNU General Public License
523b37e3 35994+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 35995+ */
35996+
35997+/*
35998+ * workqueue for asynchronous/super-io operations
acd2b654 35999+ * todo: try new credential scheme
1facf9fc 36000+ */
36001+
dece6358 36002+#include <linux/module.h>
1facf9fc 36003+#include "aufs.h"
36004+
9dbd164d 36005+/* internal workqueue named AUFS_WKQ_NAME */
b752ccd1 36006+
9dbd164d 36007+static struct workqueue_struct *au_wkq;
1facf9fc 36008+
36009+struct au_wkinfo {
36010+ struct work_struct wk;
7f207e10 36011+ struct kobject *kobj;
1facf9fc 36012+
36013+ unsigned int flags; /* see wkq.h */
36014+
36015+ au_wkq_func_t func;
36016+ void *args;
36017+
8b6a4947
AM
36018+#ifdef CONFIG_LOCKDEP
36019+ int dont_check;
36020+ struct held_lock **hlock;
36021+#endif
36022+
1facf9fc 36023+ struct completion *comp;
36024+};
36025+
36026+/* ---------------------------------------------------------------------- */
8b6a4947
AM
36027+/*
36028+ * Aufs passes some operations to the workqueue such as the internal copyup.
36029+ * This scheme looks rather unnatural for LOCKDEP debugging feature, since the
36030+ * job run by workqueue depends upon the locks acquired in the other task.
36031+ * Delegating a small operation to the workqueue, aufs passes its lockdep
36032+ * information too. And the job in the workqueue restores the info in order to
36033+ * pretend as if it acquired those locks. This is just to make LOCKDEP work
36034+ * correctly and expectedly.
36035+ */
36036+
36037+#ifndef CONFIG_LOCKDEP
36038+AuStubInt0(au_wkq_lockdep_alloc, struct au_wkinfo *wkinfo);
36039+AuStubVoid(au_wkq_lockdep_free, struct au_wkinfo *wkinfo);
36040+AuStubVoid(au_wkq_lockdep_pre, struct au_wkinfo *wkinfo);
36041+AuStubVoid(au_wkq_lockdep_post, struct au_wkinfo *wkinfo);
36042+AuStubVoid(au_wkq_lockdep_init, struct au_wkinfo *wkinfo);
36043+#else
36044+static void au_wkq_lockdep_init(struct au_wkinfo *wkinfo)
36045+{
36046+ wkinfo->hlock = NULL;
36047+ wkinfo->dont_check = 0;
36048+}
36049+
36050+/*
36051+ * 1: matched
36052+ * 0: unmatched
36053+ */
36054+static int au_wkq_lockdep_test(struct lock_class_key *key, const char *name)
36055+{
36056+ static DEFINE_SPINLOCK(spin);
36057+ static struct {
36058+ char *name;
36059+ struct lock_class_key *key;
36060+ } a[] = {
36061+ { .name = "&sbinfo->si_rwsem" },
36062+ { .name = "&finfo->fi_rwsem" },
36063+ { .name = "&dinfo->di_rwsem" },
36064+ { .name = "&iinfo->ii_rwsem" }
36065+ };
36066+ static int set;
36067+ int i;
36068+
36069+ /* lockless read from 'set.' see below */
36070+ if (set == ARRAY_SIZE(a)) {
36071+ for (i = 0; i < ARRAY_SIZE(a); i++)
36072+ if (a[i].key == key)
36073+ goto match;
36074+ goto unmatch;
36075+ }
36076+
36077+ spin_lock(&spin);
36078+ if (set)
36079+ for (i = 0; i < ARRAY_SIZE(a); i++)
36080+ if (a[i].key == key) {
36081+ spin_unlock(&spin);
36082+ goto match;
36083+ }
36084+ for (i = 0; i < ARRAY_SIZE(a); i++) {
36085+ if (a[i].key) {
36086+ if (unlikely(a[i].key == key)) { /* rare but possible */
36087+ spin_unlock(&spin);
36088+ goto match;
36089+ } else
36090+ continue;
36091+ }
36092+ if (strstr(a[i].name, name)) {
36093+ /*
36094+ * the order of these three lines is important for the
36095+ * lockless read above.
36096+ */
36097+ a[i].key = key;
36098+ spin_unlock(&spin);
36099+ set++;
36100+ /* AuDbg("%d, %s\n", set, name); */
36101+ goto match;
36102+ }
36103+ }
36104+ spin_unlock(&spin);
36105+ goto unmatch;
36106+
36107+match:
36108+ return 1;
36109+unmatch:
36110+ return 0;
36111+}
36112+
36113+static int au_wkq_lockdep_alloc(struct au_wkinfo *wkinfo)
36114+{
36115+ int err, n;
36116+ struct task_struct *curr;
36117+ struct held_lock **hl, *held_locks, *p;
36118+
36119+ err = 0;
36120+ curr = current;
36121+ wkinfo->dont_check = lockdep_recursing(curr);
36122+ if (wkinfo->dont_check)
36123+ goto out;
36124+ n = curr->lockdep_depth;
36125+ if (!n)
36126+ goto out;
36127+
36128+ err = -ENOMEM;
36129+ wkinfo->hlock = kmalloc_array(n + 1, sizeof(*wkinfo->hlock), GFP_NOFS);
36130+ if (unlikely(!wkinfo->hlock))
36131+ goto out;
36132+
36133+ err = 0;
43982f53
AM
36134+#if 0 /* left for debugging */
36135+ if (0 && au_debug_test())
8b6a4947
AM
36136+ lockdep_print_held_locks(curr);
36137+#endif
36138+ held_locks = curr->held_locks;
36139+ hl = wkinfo->hlock;
36140+ while (n--) {
36141+ p = held_locks++;
36142+ if (au_wkq_lockdep_test(p->instance->key, p->instance->name))
36143+ *hl++ = p;
36144+ }
36145+ *hl = NULL;
36146+
36147+out:
36148+ return err;
36149+}
36150+
36151+static void au_wkq_lockdep_free(struct au_wkinfo *wkinfo)
36152+{
9f237c51 36153+ au_kfree_try_rcu(wkinfo->hlock);
8b6a4947
AM
36154+}
36155+
36156+static void au_wkq_lockdep_pre(struct au_wkinfo *wkinfo)
36157+{
36158+ struct held_lock *p, **hl = wkinfo->hlock;
36159+ int subclass;
36160+
36161+ if (wkinfo->dont_check)
36162+ lockdep_off();
36163+ if (!hl)
36164+ return;
36165+ while ((p = *hl++)) { /* assignment */
36166+ subclass = lockdep_hlock_class(p)->subclass;
36167+ /* AuDbg("%s, %d\n", p->instance->name, subclass); */
36168+ if (p->read)
36169+ rwsem_acquire_read(p->instance, subclass, 0,
36170+ /*p->acquire_ip*/_RET_IP_);
36171+ else
36172+ rwsem_acquire(p->instance, subclass, 0,
36173+ /*p->acquire_ip*/_RET_IP_);
36174+ }
36175+}
36176+
36177+static void au_wkq_lockdep_post(struct au_wkinfo *wkinfo)
36178+{
36179+ struct held_lock *p, **hl = wkinfo->hlock;
36180+
36181+ if (wkinfo->dont_check)
36182+ lockdep_on();
36183+ if (!hl)
36184+ return;
36185+ while ((p = *hl++)) /* assignment */
36186+ rwsem_release(p->instance, 0, /*p->acquire_ip*/_RET_IP_);
36187+}
36188+#endif
1facf9fc 36189+
1facf9fc 36190+static void wkq_func(struct work_struct *wk)
36191+{
36192+ struct au_wkinfo *wkinfo = container_of(wk, struct au_wkinfo, wk);
36193+
2dfbb274 36194+ AuDebugOn(!uid_eq(current_fsuid(), GLOBAL_ROOT_UID));
7f207e10
AM
36195+ AuDebugOn(rlimit(RLIMIT_FSIZE) != RLIM_INFINITY);
36196+
8b6a4947 36197+ au_wkq_lockdep_pre(wkinfo);
1facf9fc 36198+ wkinfo->func(wkinfo->args);
8b6a4947 36199+ au_wkq_lockdep_post(wkinfo);
1facf9fc 36200+ if (au_ftest_wkq(wkinfo->flags, WAIT))
36201+ complete(wkinfo->comp);
36202+ else {
7f207e10 36203+ kobject_put(wkinfo->kobj);
9dbd164d 36204+ module_put(THIS_MODULE); /* todo: ?? */
9f237c51 36205+ au_kfree_rcu(wkinfo);
1facf9fc 36206+ }
36207+}
36208+
36209+/*
36210+ * Since struct completion is large, try allocating it dynamically.
36211+ */
1facf9fc 36212+#define AuWkqCompDeclare(name) struct completion *comp = NULL
36213+
36214+static int au_wkq_comp_alloc(struct au_wkinfo *wkinfo, struct completion **comp)
36215+{
36216+ *comp = kmalloc(sizeof(**comp), GFP_NOFS);
36217+ if (*comp) {
36218+ init_completion(*comp);
36219+ wkinfo->comp = *comp;
36220+ return 0;
36221+ }
36222+ return -ENOMEM;
36223+}
36224+
36225+static void au_wkq_comp_free(struct completion *comp)
36226+{
9f237c51 36227+ au_kfree_rcu(comp);
1facf9fc 36228+}
36229+
53392da6 36230+static void au_wkq_run(struct au_wkinfo *wkinfo)
1facf9fc 36231+{
53392da6
AM
36232+ if (au_ftest_wkq(wkinfo->flags, NEST)) {
36233+ if (au_wkq_test()) {
38d290e6 36234+ AuWarn1("wkq from wkq, unless silly-rename on NFS,"
acd2b654
AM
36235+ " due to a dead dir by UDBA,"
36236+ " or async xino write?\n");
53392da6
AM
36237+ AuDebugOn(au_ftest_wkq(wkinfo->flags, WAIT));
36238+ }
36239+ } else
36240+ au_dbg_verify_kthread();
36241+
36242+ if (au_ftest_wkq(wkinfo->flags, WAIT)) {
a1f66529 36243+ INIT_WORK_ONSTACK(&wkinfo->wk, wkq_func);
9dbd164d 36244+ queue_work(au_wkq, &wkinfo->wk);
4a4d8108
AM
36245+ } else {
36246+ INIT_WORK(&wkinfo->wk, wkq_func);
36247+ schedule_work(&wkinfo->wk);
36248+ }
1facf9fc 36249+}
36250+
7f207e10
AM
36251+/*
36252+ * Be careful. It is easy to make deadlock happen.
36253+ * processA: lock, wkq and wait
36254+ * processB: wkq and wait, lock in wkq
36255+ * --> deadlock
36256+ */
b752ccd1 36257+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args)
1facf9fc 36258+{
36259+ int err;
36260+ AuWkqCompDeclare(comp);
36261+ struct au_wkinfo wkinfo = {
b752ccd1 36262+ .flags = flags,
1facf9fc 36263+ .func = func,
36264+ .args = args
36265+ };
36266+
36267+ err = au_wkq_comp_alloc(&wkinfo, &comp);
8b6a4947
AM
36268+ if (unlikely(err))
36269+ goto out;
36270+ err = au_wkq_lockdep_alloc(&wkinfo);
36271+ if (unlikely(err))
36272+ goto out_comp;
1facf9fc 36273+ if (!err) {
53392da6 36274+ au_wkq_run(&wkinfo);
1facf9fc 36275+ /* no timeout, no interrupt */
36276+ wait_for_completion(wkinfo.comp);
1facf9fc 36277+ }
8b6a4947 36278+ au_wkq_lockdep_free(&wkinfo);
1facf9fc 36279+
8b6a4947
AM
36280+out_comp:
36281+ au_wkq_comp_free(comp);
36282+out:
36283+ destroy_work_on_stack(&wkinfo.wk);
1facf9fc 36284+ return err;
1facf9fc 36285+}
36286+
027c5e7a
AM
36287+/*
36288+ * Note: dget/dput() in func for aufs dentries are not supported. It will be a
36289+ * problem in a concurrent umounting.
36290+ */
53392da6
AM
36291+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
36292+ unsigned int flags)
1facf9fc 36293+{
36294+ int err;
36295+ struct au_wkinfo *wkinfo;
36296+
f0c0a007 36297+ atomic_inc(&au_sbi(sb)->si_nowait.nw_len);
1facf9fc 36298+
36299+ /*
36300+ * wkq_func() must free this wkinfo.
36301+ * it highly depends upon the implementation of workqueue.
36302+ */
36303+ err = 0;
36304+ wkinfo = kmalloc(sizeof(*wkinfo), GFP_NOFS);
36305+ if (wkinfo) {
7f207e10 36306+ wkinfo->kobj = &au_sbi(sb)->si_kobj;
53392da6 36307+ wkinfo->flags = flags & ~AuWkq_WAIT;
1facf9fc 36308+ wkinfo->func = func;
36309+ wkinfo->args = args;
36310+ wkinfo->comp = NULL;
8b6a4947 36311+ au_wkq_lockdep_init(wkinfo);
7f207e10 36312+ kobject_get(wkinfo->kobj);
9dbd164d 36313+ __module_get(THIS_MODULE); /* todo: ?? */
1facf9fc 36314+
53392da6 36315+ au_wkq_run(wkinfo);
1facf9fc 36316+ } else {
36317+ err = -ENOMEM;
e49829fe 36318+ au_nwt_done(&au_sbi(sb)->si_nowait);
1facf9fc 36319+ }
36320+
36321+ return err;
36322+}
36323+
36324+/* ---------------------------------------------------------------------- */
36325+
36326+void au_nwt_init(struct au_nowait_tasks *nwt)
36327+{
f0c0a007
AM
36328+ atomic_set(&nwt->nw_len, 0);
36329+ /* smp_mb(); */ /* atomic_set */
1facf9fc 36330+ init_waitqueue_head(&nwt->nw_wq);
36331+}
36332+
36333+void au_wkq_fin(void)
36334+{
9dbd164d 36335+ destroy_workqueue(au_wkq);
1facf9fc 36336+}
36337+
36338+int __init au_wkq_init(void)
36339+{
9dbd164d 36340+ int err;
b752ccd1
AM
36341+
36342+ err = 0;
86dc4139 36343+ au_wkq = alloc_workqueue(AUFS_WKQ_NAME, 0, WQ_DFL_ACTIVE);
9dbd164d
AM
36344+ if (IS_ERR(au_wkq))
36345+ err = PTR_ERR(au_wkq);
36346+ else if (!au_wkq)
36347+ err = -ENOMEM;
b752ccd1
AM
36348+
36349+ return err;
1facf9fc 36350+}
7f207e10 36351diff -urN /usr/share/empty/fs/aufs/wkq.h linux/fs/aufs/wkq.h
eca34b5c 36352--- /usr/share/empty/fs/aufs/wkq.h 1970-01-01 01:00:00.000000000 +0100
016522bc 36353+++ linux/fs/aufs/wkq.h 2020-01-27 10:57:18.182205184 +0100
acd2b654 36354@@ -0,0 +1,89 @@
062440b3 36355+/* SPDX-License-Identifier: GPL-2.0 */
1facf9fc 36356+/*
016522bc 36357+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 36358+ *
36359+ * This program, aufs is free software; you can redistribute it and/or modify
36360+ * it under the terms of the GNU General Public License as published by
36361+ * the Free Software Foundation; either version 2 of the License, or
36362+ * (at your option) any later version.
dece6358
AM
36363+ *
36364+ * This program is distributed in the hope that it will be useful,
36365+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36366+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36367+ * GNU General Public License for more details.
36368+ *
36369+ * You should have received a copy of the GNU General Public License
523b37e3 36370+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 36371+ */
36372+
36373+/*
36374+ * workqueue for asynchronous/super-io operations
36375+ * todo: try new credentials management scheme
36376+ */
36377+
36378+#ifndef __AUFS_WKQ_H__
36379+#define __AUFS_WKQ_H__
36380+
36381+#ifdef __KERNEL__
36382+
8b6a4947 36383+#include <linux/wait.h>
5afbbe0d 36384+
dece6358
AM
36385+struct super_block;
36386+
1facf9fc 36387+/* ---------------------------------------------------------------------- */
36388+
36389+/*
36390+ * in the next operation, wait for the 'nowait' tasks in system-wide workqueue
36391+ */
36392+struct au_nowait_tasks {
f0c0a007 36393+ atomic_t nw_len;
1facf9fc 36394+ wait_queue_head_t nw_wq;
36395+};
36396+
36397+/* ---------------------------------------------------------------------- */
36398+
36399+typedef void (*au_wkq_func_t)(void *args);
36400+
36401+/* wkq flags */
36402+#define AuWkq_WAIT 1
9dbd164d 36403+#define AuWkq_NEST (1 << 1)
1facf9fc 36404+#define au_ftest_wkq(flags, name) ((flags) & AuWkq_##name)
7f207e10
AM
36405+#define au_fset_wkq(flags, name) \
36406+ do { (flags) |= AuWkq_##name; } while (0)
36407+#define au_fclr_wkq(flags, name) \
36408+ do { (flags) &= ~AuWkq_##name; } while (0)
1facf9fc 36409+
36410+/* wkq.c */
b752ccd1 36411+int au_wkq_do_wait(unsigned int flags, au_wkq_func_t func, void *args);
53392da6
AM
36412+int au_wkq_nowait(au_wkq_func_t func, void *args, struct super_block *sb,
36413+ unsigned int flags);
1facf9fc 36414+void au_nwt_init(struct au_nowait_tasks *nwt);
36415+int __init au_wkq_init(void);
36416+void au_wkq_fin(void);
36417+
36418+/* ---------------------------------------------------------------------- */
36419+
53392da6
AM
36420+static inline int au_wkq_test(void)
36421+{
36422+ return current->flags & PF_WQ_WORKER;
36423+}
36424+
b752ccd1 36425+static inline int au_wkq_wait(au_wkq_func_t func, void *args)
1facf9fc 36426+{
b752ccd1 36427+ return au_wkq_do_wait(AuWkq_WAIT, func, args);
1facf9fc 36428+}
36429+
36430+static inline void au_nwt_done(struct au_nowait_tasks *nwt)
36431+{
f0c0a007 36432+ if (atomic_dec_and_test(&nwt->nw_len))
1facf9fc 36433+ wake_up_all(&nwt->nw_wq);
36434+}
36435+
36436+static inline int au_nwt_flush(struct au_nowait_tasks *nwt)
36437+{
f0c0a007 36438+ wait_event(nwt->nw_wq, !atomic_read(&nwt->nw_len));
1facf9fc 36439+ return 0;
36440+}
36441+
36442+#endif /* __KERNEL__ */
36443+#endif /* __AUFS_WKQ_H__ */
c1595e42 36444diff -urN /usr/share/empty/fs/aufs/xattr.c linux/fs/aufs/xattr.c
eca34b5c 36445--- /usr/share/empty/fs/aufs/xattr.c 1970-01-01 01:00:00.000000000 +0100
016522bc 36446+++ linux/fs/aufs/xattr.c 2020-01-27 10:57:18.182205184 +0100
062440b3 36447@@ -0,0 +1,356 @@
cd7a4cd9 36448+// SPDX-License-Identifier: GPL-2.0
c1595e42 36449+/*
016522bc 36450+ * Copyright (C) 2014-2020 Junjiro R. Okajima
c1595e42
JR
36451+ *
36452+ * This program, aufs is free software; you can redistribute it and/or modify
36453+ * it under the terms of the GNU General Public License as published by
36454+ * the Free Software Foundation; either version 2 of the License, or
36455+ * (at your option) any later version.
36456+ *
36457+ * This program is distributed in the hope that it will be useful,
36458+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36459+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36460+ * GNU General Public License for more details.
36461+ *
36462+ * You should have received a copy of the GNU General Public License
36463+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
36464+ */
36465+
36466+/*
36467+ * handling xattr functions
36468+ */
36469+
a2654f78
AM
36470+#include <linux/fs.h>
36471+#include <linux/posix_acl_xattr.h>
c1595e42
JR
36472+#include <linux/xattr.h>
36473+#include "aufs.h"
36474+
36475+static int au_xattr_ignore(int err, char *name, unsigned int ignore_flags)
36476+{
36477+ if (!ignore_flags)
36478+ goto out;
36479+ switch (err) {
36480+ case -ENOMEM:
36481+ case -EDQUOT:
36482+ goto out;
36483+ }
36484+
36485+ if ((ignore_flags & AuBrAttr_ICEX) == AuBrAttr_ICEX) {
36486+ err = 0;
36487+ goto out;
36488+ }
36489+
36490+#define cmp(brattr, prefix) do { \
36491+ if (!strncmp(name, XATTR_##prefix##_PREFIX, \
36492+ XATTR_##prefix##_PREFIX_LEN)) { \
36493+ if (ignore_flags & AuBrAttr_ICEX_##brattr) \
36494+ err = 0; \
36495+ goto out; \
36496+ } \
36497+ } while (0)
36498+
36499+ cmp(SEC, SECURITY);
36500+ cmp(SYS, SYSTEM);
36501+ cmp(TR, TRUSTED);
36502+ cmp(USR, USER);
36503+#undef cmp
36504+
36505+ if (ignore_flags & AuBrAttr_ICEX_OTH)
36506+ err = 0;
36507+
36508+out:
36509+ return err;
36510+}
36511+
36512+static const int au_xattr_out_of_list = AuBrAttr_ICEX_OTH << 1;
36513+
36514+static int au_do_cpup_xattr(struct dentry *h_dst, struct dentry *h_src,
7e9cd9fe
AM
36515+ char *name, char **buf, unsigned int ignore_flags,
36516+ unsigned int verbose)
c1595e42
JR
36517+{
36518+ int err;
36519+ ssize_t ssz;
36520+ struct inode *h_idst;
36521+
36522+ ssz = vfs_getxattr_alloc(h_src, name, buf, 0, GFP_NOFS);
36523+ err = ssz;
36524+ if (unlikely(err <= 0)) {
c1595e42
JR
36525+ if (err == -ENODATA
36526+ || (err == -EOPNOTSUPP
b912730e 36527+ && ((ignore_flags & au_xattr_out_of_list)
5527c038 36528+ || (au_test_nfs_noacl(d_inode(h_src))
b912730e
AM
36529+ && (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS)
36530+ || !strcmp(name,
36531+ XATTR_NAME_POSIX_ACL_DEFAULT))))
36532+ ))
c1595e42 36533+ err = 0;
b912730e
AM
36534+ if (err && (verbose || au_debug_test()))
36535+ pr_err("%s, err %d\n", name, err);
c1595e42
JR
36536+ goto out;
36537+ }
36538+
36539+ /* unlock it temporary */
5527c038 36540+ h_idst = d_inode(h_dst);
febd17d6 36541+ inode_unlock(h_idst);
c1595e42 36542+ err = vfsub_setxattr(h_dst, name, *buf, ssz, /*flags*/0);
febd17d6 36543+ inode_lock_nested(h_idst, AuLsc_I_CHILD2);
c1595e42 36544+ if (unlikely(err)) {
7e9cd9fe
AM
36545+ if (verbose || au_debug_test())
36546+ pr_err("%s, err %d\n", name, err);
c1595e42
JR
36547+ err = au_xattr_ignore(err, name, ignore_flags);
36548+ }
36549+
36550+out:
36551+ return err;
36552+}
36553+
7e9cd9fe
AM
36554+int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags,
36555+ unsigned int verbose)
c1595e42
JR
36556+{
36557+ int err, unlocked, acl_access, acl_default;
36558+ ssize_t ssz;
36559+ struct inode *h_isrc, *h_idst;
36560+ char *value, *p, *o, *e;
36561+
36562+ /* try stopping to update the source inode while we are referencing */
7e9cd9fe 36563+ /* there should not be the parent-child relationship between them */
5527c038
JR
36564+ h_isrc = d_inode(h_src);
36565+ h_idst = d_inode(h_dst);
febd17d6 36566+ inode_unlock(h_idst);
be118d29 36567+ inode_lock_shared_nested(h_isrc, AuLsc_I_CHILD);
febd17d6 36568+ inode_lock_nested(h_idst, AuLsc_I_CHILD2);
c1595e42
JR
36569+ unlocked = 0;
36570+
36571+ /* some filesystems don't list POSIX ACL, for example tmpfs */
36572+ ssz = vfs_listxattr(h_src, NULL, 0);
36573+ err = ssz;
36574+ if (unlikely(err < 0)) {
36575+ AuTraceErr(err);
36576+ if (err == -ENODATA
36577+ || err == -EOPNOTSUPP)
36578+ err = 0; /* ignore */
36579+ goto out;
36580+ }
36581+
36582+ err = 0;
36583+ p = NULL;
36584+ o = NULL;
36585+ if (ssz) {
36586+ err = -ENOMEM;
36587+ p = kmalloc(ssz, GFP_NOFS);
36588+ o = p;
36589+ if (unlikely(!p))
36590+ goto out;
36591+ err = vfs_listxattr(h_src, p, ssz);
36592+ }
3c1bdaff 36593+ inode_unlock_shared(h_isrc);
c1595e42
JR
36594+ unlocked = 1;
36595+ AuDbg("err %d, ssz %zd\n", err, ssz);
36596+ if (unlikely(err < 0))
36597+ goto out_free;
36598+
36599+ err = 0;
36600+ e = p + ssz;
36601+ value = NULL;
36602+ acl_access = 0;
36603+ acl_default = 0;
36604+ while (!err && p < e) {
36605+ acl_access |= !strncmp(p, XATTR_NAME_POSIX_ACL_ACCESS,
36606+ sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1);
36607+ acl_default |= !strncmp(p, XATTR_NAME_POSIX_ACL_DEFAULT,
36608+ sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)
36609+ - 1);
7e9cd9fe
AM
36610+ err = au_do_cpup_xattr(h_dst, h_src, p, &value, ignore_flags,
36611+ verbose);
c1595e42
JR
36612+ p += strlen(p) + 1;
36613+ }
36614+ AuTraceErr(err);
36615+ ignore_flags |= au_xattr_out_of_list;
36616+ if (!err && !acl_access) {
36617+ err = au_do_cpup_xattr(h_dst, h_src,
36618+ XATTR_NAME_POSIX_ACL_ACCESS, &value,
7e9cd9fe 36619+ ignore_flags, verbose);
c1595e42
JR
36620+ AuTraceErr(err);
36621+ }
36622+ if (!err && !acl_default) {
36623+ err = au_do_cpup_xattr(h_dst, h_src,
36624+ XATTR_NAME_POSIX_ACL_DEFAULT, &value,
7e9cd9fe 36625+ ignore_flags, verbose);
c1595e42
JR
36626+ AuTraceErr(err);
36627+ }
36628+
9f237c51 36629+ au_kfree_try_rcu(value);
c1595e42
JR
36630+
36631+out_free:
9f237c51 36632+ au_kfree_try_rcu(o);
c1595e42
JR
36633+out:
36634+ if (!unlocked)
3c1bdaff 36635+ inode_unlock_shared(h_isrc);
c1595e42
JR
36636+ AuTraceErr(err);
36637+ return err;
36638+}
36639+
36640+/* ---------------------------------------------------------------------- */
36641+
a2654f78
AM
36642+static int au_smack_reentering(struct super_block *sb)
36643+{
36644+#if IS_ENABLED(CONFIG_SECURITY_SMACK)
36645+ /*
36646+ * as a part of lookup, smack_d_instantiate() is called, and it calls
36647+ * i_op->getxattr(). ouch.
36648+ */
36649+ return si_pid_test(sb);
36650+#else
36651+ return 0;
36652+#endif
36653+}
36654+
c1595e42
JR
36655+enum {
36656+ AU_XATTR_LIST,
36657+ AU_XATTR_GET
36658+};
36659+
36660+struct au_lgxattr {
36661+ int type;
36662+ union {
36663+ struct {
36664+ char *list;
36665+ size_t size;
36666+ } list;
36667+ struct {
36668+ const char *name;
36669+ void *value;
36670+ size_t size;
36671+ } get;
36672+ } u;
36673+};
36674+
36675+static ssize_t au_lgxattr(struct dentry *dentry, struct au_lgxattr *arg)
36676+{
36677+ ssize_t err;
a2654f78 36678+ int reenter;
c1595e42
JR
36679+ struct path h_path;
36680+ struct super_block *sb;
36681+
36682+ sb = dentry->d_sb;
a2654f78
AM
36683+ reenter = au_smack_reentering(sb);
36684+ if (!reenter) {
36685+ err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
36686+ if (unlikely(err))
36687+ goto out;
36688+ }
36689+ err = au_h_path_getattr(dentry, /*force*/1, &h_path, reenter);
c1595e42
JR
36690+ if (unlikely(err))
36691+ goto out_si;
36692+ if (unlikely(!h_path.dentry))
36693+ /* illegally overlapped or something */
36694+ goto out_di; /* pretending success */
36695+
36696+ /* always topmost entry only */
36697+ switch (arg->type) {
36698+ case AU_XATTR_LIST:
36699+ err = vfs_listxattr(h_path.dentry,
36700+ arg->u.list.list, arg->u.list.size);
36701+ break;
36702+ case AU_XATTR_GET:
5afbbe0d 36703+ AuDebugOn(d_is_negative(h_path.dentry));
c1595e42
JR
36704+ err = vfs_getxattr(h_path.dentry,
36705+ arg->u.get.name, arg->u.get.value,
36706+ arg->u.get.size);
36707+ break;
36708+ }
36709+
36710+out_di:
a2654f78
AM
36711+ if (!reenter)
36712+ di_read_unlock(dentry, AuLock_IR);
c1595e42 36713+out_si:
a2654f78
AM
36714+ if (!reenter)
36715+ si_read_unlock(sb);
c1595e42
JR
36716+out:
36717+ AuTraceErr(err);
36718+ return err;
36719+}
36720+
36721+ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size)
36722+{
36723+ struct au_lgxattr arg = {
36724+ .type = AU_XATTR_LIST,
36725+ .u.list = {
36726+ .list = list,
36727+ .size = size
36728+ },
36729+ };
36730+
36731+ return au_lgxattr(dentry, &arg);
36732+}
36733+
f2c43d5f
AM
36734+static ssize_t au_getxattr(struct dentry *dentry,
36735+ struct inode *inode __maybe_unused,
36736+ const char *name, void *value, size_t size)
c1595e42
JR
36737+{
36738+ struct au_lgxattr arg = {
36739+ .type = AU_XATTR_GET,
36740+ .u.get = {
36741+ .name = name,
36742+ .value = value,
36743+ .size = size
36744+ },
36745+ };
36746+
36747+ return au_lgxattr(dentry, &arg);
36748+}
36749+
f2c43d5f
AM
36750+static int au_setxattr(struct dentry *dentry, struct inode *inode,
36751+ const char *name, const void *value, size_t size,
36752+ int flags)
c1595e42 36753+{
f2c43d5f 36754+ struct au_sxattr arg = {
c1595e42
JR
36755+ .type = AU_XATTR_SET,
36756+ .u.set = {
36757+ .name = name,
36758+ .value = value,
36759+ .size = size,
36760+ .flags = flags
36761+ },
36762+ };
36763+
f2c43d5f 36764+ return au_sxattr(dentry, inode, &arg);
c1595e42
JR
36765+}
36766+
36767+/* ---------------------------------------------------------------------- */
36768+
f2c43d5f
AM
36769+static int au_xattr_get(const struct xattr_handler *handler,
36770+ struct dentry *dentry, struct inode *inode,
36771+ const char *name, void *buffer, size_t size)
c1595e42 36772+{
f2c43d5f 36773+ return au_getxattr(dentry, inode, name, buffer, size);
c1595e42
JR
36774+}
36775+
f2c43d5f
AM
36776+static int au_xattr_set(const struct xattr_handler *handler,
36777+ struct dentry *dentry, struct inode *inode,
36778+ const char *name, const void *value, size_t size,
36779+ int flags)
c1595e42 36780+{
f2c43d5f 36781+ return au_setxattr(dentry, inode, name, value, size, flags);
c1595e42
JR
36782+}
36783+
36784+static const struct xattr_handler au_xattr_handler = {
f2c43d5f
AM
36785+ .name = "",
36786+ .prefix = "",
c1595e42
JR
36787+ .get = au_xattr_get,
36788+ .set = au_xattr_set
c1595e42
JR
36789+};
36790+
36791+static const struct xattr_handler *au_xattr_handlers[] = {
a2654f78
AM
36792+#ifdef CONFIG_FS_POSIX_ACL
36793+ &posix_acl_access_xattr_handler,
36794+ &posix_acl_default_xattr_handler,
36795+#endif
36796+ &au_xattr_handler, /* must be last */
f2c43d5f 36797+ NULL
c1595e42
JR
36798+};
36799+
36800+void au_xattr_init(struct super_block *sb)
36801+{
f2c43d5f 36802+ sb->s_xattr = au_xattr_handlers;
c1595e42 36803+}
7f207e10 36804diff -urN /usr/share/empty/fs/aufs/xino.c linux/fs/aufs/xino.c
eca34b5c 36805--- /usr/share/empty/fs/aufs/xino.c 1970-01-01 01:00:00.000000000 +0100
016522bc
AM
36806+++ linux/fs/aufs/xino.c 2020-04-03 08:16:49.834195677 +0200
36807@@ -0,0 +1,1966 @@
cd7a4cd9 36808+// SPDX-License-Identifier: GPL-2.0
1facf9fc 36809+/*
016522bc 36810+ * Copyright (C) 2005-2020 Junjiro R. Okajima
1facf9fc 36811+ *
36812+ * This program, aufs is free software; you can redistribute it and/or modify
36813+ * it under the terms of the GNU General Public License as published by
36814+ * the Free Software Foundation; either version 2 of the License, or
36815+ * (at your option) any later version.
dece6358
AM
36816+ *
36817+ * This program is distributed in the hope that it will be useful,
36818+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
36819+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36820+ * GNU General Public License for more details.
36821+ *
36822+ * You should have received a copy of the GNU General Public License
523b37e3 36823+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1facf9fc 36824+ */
36825+
36826+/*
36827+ * external inode number translation table and bitmap
062440b3
AM
36828+ *
36829+ * things to consider
36830+ * - the lifetime
36831+ * + au_xino object
36832+ * + XINO files (xino, xib, xigen)
36833+ * + dynamic debugfs entries (xiN)
36834+ * + static debugfs entries (xib, xigen)
36835+ * + static sysfs entry (xi_path)
36836+ * - several entry points to handle them.
36837+ * + mount(2) without xino option (default)
36838+ * + mount(2) with xino option
36839+ * + mount(2) with noxino option
36840+ * + umount(2)
36841+ * + remount with add/del branches
36842+ * + remount with xino/noxino options
1facf9fc 36843+ */
36844+
36845+#include <linux/seq_file.h>
392086de 36846+#include <linux/statfs.h>
1facf9fc 36847+#include "aufs.h"
36848+
062440b3
AM
36849+static aufs_bindex_t sbr_find_shared(struct super_block *sb, aufs_bindex_t btop,
36850+ aufs_bindex_t bbot,
36851+ struct super_block *h_sb)
1facf9fc 36852+{
062440b3
AM
36853+ /* todo: try binary-search if the branches are many */
36854+ for (; btop <= bbot; btop++)
36855+ if (h_sb == au_sbr_sb(sb, btop))
36856+ return btop;
36857+ return -1;
be52b249
AM
36858+}
36859+
062440b3
AM
36860+/*
36861+ * find another branch who is on the same filesystem of the specified
36862+ * branch{@btgt}. search until @bbot.
36863+ */
36864+static aufs_bindex_t is_sb_shared(struct super_block *sb, aufs_bindex_t btgt,
36865+ aufs_bindex_t bbot)
1facf9fc 36866+{
062440b3
AM
36867+ aufs_bindex_t bindex;
36868+ struct super_block *tgt_sb;
1facf9fc 36869+
062440b3
AM
36870+ tgt_sb = au_sbr_sb(sb, btgt);
36871+ bindex = sbr_find_shared(sb, /*btop*/0, btgt - 1, tgt_sb);
36872+ if (bindex < 0)
36873+ bindex = sbr_find_shared(sb, btgt + 1, bbot, tgt_sb);
1facf9fc 36874+
062440b3 36875+ return bindex;
1facf9fc 36876+}
36877+
36878+/* ---------------------------------------------------------------------- */
36879+
36880+/*
062440b3 36881+ * stop unnecessary notify events at creating xino files
1facf9fc 36882+ */
acd2b654
AM
36883+
36884+aufs_bindex_t au_xi_root(struct super_block *sb, struct dentry *dentry)
36885+{
36886+ aufs_bindex_t bfound, bindex, bbot;
36887+ struct dentry *parent;
36888+ struct au_branch *br;
36889+
36890+ bfound = -1;
36891+ parent = dentry->d_parent; /* safe d_parent access */
36892+ bbot = au_sbbot(sb);
36893+ for (bindex = 0; bindex <= bbot; bindex++) {
36894+ br = au_sbr(sb, bindex);
36895+ if (au_br_dentry(br) == parent) {
36896+ bfound = bindex;
36897+ break;
36898+ }
36899+ }
36900+
36901+ AuDbg("bfound b%d\n", bfound);
36902+ return bfound;
36903+}
36904+
062440b3
AM
36905+struct au_xino_lock_dir {
36906+ struct au_hinode *hdir;
36907+ struct dentry *parent;
36908+ struct inode *dir;
36909+};
36910+
36911+static struct dentry *au_dget_parent_lock(struct dentry *dentry,
36912+ unsigned int lsc)
1facf9fc 36913+{
062440b3
AM
36914+ struct dentry *parent;
36915+ struct inode *dir;
1facf9fc 36916+
062440b3 36917+ parent = dget_parent(dentry);
5527c038 36918+ dir = d_inode(parent);
062440b3
AM
36919+ inode_lock_nested(dir, lsc);
36920+#if 0 /* it should not happen */
36921+ spin_lock(&dentry->d_lock);
36922+ if (unlikely(dentry->d_parent != parent)) {
36923+ spin_unlock(&dentry->d_lock);
36924+ inode_unlock(dir);
36925+ dput(parent);
36926+ parent = NULL;
1facf9fc 36927+ goto out;
36928+ }
062440b3 36929+ spin_unlock(&dentry->d_lock);
1facf9fc 36930+
4f0767ce 36931+out:
062440b3
AM
36932+#endif
36933+ return parent;
1facf9fc 36934+}
36935+
062440b3 36936+static void au_xino_lock_dir(struct super_block *sb, struct path *xipath,
1facf9fc 36937+ struct au_xino_lock_dir *ldir)
36938+{
acd2b654 36939+ aufs_bindex_t bindex;
1facf9fc 36940+
36941+ ldir->hdir = NULL;
acd2b654 36942+ bindex = au_xi_root(sb, xipath->dentry);
1facf9fc 36943+ if (bindex >= 0) {
062440b3 36944+ /* rw branch root */
5527c038 36945+ ldir->hdir = au_hi(d_inode(sb->s_root), bindex);
5afbbe0d 36946+ au_hn_inode_lock_nested(ldir->hdir, AuLsc_I_PARENT);
1facf9fc 36947+ } else {
062440b3
AM
36948+ /* other */
36949+ ldir->parent = au_dget_parent_lock(xipath->dentry,
36950+ AuLsc_I_PARENT);
febd17d6 36951+ ldir->dir = d_inode(ldir->parent);
1facf9fc 36952+ }
36953+}
36954+
36955+static void au_xino_unlock_dir(struct au_xino_lock_dir *ldir)
36956+{
36957+ if (ldir->hdir)
5afbbe0d 36958+ au_hn_inode_unlock(ldir->hdir);
1facf9fc 36959+ else {
febd17d6 36960+ inode_unlock(ldir->dir);
1facf9fc 36961+ dput(ldir->parent);
36962+ }
36963+}
36964+
36965+/* ---------------------------------------------------------------------- */
36966+
062440b3
AM
36967+/*
36968+ * create and set a new xino file
36969+ */
83b672a5
AM
36970+struct file *au_xino_create(struct super_block *sb, char *fpath, int silent,
36971+ int wbrtop)
062440b3
AM
36972+{
36973+ struct file *file;
36974+ struct dentry *h_parent, *d;
36975+ struct inode *h_dir, *inode;
36976+ int err;
83b672a5 36977+ static DEFINE_MUTEX(mtx);
062440b3
AM
36978+
36979+ /*
36980+ * at mount-time, and the xino file is the default path,
36981+ * hnotify is disabled so we have no notify events to ignore.
36982+ * when a user specified the xino, we cannot get au_hdir to be ignored.
36983+ */
83b672a5
AM
36984+ if (!wbrtop)
36985+ mutex_lock(&mtx);
062440b3
AM
36986+ file = vfsub_filp_open(fpath, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
36987+ /* | __FMODE_NONOTIFY */,
cd7a4cd9 36988+ 0666);
062440b3 36989+ if (IS_ERR(file)) {
83b672a5
AM
36990+ if (!wbrtop)
36991+ mutex_unlock(&mtx);
062440b3
AM
36992+ if (!silent)
36993+ pr_err("open %s(%ld)\n", fpath, PTR_ERR(file));
36994+ return file;
36995+ }
36996+
36997+ /* keep file count */
36998+ err = 0;
36999+ d = file->f_path.dentry;
37000+ h_parent = au_dget_parent_lock(d, AuLsc_I_PARENT);
83b672a5
AM
37001+ if (!wbrtop)
37002+ mutex_unlock(&mtx);
062440b3
AM
37003+ /* mnt_want_write() is unnecessary here */
37004+ h_dir = d_inode(h_parent);
37005+ inode = file_inode(file);
37006+ /* no delegation since it is just created */
37007+ if (inode->i_nlink)
37008+ err = vfsub_unlink(h_dir, &file->f_path, /*delegated*/NULL,
37009+ /*force*/0);
37010+ inode_unlock(h_dir);
37011+ dput(h_parent);
37012+ if (unlikely(err)) {
37013+ if (!silent)
37014+ pr_err("unlink %s(%d)\n", fpath, err);
37015+ goto out;
37016+ }
37017+
37018+ err = -EINVAL;
37019+ if (unlikely(sb == d->d_sb)) {
37020+ if (!silent)
37021+ pr_err("%s must be outside\n", fpath);
37022+ goto out;
37023+ }
37024+ if (unlikely(au_test_fs_bad_xino(d->d_sb))) {
37025+ if (!silent)
37026+ pr_err("xino doesn't support %s(%s)\n",
37027+ fpath, au_sbtype(d->d_sb));
37028+ goto out;
37029+ }
37030+ return file; /* success */
37031+
37032+out:
37033+ fput(file);
37034+ file = ERR_PTR(err);
37035+ return file;
37036+}
37037+
37038+/*
37039+ * create a new xinofile at the same place/path as @base.
37040+ */
37041+struct file *au_xino_create2(struct super_block *sb, struct path *base,
37042+ struct file *copy_src)
37043+{
37044+ struct file *file;
37045+ struct dentry *dentry, *parent;
37046+ struct inode *dir, *delegated;
37047+ struct qstr *name;
37048+ struct path path;
37049+ int err, do_unlock;
37050+ struct au_xino_lock_dir ldir;
37051+
37052+ do_unlock = 1;
37053+ au_xino_lock_dir(sb, base, &ldir);
37054+ dentry = base->dentry;
37055+ parent = dentry->d_parent; /* dir inode is locked */
37056+ dir = d_inode(parent);
37057+ IMustLock(dir);
37058+
37059+ name = &dentry->d_name;
37060+ path.dentry = vfsub_lookup_one_len(name->name, parent, name->len);
37061+ if (IS_ERR(path.dentry)) {
37062+ file = (void *)path.dentry;
37063+ pr_err("%pd lookup err %ld\n", dentry, PTR_ERR(path.dentry));
37064+ goto out;
37065+ }
37066+
37067+ /* no need to mnt_want_write() since we call dentry_open() later */
cd7a4cd9 37068+ err = vfs_create(dir, path.dentry, 0666, NULL);
062440b3
AM
37069+ if (unlikely(err)) {
37070+ file = ERR_PTR(err);
37071+ pr_err("%pd create err %d\n", dentry, err);
37072+ goto out_dput;
37073+ }
37074+
37075+ path.mnt = base->mnt;
37076+ file = vfsub_dentry_open(&path,
37077+ O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE
37078+ /* | __FMODE_NONOTIFY */);
37079+ if (IS_ERR(file)) {
37080+ pr_err("%pd open err %ld\n", dentry, PTR_ERR(file));
37081+ goto out_dput;
37082+ }
37083+
37084+ delegated = NULL;
37085+ err = vfsub_unlink(dir, &file->f_path, &delegated, /*force*/0);
37086+ au_xino_unlock_dir(&ldir);
37087+ do_unlock = 0;
37088+ if (unlikely(err == -EWOULDBLOCK)) {
37089+ pr_warn("cannot retry for NFSv4 delegation"
37090+ " for an internal unlink\n");
37091+ iput(delegated);
37092+ }
37093+ if (unlikely(err)) {
37094+ pr_err("%pd unlink err %d\n", dentry, err);
37095+ goto out_fput;
37096+ }
37097+
37098+ if (copy_src) {
37099+ /* no one can touch copy_src xino */
37100+ err = au_copy_file(file, copy_src, vfsub_f_size_read(copy_src));
37101+ if (unlikely(err)) {
37102+ pr_err("%pd copy err %d\n", dentry, err);
37103+ goto out_fput;
37104+ }
37105+ }
37106+ goto out_dput; /* success */
1facf9fc 37107+
062440b3
AM
37108+out_fput:
37109+ fput(file);
37110+ file = ERR_PTR(err);
37111+out_dput:
37112+ dput(path.dentry);
37113+out:
37114+ if (do_unlock)
37115+ au_xino_unlock_dir(&ldir);
37116+ return file;
37117+}
37118+
acd2b654
AM
37119+struct file *au_xino_file1(struct au_xino *xi)
37120+{
37121+ struct file *file;
37122+ unsigned int u, nfile;
37123+
37124+ file = NULL;
37125+ nfile = xi->xi_nfile;
37126+ for (u = 0; u < nfile; u++) {
37127+ file = xi->xi_file[u];
37128+ if (file)
37129+ break;
37130+ }
37131+
37132+ return file;
37133+}
37134+
37135+static int au_xino_file_set(struct au_xino *xi, int idx, struct file *file)
37136+{
37137+ int err;
37138+ struct file *f;
37139+ void *p;
37140+
37141+ if (file)
37142+ get_file(file);
37143+
37144+ err = 0;
37145+ f = NULL;
37146+ if (idx < xi->xi_nfile) {
37147+ f = xi->xi_file[idx];
37148+ if (f)
37149+ fput(f);
37150+ } else {
37151+ p = au_kzrealloc(xi->xi_file,
37152+ sizeof(*xi->xi_file) * xi->xi_nfile,
37153+ sizeof(*xi->xi_file) * (idx + 1),
37154+ GFP_NOFS, /*may_shrink*/0);
37155+ if (p) {
37156+ MtxMustLock(&xi->xi_mtx);
37157+ xi->xi_file = p;
37158+ xi->xi_nfile = idx + 1;
37159+ } else {
37160+ err = -ENOMEM;
37161+ if (file)
37162+ fput(file);
37163+ goto out;
37164+ }
37165+ }
37166+ xi->xi_file[idx] = file;
37167+
37168+out:
37169+ return err;
37170+}
37171+
37172+/*
37173+ * if @xinew->xi is not set, then create new xigen file.
37174+ */
37175+struct file *au_xi_new(struct super_block *sb, struct au_xi_new *xinew)
37176+{
37177+ struct file *file;
37178+ int err;
37179+
37180+ SiMustAnyLock(sb);
37181+
37182+ file = au_xino_create2(sb, xinew->base, xinew->copy_src);
37183+ if (IS_ERR(file)) {
37184+ err = PTR_ERR(file);
37185+ pr_err("%s[%d], err %d\n",
37186+ xinew->xi ? "xino" : "xigen",
37187+ xinew->idx, err);
37188+ goto out;
37189+ }
37190+
37191+ if (xinew->xi)
37192+ err = au_xino_file_set(xinew->xi, xinew->idx, file);
37193+ else {
37194+ BUG();
37195+ /* todo: make xigen file an array */
37196+ /* err = au_xigen_file_set(sb, xinew->idx, file); */
37197+ }
37198+ fput(file);
37199+ if (unlikely(err))
37200+ file = ERR_PTR(err);
37201+
37202+out:
37203+ return file;
37204+}
37205+
062440b3
AM
37206+/* ---------------------------------------------------------------------- */
37207+
37208+/*
37209+ * truncate xino files
37210+ */
acd2b654
AM
37211+static int au_xino_do_trunc(struct super_block *sb, aufs_bindex_t bindex,
37212+ int idx, struct kstatfs *st)
1facf9fc 37213+{
37214+ int err;
392086de 37215+ blkcnt_t blocks;
acd2b654
AM
37216+ struct file *file, *new_xino;
37217+ struct au_xi_new xinew = {
37218+ .idx = idx
37219+ };
37220+
37221+ err = 0;
37222+ xinew.xi = au_sbr(sb, bindex)->br_xino;
37223+ file = au_xino_file(xinew.xi, idx);
37224+ if (!file)
37225+ goto out;
37226+
37227+ xinew.base = &file->f_path;
37228+ err = vfs_statfs(xinew.base, st);
37229+ if (unlikely(err)) {
37230+ AuErr1("statfs err %d, ignored\n", err);
37231+ err = 0;
37232+ goto out;
37233+ }
37234+
37235+ blocks = file_inode(file)->i_blocks;
37236+ pr_info("begin truncating xino(b%d-%d), ib%llu, %llu/%llu free blks\n",
37237+ bindex, idx, (u64)blocks, st->f_bfree, st->f_blocks);
37238+
37239+ xinew.copy_src = file;
37240+ new_xino = au_xi_new(sb, &xinew);
37241+ if (IS_ERR(new_xino)) {
37242+ err = PTR_ERR(new_xino);
37243+ pr_err("xino(b%d-%d), err %d, ignored\n", bindex, idx, err);
37244+ goto out;
37245+ }
37246+
37247+ err = vfs_statfs(&new_xino->f_path, st);
37248+ if (!err)
37249+ pr_info("end truncating xino(b%d-%d), ib%llu, %llu/%llu free blks\n",
37250+ bindex, idx, (u64)file_inode(new_xino)->i_blocks,
37251+ st->f_bfree, st->f_blocks);
37252+ else {
37253+ AuErr1("statfs err %d, ignored\n", err);
37254+ err = 0;
37255+ }
37256+
37257+out:
37258+ return err;
37259+}
37260+
37261+int au_xino_trunc(struct super_block *sb, aufs_bindex_t bindex, int idx_begin)
37262+{
37263+ int err, i;
37264+ unsigned long jiffy;
062440b3 37265+ aufs_bindex_t bbot;
392086de 37266+ struct kstatfs *st;
1facf9fc 37267+ struct au_branch *br;
acd2b654 37268+ struct au_xino *xi;
1facf9fc 37269+
392086de 37270+ err = -ENOMEM;
be52b249 37271+ st = kmalloc(sizeof(*st), GFP_NOFS);
392086de
AM
37272+ if (unlikely(!st))
37273+ goto out;
37274+
1facf9fc 37275+ err = -EINVAL;
5afbbe0d
AM
37276+ bbot = au_sbbot(sb);
37277+ if (unlikely(bindex < 0 || bbot < bindex))
392086de 37278+ goto out_st;
392086de 37279+
1facf9fc 37280+ err = 0;
acd2b654
AM
37281+ jiffy = jiffies;
37282+ br = au_sbr(sb, bindex);
37283+ xi = br->br_xino;
37284+ for (i = idx_begin; !err && i < xi->xi_nfile; i++)
37285+ err = au_xino_do_trunc(sb, bindex, i, st);
37286+ if (!err)
37287+ au_sbi(sb)->si_xino_jiffy = jiffy;
392086de
AM
37288+
37289+out_st:
9f237c51 37290+ au_kfree_rcu(st);
4f0767ce 37291+out:
1facf9fc 37292+ return err;
37293+}
37294+
37295+struct xino_do_trunc_args {
37296+ struct super_block *sb;
37297+ struct au_branch *br;
acd2b654 37298+ int idx;
1facf9fc 37299+};
37300+
37301+static void xino_do_trunc(void *_args)
37302+{
37303+ struct xino_do_trunc_args *args = _args;
37304+ struct super_block *sb;
37305+ struct au_branch *br;
37306+ struct inode *dir;
acd2b654 37307+ int err, idx;
1facf9fc 37308+ aufs_bindex_t bindex;
37309+
37310+ err = 0;
37311+ sb = args->sb;
5527c038 37312+ dir = d_inode(sb->s_root);
1facf9fc 37313+ br = args->br;
acd2b654 37314+ idx = args->idx;
1facf9fc 37315+
37316+ si_noflush_write_lock(sb);
37317+ ii_read_lock_parent(dir);
37318+ bindex = au_br_index(sb, br->br_id);
acd2b654 37319+ err = au_xino_trunc(sb, bindex, idx);
1facf9fc 37320+ ii_read_unlock(dir);
37321+ if (unlikely(err))
392086de 37322+ pr_warn("err b%d, (%d)\n", bindex, err);
062440b3 37323+ atomic_dec(&br->br_xino->xi_truncating);
acd2b654 37324+ au_lcnt_dec(&br->br_count);
1facf9fc 37325+ si_write_unlock(sb);
027c5e7a 37326+ au_nwt_done(&au_sbi(sb)->si_nowait);
9f237c51 37327+ au_kfree_rcu(args);
1facf9fc 37328+}
37329+
acd2b654
AM
37330+/*
37331+ * returns the index in the xi_file array whose corresponding file is necessary
37332+ * to truncate, or -1 which means no need to truncate.
37333+ */
392086de
AM
37334+static int xino_trunc_test(struct super_block *sb, struct au_branch *br)
37335+{
37336+ int err;
acd2b654 37337+ unsigned int u;
392086de
AM
37338+ struct kstatfs st;
37339+ struct au_sbinfo *sbinfo;
acd2b654 37340+ struct au_xino *xi;
062440b3 37341+ struct file *file;
392086de
AM
37342+
37343+ /* todo: si_xino_expire and the ratio should be customizable */
37344+ sbinfo = au_sbi(sb);
37345+ if (time_before(jiffies,
37346+ sbinfo->si_xino_jiffy + sbinfo->si_xino_expire))
acd2b654 37347+ return -1;
392086de
AM
37348+
37349+ /* truncation border */
acd2b654
AM
37350+ xi = br->br_xino;
37351+ for (u = 0; u < xi->xi_nfile; u++) {
37352+ file = au_xino_file(xi, u);
37353+ if (!file)
37354+ continue;
37355+
37356+ err = vfs_statfs(&file->f_path, &st);
37357+ if (unlikely(err)) {
37358+ AuErr1("statfs err %d, ignored\n", err);
37359+ return -1;
37360+ }
37361+ if (div64_u64(st.f_bfree * 100, st.f_blocks)
37362+ >= AUFS_XINO_DEF_TRUNC)
37363+ return u;
392086de 37364+ }
392086de 37365+
acd2b654 37366+ return -1;
392086de
AM
37367+}
37368+
1facf9fc 37369+static void xino_try_trunc(struct super_block *sb, struct au_branch *br)
37370+{
acd2b654 37371+ int idx;
1facf9fc 37372+ struct xino_do_trunc_args *args;
37373+ int wkq_err;
37374+
acd2b654
AM
37375+ idx = xino_trunc_test(sb, br);
37376+ if (idx < 0)
1facf9fc 37377+ return;
37378+
062440b3 37379+ if (atomic_inc_return(&br->br_xino->xi_truncating) > 1)
1facf9fc 37380+ goto out;
37381+
37382+ /* lock and kfree() will be called in trunc_xino() */
37383+ args = kmalloc(sizeof(*args), GFP_NOFS);
37384+ if (unlikely(!args)) {
37385+ AuErr1("no memory\n");
f0c0a007 37386+ goto out;
1facf9fc 37387+ }
37388+
acd2b654 37389+ au_lcnt_inc(&br->br_count);
1facf9fc 37390+ args->sb = sb;
37391+ args->br = br;
acd2b654 37392+ args->idx = idx;
53392da6 37393+ wkq_err = au_wkq_nowait(xino_do_trunc, args, sb, /*flags*/0);
1facf9fc 37394+ if (!wkq_err)
37395+ return; /* success */
37396+
4a4d8108 37397+ pr_err("wkq %d\n", wkq_err);
acd2b654 37398+ au_lcnt_dec(&br->br_count);
9f237c51 37399+ au_kfree_rcu(args);
1facf9fc 37400+
4f0767ce 37401+out:
062440b3 37402+ atomic_dec(&br->br_xino->xi_truncating);
1facf9fc 37403+}
37404+
37405+/* ---------------------------------------------------------------------- */
37406+
acd2b654
AM
37407+struct au_xi_calc {
37408+ int idx;
37409+ loff_t pos;
37410+};
37411+
37412+static void au_xi_calc(struct super_block *sb, ino_t h_ino,
37413+ struct au_xi_calc *calc)
37414+{
37415+ loff_t maxent;
37416+
37417+ maxent = au_xi_maxent(sb);
37418+ calc->idx = div64_u64_rem(h_ino, maxent, &calc->pos);
37419+ calc->pos *= sizeof(ino_t);
37420+}
37421+
37422+static int au_xino_do_new_async(struct super_block *sb, struct au_branch *br,
37423+ struct au_xi_calc *calc)
37424+{
37425+ int err;
37426+ struct file *file;
37427+ struct au_xino *xi = br->br_xino;
37428+ struct au_xi_new xinew = {
37429+ .xi = xi
37430+ };
37431+
37432+ SiMustAnyLock(sb);
37433+
37434+ err = 0;
37435+ if (!xi)
37436+ goto out;
37437+
37438+ mutex_lock(&xi->xi_mtx);
37439+ file = au_xino_file(xi, calc->idx);
37440+ if (file)
37441+ goto out_mtx;
37442+
37443+ file = au_xino_file(xi, /*idx*/-1);
37444+ AuDebugOn(!file);
37445+ xinew.idx = calc->idx;
37446+ xinew.base = &file->f_path;
37447+ /* xinew.copy_src = NULL; */
37448+ file = au_xi_new(sb, &xinew);
37449+ if (IS_ERR(file))
37450+ err = PTR_ERR(file);
37451+
37452+out_mtx:
37453+ mutex_unlock(&xi->xi_mtx);
37454+out:
37455+ return err;
37456+}
37457+
37458+struct au_xino_do_new_async_args {
37459+ struct super_block *sb;
37460+ struct au_branch *br;
37461+ struct au_xi_calc calc;
37462+ ino_t ino;
37463+};
37464+
9f237c51
AM
37465+struct au_xi_writing {
37466+ struct hlist_bl_node node;
37467+ ino_t h_ino, ino;
37468+};
37469+
acd2b654
AM
37470+static int au_xino_do_write(vfs_writef_t write, struct file *file,
37471+ struct au_xi_calc *calc, ino_t ino);
37472+
37473+static void au_xino_call_do_new_async(void *args)
37474+{
37475+ struct au_xino_do_new_async_args *a = args;
37476+ struct au_branch *br;
37477+ struct super_block *sb;
37478+ struct au_sbinfo *sbi;
37479+ struct inode *root;
37480+ struct file *file;
9f237c51
AM
37481+ struct au_xi_writing *del, *p;
37482+ struct hlist_bl_head *hbl;
37483+ struct hlist_bl_node *pos;
acd2b654
AM
37484+ int err;
37485+
37486+ br = a->br;
37487+ sb = a->sb;
37488+ sbi = au_sbi(sb);
37489+ si_noflush_read_lock(sb);
37490+ root = d_inode(sb->s_root);
37491+ ii_read_lock_child(root);
37492+ err = au_xino_do_new_async(sb, br, &a->calc);
9f237c51
AM
37493+ if (unlikely(err)) {
37494+ AuIOErr("err %d\n", err);
37495+ goto out;
37496+ }
37497+
37498+ file = au_xino_file(br->br_xino, a->calc.idx);
37499+ AuDebugOn(!file);
37500+ err = au_xino_do_write(sbi->si_xwrite, file, &a->calc, a->ino);
37501+ if (unlikely(err)) {
acd2b654 37502+ AuIOErr("err %d\n", err);
9f237c51
AM
37503+ goto out;
37504+ }
37505+
37506+ del = NULL;
37507+ hbl = &br->br_xino->xi_writing;
37508+ hlist_bl_lock(hbl);
37509+ au_hbl_for_each(pos, hbl) {
37510+ p = container_of(pos, struct au_xi_writing, node);
37511+ if (p->ino == a->ino) {
37512+ del = p;
37513+ hlist_bl_del(&p->node);
37514+ break;
37515+ }
37516+ }
37517+ hlist_bl_unlock(hbl);
37518+ au_kfree_rcu(del);
37519+
37520+out:
acd2b654
AM
37521+ au_lcnt_dec(&br->br_count);
37522+ ii_read_unlock(root);
37523+ si_read_unlock(sb);
37524+ au_nwt_done(&sbi->si_nowait);
9f237c51 37525+ au_kfree_rcu(a);
acd2b654
AM
37526+}
37527+
37528+/*
37529+ * create a new xino file asynchronously
37530+ */
37531+static int au_xino_new_async(struct super_block *sb, struct au_branch *br,
37532+ struct au_xi_calc *calc, ino_t ino)
37533+{
37534+ int err;
37535+ struct au_xino_do_new_async_args *arg;
37536+
37537+ err = -ENOMEM;
37538+ arg = kmalloc(sizeof(*arg), GFP_NOFS);
37539+ if (unlikely(!arg))
37540+ goto out;
37541+
37542+ arg->sb = sb;
37543+ arg->br = br;
37544+ arg->calc = *calc;
37545+ arg->ino = ino;
37546+ au_lcnt_inc(&br->br_count);
37547+ err = au_wkq_nowait(au_xino_call_do_new_async, arg, sb, AuWkq_NEST);
37548+ if (unlikely(err)) {
37549+ pr_err("wkq %d\n", err);
37550+ au_lcnt_dec(&br->br_count);
9f237c51 37551+ au_kfree_rcu(arg);
acd2b654
AM
37552+ }
37553+
37554+out:
37555+ return err;
37556+}
37557+
062440b3
AM
37558+/*
37559+ * read @ino from xinofile for the specified branch{@sb, @bindex}
37560+ * at the position of @h_ino.
37561+ */
37562+int au_xino_read(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
37563+ ino_t *ino)
37564+{
37565+ int err;
37566+ ssize_t sz;
acd2b654 37567+ struct au_xi_calc calc;
062440b3 37568+ struct au_sbinfo *sbinfo;
acd2b654 37569+ struct file *file;
9f237c51
AM
37570+ struct au_xino *xi;
37571+ struct hlist_bl_head *hbl;
37572+ struct hlist_bl_node *pos;
37573+ struct au_xi_writing *p;
062440b3
AM
37574+
37575+ *ino = 0;
37576+ if (!au_opt_test(au_mntflags(sb), XINO))
37577+ return 0; /* no xino */
37578+
37579+ err = 0;
acd2b654 37580+ au_xi_calc(sb, h_ino, &calc);
9f237c51
AM
37581+ xi = au_sbr(sb, bindex)->br_xino;
37582+ file = au_xino_file(xi, calc.idx);
37583+ if (!file) {
37584+ hbl = &xi->xi_writing;
37585+ hlist_bl_lock(hbl);
37586+ au_hbl_for_each(pos, hbl) {
37587+ p = container_of(pos, struct au_xi_writing, node);
37588+ if (p->h_ino == h_ino) {
37589+ AuDbg("hi%llu, i%llu, found\n",
37590+ (u64)p->h_ino, (u64)p->ino);
37591+ *ino = p->ino;
37592+ break;
37593+ }
37594+ }
37595+ hlist_bl_unlock(hbl);
37596+ return 0;
37597+ } else if (vfsub_f_size_read(file) < calc.pos + sizeof(*ino))
37598+ return 0; /* no xino */
062440b3 37599+
acd2b654
AM
37600+ sbinfo = au_sbi(sb);
37601+ sz = xino_fread(sbinfo->si_xread, file, ino, sizeof(*ino), &calc.pos);
062440b3
AM
37602+ if (sz == sizeof(*ino))
37603+ return 0; /* success */
37604+
37605+ err = sz;
37606+ if (unlikely(sz >= 0)) {
37607+ err = -EIO;
37608+ AuIOErr("xino read error (%zd)\n", sz);
37609+ }
062440b3
AM
37610+ return err;
37611+}
37612+
5527c038 37613+static int au_xino_do_write(vfs_writef_t write, struct file *file,
acd2b654 37614+ struct au_xi_calc *calc, ino_t ino)
1facf9fc 37615+{
1facf9fc 37616+ ssize_t sz;
37617+
acd2b654 37618+ sz = xino_fwrite(write, file, &ino, sizeof(ino), &calc->pos);
1facf9fc 37619+ if (sz == sizeof(ino))
37620+ return 0; /* success */
37621+
37622+ AuIOErr("write failed (%zd)\n", sz);
37623+ return -EIO;
37624+}
37625+
37626+/*
37627+ * write @ino to the xinofile for the specified branch{@sb, @bindex}
37628+ * at the position of @h_ino.
37629+ * even if @ino is zero, it is written to the xinofile and means no entry.
37630+ * if the size of the xino file on a specific filesystem exceeds the watermark,
37631+ * try truncating it.
37632+ */
37633+int au_xino_write(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
37634+ ino_t ino)
37635+{
37636+ int err;
37637+ unsigned int mnt_flags;
acd2b654
AM
37638+ struct au_xi_calc calc;
37639+ struct file *file;
1facf9fc 37640+ struct au_branch *br;
acd2b654 37641+ struct au_xino *xi;
9f237c51 37642+ struct au_xi_writing *p;
1facf9fc 37643+
dece6358 37644+ SiMustAnyLock(sb);
1facf9fc 37645+
37646+ mnt_flags = au_mntflags(sb);
37647+ if (!au_opt_test(mnt_flags, XINO))
37648+ return 0;
37649+
acd2b654 37650+ au_xi_calc(sb, h_ino, &calc);
1facf9fc 37651+ br = au_sbr(sb, bindex);
acd2b654
AM
37652+ xi = br->br_xino;
37653+ file = au_xino_file(xi, calc.idx);
37654+ if (!file) {
9f237c51
AM
37655+ /* store the inum pair into the list */
37656+ p = kmalloc(sizeof(*p), GFP_NOFS | __GFP_NOFAIL);
37657+ p->h_ino = h_ino;
37658+ p->ino = ino;
37659+ au_hbl_add(&p->node, &xi->xi_writing);
37660+
acd2b654
AM
37661+ /* create and write a new xino file asynchronously */
37662+ err = au_xino_new_async(sb, br, &calc, ino);
37663+ if (!err)
37664+ return 0; /* success */
37665+ goto out;
37666+ }
37667+
37668+ err = au_xino_do_write(au_sbi(sb)->si_xwrite, file, &calc, ino);
1facf9fc 37669+ if (!err) {
acd2b654 37670+ br = au_sbr(sb, bindex);
1facf9fc 37671+ if (au_opt_test(mnt_flags, TRUNC_XINO)
86dc4139 37672+ && au_test_fs_trunc_xino(au_br_sb(br)))
1facf9fc 37673+ xino_try_trunc(sb, br);
37674+ return 0; /* success */
37675+ }
37676+
acd2b654 37677+out:
1facf9fc 37678+ AuIOErr("write failed (%d)\n", err);
37679+ return -EIO;
37680+}
37681+
062440b3
AM
37682+static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf,
37683+ size_t size, loff_t *pos);
1facf9fc 37684+
062440b3
AM
37685+/* todo: unnecessary to support mmap_sem since kernel-space? */
37686+ssize_t xino_fread(vfs_readf_t func, struct file *file, void *kbuf, size_t size,
37687+ loff_t *pos)
37688+{
37689+ ssize_t err;
37690+ mm_segment_t oldfs;
37691+ union {
37692+ void *k;
37693+ char __user *u;
37694+ } buf;
37695+ int i;
37696+ const int prevent_endless = 10;
1facf9fc 37697+
062440b3
AM
37698+ i = 0;
37699+ buf.k = kbuf;
37700+ oldfs = get_fs();
37701+ set_fs(KERNEL_DS);
37702+ do {
37703+ err = func(file, buf.u, size, pos);
37704+ if (err == -EINTR
37705+ && !au_wkq_test()
37706+ && fatal_signal_pending(current)) {
37707+ set_fs(oldfs);
37708+ err = xino_fread_wkq(func, file, kbuf, size, pos);
37709+ BUG_ON(err == -EINTR);
37710+ oldfs = get_fs();
37711+ set_fs(KERNEL_DS);
37712+ }
37713+ } while (i++ < prevent_endless
37714+ && (err == -EAGAIN || err == -EINTR));
37715+ set_fs(oldfs);
37716+
37717+#if 0 /* reserved for future use */
37718+ if (err > 0)
37719+ fsnotify_access(file->f_path.dentry);
37720+#endif
37721+
37722+ return err;
37723+}
37724+
37725+struct xino_fread_args {
37726+ ssize_t *errp;
37727+ vfs_readf_t func;
37728+ struct file *file;
37729+ void *buf;
37730+ size_t size;
37731+ loff_t *pos;
37732+};
37733+
37734+static void call_xino_fread(void *args)
37735+{
37736+ struct xino_fread_args *a = args;
37737+ *a->errp = xino_fread(a->func, a->file, a->buf, a->size, a->pos);
37738+}
37739+
37740+static ssize_t xino_fread_wkq(vfs_readf_t func, struct file *file, void *buf,
37741+ size_t size, loff_t *pos)
37742+{
37743+ ssize_t err;
37744+ int wkq_err;
37745+ struct xino_fread_args args = {
37746+ .errp = &err,
37747+ .func = func,
37748+ .file = file,
37749+ .buf = buf,
37750+ .size = size,
37751+ .pos = pos
37752+ };
37753+
37754+ wkq_err = au_wkq_wait(call_xino_fread, &args);
37755+ if (unlikely(wkq_err))
37756+ err = wkq_err;
37757+
37758+ return err;
37759+}
37760+
37761+static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf,
37762+ size_t size, loff_t *pos);
37763+
37764+static ssize_t do_xino_fwrite(vfs_writef_t func, struct file *file, void *kbuf,
37765+ size_t size, loff_t *pos)
37766+{
37767+ ssize_t err;
37768+ mm_segment_t oldfs;
37769+ union {
37770+ void *k;
37771+ const char __user *u;
37772+ } buf;
37773+ int i;
37774+ const int prevent_endless = 10;
37775+
37776+ i = 0;
37777+ buf.k = kbuf;
37778+ oldfs = get_fs();
37779+ set_fs(KERNEL_DS);
37780+ do {
37781+ err = func(file, buf.u, size, pos);
37782+ if (err == -EINTR
37783+ && !au_wkq_test()
37784+ && fatal_signal_pending(current)) {
37785+ set_fs(oldfs);
37786+ err = xino_fwrite_wkq(func, file, kbuf, size, pos);
37787+ BUG_ON(err == -EINTR);
37788+ oldfs = get_fs();
37789+ set_fs(KERNEL_DS);
37790+ }
37791+ } while (i++ < prevent_endless
37792+ && (err == -EAGAIN || err == -EINTR));
37793+ set_fs(oldfs);
37794+
37795+#if 0 /* reserved for future use */
37796+ if (err > 0)
37797+ fsnotify_modify(file->f_path.dentry);
37798+#endif
37799+
37800+ return err;
37801+}
37802+
37803+struct do_xino_fwrite_args {
37804+ ssize_t *errp;
37805+ vfs_writef_t func;
37806+ struct file *file;
37807+ void *buf;
37808+ size_t size;
37809+ loff_t *pos;
37810+};
37811+
37812+static void call_do_xino_fwrite(void *args)
37813+{
37814+ struct do_xino_fwrite_args *a = args;
37815+ *a->errp = do_xino_fwrite(a->func, a->file, a->buf, a->size, a->pos);
37816+}
37817+
37818+static ssize_t xino_fwrite_wkq(vfs_writef_t func, struct file *file, void *buf,
37819+ size_t size, loff_t *pos)
37820+{
37821+ ssize_t err;
37822+ int wkq_err;
37823+ struct do_xino_fwrite_args args = {
37824+ .errp = &err,
37825+ .func = func,
37826+ .file = file,
37827+ .buf = buf,
37828+ .size = size,
37829+ .pos = pos
37830+ };
37831+
37832+ /*
37833+ * it breaks RLIMIT_FSIZE and normal user's limit,
37834+ * users should care about quota and real 'filesystem full.'
37835+ */
37836+ wkq_err = au_wkq_wait(call_do_xino_fwrite, &args);
37837+ if (unlikely(wkq_err))
37838+ err = wkq_err;
37839+
37840+ return err;
37841+}
37842+
37843+ssize_t xino_fwrite(vfs_writef_t func, struct file *file, void *buf,
37844+ size_t size, loff_t *pos)
37845+{
37846+ ssize_t err;
37847+
37848+ if (rlimit(RLIMIT_FSIZE) == RLIM_INFINITY) {
37849+ lockdep_off();
37850+ err = do_xino_fwrite(func, file, buf, size, pos);
37851+ lockdep_on();
37852+ } else {
37853+ lockdep_off();
37854+ err = xino_fwrite_wkq(func, file, buf, size, pos);
37855+ lockdep_on();
37856+ }
37857+
37858+ return err;
37859+}
37860+
37861+/* ---------------------------------------------------------------------- */
37862+
37863+/*
37864+ * inode number bitmap
37865+ */
1facf9fc 37866+static const int page_bits = (int)PAGE_SIZE * BITS_PER_BYTE;
37867+static ino_t xib_calc_ino(unsigned long pindex, int bit)
37868+{
37869+ ino_t ino;
37870+
37871+ AuDebugOn(bit < 0 || page_bits <= bit);
37872+ ino = AUFS_FIRST_INO + pindex * page_bits + bit;
37873+ return ino;
37874+}
37875+
37876+static void xib_calc_bit(ino_t ino, unsigned long *pindex, int *bit)
37877+{
37878+ AuDebugOn(ino < AUFS_FIRST_INO);
37879+ ino -= AUFS_FIRST_INO;
37880+ *pindex = ino / page_bits;
37881+ *bit = ino % page_bits;
37882+}
37883+
37884+static int xib_pindex(struct super_block *sb, unsigned long pindex)
37885+{
37886+ int err;
37887+ loff_t pos;
37888+ ssize_t sz;
37889+ struct au_sbinfo *sbinfo;
37890+ struct file *xib;
37891+ unsigned long *p;
37892+
37893+ sbinfo = au_sbi(sb);
37894+ MtxMustLock(&sbinfo->si_xib_mtx);
37895+ AuDebugOn(pindex > ULONG_MAX / PAGE_SIZE
37896+ || !au_opt_test(sbinfo->si_mntflags, XINO));
37897+
37898+ if (pindex == sbinfo->si_xib_last_pindex)
37899+ return 0;
37900+
37901+ xib = sbinfo->si_xib;
37902+ p = sbinfo->si_xib_buf;
37903+ pos = sbinfo->si_xib_last_pindex;
37904+ pos *= PAGE_SIZE;
37905+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
37906+ if (unlikely(sz != PAGE_SIZE))
37907+ goto out;
37908+
37909+ pos = pindex;
37910+ pos *= PAGE_SIZE;
c06a8ce3 37911+ if (vfsub_f_size_read(xib) >= pos + PAGE_SIZE)
1facf9fc 37912+ sz = xino_fread(sbinfo->si_xread, xib, p, PAGE_SIZE, &pos);
37913+ else {
37914+ memset(p, 0, PAGE_SIZE);
37915+ sz = xino_fwrite(sbinfo->si_xwrite, xib, p, PAGE_SIZE, &pos);
37916+ }
37917+ if (sz == PAGE_SIZE) {
37918+ sbinfo->si_xib_last_pindex = pindex;
37919+ return 0; /* success */
37920+ }
37921+
4f0767ce 37922+out:
b752ccd1
AM
37923+ AuIOErr1("write failed (%zd)\n", sz);
37924+ err = sz;
37925+ if (sz >= 0)
37926+ err = -EIO;
37927+ return err;
37928+}
37929+
b752ccd1
AM
37930+static void au_xib_clear_bit(struct inode *inode)
37931+{
37932+ int err, bit;
37933+ unsigned long pindex;
37934+ struct super_block *sb;
37935+ struct au_sbinfo *sbinfo;
37936+
37937+ AuDebugOn(inode->i_nlink);
37938+
37939+ sb = inode->i_sb;
37940+ xib_calc_bit(inode->i_ino, &pindex, &bit);
37941+ AuDebugOn(page_bits <= bit);
37942+ sbinfo = au_sbi(sb);
37943+ mutex_lock(&sbinfo->si_xib_mtx);
37944+ err = xib_pindex(sb, pindex);
37945+ if (!err) {
37946+ clear_bit(bit, sbinfo->si_xib_buf);
37947+ sbinfo->si_xib_next_bit = bit;
37948+ }
37949+ mutex_unlock(&sbinfo->si_xib_mtx);
37950+}
37951+
1facf9fc 37952+/* ---------------------------------------------------------------------- */
37953+
1facf9fc 37954+/*
062440b3 37955+ * truncate a xino bitmap file
1facf9fc 37956+ */
1facf9fc 37957+
37958+/* todo: slow */
37959+static int do_xib_restore(struct super_block *sb, struct file *file, void *page)
37960+{
37961+ int err, bit;
37962+ ssize_t sz;
37963+ unsigned long pindex;
37964+ loff_t pos, pend;
37965+ struct au_sbinfo *sbinfo;
5527c038 37966+ vfs_readf_t func;
1facf9fc 37967+ ino_t *ino;
37968+ unsigned long *p;
37969+
37970+ err = 0;
37971+ sbinfo = au_sbi(sb);
dece6358 37972+ MtxMustLock(&sbinfo->si_xib_mtx);
1facf9fc 37973+ p = sbinfo->si_xib_buf;
37974+ func = sbinfo->si_xread;
c06a8ce3 37975+ pend = vfsub_f_size_read(file);
1facf9fc 37976+ pos = 0;
37977+ while (pos < pend) {
37978+ sz = xino_fread(func, file, page, PAGE_SIZE, &pos);
37979+ err = sz;
37980+ if (unlikely(sz <= 0))
37981+ goto out;
37982+
37983+ err = 0;
37984+ for (ino = page; sz > 0; ino++, sz -= sizeof(ino)) {
37985+ if (unlikely(*ino < AUFS_FIRST_INO))
37986+ continue;
37987+
37988+ xib_calc_bit(*ino, &pindex, &bit);
37989+ AuDebugOn(page_bits <= bit);
37990+ err = xib_pindex(sb, pindex);
37991+ if (!err)
37992+ set_bit(bit, p);
37993+ else
37994+ goto out;
37995+ }
37996+ }
37997+
4f0767ce 37998+out:
1facf9fc 37999+ return err;
38000+}
38001+
38002+static int xib_restore(struct super_block *sb)
38003+{
acd2b654
AM
38004+ int err, i;
38005+ unsigned int nfile;
5afbbe0d 38006+ aufs_bindex_t bindex, bbot;
1facf9fc 38007+ void *page;
062440b3 38008+ struct au_branch *br;
acd2b654
AM
38009+ struct au_xino *xi;
38010+ struct file *file;
1facf9fc 38011+
38012+ err = -ENOMEM;
38013+ page = (void *)__get_free_page(GFP_NOFS);
38014+ if (unlikely(!page))
38015+ goto out;
38016+
38017+ err = 0;
5afbbe0d
AM
38018+ bbot = au_sbbot(sb);
38019+ for (bindex = 0; !err && bindex <= bbot; bindex++)
062440b3
AM
38020+ if (!bindex || is_sb_shared(sb, bindex, bindex - 1) < 0) {
38021+ br = au_sbr(sb, bindex);
acd2b654
AM
38022+ xi = br->br_xino;
38023+ nfile = xi->xi_nfile;
38024+ for (i = 0; i < nfile; i++) {
38025+ file = au_xino_file(xi, i);
38026+ if (file)
38027+ err = do_xib_restore(sb, file, page);
38028+ }
062440b3
AM
38029+ } else
38030+ AuDbg("skip shared b%d\n", bindex);
1c60b727 38031+ free_page((unsigned long)page);
1facf9fc 38032+
4f0767ce 38033+out:
1facf9fc 38034+ return err;
38035+}
38036+
38037+int au_xib_trunc(struct super_block *sb)
38038+{
38039+ int err;
38040+ ssize_t sz;
38041+ loff_t pos;
1facf9fc 38042+ struct au_sbinfo *sbinfo;
38043+ unsigned long *p;
38044+ struct file *file;
38045+
dece6358
AM
38046+ SiMustWriteLock(sb);
38047+
1facf9fc 38048+ err = 0;
38049+ sbinfo = au_sbi(sb);
38050+ if (!au_opt_test(sbinfo->si_mntflags, XINO))
38051+ goto out;
38052+
38053+ file = sbinfo->si_xib;
c06a8ce3 38054+ if (vfsub_f_size_read(file) <= PAGE_SIZE)
1facf9fc 38055+ goto out;
38056+
062440b3 38057+ file = au_xino_create2(sb, &sbinfo->si_xib->f_path, NULL);
1facf9fc 38058+ err = PTR_ERR(file);
38059+ if (IS_ERR(file))
38060+ goto out;
38061+ fput(sbinfo->si_xib);
38062+ sbinfo->si_xib = file;
38063+
38064+ p = sbinfo->si_xib_buf;
38065+ memset(p, 0, PAGE_SIZE);
38066+ pos = 0;
38067+ sz = xino_fwrite(sbinfo->si_xwrite, sbinfo->si_xib, p, PAGE_SIZE, &pos);
38068+ if (unlikely(sz != PAGE_SIZE)) {
38069+ err = sz;
38070+ AuIOErr("err %d\n", err);
38071+ if (sz >= 0)
38072+ err = -EIO;
38073+ goto out;
38074+ }
38075+
38076+ mutex_lock(&sbinfo->si_xib_mtx);
38077+ /* mnt_want_write() is unnecessary here */
38078+ err = xib_restore(sb);
38079+ mutex_unlock(&sbinfo->si_xib_mtx);
38080+
38081+out:
38082+ return err;
38083+}
38084+
38085+/* ---------------------------------------------------------------------- */
38086+
acd2b654 38087+struct au_xino *au_xino_alloc(unsigned int nfile)
062440b3
AM
38088+{
38089+ struct au_xino *xi;
38090+
38091+ xi = kzalloc(sizeof(*xi), GFP_NOFS);
38092+ if (unlikely(!xi))
38093+ goto out;
acd2b654
AM
38094+ xi->xi_nfile = nfile;
38095+ xi->xi_file = kcalloc(nfile, sizeof(*xi->xi_file), GFP_NOFS);
38096+ if (unlikely(!xi->xi_file))
38097+ goto out_free;
062440b3
AM
38098+
38099+ xi->xi_nondir.total = 8; /* initial size */
38100+ xi->xi_nondir.array = kcalloc(xi->xi_nondir.total, sizeof(ino_t),
38101+ GFP_NOFS);
38102+ if (unlikely(!xi->xi_nondir.array))
acd2b654 38103+ goto out_file;
062440b3
AM
38104+
38105+ spin_lock_init(&xi->xi_nondir.spin);
38106+ init_waitqueue_head(&xi->xi_nondir.wqh);
acd2b654 38107+ mutex_init(&xi->xi_mtx);
9f237c51 38108+ INIT_HLIST_BL_HEAD(&xi->xi_writing);
062440b3
AM
38109+ atomic_set(&xi->xi_truncating, 0);
38110+ kref_init(&xi->xi_kref);
38111+ goto out; /* success */
38112+
acd2b654 38113+out_file:
9f237c51 38114+ au_kfree_try_rcu(xi->xi_file);
062440b3 38115+out_free:
9f237c51 38116+ au_kfree_rcu(xi);
062440b3
AM
38117+ xi = NULL;
38118+out:
38119+ return xi;
38120+}
38121+
acd2b654 38122+static int au_xino_init(struct au_branch *br, int idx, struct file *file)
062440b3
AM
38123+{
38124+ int err;
38125+ struct au_xino *xi;
38126+
38127+ err = 0;
acd2b654 38128+ xi = au_xino_alloc(idx + 1);
062440b3
AM
38129+ if (unlikely(!xi)) {
38130+ err = -ENOMEM;
38131+ goto out;
38132+ }
38133+
acd2b654
AM
38134+ if (file)
38135+ get_file(file);
38136+ xi->xi_file[idx] = file;
062440b3
AM
38137+ AuDebugOn(br->br_xino);
38138+ br->br_xino = xi;
38139+
38140+out:
38141+ return err;
38142+}
38143+
38144+static void au_xino_release(struct kref *kref)
38145+{
38146+ struct au_xino *xi;
38147+ int i;
9f237c51
AM
38148+ unsigned long ul;
38149+ struct hlist_bl_head *hbl;
38150+ struct hlist_bl_node *pos, *n;
38151+ struct au_xi_writing *p;
062440b3
AM
38152+
38153+ xi = container_of(kref, struct au_xino, xi_kref);
acd2b654
AM
38154+ for (i = 0; i < xi->xi_nfile; i++)
38155+ if (xi->xi_file[i])
38156+ fput(xi->xi_file[i]);
062440b3
AM
38157+ for (i = xi->xi_nondir.total - 1; i >= 0; i--)
38158+ AuDebugOn(xi->xi_nondir.array[i]);
acd2b654 38159+ mutex_destroy(&xi->xi_mtx);
9f237c51
AM
38160+ hbl = &xi->xi_writing;
38161+ ul = au_hbl_count(hbl);
38162+ if (unlikely(ul)) {
38163+ pr_warn("xi_writing %lu\n", ul);
38164+ hlist_bl_lock(hbl);
43982f53 38165+ hlist_bl_for_each_entry_safe(p, pos, n, hbl, node) {
9f237c51 38166+ hlist_bl_del(&p->node);
016522bc
AM
38167+ /* kmemleak reported au_kfree_rcu() doesn't free it */
38168+ kfree(p);
9f237c51
AM
38169+ }
38170+ hlist_bl_unlock(hbl);
38171+ }
38172+ au_kfree_try_rcu(xi->xi_file);
38173+ au_kfree_try_rcu(xi->xi_nondir.array);
38174+ au_kfree_rcu(xi);
062440b3
AM
38175+}
38176+
38177+int au_xino_put(struct au_branch *br)
38178+{
38179+ int ret;
38180+ struct au_xino *xi;
38181+
38182+ ret = 0;
38183+ xi = br->br_xino;
38184+ if (xi) {
38185+ br->br_xino = NULL;
38186+ ret = kref_put(&xi->xi_kref, au_xino_release);
38187+ }
38188+
38189+ return ret;
38190+}
38191+
062440b3
AM
38192+/* ---------------------------------------------------------------------- */
38193+
1facf9fc 38194+/*
38195+ * xino mount option handlers
38196+ */
1facf9fc 38197+
38198+/* xino bitmap */
38199+static void xino_clear_xib(struct super_block *sb)
38200+{
38201+ struct au_sbinfo *sbinfo;
38202+
dece6358
AM
38203+ SiMustWriteLock(sb);
38204+
1facf9fc 38205+ sbinfo = au_sbi(sb);
062440b3 38206+ /* unnecessary to clear sbinfo->si_xread and ->si_xwrite */
1facf9fc 38207+ if (sbinfo->si_xib)
38208+ fput(sbinfo->si_xib);
38209+ sbinfo->si_xib = NULL;
f0c0a007 38210+ if (sbinfo->si_xib_buf)
1c60b727 38211+ free_page((unsigned long)sbinfo->si_xib_buf);
1facf9fc 38212+ sbinfo->si_xib_buf = NULL;
38213+}
38214+
062440b3 38215+static int au_xino_set_xib(struct super_block *sb, struct path *path)
1facf9fc 38216+{
38217+ int err;
38218+ loff_t pos;
38219+ struct au_sbinfo *sbinfo;
38220+ struct file *file;
acd2b654 38221+ struct super_block *xi_sb;
1facf9fc 38222+
dece6358
AM
38223+ SiMustWriteLock(sb);
38224+
1facf9fc 38225+ sbinfo = au_sbi(sb);
062440b3 38226+ file = au_xino_create2(sb, path, sbinfo->si_xib);
1facf9fc 38227+ err = PTR_ERR(file);
38228+ if (IS_ERR(file))
38229+ goto out;
38230+ if (sbinfo->si_xib)
38231+ fput(sbinfo->si_xib);
38232+ sbinfo->si_xib = file;
5527c038
JR
38233+ sbinfo->si_xread = vfs_readf(file);
38234+ sbinfo->si_xwrite = vfs_writef(file);
acd2b654
AM
38235+ xi_sb = file_inode(file)->i_sb;
38236+ sbinfo->si_ximaxent = xi_sb->s_maxbytes;
38237+ if (unlikely(sbinfo->si_ximaxent < PAGE_SIZE)) {
38238+ err = -EIO;
38239+ pr_err("s_maxbytes(%llu) on %s is too small\n",
38240+ (u64)sbinfo->si_ximaxent, au_sbtype(xi_sb));
38241+ goto out_unset;
38242+ }
38243+ sbinfo->si_ximaxent /= sizeof(ino_t);
1facf9fc 38244+
38245+ err = -ENOMEM;
38246+ if (!sbinfo->si_xib_buf)
38247+ sbinfo->si_xib_buf = (void *)get_zeroed_page(GFP_NOFS);
38248+ if (unlikely(!sbinfo->si_xib_buf))
38249+ goto out_unset;
38250+
38251+ sbinfo->si_xib_last_pindex = 0;
38252+ sbinfo->si_xib_next_bit = 0;
c06a8ce3 38253+ if (vfsub_f_size_read(file) < PAGE_SIZE) {
1facf9fc 38254+ pos = 0;
38255+ err = xino_fwrite(sbinfo->si_xwrite, file, sbinfo->si_xib_buf,
38256+ PAGE_SIZE, &pos);
38257+ if (unlikely(err != PAGE_SIZE))
38258+ goto out_free;
38259+ }
38260+ err = 0;
38261+ goto out; /* success */
38262+
4f0767ce 38263+out_free:
f0c0a007 38264+ if (sbinfo->si_xib_buf)
1c60b727 38265+ free_page((unsigned long)sbinfo->si_xib_buf);
b752ccd1
AM
38266+ sbinfo->si_xib_buf = NULL;
38267+ if (err >= 0)
38268+ err = -EIO;
4f0767ce 38269+out_unset:
b752ccd1
AM
38270+ fput(sbinfo->si_xib);
38271+ sbinfo->si_xib = NULL;
4f0767ce 38272+out:
062440b3 38273+ AuTraceErr(err);
b752ccd1 38274+ return err;
1facf9fc 38275+}
38276+
b752ccd1
AM
38277+/* xino for each branch */
38278+static void xino_clear_br(struct super_block *sb)
38279+{
5afbbe0d 38280+ aufs_bindex_t bindex, bbot;
b752ccd1 38281+ struct au_branch *br;
1facf9fc 38282+
5afbbe0d
AM
38283+ bbot = au_sbbot(sb);
38284+ for (bindex = 0; bindex <= bbot; bindex++) {
b752ccd1 38285+ br = au_sbr(sb, bindex);
062440b3
AM
38286+ AuDebugOn(!br);
38287+ au_xino_put(br);
38288+ }
38289+}
38290+
38291+static void au_xino_set_br_shared(struct super_block *sb, struct au_branch *br,
38292+ aufs_bindex_t bshared)
38293+{
38294+ struct au_branch *brshared;
b752ccd1 38295+
062440b3
AM
38296+ brshared = au_sbr(sb, bshared);
38297+ AuDebugOn(!brshared->br_xino);
38298+ AuDebugOn(!brshared->br_xino->xi_file);
38299+ if (br->br_xino != brshared->br_xino) {
38300+ au_xino_get(brshared);
38301+ au_xino_put(br);
38302+ br->br_xino = brshared->br_xino;
b752ccd1
AM
38303+ }
38304+}
38305+
062440b3
AM
38306+struct au_xino_do_set_br {
38307+ vfs_writef_t writef;
38308+ struct au_branch *br;
38309+ ino_t h_ino;
38310+ aufs_bindex_t bshared;
38311+};
38312+
38313+static int au_xino_do_set_br(struct super_block *sb, struct path *path,
38314+ struct au_xino_do_set_br *args)
1facf9fc 38315+{
38316+ int err;
acd2b654 38317+ struct au_xi_calc calc;
062440b3 38318+ struct file *file;
acd2b654
AM
38319+ struct au_branch *br;
38320+ struct au_xi_new xinew = {
38321+ .base = path
38322+ };
062440b3 38323+
acd2b654
AM
38324+ br = args->br;
38325+ xinew.xi = br->br_xino;
38326+ au_xi_calc(sb, args->h_ino, &calc);
38327+ xinew.copy_src = au_xino_file(xinew.xi, calc.idx);
38328+ if (args->bshared >= 0)
062440b3 38329+ /* shared xino */
acd2b654
AM
38330+ au_xino_set_br_shared(sb, br, args->bshared);
38331+ else if (!xinew.xi) {
38332+ /* new xino */
38333+ err = au_xino_init(br, calc.idx, xinew.copy_src);
38334+ if (unlikely(err))
38335+ goto out;
062440b3
AM
38336+ }
38337+
acd2b654
AM
38338+ /* force re-creating */
38339+ xinew.xi = br->br_xino;
38340+ xinew.idx = calc.idx;
38341+ mutex_lock(&xinew.xi->xi_mtx);
38342+ file = au_xi_new(sb, &xinew);
38343+ mutex_unlock(&xinew.xi->xi_mtx);
062440b3
AM
38344+ err = PTR_ERR(file);
38345+ if (IS_ERR(file))
38346+ goto out;
acd2b654
AM
38347+ AuDebugOn(!file);
38348+
38349+ err = au_xino_do_write(args->writef, file, &calc, AUFS_ROOT_INO);
38350+ if (unlikely(err))
38351+ au_xino_put(br);
062440b3 38352+
062440b3
AM
38353+out:
38354+ AuTraceErr(err);
38355+ return err;
38356+}
38357+
38358+static int au_xino_set_br(struct super_block *sb, struct path *path)
38359+{
38360+ int err;
38361+ aufs_bindex_t bindex, bbot;
38362+ struct au_xino_do_set_br args;
b752ccd1 38363+ struct inode *inode;
1facf9fc 38364+
b752ccd1
AM
38365+ SiMustWriteLock(sb);
38366+
5afbbe0d 38367+ bbot = au_sbbot(sb);
5527c038 38368+ inode = d_inode(sb->s_root);
062440b3
AM
38369+ args.writef = au_sbi(sb)->si_xwrite;
38370+ for (bindex = 0; bindex <= bbot; bindex++) {
38371+ args.h_ino = au_h_iptr(inode, bindex)->i_ino;
38372+ args.br = au_sbr(sb, bindex);
38373+ args.bshared = is_sb_shared(sb, bindex, bindex - 1);
38374+ err = au_xino_do_set_br(sb, path, &args);
b752ccd1 38375+ if (unlikely(err))
062440b3 38376+ break;
b752ccd1 38377+ }
1facf9fc 38378+
062440b3 38379+ AuTraceErr(err);
1facf9fc 38380+ return err;
38381+}
b752ccd1
AM
38382+
38383+void au_xino_clr(struct super_block *sb)
38384+{
38385+ struct au_sbinfo *sbinfo;
38386+
38387+ au_xigen_clr(sb);
38388+ xino_clear_xib(sb);
38389+ xino_clear_br(sb);
062440b3 38390+ dbgaufs_brs_del(sb, 0);
b752ccd1
AM
38391+ sbinfo = au_sbi(sb);
38392+ /* lvalue, do not call au_mntflags() */
38393+ au_opt_clr(sbinfo->si_mntflags, XINO);
38394+}
38395+
062440b3 38396+int au_xino_set(struct super_block *sb, struct au_opt_xino *xiopt, int remount)
b752ccd1
AM
38397+{
38398+ int err, skip;
062440b3 38399+ struct dentry *dentry, *parent, *cur_dentry, *cur_parent;
b752ccd1
AM
38400+ struct qstr *dname, *cur_name;
38401+ struct file *cur_xino;
b752ccd1 38402+ struct au_sbinfo *sbinfo;
062440b3 38403+ struct path *path, *cur_path;
b752ccd1
AM
38404+
38405+ SiMustWriteLock(sb);
38406+
38407+ err = 0;
38408+ sbinfo = au_sbi(sb);
062440b3
AM
38409+ path = &xiopt->file->f_path;
38410+ dentry = path->dentry;
38411+ parent = dget_parent(dentry);
b752ccd1
AM
38412+ if (remount) {
38413+ skip = 0;
b752ccd1
AM
38414+ cur_xino = sbinfo->si_xib;
38415+ if (cur_xino) {
062440b3
AM
38416+ cur_path = &cur_xino->f_path;
38417+ cur_dentry = cur_path->dentry;
38418+ cur_parent = dget_parent(cur_dentry);
38419+ cur_name = &cur_dentry->d_name;
38420+ dname = &dentry->d_name;
b752ccd1 38421+ skip = (cur_parent == parent
38d290e6 38422+ && au_qstreq(dname, cur_name));
b752ccd1
AM
38423+ dput(cur_parent);
38424+ }
38425+ if (skip)
38426+ goto out;
38427+ }
38428+
38429+ au_opt_set(sbinfo->si_mntflags, XINO);
062440b3
AM
38430+ err = au_xino_set_xib(sb, path);
38431+ /* si_x{read,write} are set */
b752ccd1 38432+ if (!err)
062440b3 38433+ err = au_xigen_set(sb, path);
b752ccd1 38434+ if (!err)
062440b3
AM
38435+ err = au_xino_set_br(sb, path);
38436+ if (!err) {
38437+ dbgaufs_brs_add(sb, 0, /*topdown*/1);
b752ccd1 38438+ goto out; /* success */
062440b3 38439+ }
b752ccd1
AM
38440+
38441+ /* reset all */
062440b3
AM
38442+ AuIOErr("failed setting xino(%d).\n", err);
38443+ au_xino_clr(sb);
b752ccd1 38444+
4f0767ce 38445+out:
b752ccd1
AM
38446+ dput(parent);
38447+ return err;
38448+}
38449+
b752ccd1
AM
38450+/*
38451+ * create a xinofile at the default place/path.
38452+ */
38453+struct file *au_xino_def(struct super_block *sb)
38454+{
38455+ struct file *file;
38456+ char *page, *p;
38457+ struct au_branch *br;
38458+ struct super_block *h_sb;
38459+ struct path path;
5afbbe0d 38460+ aufs_bindex_t bbot, bindex, bwr;
b752ccd1
AM
38461+
38462+ br = NULL;
5afbbe0d 38463+ bbot = au_sbbot(sb);
b752ccd1 38464+ bwr = -1;
5afbbe0d 38465+ for (bindex = 0; bindex <= bbot; bindex++) {
b752ccd1
AM
38466+ br = au_sbr(sb, bindex);
38467+ if (au_br_writable(br->br_perm)
86dc4139 38468+ && !au_test_fs_bad_xino(au_br_sb(br))) {
b752ccd1
AM
38469+ bwr = bindex;
38470+ break;
38471+ }
38472+ }
38473+
7f207e10
AM
38474+ if (bwr >= 0) {
38475+ file = ERR_PTR(-ENOMEM);
537831f9 38476+ page = (void *)__get_free_page(GFP_NOFS);
7f207e10
AM
38477+ if (unlikely(!page))
38478+ goto out;
86dc4139 38479+ path.mnt = au_br_mnt(br);
7f207e10
AM
38480+ path.dentry = au_h_dptr(sb->s_root, bwr);
38481+ p = d_path(&path, page, PATH_MAX - sizeof(AUFS_XINO_FNAME));
38482+ file = (void *)p;
38483+ if (!IS_ERR(p)) {
38484+ strcat(p, "/" AUFS_XINO_FNAME);
38485+ AuDbg("%s\n", p);
83b672a5 38486+ file = au_xino_create(sb, p, /*silent*/0, /*wbrtop*/1);
7f207e10 38487+ }
1c60b727 38488+ free_page((unsigned long)page);
7f207e10 38489+ } else {
83b672a5
AM
38490+ file = au_xino_create(sb, AUFS_XINO_DEFPATH, /*silent*/0,
38491+ /*wbrtop*/0);
7f207e10
AM
38492+ if (IS_ERR(file))
38493+ goto out;
2000de60 38494+ h_sb = file->f_path.dentry->d_sb;
7f207e10
AM
38495+ if (unlikely(au_test_fs_bad_xino(h_sb))) {
38496+ pr_err("xino doesn't support %s(%s)\n",
38497+ AUFS_XINO_DEFPATH, au_sbtype(h_sb));
38498+ fput(file);
38499+ file = ERR_PTR(-EINVAL);
38500+ }
7f207e10 38501+ }
0c5527e5 38502+
7f207e10
AM
38503+out:
38504+ return file;
38505+}
38506+
38507+/* ---------------------------------------------------------------------- */
38508+
062440b3
AM
38509+/*
38510+ * initialize the xinofile for the specified branch @br
38511+ * at the place/path where @base_file indicates.
38512+ * test whether another branch is on the same filesystem or not,
38513+ * if found then share the xinofile with another branch.
38514+ */
38515+int au_xino_init_br(struct super_block *sb, struct au_branch *br, ino_t h_ino,
38516+ struct path *base)
7f207e10
AM
38517+{
38518+ int err;
062440b3
AM
38519+ struct au_xino_do_set_br args = {
38520+ .h_ino = h_ino,
38521+ .br = br
38522+ };
7f207e10 38523+
062440b3
AM
38524+ args.writef = au_sbi(sb)->si_xwrite;
38525+ args.bshared = sbr_find_shared(sb, /*btop*/0, au_sbbot(sb),
38526+ au_br_sb(br));
38527+ err = au_xino_do_set_br(sb, base, &args);
79b8bda9 38528+ if (unlikely(err))
062440b3 38529+ au_xino_put(br);
7f207e10 38530+
7f207e10
AM
38531+ return err;
38532+}
521ced18
JR
38533+
38534+/* ---------------------------------------------------------------------- */
38535+
062440b3
AM
38536+/*
38537+ * get an unused inode number from bitmap
38538+ */
38539+ino_t au_xino_new_ino(struct super_block *sb)
38540+{
38541+ ino_t ino;
38542+ unsigned long *p, pindex, ul, pend;
38543+ struct au_sbinfo *sbinfo;
38544+ struct file *file;
38545+ int free_bit, err;
38546+
38547+ if (!au_opt_test(au_mntflags(sb), XINO))
38548+ return iunique(sb, AUFS_FIRST_INO);
38549+
38550+ sbinfo = au_sbi(sb);
38551+ mutex_lock(&sbinfo->si_xib_mtx);
38552+ p = sbinfo->si_xib_buf;
38553+ free_bit = sbinfo->si_xib_next_bit;
38554+ if (free_bit < page_bits && !test_bit(free_bit, p))
38555+ goto out; /* success */
38556+ free_bit = find_first_zero_bit(p, page_bits);
38557+ if (free_bit < page_bits)
38558+ goto out; /* success */
38559+
38560+ pindex = sbinfo->si_xib_last_pindex;
38561+ for (ul = pindex - 1; ul < ULONG_MAX; ul--) {
38562+ err = xib_pindex(sb, ul);
38563+ if (unlikely(err))
38564+ goto out_err;
38565+ free_bit = find_first_zero_bit(p, page_bits);
38566+ if (free_bit < page_bits)
38567+ goto out; /* success */
38568+ }
38569+
38570+ file = sbinfo->si_xib;
38571+ pend = vfsub_f_size_read(file) / PAGE_SIZE;
38572+ for (ul = pindex + 1; ul <= pend; ul++) {
38573+ err = xib_pindex(sb, ul);
38574+ if (unlikely(err))
38575+ goto out_err;
38576+ free_bit = find_first_zero_bit(p, page_bits);
38577+ if (free_bit < page_bits)
38578+ goto out; /* success */
38579+ }
38580+ BUG();
38581+
38582+out:
38583+ set_bit(free_bit, p);
38584+ sbinfo->si_xib_next_bit = free_bit + 1;
38585+ pindex = sbinfo->si_xib_last_pindex;
38586+ mutex_unlock(&sbinfo->si_xib_mtx);
38587+ ino = xib_calc_ino(pindex, free_bit);
38588+ AuDbg("i%lu\n", (unsigned long)ino);
38589+ return ino;
38590+out_err:
38591+ mutex_unlock(&sbinfo->si_xib_mtx);
38592+ AuDbg("i0\n");
38593+ return 0;
38594+}
38595+
38596+/* for s_op->delete_inode() */
38597+void au_xino_delete_inode(struct inode *inode, const int unlinked)
521ced18 38598+{
062440b3
AM
38599+ int err;
38600+ unsigned int mnt_flags;
38601+ aufs_bindex_t bindex, bbot, bi;
38602+ unsigned char try_trunc;
38603+ struct au_iinfo *iinfo;
38604+ struct super_block *sb;
38605+ struct au_hinode *hi;
38606+ struct inode *h_inode;
38607+ struct au_branch *br;
38608+ vfs_writef_t xwrite;
acd2b654
AM
38609+ struct au_xi_calc calc;
38610+ struct file *file;
521ced18 38611+
062440b3 38612+ AuDebugOn(au_is_bad_inode(inode));
521ced18 38613+
062440b3
AM
38614+ sb = inode->i_sb;
38615+ mnt_flags = au_mntflags(sb);
38616+ if (!au_opt_test(mnt_flags, XINO)
38617+ || inode->i_ino == AUFS_ROOT_INO)
38618+ return;
38619+
38620+ if (unlinked) {
38621+ au_xigen_inc(inode);
38622+ au_xib_clear_bit(inode);
38623+ }
38624+
38625+ iinfo = au_ii(inode);
38626+ bindex = iinfo->ii_btop;
38627+ if (bindex < 0)
38628+ return;
38629+
38630+ xwrite = au_sbi(sb)->si_xwrite;
38631+ try_trunc = !!au_opt_test(mnt_flags, TRUNC_XINO);
38632+ hi = au_hinode(iinfo, bindex);
38633+ bbot = iinfo->ii_bbot;
38634+ for (; bindex <= bbot; bindex++, hi++) {
38635+ h_inode = hi->hi_inode;
38636+ if (!h_inode
38637+ || (!unlinked && h_inode->i_nlink))
38638+ continue;
38639+
38640+ /* inode may not be revalidated */
38641+ bi = au_br_index(sb, hi->hi_id);
38642+ if (bi < 0)
38643+ continue;
38644+
38645+ br = au_sbr(sb, bi);
acd2b654
AM
38646+ au_xi_calc(sb, h_inode->i_ino, &calc);
38647+ file = au_xino_file(br->br_xino, calc.idx);
38648+ if (IS_ERR_OR_NULL(file))
38649+ continue;
38650+
38651+ err = au_xino_do_write(xwrite, file, &calc, /*ino*/0);
062440b3
AM
38652+ if (!err && try_trunc
38653+ && au_test_fs_trunc_xino(au_br_sb(br)))
38654+ xino_try_trunc(sb, br);
38655+ }
521ced18
JR
38656+}
38657+
062440b3
AM
38658+/* ---------------------------------------------------------------------- */
38659+
38660+static int au_xinondir_find(struct au_xino *xi, ino_t h_ino)
521ced18
JR
38661+{
38662+ int found, total, i;
38663+
38664+ found = -1;
062440b3 38665+ total = xi->xi_nondir.total;
521ced18 38666+ for (i = 0; i < total; i++) {
062440b3 38667+ if (xi->xi_nondir.array[i] != h_ino)
521ced18
JR
38668+ continue;
38669+ found = i;
38670+ break;
38671+ }
38672+
38673+ return found;
38674+}
38675+
062440b3 38676+static int au_xinondir_expand(struct au_xino *xi)
521ced18
JR
38677+{
38678+ int err, sz;
38679+ ino_t *p;
38680+
38681+ BUILD_BUG_ON(KMALLOC_MAX_SIZE > INT_MAX);
38682+
38683+ err = -ENOMEM;
062440b3 38684+ sz = xi->xi_nondir.total * sizeof(ino_t);
521ced18
JR
38685+ if (unlikely(sz > KMALLOC_MAX_SIZE / 2))
38686+ goto out;
062440b3 38687+ p = au_kzrealloc(xi->xi_nondir.array, sz, sz << 1, GFP_ATOMIC,
521ced18
JR
38688+ /*may_shrink*/0);
38689+ if (p) {
062440b3
AM
38690+ xi->xi_nondir.array = p;
38691+ xi->xi_nondir.total <<= 1;
38692+ AuDbg("xi_nondir.total %d\n", xi->xi_nondir.total);
521ced18
JR
38693+ err = 0;
38694+ }
38695+
38696+out:
38697+ return err;
38698+}
38699+
062440b3
AM
38700+void au_xinondir_leave(struct super_block *sb, aufs_bindex_t bindex,
38701+ ino_t h_ino, int idx)
38702+{
38703+ struct au_xino *xi;
38704+
38705+ AuDebugOn(!au_opt_test(au_mntflags(sb), XINO));
38706+ xi = au_sbr(sb, bindex)->br_xino;
38707+ AuDebugOn(idx < 0 || xi->xi_nondir.total <= idx);
38708+
38709+ spin_lock(&xi->xi_nondir.spin);
38710+ AuDebugOn(xi->xi_nondir.array[idx] != h_ino);
38711+ xi->xi_nondir.array[idx] = 0;
38712+ spin_unlock(&xi->xi_nondir.spin);
38713+ wake_up_all(&xi->xi_nondir.wqh);
38714+}
38715+
521ced18
JR
38716+int au_xinondir_enter(struct super_block *sb, aufs_bindex_t bindex, ino_t h_ino,
38717+ int *idx)
38718+{
38719+ int err, found, empty;
062440b3 38720+ struct au_xino *xi;
521ced18
JR
38721+
38722+ err = 0;
38723+ *idx = -1;
38724+ if (!au_opt_test(au_mntflags(sb), XINO))
38725+ goto out; /* no xino */
38726+
062440b3 38727+ xi = au_sbr(sb, bindex)->br_xino;
521ced18
JR
38728+
38729+again:
062440b3
AM
38730+ spin_lock(&xi->xi_nondir.spin);
38731+ found = au_xinondir_find(xi, h_ino);
521ced18 38732+ if (found == -1) {
062440b3 38733+ empty = au_xinondir_find(xi, /*h_ino*/0);
521ced18 38734+ if (empty == -1) {
062440b3
AM
38735+ empty = xi->xi_nondir.total;
38736+ err = au_xinondir_expand(xi);
521ced18
JR
38737+ if (unlikely(err))
38738+ goto out_unlock;
38739+ }
062440b3 38740+ xi->xi_nondir.array[empty] = h_ino;
521ced18
JR
38741+ *idx = empty;
38742+ } else {
062440b3
AM
38743+ spin_unlock(&xi->xi_nondir.spin);
38744+ wait_event(xi->xi_nondir.wqh,
38745+ xi->xi_nondir.array[found] != h_ino);
521ced18
JR
38746+ goto again;
38747+ }
38748+
38749+out_unlock:
062440b3
AM
38750+ spin_unlock(&xi->xi_nondir.spin);
38751+out:
38752+ return err;
38753+}
38754+
38755+/* ---------------------------------------------------------------------- */
38756+
38757+int au_xino_path(struct seq_file *seq, struct file *file)
38758+{
38759+ int err;
38760+
38761+ err = au_seq_path(seq, &file->f_path);
38762+ if (unlikely(err))
38763+ goto out;
38764+
38765+#define Deleted "\\040(deleted)"
38766+ seq->count -= sizeof(Deleted) - 1;
38767+ AuDebugOn(memcmp(seq->buf + seq->count, Deleted,
38768+ sizeof(Deleted) - 1));
38769+#undef Deleted
38770+
521ced18
JR
38771+out:
38772+ return err;
38773+}
537831f9 38774diff -urN /usr/share/empty/include/uapi/linux/aufs_type.h linux/include/uapi/linux/aufs_type.h
eca34b5c 38775--- /usr/share/empty/include/uapi/linux/aufs_type.h 1970-01-01 01:00:00.000000000 +0100
016522bc 38776+++ linux/include/uapi/linux/aufs_type.h 2020-04-03 08:16:49.834195677 +0200
eca34b5c
AM
38777@@ -0,0 +1,452 @@
38778+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
7f207e10 38779+/*
016522bc 38780+ * Copyright (C) 2005-2020 Junjiro R. Okajima
7f207e10
AM
38781+ *
38782+ * This program, aufs is free software; you can redistribute it and/or modify
38783+ * it under the terms of the GNU General Public License as published by
38784+ * the Free Software Foundation; either version 2 of the License, or
38785+ * (at your option) any later version.
38786+ *
38787+ * This program is distributed in the hope that it will be useful,
38788+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
38789+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38790+ * GNU General Public License for more details.
38791+ *
38792+ * You should have received a copy of the GNU General Public License
523b37e3 38793+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
7f207e10
AM
38794+ */
38795+
38796+#ifndef __AUFS_TYPE_H__
38797+#define __AUFS_TYPE_H__
38798+
f6c5ef8b
AM
38799+#define AUFS_NAME "aufs"
38800+
9dbd164d 38801+#ifdef __KERNEL__
f6c5ef8b
AM
38802+/*
38803+ * define it before including all other headers.
38804+ * sched.h may use pr_* macros before defining "current", so define the
38805+ * no-current version first, and re-define later.
38806+ */
38807+#define pr_fmt(fmt) AUFS_NAME " %s:%d: " fmt, __func__, __LINE__
38808+#include <linux/sched.h>
38809+#undef pr_fmt
a2a7ad62
AM
38810+#define pr_fmt(fmt) \
38811+ AUFS_NAME " %s:%d:%.*s[%d]: " fmt, __func__, __LINE__, \
38812+ (int)sizeof(current->comm), current->comm, current->pid
43982f53 38813+#include <linux/limits.h>
9dbd164d
AM
38814+#else
38815+#include <stdint.h>
38816+#include <sys/types.h>
43982f53 38817+#include <limits.h>
f6c5ef8b 38818+#endif /* __KERNEL__ */
7f207e10 38819+
016522bc 38820+#define AUFS_VERSION "5.4-20200302"
7f207e10
AM
38821+
38822+/* todo? move this to linux-2.6.19/include/magic.h */
38823+#define AUFS_SUPER_MAGIC ('a' << 24 | 'u' << 16 | 'f' << 8 | 's')
38824+
38825+/* ---------------------------------------------------------------------- */
38826+
43982f53 38827+#ifdef __KERNEL__
7f207e10 38828+#ifdef CONFIG_AUFS_BRANCH_MAX_127
9dbd164d 38829+typedef int8_t aufs_bindex_t;
7f207e10
AM
38830+#define AUFS_BRANCH_MAX 127
38831+#else
9dbd164d 38832+typedef int16_t aufs_bindex_t;
7f207e10
AM
38833+#ifdef CONFIG_AUFS_BRANCH_MAX_511
38834+#define AUFS_BRANCH_MAX 511
38835+#elif defined(CONFIG_AUFS_BRANCH_MAX_1023)
38836+#define AUFS_BRANCH_MAX 1023
38837+#elif defined(CONFIG_AUFS_BRANCH_MAX_32767)
38838+#define AUFS_BRANCH_MAX 32767
38839+#endif
38840+#endif
38841+
7f207e10
AM
38842+#ifndef AUFS_BRANCH_MAX
38843+#error unknown CONFIG_AUFS_BRANCH_MAX value
38844+#endif
38845+#endif /* __KERNEL__ */
38846+
38847+/* ---------------------------------------------------------------------- */
38848+
7f207e10
AM
38849+#define AUFS_FSTYPE AUFS_NAME
38850+
38851+#define AUFS_ROOT_INO 2
38852+#define AUFS_FIRST_INO 11
38853+
38854+#define AUFS_WH_PFX ".wh."
38855+#define AUFS_WH_PFX_LEN ((int)sizeof(AUFS_WH_PFX) - 1)
38856+#define AUFS_WH_TMP_LEN 4
86dc4139 38857+/* a limit for rmdir/rename a dir and copyup */
7f207e10
AM
38858+#define AUFS_MAX_NAMELEN (NAME_MAX \
38859+ - AUFS_WH_PFX_LEN * 2 /* doubly whiteouted */\
38860+ - 1 /* dot */\
38861+ - AUFS_WH_TMP_LEN) /* hex */
38862+#define AUFS_XINO_FNAME "." AUFS_NAME ".xino"
38863+#define AUFS_XINO_DEFPATH "/tmp/" AUFS_XINO_FNAME
392086de
AM
38864+#define AUFS_XINO_DEF_SEC 30 /* seconds */
38865+#define AUFS_XINO_DEF_TRUNC 45 /* percentage */
7f207e10
AM
38866+#define AUFS_DIRWH_DEF 3
38867+#define AUFS_RDCACHE_DEF 10 /* seconds */
027c5e7a 38868+#define AUFS_RDCACHE_MAX 3600 /* seconds */
7f207e10
AM
38869+#define AUFS_RDBLK_DEF 512 /* bytes */
38870+#define AUFS_RDHASH_DEF 32
38871+#define AUFS_WKQ_NAME AUFS_NAME "d"
027c5e7a
AM
38872+#define AUFS_MFS_DEF_SEC 30 /* seconds */
38873+#define AUFS_MFS_MAX_SEC 3600 /* seconds */
076b876e 38874+#define AUFS_FHSM_CACHE_DEF_SEC 30 /* seconds */
86dc4139 38875+#define AUFS_PLINK_WARN 50 /* number of plinks in a single bucket */
7f207e10
AM
38876+
38877+/* pseudo-link maintenace under /proc */
38878+#define AUFS_PLINK_MAINT_NAME "plink_maint"
38879+#define AUFS_PLINK_MAINT_DIR "fs/" AUFS_NAME
38880+#define AUFS_PLINK_MAINT_PATH AUFS_PLINK_MAINT_DIR "/" AUFS_PLINK_MAINT_NAME
38881+
8b6a4947
AM
38882+/* dirren, renamed dir */
38883+#define AUFS_DR_INFO_PFX AUFS_WH_PFX ".dr."
38884+#define AUFS_DR_BRHINO_NAME AUFS_WH_PFX "hino"
38885+/* whiteouted doubly */
38886+#define AUFS_WH_DR_INFO_PFX AUFS_WH_PFX AUFS_DR_INFO_PFX
38887+#define AUFS_WH_DR_BRHINO AUFS_WH_PFX AUFS_DR_BRHINO_NAME
38888+
7f207e10
AM
38889+#define AUFS_DIROPQ_NAME AUFS_WH_PFX ".opq" /* whiteouted doubly */
38890+#define AUFS_WH_DIROPQ AUFS_WH_PFX AUFS_DIROPQ_NAME
38891+
38892+#define AUFS_BASE_NAME AUFS_WH_PFX AUFS_NAME
38893+#define AUFS_PLINKDIR_NAME AUFS_WH_PFX "plnk"
38894+#define AUFS_ORPHDIR_NAME AUFS_WH_PFX "orph"
38895+
38896+/* doubly whiteouted */
38897+#define AUFS_WH_BASE AUFS_WH_PFX AUFS_BASE_NAME
38898+#define AUFS_WH_PLINKDIR AUFS_WH_PFX AUFS_PLINKDIR_NAME
38899+#define AUFS_WH_ORPHDIR AUFS_WH_PFX AUFS_ORPHDIR_NAME
38900+
1e00d052 38901+/* branch permissions and attributes */
7f207e10
AM
38902+#define AUFS_BRPERM_RW "rw"
38903+#define AUFS_BRPERM_RO "ro"
38904+#define AUFS_BRPERM_RR "rr"
076b876e
AM
38905+#define AUFS_BRATTR_COO_REG "coo_reg"
38906+#define AUFS_BRATTR_COO_ALL "coo_all"
38907+#define AUFS_BRATTR_FHSM "fhsm"
38908+#define AUFS_BRATTR_UNPIN "unpin"
c1595e42
JR
38909+#define AUFS_BRATTR_ICEX "icex"
38910+#define AUFS_BRATTR_ICEX_SEC "icexsec"
38911+#define AUFS_BRATTR_ICEX_SYS "icexsys"
38912+#define AUFS_BRATTR_ICEX_TR "icextr"
38913+#define AUFS_BRATTR_ICEX_USR "icexusr"
38914+#define AUFS_BRATTR_ICEX_OTH "icexoth"
1e00d052
AM
38915+#define AUFS_BRRATTR_WH "wh"
38916+#define AUFS_BRWATTR_NLWH "nolwh"
076b876e
AM
38917+#define AUFS_BRWATTR_MOO "moo"
38918+
38919+#define AuBrPerm_RW 1 /* writable, hardlinkable wh */
38920+#define AuBrPerm_RO (1 << 1) /* readonly */
38921+#define AuBrPerm_RR (1 << 2) /* natively readonly */
38922+#define AuBrPerm_Mask (AuBrPerm_RW | AuBrPerm_RO | AuBrPerm_RR)
38923+
38924+#define AuBrAttr_COO_REG (1 << 3) /* copy-up on open */
38925+#define AuBrAttr_COO_ALL (1 << 4)
38926+#define AuBrAttr_COO_Mask (AuBrAttr_COO_REG | AuBrAttr_COO_ALL)
38927+
38928+#define AuBrAttr_FHSM (1 << 5) /* file-based hsm */
38929+#define AuBrAttr_UNPIN (1 << 6) /* rename-able top dir of
c1595e42
JR
38930+ branch. meaningless since
38931+ linux-3.18-rc1 */
38932+
38933+/* ignore error in copying XATTR */
38934+#define AuBrAttr_ICEX_SEC (1 << 7)
38935+#define AuBrAttr_ICEX_SYS (1 << 8)
38936+#define AuBrAttr_ICEX_TR (1 << 9)
38937+#define AuBrAttr_ICEX_USR (1 << 10)
38938+#define AuBrAttr_ICEX_OTH (1 << 11)
38939+#define AuBrAttr_ICEX (AuBrAttr_ICEX_SEC \
38940+ | AuBrAttr_ICEX_SYS \
38941+ | AuBrAttr_ICEX_TR \
38942+ | AuBrAttr_ICEX_USR \
38943+ | AuBrAttr_ICEX_OTH)
38944+
38945+#define AuBrRAttr_WH (1 << 12) /* whiteout-able */
076b876e
AM
38946+#define AuBrRAttr_Mask AuBrRAttr_WH
38947+
c1595e42
JR
38948+#define AuBrWAttr_NoLinkWH (1 << 13) /* un-hardlinkable whiteouts */
38949+#define AuBrWAttr_MOO (1 << 14) /* move-up on open */
076b876e
AM
38950+#define AuBrWAttr_Mask (AuBrWAttr_NoLinkWH | AuBrWAttr_MOO)
38951+
38952+#define AuBrAttr_CMOO_Mask (AuBrAttr_COO_Mask | AuBrWAttr_MOO)
38953+
c1595e42 38954+/* #warning test userspace */
076b876e
AM
38955+#ifdef __KERNEL__
38956+#ifndef CONFIG_AUFS_FHSM
38957+#undef AuBrAttr_FHSM
38958+#define AuBrAttr_FHSM 0
38959+#endif
c1595e42
JR
38960+#ifndef CONFIG_AUFS_XATTR
38961+#undef AuBrAttr_ICEX
38962+#define AuBrAttr_ICEX 0
38963+#undef AuBrAttr_ICEX_SEC
38964+#define AuBrAttr_ICEX_SEC 0
38965+#undef AuBrAttr_ICEX_SYS
38966+#define AuBrAttr_ICEX_SYS 0
38967+#undef AuBrAttr_ICEX_TR
38968+#define AuBrAttr_ICEX_TR 0
38969+#undef AuBrAttr_ICEX_USR
38970+#define AuBrAttr_ICEX_USR 0
38971+#undef AuBrAttr_ICEX_OTH
38972+#define AuBrAttr_ICEX_OTH 0
38973+#endif
076b876e
AM
38974+#endif
38975+
38976+/* the longest combination */
c1595e42
JR
38977+/* AUFS_BRATTR_ICEX and AUFS_BRATTR_ICEX_TR don't affect here */
38978+#define AuBrPermStrSz sizeof(AUFS_BRPERM_RW \
38979+ "+" AUFS_BRATTR_COO_REG \
38980+ "+" AUFS_BRATTR_FHSM \
38981+ "+" AUFS_BRATTR_UNPIN \
7e9cd9fe
AM
38982+ "+" AUFS_BRATTR_ICEX_SEC \
38983+ "+" AUFS_BRATTR_ICEX_SYS \
38984+ "+" AUFS_BRATTR_ICEX_USR \
38985+ "+" AUFS_BRATTR_ICEX_OTH \
076b876e
AM
38986+ "+" AUFS_BRWATTR_NLWH)
38987+
38988+typedef struct {
38989+ char a[AuBrPermStrSz];
38990+} au_br_perm_str_t;
38991+
38992+static inline int au_br_writable(int brperm)
38993+{
38994+ return brperm & AuBrPerm_RW;
38995+}
38996+
38997+static inline int au_br_whable(int brperm)
38998+{
38999+ return brperm & (AuBrPerm_RW | AuBrRAttr_WH);
39000+}
39001+
39002+static inline int au_br_wh_linkable(int brperm)
39003+{
39004+ return !(brperm & AuBrWAttr_NoLinkWH);
39005+}
39006+
39007+static inline int au_br_cmoo(int brperm)
39008+{
39009+ return brperm & AuBrAttr_CMOO_Mask;
39010+}
39011+
39012+static inline int au_br_fhsm(int brperm)
39013+{
39014+ return brperm & AuBrAttr_FHSM;
39015+}
7f207e10
AM
39016+
39017+/* ---------------------------------------------------------------------- */
39018+
39019+/* ioctl */
39020+enum {
39021+ /* readdir in userspace */
39022+ AuCtl_RDU,
39023+ AuCtl_RDU_INO,
39024+
076b876e
AM
39025+ AuCtl_WBR_FD, /* pathconf wrapper */
39026+ AuCtl_IBUSY, /* busy inode */
39027+ AuCtl_MVDOWN, /* move-down */
39028+ AuCtl_BR, /* info about branches */
39029+ AuCtl_FHSM_FD /* connection for fhsm */
7f207e10
AM
39030+};
39031+
39032+/* borrowed from linux/include/linux/kernel.h */
39033+#ifndef ALIGN
eca34b5c 39034+#ifdef _GNU_SOURCE
7f207e10 39035+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1)
eca34b5c
AM
39036+#else
39037+#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
39038+#endif
7f207e10
AM
39039+#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask))
39040+#endif
39041+
39042+/* borrowed from linux/include/linux/compiler-gcc3.h */
39043+#ifndef __aligned
39044+#define __aligned(x) __attribute__((aligned(x)))
53392da6
AM
39045+#endif
39046+
39047+#ifdef __KERNEL__
39048+#ifndef __packed
7f207e10
AM
39049+#define __packed __attribute__((packed))
39050+#endif
53392da6 39051+#endif
7f207e10
AM
39052+
39053+struct au_rdu_cookie {
9dbd164d
AM
39054+ uint64_t h_pos;
39055+ int16_t bindex;
39056+ uint8_t flags;
39057+ uint8_t pad;
39058+ uint32_t generation;
7f207e10
AM
39059+} __aligned(8);
39060+
39061+struct au_rdu_ent {
9dbd164d
AM
39062+ uint64_t ino;
39063+ int16_t bindex;
39064+ uint8_t type;
39065+ uint8_t nlen;
39066+ uint8_t wh;
7f207e10
AM
39067+ char name[0];
39068+} __aligned(8);
39069+
39070+static inline int au_rdu_len(int nlen)
39071+{
39072+ /* include the terminating NULL */
39073+ return ALIGN(sizeof(struct au_rdu_ent) + nlen + 1,
9dbd164d 39074+ sizeof(uint64_t));
7f207e10
AM
39075+}
39076+
39077+union au_rdu_ent_ul {
39078+ struct au_rdu_ent __user *e;
9dbd164d 39079+ uint64_t ul;
7f207e10
AM
39080+};
39081+
39082+enum {
39083+ AufsCtlRduV_SZ,
39084+ AufsCtlRduV_End
39085+};
39086+
39087+struct aufs_rdu {
39088+ /* input */
39089+ union {
9dbd164d
AM
39090+ uint64_t sz; /* AuCtl_RDU */
39091+ uint64_t nent; /* AuCtl_RDU_INO */
7f207e10
AM
39092+ };
39093+ union au_rdu_ent_ul ent;
9dbd164d 39094+ uint16_t verify[AufsCtlRduV_End];
7f207e10
AM
39095+
39096+ /* input/output */
9dbd164d 39097+ uint32_t blk;
7f207e10
AM
39098+
39099+ /* output */
39100+ union au_rdu_ent_ul tail;
39101+ /* number of entries which were added in a single call */
9dbd164d
AM
39102+ uint64_t rent;
39103+ uint8_t full;
39104+ uint8_t shwh;
7f207e10
AM
39105+
39106+ struct au_rdu_cookie cookie;
39107+} __aligned(8);
39108+
1e00d052
AM
39109+/* ---------------------------------------------------------------------- */
39110+
8b6a4947
AM
39111+/* dirren. the branch is identified by the filename who contains this */
39112+struct au_drinfo {
39113+ uint64_t ino;
39114+ union {
39115+ uint8_t oldnamelen;
39116+ uint64_t _padding;
39117+ };
39118+ uint8_t oldname[0];
39119+} __aligned(8);
39120+
39121+struct au_drinfo_fdata {
39122+ uint32_t magic;
39123+ struct au_drinfo drinfo;
39124+} __aligned(8);
39125+
39126+#define AUFS_DRINFO_MAGIC_V1 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x01)
39127+/* future */
39128+#define AUFS_DRINFO_MAGIC_V2 ('a' << 24 | 'd' << 16 | 'r' << 8 | 0x02)
39129+
39130+/* ---------------------------------------------------------------------- */
39131+
1e00d052 39132+struct aufs_wbr_fd {
9dbd164d
AM
39133+ uint32_t oflags;
39134+ int16_t brid;
1e00d052
AM
39135+} __aligned(8);
39136+
39137+/* ---------------------------------------------------------------------- */
39138+
027c5e7a 39139+struct aufs_ibusy {
9dbd164d
AM
39140+ uint64_t ino, h_ino;
39141+ int16_t bindex;
027c5e7a
AM
39142+} __aligned(8);
39143+
1e00d052
AM
39144+/* ---------------------------------------------------------------------- */
39145+
392086de
AM
39146+/* error code for move-down */
39147+/* the actual message strings are implemented in aufs-util.git */
39148+enum {
39149+ EAU_MVDOWN_OPAQUE = 1,
39150+ EAU_MVDOWN_WHITEOUT,
39151+ EAU_MVDOWN_UPPER,
39152+ EAU_MVDOWN_BOTTOM,
39153+ EAU_MVDOWN_NOUPPER,
39154+ EAU_MVDOWN_NOLOWERBR,
39155+ EAU_Last
39156+};
39157+
c2b27bf2 39158+/* flags for move-down */
392086de
AM
39159+#define AUFS_MVDOWN_DMSG 1
39160+#define AUFS_MVDOWN_OWLOWER (1 << 1) /* overwrite lower */
39161+#define AUFS_MVDOWN_KUPPER (1 << 2) /* keep upper */
39162+#define AUFS_MVDOWN_ROLOWER (1 << 3) /* do even if lower is RO */
39163+#define AUFS_MVDOWN_ROLOWER_R (1 << 4) /* did on lower RO */
39164+#define AUFS_MVDOWN_ROUPPER (1 << 5) /* do even if upper is RO */
39165+#define AUFS_MVDOWN_ROUPPER_R (1 << 6) /* did on upper RO */
39166+#define AUFS_MVDOWN_BRID_UPPER (1 << 7) /* upper brid */
39167+#define AUFS_MVDOWN_BRID_LOWER (1 << 8) /* lower brid */
076b876e
AM
39168+#define AUFS_MVDOWN_FHSM_LOWER (1 << 9) /* find fhsm attr for lower */
39169+#define AUFS_MVDOWN_STFS (1 << 10) /* req. stfs */
39170+#define AUFS_MVDOWN_STFS_FAILED (1 << 11) /* output: stfs is unusable */
39171+#define AUFS_MVDOWN_BOTTOM (1 << 12) /* output: no more lowers */
c2b27bf2 39172+
076b876e 39173+/* index for move-down */
392086de
AM
39174+enum {
39175+ AUFS_MVDOWN_UPPER,
39176+ AUFS_MVDOWN_LOWER,
39177+ AUFS_MVDOWN_NARRAY
39178+};
39179+
076b876e
AM
39180+/*
39181+ * additional info of move-down
39182+ * number of free blocks and inodes.
39183+ * subset of struct kstatfs, but smaller and always 64bit.
39184+ */
39185+struct aufs_stfs {
39186+ uint64_t f_blocks;
39187+ uint64_t f_bavail;
39188+ uint64_t f_files;
39189+ uint64_t f_ffree;
39190+};
39191+
39192+struct aufs_stbr {
39193+ int16_t brid; /* optional input */
39194+ int16_t bindex; /* output */
39195+ struct aufs_stfs stfs; /* output when AUFS_MVDOWN_STFS set */
39196+} __aligned(8);
39197+
c2b27bf2 39198+struct aufs_mvdown {
076b876e
AM
39199+ uint32_t flags; /* input/output */
39200+ struct aufs_stbr stbr[AUFS_MVDOWN_NARRAY]; /* input/output */
39201+ int8_t au_errno; /* output */
39202+} __aligned(8);
39203+
39204+/* ---------------------------------------------------------------------- */
39205+
39206+union aufs_brinfo {
39207+ /* PATH_MAX may differ between kernel-space and user-space */
39208+ char _spacer[4096];
392086de 39209+ struct {
076b876e
AM
39210+ int16_t id;
39211+ int perm;
39212+ char path[0];
39213+ };
c2b27bf2
AM
39214+} __aligned(8);
39215+
39216+/* ---------------------------------------------------------------------- */
39217+
7f207e10
AM
39218+#define AuCtlType 'A'
39219+#define AUFS_CTL_RDU _IOWR(AuCtlType, AuCtl_RDU, struct aufs_rdu)
39220+#define AUFS_CTL_RDU_INO _IOWR(AuCtlType, AuCtl_RDU_INO, struct aufs_rdu)
1e00d052
AM
39221+#define AUFS_CTL_WBR_FD _IOW(AuCtlType, AuCtl_WBR_FD, \
39222+ struct aufs_wbr_fd)
027c5e7a 39223+#define AUFS_CTL_IBUSY _IOWR(AuCtlType, AuCtl_IBUSY, struct aufs_ibusy)
392086de
AM
39224+#define AUFS_CTL_MVDOWN _IOWR(AuCtlType, AuCtl_MVDOWN, \
39225+ struct aufs_mvdown)
076b876e
AM
39226+#define AUFS_CTL_BRINFO _IOW(AuCtlType, AuCtl_BR, union aufs_brinfo)
39227+#define AUFS_CTL_FHSM_FD _IOW(AuCtlType, AuCtl_FHSM_FD, int)
7f207e10
AM
39228+
39229+#endif /* __AUFS_TYPE_H__ */
2121bcd9 39230SPDX-License-Identifier: GPL-2.0
43982f53 39231aufs5.4 loopback patch
5527c038
JR
39232
39233diff --git a/drivers/block/loop.c b/drivers/block/loop.c
43982f53 39234index 5e094699215e..22b2ecb6cfe8 100644
5527c038
JR
39235--- a/drivers/block/loop.c
39236+++ b/drivers/block/loop.c
eca34b5c 39237@@ -625,6 +625,15 @@ static inline void loop_update_dio(struct loop_device *lo)
8b6a4947 39238 lo->use_dio);
5527c038
JR
39239 }
39240
5527c038
JR
39241+static struct file *loop_real_file(struct file *file)
39242+{
39243+ struct file *f = NULL;
39244+
39245+ if (file->f_path.dentry->d_sb->s_op->real_loop)
39246+ f = file->f_path.dentry->d_sb->s_op->real_loop(file);
39247+ return f;
8b6a4947
AM
39248+}
39249+
c2c0f25c 39250 static void loop_reread_partitions(struct loop_device *lo,
8b6a4947
AM
39251 struct block_device *bdev)
39252 {
eca34b5c 39253@@ -678,6 +687,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
5527c038
JR
39254 unsigned int arg)
39255 {
e1106418 39256 struct file *file = NULL, *old_file;
5527c038 39257+ struct file *f, *virt_file = NULL, *old_virt_file;
5527c038 39258 int error;
ba1aed25 39259 bool partscan;
5527c038 39260
eca34b5c 39261@@ -697,12 +707,19 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
cd7a4cd9
AM
39262 file = fget(arg);
39263 if (!file)
e1106418 39264 goto out_err;
5527c038
JR
39265+ f = loop_real_file(file);
39266+ if (f) {
39267+ virt_file = file;
39268+ file = f;
39269+ get_file(file);
39270+ }
39271
cd7a4cd9
AM
39272 error = loop_validate_file(file, bdev);
39273 if (error)
e1106418 39274 goto out_err;
cd7a4cd9 39275
5527c038
JR
39276 old_file = lo->lo_backing_file;
39277+ old_virt_file = lo->lo_backing_virt_file;
39278
39279 error = -EINVAL;
39280
eca34b5c 39281@@ -714,6 +731,7 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
8b6a4947
AM
39282 blk_mq_freeze_queue(lo->lo_queue);
39283 mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask);
39284 lo->lo_backing_file = file;
39285+ lo->lo_backing_virt_file = virt_file;
39286 lo->old_gfp_mask = mapping_gfp_mask(file->f_mapping);
39287 mapping_set_gfp_mask(file->f_mapping,
39288 lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
eca34b5c 39289@@ -727,6 +745,8 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
e1106418
JR
39290 * dependency.
39291 */
5527c038
JR
39292 fput(old_file);
39293+ if (old_virt_file)
39294+ fput(old_virt_file);
e1106418 39295 if (partscan)
c2c0f25c 39296 loop_reread_partitions(lo, bdev);
5527c038 39297 return 0;
eca34b5c 39298@@ -735,6 +755,8 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev,
e1106418
JR
39299 mutex_unlock(&loop_ctl_mutex);
39300 if (file)
39301 fput(file);
5527c038
JR
39302+ if (virt_file)
39303+ fput(virt_file);
5527c038
JR
39304 return error;
39305 }
e1106418 39306
eca34b5c 39307@@ -939,7 +961,7 @@ static void loop_update_rotational(struct loop_device *lo)
5527c038
JR
39308 static int loop_set_fd(struct loop_device *lo, fmode_t mode,
39309 struct block_device *bdev, unsigned int arg)
39310 {
062440b3 39311- struct file *file;
5527c038
JR
39312+ struct file *file, *f, *virt_file = NULL;
39313 struct inode *inode;
39314 struct address_space *mapping;
eca34b5c
AM
39315 struct block_device *claimed_bdev = NULL;
39316@@ -955,6 +977,12 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
5527c038
JR
39317 file = fget(arg);
39318 if (!file)
39319 goto out;
39320+ f = loop_real_file(file);
39321+ if (f) {
39322+ virt_file = file;
39323+ file = f;
39324+ get_file(file);
39325+ }
39326
fbc438ed
JR
39327 /*
39328 * If we don't hold exclusive handle for the device, upgrade to it
eca34b5c 39329@@ -1003,6 +1031,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
5527c038
JR
39330 lo->lo_device = bdev;
39331 lo->lo_flags = lo_flags;
39332 lo->lo_backing_file = file;
39333+ lo->lo_backing_virt_file = virt_file;
39334 lo->transfer = NULL;
39335 lo->ioctl = NULL;
39336 lo->lo_sizelimit = 0;
43982f53 39337@@ -1056,6 +1085,8 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
eca34b5c 39338 bd_abort_claiming(bdev, claimed_bdev, loop_set_fd);
e1106418 39339 out_putf:
5527c038
JR
39340 fput(file);
39341+ if (virt_file)
39342+ fput(virt_file);
e1106418 39343 out:
5527c038
JR
39344 /* This is safe: open() is still holding a reference. */
39345 module_put(THIS_MODULE);
43982f53 39346@@ -1102,6 +1133,7 @@ loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer,
ba1aed25 39347 static int __loop_clr_fd(struct loop_device *lo, bool release)
5527c038 39348 {
e1106418 39349 struct file *filp = NULL;
5527c038
JR
39350+ struct file *virt_filp = lo->lo_backing_virt_file;
39351 gfp_t gfp = lo->old_gfp_mask;
39352 struct block_device *bdev = lo->lo_device;
ba1aed25 39353 int err = 0;
43982f53 39354@@ -1125,6 +1157,7 @@ static int __loop_clr_fd(struct loop_device *lo, bool release)
5527c038 39355
5527c038 39356 spin_lock_irq(&lo->lo_lock);
5527c038
JR
39357 lo->lo_backing_file = NULL;
39358+ lo->lo_backing_virt_file = NULL;
39359 spin_unlock_irq(&lo->lo_lock);
39360
39361 loop_release_xfer(lo);
43982f53 39362@@ -1207,6 +1240,8 @@ static int __loop_clr_fd(struct loop_device *lo, bool release)
5527c038 39363 */
e1106418
JR
39364 if (filp)
39365 fput(filp);
5527c038
JR
39366+ if (virt_filp)
39367+ fput(virt_filp);
e1106418 39368 return err;
5527c038
JR
39369 }
39370
39371diff --git a/drivers/block/loop.h b/drivers/block/loop.h
43982f53 39372index af75a5ee4094..1d847cb194ff 100644
5527c038
JR
39373--- a/drivers/block/loop.h
39374+++ b/drivers/block/loop.h
39375@@ -46,7 +46,7 @@ struct loop_device {
39376 int (*ioctl)(struct loop_device *, int cmd,
39377 unsigned long arg);
39378
39379- struct file * lo_backing_file;
43982f53 39380+ struct file *lo_backing_file, *lo_backing_virt_file;
5527c038 39381 struct block_device *lo_device;
5527c038 39382 void *key_data;
8b6a4947 39383
5527c038 39384diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c
016522bc 39385index 6fb4a4ed8cc7..ba9a959f2db2 100644
5527c038
JR
39386--- a/fs/aufs/f_op.c
39387+++ b/fs/aufs/f_op.c
acd2b654 39388@@ -359,7 +359,7 @@ static ssize_t aufs_read_iter(struct kiocb *kio, struct iov_iter *iov_iter)
5527c038
JR
39389 if (IS_ERR(h_file))
39390 goto out;
39391
39392- if (au_test_loopback_kthread()) {
39393+ if (0 && au_test_loopback_kthread()) {
39394 au_warn_loopback(h_file->f_path.dentry->d_sb);
39395 if (file->f_mapping != h_file->f_mapping) {
39396 file->f_mapping = h_file->f_mapping;
39397diff --git a/fs/aufs/loop.c b/fs/aufs/loop.c
016522bc 39398index a8b63acc6204..9d97c3af5686 100644
5527c038
JR
39399--- a/fs/aufs/loop.c
39400+++ b/fs/aufs/loop.c
2121bcd9 39401@@ -133,3 +133,19 @@ void au_loopback_fin(void)
79b8bda9 39402 symbol_put(loop_backing_file);
9f237c51 39403 au_kfree_try_rcu(au_warn_loopback_array);
5527c038
JR
39404 }
39405+
39406+/* ---------------------------------------------------------------------- */
39407+
39408+/* support the loopback block device insude aufs */
39409+
39410+struct file *aufs_real_loop(struct file *file)
39411+{
39412+ struct file *f;
39413+
39414+ BUG_ON(!au_test_aufs(file->f_path.dentry->d_sb));
39415+ fi_read_lock(file);
39416+ f = au_hf_top(file);
39417+ fi_read_unlock(file);
39418+ AuDebugOn(!f);
39419+ return f;
39420+}
39421diff --git a/fs/aufs/loop.h b/fs/aufs/loop.h
016522bc 39422index 94f4f80ae33b..ca1194354aff 100644
5527c038
JR
39423--- a/fs/aufs/loop.h
39424+++ b/fs/aufs/loop.h
eca801bf 39425@@ -26,6 +26,8 @@ void au_warn_loopback(struct super_block *h_sb);
5527c038
JR
39426
39427 int au_loopback_init(void);
39428 void au_loopback_fin(void);
39429+
39430+struct file *aufs_real_loop(struct file *file);
39431 #else
83b672a5 39432 AuStub(struct file *, loop_backing_file, return NULL, struct super_block *sb)
eca801bf
AM
39433
39434@@ -36,6 +38,8 @@ AuStubVoid(au_warn_loopback, struct super_block *h_sb)
5527c038
JR
39435
39436 AuStubInt0(au_loopback_init, void)
39437 AuStubVoid(au_loopback_fin, void)
39438+
39439+AuStub(struct file *, aufs_real_loop, return NULL, struct file *file)
39440 #endif /* BLK_DEV_LOOP */
39441
39442 #endif /* __KERNEL__ */
39443diff --git a/fs/aufs/super.c b/fs/aufs/super.c
016522bc 39444index 589dd0122020..801e0a7faec5 100644
5527c038
JR
39445--- a/fs/aufs/super.c
39446+++ b/fs/aufs/super.c
fbc438ed 39447@@ -844,7 +844,10 @@ static const struct super_operations aufs_sop = {
5527c038
JR
39448 .statfs = aufs_statfs,
39449 .put_super = aufs_put_super,
39450 .sync_fs = aufs_sync_fs,
39451- .remount_fs = aufs_remount_fs
39452+ .remount_fs = aufs_remount_fs,
39453+#ifdef CONFIG_AUFS_BDEV_LOOP
39454+ .real_loop = aufs_real_loop
39455+#endif
39456 };
39457
39458 /* ---------------------------------------------------------------------- */
39459diff --git a/include/linux/fs.h b/include/linux/fs.h
43982f53 39460index 381a13995011..215b76e0f9dc 100644
5527c038
JR
39461--- a/include/linux/fs.h
39462+++ b/include/linux/fs.h
43982f53 39463@@ -1973,6 +1973,10 @@ struct super_operations {
5527c038
JR
39464 struct shrink_control *);
39465 long (*free_cached_objects)(struct super_block *,
39466 struct shrink_control *);
43982f53 39467+#if IS_ENABLED(CONFIG_BLK_DEV_LOOP) || IS_ENABLED(CONFIG_BLK_DEV_LOOP_MODULE)
5527c038
JR
39468+ /* and aufs */
39469+ struct file *(*real_loop)(struct file *);
39470+#endif
39471 };
39472
39473 /*
This page took 8.666904 seconds and 4 git commands to generate.